Jump to content

[Python] My game relies heavily on globals, but also gives me syntaxwarning even though the game won't work without them.

Ratchet Miles

How can I make this so that it just doesn't rely on globals altogether?




import random, logging

version = "Alpha 0.2.7 (Windows Edition)"

logging.basicConfig(filename='log.log',level=logging.DEBUG)
logging.debug("Game version: %s" % (version))
logging.debug("If you are experiencing issues, or feel like some commands should be added, copy and paste this log to http://pastebin.com/ and send the link to Ratchet.")

'''
Todo:
-Finish game (duh)
-Decrease lines of code used (If possible)
-Add newgame function
-Newgame on death
-Save system
'''

#intro
print("=< Mildwind by Ratchet Miles >=")
print("\"You can't bring me down\" -Ratchet")
print("Version: %s\n" % (version))

#stats
ponyattack = 0
health = 100
armor = 1
strength = 1
potion = 0
attack = (strength * 10) + ponyattack
stamina = "N/A"
shield = "lol, what shield?"
hint = 3

#actual game
name = input("Identify yourself\n>")

#presets
help = "Objective: The objective of the game is to type commands to beat the game. You simply type a command and read the results.\n\nStats: You can view your stats using the \"stats\" command. Your health is, well, your health. Armor reduces your health damage. Your strength is how strong you are. Potions are a limited resource that restore 50 health per use (This is subject to change). Attack is how much damage you give per hit. Stamina is how much strength you have. This is degraded when you use your shield and regained when the chapter ends. Hints are a limited amount of tips that assist you when you're stuck. These are also known as scrolls.\n\nCommon commands:\n-Help: Brings up this menu.\n-Hint: Gives you a hint as to what to do.\n-Potion: Uses a potion.\n-Attack: Cannot be used all the time, but is used to battle enemies.\n-Shield: Cannot be used all the time, but can give a small amount of damage and regenerate a little health. Uses stamina.\n-Continue, Press forward, Follow, etc: Cannot be used all the time, but is used to progress to the next chapter.\n-Stats: Displays stats such as health.\n-Newname: Gives you the option to change your name.\n-Exit, kill, quit, and close: Close the game."
help = "Objective: The objective of the game is to type commands to beat the game. You simply type a command and read the results.\n\nStats: You can view your stats using the \"stats\" command. Your health is, well, your health. Armor reduces your health damage. Your strength is how strong you are. Potions are a limited resource that restore 50 health per use (This is subject to change). Attack is how much damage you give per hit. Stamina is how much strength you have. This is degraded when you use your shield and regained when the chapter ends. Hints are a limited amount of tips that assist you when you're stuck. These are also known as scrolls.\n\nCommon commands:\n-Help: Brings up this menu.\n-Hint: Gives you a hint as to what to do.\n-Potion: Uses a potion.\n-Attack: Cannot be used all the time, but is used to battle enemies.\n-Shield: Cannot be used all the time, but can give a small amount of damage and regenerate a little health. Uses stamina.\n-Continue, Press forward, Follow, etc: Cannot be used all the time, but is used to progress to the next chapter.\n-Stats: Displays stats such as health.\n-Newname: Gives you the option to change your name.\n-Exit, kill, quit, and close: Close the game."

showstats = "=< STATS >=\nName: %s\nHealth: %s\nArmor: %s\nStrength: %s\nAttack: %s\nStamina: %s\nPotions: %s\nHints: %s"

#functions
def hintfunc():
global hint
if hint > 0:
hint = hint - 1
print(random.choice(randhint))
print("You have %s hint(s) left." % (hint))
else:
print("You currently don't have any hints to use.")

def potionfunc():
global health
global hint
if health == 100:
print("You already have max health.")
elif potion > 0 and health + 50 >= 100:
potion = potion - 1
health = 100
print("Potion used. Your health is now %s" % (int(round(health))))
elif potion > 0 and health + 50 <= 100:
potion = potion - 1
health = health + 50
print("Potion used. Your health is now %s" % (int(round(health))))
else:
print("You don't have any potions to use.")

def statfunc():
print(showstats % (name, int(round(health)), armor, strength, attack, stamina, potion, hint))

def helpfunc():
print(help)

def newnamefunc():
global name
newname = input("Please enter your new name\n>")
while True:
check = input("Are you sure (y/n)?\n>").lower()
if check == "y":
name = newname
print("Your name is now %s" % (name))
break
else:
print("Name left unchanged")
break

def quitfunc():
check = input("Are you sure you want to quit (y/n)?\n>").lower()
while True:
if check == "y":
quit()
else:
break

def surveyfunc():
input("When doing this survey, remember to be very descriptive, and you can't press enter to add a new paragraph. Enter goes to the next question.")
survey1 = input("On a scale of 1 - 10, what do you think of Mildwind so far?\n>")
logging.info("Question 1 \"On a scale of 1 - 10, what do you think of Mildwind so far?\": " + survey1)
survey2 = input("Are there any commands I should add? Where?\n>")
logging.info("Question 2 \"Are there any commands I should add? Where?\": " + survey2)
survey3 = input("What problems have you faced?\n>")
logging.info("Question 3 \"What problems have you faced?\": " + survey3)
survey4 = input("How could I improve the game?\n>")
logging.info("Question 4 \"How could I improve the game?\": " + survey4)
input("Thank you for doing the survey. In order for me to see your answers, you must follow the instructions in the log or readme file.")

def gamewin():
while True:
print("You win.")
print("Don't forget to send me your log if you don't mind (More info about that in the readme file)!")
survey = input("Would you like to take a survey to help me improve my game? The survey answers will be saved in the log file (y/n).\n>").lower()
if survey == "y":
surveyfunc()
quit()
else:
logging.info("END OF SESSION; NO SURVEY")
input("Thank you for playing my game!")
quit()

def gamelose():
while True:
print("You lose.")
survey = input("Would you like to take a survey to help me improve my game? The survey answers will be saved in the log file (y/n).\n>").lower()
if survey == "y":
surveyfunc()
quit()
else:
logging.info("END OF SESSION; NO SURVEY")
input("Thank you for playing my game!")
quit()

def noentryfunc():
print("Invalid entry. (Need help? Try 'hint' or 'help'.)")



#part1
def part1():
print("You awaken in a dungeon. Behind you is a tiny barred window, and in front of you is a barred door. There is a prisoner in the cell across from you and a guard that marches back and forth in the hall.")
haskey = False
hasitems = False
stolen = False
global ponyattack
global health
global armor
global strength
global potion
global attack
global stamina
global shield
global hint
while True:
command = input(">").lower()
logging.info("Part 1:" + command)
if command == "hint":
randhint = ["Maybe the guard has something of use?", "Wait for something to happen?", "Maybe the prisoner has something to say?", "The door can be unlocked.", "I guess all you can do is bash your head against the wall."]
hintfunc()
elif command in ["potion", "use potion"]:
potionfunc()
elif command == "stats":
statfunc()
elif command == "help":
helpfunc()
elif command == "newname":
newnamefunc()
elif command in ["exit", "quit", "kill", "close"]:
quitfunc()
elif command in ["look at window", "look out window", "window"]:
print("You sigh and gaze out the window.")
elif command in ["look at guard", "analyse guard", "guard"]:
print("You notice the guard has something in his pocket. As he walks, it seems to be within your reach.")
elif command in ["bash head into wall", "bang head into wall", "bang head against wall", "bash head against wall"]:
if health > 0:
health = health - (5 / armor)
print("You bashed your head into the wall out of misery. It hurts a little. You lost 5 health.")
else:
print("You bashed your head to death out of misery.")
print("\"Hopeless and Stupid\" ending")
statfunc()
gamelose()
quit()
elif command == "talk to prisoner":
if hasitems == True:
print("I have nothing else to say...")
else:
hasitems = True
potion = potion + 1
print("Greetings %s, today is my last day alive... I must face my death sentence... Take this. It won't be of use to me in my afterlife." % (name))
print("You were given a potion.")
elif command == "wait":
print("You hear a noise coming from the window, when suddenly, the wall breaks down. A man with a wooden metal-plated battering ram bashes the wall down. \"%s, We need your help, only you are capable of killing the dragon. No time to explain right now. Take these items.\"\nYou have been given a steel sword, cheap armor, and a scroll." % (name))
strength = 4
hint = hint + 1
armor = 1.5
attack = (strength * 10) + ponyattack
print("Strength increased to 4, armor increased to 1.5, and a hint added.")
part2()
elif command in ["pickpocket guard", "steal", "pickpocket", "steal from guard", "pick guards pocket", "pick pocket", "take from guard", "reach into guards pocket"]:
if stolen == True:
print("The guard shouts \"Hey, I saw that!\" and shanks you for stealing. You lost 20 health.")
health = health - (20 / armor)
if hint == 0:
hint == 0
else:
hint = hint - 1
while True:
if health > 0:
break
else:
print("You were shanked to death.\n")
print("\"Greedy\" ending")
statfunc()
gamelose()
quit()
else:
print("As the guard passes by, you reach in his pocket and grabbed some items. You found a dagger, scroll, and key.")
strength = 2
hint = hint + 1
attack = (strength * 10) + ponyattack
haskey = True
stolen = True
print("Strength increased to 2, you obtained a key, and a hint added.")
elif command in ["open door", "unlock door"]:
if haskey == True:
print("You open the door. The guard sees you and begins to run towards you. What do you do? (run/attack)")
while True:
choice = input(">")
if choice == "run":
print("As you run, a man came from behind and killed the guard. The man says \"Follow me %s\", and you ran to the exit." % (name))
part2()
elif choice == "attack":
health = health - (50 / armor)
print("You were stabbed by the guard. You lost 50 health.")
while True:
if health > 0:
print("Maybe attacking isn't such a good idea.")
break
else:
print("You were stabbed to death.\n")
print("\"Failed Escape\" ending")
statfunc()
gamelose()
quit()
elif choice in ["potion", "use potion"]:
potionfunc
elif choice == "stats":
statfunc()
else:
noentryfunc()
else:
print("You don't have a key.")
else:
noentryfunc()

#part2
def part2():
logging.info("Part 1 Stats:" + "\n" + showstats % ("Player", int(round(health)), armor, strength, attack, stamina, potion, hint))
print("\nYou just escaped the dungeon, you meet the man who helped you escape. \"%s, you are the world's only hope of defeating the dragon Dracord. Dracord has risen from the dead thanks to a curse casted upon the world. My name is Ruffin and the prophecy says that you can save humanity, that is why I saved you.\"" % (name))
hasitems = False
haskey = False
stolen = False
global ponyattack
global health
global armor
global strength
global potion
global attack
global stamina
global shield
global hint
while True:
command = input(">").lower()
logging.info("Part 2:" + command)
if command == "hint":
randhint = ["This is your chance you run free and be your own man.", "You could follow Ruffin on his quest."]
hintfunc()
elif command in ["potion", "use potion"]:
potionfunc()
elif command == "stats":
statfunc()
elif command == "help":
helpfunc()
elif command == "newname":
newnamefunc()
elif command in ["exit", "quit", "kill", "close"]:
quitfunc()
elif command in ["walk", "run", "continue", "press forward", "move along", "follow ruffin", "follow"]:
print("You follow Ruffin to the Dungeon that the dragon resides in.")
part3()
elif command == "run free":
print("You are a free man now.")
print("\"Careless\" ending")
statfunc()
gamewin()
quit()
else:
noentryfunc()

#part3
def part3():
logging.info("Part 2 Stats:" + "\n" + showstats % ("Player", int(round(health)), armor, strength, attack, stamina, potion, hint))
print("\nYou have chosen to follow Ruffin. On your way to the cave that Dracord resides in, you are stopped by a pack of wolves.")
packhealth = 200
packdead = False
global ponyattack
global health
global armor
global strength
global potion
global attack
global stamina
global shield
global hint
while True:
command = input(">").lower()
logging.info("Part 3:" + command)
if command == "hint":
randhint = ["Try to fight your way out.", "Once you've killed em off, maybe you can press forward."]
hintfunc()
elif command in ["potion", "use potion"]:
potionfunc()
elif command == "stats":
statfunc()
elif command == "help":
helpfunc()
elif command == "newname":
newnamefunc()
elif command in ["exit", "quit", "kill", "close"]:
quitfunc()
elif command in ["attack", "fight"]:
if packdead == True:
print("You and Ruffin look at the dead wolf pack.")
else:
enattack = [1, 2, 5]
packhealth = packhealth - (attack + 15)
health = health - (random.choice(enattack) / armor)
if health <= 0:
print("You were bitten to death.")
print("\"THIS BITES!\" ending")
statfunc()
gamelose()
quit()
elif packhealth <= 0:
packdead = True
potion = potion + 2
print("You and Ruffin attacked the wolves. They are now dead, and you have a health of %s. You also picked up 2 potions." % (int(round(health))))
elif packhealth > 0:
print("You and Ruffin attacked the wolves. The wolves have a health of %s, and you have a health of %s." % (packhealth, int(round(health))))
else:
print("What did you do to get this message?")
elif command in ["walk", "run", "continue", "press forward", "move along", "follow ruffin", "follow"]:
esattack = [0, 4, 10]
esattackgen = random.choice(esattack)
if packhealth > 0:
health = health - (esattackgen / armor)
if health <= 0:
print("You were killed by the pack of wolves.")
print("\"Manbaby\" ending")
statfunc()
gamelose()
quit()
else:
if esattackgen == 0:
print("You and Ruffin escaped from the pack of wolves safely.")
part4()
else:
print("The wolves bit you in the back. Your health is now %s." % (int(round(health))))
print("You can't leave until the wolves are dead.")
else:
print("You continue your journey to defeat Dracord.")
part4()
else:
noentryfunc()

#part4
def part4():
logging.info("Part 3 Stats:" + "\n" + showstats % ("Player", int(round(health)), armor, strength, attack, stamina, potion, hint))
print("\nYou make it to the entrance of the cave. You and Ruffin walk inside. There is a skeleton to the right and the darkness of the cave ahead.")
shieldget = False
global ponyattack
global health
global armor
global strength
global potion
global attack
global stamina
global shield
global hint
while True:
command = input(">").lower()
logging.info("Part 4:" + command)
if command == "hint":
randhint = ["\"I wonder what the skeleton left behind.\" Ruffin thought.", "You can move along if you wish."]
hintfunc()
elif command in ["potion", "use potion"]:
potionfunc()
elif command == "stats":
statfunc()
elif command == "help":
helpfunc()
elif command == "newname":
newnamefunc()
elif command in ["exit", "quit", "kill", "close"]:
quitfunc()
elif command == "ponies!!!":
ponyattack = 15
attack = (strength * 10) + ponyattack
print("You found a purple princess pony. She will now follow you and add 15 damage to your attacks.")
elif command in ["skeleton", "examine skeleton", "examine", "check", "check skeleton", "loot", "loot skeleton", "look at skeleton", "scavenge", "scavenge skeleton"]:
if hasitems == True:
print("You mourn over the death of the knight.")
else:
shieldget = True
stamina = 10
hasitems = True
shield = strength * 5
if armor > 1.4:
print("The armor the skeleton is wearing appears to be weaker than what you're wearing, but he has a shield. You can now use \"shield\" to defend yourself from enemies and give a small amount of damage.")
else:
armor = 1.4
print("The skeleton has a strong chestplate and shield. Your armor is now increased to 1.4. You can now use \"shield\" to defend yourself from enemies and give a small amount of damage.")
elif command in ["walk", "run", "continue", "press forward", "move along", "follow ruffin", "follow"]:
print("You and Ruffin continue into the dark cave.")
end()
else:
noentryfunc()

#end
def end():
logging.info("End Stats:" + "\n" + showstats % ("Player", int(round(health)), armor, strength, attack, stamina, potion, hint))
statfunc()
print("The game isn't done. Don't forget to send me your log if you don't mind (More info about that in the readme file)!")
survey = input("Would you like to take a survey to help me improve my game? The survey answers will be saved in the log file. (y/n)\n>").lower()
if survey == "y":
surveyfunc()
quit
else:
logging.info("END OF SESSION; NO SURVEY")
input("Thank you for playing my game!")
quit

part1()


 


-Ratchet Miles

Link to comment
Share on other sites

Link to post
Share on other sites

Did you just post your entire game code? Try putting it in spoiler tags please

Link to comment
Share on other sites

Link to post
Share on other sites

Without using globals, you need to give your functions some way of getting the information it needs. For this you can pass things in as parameters.

def function_name(param1, param2, ...):    # ...

Since you have a lot of globals, you'll end up having a lot of parameters which isn't nice either. In this case it's better to group your globals in some way. This could be done with classes, named tuples, lists, etc. Classes would probably be best in your case.

class PlayerStats():  # I named it "PlayerStats", but you can name it whatever you like    def __init__(self):  # set up your members with default values        self.health = 100        self.armor = 0        self.strength = 10        #etc

Then you can create and use it like so

player1 = PlayerStats()  # player1 now contains your class objectprint player1.health  # will print 100player1.health = 90  # change the players healthprint player1.health  # will print 90

You can reuse that class as much as you want

p1 = PlayerStats()p2 = PlayerStats()p3 = PlayerStats()p4 = PlayerStats()# ...

You can also make things more dynamic by adding more parameters to init. Maybe you don't want the stats to always be the same for some reason

class PlayerStats():    def __init__(self, health, strength, ...):        self.health = health        self.armor = 0        self.strength = strength        #etc

Then create it like

p1 = PlayerStats(100, 10, ...)

So once you have a class for all your stats (or multiple classes depending on how you wanted to group them) you don't have as much to pass into your functions

def part1(stats):    # ...

So when you start your game instead of just calling part1 you'd set up your classes first

p = PlayerStats(...)part1(p)

Then it'll keep being passed through your application because each function that needs access to the stats will get it

def part1(stats):    # ...    stats.health = 200    # ...    part2(stats)  # will now have the current stats passed to it    # ...

You may also need some functions to return the stats

def function_name(stats):    # update stats in some way    # ...    return stats

And in this case, you'll replace the current stats from other methods with the returned value like so

def part1(stats):    # ...    stats = function_name(stats)    # ...    part2(stats)

That's about it. You could add your logging in through function parameters too if you'd like, but it's generally more accepted that a logger be global. If you have any questions I'll do my best to answer them.

Link to comment
Share on other sites

Link to post
Share on other sites

Without using globals, you need to give your functions some way of getting the information it needs. For this you can pass things in as parameters.

def function_name(param1, param2, ...):    # ...

Since you have a lot of globals, you'll end up having a lot of parameters which isn't nice either. In this case it's better to group your globals in some way. This could be done with classes, named tuples, lists, etc. Classes would probably be best in your case.

class PlayerStats():  # I named it "PlayerStats", but you can name it whatever you like    def __init__(self):  # set up your members with default values        self.health = 100        self.armor = 0        self.strength = 10        #etc

Then you can create and use it like so

player1 = PlayerStats()  # player1 now contains your class objectprint player1.health  # will print 100player1.health = 90  # change the players healthprint player1.health  # will print 90

You can reuse that class as much as you want

p1 = PlayerStats()p2 = PlayerStats()p3 = PlayerStats()p4 = PlayerStats()# ...

You can also make things more dynamic by adding more parameters to init. Maybe you don't want the stats to always be the same for some reason

class PlayerStats():    def __init__(self, health, strength, ...):        self.health = health        self.armor = 0        self.strength = strength        #etc

Then create it like

p1 = PlayerStats(100, 10, ...)

So once you have a class for all your stats (or multiple classes depending on how you wanted to group them) you don't have as much to pass into your functions

def part1(stats):    # ...

So when you start your game instead of just calling part1 you'd set up your classes first

p = PlayerStats(...)part1(p)

Then it'll keep being passed through your application because each function that needs access to the stats will get it

def part1(stats):    # ...    stats.health = 200    # ...    part2(stats)  # will now have the current stats passed to it    # ...

You may also need some functions to return the stats

def function_name(stats):    # update stats in some way    # ...    return stats

And in this case, you'll replace the current stats from other methods with the returned value like so

def part1(stats):    # ...    stats = function_name(stats)    # ...    part2(stats)

That's about it. You could add your logging in through function parameters too if you'd like, but it's generally more accepted that a logger be global. If you have any questions I'll do my best to answer them.

Holy hell, I want to cry. That's working.

-Ratchet Miles

Link to comment
Share on other sites

Link to post
Share on other sites

Without using globals, you need to give your functions some way of getting the information it needs. For this you can pass things in as parameters.

def function_name(param1, param2, ...):    # ...

Since you have a lot of globals, you'll end up having a lot of parameters which isn't nice either. In this case it's better to group your globals in some way. This could be done with classes, named tuples, lists, etc. Classes would probably be best in your case.

class PlayerStats():  # I named it "PlayerStats", but you can name it whatever you like    def __init__(self):  # set up your members with default values        self.health = 100        self.armor = 0        self.strength = 10        #etc

Then you can create and use it like so

player1 = PlayerStats()  # player1 now contains your class objectprint player1.health  # will print 100player1.health = 90  # change the players healthprint player1.health  # will print 90

You can reuse that class as much as you want

p1 = PlayerStats()p2 = PlayerStats()p3 = PlayerStats()p4 = PlayerStats()# ...

You can also make things more dynamic by adding more parameters to init. Maybe you don't want the stats to always be the same for some reason

class PlayerStats():    def __init__(self, health, strength, ...):        self.health = health        self.armor = 0        self.strength = strength        #etc

Then create it like

p1 = PlayerStats(100, 10, ...)

So once you have a class for all your stats (or multiple classes depending on how you wanted to group them) you don't have as much to pass into your functions

def part1(stats):    # ...

So when you start your game instead of just calling part1 you'd set up your classes first

p = PlayerStats(...)part1(p)

Then it'll keep being passed through your application because each function that needs access to the stats will get it

def part1(stats):    # ...    stats.health = 200    # ...    part2(stats)  # will now have the current stats passed to it    # ...

You may also need some functions to return the stats

def function_name(stats):    # update stats in some way    # ...    return stats

And in this case, you'll replace the current stats from other methods with the returned value like so

def part1(stats):    # ...    stats = function_name(stats)    # ...    part2(stats)

That's about it. You could add your logging in through function parameters too if you'd like, but it's generally more accepted that a logger be global. If you have any questions I'll do my best to answer them.

Seriously man, you're a godsend.

-Ratchet Miles

Link to comment
Share on other sites

Link to post
Share on other sites

Seriously man, you're a godsend.

 

Glad I could help. Using classes starts getting you more into Object Oriented Programming which may be new to you, but it's important to learn and it'll improve the design of your game.

 

Here are some additional suggestions for your game.

 


 

1. You might want to think about what else can go into classes. For example, items and enemies might be two good options for classes but it can go much further than that. Game settings, maps/areas, commands, npcs, etc. A class is a way of abstracting data and functions in a way that's more human friendly. You automatically know how things are related (unless your classes are poorly designed).

 

Also, while I didn't mention it, classes can have functions too. Just like data, only give your classes functions if it makes sense to. You don't want to give the PlayerStats a function that calculates if you won the game or not because that doesn't make sense. It's not what PlayerStats was created to handle. But it might be nice to put some stat calculations inside of it.

 

In PlayerStats for example, you have the attack attribute which depends on the strength attribute. So you have two options here.

  1. Define attack in the init method
  2. Create a function for getting the attack.
# Option 1: Attack inside initclass PlayerStats():    def __init__(self, ...):        # ...        self.attack = self.strength * 10 + self.ponyattack  # make sure the others are set first        # ...         # Option 2: Attack as functionclass PlayerStats():    def __init__(self, ...):        # ...    def get_attack():        return self.strength * 10 + self.ponyattack

In option 1, it's up to you to update attack when strength or ponyattack changes. In option 2, get_attack will always use the current strength and ponyattack.

 


 

2. You may want to consider only (or partially) interacting with your class attributes through functions. It'll add a lot of extra code to your function, but you'll be able to handle any special cases that arise. In option 1 above, you can give your class functions for updating strength and ponyattack which then handle updating attack for you as well.

class PlayerStats():    def __init__(self, ...):        # ...        self.attack = self.strength * 10 + self.ponyattack  # make sure the others are set first        # ...    def set_strength(self, value):        self.strength = value        self.attack = self.strength * 10 + self.ponyattack    def increase_strength(self, value):        self.strength += value        self.attack = self.strength * 10 + self.ponyattack    def decrease_strength(self, value):        self.strength -= value        self.attack = self.strength * 10 + self.ponyattack    # and you could have the same three methods for ponyattack

So now instead of doing this

p1 = PlayerStats(...)p1.strength += 10

You'll do this (even though you could still technically do the above even if you had the methods)

p1 = PlayerStats(...)p1.increase_strength(10)

You'll also notice that the line that updates the attack is the same for each method. That means it's a good candidate for it's own function. So in the end, you might have something that looks kind of like a combination of option 1 and option 2 as I originally described. It's all about how you want to design things.

 


 

3. Break up your code into multiple files instead of one large file. Classes for example can go into their own files and you can import them when they need to be used in another file. You can have one file be your main file that contains the code to be run, and move everything else to other files. Import stuff as needed.

 

So if the PlayerStats class was in a file playerstats.py your other files can use it like so

# Option 1import playerstatsp1 = playerstats.PlayerStats(...)# Option 2from playerstats import PlayerStatsp1 = PlayerStats(...)# Option 3from playerstats import *p1 = PlayerStats(...)

As you can see, there's a few different ways to do things. It all depends on what is desired as you can have multiple things (classes, functions, etc) in one file and one method may be preferred over the others.

Link to comment
Share on other sites

Link to post
Share on other sites

Glad I could help. Using classes starts getting you more into Object Oriented Programming which may be new to you, but it's important to learn and it'll improve the design of your game.

 

Here are some additional suggestions for your game.

 


 

1. You might want to think about what else can go into classes. For example, items and enemies might be two good options for classes but it can go much further than that. Game settings, maps/areas, commands, npcs, etc. A class is a way of abstracting data and functions in a way that's more human friendly. You automatically know how things are related (unless your classes are poorly designed).

 

Also, while I didn't mention it, classes can have functions too. Just like data, only give your classes functions if it makes sense to. You don't want to give the PlayerStats a function that calculates if you won the game or not because that doesn't make sense. It's not what PlayerStats was created to handle. But it might be nice to put some stat calculations inside of it.

 

In PlayerStats for example, you have the attack attribute which depends on the strength attribute. So you have two options here.

  1. Define attack in the init method
  2. Create a function for getting the attack.
# Option 1: Attack inside initclass PlayerStats():    def __init__(self, ...):        # ...        self.attack = self.strength * 10 + self.ponyattack  # make sure the others are set first        # ...         # Option 2: Attack as functionclass PlayerStats():    def __init__(self, ...):        # ...    def get_attack():        return self.strength * 10 + self.ponyattack

In option 1, it's up to you to update attack when strength or ponyattack changes. In option 2, get_attack will always use the current strength and ponyattack.

 


 

2. You may want to consider only (or partially) interacting with your class attributes through functions. It'll add a lot of extra code to your function, but you'll be able to handle any special cases that arise. In option 1 above, you can give your class functions for updating strength and ponyattack which then handle updating attack for you as well.

class PlayerStats():    def __init__(self, ...):        # ...        self.attack = self.strength * 10 + self.ponyattack  # make sure the others are set first        # ...    def set_strength(self, value):        self.strength = value        self.attack = self.strength * 10 + self.ponyattack    def increase_strength(self, value):        self.strength += value        self.attack = self.strength * 10 + self.ponyattack    def decrease_strength(self, value):        self.strength -= value        self.attack = self.strength * 10 + self.ponyattack    # and you could have the same three methods for ponyattack

So now instead of doing this

p1 = PlayerStats(...)p1.strength += 10

You'll do this (even though you could still technically do the above even if you had the methods)

p1 = PlayerStats(...)p1.increase_strength(10)

You'll also notice that the line that updates the attack is the same for each method. That means it's a good candidate for it's own function. So in the end, you might have something that looks kind of like a combination of option 1 and option 2 as I originally described. It's all about how you want to design things.

 


 

3. Break up your code into multiple files instead of one large file. Classes for example can go into their own files and you can import them when they need to be used in another file. You can have one file be your main file that contains the code to be run, and move everything else to other files. Import stuff as needed.

 

So if the PlayerStats class was in a file playerstats.py your other files can use it like so

# Option 1import playerstatsp1 = playerstats.PlayerStats(...)# Option 2from playerstats import PlayerStatsp1 = PlayerStats(...)# Option 3from playerstats import *p1 = PlayerStats(...)

As you can see, there's a few different ways to do things. It all depends on what is desired as you can have multiple things (classes, functions, etc) in one file and one method may be preferred over the others.

Now I'm struck trying to figure out how to make a save/load system. I want it to save all the playerstats after each part, and load the playerstats and the last part the player didn't finish.

-Ratchet Miles

Link to comment
Share on other sites

Link to post
Share on other sites

Now I'm struck trying to figure out how to make a save/load system. I want it to save all the playerstats after each part, and load the playerstats and the last part the player didn't finish.

 

The saving/loading to a file shouldn't be bad. You just have to decide how the information you need will be organized. The toughest part may be figuring out how to "resume" your game from any point. This may mean redesigning how each part of your game is called. Just calling part1() to start the game is probably not going to cut it if the person needs to be on a later part of the game when they load their file.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×