I'm trying to figure out how to get my bot to distrubute points from a pot from the lottery game when it ends each time. So each game starts out at 1 point but everytime someone buys a ticket it goes up by a random amount. At the end of fifteen minutes it's supposed to retrieve the players and the pot and based off of where you're ranked in the list your points are determined. So basically if you're first in the list you win over the pot value. And when the ranking goes down your points that you win go down and if your near or at last place you lose points. The sum of all the points that the players earn does not have to equal 0 after they are distrubuted.
For example: Tim got 1st in the lottery. He should get 5676*1.66. Also, all the points you receive from the pot should be different based on your rank in the lottery. But if you're at the end of the list in the lottery you should lose points.
This is what I have so far:
lotteryStart = time.time()
players = []
pot = 1
def buyLottery(name):
if name not in players:
amount = int("30")
if Point.getCost(name, amount) == True:
multiplier = random.randint(217, 453)
pot = int(multiplier+pot)
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)
for i in range(1,len(players)):
if i == 1:
pot2 = int(pot*1.66)
elif i == 2:
pot2 = int(pot*1.33)
elif i == 3:
pot2 = int(pot)
elif i == 4:
pot = int(pot/1.66) #And so on but i dont want to keep doing elif
I do not understand your lottery; I can't imagine a lottery where you buy a ticket for a random amount and could lose money on top of the ticket price being very popular in real life!
That being said, I think you want to do something like this:
ratios = []
for i in range(-2, len(players) - 2):
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]
You can then easily match players[i] with their winnings[i]. Note that I have assumed that you missed out pot / 1.33 accidentally; otherwise, you will have to adjust this slightly.
For 10 players, I get:
ratios == [1.6600000000000001, 1.33, 1.0, 0.7518796992481203,
0.6024096385542168, 0.5025125628140703, 0.43103448275862066,
0.3773584905660377, 0.33557046979865773, 0.3021148036253776]
Related
I'm doing a dice roll assignment. The rules are:
The points rolled on each player’s dice are added to their score.
If the total is an even number, an additional 10 points are added to their score.
If the total is an odd number, 5 points are subtracted from their score.
If they roll a double, they get to roll one extra die and get the number of points rolled added to their score.
The score of a player cannot go below 0 at any point.
The person with the highest score at the end of the 5 rounds wins.
Basically, what I've done is created variables of what 2 separate players roll in 2 rounds of the game, now I'm trying to add these variables together so that the player can have their total for round 1 and 2 combined. My teacher had mentioned something about a while function but that was all he was allowed to say, that plus I'm not sure how to do that.
I feel like what I've done is overly complicated, plus the fact it doesn't even work.
if (round2scoreP1 % 2) == 0 + (round1scoreP1 % 2) == 0:
addedscoreround2P1even=(totalround1scoreP1even)+(totalround2scoreP1even)
print(username1,"'s total for round 1 and 2 is",addedscoreround2P1even,".")
elif (round1scoreP1 % 2) != 0 + (round2scoreP1 % 2) != 0:
addedscoreround2P1odd=(totalround1scoreodd)+(totalround2scoreodd)
print(username1,"'s total for round 1 and 2 is",addedscoreround2P1odd,".")
elif (round1scoreP1 % 2) == 0 + (round2scoreP1 % 2) != 0:
addedscoreround2P1evenodd=(totalround1scoreP1even)+(totalround1scoreP1odd)
print(username1,"'s total for round 1 and 2 is",addedscoreround2P1evenodd,".")
elif (round1scoreP1 % 2) != 0 + (round2scoreP1 % 2) == 0:
addedscoreround2P1oddeven=(totalround1scoreP1odd)+(totalround1scoreP1even)
print(username1," obtained",addedscoreround2P1oddeven,".")
I'm not going to write you the whole assignment, but you could consider using a Player-class to store the rolls and total scores in:
class Player():
def __init__(self):
self.rolls = []
self.total_score = 0
def roll_dice():
self.rolls.append(random.randint(1, 6))
I'm a novice making a small game for learning purposes.
The game rolls dice based on the inputs of the user.
The part I'm having trouble with is I want to check for patterns in the list "rolls"
patterns include:
all dice are the same value and the # of sides >=4 EXAMPLE [1, 1, 1, 1] < values are the same, atleast 4 sides. If true then mutiply user_Score by 10
at least half of the dice are >= "average_sum" with the condition that the list must have >= 5 dice
EXAMPLE if avg_sum = 2 and rolls = [2,3,4,1,1,] If true then mutiply user_Score by 5
all of the dice are different values with the conditions # of dice > 4 and # of sides > # of dice
[10, 11, 12, 13, 14]
No pattern matches. -> Multiply user_Score by 1
number_dice = int( input( "How many dice are you using? Must be between 3-6 inclusive" ) )
faces = int( input( "how many sides are on your die? enter a number between 2-20 inclusive: "))
# Set range for number of dice
#generate a random number between 1 and faces
#Add dice_roll to the list
rolls = []
for die in range(number_dice):
dice_roll = random.randint(1, faces)
rolls.append(dice_roll)
#print the score from each dice rolled
print("You have rolled: " + str(rolls))
#calculate sum of score
sum = sum(rolls)
#calculate the average and round to the nearest integer
average_sum = round(sum / number_dice)
print("These die sum to: " + str(sum) + " and have an average value of: " + str(average_sum))
#Calculate the max possible score
max_score = (number_dice * faces)
#calculate the users score
user_score = float( sum / max_score )
print("your max possible score is " + str(max_score))
print("your score is " + str(user_score))
#-----------------------------------------------------------------------------------
#now calculate the bonus factor
#Check if the list "rolls" contains the same value for each index
if rolls == {repeatingvalues???} and rolls {number_dice>=4}:
user_Score * 10
elif rolls == {half of dice > average} and {number_dice >=5}:
user_Score * 5
elif rolls == {all dice have different values} and { number_dice > 4}{faces> number_dice}:
user_score * 8
else:
user_score * 1
Not sure how to make this statement search the list for a pattern^^^^^^
Define a function to check for a repeating pattern that returns True or False
def has_repeats(my_list):
first = my_list[0]
for item in mylist:
if not item == first:
return False
return True
And then define a function to check for a no duplicates that returns True or False
def all_different(my_list):
# Remove duplicates from list
my_list2 = list(dict.fromkeys(my_list))
return len(my_list) == len(my_list2)
And finally define a function to check if half the dice are greater than the average:
def half_greater_than_averge(my_list, average):
a = 0
b = 0
for item in my_list:
if item > average:
a += 1
else:
b += 1
return a > b
So you final checks will be:
if has_repeats(rolls) and number_dice >= 4:
user_Score * 10
elif half_greater_than_averge(rolls, average_sum) and number_dice >= 5:
user_Score * 5
elif all_different(rolls) and number_dice > 4 and faces > number_dice:
user_score * 8
else:
user_score * 1
Check out my solution where add # ------ SOLUTION STARTS HERE -------
I helped refactor your code too. You shouldn't be using sum as a variable name (or identifier) in your code cos it's a reserved python keyword. So I changed it to my_sum. Check if it still works as desired.
import math # import math at the top
import random
number_dice = int( input( "How many dice are you using? Must be between 3-6 inclusive" ) )
faces = int( input( "how many sides are on your die? enter a number between 2-20 inclusive: "))
# Set range for number of dice
#generate a random number between 1 and faces
#Add dice_roll to the list
for die in range(number_dice):
dice_roll = random.randint(1, faces)
rolls.append(dice_roll)
#print the score from each dice rolled
print("You have rolled: " + str(rolls))
#calculate sum of score
my_sum = sum(rolls)
#calculate the average and round to the nearest integer
average_sum = round(my_sum / number_dice)
print("These die sum to: " + str(my_sum) + " and have an average value of: " + str(average_sum))
#Calculate the max possible score
max_score = (number_dice * faces)
#calculate the users score
user_score = float( my_sum / max_score )
print("your max possible score is " + str(max_score))
# ------ SOLUTION STARTS HERE------
rolls.sort()
rolls.reverse()
for item in rolls:
if (rolls.count(item) >= 4) and (number_dice >= 4):
user_score *= 10
break
elif (rolls[math.ceil(len(rolls)/2) -1] >= average_sum ) and (number_dice >= 5):
user_score *= 5
break
elif (sorted(rolls)==sorted(list(set(rolls))))and (number_dice > 4) and (faces > number_dice):
user_score *= 8
break
else:
user_score *= 1
# ------ SOLUTION ENDS HERE------
print("your score is " + str(user_score))
Here is a simple, faster and more 'Pythonic' way of doing it.
if all(x == rolls[0] for x in rolls):
print("Same")
elif len(rolls) == len(set(rolls)):
print("Unique")
elif number_dice/2 <= [x > avg_sum for x in rolls].count(True):
print("Half")
else:
print("No match")
The 'and' conditions are missing. Please feel free to add them.
Bonus
from random import randint
faces = int(input('Number of faces:'))
number_dice = int(input('Number of dice:'))
rolls = [randint(1, faces) for _ in range(number_dice)]
Feel free to explore
This is my code buy no matter how many times I run it all I get is you lost. What's wrong with the code?
import random
# Creates a number to count the amount of plays
count = 1;
# Creates a variable to store the amount of starting money
money = 10;
# Creates a variable telling you how much money you start with
startingCash = "You start with $" + str(money) + "!";
while (count < 101):
# Variables for the lottery numbers
lottery1 = random.randint(1,9);
lottery2 = random.randint(1,9);
lottery3 = random.randint(1,9);
lottery4 = random.randint(1,9);
# Lottery variables in one single variable
lotteryTotal = (lottery1, lottery2, lottery3, lottery4);
# Variables for the drawn ticket
drawn1 = random.randint(1,9);
drawn2 = random.randint(1,9);
drawn3 = random.randint(1,9);
drawn4 = random.randint(1,9);
# Variable for the drawn ticket in one single variable
drawnTotal = (drawn1, drawn2, drawn3, drawn4);
# Variable that changes the money variable so the player has 2 less dollars
money = money - 2;
it seems like the == sign gets ignored or acts differently. I wanted it to do the if if they are equal to each other.
if( drawnTotal == lotteryTotal):
count = count + 1;
money = money + 5;
print ("Lottery Numbers: " + str(lotteryTotal));
print ("Your Numbers: " + str(drawnTotal));
print ("You Won $5!");
input("Press Enter to continue")
else:
print ("Lottery Numbers: " + str(lotteryTotal));
print ("Your Numbers: " + str(drawnTotal));
print ("You Lost!");
input("Press Enter to continue");
Your code is working... the results are just not what you expected.
The problem is that, to win, you need to generate the same random sequence of digits twice in a row. What is the probability of that?
The probability of repeating a toss of a single 1-9 digit is 1 out of 9. If you have two such digits, you have two 1/9 probabilities and their compound probability is 1/9 * 1/9, or 1/81. If you have four as in your case, you'll win once every 1/9 * 1/9 * 1/9 * 1/9 = 1/6561 games.
You tried "many times", but... did you try enough times? Even after one thousand games, the probability of winning at least once is less than 15%. Even after 6561 games, the probability of winning at least once is nowhere near 100% - actually it's closer to two thirds.
I modified it to only tell me the number of wins, and to only do so when indeed you do win (MarkyPython's suggestion). After some time, it tells me,
100 won in 686114 games; win rate is 95% of expected.
(The first win, by the way, was after 29172 games).
Great explanation lserni.
Khodexian, in case if you are willing to increase the number of chances of winning you can simply take the numbers into account and disregard the sequence in which they were generated.
For example,
import random
# Creates a number to count the amount of plays
count = 0;
# Creates a variable to store the amount of starting money
money = 10;
# Creates a variable telling you how much money you start with
startingCash = "You start with $" + str(money) + "!";
win, lost = 0, 0
while (win < 100):
count = count + 1;
# Variables for the lottery numbers
lotteryTotal = [random.randint(1,9), random.randint(1,9), random.randint(1,9), random.randint(1,9)]
# Variable for the drawn ticket in one single variable
drawnTotal = [random.randint(1,9), random.randint(1,9), random.randint(1,9), random.randint(1,9)]
# Variable that changes the money variable so the player has 2 less dollars
money = money - 2;
if( sorted(lotteryTotal) == sorted(drawnTotal) ):
money = money + 5;
print ("Lottery Numbers: " + str(lotteryTotal));
print ("Your Numbers: " + str(drawnTotal));
print ("You Won $5!");
win += 1
else:
print ("Lottery Numbers: " + str(lotteryTotal));
print ("Your Numbers: " + str(drawnTotal));
print ("You Lost!");
lost += 1
print ('played {}, won {} and lost {}'.format(count, win, lost))
And I get a statistics like this,
played 40170, won 100 and lost 40070
I want to interate 1000 times over the following function to find out if you win or loose money in this game.
The game is designed as such that you throw a pair of dice and get money back or loose money. Let's say we start with 5 coins.
Throwing a 12 yields 1.5 coins.
Throwing an 11 yields 1 coins.
Throwing a 10 yields 0.5 coins.
Throwing a 9,8 or 7 yields nothing.
Throwing a 6,5,4,3,2 or 1 deducts 0.5 coins from your amount of coins.
This is what my implementation looks like so far:
def luckCalc():
amount = 5
# if 12 then 1/36 chance
if random.randrange(1,7) == 6 and random.randrange(1,7) == 6:
amount = amount + 1.5
# if 11 then 2/36 chance
elif (random.randrange(1,7) == 5 and random.randrange(1,7) == 6) or (random.randrange(1,7) == 6 and random.randrange(1,7) == 5):
amount = amount + 1
# if 10 then 3/36 chance
elif (random.randrange(1,7) == 5 and random.randrange(1,7) == 5) or (random.randrange(1,7) == 4 and random.randrange(1,7) == 6) or (random.randrange(1,7) == 6 and random.randrange(1,7) == 4):
amount = amount + 0.5
# if 9,8,7
# 4/36 + 5/36 + 6/36 chance
# 1+6, 2+5, 3+4, 4+3, 5+2, 6+1 chance
# 2+6, 3+5, 4+4, 5+3, 6+2 chance
# 3+6, 4+5, 5+4, 6+3 chance
# then no change in amount
# if 6,5,4,3,2,1
# chances...
# then amount -0.5
return amount
# Iterate over the dice throwing simulator and calculate total
total = 0.0
for a in range(1000):
total = total + luckCalc()
print (total)
I stopped coding towards the end of the function, because I recognised that there must be a more elegant solution on how to achieve this. Any interesting suggestions, what is this Monte Carlo I keep hearing about?
Each time you call random.randrange(1,7), you generate a new random number. Since you're testing a single "turn", roll twice:
def roll_die():
return random.randrange(1, 7)
total = roll_die() + roll_die()
And see if the sum is in a range:
def play_turn():
total = roll_die() + roll_die()
if total == 12:
return 1.5
elif total == 11:
return 1.0
elif total == 10:
return 0.5
elif total <= 6:
return -0.5
else: # total is 7, 8, or 9
return 0
Here's the result of 100,000 rounds:
>>> from collections import Counter
>>> counts = Counter(play_turn() for i in xrange(100000))
>>> counts
Counter({-0.5: 41823, 0: 41545, 0.5: 8361, 1.0: 5521, 1.5: 2750})
>>> probabilities = {score: count / 100000.0 for score, count in counts.items()}
>>> probabilities
{-0.5: 0.41823, 0: 0.41545, 0.5: 0.08361, 1.0: 0.05521, 1.5: 0.0275}
You can actually roll (ha!) everything you are doing into a single function:
from random import randrange
def play_game(rolls=1000, amount=5, n=6):
"""Play game 'rolls' times, starting with 'amount' on 'n'-sided dice."""
for i in range(rolls):
roll = randrange(1, n+1) + randrange(1, n+1)
if roll == 12:
amount += 1.5
elif roll == 11:
amount += 1
elif roll == 10:
amount += 0.5
elif roll < 7:
amount -= 0.5
return amount
I notice a few things in your code. First, for the 6-1 cases you're not actually subtracting 0.5 from the amount. Second, since you don't pass in the initial amount each loop you're adding between 5 and 6.5 to your total, which makes the total pretty pointless.
A more effective total would be to pass in the amount each time:
def luckCalc( amount ):
And then for your loop:
total = 5.0
for a in range(1000):
total = luckCalc(total)
Blender's answer, which just posted as I was writing this, is a great way to simplify your main function.
I personally like setting up my results table as an array (or a dictionary, but this suited my purpose better since every result was one of a small number of possible integers), with the index of each dice roll set to the value of the resulting change. See below.
import random
def luckCalc(coins=5):
diceroll = random.randint(1,6)+random.randint(1,6) #roll them bones
#here's that table I was talking about....
results_table = ['index 0 is blank',"you can't roll a one on two dice",-.5,-.5,-.5,-.5,-.5,0,0,0,.5,1,1.5]
coins += results_table[diceroll] #changes your coins value based on your roll (as an index of results_table)
if results_table[diceroll] > 0: #change the string if your result was + or -
result = "gained {}".format(results_table[diceroll])
else:
result = "lost {}".format(results_table[diceroll]*-1)
print("You {} coins, putting you at {}".format(result,coins)) #report back to the user
return coins #this is how you save your output
#CONSTANTS GO HERE -- YOU CAN CHANGE THESE TO CHANGE YOUR PROGRAM
STARTING_COINS = 5
HOW_MANY_ITERATIONS = 1000
#this way we don't modify a constant
coins = STARTING_COINS
#do it how many times?
for _ in range(HOW_MANY_ITERATIONS): #oh yeah that many times
coins = luckCalc(coins) #runs the function and saves the result back to coins
#report to the user your final result.
print("After {} rolls, your final total is {}".format(HOW_MANY_ITERATIONS,coins))
I am trying to come up with a simulation for the Pig dice game. I want it to simulate for the number of games the user wants(each game to 100 points) and report the average points and percent wins for each player. My program is running but it is only running for one game. I think there is something wrong with my loop but i cannot tell. Thank you for your help and time here is my program:
from random import randrange # Use "randrange(1, 7)" to get a random
# number between 1 and 6.
# Takes one turn in the game of pig. Keeps rolling until either
# the holdAmount is reached or a pig (1) is rolled. Returns the
# score accumulated during the turn.
def takeTurn(holdAmount):
totalScore = 0
while totalScore < holdAmount:
rollValue = randrange(1,7)
if rollValue == 1:
totalScore = 0
break
else:
totalScore = totalScore + rollValue
return totalScore
# Start with turn score equal to 0. Repeatedly roll die, adding
# roll value to score each time, until score reaches holdAmount.
# If at any time a pig (1) is rolled, set score to 0 and end the
# turn early.
# Tests the takeTurn function.
def main():
first = eval(input("How many points should the first player try for in each turn?"))
second = eval(input("How many points should the second player try for in each turn?"))
games = eval(input("How many games should be simulated?"))
firstScore = 0
secondScore = 0
turnCount = 0
score = 0
score1 = 0
won = 0
won1 = 0
for i in range(games):
while firstScore < 100 and secondScore < 100:
firstScore = takeTurn(first) + firstScore
secondScore = takeTurn(second) + secondScore
turnCount = turnCount + 1
if firstScore >= 100:
won = won + 1
elif secondScore >= 100:
won1 = won1 + 1
score = score + firstScore
score1 = score1 + secondScore
percent = won / games
percent1 = won1 / games
points = score / games
points2 = score1 / games
print("The average points for player one is",points)
print("The percent of games won for player one is",percent)
print("The average points for player two is",points2)
print("The percent of games won for player two is",percent1)
if __name__ == "__main__":
main()
I was confused for a while when I first looked at this. The reason is that each game ends with the same score since you do not reset the firstScore, etc. values each time. If you set each of those to 0 at the beginning of your for loop, you won't have any problems.
To be more specific, if you move firstScore, secondScore, and turnCount inside your for loop at the very top of it, the code runs properly.
The traditional way to gain a better understanding of what your program is doing is to add some print statements at looping and branching points.
A more advanced technique is to trace through the program using pdb.
You need firstScore and secondScore inside your for-loop.