class Window1: def __init__(self, controller): self._window = tk.Tk() self._ctrler = controller # ustawianie parametrów okna self._window.title("Saper") self._window.iconbitmap("icon.ico") x = (self._window.winfo_screenwidth() / 4) y = (self._window.winfo_screenheight() / 4) self._window.geometry('+%d+%d' % (x, y)) self._window.bind("<Key>", lambda event: controller.keyPressed( event.char)) # wykrywanie wciskanych przycisków # view1 self.menu = Menu(self._window, controller) # view2 self.map = GameMap(self._window, controller) self.map.timer() def setController(self, controller): self._ctrler = controller def windowLoop(self): self._window.mainloop()
def testNonIntegerMovement(self): gameMap = GameMap(1000) gameObject = GameObject([1, 0], 'drone', 'owen') gameObject.velocity = [-0.5, 0] gameMap.addObject(gameObject) gameMap.update() self.assertEqual(gameObject.loc, [0.5, 0])
def __init__(self, filename1: str, filename2: str, max_time: float, max_turn: int, map_args: dict): """初始化一局游戏,具体规则请参见文档(文档组加油! Args: filename1 (str): 玩家1的脚本 filename2 (str): 玩家2的脚本目录 max_time (float): 单步的最大思考时间 max_turn (int): 允许进行的最大回合数 map_args (dict): 包含地图配置的字典 """ self.__max_time = max_time self.__map = GameMap(map_args) self.__winner = None self.__game_end = False self.__game_end_reason = "游戏未结束。" self.__max_turn = max_turn self.__history_map = { "map": self.__map.export_map_as_dic(), "player_name": { 0: filename1, 1: filename2, -1: "No player(draw)", None: "玩家函数错误" }, "result": "游戏还没结束。", "history": [self.__map.update([], [])] } #开局的地图也要记录 try: exec( "from AIs.{} import player_func; self.player_func1 = player_func" .format(filename1)) except: # if function is not found, the opposite wins self.__winner = 1 self.__game_end = True try: exec( "from AIs.{} import player_func; self.player_func2 = player_func" .format(filename2)) except: if self.__game_end: # both players fail to write a correct function, no one wins self.__winner = None else: self.__winner = 0 self.__game_end = True history = self.get_history() filename = os.path.join(os.path.dirname(__file__), 'debug.json') with open(filename, 'w') as f: f.write('') json.dump(history, f) self.web = SeleniumClass() self.web.openJson('debug.json')
def __init__(self): self.tile_size = 64 self.map_dim = 16 self.map_size = self.tile_size * self.map_dim self.screen = pygame.display.set_mode((self.map_size, self.map_size)) self.sheet = SpriteSheet("allSprites_default.png", "allSprites_default.xml") self.map = GameMap("map.txt", self.map_dim, self.tile_size) self.players = [] self.init_tanks()
def testAddObject(self): gameMap = GameMap(100) #Testing a valid Game Object validGameObject = GameObject([0,0], 'drone', 'owen') self.assertTrue(gameMap.addObject(validGameObject)) #Testing an invalid Game Object invalidGameObject = GameObject([gameMap.size[0], 0], 'beacon', 'charter') self.assertFalse(gameMap.addObject(invalidGameObject)) dupeGameObject = GameObject([0,0], 'beacon', 'owen') self.assertTrue(gameMap.addObject(dupeGameObject)) self.assertEqual(len(gameMap.gameObjects['owen']), 2)
def testAddObject(self): gameMap = GameMap(2) #Testing a valid Game Object validGameObject = GameObject([0,0], 'drone', 'owen') self.assertTrue(gameMap.addObject(validGameObject)) #Testing an invalid Game Object invalidGameObject = GameObject([gameMap.size[0], 0], 'beacon', 'charter') self.assertFalse(gameMap.addObject(invalidGameObject)) dupeGameObject = GameObject([0,0], 'beacon', 'owen') self.assertTrue(gameMap.addObject(dupeGameObject)) self.assertEqual(len(gameMap.playerSortedObjectDict['owen']), 2) self.assertFalse(gameMap.addObject(dupeGameObject)) #Testing that too many game objects cannot be added
class Preview(object): def __init__(self): self.tile_size = 64 self.map_dim = 16 self.map_size = self.tile_size * self.map_dim self.screen = pygame.display.set_mode((self.map_size, self.map_size)) self.sheet = SpriteSheet("allSprites_default.png", "allSprites_default.xml") self.map = GameMap("map.txt", self.map_dim, self.tile_size) self.players = [] self.init_tanks() def init_tanks(self): for t in range(4): tank = self.map.get_initial_tank_state(t + 1) if tank is None: break image = self.sheet.get_image_name(tank.image_name()) player = Player(tank, image, self.tile_size, DummyController()) player.set_animation(Move(self.tile_size, "up", "forward")) self.players.append(player) def render_sand(self): base_tile = "tileSand1.png" for y in range(self.map_dim): off_y = y * self.tile_size for x in range(self.map_dim): off_x = x * self.tile_size self.screen.blit(self.sheet.get_image_name(base_tile), (off_x, off_y)) def render_obstacles(self): for y in range(self.map_dim): for x in range(self.map_dim): self.map.blit(self.screen, self.sheet, x, y) def render_tanks(self, delta_ms): for player in self.players: player.step(delta_ms) angle = player.angle() image = pygame.transform.rotate(player.canvas_image(), angle) pos = (player.canvas_x(), player.canvas_y()) self.screen.blit(image, pos) def render(self, delta_ms): self.render_sand() self.render_obstacles() self.render_tanks(delta_ms)
def __init__(self, Player1, Player2, parent=None): super(Game, self).__init__(parent) self.setFixedSize(645, 415) self.setWindowTitle("King of Siam") self.setStyleSheet( "background-color: #2d3436; color: white; font-size: 18px;") self.setWindowIcon(QtGui.QIcon('./content/boulder.png')) self.title = QtWidgets.QLabel(self) self.title.setText("King of Siam") self.title.setStyleSheet( "font-size: 41px; font-family: Bradley Hand ITC; font-weight: bold; color: #ee5253;" ) self.title.setGeometry(375, 10, 300, 50) self.namePlayer1 = Player1 self.namePlayer2 = Player2 # Game setup self.g = GameMap() if self.g.playerTurn == 'Elephant': self.currentPlayer1 = True else: self.currentPlayer1 = False self.ndir = np.array([1, 0]) self.ndirDeg = 270 self.startpoint = True self.selectValid = False # Showing the gamemap label = QtWidgets.QLabel(self) Pixmap = QtGui.QPixmap('./content/gamemap.png') label.setPixmap(Pixmap) label.setGeometry(10, 5, 360, 360) self.setTiles() self.refresh() # Creating the buttons self.cancelButton() self.deleteButton() self.validButton() self.playerBoard() self.turnWidget() self.saveWidget() self.show()
def __init__(self): self.last_room = None self.map = GameMap() self.inventory = [] self.move_count = 1 self.current_room = self.map.rooms[0][0] self.current_room.user_visited = True
def runGame(self, gm: GameMap = None, timePerTurn: float = 0): if gm is None: gm = self.initGameMap() gh = GameHistory(gm) if timePerTurn > 0: utils.clearScreen() gm.printMap() time.sleep(timePerTurn) turn = 0 while True: if self.checkGameEnd(gm): break playerPos = [pos for pos in gm.data if gm.data[pos] != None] random.shuffle(playerPos) for pos in playerPos: player = gm.data[pos] if player is None: continue vision = gm.getVision(pos, 5) gh.actions.append((pos, player.ai.getAction(vision))) gh.applyAction(gm) turn += 1 if timePerTurn > 0: utils.clearScreen() gm.printMap() print("turn: " + str(turn)) time.sleep(timePerTurn) if timePerTurn > 0: print("done in %d turns" % turn) return gh
def __init__(self, map_height=12, map_width=12, num_of_cheese=3): self.map_height = map_height self.map_width = map_width self.num_of_cheese = num_of_cheese self.visited_cheese_pos = [] self.visited_mouse_pos = [] self.visited_cat_pos = [] self.game_states = [] self.mouse_path = [] self.mouse_initial_pos = [] self.random_coordinates = [] self.generate_resources() self.cheese_pos.sort(key=self.compare_by_distance) self.game_state = GameState.BasicGameState(self.mouse.current_pos, self.cat.current_pos, self.cheese_pos) self.game_states.append(self.game_state) self.game_map = GameMap(self.game_state, map_height, map_width) self.canvas = Canvas(self.game_map)
def moveUp(gm: GameMap, pos: (int, int)): dest = (pos[0], pos[1] - 1) if pos[0] >= gm.size or pos[1] >= gm.size: return False if pos[0] < 0 or pos[1] < 0: return False if dest[0] >= gm.size or dest[1] >= gm.size: return False if dest[0] < 0 or dest[1] < 0: return False if gm.data[dest] != None: return False gm.data[dest] = gm.data[pos] gm.data[pos] = None return True
class Game: def __init__(self, size, init_fruits=None, init_pos=None, draw_settings=None, default_direction=Direction.LEFT): self.size = size self.game_controller = GameController(default_direction) if init_fruits is None: init_fruits = get_init_fruits(size) if init_pos is None: init_pos = get_init_pos(size) self.game_map = GameMap(size, init_fruits, init_pos) if draw_settings is None: draw_settings = DrawGameSettings() self.game_drawer = GameDrawer(self.game_map, draw_settings) def play(self, delay=0.4): while True: direction = self.game_controller.determine() try: self.game_map.move(direction) except CutYourselfException: raise GameOverException except BoundException: raise GameOverException time.sleep(delay) os.system('clear') self.game_drawer.draw()
def __init__(self, filename1: str, filename2: str, map_args: dict): """初始化一局游戏,具体规则请参见文档(文档组加油! Args: filename1 (str): 玩家1的脚本 filename2 (str): 玩家2的脚本目录 map_args (dict): 包含地图配置的字典 """ self.__max_time = config.MAX_TIME self.__map = GameMap(map_args) self.__winner = None self.__game_end = False self.__game_end_reason = "游戏未结束。" self.__max_turn = config.MAX_TURN self.__player = [] self.__history_map = { "map": self.__map.export_map_as_dic(), "player_name": {0: filename1, 1: filename2, -1: "No player(draw)", None: "玩家函数错误" }, "result": "游戏还没结束。", "history": [self.__map.update([], [])] }#开局的地图也要记录 try: exec("""from AIs.{} import player_class as player_class1 self.addPlayer(player_class1(0))""".format(filename1)) except: # if function is not found, the opposite wins self.__winner = 1 self.__game_end = True try: exec("""from AIs.{} import player_class as player_class2 self.addPlayer(player_class2(1))""".format(filename2)) except: if self.__game_end: # both players fail to write a correct function, no one wins self.__winner = None else: self.__winner = 0 self.__game_end = True
def __init__(self, size, init_fruits=None, init_pos=None, draw_settings=None, default_direction=Direction.LEFT): self.size = size self.game_controller = GameController(default_direction) if init_fruits is None: init_fruits = get_init_fruits(size) if init_pos is None: init_pos = get_init_pos(size) self.game_map = GameMap(size, init_fruits, init_pos) if draw_settings is None: draw_settings = DrawGameSettings() self.game_drawer = GameDrawer(self.game_map, draw_settings)
def initGameMap(self, entityList: [GameEntity] = None): gm = GameMap(self.size) spotsLeft = [pos for pos in gm.data if gm.data[pos] == None] random.shuffle(spotsLeft) if entityList == None: entityList = [] for t in NUM_TYPES: for n in range(NUM_TYPES[t]): entityList.append(GameEntity(t, KillAI())) if len(spotsLeft) < len(entityList): raise "Not enough spots for entites" spotsLeft = spotsLeft[:len(entityList)] for x in zip(spotsLeft, entityList): gm.data[x[0]] = x[1] return gm
def __init__(self, filename1: str, filename2: str, max_time: float, max_turn: int, map_args: dict): """ player's python file should include a function which looks like player_func(map: GameMap) -> [Tuple[int, int, float].....] when illegal moves are given, player would be considered to make no moves :param filename1: player 1's python file :param filename2: player 2's python file :param max_time: time limitation in seconds :param max_turn: maximum turn numbers :param map_args: game map's initialization parameters """ self.__max_time = max_time self.__map = GameMap(map_args) self.__winner = None self.__game_end = False self.__max_turn = max_turn self.__history_map = [self.__map.export_as_dic([], [])] #开局的地图也要记录 try: self.player_func1 = __import__(filename1).player_func except: # if function is not found, the opposite wins self.__winner = 'player2' self.__game_end = True try: self.player_func2 = __import__(filename2).player_func except: if self.__game_end: # both players fail to write a correct function, no one wins self.__winner = None else: self.__winner = 'player1' self.__game_end = True
def removeDead(gm: GameMap): for pos in gm.data: if gm.data[pos] != None and gm.data[pos].health <= 0: gm.data[pos] = None
return actions[action](gm, pos) def removeDead(gm: GameMap): for pos in gm.data: if gm.data[pos] != None and gm.data[pos].health <= 0: gm.data[pos] = None if __name__ == "__main__": import GameEntity print("Move right test") gm = GameMap(3) gm.data[(1, 1)] = "o" gm.printMap() execute(gm, (1, 1), MOVE_RIGHT) print() gm.printMap() print("\n") print("Move down test") gm = GameMap(3) gm.data[(1, 1)] = "o"
def displayGame(self, timePerTurn: float = 0.5): i = 1 for state in self.getAllStates(): utils.clearScreen() state.printMap() print("%d / %d" % (i, len(self.actions)+1)) i += 1 time.sleep(timePerTurn) if __name__ == "__main__": import GameEntity from GameConstants import * gm = GameMap(5) gm.data[(2, 2)] = GameEntity.GameEntity(TYPE_MALE) gh = GameHistory(gm) gh.actions.append(((2, 2), GameMove.MOVE_UP)) gh.actions.append(((2, 1), GameMove.MOVE_UP)) for state in gh.getAllStates(): state.printMap() print() for i in range(len(gh.actions)+1): gh.calcState(i).printMap() print()
class Player: logged_in = False gm = GameMap() tn = None z = 0 x = 0 y = 0 details = {"username": "******", "password": "******"} def __print_response(self): response = self.tn.read_until(b"\r\n\r\n> ", timeout=.1) print("---") for i, line in enumerate(response.decode('ascii').split("\n")): print(i, line) def get_detail(self, detail): return f"{self.details[detail]}\n".encode('ascii') def login(self): line = self.tn.read_very_eager() line = line.decode('ascii') # if line != "": # print(line.strip()) if not self.logged_in: if "what name do you wish to be known?" in line: self.tn.write(self.get_detail("username")) if "Password:"******"password")) if "PRESS RETURN" in line: self.tn.write("\n".encode('ascii')) if "Make your choice:" in line: self.tn.write("1\n".encode('ascii')) self.logged_in = True if "Reconnecting." in line: self.logged_in = True def move_west(self): self.tn.write('w\n'.encode('ascii')) self.x -= 1 def move_east(self): self.tn.write('e\n'.encode('ascii')) self.x += 1 def move_south(self): self.tn.write('s\n'.encode('ascii')) self.y -= 1 def move_north(self): self.tn.write('n\n'.encode('ascii')) self.y += 1 def move_up(self): self.tn.write('u\n'.encode('ascii')) self.z += 1 def move_down(self): self.tn.write('d\n'.encode('ascii')) self.z -= 1 def get_room_info(self): self.tn.write('l\n'.encode('ascii')) response = self.tn.read_until(b"\r\n\r\n> ", timeout=.1) self.gm.current = Tile( response.decode('ascii').split("\n")[0], self.z, self.x, self.y) # for i, line in enumerate(response.decode('ascii').split("\n")): # if i == 0: # if self.gm.current is None: # self.gm.current = Tile(line) # break def get_tile_in_direction(self, direction): temp = None success = True if direction == "n": self.move_north() elif direction == "e": self.move_east() elif direction == "s": self.move_south() elif direction == "w": self.move_west() elif direction == "u": self.move_up() elif direction == "d": self.move_down() response = self.tn.read_until(b"\r\n\r\n> ", timeout=.1) checkmove = response.decode('ascii').split("\n")[0] if "Alas, you cannot" in checkmove: success = False if success: self.tn.write('l\n'.encode('ascii')) response = self.tn.read_until(b"\r\n\r\n> ", timeout=.1) title = response.decode('ascii').split("\n")[0] temp = Tile(title, self.z, self.x, self.y) if direction == "n": # print("Im trying to move south") self.move_south() if direction == "e": self.move_west() if direction == "s": self.move_north() if direction == "w": self.move_east() if direction == "u": self.move_down() if direction == "d": self.move_up() self.tn.read_until(b"\r\n\r\n> ", timeout=.1) return temp def check_exits(self): exits = { "n": None, "e": None, "s": None, "w": None, "u": None, "d": None } for k in exits.keys(): temp = self.get_tile_in_direction(k) # print(f"MOVING {k}") if temp is not None: exits[k] = temp self.gm.current.exits = exits self.gm.add_tile(self.gm.current, self.z, self.x, self.y) self.gm.current = None
class Game: def __init__(self, filename1: str, filename2: str, map_args: dict): """初始化一局游戏,具体规则请参见文档(文档组加油! Args: filename1 (str): 玩家1的脚本 filename2 (str): 玩家2的脚本目录 map_args (dict): 包含地图配置的字典 """ self.__max_time = config.MAX_TIME self.__map = GameMap(map_args) self.__winner = None self.__game_end = False self.__game_end_reason = "游戏未结束。" self.__max_turn = config.MAX_TURN self.__player = [] self.__history_map = { "map": self.__map.export_map_as_dic(), "player_name": {0: filename1, 1: filename2, -1: "No player(draw)", None: "玩家函数错误" }, "result": "游戏还没结束。", "history": [self.__map.update([], [])] }#开局的地图也要记录 try: exec("""from AIs.{} import player_class as player_class1 self.addPlayer(player_class1(0))""".format(filename1)) except: # if function is not found, the opposite wins self.__winner = 1 self.__game_end = True try: exec("""from AIs.{} import player_class as player_class2 self.addPlayer(player_class2(1))""".format(filename2)) except: if self.__game_end: # both players fail to write a correct function, no one wins self.__winner = None else: self.__winner = 0 self.__game_end = True def addPlayer(self, player): self.__player.append(player) def next_step(self): """这里是对局面进行一次更新,询问两方玩家获得actionList,然后调用update() """ map_info1 = deepcopy(self.__map) map_info2 = deepcopy(self.__map) if True: # 测试代码,测试的时候改成False try: with time_limit(self.__max_time, "player1"): player1_actions = self.__player[0].player_func(map_info1) except Exception: print("Player func 1 error!") player1_actions = [] else: with time_limit(self.__max_time, "player1"): player1_actions = self.__player[0].player_func(map_info1) # 这里是否应该捕捉到异常之后直接判负? try: with time_limit(self.__max_time, "player2"): player2_actions = self.__player[1].player_func(map_info2) except Exception: print("Player func 2 error!") player2_actions = [] if self.__game_end: return # 历史地图字典,存入列表 self.__history_map["history"].append( self.__map.update(player1_actions, player2_actions) ) def run(self): """这是运行接口,将返回胜利者 Returns: str: 胜利者, 0, 1, or -1 """ for turn in range(self.__max_turn): if self.__game_end: break self.next_step() #print(self.__map) # 测试代码,记得删 #print("___________________________________________________________________________") end_early = self.__map.end_early() if end_early is not None: self.__winner = end_early self.__game_end = True if self.__winner==0: self.__game_end_reason = ( "Player2(%s)的基地被打爆了!"%self.__history_map["player_name"][1] ) if self.__winner==1: self.__game_end_reason = ( "Player1(%s)的基地被打爆了!"%self.__history_map["player_name"][0] ) if self.__winner==-1: self.__game_end_reason = ( "双方玩家的基地同时被打爆了!" ) self.__winner = self.__map.high_score()[0] assert self.__winner in (0, 1, -1) break else: self.__winner, self.__game_end_reason = self.__map.high_score() # 游戏已结束 self.__history_map["result"] = ( self.__game_end_reason + "\n" + self.__history_map["player_name"][self.__winner] + "获胜!" ) return self.__winner def get_history(self): return self.__history_map
def testRemoveObject(self): gameMap = GameMap(2) gameMap.addObject(GameObject([0,0], 'drone', 'owen')) self.assertTrue(gameMap.removeObject('owen-drone-0')) self.assertEqual(len(gameMap.gameObjects), 0) #Testing the length of the unsorted gameObjects list self.assertListEqual(gameMap.playerSortedObjectDict['owen'], [])
class GameDebug: def __init__(self, filename1: str, filename2: str, max_time: float, max_turn: int, map_args: dict): """初始化一局游戏,具体规则请参见文档(文档组加油! Args: filename1 (str): 玩家1的脚本 filename2 (str): 玩家2的脚本目录 max_time (float): 单步的最大思考时间 max_turn (int): 允许进行的最大回合数 map_args (dict): 包含地图配置的字典 """ self.__max_time = max_time self.__map = GameMap(map_args) self.__winner = None self.__game_end = False self.__game_end_reason = "游戏未结束。" self.__max_turn = max_turn self.__history_map = { "map": self.__map.export_map_as_dic(), "player_name": { 0: filename1, 1: filename2, -1: "No player(draw)", None: "玩家函数错误" }, "result": "游戏还没结束。", "history": [self.__map.update([], [])] } #开局的地图也要记录 try: exec( "from AIs.{} import player_func; self.player_func1 = player_func" .format(filename1)) except: # if function is not found, the opposite wins self.__winner = 1 self.__game_end = True try: exec( "from AIs.{} import player_func; self.player_func2 = player_func" .format(filename2)) except: if self.__game_end: # both players fail to write a correct function, no one wins self.__winner = None else: self.__winner = 0 self.__game_end = True history = self.get_history() filename = os.path.join(os.path.dirname(__file__), 'debug.json') with open(filename, 'w') as f: f.write('') json.dump(history, f) self.web = SeleniumClass() self.web.openJson('debug.json') def next_step(self): """这里是对局面进行一次更新,询问两方玩家获得actionList,然后调用update() """ map_info1 = deepcopy(self.__map) map_info2 = deepcopy(self.__map) if False: # 测试代码,测试的时候改成False try: with time_limit(self.__max_time, "player1"): player1_actions = self.player_func1(map_info1, 0) except Exception: print("Player func 1 error!") player1_actions = [] else: with time_limit(self.__max_time, "player1"): player1_actions = self.player_func1(map_info1, 0) # 这里是否应该捕捉到异常之后直接判负? try: with time_limit(self.__max_time, "player2"): player2_actions = self.player_func2(map_info2, 1) except Exception: print("Player func 2 error!") player2_actions = [] if self.__game_end: return # 历史地图字典,存入列表 self.__history_map["history"].append( self.__map.update(player1_actions, player2_actions)) def run(self): """这是运行接口,将返回胜利者 Returns: str: 胜利者 """ for turn in range(self.__max_turn): os.system('cls') print('=' * 30 + 'debug' + '=' * 30) if self.__game_end: break self.next_step() history = self.historyDebug() filename = os.path.join(os.path.dirname(__file__), 'debug.json') with open(filename, 'w') as f: f.write('') json.dump(history, f) self.web.openJson('debug.json') self.web.click() self.web.click() ans = '' ### print(self.__history_map) for i in self.__history_map["map"]["edges"].keys(): ans += 'Node{} Power: '.format(str(i)) ans += str(history["history"][0]['power'][i]) + '------>' ans += str(history["history"][1]['power'][i]) + '------>' ans += str(history["history"][2]['power'][i]) + '\n' print(ans) end_early = self.__map.end_early() if end_early is not None: self.__winner = end_early self.__game_end = True if self.__winner == 0: self.__game_end_reason = ( "Player2(%s)的基地被打爆了!" % self.__history_map["player_name"][1]) if self.__winner == 1: self.__game_end_reason = ( "Player1(%s)的基地被打爆了!" % self.__history_map["player_name"][0]) if self.__winner == -1: self.__game_end_reason = ("双方玩家的基地同时被打爆了!") break while True: com = input('输入n播放下一帧,输入回车运行下一步') if com == 'n': self.web.click() elif com == '': break else: self.__winner, self.__game_end_reason = self.__map.high_score() # 游戏已结束 self.__history_map["result"] = ( self.__game_end_reason + "\n" + self.__history_map["player_name"][self.__winner] + "获胜!") return self.__winner def get_history(self): return self.__history_map def historyDebug(self): map_info = self.get_history() map_info["history"] = map_info["history"][-1] return map_info
def set_map(self, new_map_name: str, one_time_decorations: Optional[List[MapDecoration]] = None, respawn_decorations: bool = False, init: bool = False) -> None: # print('setMap to', new_map_name, flush=True) old_map_name = '' if not init: old_map_name = self.get_map_name() # Set light diameter for the new map if there was not an old map or if the new default map # diameter is unlimited. Also update the light diameter for the new map if the default light # diameters between the old and new maps are different and either the old map default light # diameters was unlimited or the current diameter is less than the default light diameter of the # new map. new_map_light_diameter = self.game_info.maps[ new_map_name].light_diameter if (not old_map_name or new_map_light_diameter is None or (new_map_light_diameter != self.game_info.maps[old_map_name].light_diameter and (self.game_info.maps[old_map_name].light_diameter is None or (self.hero_party.light_diameter is not None and self.hero_party.light_diameter < new_map_light_diameter)))): self.hero_party.light_diameter = new_map_light_diameter # If changing maps and set to respawn decorations, clear the history of removed decorations if respawn_decorations: self.removed_decorations_by_map = {} map_decorations = self.game_info.maps[ new_map_name].map_decorations.copy() removed_map_decorations: List[MapDecoration] = [] if one_time_decorations is not None: map_decorations += one_time_decorations # Prune out decorations where the progress marker conditions are not met for decoration in map_decorations[:]: if not self.check_progress_markers( decoration.progress_marker, decoration.inverse_progress_marker): map_decorations.remove(decoration) # Prune out previously removed decorations if new_map_name in self.removed_decorations_by_map: for decoration in self.removed_decorations_by_map[new_map_name]: if decoration in map_decorations: map_decorations.remove(decoration) if decoration.type is not None and decoration.type.removed_image is not None: removed_map_decorations.append(decoration) if old_map_name == new_map_name: # If loading up the same map, should retain the NPC positions npcs = self.game_map.npcs # Remove any current NPCs which should be missing for npc_char in npcs[:]: if not self.check_progress_markers( npc_char.npc_info.progress_marker, npc_char.npc_info.inverse_progress_marker): npcs.remove(npc_char) # Add missing NPCs for npc in self.game_info.maps[new_map_name].npcs: if not self.check_progress_markers( npc.progress_marker, npc.inverse_progress_marker): continue is_missing = True for npc_char in npcs: if npc_char.npc_info is not None and npc == npc_char.npc_info: is_missing = False break if is_missing: npcs.append(NpcState(npc)) else: # On a map change load NPCs from scratch npcs = [] for npc in self.game_info.maps[new_map_name].npcs: if self.check_progress_markers(npc.progress_marker, npc.inverse_progress_marker): npcs.append(NpcState(npc)) self.game_map = GameMap(self, new_map_name, map_decorations, removed_map_decorations, npcs)
def initializeGameMap(map_file): return GameMap(map_file)
for d in dirs: retDist = abs(center[0] - dirs[ret][0]) + abs(center[1] - dirs[ret][1]) dirDist = abs(center[0] - dirs[d][0]) + abs(center[1] - dirs[d][1]) if dirDist < retDist: ret = d return ret if __name__ == "__main__": import GameEntity print("Test kill ai") gm = GameMap(3) gm.data[(1, 1)] = GameEntity.GameEntity(TYPE_WOLF) ai = KillAI() print(ACTION_NAMES[ai.getAction(gm)]) gm.data[(0, 0)] = GameEntity.GameEntity(TYPE_MALE) print(ACTION_NAMES[ai.getAction(gm)]) gm.data[(0, 0)] = None gm.data[(0, 1)] = GameEntity.GameEntity(TYPE_MALE) print(ACTION_NAMES[ai.getAction(gm)])
def getAction(self, vision: GameMap): center = vision.getCenter() targets = [key for key in vision.data if key != center] targets = [key for key in targets if vision.data[key] != None] targets = [ key for key in targets if vision.data[key].type != TYPE_BARRIER ] if not self.killFriends: targets = [ key for key in targets if vision.data[key].type != vision.data[center].type ] if len(targets) == 0: dirs = { MOVE_RIGHT: (center[0] + 1, center[1]), MOVE_DOWN: (center[0], center[1] + 1), MOVE_LEFT: (center[0] - 1, center[1]), MOVE_UP: (center[0], center[1] - 1), } dirs = [d for d in dirs if vision.data[dirs[d]] is None] if len(dirs) == 0: return random.choice(ACTION_LIST) return random.choice(dirs) dist = [ abs(center[0] - pos[0]) + abs(center[1] - pos[1]) for pos in targets ] closestTarget = len(dist) - 1 for i in range(len(dist) - 1): if dist[i] < dist[closestTarget]: closestTarget = i target = targets[closestTarget] if dist[closestTarget] == 1: dirs = { (center[0] + 1, center[1]): ATTACK_RIGHT, (center[0], center[1] + 1): ATTACK_DOWN, (center[0] - 1, center[1]): ATTACK_LEFT, (center[0], center[1] - 1): ATTACK_UP, } return dirs[target] dirs = { MOVE_RIGHT: (center[0] + 1, center[1]), MOVE_DOWN: (center[0], center[1] + 1), MOVE_LEFT: (center[0] - 1, center[1]), MOVE_UP: (center[0], center[1] - 1), } newDirs = {} for d in dirs: if vision.data[dirs[d]] == None: newDirs[d] = dirs[d] dirs = newDirs if len(dirs) == 0: return DO_NOTHING ret = random.choice([d for d in dirs]) for d in dirs: retDist = abs(center[0] - dirs[ret][0]) + abs(center[1] - dirs[ret][1]) dirDist = abs(center[0] - dirs[d][0]) + abs(center[1] - dirs[d][1]) if dirDist < retDist: ret = d return ret
def draw_food(map_len, screen, food_pos, map_length): food_color = (0, 166, 244) pygame.draw.rect(screen, food_color, (food_pos[1] * map_length / map_len + 1, food_pos[0] * map_length / map_len + 1, map_length / map_len, map_length / map_len)) if len(sys.argv) > 0: # x = ReadFile(sys.argv[1], "map-out.txt") x = ReadFile("test.txt", "map-out.txt") t = x.read_file() food_fen = FoodGenerator() for m in range(0,11): init_state = GameMap(t, None, [0, 2], [[0, 2], [0, 1], [0, 0]], True) init_state_diagonal = GameMap(t, None, [0, 2], [[0, 2], [0, 1], [0, 0]], False) init_state.set_food_position(food_fen.generate_food(init_state.game_map)) init_state_diagonal.set_food_position(food_fen.generate_food(init_state.game_map)) movement_list_manhattan = [] movement_list_diagonal = [] for i in range(0, 30): # print "Score=", i mySearch = AStarSearch(init_state) diagonalSearch = AStarSearch(init_state_diagonal) diagonalSearch.start_search(False) mySearch.start_search(True) answer = mySearch.get_answer() answer_diagonal = diagonalSearch.get_answer() movement_list_manhattan.append(len(answer) - 1)
def testID(self): gameMap = GameMap(100) for i in range(10): gameMap.addObject(GameObject([0,0], 'drone', 'owen')) self.assertEqual(gameMap.gameObjects[i].ID, 'owen-drone-' + str(i)) #Testing successful ID assignment gameMap.addObject(GameObject([0,0], 'beacon', 'owen')) self.assertEqual(gameMap.playerSortedObjectDict['owen'][0].ID, 'owen-drone-0') #Testing successful '0' ID assignment self.assertTrue(gameMap.removeObject('owen-drone-2')) #Testing successful removal of an object self.assertIsNone(gameMap.getObject('owen-drone-2')) #Testing that the object was indeed removed self.assertIsNotNone(gameMap.getObject('owen-drone-3')) #Testing that another object that was added indeed exists gameMap.addObject(GameObject([1, 1], 'drone', 'owen')) self.assertIsNotNone(gameMap.getObject('owen-drone-2')) #Testing that, after adding a new relevant game object, the old ID=2 has been re-used
from GameMap import GameMap from GameObject import GameObject, Asteroid import config from functools import wraps def delay(delay=0.): # sets a timer to run a function later on - http://fredericiana.com/2014/11/14/settimeout-python-delay/ def wrap(f): @wraps(f) def delayed(*args, **kwargs): timer = threading.Timer(delay, f, args=args, kwargs=kwargs) timer.start() return delayed return wrap gameMap = GameMap(config.load_var('max_entities')) def runGame(tickFreq=.1): for _ in range(config.load_var('max_asteroids')):#Creates Asteroids Before game starts loc = [random.randint(0, config.load_var('map_x_size')), random.randint(0, config.load_var('map_y_size'))] asteroid = Asteroid(loc=loc, player='map') gameMap.addObject(asteroid) currentTime = time.time() startTime = currentTime tickCount = 0 t = threading.currentThread() print("Game loop has started.") while getattr(t, "do_run", True): if(time.time() - currentTime > tickFreq): #10 ticks per second. This number can be changed as necessary
class Game(object): def __init__(self): self.last_room = None self.map = GameMap() self.inventory = [] self.move_count = 1 self.current_room = self.map.rooms[0][0] self.current_room.user_visited = True # end def __init__ def inspect(self): text = self.map.inspect() text += "Inventory: %s" % self.inventory # end def inspect def describe_scene(self): # describe the room self.current_room.describe() # describe player's inventory print ("Your Inventory: ") if len(self.inventory) > 0: for item in range(0, len(self.inventory)): print (self.inventory[item]) # end for else: print ("NONE") # end if print ("") # end def describe_scene def get_next_move(self): header = "| Move: %d |" % self.move_count print ("-" * len(header)) print(header) print ("-" * len(header)) self.describe_scene() self.move_count += 1 next_move = None while not next_move: print("") print("What do you want to do? ...") choices = [] if self.current_room: for door in self.current_room.doors: choices.append("Move %s" % door) # end for for item in self.current_room.items: if (item == "Instructions"): choices.append("Get Instructions") elif (item == "Bear"): if not self.current_room.bear_is_sleeping: choices.append("Make Noise") choices.append("Fight Bear") else: pass # Sure? # end if elif (item == "Honey"): choices.append("Get Honey") elif (item == "Treasure!"): choices.append("Get Treasure!") else: raise Exception("Room contains an unknown item: %s. Should not have been possible to get here." % item) # end if # end for else: raise Exception("Room[%d][%d] is nil. Should not have been possible to get here." % (x_position, y_position)) # end if for item in self.inventory: if (item == "Instructions"): choices.append("Read Instructions") elif (item == "Honey"): choices.append("Drop Honey") choices.append("Eat Honey") else: raise Exception("Unknown inventory: %s. Should not have been possible to get here." % item) # end if # end for choices.append("Show Places I've Been") choices.append("About this Game") choices.append("Quit") for choice in range(0, len(choices)): print("%d) %s" % (choice+1, choices[choice])) # end for print (">>> Type the number of your choice followed by <Enter> or <Return>: ") choice = int(input()) print ("") if (choice > 0 and choice <= len(choices)): next_move = choices[choice-1] else: print("Sorry, I don't understand that choice. Please try again.") # end if # end while return next_move # end def next_move def do_pause(self): print ("\n<PRESS ANY KEY TO CONTINUE> ...") input() print ("\n\n") # end def do_pause def do_move(self, move): if (move == "Move North" or move == "Move South" or move == "Move East" or move == "Move West"): if (self.current_room.door_blocked_by_bear and self.current_room.door_blocked_by_bear in move): print("The bear is blocking that door!") print("You need to distract the bear or go in a different direction.") else: self.last_room = self.current_room if (move == "Move North"): self.current_room = self.map.rooms[self.current_room.x_location-1][self.current_room.y_location] elif (move == "Move South"): self.current_room = self.map.rooms[self.current_room.x_location+1][self.current_room.y_location] elif (move == "Move East"): self.current_room = self.map.rooms[self.current_room.x_location][self.current_room.y_location+1] elif (move == "Move West"): self.current_room = self.map.rooms[self.current_room.x_location][self.current_room.y_location-1] # end if self.current_room.user_visited = True self.current_room.prepare_room() print("Ok, you have moved in that direction.") # end if self.do_pause() elif (move == "Get Instructions"): self.inventory.append(self.current_room.remove_item("Instructions")) self.do_pause() elif (move == "Read Instructions"): print("The instructions are very simple:") print(" F I N D") print(" T H E") print(" T R E A S U R E") self.do_pause() elif (move == "Make Noise"): if (self.current_room.made_noise_once): print("You disturbed the bear again.") print("The bear got angry and ate your arms and legs.") print("You are dead. Game Over.") return False else: print("Wow! You're really loud.") print("But the bear didn't like that.") self.do_pause() self.current_room.made_noise_once = True # end if elif (move == "Fight Bear"): print("That wasn't very smart! The bear won.") print("You are dead. Game Over.") return False elif (move == "Get Honey"): self.inventory.append(self.current_room.remove_item("Honey")) print("Ok, you now have the honey.") self.do_pause() elif (move == "Drop Honey"): self.inventory.remove("Honey") print("Ok, you have dropped the honey in the room.") if ("Bear" in self.current_room.items): self.current_room.bear_is_sleeping = True self.current_room.door_blocked_by_bear = None print("I've got some good news and some bad news:") print("The good news is that the bear ate all the honey,") print("fell asleep, and is no longer guarding the door.") print("The bad news is that you have no more honey :(") self.do_pause() else: self.current_room.drop_item("Honey") # end if elif (move == "Eat Honey"): self.inventory.remove("Honey") print("That was yummy!") self.do_pause() elif (move == "Get Treasure!"): print("You got the treasure! YOU WIN!") return False elif (move == "Show Places I've Been"): self.map.show_known_map() self.do_pause() elif (move == "About this Game"): print("TreasureGame, written by Steve Frechette 2015") self.do_pause() elif (move == "Quit"): print("Sorry to see you go. Come again soon!") return False else: print("I don't understand that command.") self.do_pause() # end if return True # end def do_move def play(self): next_move = self.get_next_move() return self.do_move(next_move)
class Game: def __init__(self, filename1: str, filename2: str, max_time: float, max_turn: int, map_args: dict): """ player's python file should include a function which looks like player_func(map: GameMap) -> [Tuple[int, int, float].....] when illegal moves are given, player would be considered to make no moves :param filename1: player 1's python file :param filename2: player 2's python file :param max_time: time limitation in seconds :param max_turn: maximum turn numbers :param map_args: game map's initialization parameters """ self.__max_time = max_time self.__map = GameMap(map_args) self.__winner = None self.__game_end = False self.__max_turn = max_turn self.__history_map = [self.__map.export_as_dic([], [])] #开局的地图也要记录 try: self.player_func1 = __import__(filename1).player_func except: # if function is not found, the opposite wins self.__winner = 'player2' self.__game_end = True try: self.player_func2 = __import__(filename2).player_func except: if self.__game_end: # both players fail to write a correct function, no one wins self.__winner = None else: self.__winner = 'player1' self.__game_end = True def next_step(self): map_info1 = deepcopy(self.__map) map_info2 = deepcopy(self.__map) try: with time_limit(self.__max_time, "player1"): player1_actions = self.player_func1(map_info1, 0) except Exception: print("Player func 1 error!") # 这里是否应该捕捉到异常之后直接判负? player1_actions = [] try: with time_limit(self.__max_time, "player2"): player2_actions = self.player_func2(map_info2, 1) except Exception: print("Player func 2 error!") player2_actions = [] if self.__game_end: return self.__map.update(player1_actions, player2_actions) # 历史地图字典,存入列表 self.__history_map.append( self.__map.export_as_dic(player1_actions, player2_actions)) def run(self): """ :return: 'player1', 'player2' or None if there is no winner """ for turn in range(self.__max_turn): self.next_step() #print(self.__map) # 测试代码,记得删 #print("___________________________________________________________________________") if self.__game_end: break end_early = self.__map.end_early() if end_early is not None: self.__winner = end_early self.__game_end = True if self.__winner == "draw": self.__winner = None break else: self.__winner = self.__map.high_score() return self.__winner def get_history(self): return self.__history_map
def start_search(self, which_h): self.open_list.append(self.init_state) main_node = None while len(self.open_list) > 0: # print "openList Size =", len(self.open_list) main_node = self.open_list.pop(0) # print "pop node :" # main_node.print_matrix() # print "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" self.close_list.append(main_node) if main_node.heuristic == 0: # print "exist answer" self.print_answer(main_node) break # print "================================================" # print "bottom:" bottom_node = GameMap(main_node.get_matrix(), main_node, main_node.head, main_node.snake_position, which_h) bottom_node.snake_move_bottom() # bottom_node.print_matrix() if not self.exist_in_close(bottom_node): bottom_node.g = main_node.g + 1 bottom_node.f = max(bottom_node.f, bottom_node.g + bottom_node.heuristic) # print "f=", bottom_node.f self.update_open_list(bottom_node) # print "================================================" # print "left:" # print "snake_pos main", main_node.snake_position left_node = GameMap(main_node.get_matrix(), main_node, main_node.head, main_node.snake_position, which_h) left_node.snake_move_left() # left_node.print_matrix() if not self.exist_in_close(left_node): left_node.g = main_node.g + 1 left_node.f = max(left_node.f, left_node.g + left_node.heuristic) # print "f=", left_node.f self.update_open_list(left_node) # print "================================================" # print "right:" right_node = GameMap(main_node.get_matrix(), main_node, main_node.head, main_node.snake_position, which_h) right_node.snake_move_right() # right_node.print_matrix() if not self.exist_in_close(right_node): right_node.g = main_node.g + 1 right_node.f = max(right_node.f, right_node.g + right_node.heuristic) # print "f=", right_node.f self.update_open_list(right_node) # print "================================================" # print "top:" top_node = GameMap(main_node.get_matrix(), main_node, main_node.head, main_node.snake_position, which_h) top_node.snake_move_top() # top_node.print_matrix() if not self.exist_in_close(top_node): top_node.g = main_node.g + 1 top_node.f = max(top_node.f, top_node.g + top_node.heuristic) # print "f=", top_node.f self.update_open_list(top_node)
def testVectorMoveWithoutCollision(self): gameMap = GameMap(1000) gameObject = GameObject([0, 0], 'drone', 'owen') gameObject.velocity = [1, 2] gameObject.acceleration = [-1, -1] gameMap.addObject(gameObject) gameMap.update() self.assertEqual(gameObject.loc, [1,2]) gameMap.update() self.assertEqual(gameObject.loc, [1, 3]) gameMap.update() self.assertEqual(gameObject.loc, [0, 3]) gameMap.update() #Here, instead of going negative, the vectorMovementWithoutCollision function does nothing self.assertEqual(gameObject.loc, [0, 3])
def __init__(self): self.game = Game() self.gameMap = GameMap()
import threading, time, socket from GameMap import GameMap from Tools import Tools adminOnline = False map = GameMap() nbPlayers = 4 class Server(threading.Thread): ver = threading.RLock() def __init__(self, clientsocket): threading.Thread.__init__(self) self.clientsocket = clientsocket self.tool = Tools() def run(self): global adminOnline global map global nbPlayers nbPlayers = nbPlayers - 1 while True: print(">> ") r = self.clientsocket.recv(2048) r = r.decode() print(nbPlayers)
except: print('Invalid port') sys.exit() if not 1025 <= port <= 65535: print('Invalid port') sys.exit() socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: socket.connect(('localhost', port)) except ConnectionRefusedError: print('Connection refused, check host is running') sys.exit() player = Player() game_map = GameMap(player) goals = Goals(game_map) while True: data = receive_socket_data(socket) if not data: socket.close() sys.exit() #print_view(data) game_map.update_map(data) #game_map.print_map() #action = get_action() action = goals.find_next_goal() if not action: action = goals.extended_searches() player.player_action(action)
class GameState(GameStateInterface): game_map: GameMap def __init__(self, saves_path: str, base_path: str, game_xml_path: str, win_size_tiles: Point, tile_size_pixels: int) -> None: self.saves_path = saves_path self.win_size_tiles = win_size_tiles self.image_pad_tiles = self.win_size_tiles // 2 self.win_size_pixels = self.win_size_tiles * tile_size_pixels self.__should_add_math_problems_in_combat = True super().__init__(pygame.display.get_surface()) self.game_info = GameInfo(base_path, game_xml_path, tile_size_pixels, self.win_size_pixels) self.removed_decorations_by_map: Dict[str, List[MapDecoration]] = {} self.pending_dialog: Optional[DialogType] = None self.load() self.clock = pygame.time.Clock() self.tick_count = 0 # TODO: Migrate these to here # self.message_dialog: Optional[GameDialog] = None self.combat_encounter: Optional[CombatEncounter] = None def set_map(self, new_map_name: str, one_time_decorations: Optional[List[MapDecoration]] = None, respawn_decorations: bool = False, init: bool = False) -> None: # print('setMap to', new_map_name, flush=True) old_map_name = '' if not init: old_map_name = self.get_map_name() # Set light diameter for the new map if there was not an old map or if the new default map # diameter is unlimited. Also update the light diameter for the new map if the default light # diameters between the old and new maps are different and either the old map default light # diameters was unlimited or the current diameter is less than the default light diameter of the # new map. new_map_light_diameter = self.game_info.maps[ new_map_name].light_diameter if (not old_map_name or new_map_light_diameter is None or (new_map_light_diameter != self.game_info.maps[old_map_name].light_diameter and (self.game_info.maps[old_map_name].light_diameter is None or (self.hero_party.light_diameter is not None and self.hero_party.light_diameter < new_map_light_diameter)))): self.hero_party.light_diameter = new_map_light_diameter # If changing maps and set to respawn decorations, clear the history of removed decorations if respawn_decorations: self.removed_decorations_by_map = {} map_decorations = self.game_info.maps[ new_map_name].map_decorations.copy() removed_map_decorations: List[MapDecoration] = [] if one_time_decorations is not None: map_decorations += one_time_decorations # Prune out decorations where the progress marker conditions are not met for decoration in map_decorations[:]: if not self.check_progress_markers( decoration.progress_marker, decoration.inverse_progress_marker): map_decorations.remove(decoration) # Prune out previously removed decorations if new_map_name in self.removed_decorations_by_map: for decoration in self.removed_decorations_by_map[new_map_name]: if decoration in map_decorations: map_decorations.remove(decoration) if decoration.type is not None and decoration.type.removed_image is not None: removed_map_decorations.append(decoration) if old_map_name == new_map_name: # If loading up the same map, should retain the NPC positions npcs = self.game_map.npcs # Remove any current NPCs which should be missing for npc_char in npcs[:]: if not self.check_progress_markers( npc_char.npc_info.progress_marker, npc_char.npc_info.inverse_progress_marker): npcs.remove(npc_char) # Add missing NPCs for npc in self.game_info.maps[new_map_name].npcs: if not self.check_progress_markers( npc.progress_marker, npc.inverse_progress_marker): continue is_missing = True for npc_char in npcs: if npc_char.npc_info is not None and npc == npc_char.npc_info: is_missing = False break if is_missing: npcs.append(NpcState(npc)) else: # On a map change load NPCs from scratch npcs = [] for npc in self.game_info.maps[new_map_name].npcs: if self.check_progress_markers(npc.progress_marker, npc.inverse_progress_marker): npcs.append(NpcState(npc)) self.game_map = GameMap(self, new_map_name, map_decorations, removed_map_decorations, npcs) def load(self, pc_name_or_file_name: Optional[str] = None) -> None: # Set character state for new game save_game_file_path: Optional[str] = None if pc_name_or_file_name is not None: if os.path.isfile(pc_name_or_file_name): save_game_file_path = pc_name_or_file_name else: save_game_file_path = os.path.join( self.saves_path, pc_name_or_file_name + '.xml') if save_game_file_path is None or not os.path.isfile( save_game_file_path): self.game_info.parse_initial_game_state(pc_name_or_file_name) self.pending_dialog = self.game_info.initial_state_dialog pc = HeroState(self.game_info.character_types['hero'], self.game_info.initial_hero_pos_dat_tile, self.game_info.initial_hero_pos_dir, self.game_info.pc_name, self.game_info.pc_xp) if self.game_info.pc_hp is not None and self.game_info.pc_hp < pc.hp: pc.hp = self.game_info.pc_hp if self.game_info.pc_mp is not None and self.game_info.pc_mp < pc.mp: pc.mp = self.game_info.pc_mp pc.weapon = self.game_info.pc_weapon pc.armor = self.game_info.pc_armor pc.shield = self.game_info.pc_shield pc.other_equipped_items = self.game_info.pc_otherEquippedItems pc.unequipped_items = self.game_info.pc_unequippedItems self.hero_party = HeroParty(pc) self.hero_party.gp = self.game_info.pc_gp self.hero_party.progress_markers = self.game_info.pc_progressMarkers self.set_map(self.game_info.initial_map, self.game_info.initial_map_decorations, init=True) else: xml_root = ET.parse(save_game_file_path).getroot() map = xml_root.attrib['map'] party_members: List[HeroState] = [] # Local helper method for parsing party members def parse_party_member(member_element: ET.Element) -> None: member_type = self.game_info.character_types['hero'] if 'type' in member_element.attrib: member_type = self.game_info.character_types[ member_element.attrib['type']] member_is_combat_character = True if 'is_combat_character' in member_element.attrib: member_is_combat_character = member_element.attrib[ 'is_combat_character'] == 'yes' member = HeroState( member_type, self.game_info.get_location(map, member_element), self.game_info.get_direction(map, member_element), member_element.attrib['name'], int(member_element.attrib['xp']), member_is_combat_character) if 'hp' in member_element.attrib: member.hp = int(member_element.attrib['hp']) if 'mp' in member_element.attrib: member.mp = int(member_element.attrib['mp']) for item_element in member_element.findall( "./EquippedItems/Item"): item_name = item_element.attrib['name'] if item_name in self.game_info.weapons: member.weapon = self.game_info.weapons[item_name] elif item_name in self.game_info.armors: member.armor = self.game_info.armors[item_name] elif item_name in self.game_info.shields: member.shield = self.game_info.shields[item_name] elif item_name in self.game_info.tools: member.other_equipped_items.append( self.game_info.tools[item_name]) else: print('ERROR: Unsupported item', item_name, flush=True) for item_element in member_element.findall( "./UnequippedItems/Item"): item_name = item_element.attrib['name'] item_count = 1 if 'count' in item_element.attrib: item_count = int(item_element.attrib['count']) if item_name in self.game_info.items: member.unequipped_items[ self.game_info.items[item_name]] = item_count else: print('ERROR: Unsupported item', item_name, flush=True) party_members.append(member) # Parse the party members for member_element in xml_root.findall('./PartyMember'): parse_party_member(member_element) if 0 == len(party_members): # This is an old save, attempt to parse the root element as if it were a PartyMember parse_party_member(xml_root) # Create the hero party from the party members self.hero_party = HeroParty(party_members[0]) for member in party_members[1:]: self.hero_party.add_member(member) self.hero_party.set_main_character(xml_root.attrib['name']) # Parse properties of the entire party self.hero_party.gp = int(xml_root.attrib['gp']) # Load state related to repel monsters if 'repel_monsters' in xml_root.attrib: self.hero_party.repel_monsters = xml_root.attrib[ 'repel_monsters'] == 'yes' if 'repel_monsters_decay_steps_remaining' in xml_root.attrib: self.hero_party.repel_monsters_decay_steps_remaining =\ int(xml_root.attrib['repel_monsters_decay_steps_remaining']) if 'repel_monster_fade_dialog' in xml_root.attrib: self.hero_party.repel_monster_fade_dialog = [ xml_root.attrib['repel_monster_fade_dialog'] ] # Load state related to last outside position if 'last_outside_map' in xml_root.attrib: self.hero_party.last_outside_map_name = xml_root.attrib[ 'last_outside_map'] self.hero_party.last_outside_pos_dat_tile = Point( int(xml_root.attrib['last_outside_x']), int(xml_root.attrib['last_outside_y'])) self.hero_party.last_outside_dir = Direction[ xml_root.attrib['last_outside_dir']] # Load state related to removed decorations for removed_decoration_element in xml_root.findall( "./RemovedDecorations/RemovedDecoration"): removed_decoration_map_name = removed_decoration_element.attrib[ 'map'] removed_decoration_x = int( removed_decoration_element.attrib['x']) removed_decoration_y = int( removed_decoration_element.attrib['y']) removed_decoration_type_name = None if 'type' not in removed_decoration_element.attrib \ else removed_decoration_element.attrib['type'] # Find the removed map decoration and insert it into self.removed_decorations_by_map for decoration in self.game_info.maps[ removed_decoration_map_name].map_decorations: decoration_type_name = None if decoration.type is None else decoration.type.name if decoration_type_name == removed_decoration_type_name \ and decoration.point.x == removed_decoration_x \ and decoration.point.y == removed_decoration_y: if removed_decoration_map_name not in self.removed_decorations_by_map: self.removed_decorations_by_map[ removed_decoration_map_name] = [] self.removed_decorations_by_map[ removed_decoration_map_name].append(decoration) break # Parse the progress markers for progress_marker_element in xml_root.findall( "./ProgressMarkers/ProgressMarker"): self.hero_party.progress_markers.append( progress_marker_element.attrib['name']) # print('Loaded progress marker ' + progressMarkerElement.attrib['name'], flush=True) self.set_map(map, init=True) # Load state related to light diameter if 'light_diameter' in xml_root.attrib: self.hero_party.light_diameter = int( xml_root.attrib['light_diameter']) if 'light_diameter_decay_steps' in xml_root.attrib: self.hero_party.light_diameter_decay_steps = int( xml_root.attrib['light_diameter_decay_steps']) if 'light_diameter_decay_steps_remaining' in xml_root.attrib: self.hero_party.light_diameter_decay_steps_remaining = \ int(xml_root.attrib['light_diameter_decay_steps_remaining']) self.pending_dialog = self.game_info.parse_dialog(xml_root) # TODO: Remove Mocha from party ''' mocha = HeroState(self.game_info.character_types['mocha'], self.game_info.initial_hero_pos_dat_tile, self.game_info.initial_hero_pos_dir, 'Mocha', 0) self.hero_party.add_member(mocha) ''' # Initialize the default dialog font color based on the state of the hero party gde = GameDialogEvaluator(self.game_info, self) gde.update_default_dialog_font_color() def save(self, quick_save: bool = False) -> None: # Save the overall state of the party xml_root = ET.Element('SaveState') xml_root.attrib['name'] = self.hero_party.main_character.name xml_root.attrib['map'] = self.get_map_name() xml_root.attrib['gp'] = str(self.hero_party.gp) # Save state related to light diameter if self.hero_party.light_diameter is not None: xml_root.attrib['light_diameter'] = str( self.hero_party.light_diameter) if self.hero_party.light_diameter_decay_steps is not None: xml_root.attrib['light_diameter_decay_steps'] = str( self.hero_party.light_diameter_decay_steps) if self.hero_party.light_diameter_decay_steps_remaining is not None: xml_root.attrib['light_diameter_decay_steps_remaining'] =\ str(self.hero_party.light_diameter_decay_steps_remaining) # Save state related to repel monsters xml_root.attrib[ 'repel_monsters'] = 'yes' if self.hero_party.repel_monsters else 'no' if self.hero_party.repel_monsters_decay_steps_remaining is not None: xml_root.attrib['repel_monsters_decay_steps_remaining'] =\ str(self.hero_party.repel_monsters_decay_steps_remaining) if (self.hero_party.repel_monster_fade_dialog is not None and isinstance(self.hero_party.repel_monster_fade_dialog, str)): xml_root.attrib['repel_monster_fade_dialog'] = str( self.hero_party.repel_monster_fade_dialog) # Save state related to last outside position if '' != self.hero_party.last_outside_map_name: xml_root.attrib[ 'last_outside_map'] = self.hero_party.last_outside_map_name xml_root.attrib['last_outside_x'] = str( self.hero_party.last_outside_pos_dat_tile.x) xml_root.attrib['last_outside_y'] = str( self.hero_party.last_outside_pos_dat_tile.y) xml_root.attrib[ 'last_outside_dir'] = self.hero_party.last_outside_dir.name # Save state related to removed decorations removed_decorations_element = ET.SubElement(xml_root, 'RemovedDecorations') for map_name in self.removed_decorations_by_map: for decoration in self.removed_decorations_by_map[map_name]: removed_decoration_element = ET.SubElement( removed_decorations_element, 'RemovedDecoration') removed_decoration_element.attrib['map'] = map_name removed_decoration_element.attrib['x'] = str( decoration.point.x) removed_decoration_element.attrib['y'] = str( decoration.point.y) if decoration.type is not None: removed_decoration_element.attrib[ 'type'] = decoration.type.name # Save state for member of the hero party for member in self.hero_party.members: member_element = ET.SubElement(xml_root, 'PartyMember') member_element.attrib['name'] = member.name member_element.attrib['type'] = member.character_type.name member_element.attrib['x'] = str(member.curr_pos_dat_tile.x) member_element.attrib['y'] = str(member.curr_pos_dat_tile.y) member_element.attrib['dir'] = member.direction.name member_element.attrib['xp'] = str(member.xp) member_element.attrib['hp'] = str(member.hp) member_element.attrib['mp'] = str(member.mp) member_element.attrib[ 'is_combat_character'] = 'yes' if member.is_combat_character else 'no' items_element = ET.SubElement(member_element, 'EquippedItems') if member.weapon is not None: item_element = ET.SubElement(items_element, 'Item') item_element.attrib['name'] = member.weapon.name if member.armor is not None: item_element = ET.SubElement(items_element, 'Item') item_element.attrib['name'] = member.armor.name if member.shield is not None: item_element = ET.SubElement(items_element, 'Item') item_element.attrib['name'] = member.shield.name for tool in member.other_equipped_items: item_element = ET.SubElement(items_element, 'Item') item_element.attrib['name'] = tool.name items_element = ET.SubElement(member_element, 'UnequippedItems') for item, item_count in member.unequipped_items.items(): if item_count > 0: item_element = ET.SubElement(items_element, 'Item') item_element.attrib['name'] = item.name item_element.attrib['count'] = str(item_count) progress_markers_element = ET.SubElement(xml_root, 'ProgressMarkers') for progress_marker in self.hero_party.progress_markers: progress_marker_element = ET.SubElement(progress_markers_element, 'ProgressMarker') progress_marker_element.attrib['name'] = progress_marker # TODO: This should all be captured in game.xml if not quick_save: dialog_element = ET.SubElement(xml_root, 'Dialog') dialog_element.text = '"I am glad thou hast returned. All our hopes are riding on thee."' dialog_element = ET.SubElement(xml_root, 'Dialog') dialog_element.text = '"Before reaching thy next level of experience thou must gain [NEXT_LEVEL_XP] ' \ 'experience points. See me again when thy level has increased."' dialog_element = ET.SubElement(xml_root, 'Dialog') dialog_element.text = '"Goodbye now, [NAME]. Take care and tempt not the Fates."' xml_string = xml.dom.minidom.parseString( ET.tostring(xml_root)).toprettyxml(indent=" ") save_game_file_path = os.path.join( self.saves_path, self.hero_party.main_character.name + '.xml') # Archive off the old save, if one is present self.archive_saved_game_file(save_game_file_path) # Save the game try: if not os.path.isdir(self.saves_path): os.makedirs(self.saves_path) save_game_file = open(save_game_file_path, 'w') save_game_file.write(xml_string) save_game_file.close() print('Saved game to file', save_game_file_path, flush=True) except Exception as exc: print( 'ERROR: Exception encountered while attempting to save game file:', exc, flush=True) def archive_saved_game_file(self, save_game_file_path: str, archive_dir_name: str = 'archive') -> None: if os.path.isfile(save_game_file_path): # Archive old save game files archive_dir = os.path.join(self.saves_path, archive_dir_name) from datetime import datetime timestamp = datetime.fromtimestamp( os.path.getmtime(save_game_file_path)).strftime("%Y%m%d%H%M%S") rename_file_path = os.path.join( archive_dir, self.hero_party.main_character.name + '_' + timestamp + '.xml') try: if not os.path.isdir(archive_dir): os.makedirs(archive_dir) if not os.path.isfile(rename_file_path): os.rename(save_game_file_path, rename_file_path) else: print('ERROR: File already exists:', rename_file_path, flush=True) except Exception as exc: print( 'ERROR: Exception encountered while attempting to archived saved game file:', exc, flush=True) def get_tile_info(self, tile: Optional[Point] = None) -> Tile: return self.game_map.get_tile_info(tile) # Find point transitions for either the specified point or the current position of the player character. # If auto is true, only look for automatic point transitions def get_point_transition( self, tile: Optional[Point] = None, filter_to_automatic_transitions: bool = False ) -> Optional[OutgoingTransition]: if tile is None: tile = self.hero_party.get_curr_pos_dat_tile() for point_transition in self.game_info.maps[ self.get_map_name()].point_transitions: if point_transition.point == tile and self.check_progress_markers( point_transition.progress_marker, point_transition.inverse_progress_marker): if filter_to_automatic_transitions: if point_transition.is_automatic is None and not self.is_light_restricted( ): # By default, make transitions manual in dark places return point_transition elif point_transition.is_automatic: return point_transition else: return point_transition return None def get_encounter_background( self, tile: Optional[Point] = None) -> Optional[EncounterBackground]: return self.game_map.get_encounter_background(tile) def get_decorations(self, tile: Optional[Point] = None) -> List[MapDecoration]: return self.game_map.get_decorations(tile) def get_npc_to_talk_to(self) -> Optional[NpcState]: return self.game_map.get_npc_to_talk_to() def get_npc_by_name(self, name: str) -> Optional[MapCharacterState]: return self.game_map.get_npc_by_name(name) def get_special_monster(self, tile: Optional[Point] = None ) -> Optional[SpecialMonster]: if tile is None: tile = self.hero_party.get_curr_pos_dat_tile() for special_monster in self.game_info.maps[ self.get_map_name()].special_monsters: if special_monster.point == tile and self.check_progress_markers( special_monster.progress_marker, special_monster.inverse_progress_marker): # print('Found monster at point: ', tile, flush=True) return special_monster return None # Return True if progress_markers satisfied, else False def check_progress_markers(self, progress_marker: Optional[str], inverse_progress_marker: Optional[str]) -> bool: if progress_marker is None: progress_marker_eval = True else: progress_marker_eval = self.evaluate_progress_marker_string( progress_marker) if inverse_progress_marker is None: inverse_progress_marker_eval = False else: inverse_progress_marker_eval = self.evaluate_progress_marker_string( inverse_progress_marker) return progress_marker_eval and not inverse_progress_marker_eval def evaluate_progress_marker_string(self, progress_marker_string: str) -> bool: progress_marker_term_string = progress_marker_string logical_tokens = ['(', ')', ' and ', ' or ', ' not ', '&', '|', '!'] for strip_term in logical_tokens: progress_marker_term_string = progress_marker_term_string.replace( strip_term, ' ') stripped_logical_tokens = [x.strip() for x in logical_tokens] for term in filter(None, progress_marker_term_string.split(' ')): if term in stripped_logical_tokens: continue progress_marker_string = progress_marker_string.replace( term, str(term in self.hero_party.progress_markers)) if eval(progress_marker_string): return True return False def can_move_to_tile(self, tile: Point, enforce_npc_hp_penalty_limit: bool = False, enforce_npc_dof_limit: bool = False, is_npc: bool = False, prev_tile: Optional[Point] = None) -> bool: return self.game_map.can_move_to_tile(tile, enforce_npc_hp_penalty_limit, enforce_npc_dof_limit, is_npc, prev_tile) def get_tile_monsters(self, tile: Optional[Point] = None) -> List[str]: if tile is None: tile = self.hero_party.get_curr_pos_dat_tile() for mz in self.game_info.maps[self.get_map_name()].monster_zones: if mz.x <= tile.x <= mz.x + mz.w and mz.y <= tile.y <= mz.y + mz.h: # print('in monsterZone of set ' + mz.setName + ':', self.gameInfo.monsterSets[mz.setName], flush=True) return self.game_info.monster_sets[mz.name] return self.game_map.get_tile_monsters(tile) def is_light_restricted(self) -> bool: return (self.hero_party.light_diameter is not None and self.hero_party.light_diameter <= self.win_size_tiles.w and self.hero_party.light_diameter <= self.win_size_tiles.h) def is_outside(self) -> bool: return self.game_info.maps[self.get_map_name()].is_outside def is_inside(self) -> bool: return not self.is_outside() def make_map_transition(self, transition: Optional[OutgoingTransition]) -> bool: if transition is None: return False src_map = self.game_info.maps[self.get_map_name()] dest_map = self.game_info.maps[transition.dest_map] # Find the destination transition corresponding to this transition if transition.dest_name is None: try: dest_transition = dest_map.transitions_by_map[ self.get_map_name()] except KeyError: print('Failed to find destination transition by dest_map', flush=True) return False else: try: dest_transition = dest_map.transitions_by_map_and_name[ self.get_map_name()][transition.dest_name] except KeyError: try: dest_transition = dest_map.transitions_by_name[ transition.dest_name] except KeyError: print('Failed to find destination transition by dest_name', flush=True) return False # If transitioning from outside to inside, save off last outside position if src_map.is_outside and not dest_map.is_outside: self.hero_party.set_last_outside_pos( self.get_map_name(), self.hero_party.get_curr_pos_dat_tile(), self.hero_party.get_direction()) # Make the transition and draw the map AudioPlayer().play_sound('walk_away') self.hero_party.set_pos(dest_transition.point, dest_transition.dir) self.set_map(transition.dest_map, respawn_decorations=transition.respawn_decorations) self.draw_map(True) # Slight pause on a map transition pygame.time.wait(250) return True def is_facing_locked_item(self) -> bool: return self.game_map.is_facing_locked_item() def is_facing_openable_item(self) -> bool: return self.game_map.is_facing_openable_item() def open_locked_item(self) -> Optional[MapDecoration]: removed_decoration = self.game_map.open_locked_item() if removed_decoration: if self.get_map_name() not in self.removed_decorations_by_map: self.removed_decorations_by_map[self.get_map_name()] = [] self.removed_decorations_by_map[self.get_map_name()].append( removed_decoration) return removed_decoration def remove_decoration(self, decoration: MapDecoration) -> None: removed_decoration = self.game_map.remove_decoration(decoration) if removed_decoration: if self.get_map_name() not in self.removed_decorations_by_map: self.removed_decorations_by_map[self.get_map_name()] = [] self.removed_decorations_by_map[self.get_map_name()].append( removed_decoration) def draw_map(self, flip_buffer: bool = True, draw_background: bool = True, draw_combat: bool = True, draw_status: bool = True, draw_only_character_sprites: bool = False) -> None: if draw_only_character_sprites: self.game_map.draw_character_sprites() return # Draw the map to the screen if draw_background: self.game_map.draw() # If in combat, refresh the background image and render the monsters. if draw_combat and self.combat_encounter is not None: self.combat_encounter.background_image = self.screen.copy() self.combat_encounter.render_monsters() elif draw_status: GameDialog.create_persistent_status_dialog(self.hero_party).blit( self.screen, False) # Flip the screen buffer if flip_buffer: pygame.display.flip() def advance_tick(self, update_map: bool = True, draw_map: bool = True, advance_time: bool = True, flip_buffer: bool = True) -> None: if update_map: self.game_map.update() if draw_map: self.draw_map(flip_buffer=False) if advance_time: self.clock.tick(30) # self.tick_count += 1 # if 10 == self.tick_count % 100: # print(f'FPS = {self.clock.get_fps()}', flush=True) if flip_buffer: pygame.display.flip() def get_game_info(self) -> GameInfo: return self.game_info def get_image_pad_tiles(self) -> Point: return self.image_pad_tiles def get_hero_party(self) -> HeroParty: return self.hero_party def get_dialog_replacement_variables(self) -> DialogReplacementVariables: variables = DialogReplacementVariables() variables.generic['[NAME]'] = self.hero_party.main_character.get_name() variables.generic['[NEXT_LEVEL_XP]'] = str( self.hero_party.main_character.calc_xp_to_next_level()) map_origin = self.game_info.maps[self.get_map_name()].origin if map_origin is not None: map_coord = self.hero_party.get_curr_pos_dat_tile() - map_origin variables.generic['[X]'] = str(abs(map_coord.x)) variables.generic['[Y]'] = str(abs(map_coord.y)) if map_coord.x < 0: variables.generic['[X_DIR]'] = 'East' else: variables.generic['[X_DIR]'] = 'West' if map_coord.y < 0: variables.generic['[Y_DIR]'] = 'South' else: variables.generic['[Y_DIR]'] = 'North' return variables def is_in_combat(self) -> bool: return self.combat_encounter is not None def is_combat_allowed(self) -> bool: return len(self.get_tile_monsters()) > 0 def get_map_name(self) -> str: return self.game_map.map.name def get_win_size_pixels(self) -> Point: return self.win_size_pixels def initiate_encounter( self, monster_info: Optional[MonsterInfo] = None, approach_dialog: Optional[DialogType] = None, victory_dialog: Optional[DialogType] = None, run_away_dialog: Optional[DialogType] = None, encounter_music: Optional[str] = None, message_dialog: Optional[GameDialog] = None) -> None: # TODO: Make the conditions for no monsters configurable if self.hero_party.has_item('Ball of Light'): return # Determine the monster party for the encounter if monster_info is None: # Check for special monsters special_monster_info = self.get_special_monster() if special_monster_info is not None: monster_party = MonsterParty( [MonsterState(special_monster_info)]) approach_dialog = special_monster_info.approach_dialog victory_dialog = special_monster_info.victory_dialog run_away_dialog = special_monster_info.run_away_dialog else: monster_info = self.game_info.monsters[random.choice( self.get_tile_monsters())] monster_party = MonsterParty([MonsterState(monster_info)]) else: monster_party = MonsterParty([MonsterState(monster_info)]) if self.hero_party.is_monster_party_repelled(monster_party, self.is_outside()): return # A combat encounter requires an encounter background encounter_background = self.game_info.maps[ self.get_map_name()].encounter_background if encounter_background is None: encounter_background = self.get_encounter_background() if encounter_background is None: print( 'Failed to initiate combat encounter due to lack of encounter image in map ' + self.get_map_name(), flush=True) return # Perform the combat encounter CombatEncounter.static_init('combat') self.combat_encounter = CombatEncounter( game_info=self.game_info, game_state=self, monster_party=monster_party, encounter_background=encounter_background, message_dialog=message_dialog, approach_dialog=approach_dialog, victory_dialog=victory_dialog, run_away_dialog=run_away_dialog, encounter_music=encounter_music) self.combat_encounter.encounter_loop() self.combat_encounter = None # Play the music for the current map AudioPlayer().play_music( self.game_info.maps[self.get_map_name()].music) # Clear event queue GameEvents.clear_events() def handle_death(self, message_dialog: Optional[GameDialog] = None) -> None: if not self.hero_party.has_surviving_members(): # Player death self.hero_party.main_character.hp = 0 AudioPlayer().stop_music() AudioPlayer().play_sound('player_died') GameDialog.create_encounter_status_dialog(self.hero_party).blit( self.screen, False) gde = GameDialogEvaluator(self.game_info, self) if message_dialog is None: message_dialog = GameDialog.create_message_dialog() else: message_dialog.add_message('') gde.add_and_wait_for_message('Thou art dead.', message_dialog) gde.wait_for_acknowledgement(message_dialog) for hero in self.hero_party.members: hero.curr_pos_dat_tile = hero.dest_pos_dat_tile = self.game_info.death_hero_pos_dat_tile hero.curr_pos_offset_img_px = Point(0, 0) hero.direction = self.game_info.death_hero_pos_dir hero.hp = hero.level.hp hero.mp = hero.level.mp gde.update_default_dialog_font_color() self.pending_dialog = self.game_info.death_dialog self.hero_party.gp = self.hero_party.gp // 2 self.set_map(self.game_info.death_map, respawn_decorations=True) def handle_quit(self, force: bool = False) -> None: AudioPlayer().play_sound('select') if force: self.is_running = False # Save off initial background image background_surface = self.screen.copy() menu_dialog = GameDialog.create_yes_no_menu( Point(1, 1), 'Do you really want to quit?') menu_dialog.blit(self.screen, flip_buffer=True) menu_result = GameDialogEvaluator( self.game_info, self).get_menu_result(menu_dialog, allow_quit=False) if menu_result is not None and menu_result == 'YES': self.is_running = False # Restore initial background image menu_dialog.erase(self.screen, background_surface, flip_buffer=True) def should_add_math_problems_in_combat(self) -> bool: return self.__should_add_math_problems_in_combat def toggle_should_add_math_problems_in_combat(self) -> None: self.__should_add_math_problems_in_combat = not self.__should_add_math_problems_in_combat