Skip to content

Instantly share code, notes, and snippets.

@adityashedge
Created January 18, 2017 14:04
Show Gist options
  • Save adityashedge/622216e45b69b99c1fb1862127ede7d2 to your computer and use it in GitHub Desktop.
Save adityashedge/622216e45b69b99c1fb1862127ede7d2 to your computer and use it in GitHub Desktop.
Greed 🎲 game
MIN_PLAYERS = 2
FINAL_ROUND_SCORE = 3000
class Player
attr_reader :attempts, :total
attr_accessor :name, :can_accumulate_points
def initialize
@turns = []
@total = 0
@can_accumulate_points = false
end
def display_name
"Player #{@name + 1}"
end
def add_turn(diceset)
return if !can_accumulate_points
@turns << diceset
@total += diceset.total
end
end
class DiceSet
attr_reader :values, :total, :non_scoring_dice
attr_accessor :available_dice
def initialize
@available_dice = (1..6).to_a
@non_scoring_dice = []
end
def values=(dice)
@values = Array.new(dice) { available_dice.sample }
end
def roll(dice)
self.values = dice
@total = 0
score
end
def dice_counts
@dice_counts ||= values.inject({}){|hash, face| hash[face] ? hash[face] += 1 : hash[face] = 1; hash }
end
def score
dice_counts.each do |face, count|
if face == 1
if count >= 3
@total += (1000 + ((count - 3) * 100))
else
@total += count * 100
end
elsif face == 5
if count >= 3
@total += ((face * 100) + ((count - 3) * 50))
else
@total += count * 50
end
elsif count >= 3
@total += face * 100
else
@non_scoring_dice << face
end
end
end
end
def set_next_active_player(players, current_player)
(current_player.name == players.count - 1) ? players.first : players[current_player.name + 1]
end
def roll_the_dice(active_player, dice_counts: 5, non_scoring_dice: [])
dice = DiceSet.new
dice.available_dice = non_scoring_dice unless non_scoring_dice.empty?
dice.roll(dice_counts)
puts "#{active_player.display_name} rolls: #{dice.values.join(', ')}"
puts "Score in this round: #{dice.total}"
dice
end
def final_round(players)
puts "Final round 🎲"
puts "-" * 15
players.each{|pl| roll_the_dice(pl)}
winner = players.max_by(&:total)
puts "Your winner is ", winner.display_name
end
while true
puts "Enter number of players: "
player_cnt = gets.chomp.to_i
break if player_cnt >= MIN_PLAYERS
end
players = []
player_cnt.times do |i|
pl = Player.new
puts pl.name = i
players << pl
end
active_player = players.first
turns = []
last_turn = nil
puts "-" * 15
while true
non_scoring_dice = last_turn&.non_scoring_dice
is_turn_continued = non_scoring_dice && non_scoring_dice.count > 0
dice = if is_turn_continued
roll_the_dice(active_player, dice_counts: non_scoring_dice.count)
else
roll_the_dice(active_player)
end
last_turn = dice
active_player.can_accumulate_points = true if !active_player.can_accumulate_points && dice.total >= 300
turns << dice if active_player.can_accumulate_points
if dice.total == 0
puts "You lose this turn."
last_turn = nil
turns = []
puts active_player.total
puts "-" * 15
active_player = set_next_active_player(players, active_player)
next
end
if players.any?{|pl| pl.total > FINAL_ROUND_SCORE}
final_round(players)
break
end
while true
puts "Do you want to roll the non-scoring #{dice.non_scoring_dice.count} dice? (y/n): "
response = gets.chomp
if response == "y"
break
elsif response == "n"
turns.each{|dice| active_player.add_turn(dice)}
puts "#{active_player.display_name}'s total is #{active_player.total}"
puts "-" * 15
last_turn = nil
turns = []
active_player = set_next_active_player(players, active_player)
break
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment