diff --git a/FuzzyControlSystem.py b/FuzzyControlSystem.py index 97f5557..18d2123 100644 --- a/FuzzyControlSystem.py +++ b/FuzzyControlSystem.py @@ -72,7 +72,7 @@ getStartDecision(7, 7) # ## Sterownik 2 - Decyzja o strategii w przypadku pary # ##### Dane wejściowe: # - Wartość widocznej karty krupiera -# - Wartość karty gracza (jednej z pary) +# - Wartość kart gracza # # ##### Dane wyjściowe: # - Decyzja dot. akcji w grze @@ -80,22 +80,27 @@ getStartDecision(7, 7) # In[12]: -def getSplitDecision(dealerCard, playerCard): +def getSplitDecision(dealerCard, playerCardsVal): """ Args: dealerCard (int): value of the dealer card - playerCard (int): value of the player card (one of the pair) + playerCardsVal (int): sum of the player cards 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])) + 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") @@ -103,17 +108,14 @@ def getSplitDecision(dealerCard, playerCard): 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)" + "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("playerCardValue", playerCard) + 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')] @@ -121,11 +123,6 @@ def getSplitDecision(dealerCard, playerCard): return endDecision -# In[13]: - - -getSplitDecision(5, 3) - # In[7]: @@ -135,11 +132,11 @@ getSplitDecision(5, 3) #FS.plot_variable('decision') -# ## Sterownik 3 - Decyzja jaką akcję podjąć (gracz bez asa wśród dwóch kart) +# ## Sterownik 3 - Decyzja jaką akcję podjąć (twarda ręka) # ##### Dane wejściowe: # - Wartość widocznej karty krupiera # - Suma kart gracza -# - Suma zliczonych kart +# - Liczba kart gracza # # ##### Dane wyjściowe: # - Decyzja dot. akcji w grze @@ -147,12 +144,11 @@ getSplitDecision(5, 3) # In[29]: -def getHardHandDecision(dealerCard, playerCardsVal, countedCardsVal, playerCardsNum): +def getHardHandDecision(dealerCard, playerCardsVal, 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 @@ -161,22 +157,27 @@ def getHardHandDecision(dealerCard, playerCardsVal, countedCardsVal, playerCards 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])) + 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([ - TriangleFuzzySet(0,0,12, term="low"), - TriangleFuzzySet(11,14,17, term="average"), - TriangleFuzzySet(12,21,21, term="high")], - universe_of_discourse=[0, 21])) + 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("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])) +# 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") @@ -185,40 +186,36 @@ def getHardHandDecision(dealerCard, playerCardsVal, countedCardsVal, playerCards FS.add_linguistic_variable("decision", LinguisticVariable([O1, O2, O3], universe_of_discourse=[0, 25])) - if playerCardsNum == 2: + if playerCardsNum == 2: # gdy początek rozgrywki 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)" + "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)", ]) 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)", + "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)", ]) FS.set_variable("dealerCardValue", dealerCard) FS.set_variable("playerCardsValue", playerCardsVal) - FS.set_variable("countedCardsValue", countedCardsVal) + 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[19]: - - -getHardHandDecision(4, 10, 0, 2) - # In[7]: @@ -229,11 +226,11 @@ getHardHandDecision(4, 10, 0, 2) # FS.plot_variable('decision') -# ## Sterownik 4 - Decyzja jaką akcję podjąć (gracz z asem wśród dwóch kart) +# ## Sterownik 4 - Decyzja jaką akcję podjąć (miękka ręka) # ##### Dane wejściowe: # - Wartość widocznej karty krupiera -# - Wartość drugiej karty gracza -# - Suma zliczonych kart +# - Wartość kart gracza +# - Liczba kart gracza # # ##### Dane wyjściowe: # - Decyzja dot. akcji w grze @@ -241,27 +238,40 @@ getHardHandDecision(4, 10, 0, 2) # In[25]: -def getSoftHandDecision(dealerCard, playerCardsVal, countedCardsVal, playerCardsNum): +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([ - TriangleFuzzySet(0,0,6, term="low"), - TriangleFuzzySet(4,6,8, term="average"), - TriangleFuzzySet(6,11,11, term="high")], - universe_of_discourse=[0, 11])) + 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("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("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("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])) +# 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") @@ -269,38 +279,37 @@ def getSoftHandDecision(dealerCard, playerCardsVal, countedCardsVal, playerCards O3 = TriangleFuzzySet(13,25,25, term="stand") FS.add_linguistic_variable("decision", LinguisticVariable([O1, O2, O3], universe_of_discourse=[0, 25])) - if playerCardsNum == 2: + + if playerCardsNum == 2: # gdy początek rozgrywki 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)" + "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)", ]) + 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)", + ]) + + FS.set_variable("dealerCardValue", dealerCard) - FS.set_variable("playerCardValue", playerCardsVal) - FS.set_variable("countedCardsValue", playerCardsNum) + 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[26]: - - -getSoftHandDecision(2, 8, 0, 3) - - # In[2]: @@ -309,3 +318,40 @@ getSoftHandDecision(2, 8, 0, 3) # 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)