From: <umg...@us...> - 2007-04-01 17:42:58
|
Revision: 383 http://svn.sourceforge.net/pybridge/?rev=383&view=rev Author: umgangee Date: 2007-04-01 10:42:58 -0700 (Sun, 01 Apr 2007) Log Message: ----------- Fixed to support new table/game architecture. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_bidbox.py trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/window_bidbox.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bidbox.py 2007-04-01 17:41:14 UTC (rev 382) +++ trunk/pybridge/pybridge/ui/window_bidbox.py 2007-04-01 17:42:58 UTC (rev 383) @@ -19,7 +19,7 @@ import gtk from wrapper import GladeWrapper -from eventhandler import eventhandler +from eventhandler import SimpleEventHandler from pybridge.bridge.call import Bid, Pass, Double, Redouble from pybridge.bridge.call import Level, Strain @@ -36,7 +36,7 @@ 'nt' : Strain.NoTrump, } ALL_CALLS = [Pass(), Double(), Redouble()] + \ - [Bid(l, s) for l, s in zip(list(Level)*5, list(Strain)*7)] + [Bid(l, s) for l in Level for s in Strain] class WindowBidbox(GladeWrapper): @@ -49,19 +49,16 @@ glade_name = 'window_bidbox' - callbacks = ('gameCallMade',) - def new(self): - table = self.parent.table - self.set_available_calls(table.seated, table.game.bidding) - - eventhandler.registerCallbacksFor(self, self.callbacks) + self.eventHandler = SimpleEventHandler(self) + self.parent.table.game.attach(self.eventHandler) + self.set_available_calls(self.parent.position, self.parent.table.game.bidding) - def set_available_calls(self, seat, bidding): + def set_available_calls(self, position, bidding): """Enables buttons representing the given calls.""" - if bidding.whoseTurn() == seat: + if bidding.whoseTurn() == position: self.window.set_property('sensitive', True) for call in ALL_CALLS: button = self.get_button_from_call(call) @@ -73,9 +70,8 @@ # Registered event handlers. - def event_gameCallMade(self, table, call, position): - if table == self.parent.table: - self.set_available_calls(table.seated, table.game.bidding) + def event_makeCall(self, call, position): + self.set_available_calls(self.parent.position, self.parent.table.game.bidding) # Utility methods. @@ -108,11 +104,10 @@ def on_call_clicked(self, widget, *args): """Builds a call object and submits.""" - table = self.parent.table # Do not check validity of call: the server will do that. # If call is invalid, ignore the resultant errback. call = self.get_call_from_button(widget) - d = table.gameMakeCall(call) + d = self.parent.player.callRemote('makeCall', call) d.addErrback(lambda r: True) # Ignore any error. Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-04-01 17:41:14 UTC (rev 382) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-04-01 17:42:58 UTC (rev 383) @@ -20,169 +20,180 @@ from wrapper import GladeWrapper from cardarea import CardArea -from eventhandler import eventhandler +from eventhandler import SimpleEventHandler import utils - +from pybridge.network.error import GameError from pybridge.bridge.call import Bid, Pass, Double, Redouble -from pybridge.bridge.symbols import Level, Strain, Player, Rank +from pybridge.bridge.symbols import Direction, Level, Strain, Rank, Vulnerable # Translatable symbols for elements of bridge. CALLTYPE_SYMBOLS = {Pass : _('pass'), Double : _('dbl'), Redouble : _('rdbl') } +DIRECTION_SYMBOLS = {Direction.North : _('North'), Direction.East : _('East'), + Direction.South : _('South'), Direction.West : _('West') } + LEVEL_SYMBOLS = {Level.One : _('1'), Level.Two : _('2'), Level.Three : _('3'), Level.Four : _('4'), Level.Five : _('5'), Level.Six : _('6'), - Level.Seven : _('7'), } + Level.Seven : _('7') } RANK_SYMBOLS = {Rank.Two : _('2'), Rank.Three : _('3'), Rank.Four : _('4'), Rank.Five : _('5'), Rank.Six : _('6'), Rank.Seven : _('7'), Rank.Eight : _('8'), Rank.Nine : _('9'), Rank.Ten : _('10'), Rank.Jack : _('J'), Rank.Queen : _('Q'), Rank.King : _('K'), - Rank.Ace : _('A'), } + Rank.Ace : _('A') } STRAIN_SYMBOLS = {Strain.Club : u'\N{BLACK CLUB SUIT}', Strain.Diamond : u'\N{BLACK DIAMOND SUIT}', Strain.Heart : u'\N{BLACK HEART SUIT}', Strain.Spade : u'\N{BLACK SPADE SUIT}', - Strain.NoTrump : u'NT', } + Strain.NoTrump : u'NT' } -SEAT_SYMBOLS = {Player.North : _('North'), Player.East : _('East'), - Player.South : _('South'), Player.West : _('West') } +VULN_SYMBOLS = {Vulnerable.All : _('All'), Vulnerable.NorthSouth : _('N/S'), + Vulnerable.EastWest : _('E/W'), Vulnerable.None : _('None') } class WindowBridgetable(GladeWrapper): glade_name = 'window_bridgetable' - callbacks = ('observerAdded', 'observerRemoved', 'playerAdded', - 'playerRemoved', 'gameStarted', 'gameFinished', - 'gameCallMade', 'gameCardPlayed', 'gameHandRevealed', - 'messageReceived') - def new(self): self.children = utils.WindowManager() + self.eventHandler = SimpleEventHandler(self) + self.table = None # Table currently displayed in window. - + self.handler = None + self.player, self.position = None, None + # Set up "Take Seat" menu. - items = {} + self.takeseat_items = {} menu = gtk.Menu() - for player in Player: - items[player] = gtk.MenuItem(SEAT_SYMBOLS[player], True) - items[player].connect('activate', self.on_seat_activated, player) - items[player].show() - menu.append(items[player]) + for position in Direction: + item = gtk.MenuItem(DIRECTION_SYMBOLS[position], True) + item.connect('activate', self.on_seat_activated, position) + item.show() + menu.append(item) + self.takeseat_items[position] = item self.takeseat.set_menu(menu) - self.takeseat_items = items - + # Set up CardArea widget. self.cardarea = CardArea() self.cardarea.on_card_clicked = self.on_card_clicked self.cardarea.set_size_request(640, 480) self.scrolled_cardarea.add_with_viewport(self.cardarea) self.cardarea.show() - + renderer = gtk.CellRendererText() - + # Set up bidding history and column display. self.call_store = gtk.ListStore(str, str, str, str) self.biddingview.set_model(self.call_store) - for index, player in enumerate(Player): - title = SEAT_SYMBOLS[player] + for index, position in enumerate(Direction): + title = DIRECTION_SYMBOLS[position] column = gtk.TreeViewColumn(str(title), renderer, text=index) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) column.set_fixed_width(50) self.biddingview.append_column(column) - + # Set up trick history and column display. self.trick_store = gtk.ListStore(str, str, str, str) self.trickview.set_model(self.trick_store) - for index, player in enumerate(Player): - title = SEAT_SYMBOLS[player] + for index, position in enumerate(Direction): + title = DIRECTION_SYMBOLS[position] column = gtk.TreeViewColumn(str(title), renderer, text=index) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) column.set_fixed_width(50) self.trickview.append_column(column) - + # Set up score sheet and column display. self.score_store = gtk.ListStore(str, str, str, str) self.scoresheet.set_model(self.score_store) for index, title in enumerate([_('Contract'), _('Made'), _('N/S'), _('E/W')]): column = gtk.TreeViewColumn(title, renderer, text=index) self.scoresheet.append_column(column) - + # Set up observer listing. self.observer_store = gtk.ListStore(str) self.treeview_observers.set_model(self.observer_store) column = gtk.TreeViewColumn(None, renderer, text=0) self.observer_store.set_sort_column_id(0, gtk.SORT_ASCENDING) self.treeview_observers.append_column(column) - - eventhandler.registerCallbacksFor(self, self.callbacks) def cleanup(self): + print "Cleaning up" self.table = None # Dereference table. # Close all child windows. for windowname in self.children.keys(): self.children.close(windowname) + def errback(self, failure): + print "Error: %s" % failure.getErrorMessage() + + def setTable(self, table): """Changes display to match the table specified. @param table: the (now) focal table. """ self.table = table - self.window.set_title(_('Table %s') % table.id) + self.table.attach(self.eventHandler) + self.table.game.attach(self.eventHandler) + self.player, self.position = None, None + + self.window.set_title(_('Table %s (Bridge)') % self.table.id) self.resetGame() - - if table.game: - - # Redraw hands and, if playing in progress, redraw trick. - for position in table.game.deal: - self.redrawHand(position) - if table.game.playing: + + for position in Direction: + self.redrawHand(position) # Redraw all hands. + + if self.table.game.inProgress(): + # If trick play in progress, redraw trick. + if self.table.game.play: self.redrawTrick() self.setTurnIndicator() - - for call in table.game.bidding.calls: - player = table.game.bidding.whoCalled(call) - self.addCall(call, player) - - self.setDealer(table.dealer) - self.setVuln(table.game.vulnNS, table.game.vulnEW) - + + for call in self.table.game.bidding.calls: + position = self.table.game.bidding.whoCalled(call) + self.addCall(call, position) + + self.setDealer(self.table.game.board['dealer']) + self.setVuln(self.table.game.board['vuln']) + # If contract, set contract. - if table.game.bidding.isComplete(): - contract = table.game.bidding.getContract() + if self.table.game.bidding.isComplete(): + contract = self.table.game.bidding.getContract() self.setContract(contract) - + # If playing, set trick counts. - if table.game.playing: - for player, cards in table.game.playing.played.items(): + if self.table.game.play: + for position, cards in self.table.game.play.played.items(): for card in cards: - self.addCard(card, player) - self.setTrickCount(table.game.getTrickCount()) - + self.addCard(card, position) + self.setTrickCount(self.table.game.getTrickCount()) + # If user is a player and bidding in progress, open bidding box. - if table.seated and not table.game.bidding.isComplete(): + if self.player and not self.table.game.bidding.isComplete(): self.children.open('window_bidbox', parent=self) - + # Initialise seat menu and player labels. - for seat, player in table.players.items(): - available = player is None or seat == table.seated - self.takeseat_items[seat].set_property('sensitive', available) + for position in Direction: + player = self.table.players.get(position) # Player name or None. + + available = player is None or position == self.position + self.takeseat_items[position].set_property('sensitive', available) if player: - self.event_playerAdded(table, player, seat) - else: # Player vacant. - self.event_playerRemoved(table, None, seat) + self.event_joinGame(player, position) + else: # Position vacant. + self.event_leaveGame(None, position) # Initialise observer listing. self.observer_store.clear() - for observer in table.observers: - self.event_observerAdded(table, observer) + for observer in self.table.observers: + self.event_addObserver(observer) def resetGame(self): @@ -214,8 +225,9 @@ def addCard(self, card, position): """""" + position = self.table.game.play.whoPlayed(card) column = position.index - row = self.table.game.playing.played[position].index(card) + row = self.table.game.play.played[position].index(card) if self.trick_store.get_iter_first() == None: self.trick_store.append() @@ -234,8 +246,8 @@ def addScore(self, contract, made, score): textContract = self.getContractFormat(contract) textMade = '%s' % made - if contract['declarer'] in (Player.North, Player.South) and score > 0 \ - or contract['declarer'] in (Player.East, Player.West) and score < 0: + if contract['declarer'] in (Direction.North, Direction.South) and score > 0 \ + or contract['declarer'] in (Direction.East, Direction.West) and score < 0: textNS, textEW = '%s' % abs(score), '' else: textNS, textEW = '', '%s' % abs(score) @@ -251,16 +263,15 @@ @param position: @param all: If True, do not filter out cards played. """ - hand = self.table.game.deal[position] - played = [] - if self.table.game.playing: - played = self.table.game.playing.played[position] - - if hand: # Own or known hand. - if all is True: # Show all cards. - played = [] + if all is True or self.table.game.play is None: + played = [] + else: + played = self.table.game.play.played[position] + + try: + hand = self.table.game.getHand(position) self.cardarea.set_hand(hand, position, omit=played) - else: # Unknown hand: draw cards face down, use integer placeholders. + except GameError: # Unknown hand: draw cards face down. cards, played = range(13), range(len(played)) self.cardarea.set_hand(cards, position, facedown=True, omit=played) @@ -272,24 +283,22 @@ @param trick: """ trick = None - if self.table.game.playing: - trick = self.table.game.playing.getCurrentTrick() + if self.table.game.play: + trick = self.table.game.play.getCurrentTrick() self.cardarea.set_trick(trick) def setTurnIndicator(self): """Sets the statusbar text to indicate which player is on turn.""" - turn = None - if self.table.game and not self.table.game.isComplete(): - turn = self.table.game.whoseTurn() - - self.cardarea.set_turn(turn) - context = self.statusbar.get_context_id('turn') self.statusbar.pop(context) - if turn: + try: + turn = self.table.game.getTurn() text = _("It is %s's turn") % str(turn) self.statusbar.push(context, text) + except GameError: # Game not in progress + turn = None + self.cardarea.set_turn(turn) def setContract(self, contract=None): @@ -300,7 +309,7 @@ def setDealer(self, dealer): - self.label_dealer.set_markup('<b>%s</b>' % SEAT_SYMBOLS[dealer]) + self.label_dealer.set_markup('<b>%s</b>' % DIRECTION_SYMBOLS[dealer]) def setTrickCount(self, count=None): @@ -320,143 +329,133 @@ self.label_defence.set_markup('<span size="x-large"><b>%s</b> (%s)</span>' % defence) - def setVuln(self, vulnNS, vulnEW): - vuln = {(True, True) : _('All'), - (True, False) : _('N/S'), - (False, True) : _('E/W'), - (False, False) : _('None'), } - self.label_vuln.set_markup('<b>%s</b>' % vuln[(vulnNS, vulnEW)]) + def setVuln(self, vulnerable): + self.label_vuln.set_markup('<b>%s</b>' % VULN_SYMBOLS[vulnerable]) # Registered event handlers. - def event_observerAdded(self, table, observer): - if table == self.table: - self.observer_store.append([observer]) + def event_addObserver(self, observer): + self.observer_store.append([observer]) - def event_observerRemoved(self, table, observer): - + def event_removeObserver(self, observer): + def func(model, path, iter, user_data): if model.get_value(iter, 0) in user_data: model.remove(iter) return True - - if table == self.table: - self.observer_store.foreach(func, observer) + self.observer_store.foreach(func, observer) - def event_playerAdded(self, table, player, position): - if table == self.table: - self.cardarea.set_player_name(position, player) - # Disable menu item corresponding to position. - widget = self.takeseat_items[position] - widget.set_property('sensitive', False) - # Set player label. - label = getattr(self, 'label_%s' % position.key.lower()) - label.set_markup('<b>%s</b>' % player) - - # If all seats occupied, disable Take Seat. - if len([p for p in table.players.values() if p is None]) == 0: - self.takeseat.set_property('sensitive', False) + def event_joinGame(self, player, position): + self.cardarea.set_player_name(position, player) + # Disable menu item corresponding to position. + widget = self.takeseat_items[position] + widget.set_property('sensitive', False) + # Set player label. + label = getattr(self, 'label_%s' % position.key.lower()) + label.set_markup('<b>%s</b>' % player) - def event_playerRemoved(self, table, player, position): - if table == self.table: - self.cardarea.set_player_name(position, None) - # Enable menu item corresponding to position. - widget = self.takeseat_items[position] - widget.set_property('sensitive', True) - # Reset player label. - label = getattr(self, 'label_%s' % position.key.lower()) - label.set_markup('<i>%s</i>' % _('Player vacant')) - - # If we are not seated, ensure Take Seat is enabled. - if not table.seated: - self.takeseat.set_property('sensitive', True) + # If all positions occupied, disable Take Seat. + if len(self.table.players.values()) == len(Direction): + self.takeseat.set_property('sensitive', False) - def event_gameStarted(self, table, dealer, vulnNS, vulnEW): - if table == self.table: - self.children.close('dialog_gameresult') - self.resetGame() - - self.redrawTrick() # Clear trick. - for position in table.game.deal: - self.redrawHand(position) - - self.setTurnIndicator() - self.setDealer(table.dealer) - self.setVuln(table.game.vulnNS, table.game.vulnEW) - - if table.seated: - self.children.open('window_bidbox', parent=self) + def event_leaveGame(self, player, position): + self.cardarea.set_player_name(position, None) + # Enable menu item corresponding to position. + widget = self.takeseat_items[position] + widget.set_property('sensitive', True) + # Reset player label. + label = getattr(self, 'label_%s' % position.key.lower()) + label.set_markup('<i>%s</i>' % _('Position vacant')) + # If we are not seated, ensure Take Seat is enabled. + if self.position is None: + self.takeseat.set_property('sensitive', True) - def event_gameCallMade(self, table, call, position): - if table == self.table: - self.addCall(call, position) - self.setTurnIndicator() - if table.game.bidding.isComplete(): - self.children.close('window_bidbox') # If playing. - contract = table.game.bidding.getContract() - self.setContract(contract) + def event_start(self, board): + #self.children.close('dialog_gameresult') + self.resetGame() - def event_gameCardPlayed(self, table, card, position): - if table == self.table: - self.addCard(card, position) - self.setTurnIndicator() - count = table.game.getTrickCount() - self.setTrickCount(count) - self.redrawTrick() + #self.redrawTrick() # Clear trick. + for position in Direction: self.redrawHand(position) + self.setTurnIndicator() + self.setDealer(board['dealer']) + self.setVuln(board['vuln']) - def event_gameFinished(self, table): - if table == self.table: - - for position in table.game.deal: - self.redrawHand(position, all=True) - self.setTurnIndicator() - - # Determine and display score in dialog box. - contract = table.game.bidding.getContract() - if contract: - trickCount = table.game.getTrickCount() - offset = trickCount['declarerWon'] - trickCount['required'] - score = table.game.score() - self.addScore(contract, trickCount['declarerWon'], score) - - textContract = _('Contract %s') % self.getContractFormat(contract) - textTrick = (offset > 0 and _('made by %s tricks') % offset) or \ - (offset < 0 and _('failed by %s tricks') % abs(offset)) or \ - _('made exactly') - scorer = (score >= 0 and _('declarer')) or _('defence') - textScore = _('Score %s points for %s') % (abs(score), scorer) - - message = '%s %s.\n\n%s.' % (textContract, textTrick, textScore) - else: - message = _('Bidding passed out.') - - dialog = self.children.open('dialog_gameresult', parent=self) - dialog.setup(message) + if self.player: + d = self.player.callRemote('getHand') + d.addCallbacks(self.table.game.revealHand, self.errback, + callbackKeywords={'position' : self.position}) + self.children.open('window_bidbox', parent=self) - def event_gameHandRevealed(self, table, hand, position): - if table == self.table: - self.redrawHand(position) + def event_makeCall(self, call, position): + self.addCall(call, position) + self.setTurnIndicator() + if self.table.game.bidding.isComplete(): + self.children.close('window_bidbox') # If playing. + contract = self.table.game.bidding.getContract() + self.setContract(contract) - def event_messageReceived(self, table, message, sender, recipients): - if table == self.table: - buffer = self.chat_messagehistory.get_buffer() - iter = buffer.get_end_iter() - buffer.insert(iter, '%s: %s\n' % (sender, message)) - self.chat_messagehistory.scroll_to_iter(iter, 0) + def event_playCard(self, card, position): + # Determine the position of the hand from which card was played. + playfrom = self.table.game.play.whoPlayed(card) + self.addCard(card, playfrom) + self.setTurnIndicator() + count = self.table.game.getTrickCount() + self.setTrickCount(count) + self.redrawTrick() + self.redrawHand(playfrom) + def event_gameFinished(self): + for position in self.table.game.deal: + self.redrawHand(position, all=True) + self.setTurnIndicator() + + # Determine and display score in dialog box. + contract = self.table.game.bidding.getContract() + if contract: + trickCount = self.table.game.getTrickCount() + offset = trickCount['declarerWon'] - trickCount['required'] + score = self.table.game.score() + self.addScore(contract, trickCount['declarerWon'], score) + + textContract = _('Contract %s') % self.getContractFormat(contract) + textTrick = (offset > 0 and _('made by %s tricks') % offset) or \ + (offset < 0 and _('failed by %s tricks') % abs(offset)) or \ + _('made exactly') + scorer = (score >= 0 and _('declarer')) or _('defence') + textScore = _('Score %s points for %s') % (abs(score), scorer) + + message = '%s %s.\n\n%s.' % (textContract, textTrick, textScore) + else: + message = _('Bidding passed out.') + + dialog = self.children.open('dialog_gameresult', parent=self) + dialog.setup(message) + + + def event_revealHand(self, hand, position): + self.redrawHand(position) + + + def event_messageReceived(self, message, sender, recipients): + buffer = self.chat_messagehistory.get_buffer() + iter = buffer.get_end_iter() + buffer.insert(iter, '%s: %s\n' % (sender, message)) + self.chat_messagehistory.scroll_to_iter(iter, 0) + + # Utility methods. @@ -481,41 +480,50 @@ def on_card_clicked(self, card, position): -# if self.table.playing and self.table.whoseTurn() == position: - d = self.table.gamePlayCard(card, position) - d.addErrback(lambda _: True) # Ignore any error. + if self.player: + d = self.player.callRemote('playCard', card) + d.addErrback(self.errback) + #d.addErrback(lambda _: True) # Ignore any error. - def on_seat_activated(self, widget, seat): + def on_seat_activated(self, widget, position): - def success(r): + def success(player): + self.player = player # RemoteReference to BridgePlayer object. + self.position = position + self.takeseat.set_property('sensitive', False) self.leaveseat.set_property('sensitive', True) # If game is running and bidding is active, open bidding box. - if self.table.game and not self.table.game.bidding.isComplete(): - self.children.open('window_bidbox', parent=self) + if self.table.game.inProgress(): + d = self.player.callRemote('getHand') + d.addCallbacks(self.table.game.revealHand, self.errback, + callbackKeywords={'position' : self.position}) + if not self.table.game.bidding.isComplete(): + self.children.open('window_bidbox', parent=self) - d = self.table.addPlayer(seat) # Take seat. - d.addCallback(success) + d = self.table.joinGame(position) + d.addCallbacks(success, self.errback) def on_takeseat_clicked(self, widget, *args): # TODO: match user up with preferred partner. - for seat, player in self.table.players.items(): - if player is None: # Vacant. - self.on_seat_activated(widget, seat) + for position in Direction: + if position not in self.table.players: # Position is vacant. + self.on_seat_activated(widget, position) # Take position. break def on_leaveseat_clicked(self, widget, *args): def success(r): + self.position = None self.takeseat.set_property('sensitive', True) self.leaveseat.set_property('sensitive', False) self.children.close('window_bidbox') # If open. - d = self.table.removePlayer() # Leave seat. - d.addCallback(success) + d = self.table.leaveGame(self.position) + d.addCallbacks(success, self.errback) def on_toggle_gameinfo_clicked(self, widget, *args): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |