|
From: <umg...@us...> - 2007-07-26 19:35:35
|
Revision: 496
http://pybridge.svn.sourceforge.net/pybridge/?rev=496&view=rev
Author: umgangee
Date: 2007-07-26 12:03:38 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Incorporate support for Result objects in board, make appropriate tweaks to dependencies.
Modified Paths:
--------------
trunk/pybridge/pybridge/games/bridge/board.py
trunk/pybridge/pybridge/games/bridge/game.py
trunk/pybridge/pybridge/games/bridge/result.py
trunk/pybridge/pybridge/games/bridge/ui/window_bridgetable.py
Modified: trunk/pybridge/pybridge/games/bridge/board.py
===================================================================
--- trunk/pybridge/pybridge/games/bridge/board.py 2007-07-25 21:04:25 UTC (rev 495)
+++ trunk/pybridge/pybridge/games/bridge/board.py 2007-07-26 19:03:38 UTC (rev 496)
@@ -18,7 +18,9 @@
import random
import time
+
from deal import Deal
+from result import DuplicateResult, RubberResult
from symbols import Direction, Vulnerable
@@ -43,32 +45,68 @@
@type vuln: Vulnerable
"""
+ __directionToVuln = {Direction.North: Vulnerable.NorthSouth,
+ Direction.East: Vulnerable.EastWest,
+ Direction.South: Vulnerable.NorthSouth,
+ Direction.West: Vulnerable.EastWest}
- def nextDeal(self, result=None):
- """Generates and stores a random deal for the board.
+
+ @classmethod
+ def first(cls, deal=None):
+ """Build an initial board.
- If result of a previous game is provided, the dealer and vulnerability
- are rotated according to the rules of bridge.
+ @deal: if provided, the deal to be wrapped by board.
+ Otherwise, a randomly-generated deal is wrapped.
+ """
+ board = cls()
+ board['deal'] = deal or Deal.fromRandom()
+ board['num'] = 1
+ board['time'] = tuple(time.localtime())
+
+ board['dealer'] = Direction.North # Arbitary.
+ board['vuln'] = Vulnerable.None
+
+ return board
+
+
+ def next(self, result, deal=None):
+ """Given the result for this board, builds the next board.
- @param result:
- @type result:
+ The dealer and vulnerability of the next board are calculated
+ from the result provided.
+
+ @param result: the result of the this board.
+ @param deal: if provided, the deal to be wrapped by next board.
+ Otherwise, a randomly-generated deal is wrapped.
"""
- self['deal'] = Deal.fromRandom()
+ assert result.board == self
- self['num'] = self.get('num', 0) + 1
- self['time'] = tuple(time.localtime())
+ board = Board(self.copy()) # copy() returns a dict.
+ board['deal'] = deal or Deal.fromRandom()
+ board['num'] = board.get('num', 0) + 1
+ board['time'] = tuple(time.localtime())
- if self.get('dealer'): # Rotate dealer.
- self['dealer'] = Direction[(self['dealer'].index + 1) % 4]
- else: # Select any player as the dealer.
- self['dealer'] = random.choice(Direction)
+ # Dealer rotates clockwise.
+ board['dealer'] = Direction[(board['dealer'].index + 1) % 4]
- if result:
- # TODO: proper GameResult object.
- # TODO: consider vulnerability rules for duplicate, rubber bridge.
- #if result.bidding.isPassedOut():
- # self['vuln'] = result.board['vuln']
- #elif result.getScore() >= 0
- self['vuln'] = Vulnerable[(result.board['vuln'].index + 1) % 4]
- else:
- self['vuln'] = Vulnerable.None # The default value.
+ if isinstance(result, DuplicateResult):
+ # See http://www.d21acbl.com/References/Laws/node5.html#law2
+ i = (board['num'] - 1) % 16
+ # Map from duplicate board index range 1..16 to vulnerability.
+ board['vuln'] = Vulnerable[(i%4 + i/4)%4]
+
+ elif isinstance(result, RubberResult):
+ # Determine vulnerability of board from result of previous board.
+ above, below = result.score
+ if below >= 100: # Game contract successful.
+ pair = __directionToVuln[result.contract.declarer]
+ # Vulnerability transitions.
+ if board['vuln'] == Vulnerable.None:
+ board['vuln'] = pair
+ elif board['vuln'] in (pair, Vulnerable.All): # Rubber won.
+ board['vuln'] = Vulnerable.None
+ else: # Pair not vulnerable, other pair are vulnerable.
+ board['vuln'] = Vulnerable.All
+
+ return board
+
Modified: trunk/pybridge/pybridge/games/bridge/game.py
===================================================================
--- trunk/pybridge/pybridge/games/bridge/game.py 2007-07-25 21:04:25 UTC (rev 495)
+++ trunk/pybridge/pybridge/games/bridge/game.py 2007-07-26 19:03:38 UTC (rev 496)
@@ -63,12 +63,14 @@
self.auction = None
self.play = None
- self.boardQueue = [] # Boards for successive games.
+ self.boardQueue = [] # Boards for successive rounds.
+ self.results = [] # Results of previous rounds.
self.visibleHands = {} # A subset of deal, containing revealed hands.
self.players = {} # One-to-one mapping from BridgePlayer to Direction.
contract = property(lambda self: self.auction and self.auction.contract or None)
trumpSuit = property(lambda self: self.play and self.play.trumpSuit or None)
+ result = property(lambda self: not self.inProgress() and self.results[-1])
# Implementation of ICardGame.
@@ -81,10 +83,12 @@
if board: # Use specified board.
self.board = board
elif self.board: # Advance to next deal.
- self.board.nextDeal(result=self) # TODO: proper GameResult object.
+ tricksMade, _ = self.play.wonTrickCount()
+ result = DuplicateResult(self.board, self.contract, tricksMade)
+ self.board = self.board.next(result)
else: # Create a board.
- self.board = Board()
- self.board.nextDeal()
+ self.board = Board.first()
+
self.auction = Auction(self.board['dealer']) # Start auction.
self.play = None
self.visibleHands.clear()
@@ -242,10 +246,14 @@
trumpSuit = self.__trumpMap[self.contract.bid.strain]
self.play = TrickPlay(declarer, trumpSuit)
+ # If bidding is passed out, game is complete.
+ if not self.inProgress() and self.board['deal']:
+ self.results.append(DuplicateResult(self.board, contract=None))
+
self.notify('makeCall', call=call, position=position)
- # If bidding is passed out, reveal all hands.
if not self.inProgress() and self.board['deal']:
+ # Reveal all unrevealed hands.
for position in Direction:
hand = self.board['deal'].get(position)
if hand and position not in self.visibleHands:
@@ -302,7 +310,6 @@
raise GameError, "Card cannot be played from hand"
self.play.playCard(card, playfrom)
- self.notify('playCard', card=card, position=position)
# Dummy's hand is revealed when the first card of first trick is played.
if len(self.play[0]) == 1:
@@ -310,12 +317,21 @@
if dummyhand: # Reveal hand only if known.
self.revealHand(dummyhand, self.play.dummy)
- # If play is complete, reveal all hands.
+ # If play is complete, game is complete.
if not self.inProgress() and self.board['deal']:
+ tricksMade, _ = self.play.wonTrickCount()
+ result = DuplicateResult(self.board, self.contract, tricksMade)
+ self.results.append(result)
+
+ self.notify('playCard', card=card, position=position)
+
+ if not self.inProgress() and self.board['deal']:
+ # Reveal all unrevealed hands.
for position in Direction:
hand = self.board['deal'].get(position)
if hand and position not in self.visibleHands:
self.revealHand(hand, position)
+
def revealHand(self, hand, position):
@@ -363,24 +379,8 @@
raise GameError, "No game in progress"
- def getScore(self):
- """Returns the integer score value for declarer/dummy if:
- - auction has been passed out, with no bids made.
- - trick play is complete.
- """
- if self.inProgress() or self.auction is None:
- raise GameError, "Game not complete"
- if self.auction.isPassedOut():
- return 0 # A passed out deal does not score.
- tricksMade, _ = self.play.wonTrickCount()
- result = DuplicateResult(self.contract, self.board['vuln'], tricksMade)
- return result.score
-
-
-
-
class BridgePlayer(pb.Referenceable):
"""Actor representing a player's view of a BridgeGame object."""
Modified: trunk/pybridge/pybridge/games/bridge/result.py
===================================================================
--- trunk/pybridge/pybridge/games/bridge/result.py 2007-07-25 21:04:25 UTC (rev 495)
+++ trunk/pybridge/pybridge/games/bridge/result.py 2007-07-26 19:03:38 UTC (rev 496)
@@ -30,14 +30,17 @@
Vulnerable.All: tuple(Direction)}
- def __init__(self, contract, vuln, tricksMade=None):
+ def __init__(self, board, contract, tricksMade=None):
"""
+ @type board: Board
@type contract: Contract
- @type vuln: Vulnerable
@type tricksMade: int or None
"""
+ self.board = board
self.contract = contract
self.tricksMade = tricksMade
+
+ vuln = self.board.get('vuln', Vulnerable.None)
self.isVulnerable = self.contract.declarer in self.__vulnMapping[vuln]
self.score = self._getScore()
Modified: trunk/pybridge/pybridge/games/bridge/ui/window_bridgetable.py
===================================================================
--- trunk/pybridge/pybridge/games/bridge/ui/window_bridgetable.py 2007-07-25 21:04:25 UTC (rev 495)
+++ trunk/pybridge/pybridge/games/bridge/ui/window_bridgetable.py 2007-07-26 19:03:38 UTC (rev 496)
@@ -103,7 +103,7 @@
def add_score(self, game):
declarerWon, defenceWon = game.play.wonTrickCount()
- score = game.getScore()
+ score = game.result.score
textContract = render_contract(game.contract)
textMade = str(declarerWon)
@@ -339,13 +339,13 @@
if self.table.game.contract:
self.scoreview.add_score(self.table.game)
- declarerWon, defenceWon = self.table.game.play.wonTrickCount()
- required = self.table.game.contract.bid.level.index + 7
- offset = declarerWon - required
- score = self.table.game.getScore()
+ tricksMade = self.table.game.result.tricksMade
+ tricksRequired = self.table.game.contract.bid.level.index + 7
+ offset = tricksMade - tricksRequired
+ score = self.table.game.result.score
fields = {'contract': render_contract(self.table.game.contract),
- 'offset': abs(offset) }
+ 'offset': abs(offset)}
if offset > 0:
if offset == 1:
resultText = _('Contract %(contract)s made by 1 trick.') % fields
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|