def evaluate_army_movement(self, ai_stat: AI_GameStatus, move: AI_Move): if len(ai_stat.map.army_list) == 0: return target_str = "" self.previous_attack_target = None if self.state == AI_Mazedonian.AI_State.PASSIVE: # for now, just move it out of the way. army_is_on_field = False if ai_stat.map.army_list[0].base_tile in ai_stat.map.own_farm_field_tiles: army_is_on_field = True if not army_is_on_field: has_farm = False for b in ai_stat.map.building_list: if b.type == BuildingType.FARM: has_farm = True if has_farm: # walk to random field path = [] idx = random.randint(0, len(ai_stat.map.own_farm_field_tiles) - 1) # print(f"from: {ai_stat.map.army_list[0].base_tile.offset_coordinates} to {ai_stat.map.own_farm_field_tiles[idx].offset_coordinates}") path = essentials.a_star(ai_stat.map.army_list[0].base_tile, ai_stat.map.own_farm_field_tiles[idx], ai_stat.map.walkable_tiles) if len(path) > 1: move.move_army_to = path[1].offset_coordinates move.doMoveArmy = True target_str = "corn field" #elif self.state == AI_Mazedonian.AI_State.DEFENSIVE or self.state == AI_Mazedonian.AI_State.AGGRESSIVE: else: if len(self.priolist_targets) > 0: if self.threshold_target_value <= self.priolist_targets[0].weighted_score: # hint("on warpath: {} {}".format(self.threshold_target_value, self.priolist_targets[0].score)) # attack start_tile = ai_stat.map.army_list[0].base_tile target_tile = self.priolist_targets[0].target.base_tile path = essentials.a_star(start_tile, target_tile, ai_stat.map.walkable_tiles) if len(path) > 1: self.previous_attack_target = self.priolist_targets[0] move.move_army_to = path[1].offset_coordinates move.doMoveArmy = True target = self.priolist_targets[0] s = "army" if type(target.target) is AI_Army else "building" target_str = f"Movement: target: {s} @ loc: {target.target.offset_coordinates}" if BASIC_DEBUG: self._dump('moving to: {} from {} to {}'.format(str(move.move_army_to), start_tile.offset_coordinates, target_tile.offset_coordinates)) else: self._dump("targets value to low. Will not attack") if move.doMoveArmy: self._dump(target_str)
def play_players_turn(self, player: Player): """wrapper function, extends the main update loop""" # debug(f"Play move of player {player.name} [pid: {player.id}]") self.updata_map() if self.check_win_condition(player): self.winner = player self.update_player_properties(player) player.has_lost = self.check_lose_condition(player) if player.has_lost: self.destroy_player(player) return if player.player_type == PlayerType.HUMAN: ai_game_status = AI_GameStatus() self.construct_game_status(player, ai_game_status) ai_move = AI_Move() self.human_interface.request_move(ai_game_status, ai_move, player.id) else: ai_worker = threading.Thread(target=self.spawn_ai_thread, args=(player, )) ai_worker.start()
def weight_options(self, options: List[Option], ai_stat: AI_GameStatus, move: AI_Move): used_weights: List[str] = [] for opt in options: # --------------------- Action options ---------- opt.weighted_score = opt.score.value if opt.score == Priority.P_NO: # no option (should not depend on weights) -> contain invalid info continue for w in self.weights: if w.condition(opt, ai_stat): used_weights.append(w.condition.__name__) if DETAILED_DEBUG: self._dump(f"Weight w: {w.weight} applied on score: {opt.weighted_score} of {type(opt)} ") opt.weighted_score = opt.weighted_score + w.weight used_weights.append(" | ") for m in self.priolist_targets: # --------------------- Movement options ---------- if m.score == Priority.P_NO: continue for w in self.m_weights: if w.condition(m, ai_stat): used_weights.append(w.condition.__name__) m.weighted_score = m.weighted_score + w.weight options.sort(key=lambda x: x.weighted_score, reverse=True) self.priolist_targets.sort(key=lambda x: x.weighted_score, reverse=True) self._dump("---") for opt in options: s = f"\tOption of type: {type(opt)}, score: {opt.weighted_score}" if type(opt) == RecruitmentOption or type(opt) == BuildOption: s = s + f", type {opt.type}" if type(opt) == ScoutingOption: s = s + f", site: {opt.site}" s = s + f", former priority: {opt.score}" self._dump(s) for m in self.priolist_targets: s = f"\tAttack Target : {'army' if type(m.target) is AI_Army else 'building'}, score: {m.weighted_score}" self._dump(s) s_tmp = "" for w in used_weights: s_tmp += w + ", " self._dump(s_tmp) # translate this into move best_option: Option = options[0] if type(best_option) == WaitOption: move.move_type = MoveType.DO_NOTHING move.str_rep_of_action = "waiting" elif type(best_option) == BuildOption: move.move_type = MoveType.DO_BUILD move.loc = best_option.site move.type = best_option.type for at in best_option.associated_tiles: move.info.append(at) s_tmp = f"building a {best_option.type} at {str(move.loc)} ({str(best_option.cardinal_direction)})" if move.type == BuildingType.FARM: s_tmp += f" TL: {str(best_option.threat_level)}" move.str_rep_of_action = s_tmp elif type(best_option) == RecruitmentOption: move.move_type = MoveType.DO_RECRUIT_UNIT move.type = best_option.type move.str_rep_of_action = f"recruiting a {best_option.type}" elif type(best_option) == ScoutingOption: move.move_type = MoveType.DO_SCOUT move.loc = best_option.site move.str_rep_of_action = "scouting at" + str(move.loc) elif type(best_option) == AI_Mazedonian.RaiseArmyOption: move.move_type = MoveType.DO_RAISE_ARMY move.loc = self.get_army_spawn_loc(ai_stat) move.str_rep_of_action = "raising new army at" elif type(best_option) is UpgradeOption: move.move_type = MoveType.DO_UPGRADE_BUILDING move.loc = best_option.site move.type = best_option.type move.str_rep_of_action = "upgrading hut to villa" else: error("unexpected type") self._dump(f"DECISION: {move.str_rep_of_action}")
def evaluate_trades(self, ai_stat: AI_GameStatus, move: AI_Move): for trade in ai_stat.trades: for decision in self.trade_decisions: decision(trade, ai_stat) move.trades = ai_stat.trades
def spawn_ai_thread(self, player): ai_game_status = AI_GameStatus() ai_move = AI_Move() self.construct_game_status(player, ai_game_status) self.ai_interface.do_a_move(ai_game_status, ai_move, player.id)
def weight_options(self, ai_stat: AI_GameStatus, move: AI_Move, all_options: List[Union[BuildOption, RecruitmentOption, RaiseArmyOption, WaitOption]], movement_options: List[ArmyMovementOption]): used_weights: List[str] = [] for opt in all_options: # --------------------- Action options ---------- if opt.score == Priority.P_NO: continue opt.weighted_score = opt.score.value for w in self.weights: if w.condition(opt, ai_stat): used_weights.append(w.condition.__name__) opt.weighted_score = opt.weighted_score + w.weight used_weights.append(" | ") for opt in movement_options: # --------------------- Movement options ---------- if opt.score == Priority.P_NO: continue opt.weighted_score = opt.score.value for w in self.m_weights: if w.condition(opt, ai_stat): used_weights.append(w.condition.__name__) opt.weighted_score = opt.weighted_score + w.weight all_options.sort(key=lambda x: x.weighted_score, reverse=True) movement_options.sort(key=lambda x: x.weighted_score, reverse=True) if len(all_options) > 0: best_option = all_options[0] if type(best_option) == WaitOption: move.move_type = MoveType.DO_NOTHING move.str_rep_of_action = "waiting" elif type(best_option) == BuildOption: move.move_type = MoveType.DO_BUILD move.loc = best_option.site move.type = best_option.type move.str_rep_of_action = f"building a {best_option.type} at " + str( move.loc) elif type(best_option) == UpgradeOption: move.move_type = MoveType.DO_UPGRADE_BUILDING move.loc = best_option.site move.type = best_option.type move.str_rep_of_action = f"upgrading building to {move.type}" elif type(best_option) == RecruitmentOption: move.move_type = MoveType.DO_RECRUIT_UNIT move.type = best_option.type move.str_rep_of_action = f"recruiting a {best_option.type}" elif type(best_option) == RaiseArmyOption: move.move_type = MoveType.DO_RAISE_ARMY move.loc = best_option.site move.str_rep_of_action = "raising new army at" else: error("unexpected type") if len(movement_options) > 0: best_m_option = movement_options[0] if best_m_option.weighted_score >= self.properties[ 'threshold_army_movement']: move.move_army_to = best_m_option.next_step move.doMoveArmy = True for opt in all_options: s = f"Option of type {type(opt)}, score: {opt.weighted_score} ({opt.score})" if not (type(opt) == WaitOption or type(opt) == RaiseArmyOption): s = s + f" -> Type: {opt.type}" self._dump(s) for m_opt in movement_options: stmp = 'army' if type(m_opt.target) is AI_Army else '' stmp = 'building' if type(m_opt.target) is AI_Building else '' s = f"M-Option target: {type(m_opt)} target({stmp}), score: {m_opt.weighted_score} ({m_opt.score})" self._dump(s) s = f"DECISION: {move.str_rep_of_action}" if move.doMoveArmy: s += f" moving army to {move.move_army_to}" self._dump(s)