From ab064bb64bf687e136593bd0f56351b4aca14597 Mon Sep 17 00:00:00 2001 From: SERENCH <3117094826@qq.com> Date: Mon, 7 Apr 2025 13:19:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20:zap:=20py=E6=96=87=E4=BB=B6=E7=9A=84?= =?UTF-8?q?=E5=A2=9E=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CAPI/cpp/API/include/structures.h | 12 +- CAPI/cpp/API/src/DebugAPI.cpp | 2 +- CAPI/python/AI.py | 27 --- CAPI/python/State.py | 31 +++ CAPI/python/main.py | 125 ++++++++++ CAPI/python/structures.py | 311 +++++++++++++++++++++++++ dependency/proto/Message2Clients.proto | 7 +- logic/Server/CopyInfo.cs | 11 +- 8 files changed, 484 insertions(+), 42 deletions(-) create mode 100644 CAPI/python/State.py create mode 100644 CAPI/python/main.py create mode 100644 CAPI/python/structures.py diff --git a/CAPI/cpp/API/include/structures.h b/CAPI/cpp/API/include/structures.h index ec3ae2a..39d0cab 100644 --- a/CAPI/cpp/API/include/structures.h +++ b/CAPI/cpp/API/include/structures.h @@ -71,12 +71,12 @@ namespace THUAI8 Camp1Character5 = 5, Camp1Character6 = 6, - CampCharacter1 = 7, - CampCharacter2 = 8, - CampCharacter3 = 9, - CampCharacter4 = 10, - CampCharacter5 = 11, - CampCharacter6 = 12, + Camp2Character1 = 7, + Camp2Character2 = 8, + Camp2Character3 = 9, + Camp2Character4 = 10, + Camp2Character5 = 11, + Camp2Character6 = 12, }; enum class EquipmentType : unsigned char diff --git a/CAPI/cpp/API/src/DebugAPI.cpp b/CAPI/cpp/API/src/DebugAPI.cpp index c087992..e4e876c 100644 --- a/CAPI/cpp/API/src/DebugAPI.cpp +++ b/CAPI/cpp/API/src/DebugAPI.cpp @@ -561,7 +561,7 @@ void TeamDebugAPI::PrintSelfInfo() const logger->info("*********************\n"); } -void ShipDebugAPI::Play(IAI& ai) +void CharacterDebugAPI::Play(IAI& ai) { ai.play(*this); } diff --git a/CAPI/python/AI.py b/CAPI/python/AI.py index 7cf5dca..17053fd 100644 --- a/CAPI/python/AI.py +++ b/CAPI/python/AI.py @@ -15,7 +15,6 @@ class Setting: return False @staticmethod -<<<<<<< HEAD def BuddhistsCharacterTypes() -> List[THUAI8.CharacterType]: return [ THUAI8.CharacterType.Monk, @@ -30,40 +29,20 @@ class Setting: return [ THUAI8.CharacterType.JiuTouYuanSheng, THUAI8.CharacterType.HongHaier, -======= - def ShipTypes() -> List[THUAI8.CharacterType]: - return [ - THUAI8.CharacterType.Monk, - THUAI8.CharacterType.MonkeyKing, - THUAI8.CharacterType.Pigsy, - THUAI8.CharacterType.ShaWujing, - THUAI8.CharacterType.Whitedragonhorse, - THUAI8.CharacterType.JiuTouYuanSheng, - THUAI8.CharacterType.Honghaier, ->>>>>>> 5a1751dc64f09ba19aaa818e5dc99172d15f4c69 THUAI8.CharacterType.Gyuumao, THUAI8.CharacterType.Princess_Iron_Fan, THUAI8.CharacterType.Spider, ] -<<<<<<< HEAD numOfGridPerCell: Final[int] = 1000 -======= -numOfGridPerCell: Final[int] = 1000 - ->>>>>>> 5a1751dc64f09ba19aaa818e5dc99172d15f4c69 class AI(IAI): def __init__(self, pID: int): self.__playerID = pID -<<<<<<< HEAD def CharacterPlay(self, api: ICharacterAPI) -> None: -======= - def ShipPlay(self, api: IShipAPI) -> None: ->>>>>>> 5a1751dc64f09ba19aaa818e5dc99172d15f4c69 # 公共操作 if self.__playerID == 1: # player1的操作 @@ -77,13 +56,7 @@ class AI(IAI): elif self.__playerID == 4: # player4的操作 return -<<<<<<< HEAD return -======= - elif self.__playerID == 5: - # player4的操作 - return ->>>>>>> 5a1751dc64f09ba19aaa818e5dc99172d15f4c69 def TeamPlay(self, api: ITeamAPI) -> None: # player0的操作 diff --git a/CAPI/python/State.py b/CAPI/python/State.py new file mode 100644 index 0000000..61ff38b --- /dev/null +++ b/CAPI/python/State.py @@ -0,0 +1,31 @@ +from typing import List, Union + +import PyAPI.structures as THUAI8 + + +class State: + def __init__(self) -> None: + self.teamScore = 0 + self.self = None + self.characters = [] + self.enemyCharacters = [] + self.gameMap = [] + self.mapInfo = THUAI8.GameMap() + self.gameInfo = THUAI8.GameInfo() + self.guids = [] + self.allGuids = [] + + teamScore: int + self: Union[THUAI8.Character, THUAI8.Team] + + characters: List[THUAI8.Character] + enemyCharacters: List[THUAI8.Character] + + gameMap: List[List[THUAI8.PlaceType]] + + mapInfo: THUAI8.GameMap + + gameInfo: THUAI8.GameInfo + + guids: List[int] + allGuids: List[int] diff --git a/CAPI/python/main.py b/CAPI/python/main.py new file mode 100644 index 0000000..2c02e36 --- /dev/null +++ b/CAPI/python/main.py @@ -0,0 +1,125 @@ +import argparse +import os +import platform +import sys +from typing import Callable, List + +sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/proto") + +import PyAPI.structures as THUAI8 # NOQA: E402 +from PyAPI.AI import AI, Setting # NOQA: E402 +from PyAPI.Interface import IAI # NOQA: E402 +from PyAPI.logic import Logic # NOQA: E402 + + +def PrintWelcomeString() -> None: + # Generated by http://www.network-science.de/ascii/ with font "standard" + welcomeString = r""" + ______________ ___ ____ ___ _____ .____________ + \__ ___/ | \| | \/ _ \ | \______ \ + | | / ~ \ | / /_\ \| | / / + | | \ Y / | / | \ | / / + |____| \___|_ /|______/\____|__ /___| /____/ + \/ \/ + _________ __ __ __ + / _____// |______ _______ / \ / \_____ _______ + \_____ \\ __\__ \\_ __ \ \ \/\/ /\__ \\_ __ \ + / \| | / __ \| | \/ \ / / __ \| | \/ + /_______ /|__| (____ /__| \__/\ / (____ /__| + \/ \/ \/ \/ + """ + print(welcomeString) + + +def THUAI8Main(argv: List[str], AIBuilder: Callable) -> None: + pID: int = 0 + sIP: str = "127.0.0.1" + sPort: str = "8888" + file: bool = True + screen: bool = True + warnOnly: bool = False + parser = argparse.ArgumentParser( + description="THUAI8 Python Interface Commandline Parameter Introduction" + ) + parser.add_argument( + "-I", + type=str, + required=True, + help="Server`s IP 127.0.0.1 in default", + dest="sIP", + default="127.0.0.1", + ) + parser.add_argument( + "-P", + type=str, + required=True, + help="Server`s Port 8888 in default", + dest="sPort", + default="8888", + ) + parser.add_argument( + "-t", + type=int, + required=True, + help="Team`s ID", + dest="tID", + choices=[0, 1], + ) + parser.add_argument( + "-p", + type=int, + required=True, + help="Player`s ID", + dest="pID", + choices=[0, 1, 2, 3, 4], + ) + parser.add_argument( + "-d", + action="store_true", + help="Set this flag to save the debug log to ./logs folder", + dest="file", + ) + parser.add_argument( + "-o", + action="store_true", + help="Set this flag to print the debug log to the screen", + dest="screen", + ) + parser.add_argument( + "-w", + action="store_true", + help="Set this flag to only print warning on the screen", + dest="warnOnly", + ) + args = parser.parse_args() + tID = args.tID + pID = args.pID + sIP = args.sIP + sPort = args.sPort + file = args.file + screen = args.screen + warnOnly = args.warnOnly + playerType = THUAI8.PlayerType.NullPlayerType + characterType = THUAI8.CharacterType.NullCharacterType + if pID == 0: + playerType = THUAI8.PlayerType.Team + else: + playerType = THUAI8.PlayerType.Character + characterType = Setting.CharacterTypes()[ + pID - 1 + ] # 减去1 是因为字典从0计数,而我们的角色是从1计数 + + if platform.system().lower() == "windows": + PrintWelcomeString() + + logic = Logic(pID, tID, playerType, characterType) + logic.Main(AIBuilder, sIP, sPort, file, screen, warnOnly) + + +def CreateAI(pID: int) -> IAI: + return AI(pID) + + +if __name__ == "__main__": + THUAI8Main(sys.argv, CreateAI) diff --git a/CAPI/python/structures.py b/CAPI/python/structures.py new file mode 100644 index 0000000..9890cfe --- /dev/null +++ b/CAPI/python/structures.py @@ -0,0 +1,311 @@ +import sys +from enum import Enum +from typing import Dict, List + +if sys.version_info < (3, 9): + from typing import Tuple +else: + Tuple = tuple + + +class GameState(Enum): + NullGameState = 0 + GameStart = 1 + GameRunning = 2 + GameEnd = 3 + + +class PlaceType(Enum): + NullPlaceType = 0 + Home = 1 + Space = 2 + Barrier = 3 + Bush = 4 + EconomyResource = 5 + AdditionResource = 6 + Construction = 7 + Trap = 8 + + +class ShapeType(Enum): + NullShapeType = 0 + Circle = 1 + Square = 2 + + +class PlayerTeam(Enum): + NullTeam = 0 + BuddhistsTeam = 1 + MonstersTeam = 2 + + +class PlayerType(Enum): + NullPlayerType = 0 + Character = 1 + Team = 2 + + +class CharacterType(Enum): + NullChatacterType = 0 + + Camp1Character1 = 1 + Camp1Character2 = 2 + Camp1Character3 = 3 + Camp1Character4 = 4 + Camp1Character5 = 5 + Camp1Character6 = 6 + + Camp2Character1 = 7 + Camp2Character2 = 8 + Camp2Character3 = 9 + Camp2Character4 = 10 + Camp2Character5 = 11 + Camp2Character6 = 12 + + +class EquipmentType(Enum): + NullEquipmentType = 0 + + SmallHealthPotion = 1 + MediumHealthPotion = 2 + LargeHealthPotion = 3 + + SmallShield = 4 + MediumShield = 5 + LargeShield = 6 + + Speedboots = 7 + PurificationPotion = 8 + InvisibilityPotion = 9 + BerserkPotion = 10 + + +class CharacterState(Enum): + NullCharacterState = 0 + + Idle = 1 + Harvesting = 2 + Attacking = 3 + SkillCasting = 4 + Constructing = 5 + Moving = 6 + + Blind = 7 + KnockedBack = 8 + Stunned = 9 + Invisible = 10 + Healing = 11 + Berserk = 12 + Burned = 13 + + +class CharacterBuffType(Enum): + NullCharacterBuffType = 0 + + AttackBuff1 = 1 + AttackBuff2 = 2 + AttackBuff3 = 3 + DefenseBuff = 4 + SpeedBuff = 5 + VisionBuff = 6 + + +class EconomyResourceType(Enum): + NullEconomyResourceType = 0 + + SmallEconomyResource = 1 + MediumEconomyResource = 2 + LargeEconomyResource = 3 + + +class AdditionResourceType(Enum): + NullAdditionReourceType = 0 + + SmallAdditionResource1 = 1 + MediumAdditionResource1 = 2 + LargeAdditionResource1 = 3 + + SmallAdditionResource2 = 4 + MediumAdditionResource2 = 5 + LargeAdditionResource2 = 6 + + AdditionResource3 = 7 + + AdditionResource4 = 8 + + +class EconomyResourceState(Enum): + NullEconomyResourceState = 0 + Harvestable = 1 + BeingHarvested = 2 + Harvested = 3 + + +class AdditionResourceState(Enum): + NullAdditionResourceState = 0 + Beatable = 1 + BeingBeaten = 2 + Beaten = 3 + + +class ConstructionType(Enum): + NullConstructionType = 0 + Barracks = 1 + Spring = 2 + Farm = 3 + + +class TrapType(Enum): + NullTrapType = 0 + Hole = 1 + Cage = 2 + + +class MessageOfObj(Enum): + NullMessageOfObj = 0 + CharacterMessage = 1 + BarracksMessage = 2 + SpringMessage = 3 + FarmMessage = 4 + TrapMessage = 5 + EconomyResourceMessage = 6 + AdditionResourceMessage = 7 + MapMessage = 8 + NewsMessage = 9 + TeamMessage = 10 + + +class NewsType(Enum): + NullNewsType = 0 + TextMessage = 1 + BinaryMessage = 2 + + +class Character: + def __init__(self): + self.guid: int = 0 + self.teamID: int = 0 + self.playerID: int = 0 + self.characterType: CharacterType = CharacterType.NullChatacterType + self.characterActiveState: CharacterState = CharacterState.NullCharacterState + self.blindState: CharacterState = CharacterState.NullCharacterState + self.blindTime: int = 0 + self.stunnedState: CharacterState = CharacterState.NullCharacterState + self.stunnedTime: int = 0 + self.invisibleState: CharacterState = CharacterState.NullCharacterState + self.invisibleTime: int = 0 + self.burnedState: CharacterState = CharacterState.NullCharacterState + self.burnedTime: int = 0 + self.harmCut: float = 0.0 + self.harmCutTime: int = 0 + self.deceasedState: CharacterState = CharacterState.NullCharacterState + self.characterPassiveState: CharacterState = CharacterState.NullCharacterState + self.x: int = 0 + self.y: int = 0 + self.facingDirection: float = 0.0 + self.speed: int = 0 + self.viewRange: int = 0 + self.commonAttack: int = 0 + self.commonAttackCD: int = 0 + self.commonAttackRange: int = 0 + self.skillAttackCD: int = 0 + self.economyDepletion: int = 0 + self.killScore: int = 0 + self.hp: int = 0 + self.shieldEquipment: int = 0 + self.shoesEquipment: int = 0 + self.shoesEquipmentTime: int = 0 + self.purificationEquipmentTime: int = 0 + self.attackBuffTime: int = 0 + self.speedBuffTime: int = 0 + self.visionBuffTime: int = 0 + + +class Team: + def __init__(self): + self.playerID: int = 0 + self.teamID: int = 0 + self.score: int = 0 + self.energy: int = 0 + + +class Trap: + def __init__(self): + self.trapType: TrapType = TrapType.NullTrapType + self.x: int = 0 + self.y: int = 0 + self.teamID: int = 0 + self.id: int = 0 + + +class EconomyResource: + def __init__(self): + self.economyResourceType: EconomyResourceType = ( + EconomyResourceType.NullEconomyResourceType + ) + self.economyResourceState: EconomyResourceState = ( + EconomyResourceState.NullEconomyResourceState + ) + self.x: int = 0 + self.y: int = 0 + self.process: int = 0 + self.id: int = 0 + + +class AdditionResource: + def __init__(self): + self.additionResourceType: AdditionResourceType = ( + AdditionResourceType.NullAdditionReourceType + ) + self.additionResourceState: AdditionResourceState = ( + AdditionResourceState.NullAdditionResourceState + ) + self.x: int = 0 + self.y: int = 0 + self.hp: int = 0 + self.id: int = 0 + + +class ConstructionState: + def __init__(self, teamID, HP, type: ConstructionType): + self.teamID = teamID + self.hp = HP + self.constructionType: ConstructionType = ConstructionType.NullConstructionType + + +class ConstructionState: + def __init__(self, teamID, HP, type: ConstructionType): + self.teamID = teamID + self.hp = HP + self.constructionType = type + + +class GameMap: + def __init__(self): + self.barracksState: Dict[Tuple[int, int], Tuple[int, int]] = {} + self.springState: Dict[Tuple[int, int], Tuple[int, int]] = {} + self.farmState: Dict[Tuple[int, int], Tuple[int, int]] = {} + self.trapState: Dict[Tuple[int, int], Tuple[int, int]] = {} + self.economyResource: Dict[Tuple[int, int], int] = {} + self.additionResource: Dict[Tuple[int, int], int] = {} + + +class GameInfo: + """ + :attr gameTime: 当前游戏时间 + :attr redScore: 红队当前分数 + :attr redEnergy: 红队当前经济 + :attr redHomeHp: 红队当前基地血量 + :attr blueScore: 蓝队当前分数 + :attr blueEnergy: 蓝队当前经济 + :attr blueHomeHp: 蓝队当前基地血量 + """ + + def __init__(self): + self.gameTime: int = 0 + self.buddhistsTeamScore: int = 0 + self.buddhistsTeamEconomy: int = 0 + self.buddhistsTeamHeroHp: int = 0 + self.monstersScore: int = 0 + self.monstersEconomy: int = 0 + self.monstersHeroHp: int = 0 diff --git a/dependency/proto/Message2Clients.proto b/dependency/proto/Message2Clients.proto index 15501b5..d1916eb 100644 --- a/dependency/proto/Message2Clients.proto +++ b/dependency/proto/Message2Clients.proto @@ -76,11 +76,12 @@ message MessageOfCharacter // 加成资源的Buff // CharacterBuffType attack_buff = 39; - int64 attack_buff_time = 34; + int32 attack_buff_num = 34; + int64 attack_buff_time = 35; // CharacterBuffType speed_buff = 43; - int64 speed_buff_time = 35; + int64 speed_buff_time = 36; // CharacterBuffType vision_buff = 45; - int64 vision_buff_time = 36; + int64 vision_buff_time = 37; } message MessageOfBarracks diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs index b32524c..bc8ad71 100644 --- a/logic/Server/CopyInfo.cs +++ b/logic/Server/CopyInfo.cs @@ -86,7 +86,7 @@ namespace Server StunnedTime = player.StunnedTime, InvisibleState = (player.visible) ? Protobuf.CharacterState.NullCharacterState : Protobuf.CharacterState.Invisible, // 待修改,Character.cs中没有InvisibleTime - // InvisibleTime = (double)player.InvisibleTime, + InvisibleTime = player.InvisibleTime, // 貌似不需要治疗时间 // HealingState = (player.healing) ? Protobuf.CharacterState.Healing : Protobuf.CharacterState.NullCharacterState, // HealingTime = (double)player.HealingTime, @@ -123,18 +123,19 @@ namespace Server // 待修改,Shield要分两类 ShieldEquipment = (int)player.Shield, // 加成值,只包含护盾装备 ShoesEquipment = (int)player.Shoes, // 加成值 - ShoesEquipmentTime = player.QuickStepTime, // 包含所有速度加成的时间 + ShoesEquipmentTime = player.ShoesTime, // 包含所有速度加成的时间 // 待修改,Transformation缺东西 - // PurificationEquipment = (player.Purified) ? Protobuf.EquipmentType.PurificationPotion : Protobuf.PurificationEquipmentType.NullEquipmentType, + PurificationEquipment = (player.Purified) ? Protobuf.EquipmentType.PurificationPotion : Protobuf.PurificationEquipmentType.NullEquipmentType, // 数值,1~3表示等级,0表示没有 PurificationEquipmentTime = player.PurifiedTime, // 待修改,Character.cs没有隐身时间,没有狂暴药水 // InvisibilityEquipment = player.Invisibility, // InvisibilityEquipmentTime = player.InsvisibilityTime, - // Berserk = player.CrazyManNum, // 数值,1~3表示等级,0表示没有 - // BerserkTime = player.CrazyManTime, + BerserkEquipment = (player.IsBerserk) ? Protobuf.EquipmentType.BerserkPotion : Protobuf.EquipmentType.NullEquipmentType, // 数值,1~3表示等级,0表示没有 + BerserkTime = player.BerserkTime, // 待修改,Transformation缺东西 // AttackBuff = (player.CrazyManNum == 1) ? Protobuf.CharacterBuffType.AttackBuff1 : (player.CrazyManNum == 2) ? Protobuf.CharacterBuffType.AttackBuff2 : (player.CrazyManNum == 3) ? Protobuf.CharacterBuffType.AttackBuff3 : Protobuf.CharacterBuffType.NullAttackBuff, + AttackBuffNum = (int)player.CrazyManNum, AttackBuffTime = player.CrazyManTime, // 待修改 SpeedBuffTime = player.QuickStepTime,