blackjack-fuzzy/FuzzyControlSystem.py

358 lines
12 KiB
Python
Raw Normal View History

2023-01-31 21:05:19 +01:00
#!/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)
2023-01-31 21:55:50 +01:00
FS.add_linguistic_variable("chipValue", AutoTriangle(3, terms=['low', 'average', 'high'], universe_of_discourse=[0, 10]))
2023-01-31 21:05:19 +01:00
FS.add_linguistic_variable("numLossInRow", AutoTriangle(3, terms=['low', 'average', 'high'], universe_of_discourse=[0, 10]))
2023-01-31 21:55:50 +01:00
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]))
2023-01-31 21:05:19 +01:00
FS.add_rules([
2023-01-31 21:55:50 +01:00
"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"
2023-01-31 21:05:19 +01:00
])
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
2023-02-01 00:46:03 +01:00
# - Wartość kart gracza
2023-01-31 21:05:19 +01:00
#
# ##### Dane wyjściowe:
# - Decyzja dot. akcji w grze
# In[12]:
2023-02-01 00:46:03 +01:00
def getSplitDecision(dealerCard, playerCardsVal):
2023-01-31 21:05:19 +01:00
"""
Args:
dealerCard (int): value of the dealer card
2023-02-01 00:46:03 +01:00
playerCardsVal (int): sum of the player cards
2023-01-31 21:05:19 +01:00
Returns:
str: decision
"""
FS = FuzzySystem(show_banner=False)
2023-02-01 00:46:03 +01:00
FS.add_linguistic_variable("dealerCardValue", LinguisticVariable([
FuzzySet([[0,1], [6,1], [7,0]], term='low'),
FuzzySet([[6,0], [7,1], [7.5,0]], term='high'),
FuzzySet([[7,0], [8,1]], term='very_high')
], universe_of_discourse=[0, 11]))
2023-02-01 23:45:29 +01:00
2023-02-01 00:46:03 +01:00
FS.add_linguistic_variable('splitValue', LinguisticVariable([
FuzzySet([[0,1], [2,1], [3,0], [9,0], [10,1]], term='high'),
FuzzySet([[2,0], [3,1], [4.5,1], [5,0], [5.5,1], [9,1], [9,1], [10,0]], term='low'),
], universe_of_discourse=[0, 20]))
2023-01-31 21:05:19 +01:00
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([
2023-02-01 00:46:03 +01:00
"IF (splitValue IS high) THEN (decision IS split)",
"IF (splitValue IS low) AND (dealerCardValue IS low) THEN (decision IS split)",
"IF (splitValue IS low) AND (dealerCardValue IS high) THEN (decision IS continue)",
"IF (splitValue IS low) AND (dealerCardValue IS very_high) THEN (decision IS continue)",
2023-01-31 21:05:19 +01:00
])
FS.set_variable("dealerCardValue", dealerCard)
2023-02-01 23:45:29 +01:00
FS.set_variable("splitValue", playerCardsVal)
2023-01-31 21:05:19 +01:00
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[7]:
#FS.plot_variable('dealerCardValue')
#FS.plot_variable('playerCardValue')
#FS.plot_variable('decision')
2023-02-01 00:46:03 +01:00
# ## Sterownik 3 - Decyzja jaką akcję podjąć (twarda ręka)
2023-01-31 21:05:19 +01:00
# ##### Dane wejściowe:
# - Wartość widocznej karty krupiera
# - Suma kart gracza
2023-02-01 00:46:03 +01:00
# - Liczba kart gracza
2023-01-31 21:05:19 +01:00
#
# ##### Dane wyjściowe:
# - Decyzja dot. akcji w grze
# In[29]:
2023-02-01 00:46:03 +01:00
def getHardHandDecision(dealerCard, playerCardsVal, playerCardsNum):
2023-01-31 21:05:19 +01:00
"""
Args:
dealerCard (int): value of the dealer card
playerCardsVal (int): sum of the players hand
playerCardsNum (int): number of cards in players hadn
Returns:
str: decision
"""
FS = FuzzySystem(show_banner=False)
FS.add_linguistic_variable("dealerCardValue", LinguisticVariable([
2023-02-01 00:46:03 +01:00
FuzzySet([[0,1], [6,1], [7,0]], term='low'),
FuzzySet([[6,0], [7,1], [7.5,0]], term='high'),
FuzzySet([[7,0], [8,1]], term='very_high')
], universe_of_discourse=[0, 11]))
2023-01-31 21:05:19 +01:00
FS.add_linguistic_variable("playerCardsValue", LinguisticVariable([
2023-02-01 00:46:03 +01:00
FuzzySet([[0,1], [11,1], [12,0]], term='low'),
FuzzySet([[11,0], [12,1], [16,1], [17, 0]], term='medium'),
FuzzySet([[16,0], [17,1], [18,0]], term='high'),
FuzzySet([[17,0], [18,1]], term='very_high')
], universe_of_discourse=[0, 21]))
# FS.add_linguistic_variable('splitValue', LinguisticVariable([
# FuzzySet([[0,1], [2,1], [3,0], [9,0], [10,1]], term='split_high'),
# FuzzySet([[2,0], [3,1], [4.5,1], [5,0], [5.5,1], [9,1], [9,1], [10,0]], term='split_low'),
# ], universe_of_discourse=[0, 20]))
2023-01-31 21:05:19 +01:00
2023-02-01 00:46:03 +01:00
FS.add_linguistic_variable('doubleValue', LinguisticVariable([
FuzzySet([[7,0], [8,1], [9,1], [10,0]], term='low'),
FuzzySet([[9,0], [10,1], [11,1], [12,0]], term='high'),
], universe_of_discourse=[0, 21]))
2023-01-31 21:05:19 +01:00
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]))
2023-02-01 00:46:03 +01:00
if playerCardsNum == 2: # gdy początek rozgrywki
2023-01-31 21:05:19 +01:00
FS.add_rules([
2023-02-01 00:46:03 +01:00
"IF (doubleValue IS high) THEN (decision IS double down)",
"IF (doubleValue IS low) AND (dealerCardValue IS low) THEN (decision IS double down)",
"IF (playerCardsValue IS low) THEN (decision IS hit)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS high) THEN (decision IS hit)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS very_high) THEN (decision IS hit)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS very_high) THEN (decision IS hit)",
2023-01-31 21:05:19 +01:00
])
else:
FS.add_rules([
"IF (playerCardsValue IS low) THEN (decision IS hit)",
2023-02-01 00:46:03 +01:00
"IF (playerCardsValue IS medium) AND (dealerCardValue IS high) THEN (decision IS hit)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS very_high) THEN (decision IS hit)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS very_high) THEN (decision IS hit)",
2023-01-31 21:05:19 +01:00
])
FS.set_variable("dealerCardValue", dealerCard)
FS.set_variable("playerCardsValue", playerCardsVal)
2023-02-01 00:46:03 +01:00
FS.set_variable("doubleValue", playerCardsVal)
2023-01-31 21:05:19 +01:00
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[7]:
# FS.plot_variable('dealerCardValue')
# FS.plot_variable('playerCardsValue')
# FS.plot_variable('countedCardsValue')
# FS.plot_variable('decision')
2023-02-01 00:46:03 +01:00
# ## Sterownik 4 - Decyzja jaką akcję podjąć (miękka ręka)
2023-01-31 21:05:19 +01:00
# ##### Dane wejściowe:
# - Wartość widocznej karty krupiera
2023-02-01 00:46:03 +01:00
# - Wartość kart gracza
# - Liczba kart gracza
2023-01-31 21:05:19 +01:00
#
# ##### Dane wyjściowe:
# - Decyzja dot. akcji w grze
# In[25]:
2023-02-01 00:46:03 +01:00
def getSoftHandDecision(dealerCard, playerCardsVal, playerCardsNum):
"""
Args:
dealerCard (int): value of the dealer card
playerCardsVal (int): sum of the players hand
playerCardsNum (int): number of cards in players hadn
Returns:
str: decision
"""
2023-01-31 21:05:19 +01:00
FS = FuzzySystem(show_banner=False)
FS.add_linguistic_variable("dealerCardValue", LinguisticVariable([
2023-02-01 00:46:03 +01:00
FuzzySet([[0,1], [6,1], [7,0]], term='low'),
FuzzySet([[6,0], [7,1], [7.5,0]], term='high'),
FuzzySet([[7,0], [8,1]], term='very_high')
], universe_of_discourse=[0, 11]))
2023-01-31 21:05:19 +01:00
2023-02-01 23:14:14 +01:00
FS.add_linguistic_variable("playerCardsValue", LinguisticVariable([
2023-02-01 00:46:03 +01:00
FuzzySet([[0,1], [11,1], [12,0]], term='low'),
FuzzySet([[11,0], [12,1], [16,1], [17, 0]], term='medium'),
FuzzySet([[16,0], [17,1], [18,0]], term='high'),
FuzzySet([[17,0], [18,1]], term='very_high')
], universe_of_discourse=[0, 21]))
# FS.add_linguistic_variable('splitValue', LinguisticVariable([
# FuzzySet([[0,1], [2,1], [3,0], [9,0], [10,1]], term='split_high'),
# FuzzySet([[2,0], [3,1], [4.5,1], [5,0], [5.5,1], [9,1], [9,1], [10,0]], term='split_low'),
# ], universe_of_discourse=[0, 20]))
2023-01-31 21:05:19 +01:00
2023-02-01 00:46:03 +01:00
FS.add_linguistic_variable('doubleValue', LinguisticVariable([
FuzzySet([[12,0], [13,1], [16,1], [17,0]], term='low'),
FuzzySet([[16,0], [17,1], [18,0]], term='high'),
], universe_of_discourse=[0, 21]))
2023-01-31 21:05:19 +01:00
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]))
2023-02-01 00:46:03 +01:00
if playerCardsNum == 2: # gdy początek rozgrywki
2023-01-31 21:05:19 +01:00
FS.add_rules([
2023-02-01 00:46:03 +01:00
"IF (doubleValue IS high) THEN (decision IS double down)",
"IF (doubleValue IS low) AND (dealerCardValue IS low) THEN (decision IS double down)",
"IF (playerCardsValue IS low) THEN (decision IS hit)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS high) THEN (decision IS hit)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS very_high) THEN (decision IS hit)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS very_high) THEN (decision IS hit)",
2023-01-31 21:05:19 +01:00
])
2023-02-01 00:46:03 +01:00
2023-01-31 21:05:19 +01:00
else:
FS.add_rules([
2023-02-01 23:14:14 +01:00
"IF (playerCardsValue IS low) THEN (decision IS hit)",
2023-02-01 00:46:03 +01:00
"IF (playerCardsValue IS medium) AND (dealerCardValue IS high) THEN (decision IS hit)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS very_high) THEN (decision IS hit)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS very_high) THEN (decision IS hit)",
2023-01-31 21:05:19 +01:00
])
2023-02-01 00:46:03 +01:00
2023-01-31 21:05:19 +01:00
FS.set_variable("dealerCardValue", dealerCard)
2023-02-01 23:14:14 +01:00
FS.set_variable("playerCardsValue", playerCardsVal)
2023-02-01 00:46:03 +01:00
FS.set_variable("doubleValue", playerCardsVal)
2023-01-31 21:05:19 +01:00
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[2]:
# FS.plot_variable('dealerCardValue')
# FS.plot_variable('playerCardValue')
# FS.plot_variable('countedCardsValue')
# FS.plot_variable('decision')
2023-02-01 00:46:03 +01:00
# ## Funkcja do obsługi sterowników
# ##### Dane wejściowe:
# - Wartość widocznej karty krupiera
# - Lista kart gracza
# - Flaga określająca czt jest para (ustawiona na 1 tylko gdy kest para i gdy jest to początek rozgrywki!)
2023-02-01 23:45:29 +01:00
#
2023-02-01 00:46:03 +01:00
# ##### Dane wyjściowe:
# - Decyzja dot. akcji w grze
# In[25]:
def getDecision(dealerCard, playerCards, isPair):
"""
Args:
dealerCard (int): value of the dealer card
playerCards (list): list of player cards
isPair (int): is pair in players hand - 1 only at the beggining of the game
Returns:
str: decision
"""
2023-02-01 23:45:29 +01:00
2023-02-01 00:46:03 +01:00
playerCardsNum = len(playerCards)
if 1 in playerCards: # soft hand
playerCardsVal = sum([x if x != 1 else 10 for x in playerCards])
if sum(playerCards) == 2: # is pair of aces
return 'split'
else: # controller for soft hand
return getSoftHandDecision(dealerCard, playerCardsVal, playerCardsNum)
2023-02-01 23:45:29 +01:00
2023-02-01 00:46:03 +01:00
else: # hard hand
playerCardsVal = sum(playerCards)
if isPair and getSplitDecision(dealerCard, playerCardsVal) != 'continue': # if pair - controller for splitting
return 'split'
else: # controller for hard hand
return getHardHandDecision(dealerCard, playerCardsVal, playerCardsNum)