blackjack-fuzzy/FuzzyControlSystem.py
Andrzej Preibisz 419fbd5067 Removed logs
2023-02-02 18:27:44 +01:00

377 lines
14 KiB
Python

#!/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ść kart gracza
#
# ##### Dane wyjściowe:
# - Decyzja dot. akcji w grze
# In[12]:
def getSplitDecision(dealerCard, playerCardsVal):
"""
Args:
dealerCard (int): value of the dealer card
playerCardsVal (int): sum of the player cards
Returns:
str: decision
"""
FS = FuzzySystem(show_banner=False)
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]))
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]))
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 (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)",
])
FS.set_variable("dealerCardValue", dealerCard)
FS.set_variable("splitValue", playerCardsVal)
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')
# ## Sterownik 3 - Decyzja jaką akcję podjąć (twarda ręka)
# ##### Dane wejściowe:
# - Wartość widocznej karty krupiera
# - Suma kart gracza
# - Liczba kart gracza
#
# ##### Dane wyjściowe:
# - Decyzja dot. akcji w grze
# In[29]:
def getHardHandDecision(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
"""
FS = FuzzySystem(show_banner=False)
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]))
FS.add_linguistic_variable("playerCardsValue", LinguisticVariable([
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]))
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]))
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: # gdy początek rozgrywki
FS.add_rules([
"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)",
"IF (playerCardsValue IS very_high) THEN (decision IS stand)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS high) THEN (decision IS stand)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS low) THEN (decision IS stand)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS low) THEN (decision IS stand)",
"IF (playerCardsValue IS very_high) AND (dealerCardValue IS low) THEN (decision IS stand)",
])
else:
FS.add_rules([
"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)",
"IF (playerCardsValue IS very_high) THEN (decision IS stand)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS high) THEN (decision IS stand)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS low) THEN (decision IS stand)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS low) THEN (decision IS stand)",
"IF (playerCardsValue IS very_high) AND (dealerCardValue IS low) THEN (decision IS stand)",
])
FS.set_variable("dealerCardValue", dealerCard)
FS.set_variable("playerCardsValue", playerCardsVal)
FS.set_variable("doubleValue", playerCardsVal)
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')
# ## Sterownik 4 - Decyzja jaką akcję podjąć (miękka ręka)
# ##### Dane wejściowe:
# - Wartość widocznej karty krupiera
# - Wartość kart gracza
# - Liczba kart gracza
#
# ##### Dane wyjściowe:
# - Decyzja dot. akcji w grze
# In[25]:
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
"""
FS = FuzzySystem(show_banner=False)
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]))
FS.add_linguistic_variable("playerCardsValue", LinguisticVariable([
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]))
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]))
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: # gdy początek rozgrywki
FS.add_rules([
"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)",
"IF (playerCardsValue IS very_high) THEN (decision IS stand)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS high) THEN (decision IS stand)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS low) THEN (decision IS stand)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS low) THEN (decision IS stand)",
"IF (playerCardsValue IS very_high) AND (dealerCardValue IS low) THEN (decision IS stand)",
])
else:
FS.add_rules([
"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)",
"IF (playerCardsValue IS very_high) THEN (decision IS stand)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS high) THEN (decision IS stand)",
"IF (playerCardsValue IS medium) AND (dealerCardValue IS low) THEN (decision IS stand)",
"IF (playerCardsValue IS high) AND (dealerCardValue IS low) THEN (decision IS stand)",
"IF (playerCardsValue IS very_high) AND (dealerCardValue IS low) THEN (decision IS stand)",
])
FS.set_variable("dealerCardValue", dealerCard)
FS.set_variable("playerCardsValue", playerCardsVal)
FS.set_variable("doubleValue", playerCardsVal)
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')
# ## 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!)
#
# ##### 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
"""
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)
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)