class Bridge::Result

Constants

VULN_MAP

Attributes

board[RW]

@type board: Board @type contract: Contract @type tricks_made: int or None

claimed[RW]
claimed_by[RW]
contract[RW]

@type board: Board @type contract: Contract @type tricks_made: int or None

contract_level[RW]
is_doubled[RW]
is_major[RW]
is_redoubled[RW]
is_vulnerable[RW]

@type board: Board @type contract: Contract @type tricks_made: int or None

score[RW]

@type board: Board @type contract: Contract @type tricks_made: int or None

tricks_made[RW]

@type board: Board @type contract: Contract @type tricks_made: int or None

tricks_required[RW]
trump_suit[RW]

Public Class Methods

new(board, contract, tricks_made = nil, opts = {}) click to toggle source
# File lib/bridge/result.rb, line 25
def initialize(board, contract, tricks_made = nil, opts = {})
  self.board = board
  self.contract = contract
  self.tricks_made = tricks_made
  
  # a claim has been made. Let's modify the trick count accordingly
  if opts[:claim].is_a?(Array)
    self.claimed_by = opts[:claim][0]
    self.claimed = opts[:claim][1]
    defender_tricks = opts[:claim][2]
    if [self.contract[:declarer],(self.contract[:declarer] + 2) % 4].include?(claimed_by)
      self.tricks_made += claimed # if declarer claimed, add claim to tally
    else # if defender claimed, add what remains to tally
      self.tricks_made = 13 - (defender_tricks + claimed)
    end
    self.tricks_made
  end
  
  self.is_vulnerable = nil
  if self.contract
    vuln = self.board.vulnerability || Vulnerability.none
    self.is_vulnerable = VULN_MAP[vuln].include?(self.contract[:declarer])
  end
  
  self.score = self._get_score
end

Public Instance Methods

_get_score() click to toggle source
# File lib/bridge/result.rb, line 14
def _get_score
  raise NoMethodError  # Expected to be implemented by subclasses.
end
_get_score_components() click to toggle source

Compute the component values which contribute to the score. Note that particular scoring schemes may ignore some of the components. Scoring values: en.wikipedia.org/wiki/Bridge_scoring @return: a dict of component values. @rtype: dict

# File lib/bridge/result.rb, line 57
def _get_score_components
  components = {}

  self.is_doubled      = self.contract[:double_by] ? true : false
  self.is_redoubled    = self.contract[:redouble_by] ? true : false
  self.contract_level  = self.contract[:bid].level + 1
  self.tricks_required = contract_level + 6
  self.trump_suit      = self.contract[:bid].strain
  self.is_major        = [Strain.spade, Strain.heart].include?(self.contract[:bid].strain)
  
  if tricks_made >= tricks_required  # Contract successful.
    #### Contract tricks (bid and made) ####
    if is_major || self.contract[:bid].strain == Strain.no_trump # Hearts, Spades and NT score 30 for each odd trick.
      components['odd'] = contract_level * 30
      if trump_suit == Strain.no_trump
        components['odd'] += 10  # For NT, add a 10 point bonus.
      end
    else
      components['odd'] = contract_level * 20
    end
    
    if is_redoubled
      components['odd'] *= 4  # Double the doubled score.
    elsif is_doubled
      components['odd'] *= 2  # Double score.
    end


    #### over_tricks ####
    over_tricks = tricks_made - tricks_required
    
    if is_redoubled
      # 400 for each overtrick if vulnerable, 200 if not.
      if is_vulnerable
        components['over'] = over_tricks * 400
      else
        components['over'] = over_tricks * 200
      end
    elsif is_doubled
      # 200 for each overtrick if vulnerable, 100 if not.
      if is_vulnerable
        components['over'] = over_tricks * 200
      else
        components['over'] = over_tricks * 100
      end
    else  # Undoubled contract.
      if is_major || self.contract[:bid].strain == Strain.no_trump
        # Hearts, Spades and NT score 30 for each overtrick.
        components['over'] = over_tricks * 30
      else
        # Clubs and Diamonds score 20 for each overtrick.
        components['over'] = over_tricks * 20
      end
    end

    #### Premium bonuses ####

    if tricks_required == 13
      # 1500 for grand slam if vulnerable, 1000 if not.
      if is_vulnerable
        components['slambonus'] = 1500
      else
        components['slambonus'] = 1000
      end
    elsif tricks_required == 12
      # 750 for small slam if vulnerable, 500 if not.
      if is_vulnerable
        components['slambonus'] = 750
      else
        components['slambonus'] = 500
      end
    end
    
    if components['odd'] >= 100 # Game contract (non-slam).
      # 500 for game if vulnerable, 300 if not.
      if is_vulnerable
        components['gamebonus'] = 500
      else
        components['gamebonus'] = 300
      end
    else # Non-game contract.
      components['partscore'] = 50
    end
    
    #### Insult bonus ####
    if is_redoubled
      components['insultbonus'] = 100
    elsif is_doubled
      components['insultbonus'] = 50
    end
  else  # Contract not successful.
    under_tricks = tricks_required - tricks_made
    if is_redoubled
      if is_vulnerable
        # -400 for first, then -600 each.
        components['under'] = -400 + (under_tricks - 1) * -600
      else
        # -200 for first, -400 for second and third, then -600 each.
        components['under'] = -200 + (under_tricks - 1) * -400
        if under_tricks > 3
          components['under'] += (under_tricks - 3) * -200
        end
      end
    elsif is_doubled
      if is_vulnerable
        # -200 for first, then -300 each.
        components['under'] = -200 + (under_tricks - 1) * -300
      else
        # -100 for first, -200 for second and third, then -300 each.
        components['under'] = -100 + (under_tricks - 1) * -200
        if under_tricks > 3
          components['under'] += (under_tricks - 3) * -100
        end
      end
    else
      if is_vulnerable
        # -100 each.
        components['under'] = under_tricks * -100
      else
        # -50 each.
        components['under'] = under_tricks * -50
      end
    end
  end
  components
end
to_a() click to toggle source
# File lib/bridge/result.rb, line 184
def to_a
  { 
    score: _get_score,
    tricks_made: tricks_made,
    tricks_required: tricks_required,
    contract_level: contract_level,
    trump_suit: trump_suit,
    vulnerable: is_vulnerable,
    major: is_major,
    doubled: is_doubled,
    redoubled: is_redoubled,
    claimed: claimed,
    claimed_by: claimed_by
  }
end