Add stack support for object.search
This commit is contained in:
parent
7015b4992d
commit
42612c92a7
4 changed files with 57 additions and 13 deletions
|
|
@ -18,6 +18,8 @@
|
||||||
- Added new Traits contrib, converted and expanded from Ainneve project.
|
- Added new Traits contrib, converted and expanded from Ainneve project.
|
||||||
- Added new `requirements_extra.txt` file for easily getting all optional dependencies.
|
- Added new `requirements_extra.txt` file for easily getting all optional dependencies.
|
||||||
- Change default multimatch syntax from 1-obj, 2-obj to obj-1, obj-2.
|
- Change default multimatch syntax from 1-obj, 2-obj to obj-1, obj-2.
|
||||||
|
- Make `object.search` support 'stacks=0' keyword - if ``>0``, the method will return
|
||||||
|
N identical matches instead of triggering a multi-match error.
|
||||||
|
|
||||||
### Already in master
|
### Already in master
|
||||||
- Renamed Tutorial classes "Weapon" and "WeaponRack" to "TutorialWeapon" and
|
- Renamed Tutorial classes "Weapon" and "WeaponRack" to "TutorialWeapon" and
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ bulletin boards.
|
||||||
#### How will the world be built?
|
#### How will the world be built?
|
||||||
|
|
||||||
There are two main ways to handle this:
|
There are two main ways to handle this:
|
||||||
- Traditionally, from in-game with build-commands: This pretty means builders creating content in their game
|
- Traditionally, from in-game with build-commands: This means builders creating content in their game
|
||||||
client. This has the advantage of not requiring Python skills nor server access. This can often be a quite
|
client. This has the advantage of not requiring Python skills nor server access. This can often be a quite
|
||||||
intuitive way to build since you are sort-of walking around in your creation as you build it. However, the
|
intuitive way to build since you are sort-of walking around in your creation as you build it. However, the
|
||||||
developer (you) must make sure to provide build-commands that are flexible enough for builders to be able to
|
developer (you) must make sure to provide build-commands that are flexible enough for builders to be able to
|
||||||
|
|
@ -119,13 +119,13 @@ code (such as what you can do with the `py` command). You can
|
||||||
it's suggested that this is accomplished by adding more powerful build-commands for them to use.
|
it's suggested that this is accomplished by adding more powerful build-commands for them to use.
|
||||||
|
|
||||||
For our tutorial-game, we will only allow privileged builders to modify the world. The exception is crafting,
|
For our tutorial-game, we will only allow privileged builders to modify the world. The exception is crafting,
|
||||||
where we will allow players to to use in-game commands to create specific, prescribed objects from recipes.
|
which we will limit to repairing broken items by combining them with other repair-related items.
|
||||||
|
|
||||||
### Systems
|
### Systems
|
||||||
|
|
||||||
#### Do you base your game off an existing RPG system or make up your own?
|
#### Do you base your game off an existing RPG system or make up your own?
|
||||||
|
|
||||||
We will make use of [Open Adventure](http://www.geekguild.com/openadventure/), an 'old school' RRG-system
|
We will make use of [Open Adventure](http://www.geekguild.com/openadventure/), a simple 'old school' RPG-system
|
||||||
that is available for free under the Creative Commons license. We'll only use a subset of the rules from
|
that is available for free under the Creative Commons license. We'll only use a subset of the rules from
|
||||||
the blue "basic" book. For the sake of keeping down the length of this tutorial we will limit what features
|
the blue "basic" book. For the sake of keeping down the length of this tutorial we will limit what features
|
||||||
we will include:
|
we will include:
|
||||||
|
|
@ -140,12 +140,11 @@ we will include:
|
||||||
#### What are the game mechanics? How do you decide if an action succeeds or fails?
|
#### What are the game mechanics? How do you decide if an action succeeds or fails?
|
||||||
|
|
||||||
Open Adventure's conflict resolution is based on adding a trait (such as Strength) with a random number in
|
Open Adventure's conflict resolution is based on adding a trait (such as Strength) with a random number in
|
||||||
order beat a target. We will emulate this in code.
|
order to beat a target. We will emulate this in code.
|
||||||
|
|
||||||
There are no pre-set "skills", all resolution is based on using suitable traits in different combinations.
|
Having a "skill" means getting a bonus to that roll for a more narrow action.
|
||||||
The computer can't do this decision on-the-fly like a GM could, so we need to encode what is needed
|
Since the computer will need to know exactly what those skills are, we will add them more explicitly than
|
||||||
to achieve a certain effect - this will be a set of 'skills'. We will only make the minimum amount of skills
|
in the rules, but we will only add the minimum to show off the functionality we need.
|
||||||
needed to accomplish the actions we want to support. This will mean custom Commands.
|
|
||||||
|
|
||||||
#### Does the flow of time matter in your game - does night and day change? What about seasons?
|
#### Does the flow of time matter in your game - does night and day change? What about seasons?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -375,6 +375,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
nofound_string=None,
|
nofound_string=None,
|
||||||
multimatch_string=None,
|
multimatch_string=None,
|
||||||
use_dbref=None,
|
use_dbref=None,
|
||||||
|
stacked=0,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Returns an Object matching a search string/condition
|
Returns an Object matching a search string/condition
|
||||||
|
|
@ -430,10 +431,19 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
will be treated like a normal string. If `None` (default), the ability to query by
|
will be treated like a normal string. If `None` (default), the ability to query by
|
||||||
#dbref is turned on if `self` has the permission 'Builder' and is turned off
|
#dbref is turned on if `self` has the permission 'Builder' and is turned off
|
||||||
otherwise.
|
otherwise.
|
||||||
|
stacked (int, optional): If > 0, multimatches will be analyzed to determine if they
|
||||||
|
only contains identical objects; these are then assumed 'stacked' and no multi-match
|
||||||
|
error will be generated, instead `stacked` number of matches will be returned. If
|
||||||
|
`stacked` is larger than number of matches, returns that number of matches. If
|
||||||
|
the found stack is a mix of objects, return None and handle the multi-match
|
||||||
|
error depending on the value of `quiet`.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
match (Object, None or list): will return an Object/None if `quiet=False`,
|
Object: If finding a match an `quiet=False`
|
||||||
otherwise it will return a list of 0, 1 or more matches.
|
None: If not finding a unique match and `quiet=False`.
|
||||||
|
list: With 0, 1 or more matching objects if `quiet=True`
|
||||||
|
list: With 2 or more matching objects if `stacked` is a positive integer and
|
||||||
|
the matched stack has only object-copies.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
To find Accounts, use eg. `evennia.account_search`. If
|
To find Accounts, use eg. `evennia.account_search`. If
|
||||||
|
|
@ -501,8 +511,29 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
use_dbref=use_dbref,
|
use_dbref=use_dbref,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
nresults = len(results)
|
||||||
|
if stacked > 0 and nresults > 1:
|
||||||
|
# handle stacks, disable multimatch errors
|
||||||
|
nstack = nresults
|
||||||
|
if not exact:
|
||||||
|
# we re-run exact match agains one of the matches to
|
||||||
|
# make sure we were not catching partial matches not belonging
|
||||||
|
# to the stack
|
||||||
|
nstack = len(ObjectDB.objects.get_objs_with_key_or_alias(
|
||||||
|
results[0].key,
|
||||||
|
exact=True,
|
||||||
|
candidates=list(results),
|
||||||
|
typeclasses=[typeclass] if typeclass else None
|
||||||
|
))
|
||||||
|
if nstack == nresults:
|
||||||
|
# a valid stack, return multiple results
|
||||||
|
return list(results)[:stacked]
|
||||||
|
|
||||||
if quiet:
|
if quiet:
|
||||||
|
# don't auto-handle error messaging
|
||||||
return list(results)
|
return list(results)
|
||||||
|
|
||||||
|
# handle error messages
|
||||||
return _AT_SEARCH_RESULT(
|
return _AT_SEARCH_RESULT(
|
||||||
results,
|
results,
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,18 @@ class DefaultObjectTest(EvenniaTest):
|
||||||
self.assertTrue(self.room1.get_absolute_url())
|
self.assertTrue(self.room1.get_absolute_url())
|
||||||
self.assertTrue("admin" in self.room1.web_get_admin_url())
|
self.assertTrue("admin" in self.room1.web_get_admin_url())
|
||||||
|
|
||||||
|
def test_search_stacked(self):
|
||||||
|
"Test searching stacks"
|
||||||
|
coin1 = DefaultObject.create("coin", location=self.room1)[0]
|
||||||
|
coin2 = DefaultObject.create("coin", location=self.room1)[0]
|
||||||
|
colon = DefaultObject.create("colon", location=self.room1)[0]
|
||||||
|
|
||||||
|
# stack
|
||||||
|
self.assertEqual(self.char1.search("coin", stacked=2), [coin1, coin2])
|
||||||
|
self.assertEqual(self.char1.search("coin", stacked=5), [coin1, coin2])
|
||||||
|
# partial match to 'colon' - multimatch error since stack is not homogenous
|
||||||
|
self.assertEqual(self.char1.search("co", stacked=2), None)
|
||||||
|
|
||||||
|
|
||||||
class TestObjectManager(EvenniaTest):
|
class TestObjectManager(EvenniaTest):
|
||||||
"Test object manager methods"
|
"Test object manager methods"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue