Remove PuzzlePartObject and typeclass dependency

This commit is contained in:
Henddher Pedroza 2018-10-02 15:17:15 +01:00
parent 2700b4409e
commit e92e830f87
2 changed files with 90 additions and 48 deletions

View file

@ -49,8 +49,8 @@ command). Once the recipe is created, all parts and result
can be disposed (i.e. destroyed).
At a later time, a Builder or a Script can arm the puzzle
and spawn all puzzle parts (PuzzlePartObject) in their
respective locations (See @armpuzzle).
and spawn all puzzle parts in their respective
locations (See @armpuzzle).
A regular player can collect the puzzle parts and combine
them (See use command). If player has specified
@ -101,7 +101,7 @@ def proto_def(obj, with_tags=True):
protodef = {
# FIXME: Don't we need to honor ALL properties? attributes, contents, etc.
'key': obj.key,
'typeclass': 'evennia.contrib.puzzles.PuzzlePartObject', # FIXME: what if obj is another typeclass
'typeclass': obj.typeclass_path,
'desc': obj.db.desc,
'location': obj.location,
'home': obj.home,
@ -129,20 +129,6 @@ _PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE = _colorize_message(_PUZZLE_DEFAULT_SUCCESS_
# ------------------------------------------
class PuzzlePartObject(DefaultObject):
"""
Puzzle Part, typically used by @armpuzzle command
"""
def mark_as_puzzle_member(self, puzzle_name):
"""
Marks this object as a member of puzzle named
'puzzle_name'
"""
self.db.puzzle_name = puzzle_name
self.tags.add(puzzle_name, category=_PUZZLES_TAG_CATEGORY)
class PuzzleRecipe(DefaultScript):
"""
Definition of a Puzzle Recipe
@ -161,12 +147,20 @@ class CmdCreatePuzzleRecipe(MuxCommand):
"""
Creates a puzzle recipe.
Each part and result must exist and be placed in their corresponding location.
All parts and results are left intact. Caller must explicitly
destroy them.
Each part and result must exist and be placed in their
corresponding location.
They are all left intact and Caller should explicitly destroy
them. If the /arm switch is used, the specified objects become
puzzle parts ready to be combined and spawn a new result.
Switches:
arm - the specified objects become puzzle parts as if the puzzle
had been armed explicitly. The results are left intact so
they must be explicitly destroyed.
Usage:
@puzzle name,<part1[,part2,...>] = <result1[,result2,...]>
@puzzle[/arm] name,<part1[,part2,...>] = <result1[,result2,...]>
"""
key = '@puzzle'
@ -487,7 +481,8 @@ class CmdArmPuzzle(MuxCommand):
for proto_part in puzzle.db.parts:
part = spawn(proto_part)[0]
caller.msg("Part %s(%s) spawned and placed at %s(%s)" % (part.name, part.dbref, part.location, part.location.dbref))
part.mark_as_puzzle_member(puzzle.db.puzzle_name)
part.tags.add(puzzle.db.puzzle_name, category=_PUZZLES_TAG_CATEGORY)
part.db.puzzle_name = puzzle.db.puzzle_name
caller.msg("Puzzle armed |gsuccessfully|n.")
@ -536,8 +531,7 @@ class CmdUsePuzzleParts(MuxCommand):
if not part:
return
if not part.tags.get(_PUZZLES_TAG_MEMBER, category=_PUZZLES_TAG_CATEGORY) \
or not inherits_from(part, PuzzlePartObject):
if not part.tags.get(_PUZZLES_TAG_MEMBER, category=_PUZZLES_TAG_CATEGORY):
# not a puzzle part ... abort
caller.msg('You have no idea how %s can be used' % (many))
@ -629,7 +623,8 @@ class CmdUsePuzzleParts(MuxCommand):
result_names = []
for proto_result in puzzle.db.results:
result = spawn(proto_result)[0]
result.mark_as_puzzle_member(puzzle.db.puzzle_name)
result.tags.add(puzzle.db.puzzle_name, category=_PUZZLES_TAG_CATEGORY)
result.db.puzzle_name = puzzle.db.puzzle_name
result_names.append(result.name)
# FIXME: add 'ramdon' messages:
# Hmmm ... did I search result.location?

View file

@ -1183,9 +1183,15 @@ class TestPuzzles(CommandTest):
def setUp(self):
super(TestPuzzles, self).setUp()
self.stone = create_object(key='stone', location=self.char1.location)
self.flint = create_object(key='flint', location=self.char1.location)
self.fire = create_object(key='fire', location=self.char1.location)
self.stone = create_object(
self.object_typeclass,
key='stone', location=self.char1.location)
self.flint = create_object(
self.object_typeclass,
key='flint', location=self.char1.location)
self.fire = create_object(
self.object_typeclass,
key='fire', location=self.char1.location)
self.stone.tags.add('tag-stone')
self.stone.tags.add('tag-stone', category='tagcat')
self.flint.tags.add('tag-flint')
@ -1397,7 +1403,10 @@ class TestPuzzles(CommandTest):
self.assertEqual(1,
len(list(filter(
lambda o: o.key == 'fire' \
and inherits_from(o,'evennia.contrib.puzzles.PuzzlePartObject'),
and ('makefire', puzzles._PUZZLES_TAG_CATEGORY) \
in o.tags.all(return_key_and_category=True) \
and (puzzles._PUZZLES_TAG_MEMBER, puzzles._PUZZLES_TAG_CATEGORY) \
in o.tags.all(return_key_and_category=True),
self.room1.contents))))
self._check_room_contents({'stone': 0, 'flint': 0, 'fire': 1}, check_test_tags=True)
@ -1494,15 +1503,21 @@ class TestPuzzles(CommandTest):
caller=self.char1
)
red_stone = create_object(key='red stone', location=self.char1.location)
smoke = create_object(key='smoke', location=self.char1.location)
red_stone = create_object(
self.object_typeclass,
key='red stone', location=self.char1.location)
smoke = create_object(
self.object_typeclass,
key='smoke', location=self.char1.location)
_puzzleedit('/addresult', recipe_dbref, ['smoke'], 'smoke were added to results')
_puzzleedit('/addpart', recipe_dbref, ['red stone', 'stone'], 'red stone, stone were added to parts')
# create a box so we can put all objects in
# so that they can't be found during puzzle resolution
self.box = create_object(key='box', location=self.char1.location)
self.box = create_object(
self.object_typeclass,
key='box', location=self.char1.location)
def _box_all():
for o in self.room1.contents:
if o not in [self.char1, self.char2, self.exit,
@ -1634,12 +1649,24 @@ class TestPuzzles(CommandTest):
# parts don't survive resolution
# but produce a large result set
tree = create_object(key='tree', location=self.char1.location)
axe = create_object(key='axe', location=self.char1.location)
sweat = create_object(key='sweat', location=self.char1.location)
dull_axe = create_object(key='dull axe', location=self.char1.location)
timber = create_object(key='timber', location=self.char1.location)
log = create_object(key='log', location=self.char1.location)
tree = create_object(
self.object_typeclass,
key='tree', location=self.char1.location)
axe = create_object(
self.object_typeclass,
key='axe', location=self.char1.location)
sweat = create_object(
self.object_typeclass,
key='sweat', location=self.char1.location)
dull_axe = create_object(
self.object_typeclass,
key='dull axe', location=self.char1.location)
timber = create_object(
self.object_typeclass,
key='timber', location=self.char1.location)
log = create_object(
self.object_typeclass,
key='log', location=self.char1.location)
parts = ['tree', 'axe']
results = (['sweat'] * 10) + ['dull axe'] + (['timber'] * 20) + (['log'] * 50)
recipe_dbref = self._good_recipe(
@ -1666,9 +1693,15 @@ class TestPuzzles(CommandTest):
# parts also appear in results
# causing a new puzzle to be armed 'automatically'
# i.e. the puzzle is self-sustaining
hole = create_object(key='hole', location=self.char1.location)
shovel = create_object(key='shovel', location=self.char1.location)
dirt = create_object(key='dirt', location=self.char1.location)
hole = create_object(
self.object_typeclass,
key='hole', location=self.char1.location)
shovel = create_object(
self.object_typeclass,
key='shovel', location=self.char1.location)
dirt = create_object(
self.object_typeclass,
key='dirt', location=self.char1.location)
parts = ['shovel', 'hole']
results = ['dirt', 'hole', 'shovel']
@ -1706,12 +1739,24 @@ class TestPuzzles(CommandTest):
def test_e2e_interchangeable_parts_and_results(self):
# Parts and Results can be used in multiple puzzles
egg = create_object(key='egg', location=self.char1.location)
flour = create_object(key='flour', location=self.char1.location)
boiling_water = create_object(key='boiling water', location=self.char1.location)
boiled_egg = create_object(key='boiled egg', location=self.char1.location)
dough = create_object(key='dough', location=self.char1.location)
pasta = create_object(key='pasta', location=self.char1.location)
egg = create_object(
self.object_typeclass,
key='egg', location=self.char1.location)
flour = create_object(
self.object_typeclass,
key='flour', location=self.char1.location)
boiling_water = create_object(
self.object_typeclass,
key='boiling water', location=self.char1.location)
boiled_egg = create_object(
self.object_typeclass,
key='boiled egg', location=self.char1.location)
dough = create_object(
self.object_typeclass,
key='dough', location=self.char1.location)
pasta = create_object(
self.object_typeclass,
key='pasta', location=self.char1.location)
# Three recipes:
# 1. breakfast: egg + boiling water = boiled egg & boiling water
@ -1755,7 +1800,9 @@ class TestPuzzles(CommandTest):
# create a box so we can put all objects in
# so that they can't be found during puzzle resolution
self.box = create_object(key='box', location=self.char1.location)
self.box = create_object(
self.object_typeclass,
key='box', location=self.char1.location)
def _box_all():
# print "boxing all\n", "-"*20
for o in self.room1.contents: