diff --git a/CAPI/cpp/API/include/structures.h b/CAPI/cpp/API/include/structures.h index 2b2a4787..f2bb111c 100755 --- a/CAPI/cpp/API/include/structures.h +++ b/CAPI/cpp/API/include/structures.h @@ -49,9 +49,9 @@ namespace THUAI7 enum class PlayerTeam : unsigned char { - NullTeam = 0, - Red = 1, - Blue = 2, + Red = 0, + Blue = 1, + NullTeam = 2, }; enum class PlayerType : unsigned char diff --git a/CAPI/cpp/API/src/logic.cpp b/CAPI/cpp/API/src/logic.cpp index f6d230e5..48bdbe37 100755 --- a/CAPI/cpp/API/src/logic.cpp +++ b/CAPI/cpp/API/src/logic.cpp @@ -30,6 +30,8 @@ Logic::Logic(int64_t pID, int64_t tID, THUAI7::PlayerType pType, THUAI7::Sweeper playerTeam = THUAI7::PlayerTeam::Red; if (teamID == 1) playerTeam = THUAI7::PlayerTeam::Blue; + else + playerTeam = THUAI7::PlayerTeam::NullTeam; } std::vector> Logic::GetSweepers() const diff --git a/CAPI/cpp/API/src/main.cpp b/CAPI/cpp/API/src/main.cpp index 4affbc33..b71d0f58 100755 --- a/CAPI/cpp/API/src/main.cpp +++ b/CAPI/cpp/API/src/main.cpp @@ -107,7 +107,7 @@ int THUAI7Main(int argc, char** argv, CreateAIFunc AIBuilder) else { playerType = THUAI7::PlayerType::Sweeper; - SweeperType = SweeperTypeDict[pID]; + SweeperType = SweeperTypeDict[pID - 1]; } #ifdef _MSC_VER std::cout diff --git a/CAPI/python/PyAPI/AI.py b/CAPI/python/PyAPI/AI.py index 82504ca0..1d16a3a6 100644 --- a/CAPI/python/PyAPI/AI.py +++ b/CAPI/python/PyAPI/AI.py @@ -32,18 +32,23 @@ def __init__(self, pID: int): def SweeperPlay(self, api: ISweeperAPI) -> None: # 公共操作 - - if self.__playerID == 0: - # player0的操作 - return - elif self.__playerID == 1: + if self.__playerID == 1: + api.PrintSelfInfo() + time.sleep(1) # player1的操作 return elif self.__playerID == 2: # player2的操作 return - return + elif self.__playerID == 3: + # player3的操作 + return + elif self.__playerID == 4: + # player4的操作 + return + returnF def TeamPlay(self, api: ITeamAPI) -> None: + assert self.__playerID == 0, "Team's playerID must be 0" # 操作 return diff --git a/CAPI/python/PyAPI/API.py b/CAPI/python/PyAPI/API.py index 1b207eb5..14cd6444 100644 --- a/CAPI/python/PyAPI/API.py +++ b/CAPI/python/PyAPI/API.py @@ -190,8 +190,8 @@ def GetConstructionHp(self, cellX: int, cellY: int) -> int: def GetBridgeHp(self, cellX: int, cellY: int) -> int: return self.__logic.GetBridgeHp(cellX, cellY) - def GetResouceState(self, cellX: int, cellY: int) -> int: - return self.__logic.GetResouceState(cellX, cellY) + def GetGarbageState(self, cellX: int, cellY: int) -> int: + return self.__logic.GetGarbageState(cellX, cellY) def GetHomeHp(self) -> int: return self.__logic.GetHomeHp() @@ -226,5 +226,8 @@ def Print(self, string: str) -> None: def PrintTeam(self) -> None: pass + def PrintSweeper(self) -> None: + pass + def PrintSelfInfo(self) -> None: pass diff --git a/CAPI/python/PyAPI/DebugAPI.py b/CAPI/python/PyAPI/DebugAPI.py index 3e6191e0..9405dd21 100644 --- a/CAPI/python/PyAPI/DebugAPI.py +++ b/CAPI/python/PyAPI/DebugAPI.py @@ -450,8 +450,8 @@ def GetConstructionHp(self, cellX: int, cellY: int) -> int: def GetBridgeHp(self, cellX: int, cellY: int) -> int: return self.__logic.GetBridgeHp(cellX, cellY) - def GetResouceState(self, cellX: int, cellY: int) -> int: - return self.__logic.GetResouceState(cellX, cellY) + def GetGarbageState(self, cellX: int, cellY: int) -> int: + return self.__logic.GetGarbageState(cellX, cellY) def GetHomeHp(self) -> int: return self.__logic.GetHomeHp() @@ -472,13 +472,37 @@ def GetEnergy(self) -> int: return self.__logic.GetEnergy() def Print(self, string: str) -> None: - pass + self.__logger.info(string) + + def PrintSweeper(self) -> None: + for sweeper in self.__logic.GetSweepers(): + self.__logger.info("******sweeper Info******") + self.__logger.info( + f"teamID={sweeper.teamID} playerID={sweeper.playerID}, GUID={sweeper.guid} sweeperType:{sweeper.sweeperType}" + ) + self.__logger.info( + f"x={sweeper.x}, y={sweeper.y} hp={sweeper.hp} armor={sweeper.armor} shield={sweeper.shield} state:{sweeper.sweeperState}" + ) + self.__logger.info( + f"speed={sweeper.speed}, view range={sweeper.viewRange}, facingDirection={sweeper.facingDirection}" + ) + self.__logger.info( + f"producerType:{sweeper.producerType} constructorType:{sweeper.constructorType}" + ) + self.__logger.info( + f"armorType:{sweeper.armorType} shieldType:{sweeper.shieldType} weaponType:{sweeper.weaponType}" + ) + self.__logger.info("************************\n") def PrintTeam(self) -> None: - pass + self.PrintSelfInfo() def PrintSelfInfo(self) -> None: - pass + selfInfo = self.__logic.GetSelfInfo() + self.__logger.info("******self team info******") + self.__logger.info(f"teamID:{selfInfo.teamID} playerID:{selfInfo.playerID}") + self.__logger.info(f"score:{selfInfo.score} energy:{selfInfo.energy}") + self.__logger.info("************************\n") def __GetTime(self) -> float: return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta( diff --git a/CAPI/python/PyAPI/Interface.py b/CAPI/python/PyAPI/Interface.py index 2f7cde50..803cace3 100644 --- a/CAPI/python/PyAPI/Interface.py +++ b/CAPI/python/PyAPI/Interface.py @@ -154,10 +154,6 @@ def HaveMessage(self) -> bool: def GetMessage(self) -> Tuple[int, str]: pass - @abstractmethod - def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: - pass - # 获取游戏目前所进行的帧数 @abstractmethod def GetFrameCount(self) -> int: diff --git a/CAPI/python/PyAPI/gym.py b/CAPI/python/PyAPI/gym.py new file mode 100644 index 00000000..da25dcd7 --- /dev/null +++ b/CAPI/python/PyAPI/gym.py @@ -0,0 +1,99 @@ +from collections import deque, namedtuple +import random +import PyAPI.structures as THUAI7 +from PyAPI.State import State + +Transition = namedtuple("Transition", ["state", "action", "reward", "next_state"]) + + +class ObservationSpace: + def __init__(self, state: State): + if isinstance(state.self, THUAI7.Sweeper): + self.selfSweeperInfo = self.__ObsSweeper(state.self) + self.otherSweeperInfo = [ + self.__ObsSweeper(sweeper) + for sweeper in state.sweepers + if sweeper.playerID != state.self.playerID + ] + self.bulletsInfo = [self.__ObsBullet(bullet) for bullet in state.bullets] + self.homeInfo = [ + [*key, *value] for key, value in state.mapInfo.homeState.items() + ] + elif isinstance(state.self, THUAI7.Team): + self.sweeperInfo = [ + self.__ObsSweeper(sweeper) for sweeper in state.sweepers + ] + self.enemySweeperInfo = [ + self.__ObsSweeper(sweeper) for sweeper in state.enemySweepers + ] + self.recycleBankInfo = [ + [*key, *value] for key, value in state.mapInfo.recycleBankState.items() + ] + self.chargeStationInfo = [ + [*key, *value] for key, value in state.mapInfo.chargeStationState.items() + ] + self.signalTowerInfo = [ + [*key, *value] for key, value in state.mapInfo.chargeStationState.items() + ] + self.bridgeInfo = [ + [*key, value] for key, value in state.mapInfo.bridgeState.items() + ] + self.garbageInfo = [ + [*key, value] for key, value in state.mapInfo.garbageState.items() + ] + self.gameInfo = self.__ObsGame(state.gameInfo) + + def __ObsSweeper(sweeper: THUAI7.Sweeper): + return [ + sweeper.x, + sweeper.y, + sweeper.speed, + sweeper.facingDirection, + sweeper.viewRange, + sweeper.hp, + sweeper.armor, + sweeper.shield, + sweeper.sweeperState.value, + sweeper.sweeperType.value, + sweeper.producerType.value, + sweeper.constructorType.value, + sweeper.armorType.value, + sweeper.shieldType.value, + sweeper.weaponType.value, + ] + + def __ObsBullet(bullet: THUAI7.Bullet): + return [ + bullet.x, + bullet.y, + bullet.facingDirection, + bullet.speed, + bullet.damage, + bullet.bombRange, + bullet.explodeRange, + ] + + def __ObsGame(gameInfo: THUAI7.GameInfo): + return [ + [gameInfo.redHomeHp, gameInfo.redEnergy, gameInfo.redScore], + [gameInfo.blueHomeHp, gameInfo.blueEnergy, gameInfo.blueScore], + ] + + +class ActionSpace: + def __init__(self): + pass + + +class Memory: + def __init__(self, max_len): + self.memory = deque([], maxlen=max_len) + + def push(self, *args): + self.memory.append(Transition(*args)) + + def sample(self, batch_size): + return random.sample(self.memory, batch_size) + + def __len__(self): + return len(self.memory) diff --git a/CAPI/python/PyAPI/logic.py b/CAPI/python/PyAPI/logic.py index f9c90fcb..85dcd930 100644 --- a/CAPI/python/PyAPI/logic.py +++ b/CAPI/python/PyAPI/logic.py @@ -16,7 +16,6 @@ from PyAPI.Communication import Communication from PyAPI.State import State from PyAPI.Interface import ILogic, IGameTimer -from PyAPI.DebugAPI import SweeperDebugAPI, TeamDebugAPI class Logic(ILogic): @@ -183,27 +182,27 @@ def GetHomeHp(self) -> int: with self.__mtxState: self.__logger.debug("Called GetHomeHp") return copy.deepcopy( - self.__currentState.gameInfo.blueHomeHp + self.__currentState.gameInfo.redHomeHp if self.__teamID == 1 - else self.__currentState.gameInfo.redHomeHp + else self.__currentState.gameInfo.blueHomeHp ) def GetEnergy(self) -> int: with self.__mtxState: self.__logger.debug("Called GetEnergy") return copy.deepcopy( - self.__currentState.gameInfo.blueMoney + self.__currentState.gameInfo.redEnergy if self.__teamID == 1 - else self.__currentState.gameInfo.redMoney + else self.__currentState.gameInfo.blueEnergy ) def GetScore(self) -> int: with self.__mtxState: self.__logger.debug("Called GetScore") return copy.deepcopy( - self.__currentState.gameInfo.blueScore + self.__currentState.gameInfo.redScore if self.__teamID == 1 - else self.__currentState.gameInfo.redScore + else self.__currentState.gameInfo.blueScore ) def Attack(self, angle: float) -> int: @@ -893,11 +892,19 @@ def Main( # 构造timer if not file and not screen: - self.__timer = SweeperAPI(self) + if self.__playerID == 0: + self.__timer = TeamAPI(self) + else: + self.__timer = SweeperAPI(self) else: - self.__timer = SweeperDebugAPI( - self, file, screen, warnOnly, self.__playerID - ) + if self.__playerID == 0: + self.__timer = TeamDebugAPI( + self, file, screen, warnOnly, self.__playerID + ) + else: + self.__timer = SweeperDebugAPI( + self, file, screen, warnOnly, self.__playerID + ) # 构建AI线程 def AIThread(): @@ -923,7 +930,6 @@ def AIThread(): ) self.__threadAI = threading.Thread(target=AIThread) self.__threadAI.start() - self.__logger.info("Start to Process Message") self.__ProcessMessage() self.__logger.info("Join the AI thread.") self.__threadAI.join() diff --git a/CAPI/python/PyAPI/main.py b/CAPI/python/PyAPI/main.py index fb3874a3..65f3ad06 100644 --- a/CAPI/python/PyAPI/main.py +++ b/CAPI/python/PyAPI/main.py @@ -106,7 +106,9 @@ def THUAI7Main(argv: List[str], AIBuilder: Callable) -> None: playerType = THUAI7.PlayerType.Team else: playerType = THUAI7.PlayerType.Sweeper - sweeperType = Setting.SweeperTypes()[pID] + sweeperType = Setting.SweeperTypes()[ + pID - 1 + ] # 减去1 是因为字典从0计数,而我们的船是从1计数 if platform.system().lower() == "windows": PrintWelcomeString() diff --git a/CAPI/python/PyAPI/structures.py b/CAPI/python/PyAPI/structures.py index a4b66165..66e14b65 100644 --- a/CAPI/python/PyAPI/structures.py +++ b/CAPI/python/PyAPI/structures.py @@ -34,12 +34,9 @@ class ShapeType(Enum): class PlayerTeam(Enum): - NullTeam = 0 - Red = 1 - Blue = 2 - - -playerTeamDict = {PlayerTeam.NullTeam: 0, PlayerTeam.Red: 1, PlayerTeam.Blue: 2} + Red = 0 + Blue = 1 + NullTeam =2 class PlayerType(Enum): diff --git a/CAPI/python/debug.py b/CAPI/python/debug.py new file mode 100644 index 00000000..b872c15e --- /dev/null +++ b/CAPI/python/debug.py @@ -0,0 +1,23 @@ +import subprocess +import time +commands = [ + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 0 -t 0 -o", + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 1 -t 0 -o", + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 2 -t 0 -o", + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 3 -t 0 -o", + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 4 -t 0 -o", + + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 0 -t 1 -o", + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 1 -t 1 -o", + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 2 -t 1 -o", + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 3 -t 1 -o", + "python PyAPI\main.py -I 127.0.0.1 -P 8888 -p 4 -t 1 -o", +] + +processes = [] +for cmd in commands: + processes.append(subprocess.Popen(cmd, shell=True)) + time.sleep(0.5) + +for process in processes: + process.wait() diff --git a/CAPI/shell/RunCpp.sh b/CAPI/shell/RunCpp.sh new file mode 100644 index 00000000..ced79c60 --- /dev/null +++ b/CAPI/shell/RunCpp.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 0 -t 0 -o& +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 1 -t 0 -o& +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 2 -t 0 -o& +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 3 -t 0 -o& +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 4 -t 0 -o& + +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 0 -t 1 -o& +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 1 -t 1 -o& +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 2 -t 1 -o& +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 3 -t 1 -o& +./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 4 -t 1 -o& \ No newline at end of file diff --git a/CAPI/shell/RunPython.sh b/CAPI/shell/RunPython.sh new file mode 100644 index 00000000..46eed31c --- /dev/null +++ b/CAPI/shell/RunPython.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 0 -t 0 -o& +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 1 -t 0 -o& +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 2 -t 0 -o& +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 3 -t 0 -o& +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 4 -t 0 -o& + +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 0 -t 1 -o& +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 1 -t 1 -o& +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 2 -t 1 -o& +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 3 -t 1 -o& +python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 4 -t 1 -o& \ No newline at end of file