def __roll_forward(self): # 盤面情報 stage_manager = StageDBAccessManager() board, agents = stage_manager.get_stage_data(self.battle_id) self.game = Game(board, agents) # 行動履歴取得 action_manager = ActionDBAccessManager() action_history = action_manager.get_data(battle_id=self.battle_id) action_history = sorted(action_history, key=lambda x: x["turn"]) # 盤面復元 battle_info = BattleDBAccessManager().get_data(self.battle_id)[0] for action in action_history: if action["turn"] <= battle_info["turn"]: self.__do_action(json.loads(action["detail"])["actions"]) # ターン情報復元 ## 試合が開始してからの秒数を計算 start_at_unix_time = battle_info["start_at_unix_time"] now_unix_time = int(time.mktime(datetime.datetime.now().timetuple())) passed_time_millis = (now_unix_time - start_at_unix_time) * 1000 ## 1ターンに要する時間で割る = 現在時刻でのターン数 period_time_millis = battle_info["turn_mills"] + battle_info["interval_mills"] self.turn = math.ceil(passed_time_millis / period_time_millis) self.turn = max(0, min(battle_info["turn"] + 1, self.turn)) self.max_turn = battle_info["turn"] ## 少し待機(復元ターンと現在時刻のずれを修正する) wait_millis = self.turn * period_time_millis - now_unix_time * 1000 time.sleep(max(0, wait_millis / 1000.0))
def score_test_3(): width = 8 height = 5 points = [ [1, 0, 2, 1, 1, 2, 0, 1], [0, 1, 0, 1, 1, 0, 1, 0], [1, 3, -1, 2, 2, -1, 3, 1], [0, 1, 0, 1, 1, 0, 1, 0], [1, 0, 2, 1, 1, 2, 0, 1] ] tiled = [ [0, 1, 1, 1, 1, 1, 1, 0], [0, 1, 2, 2, 2, 2, 1, 0], [0, 1, 2, 0, 0, 2, 1 ,0], [0, 1, 2, 2, 2, 2, 1, 0], [0, 1, 1, 1, 1, 1, 1, 0] ] board = Board(width, height, points, tiled) game = Game(board, []) true_score = { 1: { "tilePoint": 22, "areaPoint": 10 }, 2: { "tilePoint": 2, "areaPoint": 4 } } assert(game.cal_score([1, 2]) == true_score)
def score_test_6(): width = 7 height = 7 points = [ [0, 1, 2, 0, 2, 1, 0], [2, -2, 0, 1, 0, -2, 2], [2, 1, 0, -2, 0, 1, 2], [1, 2, 2, 3, 2, 2, 1], [1, 2, 2, 3, 2, 2, 1], [2, 1, 0, -2, 0, 1, 2], [2, -2, 0, 1, 0, -2, 2] ] tiled = [ [1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1] ] board = Board(width, height, points, tiled) game = Game(board, []) true_score = { 1: { "tilePoint": 32, "areaPoint": 22 } } assert(game.cal_score([1]) == true_score)
def score_test_5(): width = 5 height = 5 points = [ [-2, 0, 1, 0, -2], [1, 0, -2, 0, 1], [2, 2, 3, 2, 2], [2, 2, 3, 2, 2], [1, 0, -2, 0, 1] ] tiled = [ [1, 1, 1, 1, 1], [1, 0, 1, 0, 1], [1, 1, 1, 1, 1], [1, 0, 1, 0, 1], [1, 1, 1, 1, 1] ] board = Board(width, height, points, tiled) game = Game(board, []) true_score = { 1: { "tilePoint": 15, "areaPoint": 4 } } assert (game.cal_score([1]) == true_score), "Test Failed"
class BattleManager(Thread): def __init__(self, battle_id): super().__init__() self.game = None self.turn = 1 self.max_turn = 9999999 self.battle_id = battle_id self.now_interval = False self.action_writing = False self.battle_info = BattleDBAccessManager().get_data(battle_id=self.battle_id)[0] self.finish_battle = threading.Event() self.__roll_forward() BattleDBAccessManager().update_battle_status(self.battle_id, 1) def run(self): # 0. 準備 battle_db_manager = BattleDBAccessManager() battle_data = battle_db_manager.get_data(battle_id=self.battle_id)[0] turn_limit = battle_data["turn"] turn_mills = battle_data["turn_mills"] interval_mills = battle_data["interval_mills"] msleep = lambda t: time.sleep(t / 1000.0) del(battle_db_manager) # 1. 試合開始待機 self.__wait_for_start_battle() # 2. 試合プロセス self.turn = max(1, self.turn) for self.turn in range(self.turn, turn_limit + 1): # 送信待機 msleep(turn_mills) while self.action_writing: pass before_time = int(time.time() * 1000) # 行動準備 self.now_interval = True action_db_manager = ActionDBAccessManager() action = action_db_manager.get_data(self.battle_id, self.turn) # 行動 -> エージェントステータス更新 if len(action) != 0: action = json.loads(action[0]["detail"])["actions"] safety_agents, affected_agents = self.__do_action(action) for agent in action: if agent["agent_id"] in safety_agents: agent["apply"] = 1 elif agent["agent_id"] in affected_agents: agent["apply"] = 0 action_db_manager.update(self.battle_id, self.turn, json.dumps({"actions": action})) # 次ターンまで待機 after_time = int(time.time() * 1000) while before_time + interval_mills > after_time: after_time = int(time.time() * 1000) self.now_interval = False # 終了コマンドを受け取ったら if self.finish_battle.is_set(): break # 3. 終了コマンド待機 self.turn = self.max_turn + 1 while not self.finish_battle.is_set(): time.sleep(10) BattleDBAccessManager().update_battle_status(self.battle_id, 0) def get_board(self): return self.game.board def get_agents(self): return self.game.agents def get_score(self): return self.game.cal_score( [self.battle_info["teamA"], self.battle_info["teamB"]] ) def finish(self): self.finish_battle.set() def __wait_for_start_battle(self): now_datetime = datetime.datetime.now() unix_time = int(time.mktime(now_datetime.timetuple())) battle_db_manager = BattleDBAccessManager() start_at_unix_time = battle_db_manager.get_data(battle_id=self.battle_id)[0]["start_at_unix_time"] del(battle_db_manager) while unix_time < start_at_unix_time: now_datetime = datetime.datetime.now() unix_time = int(time.mktime(now_datetime.timetuple())) def __roll_forward(self): # 盤面情報 stage_manager = StageDBAccessManager() board, agents = stage_manager.get_stage_data(self.battle_id) self.game = Game(board, agents) # 行動履歴取得 action_manager = ActionDBAccessManager() action_history = action_manager.get_data(battle_id=self.battle_id) action_history = sorted(action_history, key=lambda x: x["turn"]) # 盤面復元 battle_info = BattleDBAccessManager().get_data(self.battle_id)[0] for action in action_history: if action["turn"] <= battle_info["turn"]: self.__do_action(json.loads(action["detail"])["actions"]) # ターン情報復元 ## 試合が開始してからの秒数を計算 start_at_unix_time = battle_info["start_at_unix_time"] now_unix_time = int(time.mktime(datetime.datetime.now().timetuple())) passed_time_millis = (now_unix_time - start_at_unix_time) * 1000 ## 1ターンに要する時間で割る = 現在時刻でのターン数 period_time_millis = battle_info["turn_mills"] + battle_info["interval_mills"] self.turn = math.ceil(passed_time_millis / period_time_millis) self.turn = max(0, min(battle_info["turn"] + 1, self.turn)) self.max_turn = battle_info["turn"] ## 少し待機(復元ターンと現在時刻のずれを修正する) wait_millis = self.turn * period_time_millis - now_unix_time * 1000 time.sleep(max(0, wait_millis / 1000.0)) def __do_action(self, action_detail): for agent in action_detail: team_id = agent["team_id"] agent_id = agent["agent_id"] remove_panel = agent["type"] == "remove" dx = agent["dx"] dy = agent["dy"] self.game.set_action(team_id, agent_id, dx, dy, remove_panel) return self.game.step()
def flow_test_2(): width = 7 height = 3 points = [ [1, 4, -2, 5, -2, 4, 1], [8, 9, 1, 0, 1, 9, 8], [0, 4, 6, 3, 6, 4, 0], ] tiled = [ [0, 0, 1, 0, 2, 0, 0], [0, 0, 1, 0, 2, 0, 0], [0, 0, 1, 0, 2, 0, 0] ] agents = [ Agent(1, 1, 2, 0), Agent(1, 2, 2, 1), Agent(1, 3, 2, 2), Agent(2, 4, 4, 0), Agent(2, 5, 4, 1), Agent(2, 6, 4, 2), ] board = Board(width, height, points, tiled) simulator = Game(board, agents) # 1 simulator.set_action(1, 1, 1, 0) simulator.set_action(1, 2, 1, 0) simulator.set_action(1, 3, -1, 0) simulator.set_action(2, 4, 1, 0) simulator.set_action(2, 5, -1, 0) simulator.set_action(2, 6, -1, 0) simulator.step() true_score = { 1: { "tilePoint": 14, "areaPoint": 0 }, 2: { "tilePoint": 12, "areaPoint": 0 } } assert(simulator.cal_score([1, 2]) == true_score) assert(simulator.turn == 1)
def flow_test_1(): width = 5 height = 5 points = [ [2, 1, 0, 1, 2], [4, 5, 3, 5, 4], [1, 1, 2, 1, 1], [4, 5, 3, 5, 4], [2, 1, 0, 1, 2] ] tiled = [ [0, 1, 0, 2, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 2, 0, 1, 0] ] agents = [ Agent(1, 1, 1, 0), Agent(1, 2, 3, 4), Agent(2, 3, 3, 0), Agent(2, 4, 1, 4) ] board = Board(width, height, points, tiled) simulator = Game(board, agents) simulator.set_action(1, 1, 0, 1) simulator.set_action(1, 2, -1, 0) simulator.set_action(2, 3, 1, 0) simulator.set_action(2, 4, 0, -1) simulator.step() true_score = { 1: { "tilePoint": 7, "areaPoint": 0 }, 2: { "tilePoint": 9, "areaPoint": 0 } } assert(simulator.cal_score([1, 2]) == true_score) assert(simulator.turn == 1)