2.2. Adding functionality to Player

2.2.1. Add a simple method to Player

You can define custom methods by writing your own class that inherits from textgame.player.Player. Say you want your player to eat something:

from textgame.player import Player, action_method

class MyPlayer(Player):

     @action_method
     def eat(self, noun):
         # check if player carries noun
         if noun in self.inventory:
             # define behaviour for different nouns
             if noun == "lunch":
                 # remove it
                 self.inventory.pop("lunch")
                 return "That was delicious!"
             return "Ew!"
         return "You don't have it!"

If you want user input like ‘eat lunch’ to call this method like player.eat("lunch"), you need to tell the parser to do so.

from textgame.parser import Parser

# use the world from previous example
player = MyPlayer(world, world.room("field_0"))
parser = Parser(player)

# tell the parser it's ok to say 'eat'
parser.legal_verbs.update({
 "eat": "eat"
})
# map the new verb to the method
parser.actionmap.update({
 "eat": player.eat
})

2.2.2. Overwrite an existing player method

In principle overwriting methods is straight forward, however you need to be careful with the decorator textgame.player.action_method(). It makes sure that textgame.world.World.update() gets called at the end of the method. However, you don’t want to call it twice in case your new method makes use of the old one, so you need to call the old one undecorated. Observe: Say you want to add an item’s value to the player’s score if he/she takes it.

class MyPlayer(Player):

    @action_method
    def take(self, itemid):
         # check if the thing is here
         if itemid in self.location.items:
             self.score += self.location.items[itemid].value

         # now we call take, but without the action_method-decorator
         return Player.take.undecorated(self, itemid)

2.2.3. Trigger a yes/no conversation and magic words

Here’s an obscure example of a magic word that takes the player to a magic room, but only if he/she owns a coin and confirms.

from textgame.Parser import EnterYesNoLoop

class MyPlayer(Player):

    @action_method
    def magicword(self):
         if "coin" in self.inventory:

             # define a helper function that gets called if the player answers yes
             def magicmove():
                 self.location = self.world.room("magicroom")
                 msg += self.location.check_restrictions(self)
                 msg += self.location.describe()
                 if not self.location.visited:
                     self.score += self.location.visit()
                 return msg

             return EnterYesNoLoop(
                 question = "Do you really want to travel magically?",
                 yes = magicmove,
                 no = "You stay where you are.")

         # do nothing if there's no coin
         return "Nothing happens."

Again, you need to map a word to this method.

2.2.4. Unlock advanced modes for Player

If you want certain methods to work only if the player did something special before, you can do so by dynamically adding attributes to the player:

class MyPlayer(Player):

     @action_method
     def prerequisite(self, noun):
         # make this player a magician
         self.magician = True
         # ....

     @action_method
     def do_magic(self, noun):
         # check if this player is a magician
         if hasattr(self, "magician"):
             # ...
         else:
             return "You can't do this yet!"