mirror of
https://github.com/evennia/evennia.git
synced 2026-04-01 21:47:17 +02:00
Resolve unit tests
This commit is contained in:
parent
a4eff902cc
commit
705d47fe47
14 changed files with 291 additions and 350 deletions
|
|
@ -103,7 +103,7 @@ from the _Knave_ rulebook. While we added the ability to roll on a random table
|
|||
```
|
||||
# in mygame/evadventure/random_tables.py
|
||||
|
||||
character_generation = {
|
||||
chargen_tables = {
|
||||
"physique": [
|
||||
"athletic", "brawny", "corpulent", "delicate", "gaunt", "hulking", "lanky",
|
||||
"ripped", "rugged", "scrawny", "short", "sinewy", "slender", "flabby",
|
||||
|
|
@ -135,20 +135,19 @@ During character generation we will need an entity to store/retain the changes,
|
|||
```python
|
||||
# in mygame/evadventure/chargen.py
|
||||
|
||||
from .random_tables import chargen_table
|
||||
from .random_tables import chargen_tables
|
||||
from .rules import dice
|
||||
|
||||
class TemporaryCharacterSheet:
|
||||
|
||||
def __init__(self):
|
||||
self.ability_changes = 0 # how many times we tried swap abilities
|
||||
|
||||
def _random_ability(self):
|
||||
return min(dice.roll("1d6"), dice.roll("1d6"), dice.roll("1d6"))
|
||||
|
||||
def generate(self):
|
||||
|
||||
def __init__(self):
|
||||
self.ability_changes = 0 # how many times we tried swap abilities
|
||||
|
||||
# name will likely be modified later
|
||||
self.name = dice.roll_random_table("1d282", chargen_table["name"])
|
||||
self.name = dice.roll_random_table("1d282", chargen_tables["name"])
|
||||
|
||||
# base attribute values
|
||||
self.strength = self._random_ability()
|
||||
|
|
@ -159,17 +158,17 @@ class TemporaryCharacterSheet:
|
|||
self.charisma = self._random_ability()
|
||||
|
||||
# physical attributes (only for rp purposes)
|
||||
physique = dice.roll_random_table("1d20", chargen_table["physique"])
|
||||
face = dice.roll_random_table("1d20", chargen_table["face"])
|
||||
skin = dice.roll_random_table("1d20", chargen_table["skin"])
|
||||
hair = dice.roll_random_table("1d20", chargen_table["hair"])
|
||||
clothing = dice.roll_random_table("1d20", chargen_table["clothing"])
|
||||
speech = dice.roll_random_table("1d20", chargen_table["speech"])
|
||||
virtue = dice.roll_random_table("1d20", chargen_table["virtue"])
|
||||
vice = dice.roll_random_table("1d20", chargen_table["vice"])
|
||||
background = dice.roll_random_table("1d20", chargen_table["background"])
|
||||
misfortune = dice.roll_random_table("1d20", chargen_table["misfortune"])
|
||||
alignment = dice.roll_random_table("1d20", chargen_table["alignment"])
|
||||
physique = dice.roll_random_table("1d20", chargen_tables["physique"])
|
||||
face = dice.roll_random_table("1d20", chargen_tables["face"])
|
||||
skin = dice.roll_random_table("1d20", chargen_tables["skin"])
|
||||
hair = dice.roll_random_table("1d20", chargen_tables["hair"])
|
||||
clothing = dice.roll_random_table("1d20", chargen_tables["clothing"])
|
||||
speech = dice.roll_random_table("1d20", chargen_tables["speech"])
|
||||
virtue = dice.roll_random_table("1d20", chargen_tables["virtue"])
|
||||
vice = dice.roll_random_table("1d20", chargen_tables["vice"])
|
||||
background = dice.roll_random_table("1d20", chargen_tables["background"])
|
||||
misfortune = dice.roll_random_table("1d20", chargen_tables["misfortune"])
|
||||
alignment = dice.roll_random_table("1d20", chargen_tables["alignment"])
|
||||
|
||||
self.desc = (
|
||||
f"You are {physique} with a {face} face, {skin} skin, {hair} hair, {speech} speech,"
|
||||
|
|
@ -185,21 +184,21 @@ class TemporaryCharacterSheet:
|
|||
self.level = 1
|
||||
|
||||
# random equipment
|
||||
self.armor = dice.roll_random_table("1d20", chargen_table["armor"])
|
||||
self.armor = dice.roll_random_table("1d20", chargen_tables["armor"])
|
||||
|
||||
_helmet_and_shield = dice.roll_random_table("1d20", chargen_table["helmets and shields"])
|
||||
_helmet_and_shield = dice.roll_random_table("1d20", chargen_tables["helmets and shields"])
|
||||
self.helmet = "helmet" if "helmet" in _helmet_and_shield else "none"
|
||||
self.shield = "shield" if "shield" in _helmet_and_shield else "none"
|
||||
|
||||
self.weapon = dice.roll_random_table("1d20", chargen_table["starting weapon"])
|
||||
self.weapon = dice.roll_random_table("1d20", chargen_tables["starting weapon"])
|
||||
|
||||
self.backpack = [
|
||||
"ration",
|
||||
"ration",
|
||||
dice.roll_random_table("1d20", chargen_table["dungeoning gear"]),
|
||||
dice.roll_random_table("1d20", chargen_table["dungeoning gear"]),
|
||||
dice.roll_random_table("1d20", chargen_table["general gear 1"]),
|
||||
dice.roll_random_table("1d20", chargen_table["general gear 2"]),
|
||||
dice.roll_random_table("1d20", chargen_tables["dungeoning gear"]),
|
||||
dice.roll_random_table("1d20", chargen_tables["dungeoning gear"]),
|
||||
dice.roll_random_table("1d20", chargen_tables["general gear 1"]),
|
||||
dice.roll_random_table("1d20", chargen_tables["general gear 2"]),
|
||||
]
|
||||
```
|
||||
|
||||
|
|
@ -367,7 +366,6 @@ def start_chargen(caller, session=None):
|
|||
|
||||
# this generates all random components of the character
|
||||
tmp_character = TemporaryCharacterSheet()
|
||||
tmp_character.generate()
|
||||
|
||||
EvMenu(caller, menutree, session=session, tmp_character=tmp_character)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ Turnbattle tests.
|
|||
|
||||
"""
|
||||
|
||||
from mock import patch, MagicMock
|
||||
from evennia.commands.default.tests import BaseEvenniaCommandTest
|
||||
from evennia.objects.objects import DefaultRoom
|
||||
from evennia.utils.create import create_object
|
||||
from evennia.utils.test_resources import BaseEvenniaTest
|
||||
from evennia.objects.objects import DefaultRoom
|
||||
from . import tb_basic, tb_equip, tb_range, tb_items, tb_magic
|
||||
from mock import MagicMock, patch
|
||||
|
||||
from . import tb_basic, tb_equip, tb_items, tb_magic, tb_range
|
||||
|
||||
|
||||
class TestTurnBattleBasicCmd(BaseEvenniaCommandTest):
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from evennia.prototypes.spawner import spawn
|
|||
from evennia.utils.evmenu import EvMenu
|
||||
|
||||
from .characters import EvAdventureCharacter
|
||||
from .random_tables import chargen_table
|
||||
from .random_tables import chargen_tables
|
||||
from .rules import dice
|
||||
|
||||
_ABILITIES = {
|
||||
|
|
@ -56,21 +56,12 @@ class TemporaryCharacterSheet:
|
|||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# you are only allowed to tweak abilities once
|
||||
self.ability_changes = 0
|
||||
|
||||
def _random_ability(self):
|
||||
return min(dice.roll("1d6"), dice.roll("1d6"), dice.roll("1d6"))
|
||||
|
||||
def generate(self):
|
||||
"""
|
||||
Generate random values for character.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# name will likely be modified later
|
||||
self.name = dice.roll_random_table("1d282", chargen_table["name"])
|
||||
self.name = dice.roll_random_table("1d282", chargen_tables["name"])
|
||||
|
||||
# base attribute values
|
||||
self.strength = self._random_ability()
|
||||
|
|
@ -81,23 +72,22 @@ class TemporaryCharacterSheet:
|
|||
self.charisma = self._random_ability()
|
||||
|
||||
# physical attributes (only for rp purposes)
|
||||
physique = dice.roll_random_table("1d20", chargen_table["physique"])
|
||||
face = dice.roll_random_table("1d20", chargen_table["face"])
|
||||
skin = dice.roll_random_table("1d20", chargen_table["skin"])
|
||||
hair = dice.roll_random_table("1d20", chargen_table["hair"])
|
||||
clothing = dice.roll_random_table("1d20", chargen_table["clothing"])
|
||||
speech = dice.roll_random_table("1d20", chargen_table["speech"])
|
||||
virtue = dice.roll_random_table("1d20", chargen_table["virtue"])
|
||||
vice = dice.roll_random_table("1d20", chargen_table["vice"])
|
||||
background = dice.roll_random_table("1d20", chargen_table["background"])
|
||||
misfortune = dice.roll_random_table("1d20", chargen_table["misfortune"])
|
||||
alignment = dice.roll_random_table("1d20", chargen_table["alignment"])
|
||||
physique = dice.roll_random_table("1d20", chargen_tables["physique"])
|
||||
face = dice.roll_random_table("1d20", chargen_tables["face"])
|
||||
skin = dice.roll_random_table("1d20", chargen_tables["skin"])
|
||||
hair = dice.roll_random_table("1d20", chargen_tables["hair"])
|
||||
clothing = dice.roll_random_table("1d20", chargen_tables["clothing"])
|
||||
speech = dice.roll_random_table("1d20", chargen_tables["speech"])
|
||||
virtue = dice.roll_random_table("1d20", chargen_tables["virtue"])
|
||||
vice = dice.roll_random_table("1d20", chargen_tables["vice"])
|
||||
background = dice.roll_random_table("1d20", chargen_tables["background"])
|
||||
misfortune = dice.roll_random_table("1d20", chargen_tables["misfortune"])
|
||||
alignment = dice.roll_random_table("1d20", chargen_tables["alignment"])
|
||||
|
||||
self.desc = (
|
||||
f"You are {physique} with a {face} face, {skin} skin, {hair} hair, {speech} speech,"
|
||||
f" and {clothing} clothing. You were a {background.title()}, but you were"
|
||||
f" {misfortune} and ended up a knave. You are {virtue} but also {vice}. You are of the"
|
||||
f" {alignment} alignment."
|
||||
f"You are {physique} with a {face} face, {skin} skin, {hair} hair, {speech} speech, and"
|
||||
f" {clothing} clothing. You were a {background.title()}, but you were {misfortune} and"
|
||||
f" ended up a knave. You are {virtue} but also {vice}. You tend towards {alignment}."
|
||||
)
|
||||
|
||||
# same for all
|
||||
|
|
@ -105,21 +95,21 @@ class TemporaryCharacterSheet:
|
|||
self.hp = self.hp_max
|
||||
|
||||
# random equipment
|
||||
self.armor = dice.roll_random_table("1d20", chargen_table["armor"])
|
||||
self.armor = dice.roll_random_table("1d20", chargen_tables["armor"])
|
||||
|
||||
_helmet_and_shield = dice.roll_random_table("1d20", chargen_table["helmets and shields"])
|
||||
_helmet_and_shield = dice.roll_random_table("1d20", chargen_tables["helmets and shields"])
|
||||
self.helmet = "helmet" if "helmet" in _helmet_and_shield else "none"
|
||||
self.shield = "shield" if "shield" in _helmet_and_shield else "none"
|
||||
|
||||
self.weapon = dice.roll_random_table("1d20", chargen_table["starting weapon"])
|
||||
self.weapon = dice.roll_random_table("1d20", chargen_tables["starting weapon"])
|
||||
|
||||
self.backpack = [
|
||||
"ration",
|
||||
"ration",
|
||||
dice.roll_random_table("1d20", chargen_table["dungeoning gear"]),
|
||||
dice.roll_random_table("1d20", chargen_table["dungeoning gear"]),
|
||||
dice.roll_random_table("1d20", chargen_table["general gear 1"]),
|
||||
dice.roll_random_table("1d20", chargen_table["general gear 2"]),
|
||||
dice.roll_random_table("1d20", chargen_tables["dungeoning gear"]),
|
||||
dice.roll_random_table("1d20", chargen_tables["dungeoning gear"]),
|
||||
dice.roll_random_table("1d20", chargen_tables["general gear 1"]),
|
||||
dice.roll_random_table("1d20", chargen_tables["general gear 2"]),
|
||||
]
|
||||
|
||||
def show_sheet(self):
|
||||
|
|
@ -155,7 +145,7 @@ class TemporaryCharacterSheet:
|
|||
new_character = create_object(
|
||||
EvAdventureCharacter,
|
||||
key=self.name,
|
||||
attrs=(
|
||||
attributes=(
|
||||
("strength", self.strength),
|
||||
("dexterity", self.dexterity),
|
||||
("constitution", self.constitution),
|
||||
|
|
@ -183,7 +173,7 @@ class TemporaryCharacterSheet:
|
|||
|
||||
for item in self.backpack:
|
||||
item = spawn(item)
|
||||
new_character.equipment.store(item)
|
||||
new_character.equipment.move(item)
|
||||
|
||||
return new_character
|
||||
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ class CombatActionStunt(CombatAction):
|
|||
if self.give_advantage:
|
||||
self.combathandler.gain_advantage(attacker, defender)
|
||||
self.msg(
|
||||
f"%You() $conj(gain) advantage against $You(defender.key! "
|
||||
"%You() $conj(gain) advantage against $You(defender.key! "
|
||||
f"You must use it within {stunt_duration} turns."
|
||||
)
|
||||
else:
|
||||
|
|
@ -398,15 +398,6 @@ class CombatActionUseItem(CombatAction):
|
|||
def get_help(self, item, *args):
|
||||
return item.get_help(*args)
|
||||
|
||||
def pre_use(self, item, *args, **kwargs):
|
||||
"""
|
||||
We tie into the `item.at_pre_use` hook here, which returns False if
|
||||
the item is not usable (that is, has .uses > 0).
|
||||
|
||||
"""
|
||||
if item.at_pre_use(self.combatant, *args, **kwargs):
|
||||
item.at_use(self.combatant, *args, **kwargs)
|
||||
|
||||
def use(self, item, target, *args, **kwargs):
|
||||
item.at_use(self.combatant, target, *args, **kwargs)
|
||||
|
||||
|
|
@ -442,7 +433,7 @@ class CombatActionSwapWieldedWeaponOrSpell(CombatAction):
|
|||
|
||||
def use(self, _, item, *args, **kwargs):
|
||||
# this will make use of the item
|
||||
self.combatant.equipment.use(item)
|
||||
self.combatant.equipment.move(item)
|
||||
|
||||
|
||||
class CombatActionFlee(CombatAction):
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ class EvAdventureDungeonStartRoom(EvAdventureDungeonRoom):
|
|||
branch_max_life = 60 * 60 * 24 * 7 # 1 week
|
||||
|
||||
# allow for a custom room_generator function
|
||||
room_generator = AttributeProperty(room_generator, autocreate=False)
|
||||
room_generator = AttributeProperty(lambda: room_generator, autocreate=False)
|
||||
|
||||
def get_display_footer(self, looker, **kwargs):
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -270,13 +270,15 @@ class EquipmentHandler:
|
|||
# it belongs in backpack, so goes back to it
|
||||
to_backpack = [obj]
|
||||
else:
|
||||
# for others (body, head), just replace whatever's there
|
||||
replaced = [obj]
|
||||
# for others (body, head), just replace whatever's there and put the old
|
||||
# thing in the backpack
|
||||
to_backpack = [slots[use_slot]]
|
||||
slots[use_slot] = obj
|
||||
|
||||
for to_backpack_obj in to_backpack:
|
||||
# put stuff in backpack
|
||||
slots[use_slot].append(to_backpack_obj)
|
||||
if to_backpack_obj:
|
||||
slots[WieldLocation.BACKPACK].append(to_backpack_obj)
|
||||
|
||||
# store new state
|
||||
self._save()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ Random tables - adopted from _Knave_.
|
|||
|
||||
# Character generation tables
|
||||
|
||||
character_generation = {
|
||||
chargen_tables = {
|
||||
"physique": [
|
||||
"athletic",
|
||||
"brawny",
|
||||
|
|
|
|||
|
|
@ -24,11 +24,7 @@ This module presents several singletons to import
|
|||
"""
|
||||
from random import randint
|
||||
|
||||
from evennia.utils.evform import EvForm
|
||||
from evennia.utils.evtable import EvTable
|
||||
|
||||
from .enums import Ability
|
||||
from .random_tables import character_generation as chargen_table
|
||||
from .random_tables import death_and_dismemberment as death_table
|
||||
|
||||
# Basic rolls
|
||||
|
|
@ -68,7 +64,7 @@ class EvAdventureRollEngine:
|
|||
roll_string = roll_string.lower()
|
||||
if "d" not in roll_string:
|
||||
raise TypeError(
|
||||
f"Dice roll '{roll_string}' was not recognized. " "Must be `<number>d<dicesize>`."
|
||||
f"Dice roll '{roll_string}' was not recognized. Must be `<number>d<dicesize>`."
|
||||
)
|
||||
number, diesize = roll_string.split("d", 1)
|
||||
try:
|
||||
|
|
@ -296,9 +292,6 @@ class EvAdventureRollEngine:
|
|||
Args:
|
||||
character (Character): The one resting.
|
||||
|
||||
Returns:
|
||||
int: How much HP was healed. This is never more than how damaged we are.
|
||||
|
||||
"""
|
||||
character.heal(self.roll("1d8") + character.constitution)
|
||||
|
||||
|
|
@ -334,13 +327,16 @@ class EvAdventureRollEngine:
|
|||
character.at_death()
|
||||
else:
|
||||
# refresh health, but get permanent ability loss
|
||||
self.heal(character, self.roll("1d4"))
|
||||
new_hp = self.roll("1d4")
|
||||
character.heal(new_hp)
|
||||
setattr(character, abi, current_abi)
|
||||
|
||||
character.msg(
|
||||
"~" * 78 + "\n|yYou survive your brush with death, "
|
||||
"~" * 78
|
||||
+ "\n|yYou survive your brush with death, "
|
||||
f"but are |r{result.upper()}|y and permanently |rlose {loss} {abi}|y.|n\n"
|
||||
f"|GYou recover |g{new_hp}|G health|.\n" + "~" * 78
|
||||
f"|GYou recover |g{new_hp}|G health|.\n"
|
||||
+ "~" * 78
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -43,4 +43,4 @@ class TestCharacters(BaseEvenniaTest):
|
|||
# can't get more coins than we have
|
||||
result = self.character.at_pay(100)
|
||||
self.assertEqual(result, 40)
|
||||
self.assertEqual(self.characer.coins, 0)
|
||||
self.assertEqual(self.character.coins, 0)
|
||||
|
|
|
|||
64
evennia/contrib/tutorials/evadventure/tests/test_chargen.py
Normal file
64
evennia/contrib/tutorials/evadventure/tests/test_chargen.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
"""
|
||||
Test chargen.
|
||||
|
||||
"""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from evennia import create_object
|
||||
from evennia.utils.test_resources import BaseEvenniaTest
|
||||
from parameterized import parameterized
|
||||
|
||||
from .. import chargen, enums, objects
|
||||
|
||||
|
||||
class EvAdventureCharacterGenerationTest(BaseEvenniaTest):
|
||||
"""
|
||||
Test the Character generator in the rule engine.
|
||||
|
||||
"""
|
||||
|
||||
@patch("evennia.contrib.tutorials.evadventure.rules.randint")
|
||||
def setUp(self, mock_randint):
|
||||
super().setUp()
|
||||
mock_randint.return_value = 10
|
||||
self.chargen = chargen.TemporaryCharacterSheet()
|
||||
|
||||
def test_base_chargen(self):
|
||||
self.assertEqual(self.chargen.strength, 10) # not realistic, due to mock
|
||||
self.assertEqual(self.chargen.armor, "gambeson")
|
||||
self.assertEqual(self.chargen.shield, "shield")
|
||||
self.assertEqual(
|
||||
self.chargen.backpack, ["ration", "ration", "waterskin", "waterskin", "drill", "twine"]
|
||||
)
|
||||
|
||||
def test_build_desc(self):
|
||||
self.assertEqual(
|
||||
self.chargen.desc,
|
||||
"You are scrawny with a broken face, pockmarked skin, greased hair, hoarse speech, and "
|
||||
"stained clothing. You were a Herbalist, but you were exiled and ended up a knave. You "
|
||||
"are honest but also irascible. You tend towards neutrality.",
|
||||
)
|
||||
|
||||
@patch("evennia.contrib.tutorials.evadventure.chargen.spawn")
|
||||
def test_apply(self, mock_spawn):
|
||||
|
||||
gambeson = create_object(objects.EvAdventureArmor, key="gambeson")
|
||||
mock_spawn.return_value = gambeson
|
||||
|
||||
character = self.chargen.apply()
|
||||
|
||||
self.assertIn("Herbalist", character.db.desc)
|
||||
self.assertEqual(
|
||||
character.equipment.all(),
|
||||
[
|
||||
(None, enums.WieldLocation.WEAPON_HAND),
|
||||
(None, enums.WieldLocation.SHIELD_HAND),
|
||||
(None, enums.WieldLocation.TWO_HANDS),
|
||||
(gambeson, enums.WieldLocation.BODY),
|
||||
(None, enums.WieldLocation.HEAD),
|
||||
],
|
||||
)
|
||||
|
||||
gambeson.delete()
|
||||
character.delete()
|
||||
|
|
@ -4,7 +4,10 @@ Test the EvAdventure equipment handler.
|
|||
"""
|
||||
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from evennia.utils.test_resources import BaseEvenniaTest
|
||||
from parameterized import parameterized
|
||||
|
||||
from ..enums import Ability, WieldLocation
|
||||
from ..equipment import EquipmentError
|
||||
|
|
@ -20,13 +23,6 @@ class TestEquipment(EvAdventureMixin, BaseEvenniaTest):
|
|||
setattr(self.character, Ability.CON.value, 3)
|
||||
self.assertEqual(self.character.equipment.max_slots, 13)
|
||||
|
||||
def test_validate_slot_usage(self):
|
||||
helmet = self.helmet
|
||||
self.assertTrue(self.character.equipment.validate_slot_usage(helmet))
|
||||
helmet.size = 20 # a very large helmet
|
||||
with self.assertRaises(EquipmentError):
|
||||
self.assertFalse(self.character.equipment.validate_slot_usage(helmet))
|
||||
|
||||
def test_add__remove(self):
|
||||
self.character.equipment.add(self.helmet)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.BACKPACK], [self.helmet])
|
||||
|
|
@ -53,6 +49,141 @@ class TestEquipment(EvAdventureMixin, BaseEvenniaTest):
|
|||
)
|
||||
|
||||
self.assertEqual(
|
||||
self.character.equipment.get_all(),
|
||||
[(self.helmet, WieldLocation.BACKPACK), (self.weapon, WieldLocation.BACKPACK)],
|
||||
self.character.equipment.all(),
|
||||
[
|
||||
(None, WieldLocation.WEAPON_HAND),
|
||||
(None, WieldLocation.SHIELD_HAND),
|
||||
(None, WieldLocation.TWO_HANDS),
|
||||
(None, WieldLocation.BODY),
|
||||
(None, WieldLocation.HEAD),
|
||||
(self.helmet, WieldLocation.BACKPACK),
|
||||
(self.weapon, WieldLocation.BACKPACK),
|
||||
],
|
||||
)
|
||||
|
||||
def _get_empty_slots(self):
|
||||
return {
|
||||
WieldLocation.BACKPACK: [],
|
||||
WieldLocation.WEAPON_HAND: None,
|
||||
WieldLocation.SHIELD_HAND: None,
|
||||
WieldLocation.TWO_HANDS: None,
|
||||
WieldLocation.BODY: None,
|
||||
WieldLocation.HEAD: None,
|
||||
}
|
||||
|
||||
def test_equipmenthandler_max_slots(self):
|
||||
self.assertEqual(self.character.equipment.max_slots, 11)
|
||||
|
||||
@parameterized.expand(
|
||||
[
|
||||
# size, pass_validation?
|
||||
(1, True),
|
||||
(2, True),
|
||||
(11, True),
|
||||
(12, False),
|
||||
(20, False),
|
||||
(25, False),
|
||||
]
|
||||
)
|
||||
def test_validate_slot_usage(self, size, is_ok):
|
||||
obj = MagicMock()
|
||||
obj.size = size
|
||||
|
||||
with patch("evennia.contrib.tutorials.evadventure.equipment.inherits_from") as mock_inherit:
|
||||
mock_inherit.return_value = True
|
||||
if is_ok:
|
||||
self.assertTrue(self.character.equipment.validate_slot_usage(obj))
|
||||
else:
|
||||
with self.assertRaises(EquipmentError):
|
||||
self.character.equipment.validate_slot_usage(obj)
|
||||
|
||||
@parameterized.expand(
|
||||
[
|
||||
# item, where
|
||||
("helmet", WieldLocation.HEAD),
|
||||
("shield", WieldLocation.SHIELD_HAND),
|
||||
("armor", WieldLocation.BODY),
|
||||
("weapon", WieldLocation.WEAPON_HAND),
|
||||
("big_weapon", WieldLocation.TWO_HANDS),
|
||||
("item", WieldLocation.BACKPACK),
|
||||
]
|
||||
)
|
||||
def test_move(self, itemname, where):
|
||||
self.assertEqual(self.character.equipment.slots, self._get_empty_slots())
|
||||
|
||||
obj = getattr(self, itemname)
|
||||
self.character.equipment.move(obj)
|
||||
# check that item ended up in the right place
|
||||
if where is WieldLocation.BACKPACK:
|
||||
self.assertTrue(obj in self.character.equipment.slots[where])
|
||||
else:
|
||||
self.assertEqual(self.character.equipment.slots[where], obj)
|
||||
|
||||
def test_add(self):
|
||||
self.character.equipment.add(self.weapon)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.WEAPON_HAND], None)
|
||||
self.assertTrue(self.weapon in self.character.equipment.slots[WieldLocation.BACKPACK])
|
||||
|
||||
def test_two_handed_exclusive(self):
|
||||
"""Two-handed weapons can't be used together with weapon+shield"""
|
||||
self.character.equipment.move(self.big_weapon)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.TWO_HANDS], self.big_weapon)
|
||||
# equipping sword or shield removes two-hander
|
||||
self.character.equipment.move(self.shield)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.SHIELD_HAND], self.shield)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.TWO_HANDS], None)
|
||||
self.character.equipment.move(self.weapon)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.WEAPON_HAND], self.weapon)
|
||||
|
||||
# the two-hander removes the two weapons
|
||||
self.character.equipment.move(self.big_weapon)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.TWO_HANDS], self.big_weapon)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.SHIELD_HAND], None)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.WEAPON_HAND], None)
|
||||
|
||||
def test_remove__with_obj(self):
|
||||
self.character.equipment.move(self.shield)
|
||||
self.character.equipment.move(self.item)
|
||||
self.character.equipment.add(self.weapon)
|
||||
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.SHIELD_HAND], self.shield)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[WieldLocation.BACKPACK], [self.item, self.weapon]
|
||||
)
|
||||
|
||||
self.assertEqual(self.character.equipment.remove(self.shield), [self.shield])
|
||||
self.assertEqual(self.character.equipment.remove(self.item), [self.item])
|
||||
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.SHIELD_HAND], None)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.BACKPACK], [self.weapon])
|
||||
|
||||
def test_remove__with_slot(self):
|
||||
self.character.equipment.move(self.shield)
|
||||
self.character.equipment.move(self.item)
|
||||
self.character.equipment.add(self.helmet)
|
||||
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.SHIELD_HAND], self.shield)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[WieldLocation.BACKPACK], [self.item, self.helmet]
|
||||
)
|
||||
|
||||
self.assertEqual(self.character.equipment.remove(WieldLocation.SHIELD_HAND), [self.shield])
|
||||
self.assertEqual(
|
||||
self.character.equipment.remove(WieldLocation.BACKPACK), [self.item, self.helmet]
|
||||
)
|
||||
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.SHIELD_HAND], None)
|
||||
self.assertEqual(self.character.equipment.slots[WieldLocation.BACKPACK], [])
|
||||
|
||||
def test_properties(self):
|
||||
self.character.equipment.move(self.armor)
|
||||
self.assertEqual(self.character.equipment.armor, 1)
|
||||
self.character.equipment.move(self.shield)
|
||||
self.assertEqual(self.character.equipment.armor, 2)
|
||||
self.character.equipment.move(self.helmet)
|
||||
self.assertEqual(self.character.equipment.armor, 3)
|
||||
|
||||
self.character.equipment.move(self.weapon)
|
||||
self.assertEqual(self.character.equipment.weapon, self.weapon)
|
||||
self.character.equipment.move(self.big_weapon)
|
||||
self.assertEqual(self.character.equipment.weapon, self.big_weapon)
|
||||
|
|
|
|||
|
|
@ -151,24 +151,20 @@ class EvAdventureRollEngineTest(BaseEvenniaTest):
|
|||
mock_randint.return_value = 10
|
||||
|
||||
self.assertEqual(
|
||||
self.roll_engine.roll_random_table(
|
||||
"1d20", random_tables.character_generation["physique"]
|
||||
),
|
||||
self.roll_engine.roll_random_table("1d20", random_tables.chargen_tables["physique"]),
|
||||
"scrawny",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.roll_engine.roll_random_table("1d20", random_tables.character_generation["vice"]),
|
||||
self.roll_engine.roll_random_table("1d20", random_tables.chargen_tables["vice"]),
|
||||
"irascible",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.roll_engine.roll_random_table(
|
||||
"1d20", random_tables.character_generation["alignment"]
|
||||
),
|
||||
self.roll_engine.roll_random_table("1d20", random_tables.chargen_tables["alignment"]),
|
||||
"neutrality",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.roll_engine.roll_random_table(
|
||||
"1d20", random_tables.character_generation["helmets and shields"]
|
||||
"1d20", random_tables.chargen_tables["helmets and shields"]
|
||||
),
|
||||
"no helmet or shield",
|
||||
)
|
||||
|
|
@ -176,14 +172,14 @@ class EvAdventureRollEngineTest(BaseEvenniaTest):
|
|||
mock_randint.return_value = 25
|
||||
self.assertEqual(
|
||||
self.roll_engine.roll_random_table(
|
||||
"1d20", random_tables.character_generation["helmets and shields"]
|
||||
"1d20", random_tables.chargen_tables["helmets and shields"]
|
||||
),
|
||||
"helmet and shield",
|
||||
)
|
||||
mock_randint.return_value = -10
|
||||
self.assertEqual(
|
||||
self.roll_engine.roll_random_table(
|
||||
"1d20", random_tables.character_generation["helmets and shields"]
|
||||
"1d20", random_tables.chargen_tables["helmets and shields"]
|
||||
),
|
||||
"no helmet or shield",
|
||||
)
|
||||
|
|
@ -202,17 +198,15 @@ class EvAdventureRollEngineTest(BaseEvenniaTest):
|
|||
@patch("evennia.contrib.tutorials.evadventure.rules.randint")
|
||||
def test_heal_from_rest(self, mock_randint):
|
||||
character = MagicMock()
|
||||
character.heal = MagicMock()
|
||||
character.hp_max = 8
|
||||
character.hp = 1
|
||||
character.constitution = 1
|
||||
|
||||
mock_randint.return_value = 5
|
||||
self.roll_engine.heal_from_rest(character)
|
||||
self.assertEqual(character.hp, 7) # hp + 1d8 + consititution bonus
|
||||
mock_randint.assert_called_with(1, 8) # 1d8
|
||||
|
||||
self.roll_engine.heal_from_rest(character)
|
||||
self.assertEqual(character.hp, 8) # can't have more than max hp
|
||||
character.heal.assert_called_with(6) # roll + constitution bonus
|
||||
|
||||
@patch("evennia.contrib.tutorials.evadventure.rules.randint")
|
||||
def test_roll_death(self, mock_randint):
|
||||
|
|
@ -229,233 +223,3 @@ class EvAdventureRollEngineTest(BaseEvenniaTest):
|
|||
mock_randint.return_value = 3
|
||||
self.roll_engine.roll_death(character)
|
||||
self.assertEqual(character.strength, 10)
|
||||
|
||||
|
||||
class EvAdventureCharacterGenerationTest(BaseEvenniaTest):
|
||||
"""
|
||||
Test the Character generator in the rule engine.
|
||||
|
||||
"""
|
||||
|
||||
@patch("evennia.contrib.tutorials.evadventure.rules.randint")
|
||||
def setUp(self, mock_randint):
|
||||
super().setUp()
|
||||
mock_randint.return_value = 10
|
||||
self.chargen = rules.EvAdventureCharacterGeneration()
|
||||
|
||||
def test_base_chargen(self):
|
||||
self.assertEqual(self.chargen.strength, 2)
|
||||
self.assertEqual(self.chargen.physique, "scrawny")
|
||||
self.assertEqual(self.chargen.skin, "pockmarked")
|
||||
self.assertEqual(self.chargen.hair, "greased")
|
||||
self.assertEqual(self.chargen.clothing, "stained")
|
||||
self.assertEqual(self.chargen.misfortune, "exiled")
|
||||
self.assertEqual(self.chargen.armor, "gambeson")
|
||||
self.assertEqual(self.chargen.shield, "shield")
|
||||
self.assertEqual(
|
||||
self.chargen.backpack, ["ration", "ration", "waterskin", "waterskin", "drill", "twine"]
|
||||
)
|
||||
|
||||
def test_build_desc(self):
|
||||
self.assertEqual(
|
||||
self.chargen.build_desc(),
|
||||
"Herbalist. Wears stained clothes, and has hoarse speech. Has a scrawny physique, "
|
||||
"a broken face, pockmarked skin and greased hair. Is honest, but irascible. "
|
||||
"Has been exiled in the past. Favors neutrality.",
|
||||
)
|
||||
|
||||
@parameterized.expand(
|
||||
[
|
||||
# source, target, value, new_source_val, new_target_val
|
||||
(enums.Ability.CON, enums.Ability.STR, 1, 1, 3),
|
||||
(enums.Ability.INT, enums.Ability.DEX, 1, 1, 3),
|
||||
(enums.Ability.CHA, enums.Ability.CON, 1, 1, 3),
|
||||
(enums.Ability.STR, enums.Ability.WIS, 1, 1, 3),
|
||||
(enums.Ability.WIS, enums.Ability.CHA, 1, 1, 3),
|
||||
(enums.Ability.DEX, enums.Ability.DEX, 1, 2, 2),
|
||||
]
|
||||
)
|
||||
def test_adjust_attribute(self, source, target, value, new_source_val, new_target_val):
|
||||
self.chargen.adjust_attribute(source, target, value)
|
||||
self.assertEqual(getattr(self.chargen, source.value), new_source_val, f"{source}->{target}")
|
||||
self.assertEqual(getattr(self.chargen, target.value), new_target_val, f"{source}->{target}")
|
||||
|
||||
def test_adjust_consecutive(self):
|
||||
# gradually shift all to STR (starts at 2)
|
||||
self.chargen.adjust_attribute(enums.Ability.CON, enums.Ability.STR, 1)
|
||||
self.chargen.adjust_attribute(enums.Ability.CHA, enums.Ability.STR, 1)
|
||||
self.chargen.adjust_attribute(enums.Ability.DEX, enums.Ability.STR, 1)
|
||||
self.chargen.adjust_attribute(enums.Ability.WIS, enums.Ability.STR, 1)
|
||||
self.assertEqual(self.chargen.constitution, 1)
|
||||
self.assertEqual(self.chargen.strength, 6)
|
||||
|
||||
# max is 6
|
||||
with self.assertRaises(ValueError):
|
||||
self.chargen.adjust_attribute(enums.Ability.INT, enums.Ability.STR, 1)
|
||||
# minimum is 1
|
||||
with self.assertRaises(ValueError):
|
||||
self.chargen.adjust_attribute(enums.Ability.DEX, enums.Ability.WIS, 1)
|
||||
|
||||
# move all from str to wis
|
||||
self.chargen.adjust_attribute(enums.Ability.STR, enums.Ability.WIS, 5)
|
||||
|
||||
self.assertEqual(self.chargen.strength, 1)
|
||||
self.assertEqual(self.chargen.wisdom, 6)
|
||||
|
||||
def test_apply(self):
|
||||
character = MagicMock()
|
||||
|
||||
self.chargen.apply(character)
|
||||
|
||||
self.assertTrue(character.db.desc.startswith("Herbalist"))
|
||||
self.assertEqual(character.armor, "gambeson")
|
||||
|
||||
character.equipment.add.assert_called()
|
||||
|
||||
|
||||
class EvAdventureEquipmentTest(EvAdventureMixin, BaseEvenniaTest):
|
||||
"""
|
||||
Test the equipment mechanism.
|
||||
|
||||
"""
|
||||
|
||||
def _get_empty_slots(self):
|
||||
return {
|
||||
enums.WieldLocation.BACKPACK: [],
|
||||
enums.WieldLocation.WEAPON_HAND: None,
|
||||
enums.WieldLocation.SHIELD_HAND: None,
|
||||
enums.WieldLocation.TWO_HANDS: None,
|
||||
enums.WieldLocation.BODY: None,
|
||||
enums.WieldLocation.HEAD: None,
|
||||
}
|
||||
|
||||
def test_equipmenthandler_max_slots(self):
|
||||
self.assertEqual(self.character.equipment.max_slots, 11)
|
||||
|
||||
@parameterized.expand(
|
||||
[
|
||||
# size, pass_validation?
|
||||
(1, True),
|
||||
(2, True),
|
||||
(11, True),
|
||||
(12, False),
|
||||
(20, False),
|
||||
(25, False),
|
||||
]
|
||||
)
|
||||
def test_validate_slot_usage(self, size, is_ok):
|
||||
obj = MagicMock()
|
||||
obj.size = size
|
||||
|
||||
if is_ok:
|
||||
self.assertTrue(self.character.equipment.validate_slot_usage(obj))
|
||||
else:
|
||||
with self.assertRaises(equipment.EquipmentError):
|
||||
self.character.equipment.validate_slot_usage(obj)
|
||||
|
||||
@parameterized.expand(
|
||||
[
|
||||
# item, where
|
||||
("helmet", enums.WieldLocation.HEAD),
|
||||
("shield", enums.WieldLocation.SHIELD_HAND),
|
||||
("armor", enums.WieldLocation.BODY),
|
||||
("weapon", enums.WieldLocation.WEAPON_HAND),
|
||||
("big_weapon", enums.WieldLocation.TWO_HANDS),
|
||||
("item", enums.WieldLocation.BACKPACK),
|
||||
]
|
||||
)
|
||||
def test_use(self, itemname, where):
|
||||
self.assertEqual(self.character.equipment.slots, self._get_empty_slots())
|
||||
|
||||
obj = getattr(self, itemname)
|
||||
self.character.equipment.use(obj)
|
||||
# check that item ended up in the right place
|
||||
if where is enums.WieldLocation.BACKPACK:
|
||||
self.assertTrue(obj in self.character.equipment.slots[where])
|
||||
else:
|
||||
self.assertEqual(self.character.equipment.slots[where], obj)
|
||||
|
||||
def test_add(self):
|
||||
self.character.equipment.add(self.weapon)
|
||||
self.assertEqual(self.character.equipment.slots[enums.WieldLocation.WEAPON_HAND], None)
|
||||
self.assertTrue(self.weapon in self.character.equipment.slots[enums.WieldLocation.BACKPACK])
|
||||
|
||||
def test_two_handed_exclusive(self):
|
||||
"""Two-handed weapons can't be used together with weapon+shield"""
|
||||
self.character.equipment.use(self.big_weapon)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.TWO_HANDS], self.big_weapon
|
||||
)
|
||||
# equipping sword or shield removes two-hander
|
||||
self.character.equipment.use(self.shield)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.SHIELD_HAND], self.shield
|
||||
)
|
||||
self.assertEqual(self.character.equipment.slots[enums.WieldLocation.TWO_HANDS], None)
|
||||
self.character.equipment.use(self.weapon)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.WEAPON_HAND], self.weapon
|
||||
)
|
||||
|
||||
# the two-hander removes the two weapons
|
||||
self.character.equipment.use(self.big_weapon)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.TWO_HANDS], self.big_weapon
|
||||
)
|
||||
self.assertEqual(self.character.equipment.slots[enums.WieldLocation.SHIELD_HAND], None)
|
||||
self.assertEqual(self.character.equipment.slots[enums.WieldLocation.WEAPON_HAND], None)
|
||||
|
||||
def test_remove__with_obj(self):
|
||||
self.character.equipment.use(self.shield)
|
||||
self.character.equipment.use(self.item)
|
||||
self.character.equipment.add(self.weapon)
|
||||
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.SHIELD_HAND], self.shield
|
||||
)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.BACKPACK], [self.item, self.weapon]
|
||||
)
|
||||
|
||||
self.assertEqual(self.character.equipment.remove(self.shield), [self.shield])
|
||||
self.assertEqual(self.character.equipment.remove(self.item), [self.item])
|
||||
|
||||
self.assertEqual(self.character.equipment.slots[enums.WieldLocation.SHIELD_HAND], None)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.BACKPACK], [self.weapon]
|
||||
)
|
||||
|
||||
def test_remove__with_slot(self):
|
||||
self.character.equipment.use(self.shield)
|
||||
self.character.equipment.use(self.item)
|
||||
self.character.equipment.add(self.helmet)
|
||||
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.SHIELD_HAND], self.shield
|
||||
)
|
||||
self.assertEqual(
|
||||
self.character.equipment.slots[enums.WieldLocation.BACKPACK], [self.item, self.helmet]
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
self.character.equipment.remove(enums.WieldLocation.SHIELD_HAND), [self.shield]
|
||||
)
|
||||
self.assertEqual(
|
||||
self.character.equipment.remove(enums.WieldLocation.BACKPACK), [self.item, self.helmet]
|
||||
)
|
||||
|
||||
self.assertEqual(self.character.equipment.slots[enums.WieldLocation.SHIELD_HAND], None)
|
||||
self.assertEqual(self.character.equipment.slots[enums.WieldLocation.BACKPACK], [])
|
||||
|
||||
def test_properties(self):
|
||||
self.character.equipment.use(self.armor)
|
||||
self.assertEqual(self.character.equipment.armor, 1)
|
||||
self.character.equipment.use(self.shield)
|
||||
self.assertEqual(self.character.equipment.armor, 2)
|
||||
self.character.equipment.use(self.helmet)
|
||||
self.assertEqual(self.character.equipment.armor, 3)
|
||||
|
||||
self.character.equipment.use(self.weapon)
|
||||
self.assertEqual(self.character.equipment.weapon, self.weapon)
|
||||
self.character.equipment.use(self.big_weapon)
|
||||
self.assertEqual(self.character.equipment.weapon, self.big_weapon)
|
||||
|
|
|
|||
|
|
@ -882,14 +882,18 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
return False
|
||||
# check if source location lets us go
|
||||
try:
|
||||
if not source_location.at_pre_object_leave(self, destination, **kwargs):
|
||||
if source_location and not source_location.at_pre_object_leave(
|
||||
self, destination, **kwargs
|
||||
):
|
||||
return False
|
||||
except Exception as err:
|
||||
logerr(errtxt.format(err="at_pre_object_leave()"), err)
|
||||
return False
|
||||
# check if destination accepts us
|
||||
try:
|
||||
if not self.at_pre_object_receive(self, source_location, **kwargs):
|
||||
if destination and not destination.at_pre_object_receive(
|
||||
self, source_location, **kwargs
|
||||
):
|
||||
return False
|
||||
except Exception as err:
|
||||
logerr(errtxt.format(err="at_pre_object_receive()"), err)
|
||||
|
|
|
|||
|
|
@ -2732,7 +2732,7 @@ _INT2STR_MAP_NOUN = {
|
|||
_INT2STR_MAP_ADJ = {1: "1st", 2: "2nd", 3: "3rd"} # rest is Xth.
|
||||
|
||||
|
||||
def int2str(self, number, adjective=False):
|
||||
def int2str(number, adjective=False):
|
||||
"""
|
||||
Convert a number to an English string for better display; so 1 -> one, 2 -> two etc
|
||||
up until 12, after which it will be '13', '14' etc.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue