Projects/european_roulette.py

495 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Python European Roulette (one 0)
import random
import time
import re
wagers = []
playing = True
DEBUG = False
# Define the roulette wheel and board components as dictionary values ----
Z0 = {'Z0': (0)}
N1 = {'N1': (1)}
N2 = {'N2': (2)}
N3 = {'N3': (3)}
N4 = {'N4': (4)}
N5 = {'N5': (5)}
N6 = {'N6': (6)}
N7 = {'N7': (7)}
N8 = {'N8': (8)}
N9 = {'N9': (9)}
N10 = {'N10': (10)}
N11 = {'N11': (11)}
N12 = {'N12': (12)}
N13 = {'N13': (13)}
N14 = {'N14': (14)}
N15 = {'N15': (15)}
N16 = {'N16': (16)}
N17 = {'N17': (17)}
N18 = {'N18': (18)}
N19 = {'N19': (19)}
N20 = {'N20': (20)}
N21 = {'N21': (21)}
N22 = {'N22': (22)}
N23 = {'N23': (23)}
N24 = {'N24': (24)}
N25 = {'N25': (25)}
N26 = {'N26': (26)}
N27 = {'N27': (27)}
N28 = {'N28': (28)}
N29 = {'N29': (29)}
N30 = {'N30': (30)}
N31 = {'N31': (31)}
N32 = {'N32': (32)}
N33 = {'N33': (33)}
N34 = {'N34': (34)}
N35 = {'N35': (35)}
N36 = {'N36': (36)}
I = {'I': (1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36)} # reds
J = {'J': (2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35)} # blacks
H = {'H': tuple(x for x in range(2, 37, 2))} # Evens
K = {'K': tuple(x for x in range(1, 37, 2))} # Odds
G = {'G': tuple(x for x in range(1, 19))} # Low numbers (1-18)
L = {'L': tuple(x for x in range(19, 37))} # high numbers (19-36)
D = {'D': (1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34)} # first column
E = {'E': (2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35)} # second column
F = {'F': (3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36)} # Third column
A = {'A': tuple(x for x in range(1, 13))} # first dozen
B = {'B': tuple(x for x in range(13, 25))} # second dozen
C = {'C': tuple(x for x in range(25, 37))} # third dozen
#-----------------------------------------------------------------------------------
# The 11 Doublestreets or Lines ------------------------------------------------------------------
X1 = {'X1':(1, 2, 3, 4, 5, 6)}
X2 = {'X2':(4, 5, 6, 7, 8, 9)}
X3 = {'X3':(7, 8, 9, 10, 11, 12)}
X4 = {'X4':(10, 11, 12, 13, 14, 15)}
X5 = {'X5':(13, 14, 15, 16, 17, 18)}
X6 = {'X6':(16, 17, 18, 19, 20, 21)}
X7 = {'X7':(19, 20, 21, 22, 23, 24)}
X8 = {'X8':(22, 23, 24, 25, 26, 27)}
X9 = {'X9':(25, 26, 27, 28, 29, 30)}
X10 = {'X10':(28, 29, 30, 31, 32, 33)}
X11 = {'X11':(31, 32, 33, 34, 35, 36)}
#-------------------------------------------------------------------------------------------------
# The 57 Splits --------------------------------------------------------------------------------------------
S3 = {'S3':(1, 4)}
S1 = {'S1':(1, 2)}
S4 = {'S4':(2, 5)}
S2 = {'S2':(2, 3)}
S5 = {'S5':(3, 6)}
S8 = {'S8':(4, 7)}
S6 = {'S6':(4, 5)}
S9 = {'S9':(5, 8)}
S7 = {'S7':(5, 6)}
S10 = {'S10':(6, 9)}
S13 = {'S13':(7, 10)}
S11 = {'S11':(7, 8)}
S14 = {'S14':(8, 11)}
S12 = {'S12':(8, 9)}
S15 = {'S15':(9, 12)}
S18 = {'S18':(10, 13)}
S16 = {'S16':(10, 11)}
S19 = {'S19':(11, 14)}
S17 = {'S17':(11, 12)}
S20 = {'S20':(12, 15)}
S23 = {'S23':(13, 16)}
S21 = {'S21':(13, 14)}
S24 = {'S24':(14, 17)}
S22 = {'S22':(14, 15)}
S25 = {'S25':(15, 18)}
S28 = {'S28':(16, 19)}
S26 = {'S26':(16, 17)}
S29 = {'S29':(17, 20)}
S27 = {'S27':(17, 18)}
S30 = {'S30':(18, 21)}
S33 = {'S33':(19, 22)}
S31 = {'S31':(19, 20)}
S34 = {'S34':(20, 23)}
S32 = {'S32':(20, 21)}
S35 = {'S35':(21, 24)}
S38 = {'S38':(22, 25)}
S36 = {'S36':(22, 23)}
S39 = {'S39':(23, 26)}
S37 = {'S37':(23, 24)}
S40 = {'S40':(24, 27)}
S43 = {'S43':(25, 28)}
S41 = {'S41':(25, 26)}
S44 = {'S44':(26, 29)}
S42 = {'S42':(26, 27)}
S45 = {'S45':(27, 30)}
S48 = {'S48':(28, 31)}
S46 = {'S46':(28, 29)}
S49 = {'S49':(29, 32)}
S47 = {'S47':(29, 30)}
S50 = {'S50':(30, 33)}
S53 = {'S53':(31, 34)}
S51 = {'S51':(31, 32)}
S54 = {'S54':(32, 35)}
S52 = {'S52':(32, 33)}
S55 = {'S55':(33, 36)}
S56 = {'S56':(34, 35)}
S57 = {'S57':(35, 36)}
#------------------------------------------------------------------------------------------------------------
# The 12 Streets -----------------------------------------------------------------------------------------------
O = {'O':(34, 35, 36)}
P = {'P':(1, 2, 3)}
Q = {'Q':(4, 5, 6)}
R = {'R':(7, 8, 9)}
S = {'S':(10, 11, 12)}
T = {'T':(13, 14, 15)}
U = {'U':(16, 17, 18)}
V = {'V':(19, 20, 21)}
W = {'W':(22, 23, 24)}
X = {'X':(25, 26, 27)}
Y = {'Y':(28, 29, 30)}
Z = {'Z':(31, 32, 33)}
#-------------------------------------------------------------------------------------------------------------
# The 22 Corners -------------------------------------------------------------------------------------------
C1 = {'C1':(1, 2, 4, 5)}
C2 = {'C2':(2, 3, 5, 6)}
C3 = {'C3':(4, 7, 5, 8)}
C4 = {'C4':(5, 8, 6, 9)}
C5 = {'C5':(7, 10, 8, 11)}
C6 = {'C6':(8, 11, 9, 12)}
C7 = {'C7':(10, 13, 11, 14)}
C8 = {'C8':(11, 14, 12, 15)}
C9 = {'C9':(13, 16, 14, 17)}
C10 = {'C10':(14, 17, 15, 18)}
C10 = {'C11':(16, 19, 17, 20)}
C12 = {'C12':(17, 20, 18, 21)}
C13 = {'C13':(19, 22, 20, 23)}
C14 = {'C14':(20, 23, 21, 24)}
C15 = {'C15':(22, 25, 23, 26)}
C16 = {'C16':(23, 26, 24, 27)}
C17 = {'C17':(25, 28, 26, 29)}
C18 = {'C18':(26, 29, 27, 30)}
C19 = {'C19':(28, 31, 29, 32)}
C20 = {'C20':(29, 32, 30, 33)}
C21 = {'C21':(31, 34, 32, 35)}
C22 = {'C22':(32, 35, 33, 36)}
# The 2 Trios --------------------------------------------------------------------------------------------
T1 = {'T1': {0, 1, 2}}
T2 = {'T2': (0, 2, 3)}
#-----------------------------------------------------------------------------------------------------------
# End of wheel and board layout ----------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------------
# Payouts for betting options (Payout = Multiple of bet less initial bet)
payouts = {
'numbers': 35,
'splits': 17,
'streets': 11,
'trio': 11,
'corners': 8,
'lines': 5,
'first_doz': 2,
'second_doz': 2,
'third_doz': 2,
'first_col': 2,
'second_col': 2,
'third_col': 2,
'low': 1,
'high': 1,
'odds': 1,
'evens': 1,
'reds': 1,
'blacks': 1,
'zero': 0
}
# Wager patterns
WAGER_PATTERNS = {
"numbers": r"N(?:[1-9]|[1-2][0-9]|3[0-6])",
"splits": r"S(?:[1-9]|[1-4][0-9]|5[0-7])",
"corners": r"C(?:[1-9]|1[0-9]|2[0-2])",
"streets": r"[O-Z]$", # matches exactly "O-Z"
"lines": r"X(?:[1-9]|1[0-1])",
"reds": r"I",
"blacks": r"J",
"evens": r"H",
"odds": r"K",
"low": r"G",
"high": r"L",
"first_col": r"D",
"second_col": r"E",
"third_col": r"F",
"first_doz": r"A",
"second_doz": r"B",
"third_doz": r"C$", # Matches exactly "C"
"zero": r"Z(?:[0])",
"Trio_1": r"T(?:[1])",
"Trio_2": r"T(?:[2])"
}
#----------------------------------------------------------------# Welcome Screen---------------------------------------------------
print("\n -------------------------------------------------------------------------------------------------------------------")
print()
print(" WELCOME TO EUROPEAN ROULETTE ")
print()
# ---------------------------------------------------------G A M E F U N C T I O N S -----------------------------------------------
def display_board():
print(" |<----------------------LOW (G)---------------------->|<---------------------HIGH (L)---------------------->|")
print(" |-------X1-------X2-------X3-------X4-------X5----- -X6-------X7-------X8-------X9-------X10------X11-------|-----|")
print(" | | | | | | | | | | | | | | 2 |")
print(" | F N3 | N6 | N9 | N12 | N15 | N18 | N21 | N24 | N27 | N30 | N33 | N36 F TO |")
print(" T2 | C2 C4 C6 C8 C10 C12 C14 C16 C18 C20 C22 | 1 |")
print(" | S2>---^S5|S7--^S10|S12-^S15|S17-^S20|S22-^S25|S27-^S30|S32-^S35|S37-^S40|S42-^S45|S47-^S50|S52-^S55|S57>----|-----|")
print(" | | | | | | | | | | | | | | 2 |")
print("| Z0 E N2 | N5 | N8 | N11 | N14 | N17 | N20 | N23 | N26 | N29 | N32 | N35 E TO |")
print(" | | C1 C3 C5 C7 C9 C11 C13 C15 C17 C19 C21 | 1 |")
print(" | S1>---^S4|S6---^S9|S11-^S14|S16-^S19|S21-^S24|S26-^S29|S31-^S34|S36-^S39|S41-^S44|S46-^S49|S51-^S54|S56>----|-----|")
print(" T1 | | | | | | | | | | | | | 2 |")
print(" | D N1 | N4 | N7 | N10 | N13 | N16 | N19 | N22 | N25 | N28 | N31 | N34 D TO |")
print(" | | | | | | | | | | | | | | 1 |")
print(" |--------S3-------S8------S13------S18------S23------S28------S33------S38------S43------S48------S53-------|-----|")
print(" | P Q R S | T U V W | X Y Z O <-Streets|")
print(" | 1St 12 | 2nd 12 | 3rd 12 |")
print(" | A | B | C |")
print(" |--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|")
print(" | G | H | I J | K | L |")
print(" | 1 - 18 | EVEN | RED | BLK | ODD | 19 - 36 |")
print(" | | | | | | |")
print(" |--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|")
return None
# ------------------------- GLOBAL GAME VARIABLES ------------------------------
def spin_wheel()-> int:
print()
time.sleep(2)
print("The wheel is spinning. Please wait...")
time.sleep(8)
print("The ball has dropped.")
number = random.choice(range(37))
print("The ball landed on ", end=" --------> ")
time.sleep(3)
print(number)
return number
def build_a_list_of_wager_types():
global DEBUG
wager_type_list = []
select = True
while select:
selected_key = input("Enter a wager type (e.g. S3): ").strip().upper()
if selected_key in globals():
wager_dict = globals()[selected_key]
if DEBUG:
print(f"Wager dict: {wager_dict}")
if isinstance(wager_dict, dict):
wager_type_list.append(wager_dict)
build_a_dict_of_wagers(selected_key)
else:
print(f"'{selected_key}' exists but is not a dictionary.")
else:
print(f"'{selected_key}' is not defined.")
answer = input("Do you want another wager type? (y/n): ").lower()
if answer != 'y':
select = False
else:
continue
return wager_type_list
def build_a_dict_of_wagers(code):
global wagers
global DEBUG
bet = input("Enter a wager for this wager_type (e.g. 10 for $10) ")
wager = {code: bet}
wagers.append(wager)
if DEBUG:
print(f"Wagers: {wagers}")
return wagers
def search_number_in_dicts(dict_list: list, number_to_find: int):
matching_results = {}
unmatching_results = {}
global DEBUG
for i, d in enumerate(dict_list):
if not isinstance(d, dict):
print(f"Warning: Item at index {i} is not a dictionary. Skipping.")
continue
matched_keys = []
unmatched_keys = []
for k, v in d.items():
if (
(isinstance(v, (list, tuple, set)) and number_to_find in v) or
(isinstance(v, str) and str(number_to_find) in v) or
(v == number_to_find)
):
matched_keys.append(k)
else:
unmatched_keys.append(k)
if matched_keys:
matching_results[f'dict_{i+1}'] = matched_keys
if DEBUG:
print(f"Matched Results for dict_{i+1}: {matched_keys}")
if unmatched_keys:
unmatching_results[f'dict_{i+1}'] = unmatched_keys
if DEBUG:
print(f"Unmatched Results for dict_{i+1}: {unmatched_keys}")
if DEBUG:
print(f"\nFinal Matched keys: {matching_results}")
print(f"Final Unmatched keys: {unmatching_results}")
return matching_results, unmatching_results
def match_wager_type(code):
global DEBUG
if DEBUG:
print(f"Code: {code}")
for wager_type, pattern in WAGER_PATTERNS.items():
if re.fullmatch(pattern, code) or re.match(pattern, code):
if DEBUG:
print(f"Wager type from match_wager_type(code): {wager_type}")
return wager_type
def log_match(wager_code, wager_amount, wager_type, payout):
global DEBUG
if DEBUG:
print(f"Matched {wager_code} as {wager_type}{wager_amount} × {payout} = {wager_amount * payout}")
def log_unmatched(wager_code, wager_amount, wager_type):
global DEBUG
if DEBUG:
print(f"Unmatched wager code: {wager_code} as {wager_type}{wager_amount} × -1 = {wager_amount * -1}")
unmatched = []
if wager_type is None:
losses += wager_amount
unmatched.append((wager_code, wager_amount))
def calculate_profits(matched_results):
profits = 0
global DEBUG
for item in wagers:
for key, value in item.items():
if DEBUG:
print(f"Line 346: Wager types and wagers: {wagers}")
wager_code = key
wager_amount = int(value)
for k, v in matched_results.items():
if DEBUG:
print(f"k is {k} and v is {v}")
print(f"Wager code is: {wager_code}")
wager_type = match_wager_type(wager_code)
payout = int(payouts.get(wager_type, 0))
if str(wager_code) in v:
profits += wager_amount * payout
if DEBUG:
print(f"Wager type: {wager_type}")
return profits
def calculate_losses(unmatched_results):
losses = 0
global DEBUG
for item in wagers:
for key, value in item.items():
if DEBUG:
print(f"Line 366: Wager types and wagers: {wagers}")
wager_code = key
wager_amount = int(value)
for k, v in unmatched_results.items():
if DEBUG:
print(f"k is {k} and v is {v}")
print(f"Wager code is: {wager_code}")
if str(wager_code) in v:
losses += wager_amount
if DEBUG:
print(f"LOSS → code: {wager_code}, amount: {wager_amount}")
wager_type = match_wager_type(wager_code)
if DEBUG:
print(f"Wager for type: {wager_amount}")
if DEBUG:
print(f"DEBUG: wager_code={wager_code}, wager_type={repr(wager_type)}")
return losses
def keep_playing():
global playing
playing_again = input("Do you want to keep playing? (y/n) ")
if playing_again != "y":
playing = False
print("Thanks for playing!")
exit()
else:
return playing
# ----------------------------- G A M E P L A Y ---------------------------------
def main():
holdings = int(input("Enter your initial holdings at the start of play (e.g. 1000 for $1000): "))
global playing
global DEBUG
global wagers
while playing:
display_board()
# User selects which dictionaries to search for number the wheel returns
wager_type_list = build_a_list_of_wager_types()
number = spin_wheel()
matched_results, unmatched_results = search_number_in_dicts(wager_type_list, number)
flat_list = [item for sublist in matched_results.values() for item in sublist]
wager_types_and_wagers = list(zip(flat_list, wagers))
if DEBUG:
print(f"Wager types and wagers list: {wager_types_and_wagers}")
profits = calculate_profits(matched_results)
flat_list = [item for sublist in unmatched_results.values() for item in sublist]
if DEBUG:
print(f"Line 404: {flat_list}")
wager_types_and_wagers = list(zip(flat_list, wagers))
if DEBUG:
print(f"Line 407: {wagers}")
print(f"Line 405: wager_types_and_wagers: {wager_types_and_wagers}")
losses = calculate_losses(unmatched_results)
holdings += (profits - losses)
if holdings <= 0:
print("You are busted! Thanks for playing.")
exit()
else:
print(f"\nYour profits are: ${profits} and losses are {losses} yielding current holdings: ${holdings}")
print()
keep_playing()
if __name__ == "__main__":
main()