add other game scoring scripts
This commit is contained in:
1 parent
9a87aca70c
commit
c864cf5cdb
73 files changed
+2311
No files matched your search
Executable
+375
@@ -0,0 +1,375 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'pp'
|
||||
|
||||
# RULE 1. Orange cards have a basic value of 4 and are equal to a red card and a yellow card.
|
||||
# RULE 2. White cards have the highest basic value and are equal to a red card and a blue card.
|
||||
# RULE 3. Blue cards have a basic value of twice that of yellow and half that of orange.
|
||||
# yellow = 1, blue = 2, red = 3, orange = 4, and white = 5
|
||||
|
||||
BaseValues = { :yellow => 1, :blue => 2, :red => 3, :orange => 4, :white => 5 }
|
||||
|
||||
class Card
|
||||
include Comparable
|
||||
attr_reader :color
|
||||
|
||||
def initialize(color)
|
||||
@color = color
|
||||
@multiplier = 1
|
||||
end
|
||||
|
||||
def double!
|
||||
@multiplier *= 2
|
||||
end
|
||||
|
||||
def quadruple!
|
||||
@multiplier *= 4
|
||||
end
|
||||
|
||||
def is_doubled?
|
||||
@multiplier == 2
|
||||
end
|
||||
|
||||
def is_quadrupled?
|
||||
@multiplier == 4
|
||||
end
|
||||
|
||||
def zero!
|
||||
@multiplier = 0
|
||||
end
|
||||
|
||||
def to_s
|
||||
@color.to_s
|
||||
end
|
||||
|
||||
def value
|
||||
BaseValues[@color] * @multiplier
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
# sort by color's base value (i.e. by color), then value
|
||||
# note default is a reverse sort (high to low)
|
||||
[BaseValues[other.color],other.value] <=> [BaseValues[@color],value]
|
||||
end
|
||||
end
|
||||
|
||||
class Hand
|
||||
|
||||
# TODO
|
||||
# attributes: flags (most of a color, etc.), bonuses, suit values, hand multiplier, card multiplier
|
||||
attr_reader :name
|
||||
attr_reader :score
|
||||
|
||||
def initialize(name,yellow,blue,red,orange,white)
|
||||
@name = name
|
||||
@hand_multiplier = 1
|
||||
@bonus = 0
|
||||
@blue_hits = 0
|
||||
@score = nil
|
||||
|
||||
# RULE 5. A player can score only as many orange cards as he has blue cards.
|
||||
if orange > blue
|
||||
puts "*** RULE 5 *** can only score as many orange cards as blue cards"
|
||||
puts "#{@name} lost #{orange - blue} orange cards."
|
||||
orange = blue
|
||||
puts
|
||||
end
|
||||
|
||||
# create hands
|
||||
@cards = []
|
||||
yellow.times { @cards << Card.new(:yellow) }
|
||||
blue.times { @cards << Card.new(:blue) }
|
||||
red.times { @cards << Card.new(:red) }
|
||||
orange.times { @cards << Card.new(:orange) }
|
||||
white.times { @cards << Card.new(:white) }
|
||||
|
||||
#
|
||||
# RULE 15. No more than thirteen cards in a hand can be scored. If more are handed in, the excess will be removed at random.
|
||||
#
|
||||
# check rule 15 straight away.. 13 card limit, excess deleted at random
|
||||
if size > 13
|
||||
puts "*** RULE 15 *** hand size too big (13 max)"
|
||||
puts "#{@name} has too many cards (#{size})."
|
||||
(size-13).times { puts " lost a #{rand_delete} card at random."}
|
||||
puts
|
||||
end
|
||||
end
|
||||
|
||||
# double hand
|
||||
def double!
|
||||
@hand_multiplier *= 2
|
||||
puts "#{@name}'s hand is doubled."
|
||||
end
|
||||
|
||||
# convert to a string
|
||||
def to_s
|
||||
"#{yellow} yellow, #{blue} blue, #{red} red, #{orange} orange, #{white} white"
|
||||
end
|
||||
|
||||
# individual color counts
|
||||
def count_color(color)
|
||||
@cards.count { |x| x.color == color }
|
||||
end
|
||||
def yellow; count_color(:yellow); end
|
||||
def blue; count_color(:blue); end
|
||||
def red; count_color(:red); end
|
||||
def orange; count_color(:orange); end
|
||||
def white; count_color(:white); end
|
||||
|
||||
# removes one randome card
|
||||
def rand_delete
|
||||
# return randomly deleted card (or nil if array is empty)
|
||||
@cards.slice!(Kernel.rand(@cards.size))
|
||||
end
|
||||
|
||||
# total number of cards
|
||||
def size
|
||||
@cards.size
|
||||
end
|
||||
|
||||
def counts
|
||||
[yellow,blue,red,orange,white]
|
||||
end
|
||||
|
||||
def is_pyramid?
|
||||
counts.sort == [0,1,2,3,4]
|
||||
end
|
||||
|
||||
def sets_of_all_five_colors
|
||||
counts.min
|
||||
end
|
||||
|
||||
def num_sets(color,set_size)
|
||||
count_color(color) / set_size
|
||||
end
|
||||
|
||||
def largest_color
|
||||
counts.max
|
||||
end
|
||||
|
||||
def add_bonus!(amount)
|
||||
puts "#{@name} got a bonus of #{amount}."
|
||||
@bonus += amount
|
||||
end
|
||||
|
||||
def blue_hit!(hitter = "")
|
||||
puts "#{hitter} hit #{@name} for 10 points."
|
||||
@blue_hits += 1
|
||||
end
|
||||
|
||||
def double_red!
|
||||
puts "#{@name} now has all red cards doubled in value."
|
||||
@cards.select {|h| h.color == :red }.each(&:double!)
|
||||
end
|
||||
|
||||
def calculate_score!
|
||||
|
||||
# return if we already calculated this!
|
||||
return @score unless @score.nil?
|
||||
|
||||
# otherwise start at 0
|
||||
@score = 0
|
||||
|
||||
# print a little summary
|
||||
puts "Scoring #{@name}"
|
||||
puts "========" + "=" * @name.size
|
||||
puts "* has #{to_s}"
|
||||
puts "* starts with a bonus of #{@bonus}."
|
||||
puts "* starts with a hand multiplier of #{@hand_multiplier}."
|
||||
puts "* has been hit #{@blue_hits} times for -10 points each (#{-10 * @blue_hits} total)."
|
||||
puts
|
||||
|
||||
# RULE 4. If a player has more than three white cards, all of his white cards lose their value.
|
||||
if white > 3
|
||||
puts "*** RULE 4 *** if a player has more than 3 white, all white lose their value"
|
||||
puts "#{@name} has #{white} white cards. setting all to 0."
|
||||
@cards.select { |c| c.color == :white }.each(&:zero!)
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 7. A set of three red cards protects you from one set of five blue cards.
|
||||
if num_sets(:red,3) > 0
|
||||
puts "*** RULE 7 *** A set of three red protects you from one hit of five blue"
|
||||
puts "#{@name} has a set of red; reducing hits from blue by one (+10 points)."
|
||||
@blue_hits -= 1
|
||||
@blue_hits = 0 if @blue_hits < 0
|
||||
puts "after reduction, #{@name} has been hit #{@blue_hits} times for -10 points each (#{-10 * @blue_hits} total)."
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 10. Each set of five different colors gives a bonus of 10 points.
|
||||
if sets_of_all_five_colors > 0
|
||||
puts "*** RULE 10 *** each set of all five colors gives a bonus of 10"
|
||||
sets_of_all_five_colors.times { add_bonus!(10) }
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 11. If a "pyramid" is handed in with no other cards, the value of the hand is doubled. A pyramid consists of four cards of one color, three cards of a second color, two cards of a third color, and one card of a fourth color.
|
||||
if is_pyramid?
|
||||
@hand_multiplier *= 2
|
||||
puts "*** RULE 11 *** 'pyramid' hands are doubled"
|
||||
puts "#{@name} has a pyramid; new hand multiplier is #{@hand_multiplier}."
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 13. Each set of two yellow cards doubles the value of one white card.
|
||||
yellow_sets = num_sets(:yellow,2)
|
||||
if yellow_sets > 0
|
||||
puts "*** RULE 13 *** each set of 2 yellow doubles 1 white"
|
||||
whites_to_double = [white,yellow_sets].min
|
||||
puts "#{@name} has #{yellow_sets} sets; doubling #{whites_to_double} white cards."
|
||||
@cards.select{ |x| x.color == :white }.take(yellow_sets).each(&:double!)
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 14. Each set of three blue cards quadruples the value of one orange card.
|
||||
blue_sets = num_sets(:blue,3)
|
||||
if blue_sets > 0
|
||||
puts "*** RULE 14 *** each set of 3 blue doubles 1 orange"
|
||||
oranges_to_double = [orange,blue_sets].min
|
||||
puts "#{@name} has #{blue_sets} sets; quadrupling #{oranges_to_double} orange cards."
|
||||
@cards.select{ |x| x.color == :orange }.take(blue_sets).each(&:quadruple!)
|
||||
puts
|
||||
end
|
||||
|
||||
# add up score
|
||||
@score = @cards.inject(0) { |sum,x| sum + x.value } + @bonus + @blue_hits * -10
|
||||
|
||||
puts "Final Tally for #{@name}"
|
||||
puts "================" + "=" * @name.size
|
||||
# compute score based on all the scoring attributes set by the scorer
|
||||
@cards.sort.each { |x| puts " %4d %s" % [x.value,x] }
|
||||
puts " %4d [bonus]" % [@bonus]
|
||||
puts "+ %4d [hits]" % [@blue_hits * -10]
|
||||
puts "--------------------"
|
||||
puts " %4d subtotal" % [@score]
|
||||
puts "x %4d [multiplier]" % [@hand_multiplier]
|
||||
puts "--------------------"
|
||||
@score *= @hand_multiplier
|
||||
puts " %4d TOTAL" % [@score]
|
||||
puts
|
||||
|
||||
puts
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
# default is reverse sort (high to low)
|
||||
other.score <=> score
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
puts "***************************"
|
||||
puts "*** V A L I D A T I O N ***"
|
||||
puts "***************************"
|
||||
puts
|
||||
|
||||
@hands = []
|
||||
@hands << Hand.new("Hand #1",0,6,1,3,1) # 56 + other players -10
|
||||
@hands << Hand.new("Hand #2",3,2,2,3,3) # 51 (includes -10 for Hand #1)
|
||||
@hands << Hand.new("Hand #3",0,2,5,2,2) # 52 (Hand #1's -10 is deflected)
|
||||
@hands << Hand.new("Hand #4",4,2,3,0,1) # 54
|
||||
@hands << Hand.new("Hand #5",6,0,1,0,2) # 55
|
||||
|
||||
|
||||
####
|
||||
#### Global Rules Arbitration
|
||||
####
|
||||
|
||||
puts "***********************************"
|
||||
puts "*** G L O B A L S C O R I N G ***"
|
||||
puts "***********************************"
|
||||
puts
|
||||
|
||||
# RULE 9. If a player hands in seven or more cards of the same color, he is eliminated from the game.
|
||||
@hands.each do |h|
|
||||
if h.largest_color >= 7
|
||||
puts "*** RULE 9 *** seven or more cards of one suit causes elimination"
|
||||
puts "#{h.name} is eliminated (#{h})!"
|
||||
puts
|
||||
end
|
||||
end
|
||||
@hands.reject! { |h| h.largest_color >= 7 } # do the actual elimination
|
||||
|
||||
# RULE 8. The player with the most yellow cards gets a bonus of the number of cards squared.
|
||||
# (For example, if most yellow cards are 5, bonus is 25.) If two or more players tie for most
|
||||
# yellow, they are eliminated and bonus goes to the next highest.
|
||||
|
||||
# figure out the highest yellow count
|
||||
max_yellow = @hands.map(&:yellow).max
|
||||
|
||||
# now select the players with that amount
|
||||
max_yellow_hands = @hands.select{ |h| h.yellow == max_yellow }
|
||||
|
||||
# now apply rule
|
||||
if max_yellow_hands.size > 1
|
||||
puts "*** RULE 8 *** players tied for most yellow are eliminated!"
|
||||
max_yellow_hands.each { |h| puts "#{h.name} is eliminated (#{h})!" }
|
||||
@hands = @hands - max_yellow_hands
|
||||
puts
|
||||
elsif max_yellow_hands.size == 1
|
||||
puts "*** RULE 8 *** player with most yellow gets a bonus of number of cards squared"
|
||||
max_yellow_hands[0].add_bonus!(max_yellow_hands[0].yellow ** 2)
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 12. The player with the most red cards doubles their value. In case of a tie, no player collects the extra value.
|
||||
|
||||
# first get the guy(s) with the most red
|
||||
max_red = @hands.map(&:red).max
|
||||
max_red_hands = @hands.select { |h| h.red == max_red }
|
||||
|
||||
# apply rule
|
||||
if max_red_hands.size > 1
|
||||
puts "*** RULE 12 *** in case of a tie (for most red), no player collects the extra value"
|
||||
max_red_hands.each { |h| puts "#{h.name} is tied (#{h.red} red cards)."}
|
||||
puts
|
||||
elsif max_red_hands.size == 1
|
||||
puts "*** RULE 12 *** player with most red cards doubles their value"
|
||||
max_red_hands[0].double_red!
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 6. If a player has five or more blue cards, 10 points are deducted from every other player's score.
|
||||
@hands.each do |h|
|
||||
if h.blue >= 5
|
||||
puts "*** RULE 6 *** a player with 5 or more blue deducts 10 points from all other players score"
|
||||
(@hands - [h]).each { |x| x.blue_hit!(h.name) }
|
||||
puts
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
####
|
||||
#### Summary, after eliminations, eliminated cards, etc.
|
||||
####
|
||||
puts "*********************************"
|
||||
puts "*** F I N A L E N T R I E S ***"
|
||||
puts "*********************************"
|
||||
puts
|
||||
@hands.sort_by(&:name).each { |h| puts "#{h.name}: #{h}"}
|
||||
puts
|
||||
|
||||
####
|
||||
#### Local Rules
|
||||
####
|
||||
|
||||
# second, iterate through each hand and count up local scoring rules; apply to each hand
|
||||
puts "*******************************"
|
||||
puts "*** H A N D S C O R I N G ***"
|
||||
puts "*******************************"
|
||||
puts
|
||||
@hands.sort_by(&:name).each(&:calculate_score!)
|
||||
|
||||
|
||||
####
|
||||
#### Final ranking
|
||||
####
|
||||
puts "*******************************"
|
||||
puts "*** F I N A L S C O R E S ***"
|
||||
puts "*******************************"
|
||||
puts
|
||||
@hands.sort.each_with_index { |h,i| puts "#{i+1}. #{h.name}: #{h.score} points" }
|
||||
puts
|
||||
|
||||
|
||||
+1101
File diff suppressed because it is too large.
Load diff
Executable
+501
@@ -0,0 +1,501 @@
|
||||
#!/usr/bin/env ruby -w
|
||||
|
||||
####
|
||||
#### Haggle scoring script
|
||||
#### =====================
|
||||
####
|
||||
#### Using Haggle rules (and test cases) from "A Gamut of Games", by Sid Sackson
|
||||
####
|
||||
|
||||
|
||||
#################################################################################
|
||||
### raw user data goes here! ####################################################
|
||||
#################################################################################
|
||||
|
||||
PlayerData = [
|
||||
|
||||
|
||||
##
|
||||
## test cases from "A Gamut of Games", by Sid Sackson
|
||||
##
|
||||
# +---------------+--------+--------+--------+--------+--------+
|
||||
# | NAME | YELLOW | PURPLE | PINK | ORANGE | WHITE |
|
||||
# +---------------+--------+--------+--------+--------+--------+
|
||||
#%w( hand_1 0 6 1 3 1 ), # test case, 56 pts.
|
||||
#%w( hand_2 3 2 2 3 3 ), # test case, 51 pts.
|
||||
#%w( hand_3 0 2 5 2 2 ), # test case, 52 pts.
|
||||
#%w( hand_4 4 2 3 0 1 ), # test case, 54 pts.
|
||||
#%w( hand_5 6 0 1 0 2 ), # test case, 55 pts.
|
||||
|
||||
##
|
||||
## played on July 31st, 2010
|
||||
##
|
||||
# +---------------+--------+--------+--------+--------+--------+
|
||||
# | NAME | YELLOW | PURPLE | PINK | ORANGE | WHITE |
|
||||
# +---------------+--------+--------+--------+--------+--------+
|
||||
%w( darla 4 6 3 3 3 ),
|
||||
%w( randy_y 1 3 2 0 4 ),
|
||||
%w( dundee 0 5 3 1 1 ),
|
||||
%w( casey 2 0 3 2 4 ),
|
||||
%w( vince 0 2 3 3 1 ),
|
||||
%w( matt 2 1 4 2 0 ),
|
||||
%w( josh 6 1 3 0 3 ),
|
||||
%w( bill 0 5 0 5 0 ),
|
||||
%w( fred 0 0 0 0 0 ),
|
||||
%w( aaron 0 0 0 0 0 ),
|
||||
%w( jacob 1 2 0 3 0 ),
|
||||
%w( shioui 0 2 3 2 6 ),
|
||||
%w( susan 1 4 1 3 2 ),
|
||||
%w( derek 1 0 0 0 0 ),
|
||||
%w( ratdogg 2 0 2 0 6 ),
|
||||
%w( eileen 3 3 4 3 0 ),
|
||||
%w( sarah_n 2 3 3 1 4 ),
|
||||
%w( tj 2 3 3 2 3 ),
|
||||
%w( ann 3 0 2 3 0 ),
|
||||
%w( randy_s 2 0 5 0 6 ),
|
||||
%w( adam 5 4 1 4 1 ),
|
||||
%w( steven 4 1 2 0 3 ),
|
||||
%w( sarah_w 1 0 0 0 0 ),
|
||||
%w( chris 0 5 0 5 0 ),
|
||||
%w( katie 2 3 3 4 1 ),
|
||||
%w( bonnie 2 5 3 2 2 ),
|
||||
|
||||
]
|
||||
|
||||
|
||||
#################################################################################
|
||||
### script begin ################################################################
|
||||
#################################################################################
|
||||
|
||||
# seed random number generator for consistent results across runs (using my birthday)
|
||||
Kernel.srand(032472)
|
||||
|
||||
# RULE 1. Orange cards have a basic value of 4 and are equal to a pink card and a yellow card.
|
||||
# RULE 2. White cards have the highest basic value and are equal to a pink card and a purple card.
|
||||
# RULE 3. Purple cards have a basic value of twice that of yellow and half that of orange.
|
||||
# yellow = 1, purple = 2, pink = 3, orange = 4, and white = 5
|
||||
BaseValues = { :yellow => 1, :purple => 2, :pink => 3, :orange => 4, :white => 5 }
|
||||
|
||||
|
||||
####
|
||||
#### a single card
|
||||
####
|
||||
class Card
|
||||
include Comparable
|
||||
attr_reader :color
|
||||
|
||||
# constructor
|
||||
def initialize(color)
|
||||
@color = color
|
||||
@multiplier = 1
|
||||
end
|
||||
|
||||
# double value of this card
|
||||
def double!
|
||||
@multiplier *= 2
|
||||
end
|
||||
|
||||
# quadruple value of this card
|
||||
def quadruple!
|
||||
@multiplier *= 4
|
||||
end
|
||||
|
||||
# test if card is doubled
|
||||
def is_doubled?
|
||||
@multiplier == 2
|
||||
end
|
||||
|
||||
# test if card is quadrupled
|
||||
def is_quadrupled?
|
||||
@multiplier == 4
|
||||
end
|
||||
|
||||
# zero out a card's value
|
||||
def zero!
|
||||
@multiplier = 0
|
||||
end
|
||||
|
||||
# create a string description of this card
|
||||
def to_s
|
||||
base = BaseValues[@color]
|
||||
comment_str =
|
||||
if is_doubled?
|
||||
" (doubled, was #{base})"
|
||||
elsif is_quadrupled?
|
||||
" (quadrupled, was #{base})"
|
||||
elsif ( value == 0 )
|
||||
" (zeroed, was #{base})"
|
||||
else
|
||||
""
|
||||
end
|
||||
@color.to_s + comment_str
|
||||
end
|
||||
|
||||
# get card's current value
|
||||
def value
|
||||
BaseValues[@color] * @multiplier
|
||||
end
|
||||
|
||||
# comparison (for sorting)
|
||||
def <=>(other)
|
||||
# sort by color's base value (i.e. by color), then value
|
||||
# note default is a reverse sort (high to low)
|
||||
[BaseValues[other.color],other.value] <=> [BaseValues[@color],value]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
####
|
||||
#### a single hand (contains cards)
|
||||
####
|
||||
class Hand
|
||||
|
||||
attr_reader :name
|
||||
attr_reader :score
|
||||
|
||||
# constructor
|
||||
def initialize(name,yellow,purple,pink,orange,white)
|
||||
@name = name
|
||||
@hand_multiplier = 1
|
||||
@bonus = 0
|
||||
@blue_hits = 0
|
||||
@score = nil
|
||||
|
||||
# RULE 5. A player can score only as many orange cards as he has purple cards.
|
||||
if orange > purple
|
||||
puts "*** RULE 5 *** can only score as many orange cards as purple cards"
|
||||
puts "#{@name} lost #{orange - purple} orange cards."
|
||||
orange = purple
|
||||
puts
|
||||
end
|
||||
|
||||
# populate hand with Card objects
|
||||
@cards = []
|
||||
yellow.times { @cards << Card.new(:yellow) }
|
||||
purple.times { @cards << Card.new(:purple) }
|
||||
pink.times { @cards << Card.new(:pink) }
|
||||
orange.times { @cards << Card.new(:orange) }
|
||||
white.times { @cards << Card.new(:white) }
|
||||
|
||||
#
|
||||
# RULE 15. No more than thirteen cards in a hand can be scored. If more are handed in,
|
||||
# the excess will be removed at random.
|
||||
#
|
||||
# check rule 15 straight away.. 13 card limit, excess deleted at random
|
||||
if size > 13
|
||||
puts "*** RULE 15 *** hand size too big (13 max)"
|
||||
puts "#{@name} has too many cards (#{size})."
|
||||
(size-13).times { puts " lost a #{rand_delete} card at random."}
|
||||
puts
|
||||
end
|
||||
end
|
||||
|
||||
# double hand
|
||||
def double!
|
||||
@hand_multiplier *= 2
|
||||
puts "#{@name}'s hand is doubled."
|
||||
end
|
||||
|
||||
# convert to a string
|
||||
def to_s
|
||||
"#{yellow} yellow, #{purple} purple, #{pink} pink, #{orange} orange, #{white} white"
|
||||
end
|
||||
|
||||
# get individual color counts
|
||||
def count_color(color)
|
||||
@cards.count { |x| x.color == color }
|
||||
end
|
||||
def yellow; count_color(:yellow); end
|
||||
def purple; count_color(:purple); end
|
||||
def pink; count_color(:pink); end
|
||||
def orange; count_color(:orange); end
|
||||
def white; count_color(:white); end
|
||||
|
||||
# removes one randome card
|
||||
def rand_delete
|
||||
# return randomly deleted card (or nil if array is empty)
|
||||
@cards.slice!(Kernel.rand(@cards.size))
|
||||
end
|
||||
|
||||
# total number of cards
|
||||
def size
|
||||
@cards.size
|
||||
end
|
||||
|
||||
# create an array of counts in specific order (used for sorting, various measurement fn's)
|
||||
def counts
|
||||
[yellow,purple,pink,orange,white]
|
||||
end
|
||||
|
||||
# test for a "pyramid"
|
||||
def is_pyramid?
|
||||
counts.sort == [0,1,2,3,4]
|
||||
end
|
||||
|
||||
# count sets of all five colors
|
||||
def sets_of_all_five_colors
|
||||
counts.min
|
||||
end
|
||||
|
||||
# count for sets (of size X) in color Y.. i.e. "sets of 2 in blue (i.e. pairs)"
|
||||
def num_sets(color,set_size)
|
||||
count_color(color) / set_size
|
||||
end
|
||||
|
||||
# return the size of the largest color
|
||||
def largest_color
|
||||
counts.max
|
||||
end
|
||||
|
||||
# add bonus points to this hand
|
||||
def add_bonus!(amount)
|
||||
puts "#{@name} got a bonus of #{amount}."
|
||||
@bonus += amount
|
||||
end
|
||||
|
||||
# add a "blue hit" (i.e. purple in our game) to this hand
|
||||
def blue_hit!(hitter = "")
|
||||
puts "#{hitter} hit #{@name} for 10 points."
|
||||
@blue_hits += 1
|
||||
end
|
||||
|
||||
# double the value of all red (pink on our game) cards
|
||||
def double_red!
|
||||
puts "#{@name} now has all pink cards doubled in value."
|
||||
@cards.select {|h| h.color == :pink }.each(&:double!)
|
||||
end
|
||||
|
||||
# figure out this hand's score (meant to be called once)
|
||||
def calculate_score!
|
||||
|
||||
# return if we already calculated this!
|
||||
return @score unless @score.nil?
|
||||
|
||||
# otherwise start at 0
|
||||
@score = 0
|
||||
|
||||
# print a little summary
|
||||
puts "Scoring #{@name}"
|
||||
puts "========" + "=" * @name.size
|
||||
puts "* has #{to_s}"
|
||||
puts "* starts with a bonus of #{@bonus}."
|
||||
puts "* starts with a hand multiplier of #{@hand_multiplier}."
|
||||
puts "* has been hit #{@blue_hits} times for -10 points each (#{-10 * @blue_hits} total)."
|
||||
puts
|
||||
|
||||
# RULE 4. If a player has more than three white cards, all of his white cards lose their value.
|
||||
if white > 3
|
||||
puts "*** RULE 4 *** if a player has more than 3 white, all white lose their value"
|
||||
puts "#{@name} has #{white} white cards. setting all to 0."
|
||||
@cards.select { |c| c.color == :white }.each(&:zero!)
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 7. A set of three pink cards protects you from one set of five purple cards.
|
||||
if num_sets(:pink,3) > 0
|
||||
puts "*** RULE 7 *** A set of three pink protects you from one hit of five purple"
|
||||
puts "#{@name} has a set of pink; reducing hits from purple by one (+10 points)."
|
||||
@blue_hits -= 1
|
||||
@blue_hits = 0 if @blue_hits < 0
|
||||
puts "after reduction, #{@name} has been hit #{@blue_hits} times for -10 points each (#{-10 * @blue_hits} total)."
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 10. Each set of five different colors gives a bonus of 10 points.
|
||||
if sets_of_all_five_colors > 0
|
||||
puts "*** RULE 10 *** each set of all five colors gives a bonus of 10"
|
||||
sets_of_all_five_colors.times { add_bonus!(10) }
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 11. If a "pyramid" is handed in with no other cards, the value of the hand is
|
||||
# doubled. A pyramid consists of four cards of one color, three cards of a second color,
|
||||
# two cards of a third color, and one card of a fourth color.
|
||||
if is_pyramid?
|
||||
@hand_multiplier *= 2
|
||||
puts "*** RULE 11 *** 'pyramid' hands are doubled"
|
||||
puts "#{@name} has a pyramid; new hand multiplier is #{@hand_multiplier}."
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 13. Each set of two yellow cards doubles the value of one white card.
|
||||
yellow_sets = num_sets(:yellow,2)
|
||||
if yellow_sets > 0
|
||||
puts "*** RULE 13 *** each set of 2 yellow doubles 1 white"
|
||||
whites_to_double = [white,yellow_sets].min
|
||||
puts "#{@name} has #{yellow_sets} sets; doubling #{whites_to_double} white cards."
|
||||
@cards.select{ |x| x.color == :white }.take(yellow_sets).each(&:double!)
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 14. Each set of three purple cards quadruples the value of one orange card.
|
||||
blue_sets = num_sets(:purple,3)
|
||||
if blue_sets > 0
|
||||
puts "*** RULE 14 *** each set of 3 purple quadruples 1 orange"
|
||||
oranges_to_double = [orange,blue_sets].min
|
||||
puts "#{@name} has #{blue_sets} sets; quadrupling #{oranges_to_double} orange cards."
|
||||
@cards.select{ |x| x.color == :orange }.take(blue_sets).each(&:quadruple!)
|
||||
puts
|
||||
end
|
||||
|
||||
# add up score
|
||||
@score = @cards.inject(0) { |sum,x| sum + x.value } + @bonus + @blue_hits * -10
|
||||
|
||||
# output
|
||||
puts "Final Tally for #{@name}"
|
||||
puts "================" + "=" * @name.size
|
||||
# compute score based on all the scoring attributes set by the scorer
|
||||
@cards.sort.each { |x| puts " %4d %s" % [x.value,x] }
|
||||
puts " %4d [bonus]" % [@bonus]
|
||||
puts "+ %4d [hits]" % [@blue_hits * -10]
|
||||
puts "----------------------"
|
||||
puts " %4d SUBTOTAL" % [@score]
|
||||
puts "x %4d [multiplier]" % [@hand_multiplier]
|
||||
puts "----------------------"
|
||||
@score *= @hand_multiplier
|
||||
puts " %4d TOTAL" % [@score]
|
||||
puts
|
||||
|
||||
puts
|
||||
end
|
||||
|
||||
# comparison, for sorting against other hands
|
||||
def <=>(other)
|
||||
# default is reverse sort (high to low)
|
||||
other.score <=> score
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
####
|
||||
#### initialize and validate hands
|
||||
####
|
||||
|
||||
puts "***************************"
|
||||
puts "*** V A L I D A T I O N ***"
|
||||
puts "***************************"
|
||||
puts
|
||||
|
||||
# create hands from PlayerData (at the top of this file)
|
||||
player_hands = []
|
||||
PlayerData.each do |r|
|
||||
# note some validation occurs in Hand creation
|
||||
player_hands << Hand.new(r.shift,r.shift.to_i,r.shift.to_i,r.shift.to_i,r.shift.to_i,r.shift.to_i)
|
||||
end
|
||||
|
||||
|
||||
####
|
||||
#### Global Rules Arbitration
|
||||
####
|
||||
|
||||
puts "***********************************"
|
||||
puts "*** G L O B A L S C O R I N G ***"
|
||||
puts "***********************************"
|
||||
puts
|
||||
|
||||
# RULE 1. Orange cards have a basic value of 4 and are equal to a pink card and a yellow card.
|
||||
# RULE 2. White cards have the highest basic value and are equal to a pink card and a purple card.
|
||||
# RULE 3. Purple cards have a basic value of twice that of yellow and half that of orange.
|
||||
# yellow = 1, purple = 2, pink = 3, orange = 4, and white = 5
|
||||
puts "*** RULES 1, 2, and 3 *** basic values"
|
||||
puts "yellow = 1, purple = 2, pink = 3, orange = 4, and white = 5"
|
||||
puts
|
||||
|
||||
# RULE 9. If a player hands in seven or more cards of the same color, he is eliminated from
|
||||
# the game.
|
||||
player_hands.each do |h|
|
||||
if h.largest_color >= 7
|
||||
puts "*** RULE 9 *** seven or more cards of one suit causes elimination"
|
||||
puts "#{h.name} is eliminated (#{h})!"
|
||||
puts
|
||||
end
|
||||
end
|
||||
player_hands.reject! { |h| h.largest_color >= 7 } # do the actual elimination
|
||||
|
||||
# RULE 8. The player with the most yellow cards gets a bonus of the number of cards squared.
|
||||
# (For example, if most yellow cards are 5, bonus is 25.) If two or more players tie for most
|
||||
# yellow, they are eliminated and bonus goes to the next highest.
|
||||
|
||||
# figure out the highest yellow count
|
||||
max_yellow = player_hands.map(&:yellow).max
|
||||
|
||||
# now select the players with that amount
|
||||
max_yellow_hands = player_hands.select{ |h| h.yellow == max_yellow }
|
||||
|
||||
# now apply rule
|
||||
if max_yellow_hands.size > 1
|
||||
puts "*** RULE 8 *** players tied for most yellow are eliminated!"
|
||||
max_yellow_hands.each { |h| puts "#{h.name} is eliminated (#{h})!" }
|
||||
player_hands = player_hands - max_yellow_hands
|
||||
puts
|
||||
elsif max_yellow_hands.size == 1
|
||||
puts "*** RULE 8 *** player with most yellow gets a bonus of number of cards squared"
|
||||
max_yellow_hands[0].add_bonus!(max_yellow_hands[0].yellow ** 2)
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 12. The player with the most pink cards doubles their value. In case of a tie, no
|
||||
# player collects the extra value.
|
||||
|
||||
# first get the guy(s) with the most pink
|
||||
max_red = player_hands.map(&:pink).max
|
||||
max_red_hands = player_hands.select { |h| h.pink == max_red }
|
||||
|
||||
# apply rule
|
||||
if max_red_hands.size > 1
|
||||
puts "*** RULE 12 *** in case of a tie (for most pink), no player collects the extra value"
|
||||
max_red_hands.each { |h| puts "#{h.name} is tied (#{h.pink} pink cards)."}
|
||||
puts
|
||||
elsif max_red_hands.size == 1
|
||||
puts "*** RULE 12 *** player with most pink cards doubles their value"
|
||||
max_red_hands[0].double_red!
|
||||
puts
|
||||
end
|
||||
|
||||
# RULE 6. If a player has five or more purple cards, 10 points are deducted from every other
|
||||
# player's score.
|
||||
player_hands.each do |h|
|
||||
if h.purple >= 5
|
||||
puts "*** RULE 6 *** five or more purple deducts 10 points from all other players"
|
||||
(player_hands - [h]).each { |x| x.blue_hit!(h.name) }
|
||||
puts
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
####
|
||||
#### output final hand summaries, after eliminations, eliminated cards, etc.
|
||||
####
|
||||
|
||||
puts "*********************************"
|
||||
puts "*** F I N A L E N T R I E S ***"
|
||||
puts "*********************************"
|
||||
puts
|
||||
player_hands.sort_by(&:name).each { |h| puts "#{h.name}: #{h}"}
|
||||
puts
|
||||
|
||||
|
||||
####
|
||||
#### Local Rules (i.e. global scoring is complete, now score each hand)
|
||||
####
|
||||
|
||||
puts "*******************************"
|
||||
puts "*** H A N D S C O R I N G ***"
|
||||
puts "*******************************"
|
||||
puts
|
||||
# iterate through each hand and count up local scoring rules; apply to each hand
|
||||
player_hands.sort_by(&:name).each(&:calculate_score!)
|
||||
|
||||
|
||||
####
|
||||
#### output final ranking
|
||||
####
|
||||
|
||||
puts "*******************************"
|
||||
puts "*** F I N A L S C O R E S ***"
|
||||
puts "*******************************"
|
||||
puts
|
||||
player_hands.sort.each_with_index { |h,i| puts "#{i+1}. #{h.name}: #{h.score} points" }
|
||||
puts
|
||||
|
||||
|
||||
Reference in new issue
Block a user