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,
|
||||
weapons,
|
||||
)
|
||||
from dungeonsheets.stats import Ability, ArmorClass, Initiative, Skill, Speed, findattr
|
||||
from dungeonsheets.stats import findattr
|
||||
from dungeonsheets.weapons import Weapon
|
||||
from dungeonsheets.readers import read_character_file
|
||||
from dungeonsheets.agent import Agent
|
||||
from dungeonsheets.encounter.agent import Agent
|
||||
|
||||
|
||||
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.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 dungeonsheets.utils import roll
|
||||
|
||||
|
||||
class Agent(ABC):
|
||||
@@ -81,8 +83,9 @@ class Agent(ABC):
|
||||
feature_choices = list()
|
||||
|
||||
# Current Status:
|
||||
initiative_roll = CurrentInitiative()
|
||||
current_hp = CurrentHP()
|
||||
numerical_initiative = NumericalInitiative()
|
||||
_initiative_roll = False
|
||||
_current_hp = None
|
||||
statuses = list()
|
||||
|
||||
# TODO: Pull in the monster class-variables here too
|
||||
@@ -90,6 +93,26 @@ class Agent(ABC):
|
||||
def __init__(self):
|
||||
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__?
|
||||
|
||||
@property
|
||||
@@ -18,7 +18,6 @@ class Encounter:
|
||||
|
||||
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):
|
||||
"""So, really... how deadly *is* it?"""
|
||||
|
||||
@@ -3,7 +3,7 @@ shape forms."""
|
||||
|
||||
|
||||
from dungeonsheets.stats import Ability
|
||||
from dungeonsheets.agent import Agent
|
||||
from dungeonsheets.encounter.agent import Agent
|
||||
|
||||
|
||||
class Monster(Agent):
|
||||
|
||||
@@ -240,23 +240,3 @@ class Initiative(NumericalInitiative):
|
||||
if has_advantage:
|
||||
ini += "(A)"
|
||||
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."""
|
||||
|
||||
def test_simulation(self):
|
||||
"""Can I run an encounter against Schlangdedrosa Magentawrath?"""
|
||||
"""Can I run an encounter against Langdedrosa Cyanwrath?"""
|
||||
char = Character()
|
||||
char.set_attrs(name="Stravajiaxen")
|
||||
char.set_attrs(weapons=["greataxe"])
|
||||
@@ -22,7 +22,7 @@ class TestEncounter(TestCase):
|
||||
char.set_attrs(race="half orc")
|
||||
char.set_attrs(inspiration=False)
|
||||
|
||||
class SchlangdedrosaMagentawrath(Monster):
|
||||
class LangdedrosaCyanwrath(Monster):
|
||||
"""
|
||||
**Action Surge (Recharges on a Short or Long Rest).** On his turn, Langdedrosa
|
||||
can take one additional action.
|
||||
@@ -46,7 +46,7 @@ class TestEncounter(TestCase):
|
||||
**Climbing speed:** 30 ft.
|
||||
"""
|
||||
|
||||
name = "Schlangdedrosa Magentawrath"
|
||||
name = "Langdedrosa Cyanwrath"
|
||||
description = "Medium humanoid (half-dragon), lawful evil"
|
||||
challenge_rating = 4
|
||||
armor_class = 17
|
||||
@@ -64,7 +64,7 @@ class TestEncounter(TestCase):
|
||||
hp_max = 57
|
||||
hit_dice = "6d12+18"
|
||||
|
||||
schlang = SchlangdedrosaMagentawrath()
|
||||
lang = LangdedrosaCyanwrath()
|
||||
|
||||
battle = Encounter([char], [schlang])
|
||||
battle = Encounter([char], [lang])
|
||||
results = battle.simulate()
|
||||
Reference in New Issue
Block a user