Source code for VegansDeluxe.core.Session

from uuid import uuid4

from VegansDeluxe.core.Entities.Entity import Entity
from VegansDeluxe.core.Events.EventManager import EventManager
from VegansDeluxe.core.Events.Events import HPLossGameEvent, PreActionsGameEvent, \
    PostActionsGameEvent, PreDamagesGameEvent, PostDamagesGameEvent, PostTickGameEvent, PostDeathsGameEvent, \
    DeathGameEvent, CallActionsGameEvent, AttachStateEvent, PreDeathGameEvent, StartSessionEvent
from VegansDeluxe.core.Translator.LocalizedString import ls


[docs]class Session[T: Entity]: def __init__(self, event_manager: EventManager): self.event_manager = event_manager self.id = uuid4() self.turn = 1 self.active = True self.entities: list[T] = [] self.texts = []
[docs] def attach_entity(self, entity: T): self.entities.append(entity)
[docs] def get_entity(self, entity_id: str) -> T: """ Get an entity by its ID. """ result = [entity for entity in self.entities if entity.id == entity_id] return result[0] if result else None
[docs] def say(self, text: str | ls, n: bool = True) -> None: """ Adds given text to log queue. """ self.texts.append(text + ("\n" if n else ''))
@property def alive_entities(self) -> list[T]: """ Get the list of entities which are not dead. """ return [entity for entity in self.entities if not entity.dead] @property def alive_teams(self) -> set[str]: """ Get the set of teams which have alive entities. """ return {entity.team for entity in self.alive_entities}
[docs] def tick(self): for entity in self.entities: entity.tick_turn()
[docs] def pre_move(self): for entity in self.entities: entity.pre_move() self.texts = []
[docs] def start(self): self.event_manager.publish(StartSessionEvent(self.id))
[docs] def cancel_damages(self, source): for entity in self.entities: entity.inbound_dmg.cancel(source)
[docs] def lose_hp(self, entity: T, damage: int) -> None: """ Deduct HP from the entity and print a message. """ hp_loss = (damage // 6) + 1 message = HPLossGameEvent(self.id, self.turn, entity, damage, hp_loss) self.event_manager.publish(message) entity.hp -= message.hp_loss self.say(ls("session_hp_loss_msg").format(hearts=entity.hearts, name=entity.name, hp_loss=message.hp_loss, hp=entity.hp))
[docs] def calculate_damages(self): for entity in self.entities: # Cancelling round if entity.energy > entity.max_energy: self.say(ls("session_alive_entities_msg").format(entity.name)) entity.energy = entity.max_energy if entity.inbound_dmg.sum() > entity.outbound_dmg.sum(): entity.outbound_dmg.clear() self.cancel_damages(entity) for entity in self.entities: if entity.inbound_dmg.sum() == 0: continue entity.inbound_dmg.cancel(entity) self.lose_hp(entity, entity.inbound_dmg.sum())
[docs] def stop(self): # TODO: Maybe publish some stop event? self.active = False
[docs] def death(self) -> None: """ Handle the death of entities. Publishes PreDeathGameEvent and DeathGameEvent. """ for entity in self.alive_entities: if entity.hp > 0: continue message = PreDeathGameEvent(self.id, self.turn, entity) self.event_manager.publish(message) if entity.hp > 0 or message.canceled: continue self.say(ls("session_death_msg").format(name=entity.name)) entity.dead = True for alive_entity in self.entities: alive_entity.nearby_entities.remove(entity) if entity in alive_entity.nearby_entities else None self.event_manager.publish(DeathGameEvent(self.id, self.turn, entity))
[docs] def finish(self): # TODO: Broadcast a pair of events, like in Session.death(). # Maybe someone will want to make a dungeon or something. if not len(self.alive_teams): # If everyone is dead self.stop() return if len(self.alive_teams) > 1: # If there is more than 1 team alive (no-team is also a team) return if len(self.alive_teams) == 1 and None in self.alive_teams: # If there is only no-team entities if len(list(self.alive_entities)) > 1: # If there is more than one player return self.stop()
[docs] def move(self): self.event_manager.publish(PreActionsGameEvent(self.id, self.turn)) # 1. Pre-action stage self.event_manager.publish(CallActionsGameEvent(self.id, self.turn)) # 2. Action stage self.event_manager.publish(PostActionsGameEvent(self.id, self.turn)) # 3. Post-action stage self.say(ls("session_effects_line").format(self.turn)) self.event_manager.publish(PreDamagesGameEvent(self.id, self.turn)) self.say(ls("session_results_line").format(self.turn)) self.calculate_damages() # 4. Damages stage self.event_manager.publish(PostDamagesGameEvent(self.id, self.turn)) # 5. Post-damages stage self.tick() # 6. Tick stage self.event_manager.publish(PostTickGameEvent(self.id, self.turn)) # 7. Post-tick stage self.death() # 8. Death stage self.event_manager.publish(PostDeathsGameEvent(self.id, self.turn)) # 9. Post-death stage self.finish() # 10. Finish stage self.turn += 1