Integrate panel to bidding

master
En Yi 2019-06-14 00:04:26 +01:00
parent 016a39a466
commit f88b0abda3
4 changed files with 129 additions and 49 deletions

89
UI.py
View File

@ -5,6 +5,8 @@ from signalslot import Signal
class GenericUI:
def __init__(self, x, y, width, height):
self.draw_update = Signal()
self.x = x
self.y = y
self.width = width
@ -82,13 +84,13 @@ class TextBox(GenericUI):
def redraw(self):
super().redraw()
if self.visible:
outline = (0, 0, self.rect.w, self.rect.h)
pygame.draw.rect(self.background, self.outline_colour, outline, self.outline_thickness)
rendered_text = self.font.render(self.text, True, self.text_colour).convert_alpha()
rect_center = self.background.get_rect().center
text_rect = rendered_text.get_rect(center=rect_center)
self.background.blit(rendered_text, text_rect)
#if self.visible:
outline = (0, 0, self.rect.w, self.rect.h)
pygame.draw.rect(self.background, self.outline_colour, outline, self.outline_thickness)
rendered_text = self.font.render(self.text, True, self.text_colour).convert_alpha()
rect_center = self.background.get_rect().center
text_rect = rendered_text.get_rect(center=rect_center)
self.background.blit(rendered_text, text_rect)
def set_text(self, text):
self.text = text
@ -112,13 +114,13 @@ class Button(TextBox):
self.background.fill((255, 255, 255))
else:
super().redraw()
if self.visible:
outline = (0, 0, self.rect.w, self.rect.h)
pygame.draw.rect(self.background, self.outline_colour, outline, self.outline_thickness)
rendered_text = self.font.render(self.text, True, self.text_colour).convert_alpha()
rect_center = self.background.get_rect().center
text_rect = rendered_text.get_rect(center=rect_center)
self.background.blit(rendered_text, text_rect)
#if self.visible:
outline = (0, 0, self.rect.w, self.rect.h)
pygame.draw.rect(self.background, self.outline_colour, outline, self.outline_thickness)
rendered_text = self.font.render(self.text, True, self.text_colour).convert_alpha()
rect_center = self.background.get_rect().center
text_rect = rendered_text.get_rect(center=rect_center)
self.background.blit(rendered_text, text_rect)
def hold(self, *args):
if not self.button_down:
@ -164,17 +166,17 @@ class ScrollList(GenericUI):
def redraw(self):
super().redraw()
if self.visible:
outline = (0, 0, self.rect.w, self.rect.h)
pygame.draw.rect(self.background, self.outline_colour, outline, self.outline_thickness)
i = 0
for text, text_rect in zip(self.texts, self.text_rects):
if i == self.selected:
pygame.draw.rect(self.background, self.selected_colour, text_rect)
rendered_text = self.font.render(text, True, self.text_colour).convert_alpha()
#if self.visible:
outline = (0, 0, self.rect.w, self.rect.h)
pygame.draw.rect(self.background, self.outline_colour, outline, self.outline_thickness)
i = 0
for text, text_rect in zip(self.texts, self.text_rects):
if i == self.selected:
pygame.draw.rect(self.background, self.selected_colour, text_rect)
rendered_text = self.font.render(text, True, self.text_colour).convert_alpha()
self.background.blit(rendered_text, text_rect)
i += 1
self.background.blit(rendered_text, text_rect)
i += 1
def process_events(self, event):
draw_update = super().process_events(event)
@ -274,6 +276,7 @@ class ScrollList(GenericUI):
current_y += text_rect.height
self.max_offset = max(0, current_y - self.height - self.outline_thickness)
self.redraw()
self.draw_update.emit()
class CallPanel(GenericUI):
@ -291,7 +294,7 @@ class CallPanel(GenericUI):
ui_width = 75
ui_height = 25
width_spacings = (width - 3 * ui_width - 2 * margins) / 4
height_spacings = (height - 2 * margins - 2 * ui_height) / 3
height_spacings = (height - 2 * margins - 3 * ui_height) / 4
self.output_text = ['', '']
self.label1 = TextBox(margins+width_spacings, margins,
@ -309,33 +312,39 @@ class CallPanel(GenericUI):
self.list2.list_selected.connect(lambda text, **z: self.print_list_selection(text, 1))
self.output_box = TextBox(margins+width_spacings*3+ui_width*2, margins+height_spacings,
ui_width, ui_height, text_size=self.text_size)
ui_width, ui_height, text='Bid', text_size=self.text_size)
self.confirm_button = Button(margins+width_spacings*3+ui_width*2, margins+height_spacings*2+ui_height,
ui_width, ui_height, text='OK', text_size=self.text_size)
self.confirm_button.clicked.connect(self.emit_output)
self.cancel_button = Button(margins + width_spacings * 3 + ui_width * 2,
margins + height_spacings * 3 + ui_height * 2,
ui_width, ui_height, text='Cancel', text_size=self.text_size)
self.cancel_button.visible = False
self.cancel_button.clicked.connect(self.cancelling)
self.children = [self.label1, self.list1, self.label2, self.list2,
self.confirm_button, self.output_box]
self.confirm_button, self.output_box, self.cancel_button]
for element in self.children:
element.parent = self
self.redraw()
def redraw(self):
def redraw(self, **kwargs):
super().redraw()
#self.background.fill((255,0,255))
if self.visible:
outline = (0, 0, self.rect.w, self.rect.h)
pygame.draw.rect(self.background, self.outline_colour, outline, self.outline_thickness)
#if self.visible:
outline = (0, 0, self.rect.w, self.rect.h)
pygame.draw.rect(self.background, self.outline_colour, outline, self.outline_thickness)
for element in self.children:
for element in self.children:
if element.visible:
self.background.blit(element.background, element.get_pos())
def process_events(self, event):
draw_update = False
for element in self.children:
if element.process_events(event):
if element.visible and element.process_events(event):
draw_update = True
if draw_update:
@ -347,9 +356,17 @@ class CallPanel(GenericUI):
self.output_box.set_text(' '.join(self.output_text))
def emit_output(self, **kwargs):
output = self.output_text[0]+self.output_text[1][0].lower()
initial = ''
if self.output_text[1]:
initial = self.output_text[1][0].lower()
output = self.output_text[0].lower() + initial
self.confirm_output.emit(output=output)
def cancelling(self, **kwargs):
self.confirm_output.emit(output='')
class TestScreen(view.PygView):
def __init__(self, *args, **kwargs):
@ -393,6 +410,10 @@ class TestScreen(view.PygView):
if event.key == pygame.K_ESCAPE:
running = False
if event.key == pygame.K_o:
self.panel.list1.replace_list([str(i+1) for i in range(7)])
draw_update = True
for element in self.elements:
if element.process_events(event):
draw_update = True

View File

@ -21,3 +21,4 @@ HIGHEST_CARD = 414
LOWEST_CARD = 102
DOUBLE_CLICK_EVENT = pygame.USEREVENT + 1
DOUBLE_CLICK_TIMING = 300
CALL_EVENT = pygame.USEREVENT + 2

View File

@ -1,7 +1,7 @@
import cards
import pprint
import pygame
from game_consts import GameState, PlayerRole, STARTING_HAND, DOUBLE_CLICK_EVENT, DOUBLE_CLICK_TIMING
from game_consts import GameState, PlayerRole, STARTING_HAND, DOUBLE_CLICK_EVENT, DOUBLE_CLICK_TIMING, CALL_EVENT
class Player(cards.Deck):
@ -57,7 +57,7 @@ class Player(cards.Deck):
if sub_state == 0:
if self.AI:
return self.AI.make_a_bid()
return self.make_a_bid()
return self.make_a_bid(game_events=game_events)
else:
if self.AI:
return self.AI.call_partner()
@ -69,7 +69,7 @@ class Player(cards.Deck):
return self.remove_card(pos)
return self.make_a_play(sub_state, game_events=game_events)
def make_a_bid(self):
def make_a_bid(self, game_events=None):
"""
The procedure to make a bid
:return: A valid bid number
@ -191,6 +191,36 @@ class MainPlayer(Player):
self.left_mouse_down = False
self.double_clicking = False
def make_a_bid(self, game_events=None):
"""
The procedure to make a bid
:return: A valid bid number
"""
if game_events:
for event in game_events:
if event.type == CALL_EVENT:
bid = event.call
print(bid)
if not bid:
return 0
bid = cards.convert_bid_string(bid)
if bid < 0:
print("Error in processing bid")
return -1
if self._table_status["bid"] >= bid:
if bid > 75:
print("You cannot bid beyond 7 No Trump")
else:
print("You might need to bid higher")
return -1
return bid
return -1
return -1
def make_a_play(self, substate, game_events=None):
card = None
if game_events:

View File

@ -8,7 +8,7 @@ import copy
import time
from signalslot import Signal
from ai_comp import ai
from game_consts import GameState, PlayerRole, STARTING_HAND, NUM_OF_PLAYERS
from game_consts import GameState, PlayerRole, STARTING_HAND, NUM_OF_PLAYERS, CALL_EVENT
VIEW_TRANSPARENT = False # Make the text box not transparent
@ -49,10 +49,10 @@ class Table:
All played cards go into a hidden discard pile.
"""
update_table = Signal()
def __init__(self, x, y, width, height, clear_colour, autoplay=False, view_all_cards=False):
# TODO: Reduce the amount of update_table call
self.update_table = Signal()
self.x = x
self.y = y
self.width = width
@ -195,8 +195,15 @@ class Table:
self.calling_panel = UI.CallPanel(playdeckx[0]+w_deck+5,playdecky[0]+w_deck-140,
250, 140)
self.calling_panel.parent = self
self.calling_panel.visible = False
self.parent = None
self.calling_panel.confirm_output.connect(self.emit_call)
def emit_call(self, output, **kwargs):
print(output)
pygame.event.post(pygame.event.Event(CALL_EVENT, call=output))
def get_offset_pos(self):
x, y = 0, 0
if self.parent:
@ -306,7 +313,6 @@ class Table:
if draw_update:
self.update_table.emit()
def continue_game(self, game_events):
"""
This is where the FSM is. State transition should occur here.
@ -329,7 +335,7 @@ class Table:
self.write_message("Start to Bid")
self.prepare_bidding()
elif self.game_state == GameState.BIDDING:
bid_complete = self.start_bidding()
bid_complete = self.start_bidding(game_events)
if bid_complete:
self.game_state = GameState.PLAYING
self.update_all_players(role=True, wins=True)
@ -385,30 +391,52 @@ class Table:
1 * (not self.first_player)) % NUM_OF_PLAYERS)
self.write_message(msg, line=2, delay_time=1)
def start_bidding(self):
self.calling_panel.list1.replace_list([str(i+1) for i in range(7)])
self.calling_panel.list2.replace_list(['Clubs', 'Diamonds', 'Hearts', 'Spades', 'No Trump'])
self.calling_panel.cancel_button.visible = True
self.calling_panel.redraw()
self.update_table.emit()
def start_bidding(self, game_events):
"""
The bidding procedure.
:return: Whether bidding is completed
"""
# Highest bid: 7 NoTrump. No further check required
if self.passes < NUM_OF_PLAYERS - 1 and self.table_status["bid"] < 75:
player_bid = self.players[self.current_player].make_decision(self.game_state, 0)
if not self.require_player_input:
if not self.players[self.current_player].AI:
self.require_player_input = True
self.calling_panel.visible = True
self.update_table.emit()
return
else:
player_bid = self.players[self.current_player].make_decision(self.game_state, 0)
else:
player_bid = self.players[self.current_player].make_decision(self.game_state, 0, game_events)
if player_bid < 0:
return
self.require_player_input = False
self.calling_panel.visible = False
self.update_table.emit()
if not player_bid:
if not self.first_player: # Starting bidder pass do not count at the start
self.passes += 1
else:
self.table_status["bid"] = player_bid
self.passes = 0
msg = "Current Bid: {0:d} {1:s}".format(self.table_status["bid"] // 10,
cards.get_suit_string(self.table_status["bid"] % 10))
self.write_message(msg, line=1, update_now=False)
msg = 'Bid Leader: Player {0:d}'.format(self.current_player)
self.write_message(msg, line=2, update_now=True)
if self.table_status["bid"] < 75:
self.current_player += 1
self.current_player %= NUM_OF_PLAYERS
msg = "Current Bid: {0:d} {1:s}".format(self.table_status["bid"] // 10,
cards.get_suit_string(self.table_status["bid"] % 10))
self.write_message(msg, line=1, update_now=False)
msg = 'Bid Leader: Player {0:d}'.format((self.current_player - self.passes
- 1 * (not self.first_player)) % NUM_OF_PLAYERS)
self.write_message(msg, line=2, update_now=False)
self.display_current_player(self.current_player)
if self.first_player:
self.first_player = False