Exemple #1
0
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')
Exemple #4
0
 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)
Exemple #6
0
	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
Exemple #7
0
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)
Exemple #8
0
    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()
Exemple #9
0
	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
Exemple #10
0
    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)
Exemple #12
0
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()
Exemple #14
0
    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)
Exemple #16
0
    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
Exemple #17
0
    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
Exemple #18
0
def removeDead(gm: GameMap):
    for pos in gm.data:
        if gm.data[pos] != None and gm.data[pos].health <= 0:
            gm.data[pos] = None
Exemple #19
0
    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"
Exemple #20
0
    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()
Exemple #21
0
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
Exemple #22
0
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
Exemple #23
0
	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
Exemple #25
0
    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)
Exemple #26
0
def initializeGameMap(map_file):
    return GameMap(map_file)
Exemple #27
0
        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)])
Exemple #28
0
    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
Exemple #29
0
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)
Exemple #30
0
	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
Exemple #31
0
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
Exemple #32
0
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)
Exemple #33
0
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
Exemple #34
0
 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])
Exemple #36
0
 def __init__(self):
     self.game = Game()
     self.gameMap = GameMap()
Exemple #37
0
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)
Exemple #39
0
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