mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-05-18 20:23:27 +02:00
[WIP] Creating an Encounter
This commit is contained in:
@@ -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()
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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([])
|
||||
Reference in New Issue
Block a user