[WIP] Creating an Encounter

This commit is contained in:
Matthew DeMartino
2021-05-22 20:04:47 -04:00
parent d2df428969
commit 610d75582b
7 changed files with 137 additions and 7 deletions
+43
View File
@@ -0,0 +1,43 @@
class Agent:
"""An actor in an encounter"""
strategies = ("Random", "Greedy", "KillWeakest")
strategy = "Greedy"
def __init__(self):
pass
@property
def actions(self):
"""All the things I can do in a turn"""
raise NotImplementedError()
@property
def free_actions(self):
"""Stuff I can do as much as I want in a turn"""
raise NotImplementedError()
@property
def movement(self):
"""Where I can go in a turn"""
raise NotImplementedError()
@property
def bonus_actions(self):
"""Things I can do once in addition to an action"""
raise NotImplementedError()
@property
def reactions(self):
"""Things I can do in response to an action"""
raise NotImplementedError()
@property
def lair_actions(self):
"""Things I can do at initiative count 20"""
raise NotImplementedError()
@property
def legendary_actions(self):
"""Things I can do so many times in a turn after another agent acts"""
raise NotImplementedError()
+2 -1
View File
@@ -23,6 +23,7 @@ from dungeonsheets import (
from dungeonsheets.stats import Ability, ArmorClass, Initiative, Skill, Speed, findattr
from dungeonsheets.weapons import Weapon
from dungeonsheets.readers import read_character_file
from dungeonsheets.agent import Agent
def read(fname):
@@ -145,7 +146,7 @@ def _resolve_mechanic(mechanic, module, SuperClass, warning_message=None):
return Mechanic
class Character:
class Character(Actor):
"""A generic player character."""
# General attirubtes
View File
+19
View File
@@ -0,0 +1,19 @@
from .strategy import Strategy
class Encounter:
"""A combat encounter between two parties -- good guys and bad guys"""
def __init__(self, good_guys, bad_guys):
self.good_guys = good_guys
self.bad_guys = bad_guys
def rating(self):
raise NotImplementedError() # Deadly for Python :/
def simulate(self):
"""Who will win?"""
raise NotImplementedError() # Apparently the mind flayers win for now
def analyze(self):
"""So, really... how deadly *is* it?"""
raise NotImplementedError() # TODO: Run a Monte-Carlo simulation
+5 -4
View File
@@ -3,9 +3,10 @@ shape forms."""
from dungeonsheets.stats import Ability
from dungeonsheets.agent import Agent
class Monster:
class Monster(Agent):
"""A monster that may be encountered when adventuring."""
name = "Generic Monster"
@@ -209,8 +210,8 @@ class GiantFrog(Monster):
description = "Medium beast, unaligned"
challenge_rating = 1 / 4
armor_class = 11
skills = "Pe rce ption +2, Stealth +3"
senses = "darkvi sion 30ft., passive Perception 12"
skills = "Perception +2, Stealth +3"
senses = "darkvision 30ft., passive Perception 12"
languages = ""
strength = Ability(12)
dexterity = Ability(13)
@@ -242,7 +243,7 @@ class GiantRat(Monster):
challenge_rating = 1 / 8
armor_class = 12
skills = ""
senses = "Darkvision 60 ft., Passive perception 10"
senses = "Darkvision 60 ft., passive Perception 10"
languages = ""
strength = Ability(7)
dexterity = Ability(15)
+2 -2
View File
@@ -256,7 +256,7 @@ class HalfOrc(Race):
features = (feats.Darkvision, feats.RelentlessEndurance, feats.SavageAttacks)
# Tielflings
# Tieflings
class Tiefling(Race):
name = "Tiefling"
size = "medium"
@@ -267,7 +267,7 @@ class Tiefling(Race):
features = (feats.Darkvision, feats.HellishResistance, feats.InfernalLegacy)
# Aassimar
# Aasimar
class _Aasimar(Race):
name = "Aasimar"
size = "medium"
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python
from unittest import TestCase
from dungeonsheets.character import Character
class TestEncounter(TestCase):
"""Tests for features and feature-related activities."""
def test_simulation():
"""Can I run an encounter against Schlangdedrosa Magentawrath?"""
char = Character()
char.set_attrs(name="Stravajiaxen")
char.set_attrs(weapons=["shortsword"])
char.set_attrs(armor="leather armor", shield="shield")
# Check that race gets set to an object
char.set_attrs(race="half orc")
char.set_attrs(inspiration=False)
class SchlangdedrosaMagentawrath(Monster):
"""
**Action Surge (Recharges on a Short or Long Rest).** On his turn, Langdedrosa
can take one additional action.
**Improved Critical.** Langdedrosa's weapon attacks score a critical hit on a
roll of 19 or 20.
**Multiattack:** Schlangdedrosa attacks twice, either with his greatsword or spear.
**Greatsword.** Melee Weapon Attack: +6 to hit, reach 5 ft., one target.
Hit: 11 (2d6 + 4) slashing damage.
**Spear.** Melee or Ranged Weapon Attack: +6 to hit, reach 5 ft. or
ranged 20/60 ft., one target. Hit: 7 (1d6 + 4) piercing damage.
**Lightning Breath (Recharge 5-6)**. Schlangdedrosa breathes lightning in a
30-foot line that is 5 feet wide. Each creature in the line must make a DC 13
Dexterity saving throw, taking 22 (4d10) lightning damage on a failed save, or
half as much damage on a successful one.
**Climbing speed:** 30 ft.
"""
name = "Schlangdedrosa Magentawrath"
description = "Medium humanoid (half-dragon), lawful evil"
challenge_rating = 4
armor_class = 17
skills = "Athletics +6, Intimidation +3, Perception +4"
senses = "blindsight 10 ft., darkvision 60ft., passive Perception 14"
strength = Ability(19)
dexterity = Ability(13)
constitution = Ability(16)
intelligence = Ability(10)
wisdom = Ability(14)
charisma = Ability(12)
speed = 30
swim_speed = 0
fly_speed = 0
hp_max = 57
hit_dice = "6d12+18"
schlang = SchlangdedrosaMagentawrath()
battle = Encounter([])