예제 #1
0
파일: tests.py 프로젝트: maxsond/evennia
 def test_list_to_string(self):
     self.assertEqual('1, 2, 3', utils.list_to_string([1, 2, 3], endsep=""))
     self.assertEqual(
         '"1", "2", "3"',
         utils.list_to_string([1, 2, 3], endsep="", addquote=True))
     self.assertEqual('1, 2 and 3', utils.list_to_string([1, 2, 3]))
     self.assertEqual(
         '"1", "2" and "3"',
         utils.list_to_string([1, 2, 3], endsep="and", addquote=True))
예제 #2
0
파일: objects.py 프로젝트: dmreichard/evmud
    def return_appearance(self, looker, **kwargs):
        """
        This formats a description. It is the hook a 'look' command
        should call.

        Args:
            looker (Object): Object doing the looking.
            **kwargs (dict): Arbitrary, optional arguments for users
                overriding the call (unused by default).
        """
        if not looker:
            return ""
        # get and identify all objects
        visible = (con for con in self.contents
                   if con != looker and con.access(looker, "view"))
        exits, users, things = [], [], defaultdict(list)
        for con in visible:
            key = con.get_display_name(looker)
            if con.destination:
                exits.append(key)
            elif con.has_account:
                users.append("|c%s|n" % key)
            else:
                # things can be pluralized
                things[key].append(con)
        # get description, build string
        string = "|c%s|n\n" % self.get_display_name(looker)
        desc = self.db.desc
        if desc:
            string += "%s" % desc
        if exits:
            string += "\n|wExits:|n " + list_to_string(exits)
        if users or things:
            # handle pluralization of things (never pluralize users)
            thing_strings = []
            for key, itemlist in sorted(things.items()):
                nitem = len(itemlist)
                if nitem == 1:
                    if itemlist[
                            0].stack.stackable and itemlist[0].stack.count > 1:
                        key = itemlist[0].get_numbered_name(
                            itemlist[0].stack.count, looker, key=key)[1]
                    else:
                        key, _ = itemlist[0].get_numbered_name(nitem,
                                                               looker,
                                                               key=key)
                else:
                    key = [
                        item.get_numbered_name(nitem, looker, key=key)[1]
                        for item in itemlist
                    ][0]
                thing_strings.append(key)

            string += "\n|wYou see:|n " + list_to_string(users + thing_strings)

        return string
예제 #3
0
파일: wiz.py 프로젝트: ChrisLR/scrolls
    def func(self):
        ch = self.caller
        ch.msg(self.args)
        args = self.args.strip()
        zonedb = dict(GLOBAL_SCRIPTS.zonedb.vnum)
        if not zonedb:
            ch.msg("There are no zones within the game")
            return

        vnum_zonedb = zonedb.keys()
        min_ = min(vnum_zonedb)
        max_ = max(vnum_zonedb)

        legend = ["VNum", "Name", "Builders"]
        try:
            _ = zonedb[1]
        except KeyError:
            ch.msg("No zones are saved to database, try creating one first")
            return

        if not args:
            table = self.styled_table(*legend, border='incols')

            for vnum in range(min_, max_ + 1):
                data = zonedb[vnum]
                vnum = raw_ansi(f"[|G{vnum:<4}|n]")
                table.add_row(vnum, data['name'],
                              list_to_string(data['builders']))

            msg = str(table)
            ch.msg(msg)
            return

        args = args.split(' ')
        if len(args) < 2:
            ch.msg("Supply name to search for")
            return
        table = self.styled_table(*legend, border='incols')
        type_ = args[0]
        if type_ not in ('name'):
            ch.msg("Please supply name to search by")
            return

        criteria = args[1]
        for vnum in range(min_, max_ + 1):
            # for vnum, data in GLOBAL_SCRIPTS.objdb.vnum.items():
            data = zonedb[vnum]
            if type_ == 'name':
                if match_string(criteria, data['name'].split()):
                    vnum = raw_ansi(f"[|G{vnum:<4}|n]")
                    table.add_row(vnum, data['name'],
                                  list_to_string(data['builders']))
                    continue
        msg = str(table)
        ch.msg(msg)
        return
예제 #4
0
    def remove(self, wearer, quiet=False):
        """
        Removes worn clothes and optionally echoes to the room.
        
        Args:
            wearer (obj): character object wearing this clothing object
        
        Kwargs:
            quiet (bool): If false, does not message the room
        """
        self.db.worn = False
        remove_message = "%s removes %s." % (wearer, self.name)
        uncovered_list = []

        # Check to see if any other clothes are covered by this object.
        for thing in wearer.contents:
            # If anything is covered by
            if thing.db.covered_by == self:
                thing.db.covered_by = False
                uncovered_list.append(thing.name)
        if len(uncovered_list) > 0:
            remove_message = "%s removes %s, revealing %s." % (wearer, self.name, list_to_string(uncovered_list))
        # Echo a message to the room
        if not quiet:
            wearer.location.msg_contents(remove_message)
예제 #5
0
    def wear(self, wearer, wearstyle, quiet=False):
        """
        Sets clothes to 'worn' and optionally echoes to the room.

        Args:
            wearer (obj): character object wearing this clothing object
            wearstyle (True or str): string describing the style of wear or True for none
            quiet (bool): If false, does not message the room

        Notes:
            Optionally sets db.worn with a 'wearstyle' that appends a short passage to
            the end of the name  of the clothing to describe how it's worn that shows
            up in the wearer's desc - I.E. 'around his neck' or 'tied loosely around
            her waist'. If db.worn is set to 'True' then just the name will be shown.
        """
        # Set clothing as worn
        self.db.worn = wearstyle
        # Auto-cover appropriate clothing types, as specified above
        to_cover = []
        if self.db.clothing_type and self.db.clothing_type in CLOTHING_TYPE_AUTOCOVER:
            for garment in get_worn_clothes(wearer):
                if garment.db.clothing_type and garment.db.clothing_type \
                        in CLOTHING_TYPE_AUTOCOVER[self.db.clothing_type]:
                    to_cover.append(garment)
                    garment.db.covered_by = self
        if quiet:
            return
        # Otherwise, display a message to the room
        message = "{wearer} puts on {item}"
        if wearstyle and wearstyle is not True:
            message = "{wearer} wears {item} %s" % wearstyle
        if to_cover:
            message = message + ", covering %s" % list_to_string(to_cover)
        wearer.location.msg_contents(message + ".", mapping=dict(wearer=wearer, item=self))
예제 #6
0
파일: clothing.py 프로젝트: dimaguy/NOW
    def wear(self, wearer, wearstyle, quiet=False):
        """
        Sets clothes to 'worn' and optionally echoes to the room.

        Args:
            wearer (obj): character object wearing this clothing object
            wearstyle (True or str): string describing the style of wear or True for none
            quiet (bool): If false, does not message the room

        Notes:
            Optionally sets db.worn with a 'wearstyle' that appends a short passage to
            the end of the name  of the clothing to describe how it's worn that shows
            up in the wearer's desc - I.E. 'around his neck' or 'tied loosely around
            her waist'. If db.worn is set to 'True' then just the name will be shown.
        """
        # Set clothing as worn
        self.db.worn = wearstyle
        # Auto-cover appropriate clothing types, as specified above
        to_cover = []
        if self.db.clothing_type and self.db.clothing_type in CLOTHING_TYPE_AUTOCOVER:
            for garment in get_worn_clothes(wearer):
                if garment.db.clothing_type and garment.db.clothing_type \
                        in CLOTHING_TYPE_AUTOCOVER[self.db.clothing_type]:
                    to_cover.append(garment)
                    garment.db.covered_by = self
        if quiet:
            return
        # Otherwise, display a message to the room
        message = "{wearer} puts on {item}"
        if wearstyle and wearstyle is not True:
            message = "{wearer} wears {item} %s" % wearstyle
        if to_cover:
            message = message + ", covering %s" % list_to_string(to_cover)
        wearer.location.msg_contents(message + ".",
                                     mapping=dict(wearer=wearer, item=self))
예제 #7
0
    def remove(self, wearer, quiet=False):
        """
        Removes worn clothes and optionally echoes to the room.

        Args:
            wearer (obj): character object wearing this clothing object

        Kwargs:
            quiet (bool): If false, does not message the room
        """
        self.db.worn = False
        remove_message = "%s removes %s." % (wearer, self.name)
        uncovered_list = []

        # Check to see if any other clothes are covered by this object.
        for thing in wearer.contents:
            # If anything is covered by
            if thing.db.covered_by == self:
                thing.db.covered_by = False
                uncovered_list.append(thing.name)
        if len(uncovered_list) > 0:
            remove_message = "%s removes %s, revealing %s." % (wearer, self.name, list_to_string(uncovered_list))
        # Echo a message to the room
        if not quiet:
            wearer.location.msg_contents(remove_message)
예제 #8
0
def pretty_special(character, specialname):
    "Returns a pretty-looking readout of a special move."
    effectlist = character.db.Special_Moves[specialname][1]
    effectstring = utils.list_to_string(effectlist, endsep="|255and|455", addquote=False)
    effectstringlength = len(effectstring)
    if "|255and|455" in effectstring:
        effectstringlength -= 8
    specialdesc = character.db.Special_Moves[specialname][2]
    paddinglength = max((80 - effectstringlength - len(specialname) - 9), 0)
    padding = ('{:-^%i}' % paddinglength).format('')
    text = "|455%s |255[|455%s|255] %s |455%i|255 SP|n\n%s" % (specialname, effectstring, padding, rules.special_cost(effectlist), specialdesc)
    return text
예제 #9
0
파일: menu.py 프로젝트: g33kcub/evennia-1
def node_join_room(caller, raw_string, **kwargs):

    room = kwargs["room"]
    stats = room.db.stats or {"progress": 0}

    players = [char.key for char in room.get_all_characters()]
    text = _JOIN_EXISTING_ROOM_TEXT.format(
        roomname=room.get_display_name(caller),
        percent=int(stats["progress"]),
        nplayers=len(players),
        players=list_to_string(players),
    )

    options = (
        {"key": ("|g[a]ccept|n (default)", "a"), "goto": (_move_to_room, kwargs)},
        {"key": ("|r[c]ancel|n", "c"), "goto": "node_start"},
        {"key": "_default", "goto": (_move_to_room, kwargs)},
    )

    return text, options
예제 #10
0
    def return_appearance(self, looker):
        """
        This formats a description. It is the hook a 'look' command
        should call.

        Args:
            looker (Object): Object doing the looking.

        Notes:
            The name of every clothing item carried and worn by the character
            is appended to their description. If the clothing's db.worn value
            is set to True, only the name is appended, but if the value is a
            string, the string is appended to the end of the name, to allow
            characters to specify how clothing is worn.
        """
        if not looker:
            return ""
        # get description, build string
        string = "|c%s|n\n" % self.get_display_name(looker)
        desc = self.db.desc
        worn_string_list = []
        clothes_list = get_worn_clothes(self, exclude_covered=True)
        # Append worn, uncovered clothing to the description
        for garment in clothes_list:
            # If 'worn' is True, just append the name
            if garment.db.worn is True:
                worn_string_list.append(garment.name)
            # Otherwise, append the name and the string value of 'worn'
            elif garment.db.worn:
                worn_string_list.append("%s %s" %
                                        (garment.name, garment.db.worn))
        if desc:
            string += "%s" % desc
        # Append worn clothes.
        if worn_string_list:
            string += "|/|/%s is wearing %s." % (
                self, list_to_string(worn_string_list))
        else:
            string += "|/|/%s is not wearing anything." % self
        return string
예제 #11
0
def ms_withdraw(mover, target, distance, mode):
    # Performs multiple withdraw steps and spits out the result.
    moves = 0
    blocks = 0
    blockers = []
    steps = distance
    while steps > 0:
        result = withdraw(mover, target, mode)
        if result[0] == "move":
            moves += 1
        elif result[0] == "block":
            blocks += 1
            if not result[1] in blockers:
                blockers.append(result[1])
        elif result[0] == "stop":
            steps = 0
        steps -= 1
    # Then spit out a pretty message detailing what happened.
    if moves == 1:
        pluralmove = "step"
    else:
        pluralmove = "steps"
    if blocks == 1:
        pluralblock = "step"
    else:
        pluralblock = "steps"
    newrange = mover.db.Combat_Range[target]
    stringofblockers = utils.list_to_string(blockers, endsep="and", addquote=False)
    if mode == "normal":
        if moves > 0 and blocks == 0:
            mover.location.msg_contents("%s withdraws to %s range with %s! |552[|554%i|552 %s]|n" % (mover, rules.range_name(newrange).lower(), target, moves, pluralmove))
        elif moves > 0 and blocks > 0:
            mover.location.msg_contents("%s has some movement blocked by %s, but withdraws to %s range with %s! |552[|554%i|552 %s, |554%i|552 blocked]|n" % (mover, stringofblockers, rules.range_name(newrange).lower(), target, moves, pluralmove, blocks))
        elif moves == 0 and blocks > 0:
            mover.location.msg_contents("%s tries to withdraw from %s, but is blocked by %s! |552[|554%i|552 %s blocked]|n" % (mover, target, stringofblockers, blocks, pluralblock))
    elif mode == "forced":
        mover.location.msg_contents("%s is pushed back to %s range with %s! |552[Forced |554%i|552 %s]|n" % (mover, rules.range_name(newrange).lower(), target, moves, pluralmove))
    elif mode == "free":
        mover.location.msg_contents("%s withdraws to %s range with %s! |552[Free |554%i|552 %s]|n" % (mover, rules.range_name(newrange).lower(), target, moves, pluralmove))
예제 #12
0
    def summarize(self):
        exit_summary = ""

        for ename, rvnum in self.obj['exits'].items():
            room = "" if get_room(rvnum) is None else get_room(rvnum).db.name
            exit_summary += f"    |y{ename.capitalize():<5}|n: {rvnum:<7} {room:<15}\n"

        edesc_msg = ""
        for key, edesc in self.obj['edesc'].items():
            edesc_msg += f"|c{key}|n:\n{crop(edesc)}\n"

        room_flags = list_to_string(self.obj['flags'])

        sector = self.obj['type']
        sector_symbol = VALID_ROOM_SECTORS[self.obj['type']].symbol

        status = "(|rCAN NOT EDIT|n)" if self.obj['zone'] != has_zone(
            self.caller) else ""
        msg = f"""
********Room Summary*******
        {status}
VNUM: [{self.vnum}]      ZONE:[|m{self.obj['zone']}|n]

name    : |y{self.obj['name']}|n
desc    : |y{self.obj['desc']}|n
flags   : 
|y{room_flags}|n

sector  : |m{sector}|n, [{sector_symbol}]
exits  : 
{exit_summary}

edesc   : 
{edesc_msg}
----------------Extras---------------------
"""
        for efield, evalue in self.obj['extra'].items():
            msg += f"{efield:<7}: {crop(evalue, width=50)}\n"
        self.caller.msg(msg)
예제 #13
0
    def return_appearance(self, looker):
        """
        This formats a description. It is the hook a 'look' command
        should call.

        Args:
            looker (Object): Object doing the looking.

        Notes:
            The name of every clothing item carried and worn by the character
            is appended to their description. If the clothing's db.worn value
            is set to True, only the name is appended, but if the value is a
            string, the string is appended to the end of the name, to allow
            characters to specify how clothing is worn.
        """
        if not looker:
            return ""
        # get description, build string
        string = "|c%s|n\n" % self.get_display_name(looker)
        desc = self.db.desc
        worn_string_list = []
        clothes_list = get_worn_clothes(self, exclude_covered=True)
        # Append worn, uncovered clothing to the description
        for garment in clothes_list:
            # If 'worn' is True, just append the name
            if garment.db.worn is True:
                worn_string_list.append(garment.name)
            # Otherwise, append the name and the string value of 'worn'
            elif garment.db.worn:
                worn_string_list.append("%s %s" % (garment.name, garment.db.worn))
        if desc:
            string += "%s" % desc
        # Append worn clothes.
        if worn_string_list:
            string += "|/|/%s is wearing %s." % (self, list_to_string(worn_string_list))
        else:
            string += "|/|/%s is not wearing anything." % self
        return string
예제 #14
0
 def return_appearance(self, viewer):
     """This formats a description. It is the hook a 'look' command should call.
     Args:
         viewer (Object): Object doing the looking.
     """
     if not viewer:
         return ''
     if not viewer.is_typeclass('typeclasses.accounts.Account'):
         viewer = viewer.account  # make viewer reference the account object
     char = viewer.puppet
     # get and identify all objects
     visible = (con for con in self.contents if con != viewer and
                con.access(viewer, 'view'))
     exits, users, things = [], [], []
     for con in visible:
         if con.destination:
             exits.append(con)
         elif con.has_account:
             users.append(con)
         else:
             if not con.db.worn:
                 things.append(con)
     string = "\n%s" % self.get_display_name(viewer, mxp='sense %s' % self.get_display_name(viewer, plain=True))
     if self.location and self.location.tags.get('rp', category='flags'):
         pose = self.db.messages and self.db.messages.get('pose', None)
         string += ' %s' % pose or ''
     if self.traits.mass and self.traits.mass.actual > 0:
         string += " |y(%s)|n " % mass_unit(self.get_mass())
     if self.traits.health:  # Add character health bar if character has health.
         gradient = ["|[300", "|[300", "|[310", "|[320", "|[330", "|[230", "|[130", "|[030", "|[030"]
         health = make_bar(self.traits.health.actual, self.traits.health.max, 20, gradient)
         string += " %s\n" % health
     else:
         string += "\n"
     desc = self.db.desc
     desc_brief = self.db.desc_brief
     if desc:
         string += "%s" % desc
     elif desc_brief:
         string += "%s" % desc_brief
     else:
         string += 'A shimmering illusion shifts from form to form.'
     # ---- Allow clothes wearing to be seen
     worn_string_list = []
     clothes_list = get_worn_clothes(self, exclude_covered=True)
     # Append worn, uncovered clothing to the description
     for garment in clothes_list:
         if garment.db.worn is True:  # If 'worn' is True,
             worn_string_list.append(garment.name)  # just append the name.
         # Otherwise, append the name and the string value of 'worn'
         elif garment.db.worn:
             worn_string_list.append("%s %s" % (garment.name, garment.db.worn))
     if worn_string_list:  # Append worn clothes.
         string += "|/|/%s is wearing %s." % (self, list_to_string(worn_string_list))
     # ---- List things carried (excludes worn things)
     if users or things:
         user_list = ", ".join(u.get_display_name(viewer) for u in users)
         ut_joiner = ', ' if users and things else ''
         item_list = ", ".join(t.get_display_name(viewer) for t in things)
         string += "\n|wYou see:|n " + user_list + ut_joiner + item_list
     # ---- Look Notify system:
     if self != char:
         if not (self.db.settings and 'look notify' in self.db.settings
                 and self.db.settings['look notify'] is False):
             self.msg("%s just looked at you." % char.get_display_name(self))
     return string
예제 #15
0
파일: tests.py 프로젝트: jiiieff/evennia
 def test_list_to_string(self):
     self.assertEqual('1, 2, 3', utils.list_to_string([1,2,3], endsep=""))
     self.assertEqual('"1", "2", "3"', utils.list_to_string([1,2,3], endsep="", addquote=True))
     self.assertEqual('1, 2 and 3', utils.list_to_string([1,2,3]))
     self.assertEqual('"1", "2" and "3"', utils.list_to_string([1,2,3], endsep="and", addquote=True))
예제 #16
0
def menunode_fieldfill(caller, raw_string, **kwargs):
    """
    This is an EvMenu node, which calls itself over and over in order to
    allow a player to enter values into a fillable form. When the form is
    submitted, the form data is passed to a callback as a dictionary.
    """

    # Retrieve menu info - taken from ndb if not persistent or db if persistent
    if not caller.db._menutree:
        formdata = caller.ndb._menutree.formdata
        formtemplate = caller.ndb._menutree.formtemplate
        formcallback = caller.ndb._menutree.formcallback
        pretext = caller.ndb._menutree.pretext
        posttext = caller.ndb._menutree.posttext
        submitcmd = caller.ndb._menutree.submitcmd
        borderstyle = caller.ndb._menutree.borderstyle
        formhelptext = caller.ndb._menutree.formhelptext
    else:
        formdata = caller.db._menutree.formdata
        formtemplate = caller.db._menutree.formtemplate
        formcallback = caller.db._menutree.formcallback
        pretext = caller.db._menutree.pretext
        posttext = caller.db._menutree.posttext
        submitcmd = caller.db._menutree.submitcmd
        borderstyle = caller.db._menutree.borderstyle
        formhelptext = caller.db._menutree.formhelptext

    # Syntax error
    syntax_err = "Syntax: <field> = <new value>|/Or: clear <field>, help, look, quit|/'%s' to submit form" % submitcmd

    # Display current form data
    text = (display_formdata(formtemplate, formdata, pretext=pretext,
            posttext=posttext, borderstyle=borderstyle), formhelptext)
    options = ({"key": "_default",
               "goto": "menunode_fieldfill"})

    if raw_string:
        # Test for given 'submit' command
        if raw_string.lower().strip() == submitcmd:
            # Test to see if any blank fields are required
            blank_and_required = []
            for field in formtemplate:
                if "required" in field.keys():
                    # If field is required but current form data for field is blank
                    if field["required"] is True and formdata[field["fieldname"]] is None:
                        # Add to blank and required fields
                        blank_and_required.append(field["fieldname"])
            if len(blank_and_required) > 0:
                # List the required fields left empty to the player
                caller.msg("The following blank fields require a value: %s" % list_to_string(blank_and_required))
                text = (None, formhelptext)
                return text, options

            # If everything checks out, pass form data to the callback and end the menu!
            try:
                formcallback(caller, formdata)
            except Exception:
                logger.log_trace("Error in fillable form callback.")
            return None, None

        # Test for 'look' command
        if raw_string.lower().strip() == "look" or raw_string.lower().strip() == "l":
            return text, options

        # Test for 'clear' command
        cleartest = raw_string.lower().strip().split(" ", 1)
        if cleartest[0].lower() == "clear":
            text = (None, formhelptext)
            if len(cleartest) < 2:
                caller.msg(syntax_err)
                return text, options
            matched_field = None

            for key in formdata.keys():
                if cleartest[1].lower() in key.lower():
                    matched_field = key

            if not matched_field:
                caller.msg("Field '%s' does not exist!" % cleartest[1])
                text = (None, formhelptext)
                return text, options

            # Test to see if field can be cleared
            for field in formtemplate:
                if field["fieldname"] == matched_field and "cantclear" in field.keys():
                    if field["cantclear"] is True:
                        caller.msg("Field '%s' can't be cleared!" % matched_field)
                        text = (None, formhelptext)
                        return text, options

            # Clear the field
            formdata.update({matched_field: None})
            caller.ndb._menutree.formdata = formdata
            caller.msg("Field '%s' cleared." % matched_field)
            return text, options

        if "=" not in raw_string:
            text = (None, formhelptext)
            caller.msg(syntax_err)
            return text, options

        # Extract field name and new field value
        entry = raw_string.split("=", 1)
        fieldname = entry[0].strip()
        newvalue = entry[1].strip()

        # Syntax error if field name is too short or blank
        if len(fieldname) < 1:
            caller.msg(syntax_err)
            text = (None, formhelptext)
            return text, options

        # Attempt to match field name to field in form data
        matched_field = None
        for key in formdata.keys():
            if fieldname.lower() in key.lower():
                matched_field = key

        # No matched field
        if matched_field is None:
            caller.msg("Field '%s' does not exist!" % fieldname)
            text = (None, formhelptext)
            return text, options

        # Set new field value if match
        # Get data from template
        fieldtype = None
        max_value = None
        min_value = None
        truestr = "True"
        falsestr = "False"
        verifyfunc = None
        for field in formtemplate:
            if field["fieldname"] == matched_field:
                fieldtype = field["fieldtype"]
                if "max" in field.keys():
                    max_value = field["max"]
                if "min" in field.keys():
                    min_value = field["min"]
                if "truestr" in field.keys():
                    truestr = field["truestr"]
                if "falsestr" in field.keys():
                    falsestr = field["falsestr"]
                if "verifyfunc" in field.keys():
                    verifyfunc = field["verifyfunc"]

        # Field type text verification
        if fieldtype == "text":
            # Test for max/min
            if max_value is not None:
                if len(newvalue) > max_value:
                    caller.msg("Field '%s' has a maximum length of %i characters." % (matched_field, max_value))
                    text = (None, formhelptext)
                    return text, options
            if min_value is not None:
                if len(newvalue) < min_value:
                    caller.msg("Field '%s' reqiures a minimum length of %i characters." % (matched_field, min_value))
                    text = (None, formhelptext)
                    return text, options

        # Field type number verification
        if fieldtype == "number":
            try:
                newvalue = int(newvalue)
            except:
                caller.msg("Field '%s' requires a number." % matched_field)
                text = (None, formhelptext)
                return text, options
            # Test for max/min
            if max_value is not None:
                if newvalue > max_value:
                    caller.msg("Field '%s' has a maximum value of %i." % (matched_field, max_value))
                    text = (None, formhelptext)
                    return text, options
            if min_value is not None:
                if newvalue < min_value:
                    caller.msg("Field '%s' reqiures a minimum value of %i." % (matched_field, min_value))
                    text = (None, formhelptext)
                    return text, options

        # Field type bool verification
        if fieldtype == "bool":
            if newvalue.lower() != truestr.lower() and newvalue.lower() != falsestr.lower():
                caller.msg("Please enter '%s' or '%s' for field '%s'." % (truestr, falsestr, matched_field))
                text = (None, formhelptext)
                return text, options
            if newvalue.lower() == truestr.lower():
                newvalue = True
            elif newvalue.lower() == falsestr.lower():
                newvalue = False

        # Call verify function if present
        if verifyfunc:
            if verifyfunc(caller, newvalue) is False:
                # No error message is given - should be provided by verifyfunc
                text = (None, formhelptext)
                return text, options
            elif verifyfunc(caller, newvalue) is not True:
                newvalue = verifyfunc(caller, newvalue)
                # Set '0' or '1' to True or False if the field type is bool
                if fieldtype == "bool":
                    if newvalue == 0:
                        newvalue = False
                    elif newvalue == 1:
                        newvalue = True

        # If everything checks out, update form!!
        formdata.update({matched_field: newvalue})
        caller.ndb._menutree.formdata = formdata

        # Account for truestr and falsestr when updating a boolean form
        announced_newvalue = newvalue
        if newvalue is True:
            announced_newvalue = truestr
        elif newvalue is False:
            announced_newvalue = falsestr

        # Announce the new value to the player
        caller.msg("Field '%s' set to: %s" % (matched_field, str(announced_newvalue)))
        text = (None, formhelptext)

    return text, options
예제 #17
0
 def return_appearance(self, viewer):
     """This formats a description. It is the hook a 'look' command should call.
     Args:
         viewer (Object): Object doing the looking.
     """
     if not viewer:
         return ''
     if not viewer.is_typeclass('typeclasses.accounts.Account'):
         viewer = viewer.account  # make viewer reference the account object
     char = viewer.puppet
     # get and identify all objects
     visible = (con for con in self.contents
                if con != viewer and con.access(viewer, 'view'))
     exits, users, things = [], [], []
     for con in visible:
         if con.destination:
             exits.append(con)
         elif con.has_account:
             users.append(con)
         else:
             if not con.db.worn:
                 things.append(con)
     string = "\n%s" % self.get_display_name(
         viewer, mxp='sense %s' % self.get_display_name(viewer, plain=True))
     if self.location and self.location.tags.get('rp', category='flags'):
         pose = self.db.messages and self.db.messages.get('pose', None)
         string += ' %s' % pose or ''
     if self.traits.mass and self.traits.mass.actual > 0:
         string += " |y(%s)|n " % mass_unit(self.get_mass())
     if self.traits.health:  # Add character health bar if character has health.
         gradient = [
             "|[300", "|[300", "|[310", "|[320", "|[330", "|[230", "|[130",
             "|[030", "|[030"
         ]
         health = make_bar(self.traits.health.actual,
                           self.traits.health.max, 20, gradient)
         string += " %s\n" % health
     else:
         string += "\n"
     desc = self.db.desc
     desc_brief = self.db.desc_brief
     if desc:
         string += "%s" % desc
     elif desc_brief:
         string += "%s" % desc_brief
     else:
         string += 'A shimmering illusion shifts from form to form.'
     # ---- Allow clothes wearing to be seen
     worn_string_list = []
     clothes_list = get_worn_clothes(self, exclude_covered=True)
     # Append worn, uncovered clothing to the description
     for garment in clothes_list:
         if garment.db.worn is True:  # If 'worn' is True,
             worn_string_list.append(garment.name)  # just append the name.
         # Otherwise, append the name and the string value of 'worn'
         elif garment.db.worn:
             worn_string_list.append("%s %s" %
                                     (garment.name, garment.db.worn))
     if worn_string_list:  # Append worn clothes.
         string += "|/|/%s is wearing %s." % (
             self, list_to_string(worn_string_list))
     # ---- List things carried (excludes worn things)
     if users or things:
         user_list = ", ".join(u.get_display_name(viewer) for u in users)
         ut_joiner = ', ' if users and things else ''
         item_list = ", ".join(t.get_display_name(viewer) for t in things)
         string += "\n|wYou see:|n " + user_list + ut_joiner + item_list
     # ---- Look Notify system:
     if self != char:
         if not (self.db.settings and 'look notify' in self.db.settings
                 and self.db.settings['look notify'] is False):
             self.msg("%s just looked at you." %
                      char.get_display_name(self))
     return string
예제 #18
0
def menunode_fieldfill(caller, raw_string, **kwargs):
    """
    This is an EvMenu node, which calls itself over and over in order to
    allow a player to enter values into a fillable form. When the form is
    submitted, the form data is passed to a callback as a dictionary.
    """

    # Retrieve menu info - taken from ndb if not persistent or db if persistent
    if not caller.db._menutree:
        formdata = caller.ndb._menutree.formdata
        formtemplate = caller.ndb._menutree.formtemplate
        formcallback = caller.ndb._menutree.formcallback
        pretext = caller.ndb._menutree.pretext
        posttext = caller.ndb._menutree.posttext
        submitcmd = caller.ndb._menutree.submitcmd
        borderstyle = caller.ndb._menutree.borderstyle
        formhelptext = caller.ndb._menutree.formhelptext
    else:
        formdata = caller.db._menutree.formdata
        formtemplate = caller.db._menutree.formtemplate
        formcallback = caller.db._menutree.formcallback
        pretext = caller.db._menutree.pretext
        posttext = caller.db._menutree.posttext
        submitcmd = caller.db._menutree.submitcmd
        borderstyle = caller.db._menutree.borderstyle
        formhelptext = caller.db._menutree.formhelptext

    # Syntax error
    syntax_err = (
        "Syntax: <field> = <new value>|/Or: clear <field>, help, look, quit|/'%s' to submit form"
        % submitcmd
    )

    # Display current form data
    text = (
        display_formdata(
            formtemplate, formdata, pretext=pretext, posttext=posttext, borderstyle=borderstyle
        ),
        formhelptext,
    )
    options = {"key": "_default", "goto": "menunode_fieldfill"}

    if raw_string:
        # Test for given 'submit' command
        if raw_string.lower().strip() == submitcmd:
            # Test to see if any blank fields are required
            blank_and_required = []
            for field in formtemplate:
                if "required" in field.keys():
                    # If field is required but current form data for field is blank
                    if field["required"] is True and formdata[field["fieldname"]] is None:
                        # Add to blank and required fields
                        blank_and_required.append(field["fieldname"])
            if len(blank_and_required) > 0:
                # List the required fields left empty to the player
                caller.msg(
                    "The following blank fields require a value: %s"
                    % list_to_string(blank_and_required)
                )
                text = (None, formhelptext)
                return text, options

            # If everything checks out, pass form data to the callback and end the menu!
            try:
                formcallback(caller, formdata)
            except Exception:
                logger.log_trace("Error in fillable form callback.")
            return None, None

        # Test for 'look' command
        if raw_string.lower().strip() == "look" or raw_string.lower().strip() == "l":
            return text, options

        # Test for 'clear' command
        cleartest = raw_string.lower().strip().split(" ", 1)
        if cleartest[0].lower() == "clear":
            text = (None, formhelptext)
            if len(cleartest) < 2:
                caller.msg(syntax_err)
                return text, options
            matched_field = None

            for key in formdata.keys():
                if cleartest[1].lower() in key.lower():
                    matched_field = key

            if not matched_field:
                caller.msg("Field '%s' does not exist!" % cleartest[1])
                text = (None, formhelptext)
                return text, options

            # Test to see if field can be cleared
            for field in formtemplate:
                if field["fieldname"] == matched_field and "cantclear" in field.keys():
                    if field["cantclear"] is True:
                        caller.msg("Field '%s' can't be cleared!" % matched_field)
                        text = (None, formhelptext)
                        return text, options

            # Clear the field
            formdata.update({matched_field: None})
            caller.ndb._menutree.formdata = formdata
            caller.msg("Field '%s' cleared." % matched_field)
            return text, options

        if "=" not in raw_string:
            text = (None, formhelptext)
            caller.msg(syntax_err)
            return text, options

        # Extract field name and new field value
        entry = raw_string.split("=", 1)
        fieldname = entry[0].strip()
        newvalue = entry[1].strip()

        # Syntax error if field name is too short or blank
        if len(fieldname) < 1:
            caller.msg(syntax_err)
            text = (None, formhelptext)
            return text, options

        # Attempt to match field name to field in form data
        matched_field = None
        for key in formdata.keys():
            if fieldname.lower() in key.lower():
                matched_field = key

        # No matched field
        if matched_field is None:
            caller.msg("Field '%s' does not exist!" % fieldname)
            text = (None, formhelptext)
            return text, options

        # Set new field value if match
        # Get data from template
        fieldtype = None
        max_value = None
        min_value = None
        truestr = "True"
        falsestr = "False"
        verifyfunc = None
        for field in formtemplate:
            if field["fieldname"] == matched_field:
                fieldtype = field["fieldtype"]
                if "max" in field.keys():
                    max_value = field["max"]
                if "min" in field.keys():
                    min_value = field["min"]
                if "truestr" in field.keys():
                    truestr = field["truestr"]
                if "falsestr" in field.keys():
                    falsestr = field["falsestr"]
                if "verifyfunc" in field.keys():
                    verifyfunc = field["verifyfunc"]

        # Field type text verification
        if fieldtype == "text":
            # Test for max/min
            if max_value is not None:
                if len(newvalue) > max_value:
                    caller.msg(
                        "Field '%s' has a maximum length of %i characters."
                        % (matched_field, max_value)
                    )
                    text = (None, formhelptext)
                    return text, options
            if min_value is not None:
                if len(newvalue) < min_value:
                    caller.msg(
                        "Field '%s' reqiures a minimum length of %i characters."
                        % (matched_field, min_value)
                    )
                    text = (None, formhelptext)
                    return text, options

        # Field type number verification
        if fieldtype == "number":
            try:
                newvalue = int(newvalue)
            except:
                caller.msg("Field '%s' requires a number." % matched_field)
                text = (None, formhelptext)
                return text, options
            # Test for max/min
            if max_value is not None:
                if newvalue > max_value:
                    caller.msg("Field '%s' has a maximum value of %i." % (matched_field, max_value))
                    text = (None, formhelptext)
                    return text, options
            if min_value is not None:
                if newvalue < min_value:
                    caller.msg(
                        "Field '%s' reqiures a minimum value of %i." % (matched_field, min_value)
                    )
                    text = (None, formhelptext)
                    return text, options

        # Field type bool verification
        if fieldtype == "bool":
            if newvalue.lower() != truestr.lower() and newvalue.lower() != falsestr.lower():
                caller.msg(
                    "Please enter '%s' or '%s' for field '%s'." % (truestr, falsestr, matched_field)
                )
                text = (None, formhelptext)
                return text, options
            if newvalue.lower() == truestr.lower():
                newvalue = True
            elif newvalue.lower() == falsestr.lower():
                newvalue = False

        # Call verify function if present
        if verifyfunc:
            if verifyfunc(caller, newvalue) is False:
                # No error message is given - should be provided by verifyfunc
                text = (None, formhelptext)
                return text, options
            elif verifyfunc(caller, newvalue) is not True:
                newvalue = verifyfunc(caller, newvalue)
                # Set '0' or '1' to True or False if the field type is bool
                if fieldtype == "bool":
                    if newvalue == 0:
                        newvalue = False
                    elif newvalue == 1:
                        newvalue = True

        # If everything checks out, update form!!
        formdata.update({matched_field: newvalue})
        caller.ndb._menutree.formdata = formdata

        # Account for truestr and falsestr when updating a boolean form
        announced_newvalue = newvalue
        if newvalue is True:
            announced_newvalue = truestr
        elif newvalue is False:
            announced_newvalue = falsestr

        # Announce the new value to the player
        caller.msg("Field '%s' set to: %s" % (matched_field, str(announced_newvalue)))
        text = (None, formhelptext)

    return text, options