evennia.contrib.puzzles

Puzzles System - Provides a typeclass and commands for objects that can be combined (i.e. ‘use’d) to produce new objects.

Evennia contribution - Henddher 2018

A Puzzle is a recipe of what objects (aka parts) must be combined by a player so a new set of objects (aka results) are automatically created.

Consider this simple Puzzle:

orange, mango, yogurt, blender = fruit smoothie

As a Builder:

@create/drop orange @create/drop mango @create/drop yogurt @create/drop blender @create/drop fruit smoothie

@puzzle smoothie, orange, mango, yogurt, blender = fruit smoothie … Puzzle smoothie(#1234) created successfuly.

@destroy/force orange, mango, yogurt, blender, fruit smoothie

@armpuzzle #1234 Part orange is spawned at … Part mango is spawned at … …. Puzzle smoothie(#1234) has been armed successfully

As Player:

use orange, mango, yogurt, blender … Genius, you blended all fruits to create a fruit smoothie!

Details:

Puzzles are created from existing objects. The given objects are introspected to create prototypes for the puzzle parts and results. These prototypes become the puzzle recipe. (See PuzzleRecipe and @puzzle 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 in their respective locations (See @armpuzzle).

A regular player can collect the puzzle parts and combine them (See use command). If player has specified all pieces, the puzzle is considered solved and all its puzzle parts are destroyed while the puzzle results are spawened on their corresponding location.

Installation:

Add the PuzzleSystemCmdSet to all players. Alternatively:

@py self.cmdset.add(‘evennia.contrib.puzzles.PuzzleSystemCmdSet’)

evennia.contrib.puzzles.proto_def(obj, with_tags=True)[source]

Basic properties needed to spawn and compare recipe with candidate part

evennia.contrib.puzzles.maskout_protodef(protodef, mask)[source]

Returns a new protodef after removing protodef values based on mask

class evennia.contrib.puzzles.PuzzleRecipe(*args, **kwargs)[source]

Bases: evennia.scripts.scripts.DefaultScript

Definition of a Puzzle Recipe

save_recipe(puzzle_name, parts, results)[source]
exception DoesNotExist

Bases: evennia.scripts.scripts.DefaultScript.DoesNotExist

exception MultipleObjectsReturned

Bases: evennia.scripts.scripts.DefaultScript.MultipleObjectsReturned

path = 'evennia.contrib.puzzles.PuzzleRecipe'
typename = 'PuzzleRecipe'
class evennia.contrib.puzzles.CmdCreatePuzzleRecipe(**kwargs)[source]

Bases: evennia.commands.default.muxcommand.MuxCommand

Creates a puzzle recipe. A puzzle consists of puzzle-parts that the player can ‘use’ together to create a specified result.

Usage:

@puzzle name,<part1[,part2,…>] = <result1[,result2,…]>

Example

create/drop balloon create/drop glass of water create/drop water balloon @puzzle waterballon,balloon,glass of water = water balloon @del ballon, glass of water, water balloon @armpuzzle #1

Notes: Each part and result are objects that must (temporarily) exist and be placed in their corresponding location in order to create the puzzle. After the creation of the puzzle, these objects are not needed anymore and can be deleted. Components of the puzzle will be re-created by use of the @armpuzzle command later.

key = '@puzzle'
aliases = ['@puzzlerecipe']
locks = 'cmd:perm(puzzle) or perm(Builder)'
help_category = 'puzzles'
confirm = True
default_confirm = 'no'
func()[source]

This is the hook function that actually does all the work. It is called by the cmdhandler right after self.parser() finishes, and so has access to all the variables defined therein.

lock_storage = 'cmd:perm(puzzle) or perm(Builder)'
search_index_entry = {'aliases': '@puzzlerecipe', 'category': 'puzzles', 'key': '@puzzle', 'tags': '', 'text': "\n Creates a puzzle recipe. A puzzle consists of puzzle-parts that\n the player can 'use' together to create a specified result.\n\n Usage:\n @puzzle name,<part1[,part2,...>] = <result1[,result2,...]>\n\n Example:\n create/drop balloon\n create/drop glass of water\n create/drop water balloon\n @puzzle waterballon,balloon,glass of water = water balloon\n @del ballon, glass of water, water balloon\n @armpuzzle #1\n\n Notes:\n Each part and result are objects that must (temporarily) exist and be placed in their\n corresponding location in order to create the puzzle. After the creation of the puzzle,\n these objects are not needed anymore and can be deleted. Components of the puzzle\n will be re-created by use of the `@armpuzzle` command later.\n\n "}
class evennia.contrib.puzzles.CmdEditPuzzle(**kwargs)[source]

Bases: evennia.commands.default.muxcommand.MuxCommand

Edits puzzle properties

Usage:

@puzzleedit[/delete] <#dbref> @puzzleedit <#dbref>/use_success_message = <Custom message> @puzzleedit <#dbref>/use_success_location_message = <Custom message from {caller} producing {result_names}> @puzzleedit <#dbref>/mask = attr1[,attr2,…]> @puzzleedit[/addpart] <#dbref> = <obj[,obj2,…]> @puzzleedit[/delpart] <#dbref> = <obj[,obj2,…]> @puzzleedit[/addresult] <#dbref> = <obj[,obj2,…]> @puzzleedit[/delresult] <#dbref> = <obj[,obj2,…]>

Switches:

addpart - adds parts to the puzzle delpart - removes parts from the puzzle addresult - adds results to the puzzle delresult - removes results from the puzzle delete - deletes the recipe. Existing parts and results aren’t modified

mask - attributes to exclude during matching (e.g. location, desc, etc.) use_success_location_message containing {result_names} and {caller} will

automatically be replaced with correct values. Both are optional.

When removing parts/results, it’s possible to remove all.

key = '@puzzleedit'
locks = 'cmd:perm(puzzleedit) or perm(Builder)'
help_category = 'puzzles'
func()[source]

This is the hook function that actually does all the work. It is called by the cmdhandler right after self.parser() finishes, and so has access to all the variables defined therein.

aliases = []
lock_storage = 'cmd:perm(puzzleedit) or perm(Builder)'
search_index_entry = {'aliases': '', 'category': 'puzzles', 'key': '@puzzleedit', 'tags': '', 'text': "\n Edits puzzle properties\n\n Usage:\n @puzzleedit[/delete] <#dbref>\n @puzzleedit <#dbref>/use_success_message = <Custom message>\n @puzzleedit <#dbref>/use_success_location_message = <Custom message from {caller} producing {result_names}>\n @puzzleedit <#dbref>/mask = attr1[,attr2,...]>\n @puzzleedit[/addpart] <#dbref> = <obj[,obj2,...]>\n @puzzleedit[/delpart] <#dbref> = <obj[,obj2,...]>\n @puzzleedit[/addresult] <#dbref> = <obj[,obj2,...]>\n @puzzleedit[/delresult] <#dbref> = <obj[,obj2,...]>\n\n Switches:\n addpart - adds parts to the puzzle\n delpart - removes parts from the puzzle\n addresult - adds results to the puzzle\n delresult - removes results from the puzzle\n delete - deletes the recipe. Existing parts and results aren't modified\n\n mask - attributes to exclude during matching (e.g. location, desc, etc.)\n use_success_location_message containing {result_names} and {caller} will\n automatically be replaced with correct values. Both are optional.\n\n When removing parts/results, it's possible to remove all.\n\n "}
class evennia.contrib.puzzles.CmdArmPuzzle(**kwargs)[source]

Bases: evennia.commands.default.muxcommand.MuxCommand

Arms a puzzle by spawning all its parts.

Usage:

@armpuzzle <puzzle #dbref>

Notes

Create puzzles with @puzzle; get list of defined puzzles using @lspuzzlerecipes.

key = '@armpuzzle'
locks = 'cmd:perm(armpuzzle) or perm(Builder)'
help_category = 'puzzles'
func()[source]

This is the hook function that actually does all the work. It is called by the cmdhandler right after self.parser() finishes, and so has access to all the variables defined therein.

aliases = []
lock_storage = 'cmd:perm(armpuzzle) or perm(Builder)'
search_index_entry = {'aliases': '', 'category': 'puzzles', 'key': '@armpuzzle', 'tags': '', 'text': '\n Arms a puzzle by spawning all its parts.\n\n Usage:\n @armpuzzle <puzzle #dbref>\n\n Notes:\n Create puzzles with `@puzzle`; get list of\n defined puzzles using `@lspuzzlerecipes`.\n\n '}
class evennia.contrib.puzzles.CmdUsePuzzleParts(**kwargs)[source]

Bases: evennia.commands.default.muxcommand.MuxCommand

Use an object, or a group of objects at once.

Example

You look around you and see a pole, a long string, and a needle.

use pole, long string, needle

Genius! You built a fishing pole.

Usage:

use <obj1> [,obj2,…]

key = 'use'
aliases = ['combine']
locks = 'cmd:pperm(use) or pperm(Player)'
help_category = 'puzzles'
func()[source]

This is the hook function that actually does all the work. It is called by the cmdhandler right after self.parser() finishes, and so has access to all the variables defined therein.

lock_storage = 'cmd:pperm(use) or pperm(Player)'
search_index_entry = {'aliases': 'combine', 'category': 'puzzles', 'key': 'use', 'tags': '', 'text': '\n Use an object, or a group of objects at once.\n\n\n Example:\n You look around you and see a pole, a long string, and a needle.\n\n use pole, long string, needle\n\n Genius! You built a fishing pole.\n\n\n Usage:\n use <obj1> [,obj2,...]\n '}
class evennia.contrib.puzzles.CmdListPuzzleRecipes(**kwargs)[source]

Bases: evennia.commands.default.muxcommand.MuxCommand

Searches for all puzzle recipes

Usage:

@lspuzzlerecipes

key = '@lspuzzlerecipes'
locks = 'cmd:perm(lspuzzlerecipes) or perm(Builder)'
help_category = 'puzzles'
func()[source]

This is the hook function that actually does all the work. It is called by the cmdhandler right after self.parser() finishes, and so has access to all the variables defined therein.

aliases = []
lock_storage = 'cmd:perm(lspuzzlerecipes) or perm(Builder)'
search_index_entry = {'aliases': '', 'category': 'puzzles', 'key': '@lspuzzlerecipes', 'tags': '', 'text': '\n Searches for all puzzle recipes\n\n Usage:\n @lspuzzlerecipes\n '}
class evennia.contrib.puzzles.CmdListArmedPuzzles(**kwargs)[source]

Bases: evennia.commands.default.muxcommand.MuxCommand

Searches for all armed puzzles

Usage:

@lsarmedpuzzles

key = '@lsarmedpuzzles'
locks = 'cmd:perm(lsarmedpuzzles) or perm(Builder)'
help_category = 'puzzles'
func()[source]

This is the hook function that actually does all the work. It is called by the cmdhandler right after self.parser() finishes, and so has access to all the variables defined therein.

aliases = []
lock_storage = 'cmd:perm(lsarmedpuzzles) or perm(Builder)'
search_index_entry = {'aliases': '', 'category': 'puzzles', 'key': '@lsarmedpuzzles', 'tags': '', 'text': '\n Searches for all armed puzzles\n\n Usage:\n @lsarmedpuzzles\n '}
class evennia.contrib.puzzles.PuzzleSystemCmdSet(cmdsetobj=None, key=None)[source]

Bases: evennia.commands.cmdset.CmdSet

CmdSet to create, arm and resolve Puzzles

at_cmdset_creation()[source]

Hook method - this should be overloaded in the inheriting class, and should take care of populating the cmdset by use of self.add().

path = 'evennia.contrib.puzzles.PuzzleSystemCmdSet'