Skip to content

Instantly share code, notes, and snippets.

@thebinarypenguin
Created July 2, 2012 20:47
Show Gist options
  • Save thebinarypenguin/3035605 to your computer and use it in GitHub Desktop.
Save thebinarypenguin/3035605 to your computer and use it in GitHub Desktop.
This is a solution to the extra credit project from EdgeCase's excellent Ruby Koans; it is an implementation of a dice game called greed. Greed is a "push your luck" style dice game for 2 or more players using 5 six-sided dice.
#!/usr/bin/env ruby
class UI
def self.prompt_for_player_names
puts " _____ _____ ______ ______ _____ "
puts " / ____| | __ \\ | ____| | ____| | __ \\ "
puts " | | __ | |__) | | |__ | |__ | | | | "
puts " | | |_ | | _ / | __| | __| | | | | "
puts " | |__| | | | \\ \\ | |____ | |____ | |__| | "
puts " \\_____| |_| \\_\\ |______| |______| |_____/ "
puts
puts blue("Enter player names seperated by a comma ")
gets.chomp.strip.split(/\s*,\s*/)
end
def self.display_round_number(round_number)
puts
puts white("=== Round #{round_number} ==========================================================")
end
def self.display_last_round()
puts
puts white("=== Last Round =======================================================")
end
def self.display_player_name(player_name, in_the_game)
puts
puts yellow("> #{player_name}'s turn")
if !in_the_game
puts grey("(You must roll atleast #{Game::IN_GAME_POINTS} " +
"points in one turn to enter the game)")
end
end
def self.rolled_no_scoring_dice
puts
puts "You rolled " + red("no scoring dice") + ", your turn is over."
end
def self.rolled_all_scoring_dice(roll_points, turn_points, dice_remaining)
puts
puts "You rolled " + blue(roll_points) + " points giving you " +
"a total of " + blue(turn_points) + " points for this turn. "
puts "And you rolled " + green("all scoring dice") + " so you " +
"get to roll all #{dice_remaining} dice again."
print "Do you wish to roll again? " + grey("[y/n] ")
gets.chomp
end
def self.rolled_dice(roll_points, turn_points, dice_remaining)
puts
puts "You rolled " + blue(roll_points) + " points giving you " +
"a total of " + blue(turn_points) + " points for this turn."
print "You have " + blue(dice_remaining) + " dice remaining. " +
"Do you wish to roll again? " + grey("[y/n] ")
gets.chomp
end
def self.earned_points(turn_points, total_points)
puts
puts "You earned " + green(turn_points) + " points this turn " +
"giving you a total of " + green(total_points) + " points"
end
def self.display_final_scores(players)
puts
puts white("=== Final Scores =====================================================")
puts
players.each do |player|
puts " #{player.name}: " + green(player.total_points)
end
puts
end
def self.colorize(value, color)
case color
when :black then "\e[30m" + value.to_s + "\e[0m"
when :red then "\e[31m" + value.to_s + "\e[0m"
when :green then "\e[32m" + value.to_s + "\e[0m"
when :yellow then "\e[33m" + value.to_s + "\e[0m"
when :blue then "\e[34m" + value.to_s + "\e[0m"
when :magenta then "\e[35m" + value.to_s + "\e[0m"
when :cyan then "\e[36m" + value.to_s + "\e[0m"
when :white then "\e[37m" + value.to_s + "\e[0m"
when :bright_black then "\e[1m\e[30m" + value.to_s + "\e[0m"
when :bright_red then "\e[1m\e[31m" + value.to_s + "\e[0m"
when :bright_green then "\e[1m\e[32m" + value.to_s + "\e[0m"
when :bright_yellow then "\e[1m\e[33m" + value.to_s + "\e[0m"
when :bright_blue then "\e[1m\e[34m" + value.to_s + "\e[0m"
when :bright_magenta then "\e[1m\e[35m" + value.to_s + "\e[0m"
when :bright_cyan then "\e[1m\e[36m" + value.to_s + "\e[0m"
when :bright_white then "\e[1m\e[37m" + value.to_s + "\e[0m"
else value.to_s
end
end
def self.grey(text); colorize(text, :bright_black) end
def self.red(text); colorize(text, :bright_red) end
def self.green(text); colorize(text, :bright_green) end
def self.yellow(text); colorize(text, :bright_yellow) end
def self.blue(text); colorize(text, :bright_blue) end
def self.white(text); colorize(text, :bright_white) end
end
class DiceSet
attr_reader :total_dice
attr_reader :scoring_dice
attr_reader :non_scoring_dice
attr_reader :points
attr_reader :results
def initialize(num_dice)
@total_dice = num_dice
end
def roll
@scoring_dice = 0
@non_scoring_dice = 0
@points = 0
@results = []
# Get raw results
@total_dice.times { @results << rand(6) + 1 }
# Calculate score
1.upto(6) do |num|
qty = @results.count(num)
# Score triples
if qty >= 3
@points += num == 1 ? 1000 : num * 100
@scoring_dice += 3
qty -= 3
end
# Score single 1's
if num == 1
@points += qty * 100
@scoring_dice += qty
end
# Score single 5's
if num == 5
@points += qty * 50
@scoring_dice += qty
end
end
@non_scoring_dice = @total_dice - @scoring_dice
@results
end
def no_scoring_dice?
@scoring_dice == 0 ? true : false
end
def all_scoring_dice?
@scoring_dice == @total_dice ? true : false
end
end
class Player
attr_reader :name
attr_reader :finished
attr_reader :total_points
def initialize(name)
@name = name
@in_the_game = false
@finished = false
@total_points = 0
end
def take_turn
roll_points = 0
turn_points = 0
dice_remaining = Game::DICE_TO_USE
UI.display_player_name(@name, @in_the_game)
loop do
# Roll dice
dice = DiceSet.new(dice_remaining)
dice.roll
roll_points = dice.points
turn_points += roll_points
# Check results
if dice.no_scoring_dice?
UI.rolled_no_scoring_dice
break
elsif dice.all_scoring_dice?
dice_remaining = Game::DICE_TO_USE
answer = UI.rolled_all_scoring_dice(roll_points, turn_points, dice_remaining)
else
dice_remaining = dice.non_scoring_dice
answer = UI.rolled_dice(roll_points, turn_points, dice_remaining)
end
if answer.downcase == "n"
if !@in_the_game
if turn_points < Game::IN_GAME_POINTS
turn_points = 0
else
@in_the_game = true;
end
end
@total_points += turn_points
if @total_points >= Game::END_GAME_POINTS
@finished = true
end
UI.earned_points(turn_points, @total_points)
break
end
end
end
end
class Game
DICE_TO_USE = 5
IN_GAME_POINTS = 300
END_GAME_POINTS = 3000
def initialize
@players = []
@round = 1
@last_round = false
start_game
end
def start_game
UI.prompt_for_player_names.each do |name|
@players << Player.new(name)
end
# Play normal rounds until a player accumulates END_GAME_POINTS
# That player is now the one to beat.
until @last_round
UI.display_round_number(@round)
@players.each do |player|
player.take_turn
if player.finished
@last_round = true
break
end
end
@round += 1
end
# Play last round. Give every other player one turn to try and
# beat the high score
if @last_round
UI.display_last_round()
@players.each do |player|
unless player.finished
player.take_turn
end
end
end
UI.display_final_scores(@players)
end
end
# Play Game
Game.new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment