Compare commits

...

10 Commits

3 changed files with 805 additions and 7 deletions

483
FuzzyControlSystem.ipynb Normal file

File diff suppressed because one or more lines are too long

309
FuzzyControlSystem.py Normal file
View File

@ -0,0 +1,309 @@
#!/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="leave")
O2 = TriangleFuzzySet(0,13,25, term="play")
O3 = TriangleFuzzySet(13,25,25, term="playDouble")
FS.add_linguistic_variable("decision", LinguisticVariable([O1, O2, O3], universe_of_discourse=[0, 25]))
FS.add_rules([
"IF (numLossInRow IS average) AND (chipValue IS average) THEN (decision IS play)",
"IF (numLossInRow IS low) OR (chipValue IS low) THEN (decision IS leave)",
"IF (numLossInRow IS high) AND (chipValue IS high) THEN (decision IS playDouble)",
])
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')

View File

@ -1,6 +1,6 @@
# import itertools
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
@ -23,7 +23,7 @@ def shoe(n_of_decks: int = 1) -> list:
random.shuffle(deck)
return deck
def cards_eval(hand: list) -> list:
def cards_eval(hand: list, agent: str) -> list:
"""Evaluate hand value. Will return two values if there is an ace
in the hand and both values are below 21.
@ -35,6 +35,7 @@ def cards_eval(hand: list) -> list:
"""
evaluation = [0, 0]
for value in hand:
print(f"{agent} : {value}")
if value in ['jack', 'queen', 'king']:
evaluation[0] += 10
evaluation[1] += 10
@ -61,10 +62,10 @@ def dealer(hand: list, shoe: iter) -> int:
Returns:
int: dealer hand value
"""
evaluation = cards_eval(hand)
evaluation = cards_eval(hand, "dealer")
while max(evaluation) <= 17: #solve soft 17
hand.append(next(shoe))
evaluation = cards_eval(hand)
evaluation = cards_eval(hand, "dealer")
return max(evaluation)
def AI(hand: list, face_up: str) -> str:
@ -83,7 +84,7 @@ def AI(hand: list, face_up: str) -> str:
# if face_up == 'ace':
# return 'surrender'
# else:
evaluation = cards_eval(hand)
evaluation = cards_eval(hand, "player")
if max(evaluation) <= 17:
return 'hit'
else:
@ -130,10 +131,12 @@ def blackjack(shoe: iter, dealer_hand: list=[], player_hand: list =[]) -> str:
#dealer turn
dealer_value = dealer(dealer_hand, shoe)
player_value = max(cards_eval(player_hand))
player_value = max(cards_eval(player_hand, "player"))
# print(dealer_value, player_value) #debug
#round end
print(f"Dealer's deck value: {dealer_value}")
print(f"Player's deck value: {player_value}")
if player_value > 21:
return 'dealer win'
elif dealer_value > 21:
@ -162,6 +165,9 @@ def game_loop() -> None:
# elif result == 'push':
# stats[0] += 0
# stats[1] += 1
if result in ['player win', 'dealer win']:
print(result)
print("===="*10)
return stats
# if __name__ == '__main__':
@ -181,4 +187,4 @@ if __name__ == '__main__':
result = end - start
print(result)
print(statistics)
print(statistics[0]/sum(statistics))
print(statistics[0]/sum(statistics))