add other game scoring scripts

This commit is contained in:
swaits committed 2010-10-03 18:59:24 -07:00
1 parent 9a87aca70c
commit c864cf5cdb
73 files changed
+2311

No files matched your search

+375
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+501
View File
@@ -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
BIN
View File
Binary file not shown.
+49
View File
@@ -0,0 +1,49 @@
======================================================
Steve turned in {"witnesses"=>5, "tips"=>5, "fingerprints"=>5, "suspects"=>5, "bullets"=>5}.
Hand too big... discarding 1 suspects.
Hand too big... discarding 1 suspects.
Hand too big... discarding 1 witnesses.
Hand too big... discarding 1 fingerprints.
Hand too big... discarding 1 suspects.
Hand too big... discarding 1 fingerprints.
Hand too big... discarding 1 witnesses.
Hand too big... discarding 1 suspects.
Hand too big... discarding 1 bullets.
Hand too big... discarding 1 fingerprints.
Hand too big... discarding 1 tips.
Hand too big... discarding 1 tips.
New hand is {"witnesses"=>3, "tips"=>3, "fingerprints"=>2, "suspects"=>1, "bullets"=>4}.
+5 points for 1 witnesses card.
+5 points for 1 witnesses card.
+5 points for 1 witnesses card.
+3 points for 1 tips card.
+3 points for 1 tips card.
+3 points for 1 tips card.
+2 points for 1 fingerprints card.
+2 points for 1 fingerprints card.
+4 points for 1 suspects card.
+1 points for 1 bullets card.
+1 points for 1 bullets card.
+1 points for 1 bullets card.
+1 points for 1 bullets card.
Total for Steve: 36
======================================================
======================================================
Steve turned in {"witnesses"=>4, "tips"=>2, "fingerprints"=>3, "suspects"=>1, "bullets"=>0}.
+10 points for being the first entry.
+10 points for being turned in by a girl.
Detected a set of 3 fingerprints, 1 tip will be doubled.
+5 points for 1 witnesses card.
+5 points for 1 witnesses card.
+5 points for 1 witnesses card.
+5 points for 1 witnesses card.
+6 points for 1 tips card multiplied by 2.
+3 points for 1 tips card.
+2 points for 1 fingerprints card.
+2 points for 1 fingerprints card.
+2 points for 1 fingerprints card.
+4 points for 1 suspects card.
You have a pyramid, hand value will double.
Total for Steve: 118
======================================================
BIN
View File
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

+161
View File
@@ -0,0 +1,161 @@
#!/usr/bin/env ruby
class MurderHaggleHand
def initialize(player, bullets, fingerprints, tips, suspects, witnesses, first_entry=false, girl_entered=false)
# build a hand
@player = player
@original_hand = {
'bullets' => bullets,
'fingerprints' => fingerprints,
'tips' => tips,
'suspects' => suspects,
'witnesses' => witnesses,
}
@first_entry = first_entry
@girl_entered = girl_entered
end
def score(quiet=true)
# seed the same so we always get the same results!
srand(32472)
# track the total score
hand_total = 0
card_multipliers = { "bullets" => [], "fingerprints" => [], "tips" => [], "suspects" => [], "witnesses" => [] }
puts "======================================================" unless quiet
puts "#{@player} turned in #{@original_hand.inspect}." unless quiet
# copy the hand so we can mess with it
hand = @original_hand.dup
# not allowed more suspects than witnesses
if hand["suspects"] > hand["witnesses"]
diff = hand["suspects"] - hand["witnesses"]
puts "Discarding #{diff} suspects." unless quiet
hand["suspects"] = hand["witnesses"]
end
# no more than 13 cards allowed
hand_size = hand.values.inject(0) { |sum,n| sum+n }
discarded = 0
(hand_size-13).times do
hand_array = hand.collect { |k,v| [k]*v }.flatten
i = rand(hand_array.size)
puts "Hand too big... discarding 1 #{hand_array[i]}." unless quiet
hand[hand_array[i]] = hand[hand_array[i]] - 1;
discarded += 1
end
puts "New hand is #{hand.inspect}." if discarded > 0 unless quiet
# base scores
base_scores = { "bullets" => 1, "fingerprints" => 2, "tips" => 3, "suspects" => 4, "witnesses" => 5 }
# +10 points for first envelope turned in
if @first_entry
puts "+10 points for being the first entry." unless quiet
hand_total += 10
end
# +10 points for envelope turned in by girls
if @girl_entered
puts "+10 points for being turned in by a girl." unless quiet
hand_total += 10
end
# 8 or more tips is 25 points
if hand["tips"] >= 8
puts "+25 points for having 8 or more tips." unless quiet
hand_total += 25
end
# each set of 3 suspects and 1 witness score 10 points
x = [ hand["suspects"]/3, hand["witnesses"] ].min
if x > 0
puts "+#{x*10} points for #{x} set(s) of 3 suspects/1 witness" unless quiet
hand_total += x*10
end
# each set of 3 fingerprints doubles one tip
(hand["fingerprints"]/3).times do
card_multipliers["tips"] << 2
puts "Detected a set of 3 fingerprints, one tip will be doubled." unless quiet
end
# each set of 2 suspects quadruples the value of one bullet casing
(hand["suspects"]/2).times do
card_multipliers["bullets"] << 4
puts "Detected a set of 2 suspects, one bullet will be quadrupled." unless quiet
end
# now sum up score
hand.each do |k,v|
v.times do
multiplier = card_multipliers[k].shift || 1
base = base_scores[k]
points = base * multiplier
mult_string = multiplier > 1 ? " multiplied by #{multiplier}." : "."
puts "+#{points} points for 1 #{k} card#{mult_string}" unless quiet
hand_total += points
end
end
# pyramid
sorted_counts = hand.values.sort.select { |x| x > 0 }
if sorted_counts == [1,2,3,4]
hand_total *= 2
puts "You have a pyramid, hand value will double." unless quiet
end
# input total
puts "Total for #{@player}: #{hand_total}" unless quiet
puts "======================================================" unless quiet
puts " " unless quiet
hand_total
end
end
#best = 0
#14.times do |f|
# 14.times do |t|
# 14.times do |w|
# 14.times do |s|
# 14.times do |b|
# hand = MurderHaggleHand.new("Test",b,f,t,s,w,true,true)
# score = hand.score
# if score > best
# hand.score(false)
# best = score
# end
# end
# end
# end
# end
#end
# (player, bullets, fingerprints, tips, suspects, witnesses, first_entry=false, girl_entered=false)
hands = [
MurderHaggleHand.new("Abe",2,0,0,2,1,false,false),
MurderHaggleHand.new("Casey",0,3,5,0,0,false,false),
MurderHaggleHand.new("Craig",1,2,0,3,4,false,false),
MurderHaggleHand.new("Dundee",2,2,2,3,3,false,false),
MurderHaggleHand.new("Eddy",6,3,2,2,0,false,true),
MurderHaggleHand.new("Francois",2,2,2,1,1,false,true),
MurderHaggleHand.new("Jon",9,1,0,0,0,false,false),
MurderHaggleHand.new("Josh",0,3,2,4,1,false,false),
MurderHaggleHand.new("Lonna",0,1,2,3,4,true,true),
MurderHaggleHand.new("Mary Tess",0,2,1,3,4,false,true),
MurderHaggleHand.new("Mike",1,0,0,0,0,false,false),
MurderHaggleHand.new("Nate",0,3,1,3,3,false,false),
MurderHaggleHand.new("PJ",0,3,8,0,2,false,false),
MurderHaggleHand.new("Shae",0,2,3,4,4,false,true),
]
hands.sort { |a,b| b.score <=> a.score }.each do |h|
h.score(false)
end
+124
View File
@@ -0,0 +1,124 @@
#!/usr/bin/env ruby
class MurderHaggleHand
def initialize(player, bullets, fingerprints, tips, suspects, witnesses, first_entry=false, girl_entered=false)
# build a hand
@player = player
@original_hand = {
'bullets' => bullets,
'fingerprints' => fingerprints,
'tips' => tips,
'suspects' => suspects,
'witnesses' => witnesses,
}
@first_entry = first_entry
@girl_entered = girl_entered
end
def score
# seed the same so we always get the same results!
srand(32472)
# track the total score
hand_total = 0
card_multipliers = { "bullets" => [], "fingerprints" => [], "tips" => [], "suspects" => [], "witnesses" => [] }
puts "======================================================"
puts "#{@player} turned in #{@original_hand.inspect}."
# copy the hand so we can mess with it
hand = @original_hand.dup
# no more than 13 cards allowed
hand_size = hand.values.inject(0) { |sum,n| sum+n }
discarded = 0
(hand_size-13).times do
hand_array = hand.collect { |k,v| [k]*v }.flatten
i = rand(hand_array.size)
puts "Hand too big... discarding 1 #{hand_array[i]}."
hand[hand_array[i]] = hand[hand_array[i]] - 1;
discarded += 1
end
puts "New hand is #{hand.inspect}." if discarded > 0
# base scores
base_scores = { "bullets" => 1, "fingerprints" => 2, "tips" => 3, "suspects" => 4, "witnesses" => 5 }
# not allowed more suspects than witnesses
if hand["suspects"] > hand["witnesses"]
diff = hand["suspects"] - hand["witnesses"]
puts "Discarding #{diff} suspects."
hand["suspects"] = hand["witnesses"]
end
# +10 points for first envelope turned in
if @first_entry
puts "+10 points for being the first entry."
hand_total += 10
end
# +10 points for envelope turned in by girls
if @girl_entered
puts "+10 points for being turned in by a girl."
hand_total += 10
end
# 8 or more tips is 25 points
if hand["tips"] >= 8
puts "+25 points for having 8 or more tips."
hand_total += 25
end
# each set of 4 suspects and 1 witness score 10 points
x = [ hand["suspects"]/4, hand["witnesses"] ].min
if x > 0
puts "+#{x*10} points for #{x} set(s) of 4 suspects/1 witness"
hand_total += x*10
end
# each set of 3 fingerprints doubles one tip
(hand["fingerprints"]/3).times do
card_multipliers["tips"] << 2
puts "Detected a set of 3 fingerprints, 1 tip will be doubled."
end
# each set of 2 suspects quadruples the value of one bullet casing
(hand["suspects"]/2).times do
card_multipliers["bullets"] << 4
puts "Detected a set of 2 suspects, 1 bullet will be quadrupled."
end
# now sum up score
hand.each do |k,v|
v.times do
multiplier = card_multipliers[k].shift || 1
base = base_scores[k]
points = base * multiplier
mult_string = multiplier > 1 ? " multiplied by #{multiplier}." : "."
puts "+#{points} points for 1 #{k} card#{mult_string}"
hand_total += points
end
end
# pyramid
sorted_counts = hand.values.sort.select { |x| x > 0 }
if sorted_counts == [1,2,3,4]
hand_total *= 2
puts "You have a pyramid, hand value will double."
end
# input total
puts "Total for #{@player}: #{hand_total}"
puts "======================================================"
print " "
end
end
MurderHaggleHand.new("Steve",5,5,5,5,5).score
MurderHaggleHand.new("Steve",0,3,2,1,4,true,true).score
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.