Recently, I created some item types that have different kinds of states. I’ve talked about containers before, that can have an open or closed status, and I just created another type, monsters, that can be alive or dead.
When printing these items as part of the room description, I’ve decided that in some cases I’d like that status info to become a part of the item listing, like, for example,
There is a dead creature here.
This is what my current method looks like that generates the name of an item so it can be printed. You may recall this from some previous post.
def GetName ( self, _article=globals.Articles.No ): """ Name of the item, complete with an indefinite or definite article """ if globals.Articles.Undef == _article: _aString = "a " if self.Name [ 0 ].lower () in globals.theVowels: _aString = "an " elif globals.Articles.Def == _article: _aString = "the " else: _aString = "" return _aString + self.Name
Time to get cracking and do some coding to make it happen…
First I wanted to put the code for the status info right into the
GetName() method, but then I realized it would mean I’d have to reconstruct the entire function for every item type that I want to be able to print its status for. Totally defeating the purpose of having such a function in the first place, right?
That’s when I had an idea. Why not put just the part that generates the status string into its own function? That way I can easily override it in any of the derived item classes if I need to. Of course… Doh!
For my default item class this function simply returns an empty string while other item types could create their own status string. Depending on what they are or do, I could now generate a name string that says
a blaring radio instead of just
a radio, or
a broken bottle, or
a dead monster.
Yes, I think that will work… I feel like a real trooper having thought of that elegant little concept.
def GetStatus ( self ): """ Return a string with the item's status. By default, it is empty """ return ""
To make it work, I simply change my
GetName() method to look like this.
def GetName ( self, _article=globals.Articles.No ): """ Name of the item, complete with an indefinite or definite article """ _outString = self.GetStatus () + self.Name if globals.Articles.Undef == _article: _aString = "a " if _outString [ 0 ].lower () in globals.theVowels: _aString = "an " elif globals.Articles.Def == _article: _aString = "the " else: _aString = "" return _aString + self.Name
Small change in line 5, but it makes quite a difference.
Now, let me show you my
Creature class and how I define things there to make it work for that special item type.
class Creature ( Item ): def __init__ ( self, _token, _idToken, _name, _description ): super ().__init__ ( _token, _idToken, _name, _description ) self.Alive = True def GetStatus ( self ): if not self.Alive: return "dead " else: return "" def Evaluate ( self ): return super().Evaluate()
Note how I created a custom
GetStatus() method for this class that checks the creature’s status and returns “dead” if the monster has been killed. Because this class method overrides the one from the
Item superclass, it will be called instead of the default method.
I keep being amazed by how powerful some of the seemingly simplest programming language features are when you start putting them to use.