Fix input cleansing and partner reveal

master
En Yi 2019-06-05 12:16:29 +01:00
parent b98942324f
commit 39c88aada1
2 changed files with 40 additions and 27 deletions

View File

@ -17,11 +17,11 @@ CARDS_SYMBOLS = {14: "A", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6", 7: "7",
100: "Clubs", 200: "Diamonds", 300: "Hearts", 400: "Spades", 500: "No Trump", 100: "Clubs", 200: "Diamonds", 300: "Hearts", 400: "Spades", 500: "No Trump",
} }
INPUT_SYMBOLS = {"c": 100, "d": 200, "h": 300, "s": 400, "n":500, "a": 14, INPUT_SYMBOLS = {"c": 100, "d": 200, "h": 300, "s": 400, "n": 500, "a": 14,
"2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7,
"8": 8, "9": 9, "10": 10, "j": 11, "q": 12, "k": 13, "8": 8, "9": 9, "10": 10, "j": 11, "q": 12, "k": 13,
} }
BID_SYMBOLS = {"c": 100, "d": 200, "h": 300, "s": 400, "n": 500}
class DeckReveal(Enum): class DeckReveal(Enum):
SHOW_ALL = 1 SHOW_ALL = 1
@ -353,19 +353,24 @@ def get_suit_string(value):
def convert_input_string(string): def convert_input_string(string):
string = string.lower()
try: try:
if string[0:-1].isalnum() and string[-1].isalpha():
return INPUT_SYMBOLS[string[0:-1]] + INPUT_SYMBOLS[string[-1]] return INPUT_SYMBOLS[string[0:-1]] + INPUT_SYMBOLS[string[-1]]
return -1
except KeyError: except KeyError:
return -1 return -1
def convert_bid_string(string): def convert_bid_string(string):
string = string.lower()
try: try:
return int(string[0])*10 + INPUT_SYMBOLS[string[1]]//100 if string[0].isdecimal() and string[1].isalpha():
return int(string[0])*10 + BID_SYMBOLS[string[1]]//100
return -1
except KeyError: except KeyError:
return -1 return -1
except ValueError:
return -1
class test_screen(view.PygView): class test_screen(view.PygView):

View File

@ -13,7 +13,7 @@ NUM_OF_PLAYERS = 4
STARTING_HAND = 13 STARTING_HAND = 13
HIGHEST_CARD = 414 HIGHEST_CARD = 414
LOWEST_CARD = 102 LOWEST_CARD = 102
VIEW_TRANSPARENT = False VIEW_TRANSPARENT = False # Make the text box not transparent
class GameState(Enum): class GameState(Enum):
@ -33,10 +33,11 @@ class PlayerRole(Enum):
class Table: class Table:
""" """
A Table is the place where all actions takes place. It is essentially a FSM, doing different A Table is the place where all actions takes place. It is essentially a FSM, doing different
routines at each state. It needs to keep track of the score, roles, and the rules. It needs routines at each state. It needs to keep track of the score, roles, the rules, etc. It needs
to ask each player for decisions and respond to them accordingly. The table will also need to ask each player for decisions and respond to them accordingly. The table will also need
to inform any decision to the Main Screen so that it can update the screen to reflect that to inform any decision to the Main Screen so that it can update the screen to reflect that
change through the use of callbacks (Signal and Slot). change through the use of callbacks (Signal and Slot). This call should be minimised by making
all the changes before calling to update the screen in one go.
FSM cycles FSM cycles
--- ---
@ -80,6 +81,9 @@ class Table:
# For gameplay # For gameplay
self.game_state = GameState.DEALING self.game_state = GameState.DEALING
self.current_round = 0 self.current_round = 0
self.passes = 0
self.current_player = 0
self.first_player = False # This is for bidding purposes
self.players = [] self.players = []
self.players_playzone = [] self.players_playzone = []
# Table status will be made known to the player by reference # Table status will be made known to the player by reference
@ -93,25 +97,29 @@ class Table:
self.background.fill(clear_colour) self.background.fill(clear_colour)
self.background = self.background.convert() self.background = self.background.convert()
# TODO: Update the drawing of the table?
# Prepare the card with dimensions
w_deck = min(self.height, self.width) * 0.18 w_deck = min(self.height, self.width) * 0.18
l_deck = min(self.width, self.height) * 0.7 l_deck = min(self.width, self.height) * 0.7
# This is not a deck as it will never be drawn # This is not a deck as it will never be drawn
self.discard_deck = cards.prepare_playing_cards(int(w_deck*0.7), int(w_deck*0.9)) self.discard_deck = cards.prepare_playing_cards(int(w_deck*0.7), int(w_deck*0.9))
game_margins = 5
# Players' deck positioning
playerx = ((self.width - l_deck)//2, playerx = ((self.width - l_deck)//2,
0, game_margins,
(self.width - l_deck)//2, (self.width - l_deck)//2,
self.width - w_deck) self.width - w_deck - game_margins)
playery = (self.height - w_deck, playery = (self.height - w_deck - game_margins,
(self.height - l_deck)//2, (self.height - l_deck)//2,
0, game_margins,
(self.height - l_deck)//2) (self.height - l_deck)//2)
h_spacing = 20 h_spacing = 20
v_spacing = 25 v_spacing = 25
# Middle playfield for announcer and player playing deck positioning
playfield_margins = 10 playfield_margins = 10
margins_with_w_deck = w_deck + playfield_margins margins_with_w_deck = w_deck + playfield_margins + game_margins
playfield_x = margins_with_w_deck playfield_x = margins_with_w_deck
playfield_y = margins_with_w_deck playfield_y = margins_with_w_deck
playfield_width = self.width - margins_with_w_deck * 2 playfield_width = self.width - margins_with_w_deck * 2
@ -126,6 +134,7 @@ class Table:
playfield_y, playfield_y,
playfield_y + (playfield_height - margins_with_w_deck) // 2) playfield_y + (playfield_height - margins_with_w_deck) // 2)
# Player stats positioning
stats_width = 100 stats_width = 100
self.stats_height = 100 self.stats_height = 100
stats_spacing = 10 stats_spacing = 10
@ -141,6 +150,7 @@ class Table:
self.player_stats = [[], [], [], []] self.player_stats = [[], [], [], []]
# TODO: change surface to use colorkey, maybe, if the performance is tanked # TODO: change surface to use colorkey, maybe, if the performance is tanked
# Prepare all the player surfaces
for i in range(4): for i in range(4):
vert = i % 2 == 1 vert = i % 2 == 1
spacing = h_spacing spacing = h_spacing
@ -167,8 +177,11 @@ class Table:
self.center_text_on_surface(surf, rendered_text, self.center_text_on_surface(surf, rendered_text,
(255, 255, 255, 255 * VIEW_TRANSPARENT)) (255, 255, 255, 255 * VIEW_TRANSPARENT))
self.player_stats[i].append(surf) self.player_stats[i].append(surf)
if autoplay: if autoplay:
self.players[0].add_ai(ai.RandomAI(self.table_status)) self.players[0].add_ai(ai.RandomAI(self.table_status))
# Announcer positioning and surface creation
announcer_margins = 5 announcer_margins = 5
announcer_spacing = announcer_margins + w_deck announcer_spacing = announcer_margins + w_deck
self.announcer_x = playfield_x + announcer_spacing self.announcer_x = playfield_x + announcer_spacing
@ -186,9 +199,7 @@ class Table:
self.ongoing = False self.ongoing = False
self.passes = 0
self.current_player = 0
self.first_player = False
def center_text_on_surface(self, surf, rendered_text, clear_colour): def center_text_on_surface(self, surf, rendered_text, clear_colour):
line_center = surf.get_rect().center line_center = surf.get_rect().center
@ -422,9 +433,9 @@ class Table:
# Leading player starts with the leading card, which determines the leading suit # Leading player starts with the leading card, which determines the leading suit
self.current_player = self.table_status['leading player'] self.current_player = self.table_status['leading player']
self.display_current_player(self.current_player) self.display_current_player(self.current_player)
leading_card = self.players[self.current_player].make_decision(self.game_state, 0) card = self.players[self.current_player].make_decision(self.game_state, 0)
self.table_status["played cards"][self.current_player] = leading_card self.table_status["played cards"][self.current_player] = card
self.players_playzone[self.current_player].add_card(leading_card) self.players_playzone[self.current_player].add_card(card)
elif not all(self.table_status["played cards"]): elif not all(self.table_status["played cards"]):
# Subsequent player make their plays, following suit if possible # Subsequent player make their plays, following suit if possible
self.display_current_player(self.current_player) self.display_current_player(self.current_player)
@ -472,8 +483,7 @@ class Table:
return return
if not self.table_status['partner reveal']: if not self.table_status['partner reveal']:
leading_card = self.table_status["played cards"][self.table_status['leading player']] if card.value == self.table_status['partner']:
if leading_card.value == self.table_status['partner']:
self.table_status['partner reveal'] = True self.table_status['partner reveal'] = True
self.write_message("Partner Revealed!", delay_time=1) self.write_message("Partner Revealed!", delay_time=1)
self.reveal_all_roles(self.current_player) self.reveal_all_roles(self.current_player)
@ -519,7 +529,7 @@ class Player(cards.Deck):
A player is essentially a Deck with decision making function or AI component if it is a bot A player is essentially a Deck with decision making function or AI component if it is a bot
that returns a valid action for the Table/Board. that returns a valid action for the Table/Board.
The player has the knowledge of Table status in the form of a dictatary (as it is mutable, thus passed by ref) The player has the knowledge of Table status in the form of a dictionary (as it is mutable, thus passed by ref)
so all validation is done by the player so all validation is done by the player
Possible decisions, each decision has to be enum maybe: Possible decisions, each decision has to be enum maybe:
@ -592,7 +602,7 @@ class Player(cards.Deck):
bid = cards.convert_bid_string(bid) bid = cards.convert_bid_string(bid)
if bid < 0: if bid < 0:
print("Please enter integer only") print("Error in processing bid")
continue continue
if self._table_status["bid"] < bid: if self._table_status["bid"] < bid:
@ -610,7 +620,6 @@ class Player(cards.Deck):
""" """
current_card_values = self.get_deck_values() current_card_values = self.get_deck_values()
while True: while True:
# TODO: Make a more natural input parsing
partner = input("Please call your partner card. Enter card number + suit number \n" partner = input("Please call your partner card. Enter card number + suit number \n"
"e.g. qs is Queen Spade, 8c is 8 Clubs, ah is Ace Hearts\n") "e.g. qs is Queen Spade, 8c is 8 Clubs, ah is Ace Hearts\n")
@ -628,7 +637,6 @@ class Player(cards.Deck):
:return: A valid Card :return: A valid Card
""" """
while True: while True:
# TODO: Make a more natural input parsing
play = input("Please play a card.Enter card number + suit number \n" play = input("Please play a card.Enter card number + suit number \n"
"e.g. qs is Queen Spade, 8c is 8 Clubs, ah is Ace Hearts\n") "e.g. qs is Queen Spade, 8c is 8 Clubs, ah is Ace Hearts\n")
if play == "v": if play == "v":