Remove PuzzlePartObject and typeclass dependency
This commit is contained in:
parent
555e8e5ac9
commit
2d7d6a8b78
2 changed files with 90 additions and 48 deletions
|
|
@ -49,8 +49,8 @@ command). Once the recipe is created, all parts and result
|
||||||
can be disposed (i.e. destroyed).
|
can be disposed (i.e. destroyed).
|
||||||
|
|
||||||
At a later time, a Builder or a Script can arm the puzzle
|
At a later time, a Builder or a Script can arm the puzzle
|
||||||
and spawn all puzzle parts (PuzzlePartObject) in their
|
and spawn all puzzle parts in their respective
|
||||||
respective locations (See @armpuzzle).
|
locations (See @armpuzzle).
|
||||||
|
|
||||||
A regular player can collect the puzzle parts and combine
|
A regular player can collect the puzzle parts and combine
|
||||||
them (See use command). If player has specified
|
them (See use command). If player has specified
|
||||||
|
|
@ -101,7 +101,7 @@ def proto_def(obj, with_tags=True):
|
||||||
protodef = {
|
protodef = {
|
||||||
# FIXME: Don't we need to honor ALL properties? attributes, contents, etc.
|
# FIXME: Don't we need to honor ALL properties? attributes, contents, etc.
|
||||||
'key': obj.key,
|
'key': obj.key,
|
||||||
'typeclass': 'evennia.contrib.puzzles.PuzzlePartObject', # FIXME: what if obj is another typeclass
|
'typeclass': obj.typeclass_path,
|
||||||
'desc': obj.db.desc,
|
'desc': obj.db.desc,
|
||||||
'location': obj.location,
|
'location': obj.location,
|
||||||
'home': obj.home,
|
'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):
|
class PuzzleRecipe(DefaultScript):
|
||||||
"""
|
"""
|
||||||
Definition of a Puzzle Recipe
|
Definition of a Puzzle Recipe
|
||||||
|
|
@ -161,12 +147,20 @@ class CmdCreatePuzzleRecipe(MuxCommand):
|
||||||
"""
|
"""
|
||||||
Creates a puzzle recipe.
|
Creates a puzzle recipe.
|
||||||
|
|
||||||
Each part and result must exist and be placed in their corresponding location.
|
Each part and result must exist and be placed in their
|
||||||
All parts and results are left intact. Caller must explicitly
|
corresponding location.
|
||||||
destroy them.
|
|
||||||
|
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:
|
Usage:
|
||||||
@puzzle name,<part1[,part2,...>] = <result1[,result2,...]>
|
@puzzle[/arm] name,<part1[,part2,...>] = <result1[,result2,...]>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = '@puzzle'
|
key = '@puzzle'
|
||||||
|
|
@ -487,7 +481,8 @@ class CmdArmPuzzle(MuxCommand):
|
||||||
for proto_part in puzzle.db.parts:
|
for proto_part in puzzle.db.parts:
|
||||||
part = spawn(proto_part)[0]
|
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))
|
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.")
|
caller.msg("Puzzle armed |gsuccessfully|n.")
|
||||||
|
|
||||||
|
|
@ -536,8 +531,7 @@ class CmdUsePuzzleParts(MuxCommand):
|
||||||
if not part:
|
if not part:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not part.tags.get(_PUZZLES_TAG_MEMBER, category=_PUZZLES_TAG_CATEGORY) \
|
if not part.tags.get(_PUZZLES_TAG_MEMBER, category=_PUZZLES_TAG_CATEGORY):
|
||||||
or not inherits_from(part, PuzzlePartObject):
|
|
||||||
|
|
||||||
# not a puzzle part ... abort
|
# not a puzzle part ... abort
|
||||||
caller.msg('You have no idea how %s can be used' % (many))
|
caller.msg('You have no idea how %s can be used' % (many))
|
||||||
|
|
@ -629,7 +623,8 @@ class CmdUsePuzzleParts(MuxCommand):
|
||||||
result_names = []
|
result_names = []
|
||||||
for proto_result in puzzle.db.results:
|
for proto_result in puzzle.db.results:
|
||||||
result = spawn(proto_result)[0]
|
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)
|
result_names.append(result.name)
|
||||||
# FIXME: add 'ramdon' messages:
|
# FIXME: add 'ramdon' messages:
|
||||||
# Hmmm ... did I search result.location?
|
# Hmmm ... did I search result.location?
|
||||||
|
|
|
||||||
|
|
@ -1183,9 +1183,15 @@ class TestPuzzles(CommandTest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestPuzzles, self).setUp()
|
super(TestPuzzles, self).setUp()
|
||||||
self.stone = create_object(key='stone', location=self.char1.location)
|
self.stone = create_object(
|
||||||
self.flint = create_object(key='flint', location=self.char1.location)
|
self.object_typeclass,
|
||||||
self.fire = create_object(key='fire', location=self.char1.location)
|
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')
|
||||||
self.stone.tags.add('tag-stone', category='tagcat')
|
self.stone.tags.add('tag-stone', category='tagcat')
|
||||||
self.flint.tags.add('tag-flint')
|
self.flint.tags.add('tag-flint')
|
||||||
|
|
@ -1397,7 +1403,10 @@ class TestPuzzles(CommandTest):
|
||||||
self.assertEqual(1,
|
self.assertEqual(1,
|
||||||
len(list(filter(
|
len(list(filter(
|
||||||
lambda o: o.key == 'fire' \
|
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.room1.contents))))
|
||||||
self._check_room_contents({'stone': 0, 'flint': 0, 'fire': 1}, check_test_tags=True)
|
self._check_room_contents({'stone': 0, 'flint': 0, 'fire': 1}, check_test_tags=True)
|
||||||
|
|
||||||
|
|
@ -1494,15 +1503,21 @@ class TestPuzzles(CommandTest):
|
||||||
caller=self.char1
|
caller=self.char1
|
||||||
)
|
)
|
||||||
|
|
||||||
red_stone = create_object(key='red stone', location=self.char1.location)
|
red_stone = create_object(
|
||||||
smoke = create_object(key='smoke', location=self.char1.location)
|
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('/addresult', recipe_dbref, ['smoke'], 'smoke were added to results')
|
||||||
_puzzleedit('/addpart', recipe_dbref, ['red stone', 'stone'], 'red stone, stone were added to parts')
|
_puzzleedit('/addpart', recipe_dbref, ['red stone', 'stone'], 'red stone, stone were added to parts')
|
||||||
|
|
||||||
# create a box so we can put all objects in
|
# create a box so we can put all objects in
|
||||||
# so that they can't be found during puzzle resolution
|
# 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():
|
def _box_all():
|
||||||
for o in self.room1.contents:
|
for o in self.room1.contents:
|
||||||
if o not in [self.char1, self.char2, self.exit,
|
if o not in [self.char1, self.char2, self.exit,
|
||||||
|
|
@ -1634,12 +1649,24 @@ class TestPuzzles(CommandTest):
|
||||||
|
|
||||||
# parts don't survive resolution
|
# parts don't survive resolution
|
||||||
# but produce a large result set
|
# but produce a large result set
|
||||||
tree = create_object(key='tree', location=self.char1.location)
|
tree = create_object(
|
||||||
axe = create_object(key='axe', location=self.char1.location)
|
self.object_typeclass,
|
||||||
sweat = create_object(key='sweat', location=self.char1.location)
|
key='tree', location=self.char1.location)
|
||||||
dull_axe = create_object(key='dull axe', location=self.char1.location)
|
axe = create_object(
|
||||||
timber = create_object(key='timber', location=self.char1.location)
|
self.object_typeclass,
|
||||||
log = create_object(key='log', location=self.char1.location)
|
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']
|
parts = ['tree', 'axe']
|
||||||
results = (['sweat'] * 10) + ['dull axe'] + (['timber'] * 20) + (['log'] * 50)
|
results = (['sweat'] * 10) + ['dull axe'] + (['timber'] * 20) + (['log'] * 50)
|
||||||
recipe_dbref = self._good_recipe(
|
recipe_dbref = self._good_recipe(
|
||||||
|
|
@ -1666,9 +1693,15 @@ class TestPuzzles(CommandTest):
|
||||||
# parts also appear in results
|
# parts also appear in results
|
||||||
# causing a new puzzle to be armed 'automatically'
|
# causing a new puzzle to be armed 'automatically'
|
||||||
# i.e. the puzzle is self-sustaining
|
# i.e. the puzzle is self-sustaining
|
||||||
hole = create_object(key='hole', location=self.char1.location)
|
hole = create_object(
|
||||||
shovel = create_object(key='shovel', location=self.char1.location)
|
self.object_typeclass,
|
||||||
dirt = create_object(key='dirt', location=self.char1.location)
|
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']
|
parts = ['shovel', 'hole']
|
||||||
results = ['dirt', 'hole', 'shovel']
|
results = ['dirt', 'hole', 'shovel']
|
||||||
|
|
@ -1706,12 +1739,24 @@ class TestPuzzles(CommandTest):
|
||||||
|
|
||||||
def test_e2e_interchangeable_parts_and_results(self):
|
def test_e2e_interchangeable_parts_and_results(self):
|
||||||
# Parts and Results can be used in multiple puzzles
|
# Parts and Results can be used in multiple puzzles
|
||||||
egg = create_object(key='egg', location=self.char1.location)
|
egg = create_object(
|
||||||
flour = create_object(key='flour', location=self.char1.location)
|
self.object_typeclass,
|
||||||
boiling_water = create_object(key='boiling water', location=self.char1.location)
|
key='egg', location=self.char1.location)
|
||||||
boiled_egg = create_object(key='boiled egg', location=self.char1.location)
|
flour = create_object(
|
||||||
dough = create_object(key='dough', location=self.char1.location)
|
self.object_typeclass,
|
||||||
pasta = create_object(key='pasta', location=self.char1.location)
|
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:
|
# Three recipes:
|
||||||
# 1. breakfast: egg + boiling water = boiled egg & boiling water
|
# 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
|
# create a box so we can put all objects in
|
||||||
# so that they can't be found during puzzle resolution
|
# 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():
|
def _box_all():
|
||||||
# print "boxing all\n", "-"*20
|
# print "boxing all\n", "-"*20
|
||||||
for o in self.room1.contents:
|
for o in self.room1.contents:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue