From 73167f78f45fa3096fcc4e8e45bbcbe196ceef1b Mon Sep 17 00:00:00 2001 From: Michael Pilosov Date: Sat, 26 Nov 2022 17:43:22 -0700 Subject: [PATCH] cleanup --- app.py | 93 +++++++++++++++++++++++++------ roulette.py | 155 ++++++++++++++++++++++++---------------------------- 2 files changed, 148 insertions(+), 100 deletions(-) diff --git a/app.py b/app.py index cd08cc4..0a7ceb1 100644 --- a/app.py +++ b/app.py @@ -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") diff --git a/roulette.py b/roulette.py index 81aeb05..7e4d392 100644 --- a/roulette.py +++ b/roulette.py @@ -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')