[Tutor] Design Question... from a newbie

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Wed Oct 20 22:53:42 CEST 2004



On Wed, 20 Oct 2004, Rene Lopez wrote:

> I'm trying to write a small RPG game similar to D&D or whatever.  So
> I'm trying to figure out how to best keep track of a character and all
> of the attributes/variables for that character.

Hi Rene,

One improvement that might help clean up the code is to us a table-based
approach to handle the different choices.


At the moment, the code is doing something like:

>         if job == 1:
>              self.job = job
>              self.jobdesc = "Fighter"
>         elif job == 2:
>              self.job = job
>              self.job = "Mage"
>         # assign race
>         if race == 1:
>              self.race = race
>              self.racedesc =  "Human"
>         if race == 2:
>              self.race = race
>              self.racedesc = "Elf"

As we add more jobs and races, this might get larger.  Since the logic is
pretty similar, we might want to do something like this instead:


###
"""A mapping from job numbers to job descriptions."""
job_lookup_table = { 1 : 'Fighter',
                     2 : 'Mage' }

"""A mapping from race numbers to race descriptions."""
race_lookup_table = { 1 : 'Human',
                      2 : 'Elf' }
###


What we are trying to do here is keep the thing that's really different,
the variation, in a table.  This can often be a win: the code of the
Character initializer can be written as:

###
if job in job_lookup_table:
    self.job = job
    self.jobdesc = job_lookup_table[job]
if race in race_lookup_table:
    self.race = race
    self.racedesc = race_lookup_table[race]
###

This "table-driven" approach makes it a little easier to extend the system
with more jobs and races, because it's easy to add new entries in a data
table.



An alternative approach that an OOP person might suggest is to make the
jobs and races themselves as distinct objects.  For example, we can
represent those two jobs as the following classes:

###
class Job:
    def __init__(self, desc):
       self.desc = desc

FIGHTER = Job("Fighter")
MAGE = Job("Mage")
###


If we had this, then our Character construction can take a Job instance
directly, instead of taking integers and figuring out which job we're
taking:

### (Simplified example)
class Character:
    def __init__(self, name=' ', job = FIGHTER):
        self.name = name
        self.job = job
###

The advantage of this approach is that we can consolidate the job-specific
stuff of a character within each job class.  It also means that adding new
Jobs is also possible without having to touch the Character class.

Again, I'm not positive if this is an appropriate design --- it actually
might be overkill! --- but I hope it gives some useful ideas.


Good luck!



More information about the Tutor mailing list