mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-06-07 13:15:53 +02:00
Create Actions, Executable objects
This commit is contained in:
@@ -20,10 +20,10 @@ from dungeonsheets import (
|
|||||||
spells,
|
spells,
|
||||||
weapons,
|
weapons,
|
||||||
)
|
)
|
||||||
from dungeonsheets.stats import Ability, ArmorClass, Initiative, Skill, Speed, findattr
|
from dungeonsheets.stats import findattr
|
||||||
from dungeonsheets.weapons import Weapon
|
from dungeonsheets.weapons import Weapon
|
||||||
from dungeonsheets.readers import read_character_file
|
from dungeonsheets.readers import read_character_file
|
||||||
from dungeonsheets.agent import Agent
|
from dungeonsheets.encounter.agent import Agent
|
||||||
|
|
||||||
|
|
||||||
def read(fname):
|
def read(fname):
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
class Event:
|
||||||
|
"""An event between one and possibly more entities"""
|
||||||
|
|
||||||
|
subj = None
|
||||||
|
obj = None
|
||||||
|
|
||||||
|
def __init__(self, action, subj, obj):
|
||||||
|
self.action = action
|
||||||
|
self.subj = subj
|
||||||
|
self.obj = obj
|
||||||
|
|
||||||
|
|
||||||
|
class Executable(ABC):
|
||||||
|
"""Something (like an action) that can be executed.
|
||||||
|
|
||||||
|
Executing an action results in an event that is stored
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def execute(self, subj, obj=None):
|
||||||
|
return Event(self, subj, obj)
|
||||||
|
|
||||||
|
|
||||||
|
class Action(Executable):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BonusAction(Executable):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Reaction(Executable):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Movement(Executable):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LairAction(Executable):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LegendaryAction(Executable):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Attack(Action):
|
||||||
|
|
||||||
|
def __init__(self, subj, obj):
|
||||||
|
self.subj = subj
|
||||||
|
self.obj = obj
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
# Subject makes an attack roll
|
||||||
|
# Compare attack roll to object's AC
|
||||||
|
# Store the results to look into the event later
|
||||||
|
|
||||||
|
pass # TODO: Write how to do this
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
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.stats import Ability, ArmorClass, Initiative, Speed, Skill, CurrentInitiative, CurrentHP, \
|
||||||
|
NumericalInitiative
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
|
from dungeonsheets.utils import roll
|
||||||
|
|
||||||
|
|
||||||
class Agent(ABC):
|
class Agent(ABC):
|
||||||
@@ -81,8 +83,9 @@ class Agent(ABC):
|
|||||||
feature_choices = list()
|
feature_choices = list()
|
||||||
|
|
||||||
# Current Status:
|
# Current Status:
|
||||||
initiative_roll = CurrentInitiative()
|
numerical_initiative = NumericalInitiative()
|
||||||
current_hp = CurrentHP()
|
_initiative_roll = False
|
||||||
|
_current_hp = None
|
||||||
statuses = list()
|
statuses = list()
|
||||||
|
|
||||||
# TODO: Pull in the monster class-variables here too
|
# TODO: Pull in the monster class-variables here too
|
||||||
@@ -90,6 +93,26 @@ class Agent(ABC):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def roll_initiative(self):
|
||||||
|
init_mod, adv = self.numerical_initiative
|
||||||
|
val = roll(20)
|
||||||
|
if adv:
|
||||||
|
val = max(val, roll(20))
|
||||||
|
self._initiative_roll = val + init_mod
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_hp(self):
|
||||||
|
if self._current_hp is None:
|
||||||
|
self._current_hp = self.hp_max
|
||||||
|
return self._current_hp
|
||||||
|
|
||||||
|
@property
|
||||||
|
def initiative_roll(self):
|
||||||
|
if self._initiative_roll is False:
|
||||||
|
self.roll_initiative()
|
||||||
|
return self._initiative_roll
|
||||||
|
|
||||||
|
|
||||||
# TODO: Perhaps these are better stored like the skills are as objects with a __get__?
|
# TODO: Perhaps these are better stored like the skills are as objects with a __get__?
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -18,7 +18,6 @@ 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)
|
||||||
|
|
||||||
raise NotImplementedError() # Apparently the mind flayers win for now
|
|
||||||
|
|
||||||
def analyze(self):
|
def analyze(self):
|
||||||
"""So, really... how deadly *is* it?"""
|
"""So, really... how deadly *is* it?"""
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ shape forms."""
|
|||||||
|
|
||||||
|
|
||||||
from dungeonsheets.stats import Ability
|
from dungeonsheets.stats import Ability
|
||||||
from dungeonsheets.agent import Agent
|
from dungeonsheets.encounter.agent import Agent
|
||||||
|
|
||||||
|
|
||||||
class Monster(Agent):
|
class Monster(Agent):
|
||||||
|
|||||||
@@ -240,23 +240,3 @@ class Initiative(NumericalInitiative):
|
|||||||
if has_advantage:
|
if has_advantage:
|
||||||
ini += "(A)"
|
ini += "(A)"
|
||||||
return ini
|
return ini
|
||||||
|
|
||||||
|
|
||||||
###########################
|
|
||||||
# STATUS
|
|
||||||
###########################
|
|
||||||
|
|
||||||
class CurrentHP:
|
|
||||||
"""A Numerical Representation of Current HP"""
|
|
||||||
|
|
||||||
def __get__(self, char, Character):
|
|
||||||
if not char.hp_max:
|
|
||||||
char.__set_hp_max()
|
|
||||||
return char.hp_max
|
|
||||||
|
|
||||||
|
|
||||||
class CurrentInitiative(NumericalInitiative):
|
|
||||||
"""A Numerical Representation of a Character's Rolled Initiative"""
|
|
||||||
|
|
||||||
def __get__(self, char, Character):
|
|
||||||
ini, has_advantage = super(CurrentInitiative, self).__get__(char, Character)
|
|
||||||
@@ -12,7 +12,7 @@ class TestEncounter(TestCase):
|
|||||||
"""Tests for features and feature-related activities."""
|
"""Tests for features and feature-related activities."""
|
||||||
|
|
||||||
def test_simulation(self):
|
def test_simulation(self):
|
||||||
"""Can I run an encounter against Schlangdedrosa Magentawrath?"""
|
"""Can I run an encounter against Langdedrosa Cyanwrath?"""
|
||||||
char = Character()
|
char = Character()
|
||||||
char.set_attrs(name="Stravajiaxen")
|
char.set_attrs(name="Stravajiaxen")
|
||||||
char.set_attrs(weapons=["greataxe"])
|
char.set_attrs(weapons=["greataxe"])
|
||||||
@@ -22,7 +22,7 @@ class TestEncounter(TestCase):
|
|||||||
char.set_attrs(race="half orc")
|
char.set_attrs(race="half orc")
|
||||||
char.set_attrs(inspiration=False)
|
char.set_attrs(inspiration=False)
|
||||||
|
|
||||||
class SchlangdedrosaMagentawrath(Monster):
|
class LangdedrosaCyanwrath(Monster):
|
||||||
"""
|
"""
|
||||||
**Action Surge (Recharges on a Short or Long Rest).** On his turn, Langdedrosa
|
**Action Surge (Recharges on a Short or Long Rest).** On his turn, Langdedrosa
|
||||||
can take one additional action.
|
can take one additional action.
|
||||||
@@ -46,7 +46,7 @@ class TestEncounter(TestCase):
|
|||||||
**Climbing speed:** 30 ft.
|
**Climbing speed:** 30 ft.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "Schlangdedrosa Magentawrath"
|
name = "Langdedrosa Cyanwrath"
|
||||||
description = "Medium humanoid (half-dragon), lawful evil"
|
description = "Medium humanoid (half-dragon), lawful evil"
|
||||||
challenge_rating = 4
|
challenge_rating = 4
|
||||||
armor_class = 17
|
armor_class = 17
|
||||||
@@ -64,7 +64,7 @@ class TestEncounter(TestCase):
|
|||||||
hp_max = 57
|
hp_max = 57
|
||||||
hit_dice = "6d12+18"
|
hit_dice = "6d12+18"
|
||||||
|
|
||||||
schlang = SchlangdedrosaMagentawrath()
|
lang = LangdedrosaCyanwrath()
|
||||||
|
|
||||||
battle = Encounter([char], [schlang])
|
battle = Encounter([char], [lang])
|
||||||
results = battle.simulate()
|
results = battle.simulate()
|
||||||
Reference in New Issue
Block a user