Пример #1
0
    def handle_trade(trade: Trade, player: Player, player_list: List[Player]) -> bool:
        if trade.owner == player.id:
            hint(f"cannot accept own trades -> trade will be deleted [{trade.owner}, [{player.id}]]")
            return False
        else:
            other_player = player_list[trade.owner]
            if trade.type is TradeType.OFFER:
                if not TradeHub.balance(trade.demand[0], player, -trade.demand[1]):
                    return False    # player could not balance
                # owner will receive demand, at lose the offer
                TradeHub.balance(trade.demand[0], other_player, +trade.demand[1])
                # current player will receive the offer and play the demand
                TradeHub.balance(trade.demand[0], player, -trade.demand[1])
                TradeHub.balance(trade.offer[0], player, +trade.offer[1])

            else:
                amount = 0
                trade_cat = None
                if trade.type is TradeType.GIFT:
                    amount = trade.offer[1]
                    trade_cat = trade.offer[0]
                elif trade.type is TradeType.CLAIM:
                    amount = - trade.demand[1]
                    trade_cat = trade.demand[0]

                TradeHub.balance(trade_cat, player, amount)
        return True
Пример #2
0
 def __init__(self, map_dim: (int, int), style: MapStyle):
     hint("HexMap size: {}".format(map_dim))
     if style != MapStyle.S_V_C:
         print("HexMap: Only supported style so far: S_V_C")
     self.map_dim = map_dim
     self.map: [Hexagon] = []  # linear storage of all hexagons in the map
     for y in range(map_dim[1]):
         for x in range(map_dim[0]):
             self.map.append(Hexagon((x, y)))
Пример #3
0
 def _dump(self, d: str):
     """Depending on the game settings, this will either dump the output to:
     - [if SHOW_AI_CTRL]the external AI ctrl window
     - [if DEBUG_MODE]the console (should not be the first choice, very slow)
     - [else]nowhere."""
     if Definitions.SHOW_AI_CTRL:
         self.__dump += d + "\n"
     elif Definitions.DEBUG_MODE:
         hint(d)
     else:
         pass
Пример #4
0
 def update(self, time):
     tpl = Animator.bilinear_interpolation(
         self.source, self.destination, self.start_time_ms,
         self.start_time_ms + self.time_ms, time)
     if len(tpl) != 2:
         error(
             "Animator: serious error, we left the 2d space! len(tpl): "
             + str(len(tpl)))
         hint(str(self.source))
         hint(str(self.destination))
     # if not (type(tpl) == Tuple):
     #     error("Error in Animator -> bilinear interpolation output: " + str(type(tpl)))
     if self.valid:
         self.drawable.set_sprite_pos(tpl, self.camera_pos)
Пример #5
0
 def evaluate_move_recruitment(self, ai_stat: AI_GameStatus) -> List[Union[RecruitmentOption, RaiseArmyOption]]:
     options = []
     if ai_stat.me.population >= ai_stat.me.population_limit:
         return options
     if len(ai_stat.map.army_list) == 0:
         options.append(AI_Mazedonian.RaiseArmyOption(Priority.P_HIGH))
         return options  # cannot recruit if no army available
     # calculate offset to desired population by build order
     prio_merc = Priority.P_LOW
     prio_knight = Priority.P_LOW
     offset = self.build_order.population - ai_stat.me.population
     if offset > 0:
         prio_merc = Priority.increase(prio_merc)
         prio_knight = Priority.increase(prio_knight)
     else:
         prio_merc = Priority.decrease(prio_merc)
         prio_knight = Priority.decrease(prio_knight)
     # compare to desired army composition:
     army = ai_stat.map.army_list[0]
     if army.population > 0:
         percentage_merc_wanted = self.army_comp.ac[0] / (self.army_comp.ac[0] + self.army_comp.ac[0])
         percentage_merc_actual = army.mercenaries / (army.mercenaries + army.knights)
         percentage_knig_wanted = self.army_comp.ac[1] / (self.army_comp.ac[0] + self.army_comp.ac[0])
         percentage_knig_actual = army.knights / (army.mercenaries + army.knights)
         if DETAILED_DEBUG:
             debug(f"merc: {percentage_merc_wanted} - {percentage_merc_actual} | knight: {percentage_knig_wanted} - {percentage_knig_actual}")
         if (percentage_knig_wanted - percentage_knig_actual) < (percentage_merc_wanted - percentage_merc_actual):
             prio_merc = Priority.increase(prio_merc)
         else:
             prio_knight = Priority.increase(prio_knight)
     else:   # in case the population is 0, we cannot compute the above. Just increase the priority
         prio_knight = Priority.increase(prio_knight)
         prio_merc = Priority.increase(prio_merc)
     # mercenary
     cost_unit_me = ai_stat.cost_unit_recruitment[UnitType.MERCENARY]
     if ai_stat.me.population + cost_unit_me.population <= ai_stat.me.population_limit:
         if ai_stat.me.resources >= cost_unit_me.resources:
             if ai_stat.me.culture >= cost_unit_me.culture:
                 options.append(RecruitmentOption(UnitType.MERCENARY, prio_merc))
             else:
                 if DETAILED_DEBUG:
                     hint("not enough culture to recruit a mercenary. actual: {} required: {}".format(
                         ai_stat.me.culture, cost_unit_me.culture))
         else:
             if DETAILED_DEBUG:
                 hint("not enough resources to recruit a mercenary. actual: {} required: {}".format(
                     ai_stat.me.resources, cost_unit_me.resources))
     else:
         if DETAILED_DEBUG:
             hint("not enough free population to recruit a mercenary")
     # knight
     cost_unit_kn = ai_stat.cost_unit_recruitment[UnitType.KNIGHT]
     if ai_stat.me.population + cost_unit_kn.population <= ai_stat.me.population_limit:
         if ai_stat.me.resources >= cost_unit_kn.resources:
             if ai_stat.me.culture >= cost_unit_kn.culture:
                 options.append(RecruitmentOption(UnitType.KNIGHT, prio_knight))
             else:
                 if DETAILED_DEBUG:
                     hint("not enough culture to recruit a knight. actual: {} required: {}".format(
                         ai_stat.me.culture, cost_unit_kn.culture))
         else:
             if DETAILED_DEBUG:
                 hint("not enough resources to recruit a knight. actual: {} required: {}".format(
                     ai_stat.me.resources, cost_unit_kn.resources))
     else:
         if DETAILED_DEBUG:
             hint("not enough free population to recruit a knight")
     return options
Пример #6
0
def setup_weights(self) -> List[Tuple[Callable, float]]:
    w: List[Tuple[Callable, float]] = []

    def w1(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: If AI looses food -> Make building a farm more important!"""
        if type(elem) is BuildOption:
            if elem.type == BuildingType.FARM:
                return self.is_loosing_food
        return False

    w.append((w1, 3))

    def w1_1(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: addition to w1: if we are gaining food, make building a farm less important"""
        if type(elem) is BuildOption:
            if elem.type == BuildingType.FARM:
                return not self.is_loosing_food
        return False

    w.append((w1_1, -1.5))

    def w2(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: If AI looses food, recruitment is halted"""
        if self.is_loosing_food:
            if type(elem) is RecruitmentOption or type(elem) is ScoutingOption:
                return True
        return False

    w.append((w2, -5))

    def w3(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: If AI has no army -> Recruiting an army is important"""
        if type(elem) is RaiseArmyOption:
            if len(ai_stat.map.army_list) == 0:
                return True
        return False

    w.append((w3, 3))

    def w4(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea, once we have enough resources (and is in passive/def state),
         make scouting slightly more important"""
        if type(elem) is ScoutingOption:
            if ai_stat.me.resources > 10:
                if self.state == AI_Mazedonian.AI_State.PASSIVE or self.state == AI_Mazedonian.AI_State.DEFENSIVE:
                    return True
        return False

    w.append((w4, 1))

    def w5(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: reduce significance of scouting in a low eco game"""
        if type(elem) is ScoutingOption:
            if ai_stat.me.resources < 10:
                return True
        return False

    w.append((w5, -1))

    def w6(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: If AI has more than 70 food, cut down on additional farms"""
        if type(elem) is BuildOption:
            if elem.type == BuildingType.FARM:
                if ai_stat.me.food > 70:
                    return True
        return False

    w.append((w6, -1))

    def w7(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: slightly decrease scouting and waiting if a lot of resources are available"""
        if type(elem) is ScoutingOption or type(elem) is WaitOption:
            if ai_stat.me.resources > 40:
                return True
        return False

    w.append((w7, -1.5))

    def w8(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: slightly decrease scouting in early game"""
        if type(elem) is ScoutingOption:
            if self.protocol == AI_Mazedonian.Protocol.EARLY_GAME:
                return True
        return False

    w.append((w8, -1))

    def w9(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: slightly increase building in early game"""
        if type(elem) is BuildOption:
            if self.protocol == AI_Mazedonian.Protocol.EARLY_GAME:
                return True
        return False

    w.append((w9, 1))

    def w10(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: if AI lacks population by twice the desired value -> double down"""
        if type(elem) is RecruitmentOption:
            if self.build_order.population / 2 > ai_stat.me.population:
                return True
        return False

    w.append((w10, 0.9))

    def w11(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: if AI doesn't have a farm -> highest prio (if it cannot build one -> wait)"""
        if type(elem) is BuildOption:
            if elem.type == BuildingType.FARM:
                for b in ai_stat.map.building_list:
                    if b.type == BuildingType.FARM:
                        return False
                return True  # returns true if AI does not have a farm and building one is an option
        return False

    w.append((w11, 10))

    def w12(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: extension to w11 (if it cannot build one -> wait)"""
        if type(elem) is WaitOption:
            for b in ai_stat.map.building_list:
                if b.type == BuildingType.FARM:
                    return False
            return True  # returns true if AI does not have a farm
        return False

    w.append((w12, 5))

    def w13(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: if pop >= pop_limit, make building barracks slightly more popular"""
        if ai_stat.me.population_limit <= ai_stat.me.population:
            if type(elem) is BuildOption:
                if elem.type == BuildingType.BARRACKS:
                    if not has_building_under_construction(
                            BuildingType.BARRACKS, ai_stat):
                        return True
            if type(elem) is WaitOption:
                if not has_building_under_construction(BuildingType.BARRACKS,
                                                       ai_stat):
                    return True
            return False

    w.append((w13, 1.7))

    def w14(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """during Crusade, build troops"""
        if type(elem) is RecruitmentOption:
            if self.state is AI_Mazedonian.AI_State.CRUSADE:
                return True
        return False

    w.append((w14, 5))

    def w15(elem: AI_Mazedonian.Option, ai_stat: AI_GameStatus) -> bool:
        """Idea: Upgrade villa if possible""" ""
        if type(elem) is UpgradeOption:
            if self.protocol is AI_Mazedonian.Protocol.LATE_GAME:
                return True
        return False

    w.append((w15, 3))

    hint(f"AI has found {len(w)} weight functions.")
    return w
Пример #7
0
def setup_movement_weights(
        self: AI_Mazedonian) -> List[Tuple[Callable, float]]:
    aw: List[Tuple[Callable, float]] = []

    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

    aw.append((aw1, 2))

    def aw2(elem: AI_Mazedonian.AttackTarget, ai_stat: AI_GameStatus) -> bool:
        if type(elem.target) == AI_Army:
            if self.previous_amount_of_buildings > len(
                    ai_stat.map.building_list):
                return True
        return False

    aw.append((aw2, 1))

    def aw3(elem: AI_Mazedonian.AttackTarget, ai_stat: AI_GameStatus) -> bool:
        """Idea: reduce aggressifness in opponant is stronger"""
        if type(elem.target) == AI_Army:
            if elem.target.owner in self.hostile_player:
                if self.opponent_strength[
                        elem.target.owner] == AI_Mazedonian.Strength.STRONGER:
                    return True
        return False

    aw.append((aw3, -1))

    def aw4(elem: AI_Mazedonian.AttackTarget, ai_stat: AI_GameStatus) -> bool:
        """Idea: Reduce will to attack in early game, but defend"""
        if type(elem.target) == AI_Army:
            if self.protocol == AI_Mazedonian.Protocol.EARLY_GAME:
                if len(self.hostile_player) == 0:
                    return True
        return False

    aw.append((aw4, -2))

    def aw5(elem: AI_Mazedonian.AttackTarget, ai_stat: AI_GameStatus) -> bool:
        """Idea: Move in for the kill if the opp is weaker"""
        if type(elem.target) == AI_Building:
            if elem.target.owner in self.hostile_player:
                if self.opponent_strength[
                        elem.target.owner] == AI_Mazedonian.Strength.WEAKER:
                    return True
        return False

    aw.append((aw5, 2))

    def aw6(elem: AI_Mazedonian.AttackTarget, ai_stat: AI_GameStatus) -> bool:
        """Idea: Defend if attacked by opponent"""
        if type(elem.target) == AI_Army:
            if elem.target.owner in self.hostile_player:
                for opp in ai_stat.opponents:
                    if opp.id == elem.target.owner:
                        if opp.has_attacked:
                            return True
        return False

    aw.append((aw6, 1))

    def aw7(elem: AI_Mazedonian.AttackTarget, ai_stat: AI_GameStatus) -> bool:
        """Idea: during crusade, attack target player"""
        if self.state is AI_Mazedonian.AI_State.CRUSADE:
            if elem.target.owner == self.crusade_target_id:
                return True
        return False

    aw.append((aw7, 5))

    def aw8(elem: AI_Mazedonian.AttackTarget, ai_stat: AI_GameStatus) -> bool:
        """Keep the previous attack target for static targets"""
        if self.previous_attack_target is not None:
            if elem.target.offset_coordinates == self.previous_attack_target.target.offset_coordinates:
                return True
        return False

    aw.append((aw8, 2))

    hint(f"AI has found {len(aw)} movement weight functions.")
    return aw