**[Start Program](https://replit.com/@Dexter1997/Calculate-Game)**

**Comments**

In Linux you can install a program called fortune. This program gives you a random wisdom each time you execute it. I thought about making a game, where you have to do something before you can read some wise words.

This is "the biggest" program I have written so far. I tried to practise object oriented programming by developing an idea and model the individual structures by using OOP-concepts. So I would like to read comments how to improve the structure of the code.

This game also was written by me in a simplified form in Java and in C, but now I also wanted to try Python. So if you can tell me where there is a better way, a "Python way to do something" for elements of my program, i would be thankful.

I tested the program until I have not found bugs anymore. I hope you will also don't find any bugs.

**Game Description**

You have to solve mathmatical exercises. You gain Experience points, rank points and gold. You can buy attribute upgrades for speed up the reward gaining and unlock new wisdoms from wise persons.

    #!/usr/bin/env python3
    
    from pathlib import Path
    from random import randint
    import os
    import time
    
    # this code is divided into the following parts:
    #	helpful functions
    #	the actual parts of the program (classes, functions)
    #	the starting part
    
    ### helpful functions
    
    def saveIntInput(string):
    	try:
    		number = int(input(string))
    		return number
    	except ValueError:
    		print("Please enter a number.")
    		return 0
    		
    ### parts of the program
    
    class Player:
    	rankString = ["Pupil", "Teacher's Favorite", "Freshman", "Junior", "Graduate", "College Student", 
    				  "Bachelor of Science", "Master of Science", "Doctor of Mathematics", "Professor", 
    				  "Researcher", "Nobel Laureate", "Superman", "Chuck Norris", "Better than Chuck Norris", 
    				  "Nearly the best rank", "Very good", "Very very good", "Nearly the best", "The Best", 
    				  "A true Mathematician"]
    	
    	def __init__(self):
    		self.save = Path(".save/player")
    		if self.save.is_file():
    			self.save = open(".save/player", "r")
    			self.save.readline() # skip version detection (maybe needed later)
    			
    			self.level = int(self.save.readline())
    			self.experience = int(self.save.readline())
    			self.experienceNeeded = int(self.save.readline())
    			
    			self.rank = int(self.save.readline())
    			self.rankPoints = int(self.save.readline())
    			self.rankPointsNeeded = int(self.save.readline())
    			
    			self.attributePoints = int(self.save.readline())
    			self.gold = int(self.save.readline())
    			
    			# attributes
    			self.luck = int(self.save.readline()) # improves gold gaining
    			self.knowledge = int(self.save.readline()) # improves experience gaining
    			self.wisdom = int(self.save.readline()) # improves wisdom gaining
    
    			self.save.close()
    		else:
    			self.level = 1
    			self.experience = 0
    			self.experienceNeeded = 10
    			
    			self.rank = 1
    			self.rankPoints = 0
    			self.rankPointsNeeded = 10
    			
    			self.attributePoints = 0
    			self.gold = 0
    			
    			# attributes
    			self.luck = 1
    			self.knowledge = 1
    			self.wisdom = 1
    			
    		self.trainer = Trainer(self)
    		self.wiseWords = WiseWords(self)
    			
    			
    	def __str__(self):
    		string =  "Level            : " + str(self.level) + "\n"
    		string += "Experience       : " + str(self.experience) + " / " + str(self.experienceNeeded) + "\n\n"
    		
    		if self.rank < 20:
    			string += "Rank             : " + self.rankString[self.rank - 1] + "\n"
    		else:
    			string += "Rank             : " + self.rankString[19] + "\n"
    		string += "Rank points      : " + str(self.rankPoints) + " / " + str(self.rankPointsNeeded) + "\n\n"
    		
    		string += "Gold:            : " + str(self.gold) + "\n"
    		string += "Attribute Points : " + str(self.attributePoints) + "\n\n"
    		
    		string += "Luck Level       : " + str(self.luck) + "\n"
    		string += "Knowledge Level  : " + str(self.knowledge) + "\n"
    		string += "Wisdom Level     : " + str(self.wisdom)
    		return string
    		
    	def saveToFile(self):
    		self.save = open(".save/player", "w")
    		self.save.write("v1\n") # version of program
    		# is needed maybe later to convert save files from old versions to new version,
    		# if old version is detected
    		self.save.write(str(self.level) + "\n")
    		self.save.write(str(self.experience) + "\n")
    		self.save.write(str(self.experienceNeeded) + "\n")
    		
    		self.save.write(str(self.rank) + "\n")
    		self.save.write(str(self.rankPoints) + "\n")
    		self.save.write(str(self.rankPointsNeeded) + "\n")
    		
    		self.save.write(str(self.attributePoints) + "\n")
    		self.save.write(str(self.gold) + "\n")
    		
    		self.save.write(str(self.luck) + "\n")
    		self.save.write(str(self.knowledge) + "\n")
    		self.save.write(str(self.wisdom) + "\n")
    		self.save.close()
    		
    	def reward(self, value):
    		if value:
    			goldReward = int((1 + (0.1 * self.rank)) * self.luck)
    			experienceReward = int((1 + (0.1 * self.rank)) * self.knowledge)
    			rankPointsReward = int((1 + (0.1 * self.rank)) * self.wisdom)
    			
    			self.gold += goldReward
    			self.experience += experienceReward
    			self.rankPoints += rankPointsReward
    			
    			print("Gold +", goldReward)
    			print("Exp  +", experienceReward)
    			print("RP   +", rankPointsReward)
    			self.increaseLevel()
    			self.increaseRank()
    			self.saveToFile()
    		else:
    			print("You get no reward")
    	
    	def increaseLevel(self):
    		while(self.experience >= self.experienceNeeded):
    			self.level += 1
    			self.attributePoints += 2
    			print("\nLevel Up!\n")
    			time.sleep(1)
    			self.experience -= self.experienceNeeded
    			self.experienceNeeded = 5 * self.level ** 2 + 5 * self.level
    			self.wiseWords.increaseLimit(2)
    			
    	def increaseRank(self):
    		while(self.rankPoints >= self.rankPointsNeeded):
    			self.rank += 1
    			print("\nYou have a new Rank!")
    			self.rankPoints -= self.rankPointsNeeded
    			self.rankPointsNeeded *= 2	
    			time.sleep(1)
    			
    class Trainer:
    	def __init__(self, player):
    		self.save = Path(".save/trainer")
    		
    		if self.save.is_file():
    			self.save = open(".save/trainer", "r")
    			self.luckExpense = int(self.save.readline())
    			self.knowledgeExpense = int(self.save.readline())
    			self.wisdomExpense = int(self.save.readline())
    			self.luckGoldLevel = int(self.save.readline())
    			self.knowledgeGoldLevel = int(self.save.readline())
    			self.wisdomGoldLevel = int(self.save.readline())
    			self.save.close()
    		else:
    			self.luckExpense = 10 # refers to gold
    			self.knowledgeExpense = 10
    			self.wisdomExpense = 10
    			# neccessary for calculating new price
    			self.luckGoldLevel = 1 
    			self.knowledgeGoldLevel = 1
    			self.wisdomGoldLevel = 1
    		
    		self.player = player
    		
    	def saveToFile(self):
    		self.save = open(".save/trainer", "w")
    		self.save.write(str(self.luckExpense) + "\n")
    		self.save.write(str(self.knowledgeExpense) + "\n")
    		self.save.write(str(self.wisdomExpense) + "\n")
    		self.save.write(str(self.luckGoldLevel) + "\n")
    		self.save.write(str(self.knowledgeGoldLevel) + "\n")
    		self.save.write(str(self.wisdomGoldLevel) + "\n")
    		self.save.close()
    		
    	def train(self): 
    		print("Gold has to be payed only if there are no attribute points remained")
    		print("[0] Leave")
    		while True:
    			print("Gold:", self.player.gold, "  AP:", self.player.attributePoints)
    			print("[1] Luck (costs", self.luckExpense, "Gold)")
    			print("[2] Knowledge (costs", self.knowledgeExpense, "Gold)")
    			print("[3] Wisdom (costs", self.wisdomExpense, "Gold)")
    			command = input("> ")
    			print()
    			
    			# following code looks redundant, is there a good way to change that without reduce readability?
    			
    			if command == "1":
    				if self.player.attributePoints > 0:
    					self.player.luck += 1
    					print("Luck increased!")
    					self.player.attributePoints -= 1
    					print("One attribute point was used.")
    				elif self.player.gold >= self.luckExpense:
    					self.player.luck += 1
    					print("Luck increased!")
    					self.player.gold -= self.luckExpense
    					print(self.luckExpense, "gold was payed.")
    					self.luckGoldLevel += 1
    					self.luckExpense = 5 * self.luckGoldLevel ** 2 + 5 * self.luckGoldLevel
    				else:
    					print("You can not affort that")
    				time.sleep(1)
    			elif command == "2":
    				if self.player.attributePoints > 0:
    					self.player.knowledge += 1
    					print("Knowledge increased!")
    					self.player.attributePoints -= 1
    					print("One attribute point was used.")
    				elif self.player.gold >= self.knowledgeExpense:
    					self.player.knowledge += 1
    					print("Knowledge increased!")
    					self.player.gold -= self.knowledgeExpense
    					print(self.knowledgeExpense, "gold was payed.")
    					self.knowledgeGoldLevel += 1
    					self.knowledgeExpense = 5 * self.knowledgeGoldLevel ** 2 + 5 * self.knowledgeGoldLevel
    				else:
    					print("You can not affort that")
    				time.sleep(1)
    			elif command == "3":
    				if self.player.attributePoints > 0:
    					self.player.wisdom += 1
    					print("Wisdom increased!")
    					self.player.attributePoints -= 1
    					print("One attribute point was used.")
    				elif self.player.gold >= self.wisdomExpense:
    					self.player.wisdom += 1
    					print("Wisdom increased!")
    					self.player.gold -= self.wisdomExpense
    					print(self.wisdomExpense, "gold was payed.")
    					self.wisdomGoldLevel += 1
    					self.wisdomExpense = 5 * self.wisdomGoldLevel ** 2 + 5 * self.wisdomGoldLevel
    				else:
    					print("You can not affort that")
    				time.sleep(1)
    					
    			elif command == "0":
    				break
    			self.saveToFile()
    			print()
    			
    class WiseWords:
    	# encrypted with a super-secret algorithm
    	wiseWords = [
    	"ehteoG nov .W .J - .emag gninniw a trats yam yeht tub ,netaeb eb yam yehT .drawrof devom nemssehc ekil era saedi gniraD",
    	"sdlavroT suniL - .smargorp wen etirw tonnac ohw elpoep rof si ytilibatroP",
    	"ehteoG nov .W .J - ?sruoy fo ti si ssenisub tahw ,uoy evol I fI",
    	"sdlavroT suniL - edoc eht em wohS .paehc si klaT",
    	"sdlavroT suniL - .elpoep druH eht ekil pu dne t'now uoy ebyam dna ,SGURD OT ON yas tsuj :trohs nI",
    	"namllatS drahciR - .dlrow eht tpecca t'nod I !tihslluB .dlrow eht tpecca dluohs I dias elpoeP",
    	")POO fo rotnevnI( yaK nalA - .SOD-SM ecnis gnitupmoc tih ot gniht gnissertsid tsom eht si avaJ",
    	"yaK nalA - .dnim ni ++C evah ton did I uoy llet nac I dna detneirO-tcejbO mret eht detnevni I",
    	"namllatS drahciR - .ecirp ton ,ytrebil fo rettam a si erawtfos eerF",
    	"ehteoG nov .W .J - .yawa nur d'I ,flesym wenk I fI ?flesyht wonKmlehliW resiaK - .dlrow eht reuqnoc lliw I dna reeb sevol ylurt ohw namow a em eviG",
    	"setaG lliB - enoyreve rof hguone eb lliw etyboliK 046",
    	"eM - .ynnuf era setouq-avaJ-itna eht tub ,avaJ ekil",
    	"nwonknU - evil uoy erehw swonk ohw htapohcysp tneloiv a eb lliw edoc ruoy gniniatniam pu sdne ohw yug eht fi sa edoc syawlA",
    	".margorp avaJ a etirw yllautneve lliw meht fo eno ,sdraobyek noillim a ta syeknom noillim a tup uoy fI",
    	"nwonknU - .yrotcaFmelborP a evah I woN .avaj htiw melborP a evlos ot deirt I",
    	"nwonknU - .tib a yb ffo ylno era uoy ,gnorw era uoy fi neve si naeloob a tuoba gniht tseb ehT",
    	"latkO - .gnitsil yrotcerid xinU a ni pu wohs t’ndluow ti os teN. deman tfosorciM kniht I",
    	"redniL guoD - .teerts yaw-eno a gnissorc erofeb syaw htob skool syawla ohw enoemos si remmargorp doog A",
    	"gnireenignE erawtfoS fo waL s’rehsoM - boj a fo tuo eb d’uoy ,did gnihtyreve fI .thgir krow t’nseod ti fi yrrow t’noD",
    	".margorp avaJ a etirw yllautneve lliw meht fo eno ,sdraobyek noillim a ta syeknom noillim a tup uoy fI"]
    	amount = len(wiseWords)
    	
    	def __init__(self, player):
    		self.save = Path(".save/wisdom")
    		if self.save.is_file():
    			self.save = open(".save/wisdom", "r")
    			self.limit = int(self.save.readline())
    			self.unlocked = int(self.save.readline())
    			self.expenses = int(self.save.readline())
    			self.save.close()
    		else:
    			self.limit = 2 # limit of wisdom you can unlock
    			self.unlocked = 1 # number of unlocked wisdoms
    			self.expenses = 10 # for buying a new wisdom
    		
    		self.player = player
    		
    	def saveToFile(self):
    		self.save = open(".save/wisdom", "w")
    		self.save.write(str(self.limit) + "\n")
    		self.save.write(str(self.unlocked) + "\n")
    		self.save.write(str(self.expenses) + "\n")
    		self.save.close()
    		
    	def overview(self):
    		print("[0] Leave")
    		while(True):
    			print("Wisdoms unlocked: ", self.unlocked, "/", self.limit)
    			print("[1] Buy new Wisdom (costs", self.expenses, "gold)")
    			print("[2] Give me a random Wisdom")
    			print("[3] Show all wisdoms")
    			command = input("> ")
    			print()
    			
    			if command == "1":
    				self.buyWisdom()
    				time.sleep(1)
    			elif command == "2":
    				self.showRandomWisdom()
    				time.sleep(1)
    			elif command == "3":
    				self.showAllWisdoms()
    				time.sleep(1)
    			elif command == "0":
    				break
    			print()
    
    	def buyWisdom(self):
    		if self.player.gold >= self.expenses and self.unlocked < 20:
    			self.unlocked += 1
    			print(self.wiseWords[self.unlocked - 1][::-1])
    			self.player.gold -= self.expenses
    			self.expenses = 5 * self.unlocked ** 2 + 5 * self.unlocked
    			self.saveToFile()
    		elif self.player.gold < self.expenses:
    			print("You have not enough gold.")
    		else:
    			print("You allready have unlocked all wisdoms")
    	
    	def showRandomWisdom(self):
    		print(self.wiseWords[randint(0, self.unlocked - 1)][::-1])
    	
    	def showAllWisdoms(self):
    		for i in range(self.unlocked):
    			print(self.wiseWords[i][::-1])
    	
    	def increaseLimit(self, value):
    		if self.limit + value <= self.amount:
    			self.limit += 2
    			print("You can buy", value, "new wisdoms")
    			self.saveToFile()
    			time.sleep(1)
    	
    			
    class Exercise:
    	def __init__(self, number1, number2, solution, string):
    		self.number1 = number1
    		self.number2 = number2
    		self.solution = solution
    		self.string =  string
    			
    	def getRandomExercise():
    		type = randint(1, 4) # + - * /
    		if type == 1:
    			n1 = randint(5, 25); n2 = randint(5, 25)
    			return Exercise(n1, n2, n1 + n2, str(n1) + " + " + str(n2) + " = ")
    		if type == 2:
    			n1 = randint(5, 25); n2 = randint(5, 25)
    			return Exercise(n1, n2, n1 - n2, str(n1) + " - " + str(n2) + " = ")
    		if type == 3:
    			n1 = randint(5, 15); n2 = randint(5, 15)
    			return Exercise(n1, n2, n1 * n2, str(n1) + " * " + str(n2) + " = ")
    		if type == 4:
    			n1 = randint(10, 100); n2 = randint(2, 15)
    			return Exercise(n1, n2, int(n1 / n2), str(n1) + " / " + str(n2) + " = ")
    			
    	def calculate(self):
    		guess = saveIntInput(self.string)
    		print()
    		if guess == self.solution:
    			return True
    		else:
    			return False
    			
    class Game:
    	def __init__(self):
    		self.player = Player()
    	
    	def mainLoop(self):
    		print("Division Exercises have to be solved without rest.")
    		print("[0] Leave")
    		while(True):
    			print("[1] Show Character")
    			print("[2] Calculate")
    			print("[3] Improve Attributes")
    			print("[4] Give me a Wisdom")
    			command = input("> ")
    			print()
    			
    			if command == "1":
    				print(self.player, "\n")
    			elif command == "2":
    				iterations = saveIntInput("How much times: ")
    				print()
    				for i in range(iterations):
    					exercise = Exercise.getRandomExercise()
    					self.player.reward(exercise.calculate())
    					print()
    			elif command == "3":
    				self.player.trainer.train()
    			elif command == "4":
    				self.player.wiseWords.overview()
    				
    			elif command == "0":
    				break
    			
    ### starting
    			
    if not os.path.exists(".save"):
        os.makedirs(".save")
    			
    game = Game()
    game.mainLoop()