I am making a poker game where I want to be able to customize the amount of players there are. I am trying to make a function that would move the dealer position to the next player at the table. I have a list of player objects and each have the boolean is_dealer. In the function I want to be able to make the boolean true for the next player on the list and make it false for the current player I am iterating through. My problem is that I don't know how to get the last player in the list to pass the position to the first player in the list.
def move_positions(self):
for people in range(number_of_players):
if self.players[people].is_dealer==True:
self.players[people].is_dealer= False
self.players[people+1].is_dealer=True
players is my list of player objects.
I would recommend that, instead of finding the current dealer each time you want to advance the dealer, you simply have a variable that keeps track of who the current dealer is. That being said, this snippet doesn't do that: It finds the current dealer, and then sets the next player to be the dealer, wrapping around if necessary:
def move_positions(self):
dealer_index = next(index for index, player in enumerate(self.players) if player.is_dealer)
self.players[dealer_index].is_dealer = False
self.player[(dealer_index+1)%number_of_players].is_dealer = True
Exit the loop as soon as you find the dealer. Handle the case where the last player is the dealer. Also, remove comparison operator with boolean.
for people in range(number_of_players):
if self.players[people].is_dealer:
self.players[people].is_dealer = False
self.players[(people+1)%number_of_players].is_dealer = True
break
Related
SOLVED: I read through my code, it was a 'bug'. When I copied the dice roll method from the 'player character', since it uses the same mechanics for the enemies, I set the damage to 0 if it rolls with one die on accident.
Beginner here. (Python crash course halfway of chapter 9)
I am trying to build a simple turn based text game to practice (classes,if statement, modifying dictionaries/lists etc).
I will copy two snippets from my code, so you can understand my problem better.
(I'm really sorry that I can't give a short description, my best try was the title, but that still doesn't make it good enough. If you want an abridged tldr, go to the bottom with the bold texts.)
First, I have two characters, that you can choose from as an if-elif-else statement.
I used the same "player_xy" (xy being like health, damage etc) for the two characters, but assigning different values to them based on the player's choice. (My reasoning being is so I only have to reference the same variable in the code later in the battle system, making my job easier.)
(The variables fighter_max_hp.. etc are defined earlier, but it doesn't matter (tried moving it to before/inside the if statements.)
while select_repeat == True:
print("Type 'f' for fighter , 'm' for mage, or 'q' to quit!")
character = input("TYPE: ")
#player chooses fighter
if character == 'f':
player_max_hp = fighter_max_hp
player_max_mana = fighter_max_mana
#this goes on for a while, setting up all the stats
#player chooses mage
elif character == 'm':
player_max_hp = mage_max_hp
player_max_mana = mage_max_mana
#this goes on for a while, setting up all the stats
#player chooses to quit
elif character == 'q':
select_repeat = False
#invalid input
else:
print("\nPlease choose a valid option!")
Later in the code, I have a part where a randomizer sets up enemies to fight.
I used the same "enemy_xy" (xy being like health, damage etc) for the enemies. (My reasoning was the same here as for the characters.)
(Same, as with the player variables (tried moving it to before/inside the if statements.)
while enemy_select == True:
#game chooses an enemy to fight!
min = 1
max = 3
enemy_chooser = int(random.randint(min, max))
if enemy_chooser == 1:
#choose werewolf
enemy_hp = werewolf_hp
enemy_dice = werewolf_dice
#this goes on for a while, setting up all the stats
if enemy_chooser == 2:
#choose lesser mimic
enemy_hp = int(player_max_hp / 2)
enemy_dice = player_dice
elif enemy_chooser == 3:
#choose zombie
enemy_hp = zombie_hp
enemy_dice = zombie_dice
#this goes on for a while, setting up all the stats
Keep in mind, all of these enemies use the same "enemy_hp", "enemy_dice" etc. variables, within the same battle system, just assigned as "enemy_hp = werewolf_hp" or "enemy_hp = "zombie_hp".
The fight happens, and:
If your enemy is the werewolf:
you deal damage to it
you receive damage from it
you can kill it
you can get killed by it
If your enemy is the lesser mimic:
you deal damage to it
you can ONLY receive damage from it if you are a fighter (mage's hp doesn't decrease)
you can kill it
you can ONLY get killed by it if you are a fighter (obviously, since it doesn't deal damage to mage hp)
If your enemy is the zombie:
you deal damage to it
you CAN NOT receive damage from it (not the fighter, or the mage)
you can kill it
you can not get killed by it (obviously, since no damage)
Otherwise, it prints out the different variable values as assigned (different stats for each monster) as expected, and it uses correct calculations to deal damage.. it just can't in the two cases mentioned above.
Now comes the main part of my question...
If I change the variables like this:
elif enemy_chooser == 2:
#choose zombie
enemy_hp = werewolf_hp ##CHANGE
enemy_dice = werewolf_dice ##CHANGE
#this goes on for a while, setting up all the stats
Then the zombie can finally deal damage to the player (with the werewolf's stats).
It's as if because the lines
enemy_hp = werewolf_hp
enemy_dice = werewolf_dice
#etc
are written earlier than:
enemy_hp = zombie_hp
enemy_dice = zombie_dice
#etc
it somehow effects the variable (regardless or not if the "if" statement is true).
because werewolf_xy was defined earlier than zombie_xy
#enemy werewolf defined first in the code
werewolf_hp = 20
werewolf_dice = 2
#etc
#enemy zombie defined right after
zombie_hp = 35
zombie_dice = 1
#etc
Same happens with the fighter and mage selection.
Somehow the player_hp = xy_hp only works if xy = fighter, because the fighters variables are defined earlier in the code, and thus making the "lesser mimic" deal damage only to the fighter.
My question is "simply".. why?
I tried everything in my power, to no avail.
As you have seen, I could identify what causes the problem (and thus I >could< potentionally work around it), but I still don't know why Python does what it does, and that bothers me.
Any help or input from more experienced users would be greatly appreciated.
Thank you in advance!
Tankerka
You have a bug.
There's not enough details in this (long!) narrative to identify the bug.
Here's how you fix it:
breakpoint()
Put that near the top of your code,
and use n next, plus p print var,
to see what your code is doing.
It is quicker and more flexible than print( ... ).
Read up on that pair of commands here:
https://docs.python.org/3/library/pdb.html
Separate item: refactor your code as you go along.
You're starting to have enough if / elif logic
that it won't all fit in a single screenful
with no scrolling.
That suggests that it's a good time to use def
to break out a helper function.
You might def get_enemy_hp( ... ):, for example,
and also define get_enemy_dice().
Other things you might choose to study:
a class can be a good way to organize the variables you're defining -- embrace the self syntax!
a dict could map from enemy type to hp, or to dice
The nice thing about helper functions is they're
the perfect target for unit tests.
It takes a minute to write a test, but it winds up saving you time.
https://docs.python.org/3/library/unittest.html
When you identify and fix the problem, let us know!
https://stackoverflow.com/help/self-answer
I'm working on a choose-your-own-adventure game in Python to try to learn how to code. I might be doing this entirely wrong, but I thought rather than just nesting if-elif-else statements endlessly, I could write some sort of function that would be a template for all choices in the game.
My ideas was to have every decision in a given scene to generate two lists - choices and outcomes. The "multitemplate" function would then load the choose and outcomes lists, present the options to the player, take in the answer, and call the correct function for the outcome given.
My issue is that the outcome list is a list of functions, which Python doesn't seem to like. It says I've not defined the functions properly, but when I define my outcome functions before calling "multitemplate", it just prints them first.
Here's my code:
#Function to allow the adventurer to make choices
def refusal():
print("You stop at the roadsign you passed on your way into town. There are only two directions - towards Tarroway, or towards Angion, the town from whence you came.")
def guards():
print("The guards stop you.")
def theinn():
print("You follow the joyful chatter down the deserted street. Its source is a squat, one story building. A sign above the door reads \"The Forked Tongue\"")
choose = ["I walk towards the merry sounds.", "I turn on my heels and head back where I came from.","I stay where I am and watch the night quietly."]
outcome = [theinn(), refusal(), guards()]
def multitemplate(choose,outcome):
global mychoice
global carryon
for x in range(len(choose)):
print (f"{x+1}) " + choose[x], end="\n")
mychoice = (input())-1
while True:
if (mychoice) in range(len(choose)):
carryon = True
outcome[mychoice]
carrion()
else:
print("Please enter the number of the choice you wish to make.")
carryon = False
mychoice = int((input()))-1
I'd appreciate any input on how this should work properly, or if I'm going down a completely blind alley here.
Thanks!
So I have a game that requires the player to become immune to damage for 1 second, otherwise, the code wold instantly kills the player. The way I'm doing it is by checking if the enemy and player are colliding in an IF statement and then taking 1 away from health. The issue is that if I use the "pause" feature my entire code freezes for 2 seconds, I only need this single IF loop to freeze.
Thankyou Alex!
Like user1558604 said, you should make a boolean called is_immune set to false. When you take damage, set it to true, and set it to false after one second, and before removing health from the player, checking if the player is immune or not.
is_immune = False
if player_is_hit:
if not is_immune:
player_health -= 1 # Remove 1 from health
is_immune = True
# Wait one second
is_immune = False
I am creating a sidescroller shooter game in which the enemies(drones)spawn contantly on the right side of the screen. The recently created enemies are appended to a list drones Each enemy goes towards the left of the screen. Once they are out of the screen, they get removed from the list.
I also want to remove the drones when they collide with the player. The following code works properly as long as there are multiple objects in the drones list, but when the list has only one item (so one drone is on the screen) that drone does not get deleted upon collision.
I have no idea why the first list item cannot be destroyed.
drones = []
class Drone
#other call methods
def hit(self):
del drones[drones.index(self)]
def generate_enemy():
global drones
if len(drones) < 20:
if (random.randint(1,100) == 1):
drones.append(Drone(screenWidth, random.randint(300,500))
def main():
global drones
while True:
#main loop stuff happening
if condition == True:
generate_enemy():
#main loop stuff happening
if player and (len(drones) > 0):
for i in range(len(drones)-1):
if drones[i].hitbox.colliderect(player.hitbox):
drones[i].hit()
main()
The "correct" way to do this in pygame is to let your classes inherit from Sprite, then use a Group instead of a simple list to store your enemies, and using pygame.sprite.spritecollide for collision detection with the dokill argument set to True.
I'm writing a poker game and I'm having trouble creating a function for turns where one player can raise, then another player call then raise again, followed by another (etc). I'm not sure how to organize this. I have this so far:
def turn(playerBank,label):
#playerBank is just the player's balance (whoever's turn it is) and label is just tkinter text.
win.getMouse()
action = ent.getText()
if action == 'check':
pass
elif action == 'call':
playerBank = playerBank - cashMoney
pool = pool + cashMoney
elif action == 'raise':
cashMoney = cash.getText()
playerBank = playerBank - cashMoney
pool = pool + cashMoney
elif action == 'fold':
break
How would i make it two turns (one per player) but then, if a player raises, allow it to loop AGAIN so that the other player has the option to call or fold... etc.?
The first thing that comes to mind is to use booleans. Make a function that checks if the turn is completely over and make another boolean to check whether a player has raised or not.
Boolean playerRaise would be false until a player raises, and turns true only when all the players have responded to the raise. You can check that by using the number of players and measuring how many responses there were. This resets every time a player raises.
Function checkTurn would just check if playerRaise has become false because if its false then we know for sure the turn has been finished.
I'm just thinking out loud here, but it seems to be a plausible solution, what do you think?