I'm following a Python course on Udemy.com and we are practicing Python by building an RPG game. So far the game was working fine for a single player but as soon as we added 3 players the game seems to just get stuck after executing all 3 players attacks.
The concept is that there are 3 players or so, as the game starts the player stats are shown, after all the players have attacked each other this includes the enemy as well, the player stats are printed as shown below in the picture and the game asks for input from all the three players again, but it's just running once as shown below in the picture.
I followed the code for word to word and also posted a question regarding it. So I thought I should try StackoverFlow.
Below is my code kindly see why is it not going in loop as it should.
Mainfile
# -*- coding: utf-8 -*-
from game_class.invin import Item
from game_class.game import player
from game_class.magic import Spell
import time
# Player and Enemies magic create
Fire_Shot = Spell('Fire Shot', 10, 45, "Black Magic")
Thunder_Storm = Spell("Thunder Storm",25,65,"Black Magic")
Ninja_Summon = Spell("Ninja Summon",45,75,"Ninjustu")
The_End = Spell("THE END",80,300,"Finisher")
Heal = Spell("HEAL ME",60,140,'Heal')
player_magic = [Fire_Shot,Thunder_Storm,Ninja_Summon,Heal,The_End]
enemy_magic = [
{'Name': "Big Punch", 'cost': 30, "DMG": 45},
{'Name': "Slap", 'cost': 15, "DMG": 25},
{'Name': "Rock Throw", 'cost': 20, "DMG": 30},
{'Name': "Kick", 'cost': 45, "DMG": 60}
]
boss_magic = [
{'Name': "STORM", 'cost': 10, "DMG": 45},
{'Name': "DARK BACK-BITTING", 'cost': 10, "DMG": 25},
{'Name': "D.D.T", 'cost': 10, "DMG": 30}
]
# Items create
potion = Item("Potion", 'Potion', 'Heals for 50 HP', 50)
high_potion = Item("Potion+", 'Potion', 'Heals for 120 HP', 120)
super_potion = Item("Ultra Potion", 'Potion', 'Heal for 250 HP', 250)
elixir = Item("Elixir", 'Elixir', 'Give 1 EVERYTHING BACK', 9000)
high_elixir = Item("Omega Elixir", 'Elixir', 'Give all EVERYTHING BACK', 9000)
bomb = Item("Bomb",'Attack','Deals 350 Damage',350)
player_items = [ {"item":potion,"quantity":3},
{'item':high_potion,"quantity":2}
,{"item":super_potion,"quantity":1}
,{'item':elixir,"quantity":2}
,{'item':high_elixir,"quantity":1}
,{"item": bomb, "quantity": 2} ]
# PLAYER CREATE
Player1 = player('Night Man ',1000, 100, 145, 140, player_magic, player_items)
Player2 = player('Ray Wills ', 1000, 100, 155, 135, player_magic, player_items)
Player3 = player("Randy Orton",1000, 100, 150, 120, player_magic, player_items)
Enemy1 = player("Door Keeper",1500, 200, 250, 150, enemy_magic, None)
BOSS = player("Boss Man",1200, 200, 45, 300, boss_magic, None)
players = [Player1,Player2,Player3]
# Game starts
run = True
i = 1
while run is True:
print ("=======================================")
print("\n\n")
print(" NAME HP MP\n")
for player in players:
player.get_stats()
for player in players:
print("\n")
player.chose_action()
print("=========\n")
print (player.name)
print ("=============")
choice = input("CHOSE ACTION: ")
index = int(choice) - 1
if index == 0:
dmg = player.gen_dmg()
Enemy1.get_dmg(dmg)
print(player.name+ " attacked for " + str(dmg) + " damage points")
elif index == 1:
player.chose_magic()
magic_choice = (int(input("Chose Spell: ")) - 1)
spell = player.magic[magic_choice]
magic_dmg = spell.gen_spell_dmg()
current_mp = player.get_mp()
if magic_choice == -1:
continue
if spell.cost > current_mp:
print ("\nNOT ENOUGH MANA")
continue
if spell.stype == "Heal":
player.heal(magic_dmg)
print (str(magic_dmg) +' HP restored')
print("Remaining Magic Points: " + str(player.get_mp()) +
"/" + str(player.get_max_mp()))
elif spell.stype == "Black Magic" or spell.stype == "Ninjustu" or spell.stype == "Finisher":
player.reduce_mp(spell.cost)
Enemy1.get_dmg(magic_dmg)
print (str(spell.name) + ' did damage of '+ str(magic_dmg) +" points")
print ("Remaining Magic Points: " + str(player.get_mp()) +"/" +str(player.get_max_mp()))
elif index == 2:
player.chose_item()
item_choice = (int(input("Chose Spell: ")) - 1)
if item_choice == -1:
continue
item = player.items[item_choice]['item']
if player.items[item_choice]['quantity'] == 0:
print("No Item...")
continue
player.items[item_choice]['quantity'] -= 1
if item.itype == 'Potion':
player.heal(item.prop)
print("\n"+ str(item.name) + " used and healed for "+ str(item.prop) + " HP")
elif item.itype == "Elixir":
player.hp = Player1.maxhp
player.mp = Player1.maxmp
print ("\n"+"STATS RESTORED BECASUE OF " +str(item.name))
elif item.itype == "Attack":
Enemy1.get_dmg(item.prop)
print ("You used a Bomb & that dealt damage of: " + str(item.prop))
enemy_choice = 1
enemy_dmg = Enemy1.gen_dmg()
Player1.get_dmg(enemy_dmg)
print("========================================")
print("\n")
print ("ENEMY ATTACKED YOU FOR " + str(enemy_dmg) + " POINTS")
print ("ENEMY HP: "+str(Enemy1.get_hp()) +'/'+ str(Enemy1.get_maxhp()))
if Enemy1.get_hp() == 0:
print('')
print ('ENEMY DEAD')
run = False
elif Player1.get_hp() == 0:
print('')
print('YOU DIED')
run = False
elif index == 3:
print("Arigato Gozaimasu for playing")
time.sleep(1)
print ("BYE BYE")
run = False
invin.py
class Item:
def __init__(self, name,itype,desc,prop):
self.name = name
self.itype = itype
self.desc = desc
self.prop = prop
magic.py
import random
class Spell():
def __init__(self, name, cost,dmg,stype):
self.name = name
self.cost = cost
self.dmg = dmg
self.stype = stype
def gen_spell_dmg(self):
low = self.dmg - 15
high = self.dmg + 10
return random.randrange(low,high)
game.py
# -*- coding: utf-8 -*-
from .magic import Spell
import random
class player:
def __init__(self,name, hp , mp , atk ,df ,magic,items):
self.hp = hp
self.name = name
self.items = items
self.mp = mp
self.magic = magic
self.df = df
self.maxhp = hp
self.atkH = atk + 25
self.atkL= atk - 10
self.actions=['Attack',"Magic","Items"]
self.maxmp = mp + 10
def gen_dmg(self):
return random.randrange(self.atkL,self.atkH)
def get_dmg(self,dmg):
self.hp -= dmg
if self.hp < 0:
self.hp = 0
return self.hp
def get_hp(self):
return self.hp
def get_maxhp(self):
return self.maxhp
def get_max_mp(self):
return self.maxmp
def get_mp(self):
return self.mp
def reduce_mp(self,cost):
self.mp -= cost
def spell_cost(self, i):
return self.magic[i]["cost"]
def chose_action(self):
print ("Actions")
print ("===========")
i = 1
for item in self.actions:
print(" " + str(i)+":" + str(item))
i += 1
def chose_magic(self):
print ("Spells")
print ("===========")
i = 1
for spell in self.magic:
print (" " + str(i) + ": " + str(spell.name) + str( " (Cost: " + str ( spell.cost ) +")" ) )
#the 3rd str helps to print it without the brackets
i += 1
def chose_item(self):
print ("Items")
print ("===========")
i = 1
for item in self.items:
print(" " + str(i) + ": " +
str(item['item'].name) + str(" (" + str(item['item'].desc) + ") ") + " (x"+str(item['quantity'])+")")
#the 3rd str helps to print it without the brackets
i += 1
def heal(self,dmg):
self.hp += dmg
def get_stats(self):
hp_bar = ''
bar_ticks = ( (self.hp/self.maxhp) * 100 ) / 4
mp_bar = ''
mp_bar_ticks = ( (self.mp/self.maxmp) * 100 ) / 10
while bar_ticks > 0:
hp_bar += '█'
bar_ticks -= 1
while len(hp_bar) < 25:
hp_bar = " "
while mp_bar_ticks > 0:
mp_bar += '▒'
mp_bar_ticks -= 1
while len(mp_bar) < 10:
mp_bar = " "
hp_string = str(self.hp) + "/"+str(self.maxhp)
current_hp = ''
if len(hp_string) < 9:
decreased = 9 - len(hp_string)
while decreased > 0:
current_hp += ' '
decreased -= 1
current_hp += hp_string
else:
current_hp = hp_string
mp_string = str(self.mp) +"/"+str(self.maxmp)
current_mp = ''
if len(mp_string) < 9:
mp_decreased = 9 - len(mp_string)
while mp_decreased > 0:
current_mp += ' '
mp_decreased -= 1
current_mp += mp_string
else:
current_mp = mp_string
print(" _________________________ __________")
print(str(self.name) + " " + str(hp_string) +
" |"+ hp_bar+"| " + str(mp_string) + " |"+mp_bar+"|")
The game is an RPG replica and it works by using while loop.
Each player gets a turn and then the player stats are shown after all 3 players have attacked.
This is how the loop should show player stats after all 3 players attacked
But I'm getting this
If we compare the "This is how the loop should show player stats after all 3 players attacked" and "But I'm getting this" screenshots, we can see, by looking at the code, that the issue is caused on the second run of player.get_stats(). This method is defined in the game.py file.
Inside the method we can see the following 2 lines of code:
while len(hp_bar) < 25:
hp_bar = " "
If the while-loop ever gets to run, it will be stuck forever. This is because if len(hp_bar) < 25 is True, the code does hp_bar = " ", which in turns makes len(hp_bar) to be equal to 1 now. This now gets the while loop to check if len(hp_bar) < 25 again, which returns True (as len(hp_bar) is 1) so the while-loop runs again. This creates an endless loop.
Related
I am trying to make it so that the user can input the name of another pokemon class so that I can use the attack function. Is there any way I could do this from user input? It seems as though even when I put in a valid name it returns an error. I would love to know as to how I can do this so that I can finish my game.
import random
class Pokemon(object):
def __init__(self, name, level, pokemon_type, max_health, current_health, is_knocked_out):
self.name = name
self.level = level
self.pokemon_type = pokemon_type
self.current_health = current_health
self.max_health = max_health
self.is_knocked_out = is_knocked_out
#knock out function
def knock_out(self):
self.is_knocked_out = True
print(self.name + " is now knocked out")
#lose health func, takes in one parameter which is damage
def lose_health(self, amount):
if amount > self.current_health:
print(self.name + " has been knocked out and now has 0 hp")
self.current_health = 0
self.is_knocked_out = True
else:
self.current_health -= amount
print(self.name + " now has " + str(self.current_health) + " HP")
#hp regen function, takes in one parameter which is the amount of hp to be regained, wont allow you to go above the max
def regain_health(self, amount):
if amount > self.max_health:
print("You cannot heal past your max HP")
else:
self.current_health += amount
print(self.current_health)
#function to revive dead mons
def revive(self):
if self.is_knocked_out == True:
self.is_knocked_out = False
print(self.name + " has been revived and half of his hp has been restored!")
self.current_health = self.max_health / 2
else:
print("This pokemon is still alive ")
return
#attack function, in progress
def attack(self, pokemon_name, move_number):
if self.current_health > 0 and self.is_knocked_out == False:
if move_number == 1:
pokemon_name.lose_health(random.randint(1,150)) #Here is where the issue is, how can I make user input determine the name of the pokemon which is being attacked and sequentially make it lose HP?
print(pokemon_name + " was attacked")
elif move_number == 2:
pass
elif move_number == 3:
pass
elif move_number == 4:
pass
else:
print("You are knocked out!")
Lucario = Pokemon("Lucario", 12, "fighting", 200, 200, False)
Blastoise = Pokemon("Blastoise", 12, "water", 200,200, False)
Blastoise.attack("Lucario", 1)
just use:
if move_number == 1:
globals()[pokemon_name]
what is globals()? it's a built-in function that load all global variable (predefined or user-defined), it's a dictionary
data = 5
globals()["data"]
every variable you defined, it will be added to globals() as
globals()[name] = value
def attack(self, pokemon, move_number):
if self.current_health > 0 and self.is_knocked_out == False:
if move_number == 1:
pokemon.lose_health(random.randint(1,150)) #Here is where the issue is, how can I make user input determine the name of the pokemon which is being attacked and sequentially make it lose HP?
print(pokemon.name + " was attacked")
elif move_number == 2:
pass
elif move_number == 3:
pass
elif move_number == 4:
pass
else:
print("You are knocked out!")
Characters = dict()
Characters["Lucario"] = Pokemon("Lucario", 12, "fighting", 200, 200, False)
Characters["Blastoise"] = Pokemon("Blastoise", 12, "water", 200,200, False)
Characters["Blastoise"].attack(Characters["Lucario"], 1)
you also can use dictionary. what is dictionary? a dictionary is a collection of named variable, like list, but you can add to it by name...
how to define dictionary?
Characters = dict()
and add your variables:
Characters["<name>"] = value
like:
Characters["Blastoise"] = Pokemon("Blastoise", 12, "water", 200,200, False)
and use variables:
Characters["<name>"].<your-method>
like:
Characters["Blastoise"].attack(Characters["Lucario"], 1)
just one point: if you use dictionary, so you send variable (Pokemon object, not it's name), so attack's second parameter is pokemon and use:
print(pokemon.name + " was attacked")
i have a problem with creating a dict in python.
In my mainloop i call function 1 which should creat an empty dict.
function 1 calls function 2.
function 2 calls itself (loop through a game tree)
but i can not use the dict i created in f1.
and it is not possible to pass it as agrument.
i would like to have the dict globaly accessible
def f1(): # function 1
#test_dict = {} # this needs to be global scope
#test_dict["key"] = "value"
test_dict["key2"] = "value2"
print (test_dict)
f2()
def f2(): # function 2
# here starts a loop that calls f2 again and again -> global dict is needed
# dict needs to be created
print (test_dict)
test_dict = {} # only works without errors when i create it before calling f1
test_dict["key"] = "value"
f1()
Here is my "real" Code :)
The >>MinMaxComputerMove<< need to edit the dict.
but at the end of a nood i cant pass it because the for loop just goes on.
# [] [] []
# [] [] []
# [] [] []
#Input Layer:
#9 Punkte mit -1 (geg.) 0 (leer) 1 (eig.)
from time import sleep
from random import randint
from random import choice
from IPython.display import clear_output
def clearBoard():
board = [0] * 10
return (board)
def drawBoard(board, PlayerSymbol, ComputerSymbol, turn):
turn += 1
#clear_output()
Symbolboard = []
for index, value in enumerate(board):
if value == 1:
Symbolboard.append(PlayerSymbol)
elif value == -1:
Symbolboard.append(ComputerSymbol)
else:
Symbolboard.append(" ")
print ("Turn: " + str(turn))
print ("")
print (str(Symbolboard[7]) + " - " + str(Symbolboard[8]) + " - " + str(Symbolboard[9]))
print ("| \ | / |")
print (str(Symbolboard[4]) + " - " + str(Symbolboard[5]) + " - " + str(Symbolboard[6]))
print ("| / | \ |")
print (str(Symbolboard[1]) + " - " + str(Symbolboard[2]) + " - " + str(Symbolboard[3]))
return (validMoves(board), turn)
def validMoves(board):
#return list with valid indices
validMoveList = []
for index, value in enumerate(board):
if index > 0 and value == 0:
validMoveList.append(index)
return (validMoveList)
def Symbol():
#X always goes first
if randint(0, 1) == 0:
print ("X: YOU")
print ("O: COMPUTER")
return ("X"), ("O")
else:
print ("X: COMPUTER")
print ("O: YOU")
return ("O"), ("X")
def PlayerMove(validMoveList, PlayerSymbol):
PlayerInput = input("Welches Feld? (1-9):")
if int(PlayerInput) in validMoveList:
return (PlayerInput, PlayerSymbol)
else:
print("Falsche Eingabe." + PlayerInput + " kein möglicher Zug")
def ComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, AI):
print("ComputerMove")
if AI == 1:
return RandomComputerMove(validMoveList, ComputerSymbol)
elif AI == 2:
path_dict = {}
return MinMaxComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, depth = 1, firstrun = 1)
# more AIs
# ...
def ComputerThinking():
print("Computer is thinking", end = "")
sleep(0.5)
print(".", end = "")
sleep(0.5)
print(".", end = "")
sleep(0.5)
print(".")
sleep(1)
return
def RandomComputerMove(validMoveList, ComputerSymbol):
ComputerChoice = choice(validMoveList)
ComputerThinking()
print("ComputerChoice: " + str(ComputerChoice))
sleep(1.5)
print("RandomComputerMove Output: " + str((ComputerChoice, ComputerSymbol)))
return (ComputerChoice, ComputerSymbol)
def MinMaxComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, depth, firstrun = 0, start_path = -1):
initial_validMoveList = validMoveList.copy()
initial_board = board.copy()
turns_left = len(initial_validMoveList)
#debug
print("firstrun: " + str(firstrun))
print("depth: " + str(depth))
if firstrun == 1: #first run of function
path_dict = {}
for path, field in enumerate(initial_validMoveList):
path_dict[path] = {}
for extent in range(3):
path_dict[path][extent+1] = 5
#debug
print("---MinMaxComputerMove---")
print("Start MinMaxComputerMove with depth: " + str(depth))
print("validMoveList: " + str(validMoveList) + str(id(validMoveList)))
print("board: " + str(board) + str(id(board)))
print("ComputerSymbol: " + str(ComputerSymbol))
print("start_path: " + str(start_path))
for path, field in enumerate(initial_validMoveList): #(2, 6, 8):
if firstrun == 1:
start_path = path
print("start_path: " + str(start_path))
# for every path in tree diagram create a key in dict with empty list
# goal: dict("path": [field, depth_1_(max)value, depth_2_(min)value, depth_3_(max)value])
#debug
print("depth: " + str(depth))
if depth % 2 == 1: # Computer:
ChoosenIndex = (str(field), ComputerSymbol)
else: # Player
ChoosenIndex = (str(field), PlayerSymbol)
new_board = updateBoard(initial_board.copy(), ChoosenIndex, PlayerSymbol) # copy() or initial_board would change
new_validMoveList = validMoves(new_board)
#debug
print("---For Loop---")
print("ChoosenIndex: " + str(ChoosenIndex) + str(id(ChoosenIndex)))
print("new_validMoveList: " + str(new_validMoveList) + str(id(new_validMoveList)))
print("new_board: " + str(new_board) + str(id(new_board)))
print("path_dict: " + str(path_dict))
print("depth: " + str(depth))
if checkWinner(new_board) == 0 and depth != 3 and turns_left >= 1: # no winner yet and game not over
print ("no winner yet and game not over")
# go deeper
path_dict[start_path][depth] = 0
MinMaxComputerMove(new_validMoveList, new_board, PlayerSymbol, ComputerSymbol, depth + 1, 0, start_path)
elif checkWinner(new_board) == 0 and depth == 3 and turns_left >= 1: # no winner yet and game not over and minmax ends (depth = 3)
print ("checkWinner(new_board) == 0 and depth == 3 and turns_left >= 1")
path_dict[start_path][depth] = 0
elif checkWinner(new_board) == -1: # computer wins
print ("elif checkWinner(new_board) == -1")
if depth % 2 == 1: # Computer -> MIN:
path_dict[start_path][depth] <= -1
else: # Player -> MAX
if path_dict[start_path][depth] > -1:
path_dict[start_path][depth] = -1
elif checkWinner(new_board) == 1: # player wins
print ("elif checkWinner(new_board) == 1")
path_dict[start_path][depth] = 1
elif depth >= 3 or turns_left < 1: # reached depth 3 or no more turns
print ("elif depth >= 3 or turns_left < 1:")
else:
print ("else")
print("--- END FOR PATH ---")
print("--- END FOR LOOP ---")
print(path_dict)
# return choise
return (2, ComputerSymbol)
def updateBoard(board, ChoosenIndex, PlayerSymbol): #[0, 1, -1, 0, ...],[5, "X"], "X"
if PlayerSymbol == ChoosenIndex[1]:
board[int(ChoosenIndex[0])] = 1
return (board)
else:
board[int(ChoosenIndex[0])] = -1
return (board)
def checkWinner(board):
if (board[7] == board[8] == board[9]) and 0 != board[7]: # top row
return board[7]
elif (board[4] == board[5] == board[6]) and 0 != board[4]: # mid row
return board[4]
elif (board[1] == board[2] == board[3]) and 0 != board[1]: # bot row
return board[1]
elif (board[7] == board[4] == board[1]) and 0 != board[7]: # left column
return board[7]
elif (board[8] == board[5] == board[2]) and 0 != board[8]: # mid row
return board[8]
elif (board[9] == board[6] == board[3]) and 0 != board[9]: # right row
return board[9]
elif (board[7] == board[5] == board[3]) and 0 != board[7]: # diagonal \
return board[7]
elif(board[1] == board[5] == board[9]) and 0 != board[1]: # diagonal /
return board[1]
else:
return 0
def GameLoop(AI, turn = 0, winner = 0):
#choose AI difficulty
#...
#...
#set first player (X)
PlayerSymbol, ComputerSymbol = Symbol()
sleep(3)
#init board with list 10 * 0
board = clearBoard()
#debug
board = [0, 1, 0, 1, -1, -1, 0, 1, 0, -1]
PlayerSymbol, ComputerSymbol = ("O", "X") # computer first
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
while winner == 0 and turn <=9:
sleep(1.5)
if turn % 2 == 1: # "X" player move
if PlayerSymbol == "X":
#player move
ChoosenIndex = PlayerMove(validMoveList, PlayerSymbol)
#update current board
board = updateBoard(board, ChoosenIndex, PlayerSymbol)
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
#check for winner
winner = checkWinner(board)
else:
#computer move
ChoosenIndex = ComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, AI)
#update current board
board = updateBoard(board,ChoosenIndex, PlayerSymbol)
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
#check for winner
winner = checkWinner(board)
else: # "O" player move
if PlayerSymbol == "O":
#player move
ChoosenIndex = PlayerMove(validMoveList, PlayerSymbol)
#update current board
board = updateBoard(board,ChoosenIndex, PlayerSymbol)
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
#check for winner
winner = checkWinner(board)
else:
#computer move
ChoosenIndex = ComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, AI)
#update current board
board = updateBoard(board,ChoosenIndex, PlayerSymbol)
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
#check for winner
winner = checkWinner(board)
else:
if winner == 1:
print ("YOU WON!")
elif winner == -1:
print ("COMPUTER WON!")
else:
print ("DRAW!")
GameLoop(AI = 2)
The "return value" answer is:
def f1(test_dict): # function 1
#test_dict = {} # this needs to be global scope
#test_dict["key"] = "value"
test_dict["key2"] = "value2"
print ('In f1 {}'.format(test_dict))
f2(test_dict)
return test_dict
def f2(test_dict): # function 2
# here starts a loop that calls f2 again and again -> global dict is needed
# dict needs to be created
print ('In f2 {}'.format(test_dict))
return test_dict
test_dict = {} # only works without errors when i create it before calling f1
test_dict["key"] = "value"
test_dict = f1(test_dict)
which gives output of:
In f1 {'key2': 'value2', 'key': 'value'}
In f2 {'key2': 'value2', 'key': 'value'}
But at some level, you probably want to put some of this into a class and then have test_dict as a variable within the class. That allows f1 and f2 (assuming they are class methods) to access the class variable without passing it as a parameter to the two methods.
class Example:
def __init__(self):
self._test_dict = {}
self._test_dict["key"] = "value"
def f1(self): # function 1
self._test_dict["key2"] = "value2"
print ('In f1 {}'.format(self._test_dict))
self.f2()
def f2(self): # function 2
print ('In f2 {}'.format(self._test_dict))
example = Example()
example.f1()
Below is a very simply version of what your script is attempting. You need to consider what your function parameters should be (what is passed to the function), as well as what your function should be providing at the end of its execution (given to you with the return statement). This way you can manipulate objects without having to keep everything in global scope, and you can avoid having to initialize every conceivable variable at the start of the routine.
Python Functions
Return Statement
def f1():
f1_dict = {}
f1_dict = f2(f1_dict)
return f1_dict
def f2(dict_arg):
f2_dict = {}
for i in range(0,5):
f2_dict[str(i)] = i**i
return f2_dict
dictionary = f1()
print(dictionary)
The title is terrible, but hopefully I can explain in my post. Creating a little game as my pet project for python, and I'm currently creating the inventory. Everything was... ok when developing the game until it came to making the function that will show all of the player's inventory.
elif (prompt == "examine"):
print(inventory[1].name)
gameprompt()
Ok, so I created a list that basically has a bunch of classes from Items in it. To call on the name element of these classes I have to do something like this, otherwise I just get its memory location which is largely useless to the player. I've tried
elif (prompt == "examine"):
print(inventory[].name)
gameprompt()
Thought that this above example would print only the name of all the Item objects, but there's a compilation error instead because I didn't specify which one. So I then tried~
elif (prompt == "examine"):
print(inventory[1:1000].name)
gameprompt()
Thinking that it would print all of the Item objects names up to 1000, but I obviously don't have that so I thought it would print the names up to the latest object that was there and stop but there was another compilation error from this...
If there is anyway to print out an element of a class for all class objects in a list please let me know. The full code of this game is here, although I don't think you'll need it to help me solve my problem (it is also very large.)
playername = input("What is your name?")
zone = 1
movement = 0
restcounter = 0
searchcounter = 0
class Player:
def __init__(self, name, hp, mp, atk, xp, dodgerate, atkrate):
self.name = playername
self.hp = hp
self.mp = mp
self.atk = atk
self.xp = xp
self.dodgerate = dodgerate
self.atkrate = atkrate
class Enemy(Player):
def __init__(self, name, gold, maxhp, hp, mp, atk, xp):
self.name = name
self.gold = gold
self.maxhp = maxhp
self.hp = hp
self.mp = mp
self.atk = atk
self.xp = xp
class Items:
def __init__(self, name, quantity, description, price, weight):
self.name = name
self.quantity = quantity
self.description = description
self.price = price
self.weight = weight
Player = Player(playername, 1, 1, 1, 1, 25, 3)
print(Player.name + " has been created. ")
def raceselection():
raceinput = input("Do you float towards the TEMPLE, CAVE or FOREST?")
if raceinput == "TEMPLE":
print("You are now a high elf. High elves utlize a lot of magical power at the cost of being very frail.")
Player.hp = Player.hp + 24
Player.mp = Player.mp + 100
Player.atk = Player.atk + 50
print("You awaken from your slumber. Your room's walls are gold plated, and you rested on a flat board.")
print("Out the door, you see many elves with robes praying to some goddess.")
print("You walk out of your door and into the praying area. You are immediately greeted by a tall man.")
elif raceinput == "CAVE":
print("You are now an orc.")
Player.hp = Player.hp + 1000
Player.mp = Player.mp + 15
Player.atk = Player.atk + 50
print("cave")
elif raceinput == "FOREST":
print("You are now a human.")
Player.hp = Player.hp + 50
Player.mp = Player.mp + 25
Player.atk = Player.atk + 25
else:
print("You can't float there!")
raceselection()
raceselection()
inventory = []
def gameprompt():
global inventory
global zone
global movement
global restcounter
global searchcounter
if (movement == 5):
movement = movement - movement
zone = zone + 1
print("You have advanced to zone",zone,"!!!")
gameprompt()
if (zone == 1):
print("Welcome to the first zone! Easy enemies are here with not very good loot./fix grammar, add description of zone/")
elif (zone == 2):
print("Hey, it actually travelled to the second zone, awesome!")
elif (zone == 3):
print("No way would this actually work!")
prompt = input("Would you like to walk, search or rest?: ")
if (prompt == "walk"):
encounterchance = random.randint(1, 3)
if (encounterchance == 2):
if (zone == 1):
mobspawnrate = random.randint(1,3)
if (mobspawnrate == 1):
Enemy = Enemy("Blue SlimeBall", 50, 0, 25, 15, 25, 0.500)
print("You have encountered a " + Enemy.name + "!!!")
elif (mobspawnrate == 2):
Enemy = Enemy("Blue SlimeBall", 50, 0, 25, 15, 25, 0.500)
print("You have encountered a " + Enemy.name + "!!!")
elif (mobspawnrate == 3):
Enemy = Enemy("Blue SlimeBall", 50, 0, 25, 15, 25, 0.500)
print("You have encountered a " + Enemy.name + "!!!")
else:
movement = movement + 1
print("You have walked a step. You are now at ",movement," steps")
gameprompt()
elif (prompt == "search"):
if (searchcounter == 3):
print("You cannot search this area anymore! Wait until you reach the next zone!")
gameprompt()
else:
searchchance = random.randint(1, 5)
if (searchchance == 1 or 2 or 3 or 4):
searchcounter = searchcounter + 1
print(searchcounter)
print("You have found something!")
searchchance = random.randint(1,4)
if (searchchance == 1 or 2):
inventory.append(Items("Old Boot", 1, "An old smelly boot. It's a mystery as to who it belongs to...", 5, 50))
print("You have found a Boot!")
print(inventory)
elif(searchchance == 3):
inventory.append(Items("Shiny Boot", 1, "Looks like a boot that was lightly worn. You could still wear this.", 5, 50))
print(inventory)
print("You have found a Shiny Boot!")
elif(searchchance == 4):
inventory.append(Items("Golden Boot", 1, "It's too heavy to wear, but it looks like it could sell for a fortune!", 5, 50))
print("You have found a Golden Boot?")
print(inventory)
else:
searchcounter = searchcounter + 1
print(searchcounter)
print("You did not find anything of value")
gameprompt()
elif (prompt == "rest"):
if (restcounter == 1):
print("Wait until you reach the next zone to rest again!")
gameprompt()
else:
# Add a MaxHP value to the player later, and the command rest will give 25% of that HP back.
Player.hp = Player.hp + (Player.hp / 5)
print("You have restored ",(Player.hp / 5)," hit points!")
restcounter = restcounter + 1
gameprompt()
elif (prompt == "examine"):
print(inventory[1].name)
gameprompt()
gameprompt()
A list comprehension or map would work perfectly here:
print([item.name for item in inventory])
The comprehension iterates the list, and "replaces" each element in the list with whatever the part before for evaluates to. In this case, it's item.name.
° It actually doesn't replace the element in the original list. It evaluates to a new list full of replaced items.
import random
class Spinner(object):
#staticmethod
def getSpin():
newSpin = random.randint(1,6)
return newSpin
class Player(object):
def __init__(self,name):
self.position = 1
self.name = name
def setName(self,name):
self.name = name
def changePosition(self,number):
self.position = self.position + number
def setPosition(self,pos):
self.position = pos
return self.position
def getPosition(self):
return self.position
def getName(self):
return self.name
def spin(self):
newSpin = Spinner.getSpin()
self.position = self.position + newSpin
print(str(self.name) + "'s spin was: " + str(newSpin))
class Display():
def buildLadders():
ladders = [[0 for x in range(2)] for x in range(2)]
ladders[0][0] = 2
ladders[0][1] = 7
ladders[1][0] = 4
ladders[1][1] = 5
return ladders
def buildChutes():
chutes = [[0 for x in range(2)] for x in range(2)]
chutes[0][0] = 9
chutes[0][1] = 2
chutes[1][0] = 6
chutes[1][1] = 3
return chutes
class Check(Player):
def checkLadders(self):
ladders = Display.buildLadders()
for i in range(0,len(ladders),1):
if self.getPosition() == ladders[i][0]:
self.position = self.setPosition(ladders[i][1])
print(str(self.name) + " Landed on a Ladder! from " + \
str(ladders[i][0]) +" to " + str(ladders[i][1]))
def checkChutes(self):
chutes = Display.buildChutes()
for i in range(0,len(chutes),1):
if self.getPosition() == chutes[i][0]:
self.position = self.setPosition(chutes[i][1])
print(str(self.name) + " Landed on a Chutes! from " + \
str(chutes[i][0]) + " to " + str(chutes[i][1]))
def checkQuestions(num):
one = random.randint(num,num*10)
two = random.randint(num,num*10)
listqq = [one,two]
return listqq
class Controller(object):
def __init__(self,names):
self.winner = ''
self.players = []
for n in names:
p = Player(n)
self.players.append(p)
def move(self):
players = self.players
winner = self.winner
click = ''
count = 1
while True:
for i in range(0,len(players)):
if winner == '' and click != 'e':
print("----" + str(players[i].getName()) + "'s TURN----")
click = input("Press r to roll or e to exit: ")
while click != 'r' and click != 'e':
click = input("Press r to roll or e to exit: ")
if click == 'r' and click != 'e':
count = count + 1
listqq = Check.checkQuestions(count)
answer = input(str(listqq[0]) + ' + ' + str(listqq[1]) +' is:')
if answer == str(listqq[0]+listqq[1]):
print(str(players[i].getName()) + "'s initial position is " \
+ str(players[i].getPosition()))
View(players).display()
players[i].spin()
Check.checkLadders(players[i])
Check.checkChutes(players[i])
else:
pass
if players[i].getPosition() >= 12:
players[i].position = players[i].setPosition(12 - (players[i].getPosition() - 12))
print(str(players[i].getName()) + "'s new position is " \
+ str(players[i].getPosition()))
View(players).display()
if players[i].getPosition() == 12:
winner = players[i].getName()
if click == 'e' and click != 'r':
print('Bye')
break
if winner != '':
print(str(winner) + " is the winner!!!")
break
class View(Player):
def __init__(self,player):
self.players = player
def display(self):
players = self.players
listof = [9,10,11,12,8,7,6,5,1,2,3,4]
ladders = Display.buildLadders()
chutes = Display.buildChutes()
board = [[]] * 3
for i in range(len(players)):
for j in range(len(listof)):
if self.players[i].position == listof[j]:
listof[j] = 'X'
for j in range(len(listof)):
for i in range(len(ladders)):
if ladders[i][0] == listof[j]:
listof[j] = 'L'
for j in range(len(listof)):
for i in range(len(chutes)):
if chutes[i][0] == listof[j]:
listof[j] = 'C'
for i in range(0,4):
board[0] = board[0] + [listof[i]]
for i in range(4,8):
board[1] = board[1] + [listof[i]]
for i in range(8,12):
board[2] = board[2] + [listof[i]]
for row in board:
for num in row:
if num == 'X':
print(" X", end=" ")
if num == 'L':
print(" L", end= " ")
if num == 'C':
print(" C", end= " ")
if num != 'X' and num != 'L' and num != 'C':
if 10 <= num <= 20:
print(num,end=" ")
if num != 'X' and num != 'L' and num!= 'C':
if 1 <= num <= 9:
print(str(num).rjust(2), end= " ")
print()
def main():
n = input("Please enter number of players: ")
names = []
for i in range (0,int(n)):
name = input("Please input your name: ")
names.append(name)
game = Controller(names)
game.move()
while True:
ask = input("Do you want to play again? (y/n)")
if ask == 'y':
game = Controller(names)
game.move()
if ask == 'n':
print("Bye, see you again!")
break
main()
fixed version:
import random
class Player(object):
def __init__(self,name):
self.position = 1
self.name = name
def setName(self,name):
self.name = name
def changePosition(self,number):
self.position = self.position + number
def setPosition(self,pos):
self.position = pos
return self.position
def spin(self):
newSpin = self.getSpin()
self.position = self.position + newSpin
print(str(self.name) + "'s spin was: " + str(newSpin))
def checkLadders(self):
ladders = self.buildLadders()
for i in range(0,len(ladders),1):
if self.position == ladders[i][0]:
self.position = self.setPosition(ladders[i][1])
print(str(self.name) + " Landed on a Ladder! from " + \
str(ladders[i][0]) +" to " + str(ladders[i][1]))
def checkChutes(self):
chutes = self.buildChutes()
for i in range(0,len(chutes),1):
if self.position == chutes[i][0]:
self.position = self.setPosition(chutes[i][1])
print(str(self.name) + " Landed on a Chutes! from " + \
str(chutes[i][0]) + " to " + str(chutes[i][1]))
#staticmethod
def checkQuestions(num):
one = random.randint(num,num*10)
two = random.randint(num,num*10)
listqq = [one,two]
return listqq
#staticmethod
def getSpin():
newSpin = random.randint(1,6)
return newSpin
#staticmethod
def buildLadders():
ladders = [[0 for x in range(2)] for x in range(2)]
ladders[0][0] = 2
ladders[0][1] = 7
ladders[1][0] = 4
ladders[1][1] = 5
return ladders
#staticmethod
def buildChutes():
chutes = [[0 for x in range(2)] for x in range(2)]
chutes[0][0] = 9
chutes[0][1] = 2
chutes[1][0] = 6
chutes[1][1] = 3
return chutes
class Controller(object):
def __init__(self,names):
self.winner = ''
self.players = []
for n in names:
p = Player(n)
self.players.append(p)
def move(self):
players = self.players
winner = self.winner
click = ''
count = 1
while True:
for i in range(0,len(players)):
if winner == '' and click != 'e':
print("----" + str(players[i].name) + "'s TURN----")
click = input("Press r to roll or e to exit: ")
while click != 'r' and click != 'e':
click = input("Press r to roll or e to exit: ")
if click == 'r' and click != 'e':
count = count + 1
listqq = Player.checkQuestions(count)
answer = input(str(listqq[0]) + ' + ' + str(listqq[1]) +' is:')
if answer == str(listqq[0]+listqq[1]):
print(str(players[i].name) + "'s initial position is " \
+ str(players[i].position))
View(players).display()
players[i].spin()
Player.checkLadders(players[i])
Player.checkChutes(players[i])
else:
pass
if players[i].position >= 12:
players[i].position = players[i].setPosition(12 - (players[i].getPosition() - 12))
print(str(players[i].name) + "'s new position is " \
+ str(players[i].position))
View(players).display()
if players[i].position == 12:
winner = players[i].name
if click == 'e' and click != 'r':
print('Bye')
break
if winner != '':
print(str(winner) + " is the winner!!!")
break
class View():
def __init__(self,player):
self.players = player
def display(self):
players = self.players
listof = [9,10,11,12,8,7,6,5,1,2,3,4]
ladders = Player.buildLadders()
chutes = Player.buildChutes()
board = [[]] * 3
for i in range(len(players)):
for j in range(len(listof)):
if self.players[i].position == listof[j]:
listof[j] = 'X'
for j in range(len(listof)):
for i in range(len(ladders)):
if ladders[i][0] == listof[j]:
listof[j] = 'L'
for j in range(len(listof)):
for i in range(len(chutes)):
if chutes[i][0] == listof[j]:
listof[j] = 'C'
for i in range(0,4):
board[0] = board[0] + [listof[i]]
for i in range(4,8):
board[1] = board[1] + [listof[i]]
for i in range(8,12):
board[2] = board[2] + [listof[i]]
for row in board:
for num in row:
if num == 'X':
print(" X", end=" ")
if num == 'L':
print(" L", end= " ")
if num == 'C':
print(" C", end= " ")
if num != 'X' and num != 'L' and num != 'C':
if 10 <= num <= 20:
print(num,end=" ")
if num != 'X' and num != 'L' and num!= 'C':
if 1 <= num <= 9:
print(str(num).rjust(2), end= " ")
print()
def main():
n = input("Please enter number of players: ")
names = []
for i in range (0,int(n)):
name = input("Please input your name: ")
names.append(name)
game = Controller(names)
game.move()
while True:
ask = input("Do you want to play again? (y/n)")
if ask == 'y':
game = Controller(names)
game.move()
if ask == 'n':
print("Bye, see you again!")
break
main()
Is this following the MVC infrastructure? How to know if it fits the MVC structure or not? Thanks. Does we have to put each model,view,and controller in different module for it to be described as following the MVC structure?
First off the program is not really object oriented. View is instanciated every time when the game state has to be displayed just to call the one and only method. Classes with just the __init__() and one other method are a code smell because, like in this case, it's just a function crammed into a class for no good reason. The same can be said about Control — also just the __init__() and one additional method that get's called exactly once right after instanciating the object and directly after the call the object isn't used anymore.
Taking those ”fake” classes and considering the amount of static methods it seems you are under the impression classes automatically lead to object oriented programs — they don't. And there is nothing wrong with using functions instead of artificially introducing unnecessary complexity with classes that are just syntactically classes. Functions are objects too in Python, so when you have a display function it's okay to pass that around as „view” part of an MVC pattern. It's a callable object.
Which brings us to the MVC question: Supposing Player is the model then it should not interact with the user by printing stuff. Display and input is for the view to handle. So Control isn't a controller because the function in disguise also heavily interacts with the user via print() and input().
So I have to create a game of craps that takes into account bets for an assignment. So far, my code works in that the dice rolls are correct and other little tidbits the assignment called for. But now I don't know how to record each game as a win / lose for the player or computer so that the pot can be added to the winner's money. I realize that my code is half doe, isn't finished, and doesn't run as is, but I just seriously need some help from someone. Please and thank you. Here are more specific directions on my assignment:
http://www.ics.uci.edu/~kay/courses/i42/hw/labA.html
import random
def craps():
print("Welcome to Sky Masterson's Craps Game")
handle_commands()
def handle_commands(): # Collection -> Collection (plus interaction)
""" Display menu to user, accept and process commands
"""
playerInitial = 500
compInitial = 500
MENU = "How much would you like to bet?: "
while True:
bet = float(input(MENU))
if bet <= playerInitial:
human_game()
elif bet > playerInitial:
print("Sorry, you can't bet more than you have")
def handle_commands2():
MENU2 = "Would you like to play again? (y or n): "
while True:
response = input (MENU2)
if response=="y":
counter = counter + multipleGames()
elif response=="n":
while ( counter < 2000):
roll = random.randint(1, 6) + random.randint(1,6)
updateCount(roll)
counter += 1
print ("Thank you for playing." + "\n" + "\n" + "Distribution of dice rolls: " + "\n")
return
else:
invalid_command(response)
def invalid_command(reponse):
"""print message for invalid menu command.
"""
print("Sorry; '" + response + "' isn't a valid command. Please try again.")
def play_game():
"""prints shooters roll results
"""
diceRoll = 0
roll = random.randint(1, 6) + random.randint(1, 6)
updateCount(roll)
diceRoll = diceRoll + 1
point = 0
print("The roll is " + str(roll))
response = (roll)
if response== 7 or response== 11:
print("Natural; shooter wins" + "\n" + "Thank you for playing")
handle_commands2()
elif response== 2 or response== 3 or response== 12:
print("Crapped out; shooter loses" + "\n" + "Thank you for playing")
handle_commands2()
else:
print("The point is " + str(roll))
point = roll
secondRoll = 0
handle_commands()
while (secondRoll !=point) and (secondRoll != 7):
secondRoll = random.randint(1, 6) + random.randint(1, 6)
updateCount(secondRoll)
diceRoll += 1
print("The roll is " + str(secondRoll))
handle_commands()
if secondRoll== point:
print ("Made the point; shooter wins." + "\n" + "Thank you for playing")
handle_commands2()
elif (secondRoll == 7):
print ("Crapped out; shooter loses." + "\n" + "Thank you for playing")
handle_commands2()
return diceRoll
def multipleGames():
gameCounter = 0
while (gameCounter <= 2000):
print("Your game: ")
gameCounter += play_game()
print("\n")
print("Computer's game: ")
gameCounter += play_game()
print( "\n")
return gameCounter
def updateCount(point):
count =List[point] + 1
List[point] = count
List = {2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0}
def human_game():
playerInitial = 500
compInitial = 500
while True:
play_game()
if
playerInitial += bet
compInitial += bet
counter = 0
counter = counter + multipleGames()
playerInitial -= bet
craps()
for point in List:
print("%2d" %(point) + ": " + "%3d" %(List[point]) + " " + "(" + ("%2d" % (int((List[point])/2000*100)))+ "%" + ")" + " " + ("*" *(int((List[point])/2000*100))))
Use classes:
import random
class Human:
def __init__(self):
self.name = 'Human'
self.wins = []
self.losses = []
self.bets = []
self.total = 0
class Computer:
def __init__(self):
self.name = 'Computer'
self.wins = []
self.losses = []
self.bets = []
self.total = 0
class Game:
def __init__(self):
self.rolls = []
self.currentPlayer = None
def roll(self):
self.rolls.append(random.randint(1, 6))
if __name__ == '__main__':
human = Human()
computer = Computer()
game = Game()
game.roll()
print games.rolls
I won't code all of it for you, but using classes will make things much simpler.