# Import Modules
from Dice import dice
d10 = dice(10,1)
d4 = dice(4,1)
# Assign Classes
class Player_Character:
def __init__(self, hp, maxhp, ac, THAC0, Surprise_Adjustment, Initiative_Adjustment):
self.hp = int(hp)
self.maxhp = int(maxhp)
self.ac = int(ac)
self.THAC0 = int(THAC0)
self.Surprise_Adjustment = int(Surprise_Adjustment)
self.Initiative_Adjustment = int(Initiative_Adjustment)
def attack(self, goblin):
Player_Character_Damage = d10.die_roll()
goblin.hp -= Player_Character_Damage
if (goblin.hp <= 0):
print("congratulations you killed the goblin")
def flee(self):
print("you run away ")
quit()
def heal(self, Player_Character):
Player_Character.hp += d10.die_roll()
if Player_Character.hp >= Player_Character.maxhp:
Player_Character.hp = Player_Character.maxhp
class goblin:
def __init__(self, hp, maxhp, ac, THAC0, Surprise_Adjustment, Initiative_Adjustment):
self.hp = int(hp)
self.maxhp = int(maxhp)
self.ac = int(ac)
self.THAC0 = int(THAC0)
self.Surprise_Adjustment = int(Surprise_Adjustment)
self.Initiative_Adjustment = int(Initiative_Adjustment)
def attack(self, Player_Character):
goblin_damage = d4.die_roll()
Player_Character.hp -= goblin_damage
if (Player_Character.hp <= 0):
print("oh dear you have died")
del Player_Character
MrHezy = Player_Character(10, 20, 10, 15, 0, 2)
def spawn_goblin(goblin):
G1 = goblin(5, 10, 8, 18, 0, 0)
return G1
goblin1 = spawn_goblin(goblin)
def battle(goblin1):
# user input
player_initiative_adjustment = MrHezy.Initiative_Adjustment
monster_initiative_adjustment = goblin1.Initiative_Adjustment
#define while loop for the battle
battle_not_over = 'yes'
while battle_not_over == 'yes':
#use random.randint(a,b) to generate player and monster base initiative
player_base_initiative = d10.die_roll()
monster_base_initiative = d10.die_roll()
#subtract the adjustment to get player and monster initiative
player_initiative = player_base_initiative - player_initiative_adjustment
monster_initiative = monster_base_initiative - monster_initiative_adjustment
#compare the initiatives and display the results
if (player_initiative < monster_initiative):
attack_flee_heal = input("congratulations you go first. Would you like to attack, flee, or heal?")
while attack_flee_heal != 'attack' or 'flee' or 'heal':
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
print("the goblin attacks")
goblin1.attack(MrHezy)
break
elif attack_flee_heal == 'flee':
MrHezy.flee()
break
else:
print("uhoh, the monsters go first, they attack!")
goblin1.attack(MrHezy)
attack_flee_heal = input("Would you like to attack, flee, or heal? ")
while attack_flee_heal != 'attack' or 'flee' or 'heal':
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
print("the goblin attacks")
goblin1.attack(MrHezy)
break
elif attack_flee_heal == 'flee':
MrHezy.flee()
break
#main game loop
while True:
spawn_goblin(goblin)
battle(goblin1)
This is a code for a battle simulator that ive been working on. it starts by importing a module that i made which consists of a class called 'dice' which I use for randomly generating numbers. Defining classes is next, with attributes including hp, maxhp, armor class, 'to hit armor class 0', surprise adjustment, and initiative adjustment, and methods including attack which allows you to attack the monsters, flee which exits the battle, and heal which gives your character more hit points. The program moves on to define the spawn_goblin() function which spawns a goblin (this works just fine for the first iteration of the loop). Then it moves on to the battle part which is pretty simple; all it does is check who goes first and then allows you to attack, or flee, or heal yourself. Please ignore the "heal" and "flee" methods, these are working just fine. The problem occurs when I attack the goblin. Instead of killing the goblin and spawning another it creates an infinite loop saying "congratulations you killed the goblin"
while (goblin.hp <= 0):
print("congratulations you killed the goblin")
I think this part of your code is wrong. The while should be if, since you only want to check if the goblin has died, and run some code once. Once the goblin's HP becomes lesser than or equal to 0, the print statement will loop forever since the expression goblin.hp <= 0 will always return True.
EDIT: Now where I think your code is wrong is here:
while attack_flee_heal != 'attack' or 'flee' or 'heal':
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
...
I think you have missed the break in the first if (if attack_flee_heal == 'attack'
Also, it would be more appropriate to use an if here rather than a while, since, as I mentioned above, you only want to check once.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am trying to create a turn based rpg game in python. Currently i am using the list method to display and create individual values for each role. For example, the game allows player to setup a team of units for battle (minimum of 1 unit, default is 3). Each unit has a unique name and attributes like health point (HP), attack point (ATK), defence point (DEF), experience point (EXP) and a rank (default is level 1).
A unit can be either a Warrior, a Tanker or a Wizard whom have different strength in ATK and DEF point. In addition, a Wizard has special ability to cast spells that can impact friendly and enemy units (Heal, Poison, Cure, Freeze).
The suggested initial values for each unit’s attribute point are described in requirement details under Part A – Game Setup section.
The game will automatically setup either (1) player vs Artificial Intelligence (AI) or (2) two-player mode, of which both teams are made up of same number of units.
For AI team, the type of units will be assigned randomly or by specific AI algorithm. The name of units will be specified by the player, whereas AI unit names can be defined with prefix + random numbers (eg AI87). For two-player mode, each player will be able to go through the same unit selection process either through console or GUI.
For each turn, player can select an active friendly unit (non-frozen or dead) to perform an action on a target unit. Units which are severely damaged (i.e. HP equals to or less than 0) will be considered killed (or flagged as “dead”).
How do I use Object Oriented Programming method to create the 3 characters with input name for each team (can display the name keyed and the information of each character), instead of use list method.
#Menu page
print('Welcome to PSB Battle Game! \n(N)ew game\n(S)ave game\n(Q)uit')
def main():
selection = input('Choose your option then hit <ENTER> ==> ')
if selection.upper() == 'N':
new_game()
elif selection.upper() == 'S':
print('Loading save game...')
pass
elif selection.upper() == 'Q':
print('Exit game...')
pass
else:
print("I don't understand what are you typing.")
return main()
def new_game():
print('\nSetting up Player 1 team...\n')
name_list = []
for unit_name in range(1,4):
print(f'Enter a unique name for unit #{unit_name}-> ', end='')
name = input('')
repeated = False
while repeated:
if name == "":
continue
repeated = True
if name in name_list:
print('\nUnit name must be unique.\n')
return new_game()
if not name.strip():
print('\nUnit name could not be blank.\n')
return new_game()
else:
print('Name looks good!')
name_list.append(name)
print(f'Select unit #{unit_name}, type: (W)arrior, (T)anker, or Wi(Z)ard ==> ', end='')
role = input('')
if role.upper() == 'W':
print('Added ' + str(name_list))
warrior()
elif role.upper() == 'T':
print('Added ' + str(name_list))
tanker()
elif role.upper() == 'Z':
print('Added ' + str(name_list))
wizard()
else:
print("I don't understand what are you typing.")
return role()
def warrior ():
charac = [1,50,8,3,0,'True','False','False']
print ('\nWarrior Level 1: ','HP =',charac[1],',''ATK =',charac[2],',''DEF =',charac[3],',''EXP =',charac[4],',''ALIVE =',charac[5],',''POISONED =',charac[6],',''FROZEN =',charac[7])
print ()
def tanker ():
charac = [1,60,5,5,0,'True','False','False']
print ('\nTanker Level 1: ','HP =',charac[1],',''ATK =',charac[2],',''DEF =',charac[3],',''EXP =',charac[4],',''ALIVE =',charac[5],',''POISONED =',charac[6],',''FROZEN =',charac[7])
print ()
def wizard ():
charac = [1,40,3,2,0,'True','False','False']
print ('\nWizard Level 1: ','HP =',charac[1],',''ATK =',charac[2],',''DEF =',charac[3],',''EXP =',charac[4],',''ALIVE =',charac[5],',''POISONED =',charac[6],',''FROZEN =',charac[7])
print ()
main()
Your game is far from functional. I took the liberty of setting up a small sketch of a game after your design with battle functionality and character classes. From this code you can work forward to include other functionalities, such as chance, moving, changing skill points, and other stuff.
class Char:
def __init__(self, name = '', cclass = "Warrior", stats = [1,50,5,5,0,'True','False','False']):
self.c = cclass
self.name = name
self.stats = {'LVL':stats[0],
'HP':stats[1],
'ATK':stats[2],
'DEF':stats[3],
'EXP':stats[4],
'ALIVE':stats[5],
'POISONED':stats[6],
'FROZEN':stats[7]}
self.calc_level()
def __repr__(self):
outs = ''
outs+="Character Name: {0} of class {1}:\n---------------".format(self.name,self.c)
for k,v in self.stats.items():
outs+='\n {0}: {1}'.format(k,v)
return outs
def calc_level(self):
self.stats['LVL'] = int(self.stats['EXP']**.5)+1
def attack(self,other):
print("\n{0} furiously attacks {1} with {2} attack. {1} has {3} defense.".format(self.name,other.name,self.stats['ATK'],other.stats['DEF']))
if self.stats['ATK']>=other.stats['DEF']:
other.stats['HP'] -= self.stats['ATK']
print("\nThat was a hit! The HP of {0} is now {1}".format(other.name,other.stats['HP']))
else:
print("\nYou missed and only made him angrier!")
def new_char(existing):
cc = ''
accept = False
while not accept:
n = input("\nPlease input a new name: ")
accept = True
for c in existing:
if n == c.name:
accept = False
print("This name is taken, already")
while not cc in ['w','t','z']:
cc = input("\nPlease input a class, noble {0}. (W)arrior, (T)ank, Wi(z)ard: ".format(n)).lower()
cclasses = {'w':'Warrior','t':'Tank','z':'Wizard'}
newc = Char(n,cclasses[cc])
print('\nCharacter successfully created:')
print(newc)
return newc
def play(chars):
print("May the games begin. The following characters are present:\n")
for c in chars:
print(c)
print('')
game_over = False
turn = 0
while not game_over:
print("It's the turn of noble {0} {1}. Please select a player to attack:".format(chars[turn].c,chars[turn].name))
possible = []
for i in range(len(chars)):
if not i==turn:
possible.append(i)
print(" - ({0}): {1} named {2}".format(i,chars[i].c,chars[i].name))
sel = -1
while not sel in possible:
s = input('Selection: ')
try:
sel = int(s)
except:
print("That's not a valid choice")
chars[turn].attack(chars[sel])
if chars[sel].stats['HP']<=0:
game_over=True
print("That was it! {0} has died and the game is over.".format(chars[sel].name))
turn +=1
if turn==len(chars):turn=0
def main():
chars = []
entry = ''
print("Welcome to PSB Battle Game!")
while not entry.lower() in ['q','p']:
entry = input('\n(N)ew character\n(P)lay game\n(Q)uit\nSelection: ').lower()
if entry == 'p' and len(chars)<2:
print("\nYou can't play with only one character. Create characters first")
entry = '' ## You can't play with only one char
elif entry == 'n':
chars.append(new_char(chars))
entry = ''
elif entry == 'p':
play(chars)
elif entry == 'q':
print("\nOK, good bye")
main()
So this is a simplified version of my bigger code (there is some unnecessary bits that makes more sense in my main code), and I cannot seem to understand why it neither breaks out of the playing nor the fight loops:
fight = True
a = "enemy"
t = ""
ccd = False,False
playing = True
def lvl():
playing = True
fight = True
while fight:
if a == "enemy":
t = "enemy"
else:
if a == "enemy":
t = "enemy"
else:
t = "player"
while t == "enemy":
print ("enemy attacks player")
t = "player"
while t == "player":
if ccd == (False , False):
fight = False
playing = False
turn = "no one"
t = "enemy"
fight = True
while playing:
fight = True
lvl()
while not playing:
print ("no")
Your program actually is breaking out of the "fight" loop, but it is sent right back in because the playing loop is still running.
The reason why you are not breaking out of the playing loop is that your "playing" variable is local, not global. As such, when you change the variable in the function it doesn't change the one in main (even though they have the same name), which you are using to control the while loop. A possible solution for this would be to return "playing" at the end of your function. Here is some modified code that should suit your purposes:
'''
fight = True
a = "enemy"
t = ""
ccd = False,False
playing = True
def lvl():
playing = True
fight = True
while fight:
if a == "enemy":
t = "enemy"
else:
t = "player"
while t == "enemy":
print ("enemy attacks player")
t = "player"
while t == "player":
if ccd == (False , False):
fight = False
playing = False
t = "enemy"
return playing
fight = True
while playing:
fight = True
playing = lvl()
while not playing:
print ("no")
'''
To have lvl() affect the global variable, you must do the following:
def lvl():
global playing
playing = True
#
# Monty Hall Problem Simulation
# Author: Ryan Sturmer
#
import random
def play_round(doors, switch):
# Choose the location of the car
car = random.randint(1, doors)
# Contestant chooses a door
initial_choice = random.randint(1, doors)
# Monty opens ALL the other doors except one
if initial_choice != car:
monty_leaves = car # If the car wasn't chosen, Monty is forced to reveal its location
else:
while True:
monty_leaves = random.randint(1, doors)
if monty_leaves != initial_choice:
break
# monty_leaves is now the door that Monty DIDN'T open
if switch:
final_choice = monty_leaves
else:
final_choice = initial_choice
victory = (final_choice == car)
return victory, initial_choice, final_choice, car
def simulation(iterations, doors=3):
games_won_switch = 0
games_won_noswitch = 0
for i in range(iterations):
won_game, intial_choice, final_choice, car = play_round(doors, False)
if(won_game):
games_won_noswitch += 1
won_game, intial_choice, final_choice, car = play_round(doors, True)
if(won_game):
games_won_switch += 1
print ""
print " Monty Hall Simulation"
print "---------------------------------------------"
print " Iterations: %d" % iterations
print " Games won when switching doors: %d (%g%%)" % (games_won_switch, 100*float(games_won_switch)/float(iterations))
print "Games won when NOT switching doors: %d (%g%%)" % (games_won_noswitch, 100*float(games_won_noswitch)/float(iterations))
===========================================================================
I found this code from github.
When I run this code, the sum of games_won_switch and games_won_noswitch is not equals to iteration.
(For example, if I set iteration 1,000 -> it appears 996, 1,001, 1,008 not exact 1,000)
How can i fix problem this up?
There is no mistake in the code; it runs the simulations twice:
Once when the player chooses to switch doors every time, and another time when the player chooses to never switch doors. It then prints the results of both simulations.
The results are from independent simulations.
for i in range(iterations):
# Sim with player choose to open the door each time
won_game, intial_choice, final_choice, car = play_round(doors, False)
if(won_game):
games_won_noswitch += 1
# Sim with player choose NEVER to open the door
won_game, intial_choice, final_choice, car = play_round(doors, True)
if(won_game):
games_won_switch += 1
In consequence, because sim(open=True) is not (1 - sim(open=False)), but result from two sets of simulations, the addition of results may not add up precisely to the number of trials.
I am making a simple text-based RPG in Python. Currently I have two methods for most rooms, one for when they first enter and one if they return. Is there a way that I can make sure that they haven't been in that room before without another method?
For example, if I had a method named tomb() i create another method called tombAlready() that contains the same code except for the introduction text to the room.
So if I had
slow_type("\n\nTomb\n\n")
slow_type("There is an altar in the middle of the room, with passages leading down and west.")
choice = None
while choice == None:
userInput = input("\n>")
if checkDirection(userInput) == False:
while checkDirection == False:
userInput = input("\n>")
checkDirection(userInput)
userInput = userInput.lower().strip()
if userInput == "d":
catacombs()
elif userInput == "n":
altar()
elif userInput == "w":
throneroom()
else:
slow_type("You cannot perform this action.")
Then tombAlready() would have the same code except for slow_type("There is an altar in the middle of the room, with passages leading down and west.")
What you want is state associated with a function. Use an object with a method:
class Room:
def __init__(self, description):
self._description = description
self._visited = False
def visit(self):
if not self._visited:
print(self._description)
self._visited = True
Then you can have a Room object for each room:
catacombs = Room('There is a low, arched passageway. You have to stoop.')
tomb = Room('There is an altar in the middle of the room, with passages leading down and west.')
throneroom = Room('There is a large chair. It looks inviting.')
You can visit a room twice but it only prints its description once:
>>> catacombs.visit()
There is a low, arched passageway. You have to stoop.
>>> catacombs.visit()