Skip to main content
2 of 6
edited tags
Ludisposed
  • 11.6k
  • 2
  • 39
  • 91

Python - A Calculating game with wise words

Start Program:

https://repl.it/@Dexter1997/YouthfulEmotionalFulmar

Personal 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 till i have not found bugs anymore. I hope you will also dont find any bugs.

Thank you for your attention!

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           : " + 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()
Dexter Thorn
  • 2.2k
  • 2
  • 22
  • 37