Class: Tabletop::Deck

Inherits:
Hash
  • Object
show all
Defined in:
lib/tabletop/deck.rb

Instance Method Summary collapse

Constructor Details

#initializeDeck

Returns a new instance of Deck.



6
7
8
# File 'lib/tabletop/deck.rb', line 6

def initialize
  super(0)
end

Instance Method Details

#<<(object) ⇒ Object



10
11
12
13
14
15
16
# File 'lib/tabletop/deck.rb', line 10

def << object
  if object.respond_to? :merge
    merge(object) {|card,ours,new| ours+new}
  else
    self[object] = 1
  end
end

#chance_to_draw(cards) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/tabletop/deck.rb', line 93

def chance_to_draw(cards)
  if Array === cards
    copy = self.clone
    odds = 1
    cards.each do |card|
      odds *= copy.chance_to_draw(card)
      copy[card] -= 1
    end
    odds
  else
    if self[cards] and self[cards] != 0
      Float(self[cards])/self.deck_size
    else
      0
    end
  end
end

#deck_sizeObject



18
19
20
# File 'lib/tabletop/deck.rb', line 18

def deck_size
  self.values.inject(:+)
end

#draw(cards = 1) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/tabletop/deck.rb', line 22

def draw(cards=1)
  raise DrawMoreCardsThanDeckHasError if cards > self.deck_size
  drawable_cards = self.clone
  if block_given?
    drawable_cards = drawable_cards.keep_if {|card,copies| yield(card,copies) }
    return nil if drawable_cards.empty?
    # can't use select here, since that returns a Hash instead of a Deck
  end
  drawn = Deck.new
  cards.times do
    running_weight = 0
    n = rand*drawable_cards.deck_size
    drawable_cards.each do |card, weight|
      if running_weight < n && n <= running_weight + weight
        self[card] -= 1
        drawable_cards[card] -= 1
        drawn << card
      end
      running_weight += weight
    end
  end
  drawn
end

#possible_hand?(array) ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
89
90
91
# File 'lib/tabletop/deck.rb', line 86

def possible_hand?(array)
  hand = Hash.new(0)
  array.each { |e| hand[e] +=1 }
  hand.each {|card, number| return false if (self[card].nil? or self[card] < number) }
  true
end

#possible_starting_hands(hand_size = 7) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/tabletop/deck.rb', line 46

def possible_starting_hands(hand_size=7)

  # at any moment, there is some set of cards A that have the highest values, countA
  # (ie, there's the most of them in the deck)
  # there may also be some set of cards B that have the next-highest values, countB
  #
  # in the case of there only being As
    # the most likely combinations are equal numbers of each of them, or as close to that as possible.
    # if A.size is 1, and countA is greater than hand_size
      # the first and last combination would be {A1=>hand_size}
    # if A.size is 1, and countA is less than hand_size...
      # then raise an exception, of course
    # if A.size is 2, and countA is greater than hand_size
      # the first combination would be {A1=>hand}
    # if A.size is 2, and 2*countA is greater than hand_size
    # if A.size is 2, and 2*countA is less than hand_size, then again, exception
  #
  # So the first set of combinations has as it's left term
  # countA-countB of each card in A
  # and as it's right term,
  #
  # they are likely
  # n = copies of most popular card - copies of next most popular card
  #
  # first_hand = n copies of most popular card, up to seven
  # now there is some number A>=2 of cards that are equally likely
  # If A >= 7-n
  # first_hand << unique (k-n)-combinations of those A cards
  # if A < 7-n (that is, if )
  cards_uniq = self.keys
  Enumerator.new do |hands|

    counts = self.values.uniq.sort

    cards_uniq.repeated_combination(hand_size).each do |a|
      hands << a  if self.possible_hand?(a)
    end
  end
end