diff --git a/evennia/contrib/barter.py b/evennia/contrib/barter.py index 1fd5a51f76..9430501fef 100644 --- a/evennia/contrib/barter.py +++ b/evennia/contrib/barter.py @@ -104,7 +104,9 @@ class TradeTimeout(DefaultScript): This times out the trade request, in case player B did not reply in time. """ def at_script_creation(self): - "called when script is first created" + """ + Called when script is first created + """ self.key = "trade_request_timeout" self.desc = "times out trade requests" self.interval = TRADE_TIMEOUT @@ -113,13 +115,17 @@ class TradeTimeout(DefaultScript): self.persistent = False def at_repeat(self): - "called once" + """ + called once + """ if self.ndb.tradeevent: self.obj.ndb.tradeevent.finish(force=True) self.obj.msg("Trade request timed out.") def is_valid(self): - "Only valid if the trade has not yet started" + """ + Only valid if the trade has not yet started + """ return self.obj.ndb.tradeevent and not self.obj.ndb.tradeevent.trade_started @@ -130,12 +136,19 @@ class TradeHandler(object): """ def __init__(self, partA, partB): """ - Initializes the trade. This is called when part A tries to initiate - a trade with part B. The trade will not start until part B repeats - this command (B will then call the self.join() command) + Initializes the trade. This is called when part A tries to + initiate a trade with part B. The trade will not start until + part B repeats this command (B will then call the self.join() + command) + + Args: + partA (object): The party trying to start barter. + partB (object): The party asked to barter. + + Notes: + We also store the back-reference from the respective party + to this object. - We also store the back-reference from the respective party to - this object. """ # parties self.partA = partA @@ -152,9 +165,14 @@ class TradeHandler(object): def msg(self, party, string): """ - Relay a message to the other party. This allows - the calling command to not have to worry about - which party they are in the handler. + Relay a message to the other party. This allows the calling + command to not have to worry about which party they are in the + handler. + + Args: + party (object): One of partA or B. The method will figure + out which is which. + string (str): Text to send. """ if self.partA == party: self.partB.msg(string) @@ -165,7 +183,16 @@ class TradeHandler(object): self.party.msg(string) def get_other(self, party): - "Returns the other party of the trade" + """ + Returns the other party of the trade + + Args: + partyX (object): One of the parties of the negotiation + + Returns: + partyY (object): The other party, not partyX. + + """ if self.partA == party: return self.partB if self.partB == party: @@ -175,6 +202,10 @@ class TradeHandler(object): def join(self, partB): """ This is used once B decides to join the trade + + Args: + partB (object): The party accepting the barter. + """ print "join:", self.partB, partB, self.partB == partB, type(self.partB), type(partB) if self.partB == partB: @@ -186,7 +217,11 @@ class TradeHandler(object): def unjoin(self, partB): """ - This is used if B decides not to join the trade + This is used if B decides not to join the trade. + + Args: + partB (object): The party leaving the barter. + """ if self.partB == partB: self.finish() @@ -198,6 +233,11 @@ class TradeHandler(object): Change the current standing offer. We leave it up to the command to do the actual checks that the offer consists of real, valid, objects. + + Args: + party (object): Who is making the offer + args (objects or str): Offerings. + """ if self.trade_started: # reset accept statements whenever an offer changes @@ -212,15 +252,25 @@ class TradeHandler(object): def list(self): """ - Returns two lists of objects on offer, separated by partA/B. + List current offers. + + Returns: + offers (tuple): A tuple with two lists, (A_offers, B_offers). + """ return self.partA_offers, self.partB_offers def search(self, offername): """ - Returns an object on offer, based on a search criterion. - If the search criterion is an integer, treat it as an - index to return in the list of offered items + Search current offers. + + Args: + offername (str or int): Object to search for, or its index in + the list of offered items. + + Returns: + offer (object): An object on offer, based on the search criterion. + """ all_offers = self.partA_offers + self.partB_offers if isinstance(offername, int): @@ -242,7 +292,18 @@ class TradeHandler(object): """ Accept the current offer. - Returns True if this closes the deal, False otherwise + Args: + party (object): The party accepting the deal. + + Returns: + result (object): `True` if this closes the deal, `False` + otherwise + + Notes: + This will only close the deal if both parties have + accepted independently. This is done by calling the + `finish()` method. + """ if self.trade_started: if party == self.partA: @@ -255,9 +316,20 @@ class TradeHandler(object): def decline(self, party): """ - Remove an previously accepted status (changing ones mind) + Decline the offer (or change one's mind). + + Args: + party (object): Party declining the deal. + + Returns: + did_decline (bool): `True` if there was really an + `accepted` status to change, `False` otherwise. + + Notes: + If previously having used the `accept` command, this + function will only work as long as the other party has not + yet accepted. - returns True if there was really a status to change, False otherwise. """ if self.trade_started: if party == self.partA: @@ -276,6 +348,12 @@ class TradeHandler(object): def finish(self, force=False): """ Conclude trade - move all offers and clean up + + Args: + force (bool, optional): Force cleanup regardless of if the + trade was accepted or not (if not, no goods will change + hands but trading will stop anyway) + """ fin = False if self.trade_started and self.partA_accepted and self.partB_accepted: @@ -303,8 +381,8 @@ class TradeHandler(object): class CmdTradeBase(Command): """ - Base command for Trade commands to inherit from. Implements - the custom parsing. + Base command for Trade commands to inherit from. Implements the + custom parsing. """ def parse(self): """ diff --git a/evennia/contrib/chargen.py b/evennia/contrib/chargen.py index 6f470873ed..683edd6c0f 100644 --- a/evennia/contrib/chargen.py +++ b/evennia/contrib/chargen.py @@ -2,9 +2,9 @@ Contribution - Griatch 2011 -[Note - with the advent of MULTISESSION_MODE=2, this is not really -as necessary anymore - the ooclook and @charcreate commands in that -mode replaces this module with better functionality.] +[Note - with the advent of MULTISESSION_MODE=2, this is not really as +necessary anymore - the ooclook and @charcreate commands in that mode +replaces this module with better functionality.] This is a simple character creation commandset. A suggestion is to test this together with menu_login, which doesn't create a Character @@ -18,11 +18,11 @@ while puppeting a Character already before. Installation: -Read the instructions in contrib/examples/cmdset.py in -order to create a new default cmdset module for Evennia to use (copy -the template up one level, and change the settings file's relevant -variables to point to the cmdsets inside). If you already have such -a module you should of course use that. +Read the instructions in contrib/examples/cmdset.py in order to create +a new default cmdset module for Evennia to use (copy the template up +one level, and change the settings file's relevant variables to point +to the cmdsets inside). If you already have such a module you should +of course use that. Next import this module in your custom cmdset module and add the following line to the end of OOCCmdSet's at_cmdset_creation(): diff --git a/evennia/contrib/dice.py b/evennia/contrib/dice.py index 9845e5f965..ce943e0530 100644 --- a/evennia/contrib/dice.py +++ b/evennia/contrib/dice.py @@ -4,8 +4,8 @@ Dice - rolls dice for roleplaying, in-game gambling or GM:ing Evennia contribution - Griatch 2012 -This module implements a full-fledged dice-roller and a 'dice' command to -go with it. It uses standard RPG 'd'-syntax (e.g. 2d6 to roll two +This module implements a full-fledged dice-roller and a 'dice' command +to go with it. It uses standard RPG 'd'-syntax (e.g. 2d6 to roll two six-sided die) and also supports modifiers such as 3d6 + 5. One can also specify a standard Python operator in order to specify @@ -39,31 +39,53 @@ def roll_dice(dicenum, dicetype, modifier=None, conditional=None, return_tuple=F """ This is a standard dice roller. - Input: - dicenum - number of dice to roll (the result to be added) - dicetype - number of sides of the dice to be rolled - modifier - tuple (operator, value), where operator is a character string - with one of +,-,/ or *. The entire result of the dice rolls will - be modified by this value. - conditional - tuple (conditional, value), where conditional is a character - string with one of ==,<,>,>=,<= or !=. - return_tuple - return result as a tuple containing all relevant info - return_tuple - (default False) - return a tuple with all individual roll - results - All input numbers are converted to integers. + Args: + dicenum (int): Number of dice to roll (the result to be added). + dicetype (int): Number of sides of the dice to be rolled. + modifier (tuple): A tuple `(operator, value)`, where operator is + one of `"+"`, `"-"`, `"/"` or `"*"`. The result of the dice + roll(s) will be modified by this value. + conditional (tuple): A tuple `(conditional, value)`, where + conditional is one of `"=="`,`"<"`,`">"`,`">="`,`"<=`" or "`!=`". + This allows the roller to directly return a result depending + on if the conditional was passed or not. + return_tuple (bool): Return a tuple with all individual roll + results or not. Returns: - normally returns the result - if return_tuple=True, returns a tuple (result, outcome, diff, rolls) - In this tuple, outcome and diff will be None if conditional is - not set. rolls is itself a tuple holding all the individual - rolls in the case of multiple die-rolls. + roll_result (int): The result of the roll + modifiers. This is the + default return. + condition_result (bool): A True/False value returned if `conditional` + is set but not `return_tuple`. This effectively hides the result + of the roll. + full_result (tuple): If, return_tuple` is `True`, instead + return a tuple `(result, outcome, diff, rolls)`. Here, + `result` is the normal result of the roll + modifiers. + `outcome` and `diff` are the boolean result of the roll and + absolute difference to the `conditional` input; they will + be will be `None` if `conditional` is not set. `rolls` is + itself a tuple holding all the individual rolls in the case of + multiple die-rolls. Raises: TypeError if non-supported modifiers or conditionals are given. + Notes: + All input numbers are converted to integers. + + Examples: + print roll_dice(2, 6) # 2d6 + <<< 7 + print roll_dice(1, 100, ('+', 5) # 1d100 + 5 + <<< 34 + print roll_dice(1, 20, conditional=('<', 10) # let'say we roll 3 + <<< True + print roll_dice(3, 10, return_tuple=True) + <<< (11, None, None, (2, 5, 4)) + print roll_dice(2, 20, ('-', 2), conditional=('>=', 10), return_tuple=True) + <<< (8, False, 2, (4, 6)) # roll was 4 + 6 - 2 = 8 + """ - dicelimit = 0 # This is the maximum number of dice that can be used in a single roll. dicenum = int(dicenum) dicetype = int(dicetype) @@ -90,7 +112,10 @@ def roll_dice(dicenum, dicetype, modifier=None, conditional=None, return_tuple=F if return_tuple: return (result, outcome, diff, rolls) else: - return result + if conditional: + return outcome + else: + return result RE_PARTS = re.compile(r"(d|\+|-|/|\*|<|>|<=|>=|!=|==)") RE_MOD = re.compile(r"(\+|-|/|\*)") diff --git a/evennia/contrib/extended_room.py b/evennia/contrib/extended_room.py index 7f51e9cd51..5c1544fefa 100644 --- a/evennia/contrib/extended_room.py +++ b/evennia/contrib/extended_room.py @@ -158,8 +158,16 @@ class ExtendedRoom(DefaultRoom): def replace_timeslots(self, raw_desc, curr_time): """ - Filter so that only time markers `...` of the - correct timeslot remains in the description. + Filter so that only time markers `...` of + the correct timeslot remains in the description. + + Args: + raw_desc (str): The unmodified description. + curr_time (str): A timeslot identifier. + + Returns: + description (str): A possibly moified description. + """ if raw_desc: regextuple = REGEXMAP[curr_time] @@ -171,14 +179,24 @@ class ExtendedRoom(DefaultRoom): def return_detail(self, key): """ - This will attempt to match a "detail" to look for in the room. A detail - is a way to offer more things to look at in a room without having to - add new objects. For this to work, we require a custom `look` command that - allows for `look ` - the look command should defer to this - method on the current location (if it exists) before giving up on - finding the target. + This will attempt to match a "detail" to look for in the room. - Details are not season-sensitive, but are parsed for timeslot markers. + Args: + key (str): A detail identifier. + + Returns: + detail (str or None): A detail mathing the given key. + + Notes: + A detail is a way to offer more things to look at in a room + without having to add new objects. For this to work, we + require a custom `look` command that allows for `look + ` - the look command should defer to this method on + the current location (if it exists) before giving up on + finding the target. + + Details are not season-sensitive, but are parsed for timeslot + markers. """ try: detail = self.db.details.get(key.lower(), None) @@ -192,7 +210,17 @@ class ExtendedRoom(DefaultRoom): return None def return_appearance(self, looker): - "This is called when e.g. the look command wants to retrieve the description of this object." + """ + This is called when e.g. the look command wants to retrieve + the description of this object. + + Args: + looker (Object): The object looking at us. + + Returns: + description (str): Our description. + + """ raw_desc = self.db.raw_desc or "" update = False diff --git a/evennia/contrib/gendersub.py b/evennia/contrib/gendersub.py index 6b21fb2ebd..0d137ee082 100644 --- a/evennia/contrib/gendersub.py +++ b/evennia/contrib/gendersub.py @@ -8,8 +8,8 @@ insert custom markers in their text to indicate gender-aware messaging. It relies on a modified msg() and is meant as an inspiration and starting point to how to do stuff like this. -When in use, all messages being sent to the character will make use -of the character's gender, for example the echo +When in use, all messages being sent to the character will make use of +the character's gender, for example the echo ``` char.msg("%s falls on {p face with a thud." % char.key) diff --git a/evennia/contrib/menu_login.py b/evennia/contrib/menu_login.py index 1355345552..4bcc491338 100644 --- a/evennia/contrib/menu_login.py +++ b/evennia/contrib/menu_login.py @@ -19,8 +19,10 @@ CMDSET_UNLOGGEDIN = "contrib.menu_login.UnloggedInCmdSet" That's it. Reload the server and try to log in to see it. -The initial login "graphic" is taken from strings in the module given -by settings.CONNECTION_SCREEN_MODULE. +You will want to change the login "graphic", which defaults to give +information about commands which are not used in this version of the +login. You can change the screen used by editing +`mygame/server/conf/connection_screens.py`. """ diff --git a/evennia/contrib/menusystem.py b/evennia/contrib/menusystem.py index f40db50b84..cfeaeffa36 100644 --- a/evennia/contrib/menusystem.py +++ b/evennia/contrib/menusystem.py @@ -11,14 +11,29 @@ in one or more columns. The menu system consists of a MenuTree object populated by MenuNode objects. Nodes are linked together with automatically created commands so the player may select and traverse the menu. Each node can display -text and show options, but also execute arbitrary code to act on the +text and show options, but also execute a callback to act on the system and the calling object when they are selected. -There is also a simple Yes/No function supplied. This will create a -one-off Yes/No question and executes a given code depending on which -choice was made. +There is also a simple Yes/No function as well as a one-level choice +function supplied. This will create a one-off Yes/No question or a +one-level choice. These helpers will execute a given callback +depending on which choice was made. -To test, add this to the default cmdset +To start a menu, define the nodes of the menu and then add the +following to a command `func` you can call: + +```python + +menu = MenuTree(self.caller, nodes=(...)) +menu.start() + +``` + +This will switch you into menu-mode. See `contrib/menu_login.py` for an +example of usage. + + +For a simple demonstration, add `CmdMenuTest` from this module to the default cmdset. """ from types import MethodType @@ -49,8 +64,6 @@ class CmdMenuNode(Command): menutree = None callback = None - # deprecated - code = None def func(self): "Execute a selection" @@ -60,12 +73,6 @@ class CmdMenuNode(Command): self.callback() except Exception, e: self.caller.msg("%s\n{rThere was an error with this selection.{n" % e) - elif self.code: - evennia.logger.log_depmsg("menusystem.code is deprecated. Use menusystem.func.") - try: - exec(self.code) - except Exception, e: - self.caller.msg("%s\n{rThere was an error with this selection.{n" % e) else: self.caller.msg("{rThis option is not available.{n") @@ -173,8 +180,19 @@ class MenuTree(object): enter and where to exit the menu tree. If nodes is given, it should be a list of valid node objects to add to the tree. - exec_end - if not None, will execute the given command string - directly after the menu system has been exited. + caller (Object): The caller triggering the menu + nodes (tuple, optional): A tuple of `MenuNode` objects. This need + not be in any particular order. + startnode (str, optional): The key of the first `MenuNode` to jump + to when starting the menu. Defaults to "START". + endnode (str, optional): The key of the end node. When + instructed to go to this node (by any means), the menu + will be gracefully exited. Defaults to "END". + exec_end (str, optional): If not `None`, this command name will be executed + directly after the menu system has been exited. It is + normally useful for making sure the user realizes their UI + mode has changed. + """ self.tree = {} self.startnode = startnode @@ -187,7 +205,8 @@ class MenuTree(object): def start(self): """ - Initialize the menu + Initialize the menu and go to the starting node. + """ self.goto(self.startnode) @@ -195,6 +214,9 @@ class MenuTree(object): """ Add a menu node object to the tree. Each node itself keeps track of which nodes it is connected to. + + Args: + menunode (MenuNode): The node to add. """ self.tree[menunode.key] = menunode @@ -202,6 +224,10 @@ class MenuTree(object): """ Go to a key in the tree. This sets up the cmdsets on the caller so that they match the choices in that node. + + Args: + key (str): The node-key to go to. + """ if key == self.endnode: # if we was given the END node key, we clean up immediately. @@ -210,7 +236,7 @@ class MenuTree(object): if self.exec_end is not None: self.caller.execute_cmd(self.exec_end) return - # not exiting, look for a valid code. + # not exiting, look for a valid node node = self.tree.get(key, None) # make caller available on node node.caller = self.caller @@ -222,13 +248,6 @@ class MenuTree(object): except Exception: logger.log_trace() self.caller.msg("{rNode callback could not be executed for node %s. Continuing anyway.{n" % key) - if node.code: - # Execute eventual code active on this node. self.caller is available at this point. - evennia.logger.log_depmsg("menusystem.code is deprecated. Use menusystem.callback.") - try: - exec(node.code) - except Exception: - self.caller.msg("{rCode could not be executed for node %s. Continuing anyway.{n" % key) # initialize - this creates new cmdset node.init(self) # clean old menu cmdset and replace with the new one @@ -252,42 +271,48 @@ class MenuNode(object): """ def __init__(self, key, text="", links=None, linktexts=None, keywords=None, cols=1, helptext=None, - selectcmds=None, callback=None, code="", nodefaultcmds=False, separator=""): + selectcmds=None, callback=None, nodefaultcmds=False, separator=""): """ - key - the unique identifier of this node. - text - is the text that will be displayed at top when viewing this - node. - links - a list of keys for unique menunodes this is connected to. - The actual keys will not printed - keywords will be used - (or a number) - linktexts - an optional list of texts to describe the links. Must - match link list if defined. Entries can be None to not - generate any extra text for a particular link. - keywords - an optional list of unique keys for choosing links. Must - match links list. If not given, index numbers will be used. - Also individual list entries can be None and will be replaed - by indices. If CMD_NOMATCH or CMD_NOENTRY, no text will be - generated to indicate the option exists. - cols - how many columns to use for displaying options. - helptext - if defined, this is shown when using the help command - instead of the normal help index. - selectcmds- a list of custom cmdclasses for handling each option. - Must match links list, but some entries may be set to None - to use default menu cmds. The given command's key will be - used for the menu list entry unless it's CMD_NOMATCH or - CMD_NOENTRY, in which case no text will be generated. These - commands have access to self.menutree and so can be used to - select nodes. - code - functional code. Deprecated. This will be executed just before this - node is loaded (i.e. as soon after it's been selected from - another node). self.caller is available to call from this - code block, as well as the evennia flat API. - callback - function callback. This will be called as callback(currentnode) just - before this node is loaded (i.e. as soon as possible as it's - been selected from another node). currentnode.caller is available. - nodefaultcmds - if true, don't offer the default help and look commands - in the node - separator - this string will be put on the line between menu nodes. + Initialize the node. + + Args: + key (str): The unique identifier of this node. + text (str, optional): The text that will be displayed at + top when viewing this node. + Kwargs: + links (list): A liist of keys for unique menunodes this is connected to. + The actual keys will not printed - keywords will be + used (or a number) + linktexts (list)- A list of texts to describe the links. Must + match order of `links` list if defined. Entries can be + None to not generate any extra text for a particular + link. + keywords (list): A list of unique keys for choosing links. Must + match links list. If not given, index numbers will be + used. Also individual list entries can be None and + will be replaed by indices. If CMD_NOMATCH or + CMD_NOENTRY, no text will be generated to indicate the + option exists. + cols (int): How many columns to use for displaying options. + helptext (str): If defined, this is shown when using the help command + instead of the normal help index. + selectcmds (list): A list of custom cmdclasses for + handling each option. Must match links list, but some + entries may be set to None to use default menu cmds. + The given command's key will be used for the menu list + entry unless it's CMD_NOMATCH or CMD_NOENTRY, in which + case no text will be generated. These commands have + access to self.menutree and so can be used to select + nodes. + callback (function): Function callback. This will be + called as callback(currentnode) just before this node is + loaded (i.e. as soon as possible as it's been selected + from another node). currentnode.caller is available. + nodefaultcmds (bool): If `True`, don't offer the default + help and look commands in the node + separator (str): This string will be put on the line + between menu nodes. + """ self.key = key self.cmdset = None @@ -296,15 +321,11 @@ class MenuNode(object): self.keywords = keywords self.cols = cols self.selectcmds = selectcmds - self.code = code self.callback = MethodType(callback, self, MenuNode) if callback else None self.nodefaultcmds = nodefaultcmds self.separator = separator Nlinks = len(self.links) - if code: - evennia.logger.log_depmsg("menusystem.code is deprecated. Use menusystem.callback.") - # validate the input if not self.links: self.links = [] @@ -399,17 +420,21 @@ class MenuNode(object): # make use the node system since there is only one level of choice. # -def prompt_yesno(caller, question="", yesfunc=None, nofunc=None, yescode="", nocode="", default="N"): +def prompt_yesno(caller, question="", yesfunc=None, nofunc=None, default="N"): """ This sets up a simple yes/no questionnaire. Question will be asked, followed by a Y/[N] prompt where the [x] signifies the - default selection. Note that this isn't making use of the menu - node system. + default selection. Note that this isn't actually making use of the + menu node system, but does use the MenuCmdSet. + + Args: + caller (Object): The object triggering the prompt. + question (str, optional): The Yes/No question asked. + yesfunc (function, optional): Callback for a Yes answer. + nofunc (functionm optional): Callback for a No answer. + default (str, optional): Default used if caller just hits + return. Either `"Y"` or `"N"` - yesfunc - function callback to be called as yesfunc(self) when choosing yes (self.caller is available) - nofunc - function callback to be called as yesfunc(self) when choosing no (self.caller is available) - yescode - deprecated, executable code - nocode - " """ # creating and defining commands @@ -441,14 +466,6 @@ def prompt_yesno(caller, question="", yesfunc=None, nofunc=None, yescode="", noc self.caller.execute_cmd('%s' % default) defaultcmd.callback = MethodType(_defaultcmd, defaultcmd, CmdMenuNode) - # code exec is deprecated: - if yescode: - evennia.logger.log_depmsg("yesnosystem.code is deprecated. Use yesnosystem.callback.") - cmdyes.code = yescode + "\nself.caller.cmdset.delete('menucmdset')\ndel self.caller.db._menu_data" - if nocode: - evennia.logger.log_depmsg("yesnosystem.code is deprecated. Use yesnosystem.callback.") - cmdno.code = nocode + "\nself.caller.cmdset.delete('menucmdset')\ndel self.caller.db._menu_data" - # creating cmdset (this will already have look/help commands) yesnocmdset = MenuCmdSet() yesnocmdset.add(cmdyes) @@ -481,33 +498,57 @@ def prompt_choice(caller, question="", prompts=None, choicefunc=None, force_choo """ This sets up a simple choice questionnaire. Question will be asked, followed by a series of prompts. Note that this isn't - making use of the menu node system. + making use of the menu node system but uses the MenuCmdSet. + + Args: + caller (object): The object calling and being offered the choice + question (str, optional): Text describing the offered choice + prompts (list, optional): List of strings defining the available choises. + choicefunc (function, optional): A function called as + `choicefunc(self)` when a choice is made. Inside this function, + `self.caller` is available and `self.prompt_index` is the index + (starting with 0) matching the chosen prompt in the `prompts` list. + force_choose - force user to make a choice + + Examples: + + ```python + def mychoice(self): + self.caller.msg("Index of choice is %s." % self.prompt_index) + + prompt_choice(caller, "Make a choice:", prompts=["A","B","C"], choicefunc=mychoice) + ``` + + When triggering the above from a command or @py prompt you get the following options: + + >>> Make a choice: + [1] A + [2] B + [3] C + <<< 2 + >>> Index of choice is 1. - caller - the object calling and being offered the choice - question - text describing the offered choice - prompts - list of choices - choicefunc - functions callback to be called as func(self) when - make choice (self.caller is available) The function's definition - should be like func(self, menu_node), and menu_node.key is user's - choice. - force_choose - force user to make a choice or not """ # creating and defining commands count = 0 choices = "" commands = [] + for choice in utils.make_iter(prompts): + # create the available choice-commands count += 1 choices += "\n{lc%d{lt[%d]{le %s" % (count, count, choice) cmdfunc = CmdMenuNode(key="%d" % count) + cmdfunc.prompt_index = count-1 if choicefunc: cmdfunc.choicefunc = choicefunc def _choicefunc(self): self.caller.cmdset.delete('menucmdset') del self.caller.db._menu_data self.choicefunc(self) + # set a new method "callback" on cmdfunc cmdfunc.callback = MethodType(_choicefunc, cmdfunc, CmdMenuNode) commands.append(cmdfunc) @@ -517,6 +558,7 @@ def prompt_choice(caller, question="", prompts=None, choicefunc=None, force_choo prompt = question + choices + "\nPlease choose one." + # create the error-reporting command errorcmd = CmdMenuNode(key=CMD_NOMATCH) if force_choose: def _errorcmd(self): @@ -531,6 +573,7 @@ def prompt_choice(caller, question="", prompts=None, choicefunc=None, force_choo self.choicefunc(self) errorcmd.callback = MethodType(_errorcmd, errorcmd, CmdMenuNode) + # create the fallback command defaultcmd = CmdMenuNode(key=CMD_NOINPUT) if force_choose: def _defaultcmd(self): @@ -547,7 +590,8 @@ def prompt_choice(caller, question="", prompts=None, choicefunc=None, force_choo # creating cmdset (this will already have look/help commands) choicecmdset = MenuCmdSet() - for cmdfunc in commands: choicecmdset.add(cmdfunc) + for cmdfunc in commands: + choicecmdset.add(cmdfunc) choicecmdset.add(errorcmd) choicecmdset.add(defaultcmd) choicecmdset.add(CmdMenuLook()) diff --git a/evennia/contrib/talking_npc.py b/evennia/contrib/talking_npc.py index 71858df044..7ba7d17946 100644 --- a/evennia/contrib/talking_npc.py +++ b/evennia/contrib/talking_npc.py @@ -4,22 +4,19 @@ Evennia Talkative NPC Contribution - Griatch 2011 -This is a simple NPC object capable of holding a -simple menu-driven conversation. Create it by -creating an object of typeclass contrib.talking_npc.TalkingNPC, -For example using @create: +This is a simple NPC object capable of holding a simple menu-driven +conversation. Create it by creating an object of typeclass +contrib.talking_npc.TalkingNPC, For example using @create: @create John : contrib.talking_npc.TalkingNPC -Walk up to it and give the talk command -to strike up a conversation. If there are many -talkative npcs in the same room you will get to -choose which one's talk command to call (Evennia -handles this automatically). +Walk up to it and give the talk command to strike up a conversation. +If there are many talkative npcs in the same room you will get to +choose which one's talk command to call (Evennia handles this +automatically). -Note that this is only a prototype class, showcasing -the uses of the menusystem module. It is NOT a full -mob implementation. +Note that this is only a prototype class, showcasing the uses of the +menusystem module. It is NOT a full mob implementation. """ diff --git a/evennia/contrib/tutorial_examples/bodyfunctions.py b/evennia/contrib/tutorial_examples/bodyfunctions.py index 26b3340de5..70bdf6de6f 100644 --- a/evennia/contrib/tutorial_examples/bodyfunctions.py +++ b/evennia/contrib/tutorial_examples/bodyfunctions.py @@ -1,14 +1,12 @@ """ -Example script for testing. This adds a simple timer that -has your character make observations and notices at irregular -intervals. +Example script for testing. This adds a simple timer that has your +character make observations and notices at irregular intervals. To test, use @script me = examples.bodyfunctions.BodyFunctions -The script will only send messages to the object it -is stored on, so make sure to put it on yourself -or you won't see any messages! +The script will only send messages to the object it is stored on, so +make sure to put it on yourself or you won't see any messages! """ import random diff --git a/evennia/contrib/tutorial_examples/red_button.py b/evennia/contrib/tutorial_examples/red_button.py index 2f3d961fd6..3b2402c9a0 100644 --- a/evennia/contrib/tutorial_examples/red_button.py +++ b/evennia/contrib/tutorial_examples/red_button.py @@ -66,6 +66,7 @@ class RedButton(DefaultObject): """ Opens the glass lid and start the timer so it will soon close again. + """ if self.db.lid_open: @@ -91,6 +92,7 @@ class RedButton(DefaultObject): Close the glass lid. This validates all scripts on the button, which means that scripts only being valid when the lid is open will go away automatically. + """ if not self.db.lid_open: @@ -111,6 +113,9 @@ class RedButton(DefaultObject): """ Breaks the lamp in the button, stopping it from blinking. + Args: + feedback (bool): Show a message about breaking the lamp. + """ self.db.lamp_works = False desc = self.db.desc_lamp_broken @@ -126,7 +131,10 @@ class RedButton(DefaultObject): def press_button(self, pobject): """ Someone was foolish enough to press the button! - pobject - the person pressing the button + + Args: + pobject (Object): The person pressing the button + """ # deactivate the button so it won't flash/close lid etc. self.scripts.add(scriptexamples.DeactivateButtonEvent)