def update_diplo_events(self, ai_stat: AI_GameStatus): for e_b in ai_stat.map.opp_building_list: if e_b.visible: if essentials.is_obj_in_list(e_b, list(self.claimed_tiles)): self.diplomacy.add_event(e_b.owner, e_b.offset_coordinates, DiploEventType.ENEMY_BUILDING_IN_CLAIMED_ZONE, -2, 3) for e_a in ai_stat.map.opp_army_list: if essentials.is_obj_in_list(e_a, list(self.claimed_tiles)): self.diplomacy.add_event(e_a.owner, e_a.offset_coordinates, DiploEventType.ENEMY_ARMY_INVADING_CLAIMED_ZONE, -2, 3)
def create_heat_maps(self, ai_stat: AI_GameStatus, move: AI_Move): # cond = lambda n: AI_Toolkit.is_obj_in_list(n, ai_stat.map.walkable_tiles) heat_map = essentials.simple_heat_map(ai_stat.map.building_list, ai_stat.map.walkable_tiles, lambda n: essentials.is_obj_in_list(n, ai_stat.map.walkable_tiles)) self.claimed_tiles.clear() c_dist = 2 if 'claiming_distance' not in self.properties else self.properties['claiming_distance'] for d, s in heat_map: if d < c_dist: self.claimed_tiles.add(s) heat_map_2 = essentials.simple_heat_map(ai_stat.map.scoutable_tiles, ai_stat.map.discovered_tiles, lambda n: True) self.center_tile = ai_stat.map.building_list[0].base_tile if self.center_tile is None: """code to find the center tile""" max = -1 tile_max = None for d, s in heat_map_2: val = d if d > max: max = d tile_max = s if BASIC_DEBUG: self._dump("Center is located @ " + str(tile_max.offset_coordinates)) self.center_tile = tile_max ## get heatmap for danger zone -> heat_map_3 = essentials.simple_heat_map(ai_stat.map.opp_building_list, ai_stat.map.discovered_tiles, lambda n: True) for d, s in heat_map_3: if d <= 2: self.danger_zone.add(s)
def calculate_heatmaps(self, ai_stat: AI_GameStatus): heat_map = essentials.simple_heat_map( ai_stat.map.building_list, ai_stat.map.walkable_tiles, lambda n: essentials.is_obj_in_list(n, ai_stat.map.walkable_tiles)) for d, s in heat_map: if d <= self.properties['range_claimed_tiles']: self.claimed_tiles.append(s)
def __best_building_site_farm(self, ai_stat: AI_GameStatus) -> BuildOption: """building sites get scored by how many buildable fields there are next to it""" best_score = -1 best_site = (-1, -1) best_cd: Optional[List[CardinalDirection]] = None best_tl = None fields = [] p = Priority.P_NO is_next_to_res = False # just for printing if ai_stat.me.resources >= ai_stat.cost_building_construction[BuildingType.FARM]: for ai_t in ai_stat.map.buildable_tiles: tmp = False # just for printing possible_fields = [] score = 0 for n in essentials.get_neighbours_on_set(ai_t, ai_stat.map.buildable_tiles): if basic.num_resources_on_adjacent(n) == 0: possible_fields.append(n) if essentials.is_obj_in_list(n, ai_stat.map.scoutable_tiles): score += 1 score += len(possible_fields) amount_of_fields = min(3, len(possible_fields)) sampled = random.sample(possible_fields, amount_of_fields) score += len(essentials.get_neighbours_on_set(ai_t, ai_stat.map.scoutable_tiles)) / 2 # if build site is next to a resource --> reduce value by 1 for each resource field score = score - basic.num_resources_on_adjacent(ai_t) # make the score dependent on safety level of region #score = score - self.compass.get_threat_level(ai_t).value * 2 if ai_t in self.danger_zone: score += - 10 if best_score < score: best_score = score is_next_to_res = tmp best_site = ai_t.offset_coordinates best_cd = self.compass.get_cardinal_direction_obj(ai_t, self.compass.center_tile) best_tl = self.compass.get_threat_level(ai_t) fields.clear() for s in sampled: fields.append(s.offset_coordinates) if is_next_to_res: debug("The farm will be next to a resource (apparently there is no better spot)") # translate score to priority (normalization step) if len(fields) >= 3: p = Priority.P_HIGH elif len(fields) >= 2: p = Priority.P_MEDIUM elif len(fields) >= 1: p = Priority.P_LOW # hint(f" type eval: {type(p)}") return BuildOption(BuildingType.FARM, best_site, fields, p, cardinal_direction=best_cd, threat_level=best_tl)
def evaluate_move_scouting(self, ai_stat: AI_GameStatus) -> List[ScoutingOption]: """scores the scouting options, currently by the distance to a own building (want to make sure that all claimable tiles are scouted) and by the proximity to a resource fieled""" options: List[ScoutingOption] = [] if ai_stat.me.resources < ai_stat.costScout: return options for s in ai_stat.map.scoutable_tiles: options.append(ScoutingOption(s.offset_coordinates, Priority.P_NO)) for so in options: value = 0 tmp_tile = ai_stat.map.get_tile(so.site) dist1 = essentials.get_neighbours(tmp_tile) # 1. increase value by resources nearby num_of_tiles_with_res = 0 for t_at_dist_1 in dist1: if t_at_dist_1.has_resource(): num_of_tiles_with_res = num_of_tiles_with_res + 1 value = value + (num_of_tiles_with_res * self.w_scouting_resource) # 2. increase value by proximity to claimed tiles num_of_claimed_tiles = 0 for t_at_dist_1 in dist1: if essentials.is_obj_in_list(t_at_dist_1, list(self.claimed_tiles)): num_of_claimed_tiles = num_of_claimed_tiles + 1 value = value + (num_of_claimed_tiles * self.w_scouting_claimed) # 3. try to smooth out border # value = value + (len(dist1) * self.w_scouting_smooth_border) # Normalize high = max(2 * self.w_scouting_resource, 4 * self.w_scouting_claimed, 4 * self.w_scouting_smooth_border) # hint(f"scouting value: {value} (res nearby: {num_of_tiles_with_res},") # f" claimed_tiles near_by: {num_of_claimed_tiles} ) ") if value < 0.3 * high: so.score = Priority.P_LOW elif value < 0.6 * high: so.score = Priority.P_MEDIUM elif value < high: so.score = Priority.P_HIGH else: so.score = Priority.P_CRITICAL # hint("Tile at {} has scouting prio: {}".format(so.site, so.score)) options.sort(key=lambda x: x.score.value, reverse=True) return options
def aw1(elem: AI_Mazedonian.AttackTarget, ai_stat: AI_GameStatus) -> bool: if type(elem.target) == AI_Army: if essentials.is_obj_in_list(elem.target, self.claimed_tiles): return True return False
def __handle_state_selection(self, mouse_x: int, mouse_y: int): """Lets the player select an icon and translates this to the move object. If necessary, the state is set to await additional input (e.g. for army movement)""" action = None active_icon = None candidates = [] for icon in self.active_selection: if self.__check_icon_boudning_box(mouse_x, mouse_y, icon): if icon.is_active: action = icon.action active_icon = icon else: if len(icon.info_text) > 0: Logger.log_notification(icon.info_text) else: Logger.log_notification("Invalid option") if action: if action == Action.ARMY_MOVEMENT: if not (self.movement_specified is MoveState.USED): self.move.doMoveArmy = True self.active_hexagon = active_icon.hex candidates = [ x for x in self.gl.hex_map.get_neighbours( self.active_hexagon) if essentials.is_obj_in_list( x, self.game_status.map.walkable_tiles) ] self.set_state(HI_State.SPECIFY_MOVEMENT) else: Logger.log_notification("you already moved the army.") self.set_state(HI_State.GRIDMODE) else: if not (self.action_specified is MoveState.USED): if action == Action.BUILD_FARM: self.move.type = BuildingType.FARM self.move.move_type = MoveType.DO_BUILD self.move.loc = active_icon.hex.offset_coordinates self.active_hexagon = active_icon.hex candidates = [ x for x in self.gl.hex_map.get_neighbours( self.active_hexagon) if essentials.is_obj_in_list( x, self.game_status.map.buildable_tiles) ] self.set_state(HI_State.SPECIFY_FIELDS) elif action == Action.BUILD_HUT: self.move.type = BuildingType.HUT self.move.move_type = MoveType.DO_BUILD self.move.loc = active_icon.hex.offset_coordinates self.action_specified = MoveState.READY self.set_state(HI_State.GRIDMODE) elif action == Action.BUILD_RACKS: self.move.type = BuildingType.BARRACKS self.move.move_type = MoveType.DO_BUILD self.move.loc = active_icon.hex.offset_coordinates self.action_specified = MoveState.READY self.set_state(HI_State.GRIDMODE) elif action == Action.RECRUIT_KNIGHT: self.move.type = UnitType.KNIGHT self.move.move_type = MoveType.DO_RECRUIT_UNIT self.action_specified = MoveState.READY self.set_state(HI_State.GRIDMODE) elif action == Action.RECRUIT_MERC: self.move.type = UnitType.MERCENARY self.move.move_type = MoveType.DO_RECRUIT_UNIT self.action_specified = MoveState.READY self.set_state(HI_State.GRIDMODE) elif action == Action.SCOUT: self.move.move_type = MoveType.DO_SCOUT self.move.loc = active_icon.hex.offset_coordinates self.action_specified = MoveState.READY self.set_state(HI_State.GRIDMODE) elif action == Action.RAISE_ARMY: self.move.move_type = MoveType.DO_RAISE_ARMY self.move.loc = active_icon.hex.offset_coordinates self.action_specified = MoveState.READY self.set_state(HI_State.GRIDMODE) else: Logger.log_notification( "you already used up the action, wait until next turn") self.set_state(HI_State.GRIDMODE) ###### for c in candidates: pix_c = HexMap.offset_to_pixel_coords(c.offset_coordinates) si = SelectionIcon(pix_c[0] + self.camera_pos[0], pix_c[1] + self.camera_pos[1], self.textures['hi_specify'], Action.NONE, c, scale=0.9) self.zlvl_icons.append(si) self.candidates.append(si) else: self.set_state(HI_State.GRIDMODE) for icon in self.active_selection: self.zlvl_icons.remove(icon) self.active_selection.clear()
def __handle_state_gridmode(self, mouse_x: int, mouse_y: int): """If in gridmode and the player clicks on a tile, this function decides what options are available""" h = self.gl.hex_map.get_hex_by_pixel((mouse_x, mouse_y), self.camera_pos) obj, obj_class = self.gl.get_map_element(h.offset_coordinates) # tiles is scoutable if essentials.is_obj_in_list(h, self.game_status.map.scoutable_tiles): has_res_for_scouting = self.game_status.me.resources >= 1 pos_list = self.get_icon_coordinates((mouse_x, mouse_y), 1) self.active_selection.append( SelectionIcon(pos_list[0][0], pos_list[0][1], self.textures['hi_scout'], Action.SCOUT, h, is_active=has_res_for_scouting)) # tile is buildable elif obj is None and h is not None: if essentials.is_obj_in_list(h, self.game_status.map.buildable_tiles): has_res_for_hut = Building.building_info[BuildingType.HUT][ 'construction_cost'] <= self.game_status.me.resources has_res_for_farm = Building.building_info[BuildingType.FARM][ 'construction_cost'] <= self.game_status.me.resources has_res_for_racks = Building.building_info[ BuildingType.BARRACKS][ 'construction_cost'] <= self.game_status.me.resources can_raise_army = len(self.game_status.map.army_list) == 0 pos_list = self.get_icon_coordinates((mouse_x, mouse_y), 4) idx = 0 self.active_selection.append( SelectionIcon(pos_list[idx][0], pos_list[idx][1], self.textures['hi_build_farm'], Action.BUILD_FARM, h, is_active=has_res_for_farm)) idx += 1 self.active_selection.append( SelectionIcon(pos_list[idx][0], pos_list[idx][1], self.textures['hi_build_hut'], Action.BUILD_HUT, h, is_active=has_res_for_hut)) idx += 1 self.active_selection.append( SelectionIcon(pos_list[idx][0], pos_list[idx][1], self.textures['hi_build_racks'], Action.BUILD_RACKS, h, is_active=has_res_for_racks)) idx += 1 self.active_selection.append( SelectionIcon(pos_list[idx][0], pos_list[idx][1], self.textures['hi_raise_army'], Action.RAISE_ARMY, h, is_active=can_raise_army)) else: # at this point it is not scoutable nor buildable return elif obj_class is Army: if essentials.is_obj_in_list(obj.tile, self.game_status.map.army_list): merc_cost = Unit.get_unit_cost(UnitType.MERCENARY) knight_cost = Unit.get_unit_cost(UnitType.KNIGHT) has_res_for_merc = self.game_status.me.resources >= merc_cost.resources and \ self.game_status.me.culture >= merc_cost.culture and \ self.game_status.me.population + merc_cost.population <= self.game_status.me.population_limit has_res_for_knight = self.game_status.me.resources >= knight_cost.resources and \ self.game_status.me.culture >= knight_cost.culture and \ self.game_status.me.population + knight_cost.population <= self.game_status.me.population_limit army_pop = self.game_status.map.army_list[ 0].population and self.movement_specified is not MoveState.USED pos_list = self.get_icon_coordinates((mouse_x, mouse_y), 3) idx = 0 self.active_selection.append( SelectionIcon(pos_list[idx][0], pos_list[idx][1], self.textures['hi_recruit_merc'], Action.RECRUIT_MERC, h, is_active=has_res_for_merc)) idx += 1 self.active_selection.append( SelectionIcon(pos_list[idx][0], pos_list[idx][1], self.textures['hi_recruit_knight'], Action.RECRUIT_KNIGHT, h, is_active=has_res_for_knight)) idx += 1 self.active_selection.append( SelectionIcon(pos_list[idx][0], pos_list[idx][1], self.textures['hi_move_army'], Action.ARMY_MOVEMENT, h, is_active=(army_pop > 0))) for ai in self.active_selection: self.zlvl_icons.append(ai) self.set_state(HI_State.SELECTION)