mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-05-19 04:33:26 +02:00
Filling in skeleton for encounter
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from dungeonsheets.conditions.conditions import Blinded, Charmed
|
from dungeonsheets.conditions.conditions import Blinded, Charmed
|
||||||
from dungeonsheets.stats import Ability, ArmorClass, Initiative, Speed, Skill, CurrentInitiative, CurrentHP, \
|
from dungeonsheets.encounter.actions import Attack
|
||||||
|
from dungeonsheets.stats import Ability, ArmorClass, Initiative, Speed, Skill, \
|
||||||
NumericalInitiative
|
NumericalInitiative
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from dungeonsheets.utils import roll
|
from dungeonsheets.utils import roll
|
||||||
@@ -91,7 +92,7 @@ class Agent(ABC):
|
|||||||
# TODO: Pull in the monster class-variables here too
|
# TODO: Pull in the monster class-variables here too
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
self.long_rest()
|
||||||
|
|
||||||
def roll_initiative(self):
|
def roll_initiative(self):
|
||||||
init_mod, adv = self.numerical_initiative
|
init_mod, adv = self.numerical_initiative
|
||||||
@@ -112,40 +113,101 @@ class Agent(ABC):
|
|||||||
self.roll_initiative()
|
self.roll_initiative()
|
||||||
return self._initiative_roll
|
return self._initiative_roll
|
||||||
|
|
||||||
|
def make_actions(self, encounter):
|
||||||
|
"""Return a series of actions"""
|
||||||
|
|
||||||
# TODO: Perhaps these are better stored like the skills are as objects with a __get__?
|
# TODO: Dramatically improve logic, consider healing, consider encounter state, etc.
|
||||||
|
best_opponent = encounter.opponents(self)[0] # TODO: Choose opponent cleverly
|
||||||
|
action = Attack(self, best_opponent)
|
||||||
|
event = action.execute()
|
||||||
|
return [event] # TODO: Also allow bonus actions, etc.
|
||||||
|
|
||||||
|
def long_rest(self):
|
||||||
|
self.current_hp = self.hp_max
|
||||||
|
self._free_actions = self._default_free_actions
|
||||||
|
# TODO: Support spell slots
|
||||||
|
self.new_turn()
|
||||||
|
|
||||||
|
def new_turn(self):
|
||||||
|
self._actions = self._default_actions
|
||||||
|
self._bonus_actions = self._default_bonus_actions
|
||||||
|
self._reactions = self._default_reactions
|
||||||
|
self._legendary_actions = self._default_legendary_actions
|
||||||
|
self._lair_actions = self._default_lair_actions
|
||||||
|
|
||||||
|
# TODO: Consider having a single list of actions and gain or lose them each
|
||||||
|
# turn based on their sub-type instead.
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def actions(self):
|
def default_actions(self):
|
||||||
"""All the things I can do in a turn"""
|
"""All the things I can do in a turn"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def free_actions(self):
|
def default_free_actions(self):
|
||||||
"""Stuff I can do as much as I want in a turn"""
|
"""Stuff I can do as much as I want in a turn"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def movement(self):
|
def default_movement(self):
|
||||||
"""Where I can go in a turn"""
|
"""Where I can go in a turn"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bonus_actions(self):
|
def default_bonus_actions(self):
|
||||||
"""Things I can do once in addition to an action"""
|
"""Things I can do once in addition to an action"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def reactions(self):
|
def default_reactions(self):
|
||||||
"""Things I can do in response to an action"""
|
"""Things I can do in response to an action"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lair_actions(self):
|
def default_lair_actions(self):
|
||||||
"""Things I can do at initiative count 20"""
|
"""Things I can do at initiative count 20"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def default_legendary_actions(self):
|
||||||
|
"""Things I can do only so many times in a turn after another agent acts"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def default_long_rest_actions(self):
|
||||||
|
"""Actions I gain back if I've had a long rest"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def actions(self):
|
||||||
|
"""All the remaining things I can do in a turn"""
|
||||||
|
return self._actions
|
||||||
|
|
||||||
|
@property
|
||||||
|
def free_actions(self):
|
||||||
|
"""Stuff I can do as much as I want in a turn"""
|
||||||
|
return self._free_actions
|
||||||
|
|
||||||
|
@property
|
||||||
|
def movement(self):
|
||||||
|
"""The rest of where I can go in a turn"""
|
||||||
|
return self._movement
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bonus_actions(self):
|
||||||
|
"""The rest of the things I can do once in addition to an action"""
|
||||||
|
return self._bonus_actions
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reactions(self):
|
||||||
|
"""The remaining things I can do in response to an action"""
|
||||||
|
return self._reactions
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lair_actions(self):
|
||||||
|
"""Remaining things I can do at initiative count 20"""
|
||||||
|
return self._lair_actions
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def legendary_actions(self):
|
def legendary_actions(self):
|
||||||
"""Things I can do so many times in a turn after another agent acts"""
|
"""Remaining things I can do only so many times in a turn after another agent acts"""
|
||||||
return []
|
return self._legendary_actions
|
||||||
@@ -6,6 +6,26 @@ class Encounter:
|
|||||||
self.group_b = group_b
|
self.group_b = group_b
|
||||||
self.all_agents = group_a + group_b
|
self.all_agents = group_a + group_b
|
||||||
|
|
||||||
|
self._events = []
|
||||||
|
|
||||||
|
def opponents(self, agent):
|
||||||
|
"""Who opposes the given agent in an encounter?"""
|
||||||
|
if agent in self.group_a:
|
||||||
|
return self.group_b
|
||||||
|
else:
|
||||||
|
return self.group_a
|
||||||
|
|
||||||
|
def allies(self, agent):
|
||||||
|
"""Who sides with the given agent in an encounter?"""
|
||||||
|
if agent in self.group_a:
|
||||||
|
return list(set(self.group_a) - set(agent))
|
||||||
|
else:
|
||||||
|
return list(set(self.group_b) - set(agent))
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self._events = []
|
||||||
|
self.long_rest()
|
||||||
|
|
||||||
def rating(self):
|
def rating(self):
|
||||||
raise NotImplementedError() # Deadly for Python :/
|
raise NotImplementedError() # Deadly for Python :/
|
||||||
|
|
||||||
@@ -18,6 +38,39 @@ class Encounter:
|
|||||||
|
|
||||||
self.all_agents = sorted(self.all_agents, key=lambda a: a.initiative_roll)
|
self.all_agents = sorted(self.all_agents, key=lambda a: a.initiative_roll)
|
||||||
|
|
||||||
|
# TODO: Support Lair Actions, cleverer loop
|
||||||
|
while not self.is_encounter_over():
|
||||||
|
self.new_turn()
|
||||||
|
for agent in self.all_agents:
|
||||||
|
agent.make_actions(self)
|
||||||
|
if self.is_encounter_over():
|
||||||
|
return self.events
|
||||||
|
|
||||||
|
return self.events # Should never get here -- self.is_encounter_over() will end it
|
||||||
|
|
||||||
|
raise NotImplementedError() # TODO: Finish the encounter
|
||||||
|
|
||||||
|
def is_encounter_over(self):
|
||||||
|
"""If all members of one party are at HP <= 0, it's over"""
|
||||||
|
return (
|
||||||
|
all([agent.current_hp <= 0 for agent in self.group_a]) or
|
||||||
|
all([agent.current_hp <= 0 for agent in self.group_b])
|
||||||
|
)
|
||||||
|
|
||||||
|
def long_rest(self):
|
||||||
|
"""Resets all agents to have full actions, abilities, etc."""
|
||||||
|
for agent in self.all_agents:
|
||||||
|
agent.long_rest()
|
||||||
|
|
||||||
|
def new_turn(self):
|
||||||
|
"""Resets turn-based actions for all agents"""
|
||||||
|
for agent in self.all_agents:
|
||||||
|
agent.new_turn()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def events(self):
|
||||||
|
"""What series of events went down in the encounter?"""
|
||||||
|
return self._events
|
||||||
|
|
||||||
def analyze(self):
|
def analyze(self):
|
||||||
"""So, really... how deadly *is* it?"""
|
"""So, really... how deadly *is* it?"""
|
||||||
|
|||||||
Reference in New Issue
Block a user