2
\$\begingroup\$

I have a basic outline for the best way I can come up with to move a character through a basic text map. I want to implement this module in my simple text RPG. I know there has to be a better way to implement this code with less functions, and possibly with less print statements. Also I am not sure if this is a module I can simply import and call in my main file. Any suggestions on how to condense or improve the function of this code would be appreciated.

def room1():
    print('- -\n'
          '|@|\n'
          '---')
    print('you see a path to the north')
def hall1():
    print('|-|\n'
          '| |\n'
          '| |\n'
          '| D\n'
          '| |\n'
          '|@|')
def hall2():    
    print('|-|\n'
          '| |\n'
          '| |\n'
          '| D\n'
          '|@|\n'
          '| |')
def hall3():
    print('|-|\n'
          '| |\n'
          '| |\n'
          '|@D\n'
          '| |\n'
          '| |')
    print('You see a door to the east.')
def hall4():
    print('|-|\n'
          '| |\n'
          '|@|\n'
          '| D\n'
          '| |\n'
          '| |')
def hall5():
    print('|-|\n'
          '|@|\n'
          '| |\n'
          '| D\n'
          '| |\n'
          '| |')
def door1():
    print('|-|\n'
          '| |---\n'
          '| | m |\n'
          '|@ _  |\n'
          '| |---|\n'
          '| |')
    print('You see a monster in the room!')
def room2():
    print('|-|\n'
          '| |---\n'
          '| |   |\n'
          '|  @m |\n'
          '| |---|\n'
          '| |')
def move1():
    move=input("press N to move north")
    if move=='n':
        hall1()
def move2():
    move=input("press N to move north")
    if move=='n':
        hall2()
def move3():
    move=input("press N to move north")
    if move=='n':
        hall3()
def move4():
    move=input("Press E to move into the room.")
    if move =='e':
        room2()
def move5():
    move=input("Press N to move north.")
    if move=='n':
        hall5()
def choice1():
    move=input("press O to open the door\n press N to move north")

    if move =='o':
        door1()
        move4()
    elif move=='n':
        hall4()
        move5()
def maploop():
    room1()
    move1()
    move2()
    move3()
    choice1()
maploop()

My main code after the suggested changes:

#!/usr/bin/env python3
from random import randint
class Die:
    def __init__(self, sides=6):
        self.sides=sides

    def roll(self):
        return randint(1,self.sides)

class Character(object):
    def __init__(self,name,hp,thaco,ac,inventory,exp):
        self.name=name
        self.hp=hp
        self.thaco=thaco
        self.ac=ac
        self.inventory=inventory
        self.exp=exp

class Player(Character):
    def __init__(self,hp,exp):
        super().__init__(input("What is your characters name?\n>>>"),hp,
                         20,10,{},exp)    

    s=0
    i=0
    w=0
    d=0
    c=0
    ch=0

    def fight():
        playerAttack()

    def sheet():
        print ("Name: {} HP: {} Thac0: {} AC:{} XP:{}".format(
              sprite.hero.name,sprite.hero.hp,sprite.hero.thaco,sprite.hero.ac,sprite.hero.exp))
        print("Strength: {}\nIntelligence: {}\nWisdom: {}\nDexterity:{}\nConstitution: {}\nCharisma: {}\n".format(
              sprite.hero.s,sprite.hero.i,sprite.hero.w,sprite.hero.d,sprite.hero.c,sprite.hero.ch))
        commands()

class Fighter(Player):

    prof = "fighter"
    maxhp=10
    level=1
    hd=10
    level2=20
    attackDie=10

    def __init__(self):
        super().__init__(hp=10,exp=10)

    def fight():
        Player.fight()

    def sheet():
        Player.sheet()

    COMMANDS={
        'f':('fight',fight),
        'i':('info',sheet),
        }
class Cleric(Player):

    prof= "cleric"
    maxhp=8
    level=1
    hd=8
    level2=15
    attackDie=6

    def __init__(self):
        super().__init__(hp=8,exp=8)

    def sheet():
        Player.sheet()

    def fight():
        Player.fight()

    def heal():
        if sprite.hero.hp<sprite.hero.maxhp:
            sprite.hero.hp+=D8.roll()                
            if sprite.hero.hp>sprite.hero.maxhp:
                sprite.hero.hp=sprite.hero.hp-(sprite.hero.hp-sprite.hero.maxhp)                    
            print("You now have: {}/{} hp".format(sprite.hero.hp,sprite.hero.maxhp))
        else:
            print("Your hit points are full")
            print("You have: {}/{} hp".format(sprite.hero.hp,sprite.hero.maxhp))
            commands()

    COMMANDS={
        'f':('fight',fight),
        'h':('heal',heal),
        'i':('info',sheet),
        }
class Mage(Player):

    prof= "mage"
    mana=1
    maxmana=1
    maxhp=4
    level=1
    hd=4
    level2=10
    attackDie=4

    def __init__(self):
        super().__init__(hp=4,exp=4)

    def sheet():
        Player.sheet()

    def fight():
        Player.fight()

    def rest():        
        if sprite.hero.mana<sprite.hero.maxmana:
            sprite.hero.mana+=1
            print("You have",sprite.hero.mana,"mana")
        elif sprite.hero.mana>=sprite.hero.maxmana:
            print("Your mana is full.")
            print("You have",sprite.hero.mana,"mana")
            commands()

    def castSpell():

        def sleep():
            print("You put the monster to sleep it is easy to kill now")
            sprite.mob.hp-=sprite.mob.hp
            sprite.hero.mana-=1

        def magicMissile():
            dam =D4.roll()*sprite.hero.mana
            sprite.mob.hp-=dam
            print("You use all your mana! and do",dam,"damage!")
            sprite.hero.mana-=sprite.hero.mana

        def fireball():
            print("You are temporarily blinded by a feiry flash of light.")
            dam=roll3D6()

            sprite.mob.hp-=dam
            print("You did",dam,"points of damage")            
            sprite.hero.mana-=3

        def rewind():                    
            commands()


        print("You have",sprite.hero.mana,"mana")
        if sprite.hero.mana>=1 and sprite.hero.mana<3:
            spells={
                's':('sleep',sleep),
                'm':('magic missile',magicMissile),
                }
        elif sprite.hero.mana>=3:
             spells={
                's':('sleep',sleep),
                'm':('magic missile',magicMissile),
                'f':('fireball',fireball),
                }
        else:
            spells={
                'e':('rewind',rewind),
                }
            print('You are out of mana!')


        for command, action in spells.items():
            print('Press {} to cast {}'.format(command,action[0]))
        print('press Enter to skip')

        while True:
            print("~~~~~~~~~Press a key to Continue.~~~~~~~")
            command=input(">>>")
            if command and command not in spells:
                print('Not a valid command')
                continue
            break
        if command:
            spells[command][1]()

    COMMANDS={
        'f':('fight',fight),
        's':('spells',castSpell),
        'r':('generate mana',rest),
        'i':('info',sheet),
        }

class Monster(Character):
    pass

class Goblin(Character):
    def __init__(self):
        super().__init__(name="goblin",
                         hp=7,thaco=20,
                         ac=6,inventory={},
                         exp=7)

    attackDie=4

class Orc(Character):
    def __init__(self):
        super().__init__(name="orc",
                         hp=8,thaco=18,
                         ac=6,inventory={},
                         exp=8)

    attackDie=6


def profession():
    choice = {
        'f': Fighter,
        'c': Cleric,
        'm': Mage,
        }
    print("What is your class?")    
    for letter in choice.keys():        
        print("- Press {} for {}".format(
            letter, choice[letter].__name__))      
    pclass = input(">>>")
    if pclass in choice.keys():
        return choice[pclass]()
    else:
        return choice['f']()

def ranmob():
    mob = Goblin() if D2.roll()<2 else Orc()
    return mob


def playerAttack():
    roll=D20.roll()   
    if roll>=sprite.hero.thaco-sprite.mob.ac:
        print("You hit")        
        rollD=Die(sprite.hero.attackDie).roll()
        print("for",rollD,"damage")
        sprite.mob.hp-=rollD
        print("the",sprite.mob.name,"has",sprite.mob.hp,"hp left")
    else:
        print("You miss")

def monsterAttack():
    roll=D20.roll()   
    if roll>=sprite.mob.thaco-sprite.hero.ac:
        print('The monster hit')
        rollD=Die(sprite.mob.attackDie).roll()
        print("for",rollD,"damage")
        sprite.hero.hp-=rollD
        print(sprite.hero.name,"has",sprite.hero.hp,"hp left")
    else:
        print("Monster misses")

def levelUp():        
    while sprite.hero.exp>=sprite.hero.level2:
        levelGain=False
        sprite.hero.level+=1
        levelGain=True
        sprite.hero.level2=sprite.hero.level2*2
        if levelGain==True:
            sprite.hero.maxhp+=Die(sprite.hero.hd).roll()
            sprite.hero.hp=sprite.hero.maxhp
            if sprite.hero.prof=="mage":
                sprite.hero.maxmana+=1
                sprite.hero.mana=sprite.hero.maxmana            
            print("You Gained a level","\n",'hp:',sprite.hero.hp,"\n",'level:',sprite.hero.level)
            levelGain=False
    while sprite.hero.level>=3:
        sprite.hero.level-=3
        sprite.hero.thaco-=1
        print("thaco:",sprite.hero.thaco)    

def commands():
    for command, action in sprite.hero.COMMANDS.items():
        print('Press {} to {}'.format(command,action[0]))
    print('press Enter to skip')
    while True:
        print("~~~~~~~~~Press a key to Continue.~~~~~~~")
        command=input(">>>")
        if command and command not in sprite.hero.COMMANDS:
            print('Not a valid command')
            continue
        break
    if command:
        sprite.hero.COMMANDS[command][1]()

def roll3D6():
    roll=0
    roll+=D6.roll()
    roll+=D6.roll()
    roll+=D6.roll()
    return roll

def assignStats():
    Player.s=roll3D6()
    Player.i=roll3D6()
    Player.w=roll3D6()
    Player.d=roll3D6()
    Player.c=roll3D6()
    Player.ch=roll3D6()

def  encounter(mob1,hero1):
    sprite.mob=mob1
    sprite.hero=hero1
    print("The {} has {} hp.".format(sprite.mob.name,sprite.mob.hp))
    if sprite.hero.hp>0:
        commands()
    if sprite.mob.hp>0:                
        monsterAttack()

def checkDead(mob1,hero1):
    sprite.mob=mob1
    sprite.hero=hero1
    if sprite.mob.hp<=0:
        print('The',sprite.mob.name,'is dead!')        
        sprite.hero.exp+=sprite.mob.exp        
        print('hero xp',sprite.hero.exp)
        sprite.mob=ranmob()
        return True
    if sprite.hero.hp<=0:
        sprite.mob.exp+=sprite.hero.exp
        print("mob xp:",sprite.mob.exp)
        print(sprite.hero.name,'died!')              
        sprite.hero=profession()
        print ("Name: {} HP: {} Thac0: {} AC:{} XP:{}".format(
              sprite.hero.name,sprite.hero.hp,sprite.hero.thaco,sprite.hero.ac,sprite.hero.exp))
        assignStats()
        return True
    else: return False

def combat():
    while checkDead(sprite.mob,sprite.hero)==False:
        encounter(sprite.mob,sprite.hero)

####DICE#####
D2=Die(2)
D4=Die(4)
D6=Die(6)
D8=Die(8)
D10=Die(10)
D12=Die(12)
D20=Die(20)
D100=Die(100)
#############

class sprite:
    hero=profession()
    mob=ranmob()

def gameLoop():    
    assignStats()
    levelUp()
    combat()
    gameLoop()

gameLoop()
\$\endgroup\$
  • 2
    \$\begingroup\$ This question has been flagged as "Unclear what you're asking." It seems to me that it was probably because it's unclear that you're code works as intended. Does it? Please try to clarify your question a bit. \$\endgroup\$ – RubberDuck May 19 '15 at 23:12
2
\$\begingroup\$

First off, I do see a few improvements on your original code, although are there are still some things I'm going to suggest for what you're trying to do now.

  • Add some comments and remove useless ones. Comments are very useful in programming. They help describe what a block of code is doing, and how it does that, but comments like ####DICE#####, or #############, are just plain useless. Comments should be helpful, and clearly describe what a piece of code does, like the below example from a project of mine.

...

 def _final_pass(self):
        """
        Check to make sure that there are no
        NoneTypes left in the array, and if
        there are, change them to the minimum
        tile value.
        """
        for row in self.terrain:
            for tile in row:
                if tile == None:
                    self.terrain[self.terrain.index(row)][row.index(tile)] = self.min_height-1
...

  • As you can see, there is a docstring describing what this function does, and even without the rest of the code as context, someone can still somewhat understand what this does, without needed the rest of the code for context.
  • You still have some whitespace issues. There should be spaces in between operators and variable declaration. For example: variable = value, or variable != value. There should be two spaces between module-level functions and classes, like so:

def function():
    """
    Do X and return Y
    """
    pass


class O(object):
    def f():
        """
        Do X and return Y
        """
        pass

    def g():
        """
        Do X and return Y
        """
        pass

  • Secondly, if you want to get rid of "all the printing", you can create a string variable to store the hallway string in, and just use Python's str.format() method to format it. Here's how you'd do that.

hallway_map = """
|-|
|{}|
|{}|
|{}|
|{}|
|-|
"""

# To print the player at the beginning of the hallway, 
# just format the string like so:
print(hallway_map.format(
    "@", " ", " ", " ",
))

  • This helps remove repeated, redundant code. In general, when programming, you should find areas where your code is repeated, and try to find a way to make it not repeated. In other words, try to remove redundancy.
  • Once again, variables, functions and classes should be in their correct cases. Variables and functions should be in underscore_case, and classes should be in PascalCase.
  • You should have if __name__ == "__main__": mainLoop() when running mainLoop(). See this Stack Overflow question for more details..
  • Finally, please read PEP8, and if you need to check your code, you can use this online tool.

Anyway's once again, I hope that this helped you with your project!

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.