def _simulate(self, action, player_status, enemy_status): ''' Takes away num_armies from source, and add num_armies to the destination ''' source, destination, num_armies = action sim_player_status = copy.deepcopy(player_status) sim_source = get_territory_by_id(source['territory'], sim_player_status['territories']) sim_source['num_armies'] -= num_armies sim_dest = get_territory_by_id(destination['territory'], sim_player_status['territories']) sim_dest['num_armies'] += num_armies return (sim_player_status, enemy_status)
def _our_threat(t_id, map_layout, player_status, enemy_status): bst = 0 enemy_territory_ids = [t['territory'] for t in enemy_status['territories']] player_territory_ids = [t['territory'] for t in player_status['territories']] for adjacent_id in get_territory_by_id(t_id, map_layout['territories'])['adjacent_territories']: if adjacent_id in player_territory_ids: bst += get_territory_by_id(adjacent_id, player_status['territories'])['num_armies'] bsr = float(bst) / get_territory_by_id(t_id, enemy_status['territories'])['num_armies'] return bsr
def _our_threat(t_id, map_layout, player_status, enemy_status): bst = 0 enemy_territory_ids = [t['territory'] for t in enemy_status['territories']] player_territory_ids = [ t['territory'] for t in player_status['territories'] ] for adjacent_id in get_territory_by_id( t_id, map_layout['territories'])['adjacent_territories']: if adjacent_id in player_territory_ids: bst += get_territory_by_id( adjacent_id, player_status['territories'])['num_armies'] bsr = float(bst) / get_territory_by_id( t_id, enemy_status['territories'])['num_armies'] return bsr
def _distance(t_id, map_layout, player_status, enemy_status): q = deque() path = (t_id, ) q.append(path) visited = set([t_id]) while q: path = q.popleft() last_node = path[-1] if get_territory_by_id(last_node, enemy_status['territories']): return len(path) - 1 for node in get_territory_by_id(last_node, map_layout['territories'])['adjacent_territories']: if node not in visited: visited.add(node) q.append(path + (node, )) return 99999
def _distance(t_id, map_layout, player_status, enemy_status): q = deque() path = (t_id, ) q.append(path) visited = set([t_id]) while q: path = q.popleft() last_node = path[-1] if get_territory_by_id(last_node, enemy_status['territories']): return len(path) - 1 for node in get_territory_by_id( last_node, map_layout['territories'])['adjacent_territories']: if node not in visited: visited.add(node) q.append(path + (node, )) return 99999
def _simulate(self, action, player_status, enemy_status): # 0.0004 sim_player_status = copy.deepcopy(player_status) # 0.00035 sim_player_status["num_armies"] += 1 sim_player_status["num_reserves"] -= 1 t = get_territory_by_id(action["territory"], sim_player_status["territories"]) # 9e-6 t["num_armies"] += 1 return (sim_player_status, enemy_status)
def reinforce(self, num_reserves): """ Returns {<territoryId>: <num troops deployed>} """ if ( self.tank_territory_id == None or utils.get_territory_by_id(self.tank_territory_id, self.player_status["territories"]) == None ): self.tank_territory_id = self.player_status["territories"][0]["territory"] return {self.tank_territory_id: num_reserves}
def fortify(self, legal_territories_to_fortify): """ Returns (from_territory, to_territory, num_armies_to_move), or a None value if ending turn """ if self.target_id: conqueredTerritory = utils.get_territory_by_id(self.target_id, self.player_status["territories"]) if conqueredTerritory: tmp_id = self.tank_territory_id self.tank_territory_id = self.target_id source = utils.get_territory_by_id(tmp_id, self.player_status["territories"]) num_armies = source["num_armies"] if num_armies > 1: return (tmp_id, self.target_id, num_armies - 1) return None
def fortify(self, legal_territories_to_fortify): ''' Returns (from_territory, to_territory, num_armies_to_move), or a None value if ending turn ''' if self.target_id: conqueredTerritory = utils.get_territory_by_id(self.target_id, self.player_status['territories']) if conqueredTerritory: tmp_id = self.tank_territory_id self.tank_territory_id = self.target_id source = utils.get_territory_by_id(tmp_id, self.player_status['territories']) num_armies = source['num_armies'] if num_armies > 1: return (tmp_id, self.target_id, num_armies - 1) return None
def _simulate(self, action, player_status, enemy_status): # 0.0004 # outcomes = {prob: game_state} outcomes = {} # if win src, dest = action win_prob = Battle_Computer.compute(src['num_armies'], dest['num_armies']) win_player_status = copy.deepcopy(player_status) win_enemy_status = copy.deepcopy(enemy_status) win_src = get_territory_by_id(action[0]['territory'], win_player_status['territories']) win_dest = get_territory_by_id(action[1]['territory'], win_enemy_status['territories']) win_src['num_armies'] = max(win_src['num_armies'] - win_dest['num_armies'], 1) # Expected winner loss win_dest['num_armies'] = 3 # Expected number of troops moved win_player_status['territories'].append(win_dest) win_enemy_status['territories'].remove(win_dest) win_state = { 'player_status': win_player_status, 'enemy_status': win_enemy_status } lose_prob = 1 - win_prob lose_player_status = copy.deepcopy(player_status) lose_player_status['num_armies'] -= (src['num_armies'] - 1) lose_enemy_status = copy.deepcopy(enemy_status) lose_src = get_territory_by_id(action[0]['territory'], lose_player_status['territories']) lose_src['num_armies'] = 1 # Number of troops remaining on battle loss lose_dest = get_territory_by_id(action[1]['territory'], lose_enemy_status['territories']) lose_dest['num_armies'] = lose_dest['num_armies'] / 2 + 1 # Expected enemy troop loss lose_state = { 'player_status': lose_player_status, 'enemy_status': lose_enemy_status } outcomes[win_prob] = win_state outcomes[lose_prob] = lose_state return outcomes
def do_battle(self): ''' Returns True when done, false otherwise ''' legal_battles = self._create_set_of_legal_battles() battle = self.battle(legal_battles) if battle: tattack, tdefend, num_armies = battle legal_battles_to_ids = map( lambda (a, d): (a['territory'], d['territory']), legal_battles) if ((tattack, tdefend) not in legal_battles_to_ids): self._err(AttackError.ILLEGAL_ATTACK(tattack, tdefend)) else: t = utils.get_territory_by_id( tattack, self.player_status['territories']) # There must be enough troops to attack if num_armies > t['num_armies'] - 1: self._err( AttackError.NOT_ENOUGH_ARMY(tattack, tdefend, num_armies)) # There can't be more than 3 troops attacking elif num_armies > 3: self._err( AttackError.TOO_MUCH_ARMY(tattack, tdefend, num_armies)) else: # Everything is valid self.attack(tattack, tdefend, num_armies) time.sleep(config.DELAY_BETWEEN_ACTIONS) self._refresh_state() if utils.get_territory_by_id( tdefend, self.player_status['territories']): print "Conquered" attack_move = (utils.get_territory_by_id(tattack, self.player_status['territories']), \ utils.get_territory_by_id(tdefend, self.player_status['territories']), \ utils.get_territory_by_id(tattack, self.player_status['territories'])['num_armies'] - 1) sim_score = self.fe.evaluate_action( attack_move, self.map_layout, self.player_status, self.enemy_status) score = features.evaluate_fortify( self.map_layout, self.player_status, self.enemy_status) if sim_score > score: print "ATTACK MOVE!" self.transfer_armies( tattack, tdefend, utils.get_territory_by_id( tattack, self.player_status['territories']) ['num_armies'] - 1) return False else: return True
def do_fortify(self): legal_forts = self._create_set_of_legal_fortifications() fortification = self.fortify(legal_forts) if fortification: tfrom, tto, num_armies = fortification legal_forts_to_ids = map(lambda (f,t): (f['territory'], t['territory']), legal_forts) # Fortification must occur between adjacent territories if (tfrom, tto) not in legal_forts_to_ids: self._err(FortifyError.ILLEGAL_FORTIFY(tfrom, tto)) else: t = utils.get_territory_by_id(tfrom, self.player_status['territories']) # There must be enough troops to move if num_armies > t['num_armies'] - 1: self._err(FortifyError.NOT_ENOUGH_ARMY(tfrom, tto, num_armies)) else: # Everything is valid self.transfer_armies(tfrom, tto, num_armies) else: self.end_turn()
def do_reinforce(self): num_reserves = self.player_status['num_reserves'] reinforcements = self.reinforce(num_reserves) # TODO handle error when placing in enemy territory invalid_ids = filter(lambda t_id: utils.get_territory_by_id(t_id,self.player_status['territories']) == None, reinforcements.keys()) if invalid_ids: self._err(ReinforceError.TERRITORY_NOT_OWNED(invalid_ids)) num_deployed = sum(reinforcements.values()) # All troops must be deployed if (num_deployed < num_reserves): self._err(ReinforceError.LEFTOVER_ARMY) # Cannot deploy too many troops elif (num_deployed > num_reserves): self._err(ReinforceError.TOO_MUCH_ARMY) # Execute reinforcement for t_id, num_troops in reinforcements.iteritems(): self.place_armies(t_id, num_troops)
def do_reinforce(self): num_reserves = self.player_status['num_reserves'] reinforcements = self.reinforce(num_reserves) # TODO handle error when placing in enemy territory invalid_ids = filter( lambda t_id: utils.get_territory_by_id( t_id, self.player_status['territories']) == None, reinforcements.keys()) if invalid_ids: self._err(ReinforceError.TERRITORY_NOT_OWNED(invalid_ids)) num_deployed = sum(reinforcements.values()) # All troops must be deployed if (num_deployed < num_reserves): self._err(ReinforceError.LEFTOVER_ARMY) # Cannot deploy too many troops elif (num_deployed > num_reserves): self._err(ReinforceError.TOO_MUCH_ARMY) # Execute reinforcement for t_id, num_troops in reinforcements.iteritems(): self.place_armies(t_id, num_troops)
def do_fortify(self): legal_forts = self._create_set_of_legal_fortifications() fortification = self.fortify(legal_forts) if fortification: tfrom, tto, num_armies = fortification legal_forts_to_ids = map( lambda (f, t): (f['territory'], t['territory']), legal_forts) # Fortification must occur between adjacent territories if (tfrom, tto) not in legal_forts_to_ids: self._err(FortifyError.ILLEGAL_FORTIFY(tfrom, tto)) else: t = utils.get_territory_by_id( tfrom, self.player_status['territories']) # There must be enough troops to move if num_armies > t['num_armies'] - 1: self._err( FortifyError.NOT_ENOUGH_ARMY(tfrom, tto, num_armies)) else: # Everything is valid self.transfer_armies(tfrom, tto, num_armies) else: self.end_turn()
def do_battle(self): ''' Returns True when done, false otherwise ''' legal_battles = self._create_set_of_legal_battles() battle = self.battle(legal_battles) if battle: tattack, tdefend, num_armies = battle legal_battles_to_ids = map(lambda (a,d): (a['territory'], d['territory']), legal_battles) if ((tattack, tdefend) not in legal_battles_to_ids): self._err(AttackError.ILLEGAL_ATTACK(tattack, tdefend)) else: t = utils.get_territory_by_id(tattack, self.player_status['territories']) # There must be enough troops to attack if num_armies > t['num_armies'] - 1: self._err(AttackError.NOT_ENOUGH_ARMY(tattack, tdefend, num_armies)) # There can't be more than 3 troops attacking elif num_armies > 3: self._err(AttackError.TOO_MUCH_ARMY(tattack, tdefend, num_armies)) else: # Everything is valid self.attack(tattack, tdefend, num_armies) time.sleep(config.DELAY_BETWEEN_ACTIONS) self._refresh_state() if utils.get_territory_by_id(tdefend, self.player_status['territories']): print "Conquered" attack_move = (utils.get_territory_by_id(tattack, self.player_status['territories']), \ utils.get_territory_by_id(tdefend, self.player_status['territories']), \ utils.get_territory_by_id(tattack, self.player_status['territories'])['num_armies'] - 1) sim_score = self.fe.evaluate_action(attack_move, self.map_layout, self.player_status, self.enemy_status) score = features.evaluate_fortify(self.map_layout, self.player_status, self.enemy_status) if sim_score > score: print "ATTACK MOVE!" self.transfer_armies(tattack, tdefend, utils.get_territory_by_id(tattack, self.player_status['territories'])['num_armies'] - 1) return False else: return True
def reinforce(self, num_reserves): ''' Returns {<territoryId>: <num troops deployed>} ''' if self.tank_territory_id == None or utils.get_territory_by_id(self.tank_territory_id, self.player_status['territories']) == None: self.tank_territory_id = self.player_status['territories'][0]['territory'] return { self.tank_territory_id: num_reserves }