Merge branch 'master' into ints
This commit is contained in:
commit
da3cbdfd17
311
FuzzyControlSystem.py
Normal file
311
FuzzyControlSystem.py
Normal file
@ -0,0 +1,311 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
# In[1]:
|
||||
|
||||
|
||||
from simpful import *
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
# ## Sterownik 1 - Decyzja o udziale w grze
|
||||
# ##### Dane wejściowe:
|
||||
# - Wartość żetonów
|
||||
# - Liczba przegranych z rzędu
|
||||
#
|
||||
# ##### Dane wyjściowe:
|
||||
# - Decyzja dot. udziału w grze
|
||||
|
||||
# In[27]:
|
||||
|
||||
|
||||
def getStartDecision(chipVal, lossNum):
|
||||
"""
|
||||
Args:
|
||||
chipVal (int): current value of the player's chips
|
||||
lossNum (int): number of losses in a row
|
||||
Returns:
|
||||
str: decision
|
||||
"""
|
||||
|
||||
FS = FuzzySystem(show_banner=False)
|
||||
|
||||
FS.add_linguistic_variable("chipValue", AutoTriangle(3, terms=['low', 'average', 'high'], universe_of_discourse=[0, 10]))
|
||||
FS.add_linguistic_variable("numLossInRow", AutoTriangle(3, terms=['low', 'average', 'high'], universe_of_discourse=[0, 10]))
|
||||
|
||||
O1 = TriangleFuzzySet(0,0,13, term="surrender")
|
||||
O2 = TriangleFuzzySet(0,13,25, term="hit")
|
||||
O3 = TriangleFuzzySet(13,15,17, term="double_down")
|
||||
O4 = TriangleFuzzySet(16,21,21, term="stand")
|
||||
FS.add_linguistic_variable("decision", LinguisticVariable([O1, O2, O3, O4], universe_of_discourse=[0, 25]))
|
||||
|
||||
FS.add_rules([
|
||||
"IF (numLossInRow IS average) AND (chipValue IS average) THEN (decision IS hit)",
|
||||
"IF (numLossInRow IS high) OR (chipValue IS low) THEN (decision IS surrender)",
|
||||
"IF (numLossInRow IS low) AND (chipValue IS average) THEN (decision IS double_down)",
|
||||
"IF chipValue IS high THEN decision IS stand"
|
||||
])
|
||||
|
||||
FS.set_variable("chipValue", chipVal)
|
||||
FS.set_variable("numLossInRow", lossNum)
|
||||
|
||||
result = FS.inference()
|
||||
decision_terms = [(i.get_term(), FS.get_fuzzy_set('decision', i.get_term()).get_value(result['decision'])) for i in FS.get_fuzzy_sets('decision')]
|
||||
endDecision = max(decision_terms, key=lambda item:item[1])[0]
|
||||
return endDecision
|
||||
|
||||
|
||||
# In[28]:
|
||||
|
||||
|
||||
getStartDecision(7, 7)
|
||||
|
||||
|
||||
# In[1]:
|
||||
|
||||
|
||||
# FS.plot_variable('chipValue')
|
||||
# FS.plot_variable('numLossInRow')
|
||||
# FS.plot_variable('decision')
|
||||
|
||||
|
||||
# ## Sterownik 2 - Decyzja o strategii w przypadku pary
|
||||
# ##### Dane wejściowe:
|
||||
# - Wartość widocznej karty krupiera
|
||||
# - Wartość karty gracza (jednej z pary)
|
||||
#
|
||||
# ##### Dane wyjściowe:
|
||||
# - Decyzja dot. akcji w grze
|
||||
|
||||
# In[12]:
|
||||
|
||||
|
||||
def getSplitDecision(dealerCard, playerCard):
|
||||
"""
|
||||
Args:
|
||||
dealerCard (int): value of the dealer card
|
||||
playerCard (int): value of the player card (one of the pair)
|
||||
Returns:
|
||||
str: decision
|
||||
"""
|
||||
|
||||
FS = FuzzySystem(show_banner=False)
|
||||
|
||||
T1 = TriangleFuzzySet(0,0,6, term="low")
|
||||
T2 = TriangleFuzzySet(4,6,8, term="average")
|
||||
T3 = TriangleFuzzySet(6,11,11, term="high")
|
||||
FS.add_linguistic_variable("dealerCardValue", LinguisticVariable([T1, T2, T3], universe_of_discourse=[0, 11]))
|
||||
FS.add_linguistic_variable("playerCardValue", LinguisticVariable([T1, T2, T3], universe_of_discourse=[0, 11]))
|
||||
|
||||
|
||||
O1 = TriangleFuzzySet(0,0,15, term="continue")
|
||||
O2 = TriangleFuzzySet(11,25,25, term="split")
|
||||
FS.add_linguistic_variable("decision", LinguisticVariable([O1, O2], universe_of_discourse=[0, 25]))
|
||||
|
||||
FS.add_rules([
|
||||
"IF (playerCardValue IS high) THEN (decision IS split)",
|
||||
"IF (playerCardValue IS average) AND (dealerCardValue IS average) THEN (decision IS split)",
|
||||
"IF (playerCardValue IS average) AND (dealerCardValue IS low) THEN (decision IS split)",
|
||||
"IF (playerCardValue IS low) AND (dealerCardValue IS high) THEN (decision IS continue)",
|
||||
"IF (playerCardValue IS low) AND (dealerCardValue IS average) THEN (decision IS split)",
|
||||
"IF (playerCardValue IS low) AND (dealerCardValue IS low) THEN (decision IS continue)",
|
||||
"IF (playerCardValue IS low) AND (dealerCardValue IS high) THEN (decision IS continue)"
|
||||
])
|
||||
|
||||
FS.set_variable("dealerCardValue", dealerCard)
|
||||
FS.set_variable("playerCardValue", playerCard)
|
||||
|
||||
result = FS.inference()
|
||||
decision_terms = [(i.get_term(), FS.get_fuzzy_set('decision', i.get_term()).get_value(result['decision'])) for i in FS.get_fuzzy_sets('decision')]
|
||||
endDecision = max(decision_terms, key=lambda item:item[1])[0]
|
||||
return endDecision
|
||||
|
||||
|
||||
# In[13]:
|
||||
|
||||
|
||||
getSplitDecision(5, 3)
|
||||
|
||||
|
||||
# In[7]:
|
||||
|
||||
|
||||
#FS.plot_variable('dealerCardValue')
|
||||
#FS.plot_variable('playerCardValue')
|
||||
#FS.plot_variable('decision')
|
||||
|
||||
|
||||
# ## Sterownik 3 - Decyzja jaką akcję podjąć (gracz bez asa wśród dwóch kart)
|
||||
# ##### Dane wejściowe:
|
||||
# - Wartość widocznej karty krupiera
|
||||
# - Suma kart gracza
|
||||
# - Suma zliczonych kart
|
||||
#
|
||||
# ##### Dane wyjściowe:
|
||||
# - Decyzja dot. akcji w grze
|
||||
|
||||
# In[29]:
|
||||
|
||||
|
||||
def getHardHandDecision(dealerCard, playerCardsVal, countedCardsVal, playerCardsNum):
|
||||
"""
|
||||
Args:
|
||||
dealerCard (int): value of the dealer card
|
||||
playerCardsVal (int): sum of the players hand
|
||||
countedCardsVal (int): value of the counted cards
|
||||
playerCardsNum (int): number of cards in players hadn
|
||||
Returns:
|
||||
str: decision
|
||||
"""
|
||||
|
||||
FS = FuzzySystem(show_banner=False)
|
||||
|
||||
FS.add_linguistic_variable("dealerCardValue", LinguisticVariable([
|
||||
TriangleFuzzySet(0,0,6, term="low"),
|
||||
TriangleFuzzySet(4,6,8, term="average"),
|
||||
TriangleFuzzySet(6,11,11, term="high")],
|
||||
universe_of_discourse=[0, 11]))
|
||||
|
||||
FS.add_linguistic_variable("playerCardsValue", LinguisticVariable([
|
||||
TriangleFuzzySet(0,0,12, term="low"),
|
||||
TriangleFuzzySet(11,14,17, term="average"),
|
||||
TriangleFuzzySet(12,21,21, term="high")],
|
||||
universe_of_discourse=[0, 21]))
|
||||
|
||||
FS.add_linguistic_variable("countedCardsValue", LinguisticVariable([
|
||||
TriangleFuzzySet(-20,-20,0, term="low"),
|
||||
TriangleFuzzySet(-5,0,5, term="average"),
|
||||
TriangleFuzzySet(0,20,20, term="high")],
|
||||
universe_of_discourse=[-20, 20]))
|
||||
|
||||
|
||||
O1 = TriangleFuzzySet(0,0,13, term="double down")
|
||||
O2 = TriangleFuzzySet(0,13,25, term="hit")
|
||||
O3 = TriangleFuzzySet(13,25,25, term="stand")
|
||||
FS.add_linguistic_variable("decision", LinguisticVariable([O1, O2, O3], universe_of_discourse=[0, 25]))
|
||||
|
||||
|
||||
if playerCardsNum == 2:
|
||||
FS.add_rules([
|
||||
"IF (playerCardsValue IS low) THEN (decision IS double down)",
|
||||
"IF (playerCardsValue IS average) AND (dealerCardValue IS high) THEN (decision IS double down)",
|
||||
"IF (playerCardsValue IS high) THEN (decision IS stand)",
|
||||
"IF (playerCardsValue IS average) AND (dealerCardValue IS average) THEN (decision IS stand)",
|
||||
"IF (playerCardsValue IS average) AND (dealerCardValue IS average) THEN (decision IS double down)"
|
||||
])
|
||||
|
||||
else:
|
||||
FS.add_rules([
|
||||
"IF (playerCardsValue IS high) THEN (decision IS stand)",
|
||||
"IF (playerCardsValue IS low) THEN (decision IS hit)",
|
||||
"IF (playerCardsValue IS average) AND (dealerCardValue IS low) THEN (decision IS stand)",
|
||||
"IF (playerCardsValue IS average) AND (dealerCardValue IS high) THEN (decision IS hit)",
|
||||
"IF (playerCardsValue IS average) AND (dealerCardValue IS average) AND (countedCardsValue IS low) THEN (decision IS hit)",
|
||||
])
|
||||
|
||||
|
||||
FS.set_variable("dealerCardValue", dealerCard)
|
||||
FS.set_variable("playerCardsValue", playerCardsVal)
|
||||
FS.set_variable("countedCardsValue", countedCardsVal)
|
||||
|
||||
result = FS.inference()
|
||||
decision_terms = [(i.get_term(), FS.get_fuzzy_set('decision', i.get_term()).get_value(result['decision'])) for i in FS.get_fuzzy_sets('decision')]
|
||||
endDecision = max(decision_terms, key=lambda item:item[1])[0]
|
||||
return endDecision
|
||||
|
||||
|
||||
# In[19]:
|
||||
|
||||
|
||||
getHardHandDecision(4, 10, 0, 2)
|
||||
|
||||
|
||||
# In[7]:
|
||||
|
||||
|
||||
# FS.plot_variable('dealerCardValue')
|
||||
# FS.plot_variable('playerCardsValue')
|
||||
# FS.plot_variable('countedCardsValue')
|
||||
# FS.plot_variable('decision')
|
||||
|
||||
|
||||
# ## Sterownik 4 - Decyzja jaką akcję podjąć (gracz z asem wśród dwóch kart)
|
||||
# ##### Dane wejściowe:
|
||||
# - Wartość widocznej karty krupiera
|
||||
# - Wartość drugiej karty gracza
|
||||
# - Suma zliczonych kart
|
||||
#
|
||||
# ##### Dane wyjściowe:
|
||||
# - Decyzja dot. akcji w grze
|
||||
|
||||
# In[25]:
|
||||
|
||||
|
||||
def getSoftHandDecision(dealerCard, playerCardsVal, countedCardsVal, playerCardsNum):
|
||||
|
||||
FS = FuzzySystem(show_banner=False)
|
||||
|
||||
FS.add_linguistic_variable("dealerCardValue", LinguisticVariable([
|
||||
TriangleFuzzySet(0,0,6, term="low"),
|
||||
TriangleFuzzySet(4,6,8, term="average"),
|
||||
TriangleFuzzySet(6,11,11, term="high")],
|
||||
universe_of_discourse=[0, 11]))
|
||||
|
||||
FS.add_linguistic_variable("playerCardValue", LinguisticVariable([
|
||||
TriangleFuzzySet(0,0,5, term="low"),
|
||||
TriangleFuzzySet(4,6,8, term="average"),
|
||||
TriangleFuzzySet(7,9,9, term="high")],
|
||||
universe_of_discourse=[0, 9]))
|
||||
|
||||
FS.add_linguistic_variable("countedCardsValue", LinguisticVariable([
|
||||
TriangleFuzzySet(-20,-20,0, term="low"),
|
||||
TriangleFuzzySet(-5,0,5, term="average"),
|
||||
TriangleFuzzySet(0,20,20, term="high")],
|
||||
universe_of_discourse=[-20, 20]))
|
||||
|
||||
|
||||
O1 = TriangleFuzzySet(0,0,13, term="double down")
|
||||
O2 = TriangleFuzzySet(0,13,25, term="hit")
|
||||
O3 = TriangleFuzzySet(13,25,25, term="stand")
|
||||
FS.add_linguistic_variable("decision", LinguisticVariable([O1, O2, O3], universe_of_discourse=[0, 25]))
|
||||
|
||||
if playerCardsNum == 2:
|
||||
FS.add_rules([
|
||||
"IF (playerCardValue IS average) AND (dealerCardValue IS average) THEN (decision IS double down)",
|
||||
"IF (playerCardValue IS high) THEN (decision IS Stand)",
|
||||
"IF (playerCardValue IS average) AND (dealerCardValue IS high) THEN (decision IS hit)",
|
||||
"IF (playerCardValue IS low) AND (dealerCardValue IS low) THEN (decision IS hit)",
|
||||
])
|
||||
else:
|
||||
FS.add_rules([
|
||||
"IF (playerCardValue IS high) THEN (decision IS Stand)",
|
||||
"IF (playerCardValue IS low) THEN (decision IS hit)",
|
||||
"IF (playerCardValue IS average) AND (dealerCardValue IS high) THEN (decision IS Hit)",
|
||||
"IF (playerCardValue IS average) AND (dealerCardValue IS average) AND (countedCardsValue IS high) THEN (decision IS Stand)",
|
||||
"IF (playerCardValue IS average) AND (dealerCardValue IS average) AND (countedCardsValue IS low) THEN (decision IS Hit)"
|
||||
])
|
||||
|
||||
FS.set_variable("dealerCardValue", dealerCard)
|
||||
FS.set_variable("playerCardValue", playerCardsVal)
|
||||
FS.set_variable("countedCardsValue", playerCardsNum)
|
||||
|
||||
result = FS.inference()
|
||||
decision_terms = [(i.get_term(), FS.get_fuzzy_set('decision', i.get_term()).get_value(result['decision'])) for i in FS.get_fuzzy_sets('decision')]
|
||||
endDecision = max(decision_terms, key=lambda item:item[1])[0]
|
||||
return endDecision
|
||||
|
||||
|
||||
# In[26]:
|
||||
|
||||
|
||||
getSoftHandDecision(2, 8, 0, 3)
|
||||
|
||||
|
||||
# In[2]:
|
||||
|
||||
|
||||
# FS.plot_variable('dealerCardValue')
|
||||
# FS.plot_variable('playerCardValue')
|
||||
# FS.plot_variable('countedCardsValue')
|
||||
# FS.plot_variable('decision')
|
||||
|
35
cards.py
35
cards.py
@ -1,5 +1,5 @@
|
||||
import random
|
||||
|
||||
from FuzzyControlSystem import getStartDecision, getSplitDecision, getHardHandDecision, getSoftHandDecision
|
||||
|
||||
def shoe(n_of_decks: int = 1) -> list:
|
||||
"""Create shuffled shoe of n decks of cards
|
||||
@ -58,7 +58,7 @@ def dealer(hand: list, shoe: iter) -> int:
|
||||
evaluation = cards_eval(hand)
|
||||
return max(evaluation)
|
||||
|
||||
def AI(hand: list, face_up: str, splited) -> str:
|
||||
def AI(hand: list, face_up: str, losses_in_row: int) -> str:
|
||||
#TODO: add fuzzy logic
|
||||
"""Fuzzy AI
|
||||
possible player decision:
|
||||
@ -66,7 +66,7 @@ def AI(hand: list, face_up: str, splited) -> str:
|
||||
Args:
|
||||
hand (list): player hand
|
||||
face_up (str): dealer face up card
|
||||
|
||||
losses_in_row: number of losses in row in the current game
|
||||
Returns:
|
||||
list: player decision
|
||||
"""
|
||||
@ -74,12 +74,12 @@ def AI(hand: list, face_up: str, splited) -> str:
|
||||
# if face_up == 'ace':
|
||||
# return 'surrender'
|
||||
# else:
|
||||
evaluation = cards_eval(hand)
|
||||
if len(hand) == 2 and hand[0] == hand[1] and not splited:
|
||||
return 'split'
|
||||
if max(evaluation) == 11:
|
||||
evaluation = max(cards_eval(hand))
|
||||
decision = getStartDecision(evaluation, losses_in_row)
|
||||
print(evaluation, decision)
|
||||
if evaluation == 11:
|
||||
return 'double down'
|
||||
if max(evaluation) <= 17:
|
||||
if evaluation <= 17:
|
||||
return 'hit'
|
||||
else:
|
||||
return 'stand'
|
||||
@ -105,25 +105,24 @@ def show_game_state(player_hand: list, dealer_hand: list, splited: bool, decisio
|
||||
print("split| " if splited else '', end='')
|
||||
print(f"dealer: {cards_eval(dealer_hand)} player: {cards_eval(player_hand)}")
|
||||
|
||||
def blackjack(shoe: iter, dealer_hand: list=[], player_hand: list=[], bet: int=10) -> str:
|
||||
def blackjack(shoe: iter, dealer_hand: list=[], player_hand: list=[], bet: int=10, losses_in_row: int=0) -> str:
|
||||
"""Single blackjack round
|
||||
|
||||
Args:
|
||||
shoe (iter): shoe iterator
|
||||
dealer_hand (list, optional): dealer hand. Should be non empty only in SPLIT.
|
||||
player_hand (list, optional): player hand. Should be non empty only in SPLIT.
|
||||
|
||||
bet: amount of money the player betted
|
||||
losses_in_row: number of losses in row in the current game
|
||||
Returns:
|
||||
str: game result
|
||||
"""
|
||||
splited = False
|
||||
splited_ai = False #temp
|
||||
if dealer_hand == [] and player_hand == []:
|
||||
dealer_hand = [next(shoe), next(shoe)]
|
||||
player_hand = [next(shoe), next(shoe)]
|
||||
else:
|
||||
splited = True
|
||||
splited_ai = True #temp
|
||||
|
||||
#dealer turn
|
||||
face_up = dealer_hand[0]
|
||||
@ -131,7 +130,7 @@ def blackjack(shoe: iter, dealer_hand: list=[], player_hand: list=[], bet: int=1
|
||||
|
||||
decision = ''
|
||||
while decision != 'stand' or decision != 'surrender':
|
||||
decision = AI(player_hand, face_up, splited_ai)
|
||||
decision = AI(player_hand, face_up, losses_in_row)
|
||||
show_game_state(player_hand, [face_up], splited, decision)
|
||||
if decision == 'hit':
|
||||
player_hand.append(next(shoe))
|
||||
@ -175,25 +174,31 @@ def blackjack(shoe: iter, dealer_hand: list=[], player_hand: list=[], bet: int=1
|
||||
def game_loop(balance, bet) -> None:
|
||||
wins, losses, draws = 0, 0, 0
|
||||
player_blackjack = 0
|
||||
|
||||
shoe_iter = iter(shoe(10))
|
||||
losses_in_row = 0
|
||||
notable_results = ['player win', 'dealer win', 'player blackjack']
|
||||
while True:
|
||||
#round start
|
||||
try:
|
||||
balance -= bet
|
||||
result, game_bet = blackjack(shoe_iter, bet=bet)
|
||||
result, game_bet = blackjack(shoe_iter, bet=bet, losses_in_row=losses_in_row)
|
||||
except StopIteration:
|
||||
break
|
||||
if result == 'player win':
|
||||
wins += 1
|
||||
balance += (2*game_bet)
|
||||
losses_in_row = 0
|
||||
|
||||
elif result == 'player blackjack':
|
||||
wins += 1
|
||||
# player_blackjack += 1
|
||||
balance += (2*game_bet) + (game_bet/2)
|
||||
losses_in_row = 0
|
||||
|
||||
elif result == 'dealer win':
|
||||
losses += 1
|
||||
losses_in_row += 1
|
||||
|
||||
elif result == 'push':
|
||||
balance += game_bet
|
||||
draws += 1
|
||||
|
Loading…
Reference in New Issue
Block a user