Exemple #1
0
 def __init__(self):
     possible_areas = [area for area in Map().areas if not len(area.players)]
     if START_AREA in possible_areas:
         area = Map().get_area(START_AREA)
     else:
         area = choice(possible_areas)
     Event.__init__(self, 'drop', [area])
Exemple #2
0
 def pillage(self, stuff):
     if len([p for p in Context().alive_players if p.is_alive]) == 1:
         return
     if Map().players_count(self) > 1:
         return
     looted = []
     for item in stuff:
         if item not in Map().loot(self.current_area):
             continue
         if isinstance(item, Weapon):
             if item.damage_mult > self.weapon.damage_mult:
                 looted.append(item)
                 Map().remove_loot(item, self.current_area)
         else:
             looted.append(item)
             Map().remove_loot(item, self.current_area)
     if not len(looted):
         return
     Narrator().add(
         [self.name, 'loots',
          format_list([e.long_name for e in looted])])
     for item in looted:
         if isinstance(item, Weapon):
             self.get_weapon(item)
         else:
             self.get_item(item)
Exemple #3
0
    def loot_bag(self):
        items: List[Item] = []
        for _ in self.acting_players:
            b = Map().pick_bag(self)
            if b is None:
                b = Map().pick_item(self)
            if b is not None:
                items.append(b)

        items.sort(key=lambda x: (isinstance(x, Bag)) * 10 + random())
        self.acting_players.sort(
            key=lambda x: (x.bag is not None) * 10 + random())

        empty_handed: List[Player] = []
        for player in self.acting_players:
            if len(items):
                item = items.pop(0)
                Narrator().add([
                    player.name, 'picks up', item.long_name,
                    self.current_area.at
                ])
                player.get_item(item)
            else:
                empty_handed.append(player)

        if len(empty_handed):
            verb = 'try' if len(empty_handed) > 1 else 'tries'
            Narrator().add([
                player_names(empty_handed), verb, 'to find loot',
                self.current_area.at, 'but can\'t find anything good'
            ])
Exemple #4
0
 def go_to(self, area: Union[str, Area, Entity]) -> Optional[Area]:
     area = Map().get_area(area)
     if area != self.current_area:
         self.end_ambush()
         for p in self.acting_players:
             p.go_to(area)
         return Map().move_player(self, area)
     return None
Exemple #5
0
 def go_to(self, area: Union[str, Area, Entity]) -> Optional[Area]:
     area = Map().get_area(area)
     if area != self.current_area:
         self.reveal()
         self._energy -= self.move_cost
         self.busy = True
         return Map().move_player(self, area)
     return None
Exemple #6
0
 def loot_start(self):
     w = self.estimate(Map().weapons(self))
     b = self.weapon.damage_mult * Map().has_bags(self) * (self.bag is None)
     if w > b and w > 0:
         self.loot_weapon()
     elif b > 0:
         self.loot_bag(take_a_break=False)
     else:
         self.hide(panic=True)
Exemple #7
0
 def hide(self, panic=False, stock=False):
     if panic:
         Narrator().add([self.name, 'hides', self.current_area.at], stock=stock)
         return
     if self.sleep < 0.1 \
             or (Context().time == NIGHT and Map().players_count == 1 and len(self.wounds) == 0) \
             or (Map().players_count == 1 and self.sleep < 0.2 and len(self.wounds) == 0) \
             or (Context().time == NIGHT and self.sleep < 0.3 and len(self.wounds) == 0):
         self.go_to_sleep(stock=stock)
         return
     return self.rest(stock=stock)
Exemple #8
0
 def check_for_ambush_and_traps(self):
     traps = Map().traps(self)
     for t in traps:
         if t.check(self):
             t.apply(self)
             return True
     ambushers = Map().ambushers(self)
     if not len(ambushers):
         return False
     ambusher = choice(ambushers)
     ambusher.trigger_ambush(self)
     return True
Exemple #9
0
 def available_areas(cls) -> List[Area]:
     areas = copy(Map().areas)
     if cls.water == -1:
         areas = [a for a in areas if not a.has_water]
     if cls.water == 1:
         areas = [a for a in areas if a.has_water]
     return areas
Exemple #10
0
 def loot_weapon(self, weapon: Optional[Weapon] = None, retry=True):
     if weapon is None:
         weapon = Map().pick_weapon(self.current_area)
     if weapon is None or (weapon.damage_mult <= self.weapon.damage_mult and
                           (not weapon.small or Context().time == STARTER
                            or self.bag is None)):
         if retry:
             return self.loot(take_a_break=False)
         else:
             Narrator().add([
                 self.name, 'tries to find a weapon', self.current_area.at,
                 'but can\'t find anything good'
             ])
         return
     if weapon.name == self.weapon.name:
         self.weapon.long_name.replace('\'s', '\'s old')
         Narrator().add([
             self.name, 'picks up', f'a better {weapon.name}',
             self.current_area.at
         ])
     else:
         Narrator().add([
             self.name, 'picks up', weapon.long_name, self.current_area.at
         ])
     self.get_weapon(weapon)
Exemple #11
0
 def fill_bottles(self):
     self.water_upkeep()
     if Map().has_water(self):
         total_water = self.water + sum(b.fill for b in self.bottles)
         self._water = max(1.5, self.water)
         for b in self.bottles:
             b.fill = 1
         new_total_water = self.water + sum(b.fill for b in self.bottles)
         if new_total_water > total_water + 1:
             if len(self.bottles):
                 Narrator().add([
                     self.name, 'fills', self.his,
                     'bottles' if len(self.bottles) > 1 else 'bottle',
                     self.current_area.at
                 ])
             else:
                 Narrator().add([self.name, 'drinks', self.current_area.at])
     else:
         water = random()
         amount = min(self.thirst, water)
         self._water += amount
         water -= amount
         for b in self.bottles:
             amount = min(1 - b.fill, water)
             b.fill += amount
             water -= amount
Exemple #12
0
    def flee(self,
             area=None,
             panic=False,
             drop_verb='drops',
             stock=False,
             filtered_areas=None):
        if area is None:
            if filtered_areas is None:
                filtered_areas = []
            filtered_areas = [*Context().forbidden_areas, *filtered_areas]
            self.status.append(FLEEING)
            if panic and random() > self.courage + 0.5:
                self.drop_weapon(verbose=True, drop_verb=drop_verb)

            available_areas = [
                area for area in Map().areas if area not in filtered_areas
            ]
            available_areas.sort(key=lambda x: self._flee_value(x))
            if available_areas:
                area = available_areas[-1]
        out = None
        self.reveal()
        if area is not None:
            out = self.go_to(area)
        if out is None:
            self.hide(panic=panic, stock=stock)
        else:
            Narrator().add([self.name, f'flees {out.to}'], stock=stock)
            self.check_for_ambush_and_traps()
Exemple #13
0
 def set_up_ambush(self):
     self.stealth += (random() / 2 + 0.5) * (1 - self.stealth)
     self.end_ambush()
     Map().add_ambusher(self, self)
     self._ambush = True
     Narrator().add(
         [self.name, 'sets up', 'an ambush', self.current_area.at])
Exemple #14
0
 def loot_bag(self, take_a_break=True):
     item = Map().pick_bag(self.current_area)
     if item is None:
         return self.loot(take_a_break=take_a_break)
     Narrator().add(
         [self.name, 'picks up', item.long_name, self.current_area.at])
     self.get_item(item)
Exemple #15
0
def get_drop_strats():
    return [
        Strategy(f'go get loot {area.at}',
                 lambda x: x.should_go_get_drop(area),
                 lambda x: x.go_get_drop(area)) for area in Map().areas
        if area not in Context().forbidden_areas
    ]
Exemple #16
0
 def __init__(self, owner, stealth):
     Entity.__init__(self, self._name, 'it')
     self.long_name = f'{owner.name}\'s {self.name}'
     self.owner = owner
     self.knowing = owner.players
     self.stealth = stealth
     Map().add_trap(self, owner)
Exemple #17
0
 def can_flee(self):
     filtered_areas = Context().forbidden_areas
     accessible_areas = [a for a in Map().areas if a not in filtered_areas]
     if not len(accessible_areas):
         return False
     if TRAPPED in self.status:
         return False
     return self.energy + self.health > self.move_cost or not self.current_area.is_start
Exemple #18
0
 def estimate_of_danger(self, area) -> float:
     neighbors = Map().potential_players(area)
     if not len(neighbors):
         return 0
     seen_neighbors = [
         p for p in neighbors if self.can_see(p) and p != self
     ]
     return sum([p.dangerosity for p in seen_neighbors])
Exemple #19
0
 def drop_weapon(self, verbose=True, drop_verb='drops'):
     if self.weapon != HANDS:
         if verbose:
             Narrator().add([
                 self.name, drop_verb, f'{self.his} {self.weapon.name}',
                 self.current_area.at
             ])
         Map().add_loot(self.weapon, self.current_area)
     self._weapon = HANDS
Exemple #20
0
    def go_get_drop(self, area: Area):
        self.end_ambush()
        out = self.go_to(area)
        if out is not None:
            Narrator().add([self.name, f'goes {out.to} to get loot'])
        else:
            Narrator().cut()
        if self.check_for_ambush_and_traps():
            return
        seen_neighbors = [
            p for p in Map().potential_players(self)
            if self.can_see(p) and p != self
        ]
        free_neighbors = [
            p for p in seen_neighbors
            if p.current_area == self.current_area and not p.busy
        ]
        potential_danger = sum([p.dangerosity for p in seen_neighbors])
        actual_danger = sum([p.dangerosity for p in free_neighbors])

        if potential_danger > self.dangerosity and potential_danger > self.courage:
            Narrator().add([
                self.name, 'sees',
                format_list([p.name for p in seen_neighbors])
            ])
            self.flee(filtered_areas=[area])
        elif actual_danger > self.dangerosity and actual_danger > self.courage:
            Narrator().add([
                self.name, 'sees',
                format_list([p.name for p in free_neighbors])
            ])
            self.flee(filtered_areas=[area])
        elif actual_danger > 0:  # enemy present -> fight them
            Narrator().cut()
            self.attack_at_random()
        elif potential_danger > 0 and actual_danger == 0:  # enemy busy but incoming
            if self.dangerosity > potential_danger:  # attack before the other(s) arrive
                Narrator().cut()
                self.attack_at_random()
            else:  # loot and go/get your load and hit the road
                Narrator().add([
                    self.name, 'avoids',
                    format_list([p.name for p in seen_neighbors])
                ])
                self.loot(take_a_break=False)
                self.flee(filtered_areas=[area])
        else:  # servez-vous
            self.loot()
        if len(Narrator().current_sentence) == 0:
            Narrator().add([
                self.name,
                f'potential_danger={potential_danger}',
                f'actual_danger={actual_danger}',
                f'dangerosity={self.dangerosity}',
                f'courage={self.courage}',
            ])
Exemple #21
0
 def loot(self, take_a_break=True):
     if take_a_break:
         self.take_a_break()
     if Map().players_count(self) == 1:
         item = Map().pick_best_item(self)
     else:
         item = Map().pick_item(self.current_area)
     if item is None or (isinstance(item, Weapon)
                         and item.damage_mult <= self.weapon.damage_mult):
         Narrator().add([
             self.name, 'tries to loot', self.current_area.at,
             'but can\'t find anything useful'
         ])
         return
     if isinstance(item, Weapon):
         self.loot_weapon(item, retry=False)
     else:
         Narrator().add(
             [self.name, 'picks up', item.long_name, self.current_area.at])
         self.get_item(item)
Exemple #22
0
 def apply(self, players: Union[PlayingEntity, List[PlayingEntity]]):
     if not isinstance(players, list):
         players = [players]
     if not self.group_trap:
         players = [choice(players)]
     for player in players:
         name = self.long_name
         if player is self.owner:
             name = f'{player.his} own {self.name}'
         Map().remove_trap(self)
         player.reveal()
         self._apply(name, player)
Exemple #23
0
 def __init__(self, players: Optional[List[Player]]=None):
     if players is None:
         raise ValueError('No players in the arena')
     Context().game = self
     self.players = players
     self.map = Map(len(players))
     self._event_gauge = 0
     self._players_at_last_event = 0
     self._time_since_last_event = 0
     for p in self.players:
         self.map.add_player(p)
         for p2 in self.players:
             if p != p2:
                 if p.district == p2.district:
                     p.relationship(p2).add_friendship(random() * 0.5 + 0.5)
                     p.relationship(p2).add_trust(random() * 0.5)
                 else:
                     p.relationship(p2).add_friendship(random())
                     p.relationship(p2).add_trust(random() * 0.25)
     self.event_classes = [WildFire, DropEvent, Flood, AcidGas, Wasps, Beasts]
     self.day = 0
     self.time = STARTER
Exemple #24
0
 def judge_strats(self) -> dict:
     if self.sleep < 0:
         if Map().players_count(self) > 1 and self.energy > self.move_cost:
             strats = flee_strats()
         else:
             return {hide_strat: 1}
     else:
         if Context().time == NIGHT:
             strats = night_strategies()
         elif Context().time == STARTER:
             strats = start_strategies()
         else:
             strats = morning_strategies()
     # strats.sort(key=lambda x: -x.pref(self) + random() * (1 - self.wisdom))
     return {s: s.pref(self) + random() * (1 - self.wisdom) for s in strats}
Exemple #25
0
    def trigger(self):
        Context().forbidden_areas.extend(self.areas)
        saw_it_coming = []
        warned = []
        # Narrator().add(['should trigger for', [p.name for a in self.areas for p in a.players]])
        for area in self.areas:
            for p_e in Context().playing_entities_at(area):
                for p in p_e.players:
                    if p.wisdom * random() > self.stealth:
                        saw_it_coming.append(p.name)
                        warned.extend(p_e.players)
                        break
        if len(saw_it_coming):
            Narrator().new([
                format_list(saw_it_coming), 'see' if len(saw_it_coming) > 1 else 'sees', self.it, 'coming'
            ])
        for area in self.areas:
            area_players = copy(area.players)
            for p in area_players:
                Narrator().cut()

                if p.can_flee():
                    if p in warned:
                        p.flee()
                        if p.current_area in self.areas:
                            Narrator().new([
                                'error:', 'forbidden:', Context().forbidden_areas, p.name, p.current_area.at])
                            Map().test = 'SHIT'
                    elif p.be_damaged(self.base_damage, weapon=self.weapon_name):
                        Narrator().new([p.name, 'fails', 'to escape', self.it, 'and', self.dies, area.at])
                    else:
                        Narrator().apply_stock()
                        p.flee(panic=True, drop_verb='loses')
                    continue  # successful escape
                Narrator().new([p.name, 'is', 'trapped', area.at])
                if self.trapped_means_dead:
                    p.be_damaged(1)
                    Narrator().add([p.name, 'is', 'swiped', 'by', self.it, area.at, 'and', self.dies])
                elif p.be_damaged(random() * self.extra_damage + self.base_damage, weapon=self.weapon_name):
                    Narrator().add(['and', self.dies])
                else:
                    Narrator().apply_stock()
                if not len(Narrator().current_sentence):  # error
                    Narrator().add([p.name, 'escaped', self.it, 'and is', p.current_area.at])
            Narrator().clear_stock()
            if self.remove_loot:
                area.loot.clear()
Exemple #26
0
    def loot_weapon(self,
                    weapon: Optional[Union[Weapon, List[Weapon]]] = None):
        weapons: List[Weapon] = []
        if isinstance(weapon, Weapon):
            weapons.append(weapon)
        if isinstance(weapon, list):
            weapons = weapon
        if weapon is None:
            for _ in self.acting_players:
                weapons.append(Map().pick_weapon(self))
        weapons = [w for w in weapons if w is not None]

        weapons.sort(key=lambda x: -x.damage_mult)
        self.acting_players.sort(key=lambda x: -x.weapon.damage_mult)

        empty_handed: List[Player] = []
        for player in self.acting_players:
            picked = False
            for weapon in weapons:
                if weapon.damage_mult > player.weapon.damage_mult:
                    if weapon.name == player.weapon.name:
                        player.weapon.long_name.replace('\'s', '\'s old')
                        Narrator().add([
                            player.name, 'picks up', f'a better {weapon.name}',
                            self.current_area.at
                        ])
                    else:
                        Narrator().add([
                            player.name, 'picks up', weapon.long_name,
                            self.current_area.at
                        ])
                    if player.weapon != HANDS:
                        weapons.append(player.weapon)
                    player.get_weapon(weapon)
                    weapons.remove(weapon)
                    picked = True
                    break
            if not picked:
                empty_handed.append(player)
        if len(empty_handed):
            verb = 'try' if len(empty_handed) > 1 else 'tries'
            Narrator().add([
                player_names(empty_handed), verb, 'to find weapons',
                self.current_area.at, 'but can\'t find anything good'
            ])
Exemple #27
0
 def set_up_ambush(self):
     self.stealth += (random() / 2 + 0.5) * (1 - self.stealth)
     if AMBUSH not in self.status:
         self.status.append(AMBUSH)
         Map().add_ambusher(self, self)
         Narrator().add(
             [self.name, 'sets up', 'an ambush', self.current_area.at])
     else:
         self._waiting += 1
         if self._waiting < 2:
             Narrator().add(
                 [self.name, 'keeps', 'hiding', self.current_area.at])
         else:
             Narrator().add([
                 self.name, 'gets', 'tired of hiding', self.current_area.at
             ])
             self.end_ambush()
             self.pursue()
Exemple #28
0
 def pursue(self):
     available_areas = [
         a for a in Map().areas if a not in Context().forbidden_areas
     ]
     available_areas.sort(
         key=lambda x: sum(p._pursue_value(x) for p in self.acting_players))
     out = None
     if not available_areas:
         out = self.go_to(available_areas[-1])
     if out is None:
         self.hide()
         Narrator().replace('hides and rests', 'rests')
     else:
         targets = [
             p.name for p in Context().alive_players
             if p not in self.players
         ]
         players = 'players' if len(targets) > 2 else format_list(targets)
         Narrator().add([self.name, 'searches for', players, out.at])
         self.check_for_ambush_and_traps()
Exemple #29
0
 def consider_betrayal(self):
     allies = self.allies()
     # when there are no enemies left
     if len([
             p for p in Context().alive_players
             if p != self and not self.is_allied_to(p)
     ]) == 0:
         if len(allies):
             allies.sort(key=lambda x: x.dangerosity)
             self.betray(allies[-1])  # betray the most dangerous one
             return True
     allies_by_value = {
         x.dangerosity + self.relationship(x).trust +
         self.relationship(x).friendship: x
         for x in allies
     }
     if allies and min(allies_by_value) < 0:
         Map().test = f'{self.name} betrays'
         self.betray(allies_by_value[min(
             allies_by_value)])  # get rid of useless/untrustworthy
     return False
Exemple #30
0
 def pursue(self):
     available_areas = [
         a for a in Map().areas if a not in Context().forbidden_areas
     ]
     available_areas.sort(key=lambda x: -self._pursue_value(x))
     out = self.go_to(available_areas[0])
     if out is None:
         self.hide()
         Narrator().replace('hides and rests', 'rests')
     else:
         self.end_ambush()
         targets = [
             p.name for p in Context().alive_players
             if p != self and not self.relationship(p).allied
         ]
         if len(targets) == 0:
             Narrator().add(
                 [self.name, 'doesn\'t know', 'who to look for', out.at])
         else:
             players = 'players' if len(targets) > 1 else targets[0]
             Narrator().add([self.name, 'searches for', players, out.at])
         self.check_for_ambush_and_traps()