# evennia.contrib.game_systems.puzzles.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.

Installation:

Add the PuzzleSystemCmdSet to all players (e.g. in their Character typeclass).

Alternatively:

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

Usage:

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.

`evennia.contrib.game_systems.puzzles.puzzles.``proto_def`(obj, with_tags=True)

  Basic properties needed to spawn and compare recipe with candidate part

`evennia.contrib.game_systems.puzzles.puzzles.``maskout_protodef`(protodef, mask)

  Returns a new protodef after removing protodef values based on mask

class `evennia.contrib.game_systems.puzzles.puzzles.``PuzzleRecipe`(*args, **kwargs)

  Bases: `evennia.scripts.scripts.DefaultScript`

  Definition of a Puzzle Recipe

  `save_recipe`(puzzle_name, parts, results)
  exception `DoesNotExist`

    Bases: `evennia.scripts.scripts.DefaultScript.DoesNotExist`

  exception `MultipleObjectsReturned`

    Bases: `evennia.scripts.scripts.DefaultScript.MultipleObjectsReturned`

  `path` = 'evennia.contrib.game_systems.puzzles.puzzles.PuzzleRecipe'
  `typename` = 'PuzzleRecipe'

class `evennia.contrib.game_systems.puzzles.puzzles.``CmdCreatePuzzleRecipe`(**kwargs)

  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`()

    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', 'no_prefix': 'puzzle puzzlerecipe', '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.game_systems.puzzles.puzzles.``CmdEditPuzzle`(**kwargs)

  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`()

    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', 'no_prefix': '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.game_systems.puzzles.puzzles.``CmdArmPuzzle`(**kwargs)

  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`()

    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', 'no_prefix': '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.game_systems.puzzles.puzzles.``CmdUsePuzzleParts`(**kwargs)

  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`()

    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', 'no_prefix': ' combine', '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.game_systems.puzzles.puzzles.``CmdListPuzzleRecipes`(**kwargs)

  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`()

    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', 'no_prefix': 'lspuzzlerecipes ', 'tags': '', 'text': '\n Searches for all puzzle recipes\n\n Usage:\n @lspuzzlerecipes\n '}

class `evennia.contrib.game_systems.puzzles.puzzles.``CmdListArmedPuzzles`(**kwargs)

  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`()

    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', 'no_prefix': 'lsarmedpuzzles ', 'tags': '', 'text': '\n Searches for all armed puzzles\n\n Usage:\n @lsarmedpuzzles\n '}

class `evennia.contrib.game_systems.puzzles.puzzles.``PuzzleSystemCmdSet`(cmdsetobj=None, key=None)

  Bases: `evennia.commands.cmdset.CmdSet`

  CmdSet to create, arm and resolve Puzzles

  `at_cmdset_creation`()

    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.game_systems.puzzles.puzzles.PuzzleSystemCmdSet'