This commit is contained in:
Michael Pilosov 2022-11-26 17:43:22 -07:00
parent dff8ce9131
commit 73167f78f4
2 changed files with 148 additions and 100 deletions

93
app.py
View File

@ -1,32 +1,44 @@
from roulette import init_bet, place_bet, interpret_bet
from roulette import (
init_bet,
place_bet,
interpret_bet,
generate_players,
simulate_games,
Player,
Strategy,
Placement,
FEASIBLE_MOVES,
)
from random import choice, randint
if __name__ == "__main__":
bet = init_bet()
#bet = place_bet(bet, 21, 20)
# bet = place_bet(bet, 21, 20)
print(bet[21])
#bet = interpret_bet("red", 36, bet)
#bet = interpret_bet("25-36", 1, bet)
#bet = interpret_bet("street-1", 3, bet)
#bet = interpret_bet("street-10", 3, bet)
#bet = interpret_bet("col-1", 12, bet)
# bet = interpret_bet("red", 36, bet)
# bet = interpret_bet("25-36", 1, bet)
# bet = interpret_bet("street-1", 3, bet)
# bet = interpret_bet("street-10", 3, bet)
# bet = interpret_bet("col-1", 12, bet)
# james bond
bet = place_bet(bet, 0, 1)
for n in range(13,19):
for n in range(13, 19):
bet = place_bet(bet, n, 5)
bet = interpret_bet("19-36", 14, bet)
#print(bet[21])
# print(bet[21])
from statistics import stdev, mean
def expected(bet) -> float:
bets = list(bet.values())
cond_bets = filter(lambda x: x > 0, bets)
amt = sum(bets)
payout = amt*36/38
print(f"bet: {amt:.2f}, expected: {payout:.2f}: {payout/amt:2.4f} with std {stdev(bets*36)} mean win of {36*mean(cond_bets)} {sum(filter(lambda x: x > 0, bets))}/38 times.")
payout = amt * 36 / 38
print(
f"bet: {amt:.2f}, expected: {payout:.2f}: {payout/amt:2.4f} with std {stdev(bets*36)} mean win of {36*mean(cond_bets)} {sum(filter(lambda x: x > 0, bets))}/38 times."
)
return payout
print("bond")
@ -45,13 +57,62 @@ if __name__ == "__main__":
print("singles")
bet = init_bet()
bet = place_bet(bet, 21, 40)
#bet = place_bet(bet, 1, 1)
# bet = place_bet(bet, 1, 1)
print(expected(bet))
print()
print("stupid")
bet = init_bet()
bet = interpret_bet("odd", 18, bet)
bet = interpret_bet("even", 18, bet)
#bet = place_bet(bet, -1, 1)
#bet = place_bet(bet, 0, 1)
# bet = place_bet(bet, -1, 1)
# bet = place_bet(bet, 0, 1)
print(expected(bet))
# min_games = randint(1, 10)
# print(min_games, Player(200, simulate_random_strategy(min_num_games=min_games, total_budget=200)))
# create a list of random Placements
placements = [
Placement(randint(1, 10), 1, choice(list(FEASIBLE_MOVES))) for _ in range(10)
]
# strategy = Strategy.generate_random(50)
# strategy.print_all()
# define the minimum number of games that you want players to play
# print the total sum of all the placements
# print("SUM")
# print(sum([p.value for p in placements]))
# # place the bets
# bet = place_bets(placements)
# print(bet)
# generate players and print them out
players = generate_players(num_players=3, min_num_games=4, total_budget=200)
players[0] = Player(
budget=200.0,
strategy=Strategy(
budget=50,
placements=[
Placement(num=2, amt=5, on="triple-00"),
Placement(num=1, amt=10, on="col-1"),
Placement(num=60, amt=0.25, on="corner-23-24-26-27"),
Placement(num=10, amt=1, on="14"),
Placement(num=1, amt=5, on="street-2"),
],
),
)
for p in players:
print(p, "\n")
print("======================")
print("SIMULATING GAMES")
# simulate 10 games
players = simulate_games(players, num_games=100)
for p in players:
print(p, "\n")

View File

@ -8,19 +8,33 @@ Bet = Dict[int, float]
SINGLE_BETS = {str(i) for i in range(-1, 37)}
FEASIBLE_MOVES = sorted({
*[f"street-{i}" for i in range(1,14)],
*[f"col-{i}" for i in range(1,4)],
*[f"corner-{i}-{i+1}-{i+3}-{i+4}" for i in range(1,33) if (i - 1)%3 < 2],
*["1-12", "13-24", "25-36", "1-18", "19-36", "even", "odd", "red", "black"],
*["triple-0", "triple-00"],
*SINGLE_BETS
})
FEASIBLE_MOVES = sorted(
{
*[f"street-{i}" for i in range(1, 14)],
*[f"col-{i}" for i in range(1, 4)],
*[f"corner-{i}-{i+1}-{i+3}-{i+4}" for i in range(1, 33) if (i - 1) % 3 < 2],
*["1-12", "13-24", "25-36", "1-18", "19-36", "even", "odd", "red", "black"],
*["triple-0", "triple-00"],
*SINGLE_BETS,
}
)
ALIASES = {"reds", "blacks", "evens", "odds", "first-half", "last-half", "second-half", "first-18", "last-18", "second-18"}
ALIASES = {
"reds",
"blacks",
"evens",
"odds",
"first-half",
"last-half",
"second-half",
"first-18",
"last-18",
"second-18",
}
CHIP_VALUES = {0.25, 0.5, 1, 5, 10, 25, 50, 100}
CHIP_VALUES = { 0.25, 0.5, 1, 5, 10, 25, 50, 100}
def expectation(bet):
odds = 0
@ -48,7 +62,9 @@ def place_bet(bet: Bet, on: int, amount: float):
def interpret_bet(on="red", amount=0, bet=Optional[Bet]):
assert (on in FEASIBLE_MOVES) or (on in ALIASES), f"Bet `{on}` not understood. Choose from feasible moves:\n {FEASIBLE_MOVES}"
assert (on in FEASIBLE_MOVES) or (
on in ALIASES
), f"Bet `{on}` not understood. Choose from feasible moves:\n {FEASIBLE_MOVES}"
if bet is None:
bet = init_bet()
else:
@ -63,16 +79,16 @@ def interpret_bet(on="red", amount=0, bet=Optional[Bet]):
if on in ("black", "blacks"):
NUMS = BLACKS
if on in ("odd", "odds"):
NUMS = {i for i in range(1,37) if i % 2 == 0}
NUMS = {i for i in range(1, 37) if i % 2 == 0}
if on in ("even", "evens"):
NUMS = {i for i in range(1,37) if i % 2}
NUMS = {i for i in range(1, 37) if i % 2}
if on in ("1-18", "first-18", "first-half"):
NUMS = set(range(1, 19))
if on in ("19-36", "last-18", "last-half", "second-half", "second-18"):
NUMS = set(range(19, 37))
if on in ("1-12", "13-24", "25-36"):
low, high = on.split("-")
NUMS = set(range(int(low), int(high)+1))
NUMS = set(range(int(low), int(high) + 1))
div = 12
if on in ["triple-0", "triple-00"]:
NUMS = {0, 1, 2} if on == "triple-0" else {-1, 2, 3}
@ -82,14 +98,16 @@ def interpret_bet(on="red", amount=0, bet=Optional[Bet]):
if other_bet[0] == "street":
street = int(other_bet[1]) - 1
assert street in list(range(13))
NUMS = {i for i in range(street+1, street+4)}
NUMS = {i for i in range(street + 1, street + 4)}
div = 3
elif other_bet[0] == "col":
col = int(other_bet[1]) - 1
assert col in list(range(0,3))
NUMS = {i for i in range(1, 37) if (i-1) % 3 == col}
assert col in list(range(0, 3))
NUMS = {i for i in range(1, 37) if (i - 1) % 3 == col}
div = 12
elif other_bet[0] == "split": # TODO: validate choices, for now we disallow these.
elif (
other_bet[0] == "split"
): # TODO: validate choices, for now we disallow these.
num_1, num_2 = int(other_bet[1]), int(other_bet[2])
NUMS = {num_1, num_2}
div = 2
@ -103,7 +121,9 @@ def interpret_bet(on="red", amount=0, bet=Optional[Bet]):
NUMS = {int(on)}
div = 1
except ValueError as e:
raise e(f"Bet `{on}` not understood. Choose from feasible moves:\n {set(range(-1, 37))}")
raise e(
f"Bet `{on}` not understood. Choose from feasible moves:\n {set(range(-1, 37))}"
)
bet = reduce(lambda bet, num: place_bet(bet, num, amount / div), NUMS, bet)
@ -119,46 +139,44 @@ class Placement:
num (int): number of chips
amt (float): value of each chip
on (str): bet type
Returns:
Placement: an object representing the placement of a stack of chips on a particular bet type.
"""
num: int
amt: float
on: str
def __post_init__(self):
assert (self.on in FEASIBLE_MOVES) or (self.on in ALIASES), f"Bet `{self.on}` not understood. Choose from feasible moves:\n {FEASIBLE_MOVES}"
assert (self.on in FEASIBLE_MOVES) or (
self.on in ALIASES
), f"Bet `{self.on}` not understood. Choose from feasible moves:\n {FEASIBLE_MOVES}"
@property
def value(self):
"""
Returns the value of the bet.
"""
return self.num*self.amt
return self.num * self.amt
def place_bet(self, bet=None):
"""
Places a bet on the wheel based on the bet type.
"""
return interpret_bet(self.on, self.num*self.amt, bet)
return interpret_bet(self.on, self.num * self.amt, bet)
# for two bets of structure Dict[int, float], iterate through all the keys and add up the values, returning a new dict.
def combine_bets(bet_1, bet_2):
return {k: bet_1.get(k, 0) + bet_2.get(k, 0) for k in set(bet_1) | set(bet_2)}
# for a list of Placements, call the place_bet method on each one and combine the results using reduce and combine_bets, starting with an empty dictionary as the initial argument
def place_bets(placements):
return reduce(lambda bet, placement: combine_bets(bet, placement.place_bet()), placements, {})
# create a list of random Placements
placements = [Placement(randint(1, 10), 1, choice(list(FEASIBLE_MOVES))) for _ in range(10)]
# for a given budget, generate placements until you run out of money, where the value of each placement is the number of chips times the value of each chip.
return reduce(
lambda bet, placement: combine_bets(bet, placement.place_bet()), placements, {}
)
@dataclass
@ -187,7 +205,9 @@ class Strategy:
on = choice(list(FEASIBLE_MOVES))
else:
on = choice(list(SINGLE_BETS))
on = choice(list(FEASIBLE_MOVES)) # todo: make a parameter, allow for just single bets.
on = choice(
list(FEASIBLE_MOVES)
) # todo: make a parameter, allow for just single bets.
placement = Placement(num, amt, on)
placements.append(placement)
budget -= placement.value
@ -200,47 +220,29 @@ class Strategy:
def get_bet(self):
return place_bets(self.placements)
@dataclass
class Player:
budget: float
strategy: Strategy
def simulate_random_strategy(
min_num_games = 1,
total_budget = 200
):
def simulate_random_strategy(min_num_games=1, total_budget=200):
strategy_budget = total_budget // min_num_games
return Strategy.generate_random(strategy_budget)
# strategy = Strategy.generate_random(50)
# strategy.print_all()
# define the minimum number of games that you want players to play
# print the total sum of all the placements
# print("SUM")
# print(sum([p.value for p in placements]))
# # place the bets
# bet = place_bets(placements)
# print(bet)
min_games = randint(1, 10)
print(min_games, Player(200, simulate_random_strategy(min_num_games=min_games, total_budget=200)))
# given BUDGET, generate a bunch of random players, each with a random strategy, and return a list of players
def generate_players(
num_players = 10,
min_num_games = 1,
total_budget = 200
):
return [Player(total_budget, simulate_random_strategy(min_num_games=min_num_games, total_budget=total_budget)) for _ in range(num_players)]
def generate_players(num_players=10, min_num_games=1, total_budget=200):
return [
Player(
total_budget,
simulate_random_strategy(
min_num_games=min_num_games, total_budget=total_budget
),
)
for _ in range(num_players)
]
# simulate a game of roulette, picking a random integer from -1 to 37, taking the players as inputs and returning their expected winnings
@ -255,11 +257,9 @@ def simulate_game(players):
# for each player, calculate their expected winnings
return winnings
# simulate multiple games, reducing each player's budget by the amount of their bet and adding the amount of their winnings
def simulate_games(
players,
num_games = 10
):
def simulate_games(players, num_games=10):
losers = []
for g in range(num_games):
if not players:
@ -269,7 +269,9 @@ def simulate_games(
new_losers = []
for i, p in enumerate(players):
p.budget -= p.strategy.value
p.budget += winnings[i]
p.budget += winnings[
i
] # TODO: reinvestment logic goes here. maybe add "reinvest" as a player attribute?
# if a player runs out of money to keep using their strategy,
# remove them from the list of players and add them to the list of losers
if p.budget < p.strategy.value:
@ -279,18 +281,3 @@ def simulate_games(
losers.extend(new_losers)
return players + losers
import ast
# generate players and print them out
players = generate_players(num_players=3, min_num_games=4, total_budget=200)
players[0] = Player(budget=200.0, strategy=Strategy(budget=50, placements=[Placement(num=2, amt=5, on='triple-00'), Placement(num=1, amt=10, on='col-1'), Placement(num=60, amt=0.25, on='corner-23-24-26-27'), Placement(num=10, amt=1, on='14'), Placement(num=1, amt=5, on='street-2')]))
for p in players:
print(p,'\n')
print("======================")
print("SIMULATING GAMES")
# simulate 10 games
players = simulate_games(players, num_games=100)
for p in players:
print(p,'\n')