python while loop point system - running slow - python

I have to simulate a points game where the first person to reach 11 points and win by 2 clear points wins the game
I have used a function to decide who wins a point
def simulatePoint(winProbabilityA, winProbabilityB):
rNumber = random.random()
if rNumber - winProbabilityA <= 0:
# A wins the game
return 0
elif rNumber - winProbabilityA > 0:
# B wins the game
return 1
and another one to simulate a game
def simulateGame (playerA_winProb, playerB_winProb):
gameWon = False
pointsA = 0
pointsB = 0
while gameWon == False:
# Simulate point
point = simulatePoint(playerA_winProb, playerB_winProb)
if point == 0:
pointsA += 1
elif point == 1:
pointsB += 1
# Checks for points to be equal to 11
if (pointsA == 11) and (pointsA - pointsB >= 2):
# A wins the game
gameWon = True
return 0
elif (pointsB == 11) and (pointsB - pointsA >= 2):
# B wins the game
gameWon = True
return 1
This is where i believe i am going wrong, i think the while loop is causing the code to run slow
Any help is greatfully accepted

What if the difference becomes greater than or equal to 2, after they have won more than 11 games. So, the logic should have been like this
if (pointsA >= 11) and (pointsA - pointsB >= 2):
...
elif (pointsB >= 11) and (pointsB - pointsA >= 2):
...

I think your code is running infinitely.
Consider: pointsA and pointsB reach 10 and 10 respectively. Now, no matter what player gets the next point, neither of your terminating conditions will be reached because neither pointsA nor pointsB will be 11 and up by 2 at the same time. This creates an infinite loop.
You'd probably want to check if pointsA >= 11 and pointsB >= 11 instead of A == 11 and B == 11.
Looks like thefourtheye beat me by a bit - he gets my vote.

Related

Python : Calculating probability of a dice throw function

Hello this is a question I have been tasked with.
..........................................................................................................
You are at the bottom of a staircase with a die. With each throw of the die, you
either move down one step (if you get a 1 or 2 on the dice) or move up one step (if you get a
3, 4, or 5 on the dice). If you throw a 6 on the die, you throw the die again and move up the
staircase by the number you get on that second throw. Note if you are at the base of the
staircase, you cannot move down!
The function has a parameter that takes a probability distribution over all
outcomes from a dice throw. For example (0.2,0.3,0.2,0.1,0.1,0.1) would suggest that the
probability of getting a 1 is 0.2, 2 is 0.3 etc. Calculate the probability of reaching a step
higher than the 200th one for the following case: 100 throws, [0.2,0.2,0.2,0.2,0.1,0.1] distribution.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
I have been able to create some code which serves as the function (I'm sure it could be simplified but I am new to this) however I am unsure as to how to work out the probability of it being higher than the 200th step.
import random
def rolldice(T:int, D): #T = throws, D = distribution in format [0.0,0.0,0.0,0.0,0.0,1] [0.2,0.2,0.2,0.2,0.1,0.1]
Stair = 0
for i in range(T):
print(i,Stair)
roll = random.choices([1,2,3,4,5,6], weights= D)
roll2 = random.choices([1,2,3,4,5,6])
roll1 = roll[0]
if roll[0] == 1 and Stair > 0:
Stair -= 1
elif roll[0] == 2 and Stair > 0:
Stair -= 1
elif roll[0] == 3:
Stair += 1
elif roll[0] == 4:
Stair += 1
elif roll[0] == 5:
Stair += 1
elif roll[0] == 6:
Stair += roll2[0]
return Stair
rolldice(100, [0.2,0.2,0.2,0.2,0.1,0.1])
You could assign T to 1000 by an input function and it would then loop for a certain amount of throws.

players roll 2 dice till one reaches 100

Each player roll two dice in a row on one turn. The amount of dice obtained is
added to the player's total points. The game ends when one of the players
the first has achieved at least 100 points.
from random import randint
dicesum2 = 0
dicesum1 = 0
while (dicesum1 < 100):
dice1 = [randint(1, 6) for i in range(2)]
dicesum1 += sum(dice1)
print('player 1',dice1,'|',dicesum1)
dice2 = [randint(1, 6) for i in range(2)]
dicesum2 += sum(dice2)
print('player 2',dice2,'|',dicesum2)
i need it to end when one reaches 100. how do i check both?
if a player throws exactly one single, he loses the points obtained in the turn;
how do i check when one of the generated numbers is 1?
I need it to end when one reaches 100. how do i check both?
Learn about what the or logical operator does:
dicesum1 < 100 or dicesum2 < 100
how do i check when one of the generated numbers is 1?
Learn what the in operator does:
if 1 in dice1:
# Apply penalty.
Take a look at this and see if it helps out
from random import randint
def roll():
return [randint(1, 6) for i in range(2)]
def check_for_one(rolls):
for roll in rolls:
# this could be simplified to "if 1 in rolls", this was just my preference
if roll == 1:
return True
return False
dicesum2 = 0
dicesum1 = 0
while True:
d1 = roll()
dicesum1 += sum(d1)
if check_for_one(d1):
print(f"Player 1 rolled a 1 in batch: {d1}")
print(f"Player 1 roll: {d1} | {dicesum1}")
d2 = roll()
dicesum2 += sum(d2)
if check_for_one(d2):
print(f"Player 2 rolled a 1 in batch: {d2}")
print(f"Player 2 roll: {d2} | {dicesum2}")
if dicesum1 >= 100:
print(f"Player 1 won with: {dicesum1}")
break
elif dicesum2 >= 100:
print(f"Player 2 won with: {dicesum2}")
break
So in this example, we shove the roll out to a function and check_for_one which iterates the list you are making checking for ones and returning a boolean.
I changed the loop to while True so the loop wasn't responsible for the more complex condition which can be limiting.
For each player, it performs the roll, sums, checks and reports if a 1 is in the batch, reports the roll.
Finally it checks for the winner and breaks if one is at or over 100, reporting their win.
You can change the while condition as follow :
while (dicesum1 < 100 and dicesum2 < 100):
Alternatively, you can also use break :
...
if dicesum1 >= 100:
break
...
if dicesum2 >= 100:
break

(Python) List index out of range

So, in a Tic-Tac-Toe game I was developing I decided to make the AI a random number, as a joke. Here are the specifics:
board = []
def createboard():
board.append(['_',' ','_',' ','_'])
board.append(['_',' ','_',' ','_'])
board.append(['_',' ','_',' ','_'])
...
while bot_move_val == False or bot_move_made == False:
bot_move_row = 0
bot_move_col = 0
bot_move_row_rand = randint(0,3)
bot_move_col_rand = randint(0,3)
if bot_move_row_rand == 1:
bot_move_row = 0
bot_move_made = True
elif bot_move_row_rand == 2:
bot_move_row = 2
bot_move_made = True
elif bot_move_row_rand == 3:
bot_move_row = 4
bot_move_made = True
if bot_move_col_rand == 1:
bot_move_col = 0
bot_move_made = True
elif bot_move_col_rand == 2:
bot_move_col = 2
bot_move_made = True
elif bot_move_col_rand == 3:
bot_move_col = 4
bot_move_made = True
if bot_move_row > 4 or bot_move_row < 0 or bot_move_col > 4 or bot_move_col < 0 or board[bot_move_row][bot_move_col] == 'X':
break
else:
bot_move_val = True
The code generates this error:
Traceback (most recent call last):
File "C:\Users\[DATA EXPUNGED]\gamestravaganza.py", line 250, in <module>
if bot_move_row > 4 or bot_move_row < 0 or bot_move_col > 4 or bot_move_col < 0 or board[bot_move_row][bot_move_col] == 'X':
IndexError: list index out of range
As far as I can tell, bot_move_row and bot_move_col are not in the list board, despite being at most as long as the list by definition.
Unlike some other places in Python (like the range method), random.randint(a,b) includes the upper bound. So 3 is a possible outcome, and since the board list is zero-indexed, that would be out of range.
Or as the docs put it :
random.randint(a, b)
Return a random integer N such that a <= N <= b.
So you should use randint(0,2) instead.
You have only 3 rows.
The if condition should be
if bot_move_row > 2 or bot_move_row < 0 or bot_move_col > 4 or bot_move_col < 0 or board[bot_move_row][bot_move_col] == 'X':
break
Assuming at some point you call the function createboard to build your board then there are a few places that are causing difficulty.
The board you create has 3 rows and 5 columns, but you are translating both rows and columns in the same way (ie anticipating equal numbers of rows vs columns). I would keep them both the same at 3.
As stated elsewhere your calls to randint select from a range with 4 numbers (0, 1, 2, 3) as randint includes both endpoints.
Finally your if condition tests that values are within a range that you specify yourself, making it less clear what you are really testing for.
To get the same basic functionality as what you seem to intend above you could rewrite it as:
# Create your board
board = [['_','_','_'], ['_','_','_'], ['_','_','_']]
#Handle one move
def botMove():
while False:
# Attempt to choose a row/column
row = randint(0, 2)
column = randint(0, 2)
if board[row][column] == '_':
# Randomly selected row/column is Empty, mark it as the bots and return
board[row][column] = 'X'
break
This of course does not handle what happens when the board is full (as written above it would loop indefinitely). To flesh out the game you would need something to handle user input (presuming player vs computer) and something to determine winner/draw.

def getLotteryGame(): won't return(True)

In my def getLotteryGame(): Which is suppose to check if the timer runs out and if it does it sorts the players, ranks them, gives them their winnings and stores a note for them and then return True and when it returns True the bot reloads the game making a new round. I tried several ways of trying to get it to return True. This is the code:
def getLotteryGame():
global pot
global players
different = float(time.time() - lotteryStart)
years = int(different / Point.YEAR)
days = int((different % Point.YEAR) / Point.DAY)
hours = int((different % Point.DAY) / Point.HOUR)
mins = int((different % Point.HOUR) / Point.MINUTE)
secs = int(different % Point.MINUTE)
if secs <= 0:
if len(players) > 0:
random.shuffle(players)
ratios = []
for i in range(-2, len(players) - 2) if i > 0 else range(len(players)):
if i < 0:
ratios.append(1 - (i * 0.33)) # ratio > 1
else:
ratios.append(1 / (1 + (i * 0.33))) # ratio <= 1
winnings = [pot * r for r in ratios]
for m in range(1, len(players)):
notes.store("~lottery~", players[m], "The system has placed you "+Point.ordinal(m)+" in the lottery. The lottery awarded you "+winnings+" P$", time.time())
alerts.append(players[m])
winnings = int(winnings)
point = Point.dPoint[players[m]]
point = int(point)
point = int(point+winnings)
Point.dPoint[players[m]] = int(point)
return(True)
elif len(players) == 0:
return(True)
else:
return(False)
When I wait for the difference to go <= 0 for if secs <= 0. It keeps returning False instead and I'm not sure why.
Your code logic is brokem. lotteryStart is defined when the code first runs, as time.time(). Later, you find the number of seconds since lotteryStart. This number of seconds, might be zero occasionally, and is never going to be less than zero. Since time moves forward, it should always be positive. Thus your code always executes the final else statement that returns False.
different = float(time.time() - lotteryStart)
Maybe lotteryStart is a global variable as well as it is not defined anywhere?

whats wrong with my code to simulate a squash game?

I am trying to simulate the scoring of a squash game using english rules.
These are:
Only the server is awarded a point if they win a rally.
If the server wins a rally, they receive a point and continue as server.
If the returner wins a rally, they become the server but don’t receive a point.
The first player to reach 9 points wins the game unless the score has reached 8-8.
If the score reaches 8-8, the player who reached 8 first decides whether to play to 9 or to 10.
The code I have is this:
import random
def eng_game(a,b):
A = 'bob'
B = 'susie'
players = [A, B]
server = random.choice(players)
print server
points_bob = 0
points_susie= 0
prob_A_wins = 0.4
prob_B_wins = 0.6
while points_bob or points_susie < 9:
probability = random.random()
print probability
if probability < prob_A_wins and server == A:
points_bob += 1
elif probability < prob_A_wins and server == B:
server == A
print server
if probability > prob_A_wins and server == B:
points_susie += 1
elif probability > prob_A_wins and server == A:
server == B
print server
print points_bob
print points_susie
This code returns that Susie wins 9-0 when in some cases the server should be swapped to Bob to win the point, but this doesn't happen. The serve stays with Susie and she wins the point.
I think the issue is the statements server == A and server == B should be server = A and server = B so that assignment takes place instead of a comparison.
Another edge case bug I see is if probability ends up exactly 0.4 your program will act like that virtual serve never took place.
I would change your loop to:
while points_bob < 9 and points_susie < 9:
probability = random.random()
print probability
if probability <= prob_A_wins and server == A:
points_bob += 1
elif probability <= prob_A_wins and server == B:
server = A
print server
if probability > prob_A_wins and server == B:
points_susie += 1
elif probability > prob_A_wins and server == A:
server = B
print server
print points_bob
print points_susie
I suspect your loop condition
while points_bob or points_susie < 9:
is not doing what you think. When interpreted as booleans, numbers are False if they are zero and True otherwise, meaning this will actually check (points_bob != 0) or (points_susie < 9). This will only be False (i.e., the loop will only stop) when Susie has at least 9 points and Bob has no points - if Bob gets any points, the game will go on forever.
To fix this, you should switch to an and condition. This will only continue while both players have less than nine points, or to put it another way, it will stop as soon as somebody reaches nine. Therefore, your loop condition should be
while points_bob < 9 and points_susie < 9:
If you want to change the winning condition to 10 points, then you'll need to compare the player's points to a variable rather than a constant, and then change the variable as needed:
winning_score = 9
while points_bob < winning_score and points_susie < winning_score:
# ...
# Accumulate your points etc.
# ...
# Now need to reach ten points to win.
winning_score = 10

Categories

Resources