Created
April 19, 2009 17:14
-
-
Save elight/98135 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DieCode < String | |
cattr_accessor :wild_die | |
attr_reader :dice, :pips | |
REGEXP = /(^\d+)D\+?([12])?$/ | |
class << self | |
def valid?(code) | |
code =~ REGEXP | |
end | |
def from_int(code) | |
return unless code.is_a?(Fixnum) | |
str = "#{code / 3}D" | |
pip = code % 3 | |
str += "+#{pip}" if pip != 0 | |
str | |
end | |
end | |
def initialize(code = "") | |
val = code | |
unless DieCode.valid? code | |
val = DieCode.from_int code | |
raise Exception.new("Invalid die code '#{code}'") unless val | |
end | |
val =~ REGEXP | |
@dice = $1.to_i | |
@pips = $2.to_i | |
super val | |
end | |
def to_i | |
(3 * dice) + pips | |
end | |
def +(other_code) | |
DieCode.new(to_i + other_code.to_i) | |
end | |
def -(other_code) | |
DieCode.new((to_i - other_code.to_i).abs) | |
end | |
def roll | |
first_roll = true | |
wild_result = nil | |
the_roll = (1..self.dice).inject(0) { |total, v| | |
if first_roll | |
first_roll = false | |
roll, wild_result = handle_wild_die | |
total += roll | |
else | |
total += die_roll | |
end | |
total | |
} + self.pips | |
@@wild_die ? [the_roll, wild_result] : the_roll | |
end | |
def die_roll | |
rand(6) + 1 | |
end | |
private | |
def handle_wild_die | |
return die_roll unless @@wild_die | |
wild_result = nil | |
total = 0 | |
first_roll = true | |
begin | |
roll = die_roll | |
total += roll | |
if first_roll && roll == 1 | |
wild_result = :FAIL | |
elsif roll == 6 | |
wild_result ||= :SUCCESS | |
end | |
first_roll = false | |
end while roll == 6 | |
[total, wild_result] | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') | |
describe DieCode, "that is invalid" do | |
it "should raise when created" do | |
lambda { DieCode.new "" }.should raise_error | |
end | |
end | |
describe DieCode, "provided as an int" do | |
it "should be parseable into a DieCode" do | |
lambda { DieCode.new 10 }.should_not raise_error | |
end | |
end | |
describe DieCode, "that is valid" do | |
before do | |
@valid_code1 = DieCode.new "1D" | |
end | |
it "should start with an integer value representing the number of dice" do | |
@valid_code1.should match(/^\d+/) | |
end | |
it "should have a 'D' following the number of dice" do | |
@valid_code1.should match(/^\d+D/) | |
end | |
it "should end with an optional '+1' or '+2'" do | |
@valid_code1.should match(/(\+[12])?$/) | |
end | |
it "can be resolved to an integer by multiplying the number before the D by 3 and adding the number after the '+'" do | |
@valid_code1.to_i.should == 3 | |
end | |
it "can be rolled" do | |
@valid_code1.should respond_to(:roll) | |
end | |
describe "when the wild die is disabled" do | |
before do | |
DieCode.wild_die = false | |
end | |
it "should return the die roll and the wild die result" do | |
@valid_code1.roll.should be_a(Fixnum) | |
end | |
end | |
describe "when the wild die is enabled" do | |
before do | |
DieCode.wild_die = true | |
end | |
it "should return the die roll and the wild die result" do | |
@valid_code1.roll.should have(2).values | |
end | |
it "should indicate a wild die failure if the wild die turns up a 1 on its first roll" do | |
@valid_code1.should_receive(:die_roll).at_least(:once).and_return(1) | |
total, wild_die_result = @valid_code1.roll | |
wild_die_result.should == :FAIL | |
end | |
it "should indicate a wild die success if the wild die rolls one or more 6s" do | |
@valid_code1.stub!(:die_roll).and_return(6,5) | |
total, wild_die_result = @valid_code1.roll | |
wild_die_result.should == :SUCCESS | |
end | |
it "should roll an additional die on the occurrence of a 6 on the wild die" do | |
@valid_code1.stub!(:die_roll).and_return(6,5) | |
total, wild_die_result = @valid_code1.roll | |
total.should == 11 | |
end | |
end | |
end | |
describe "Two valid die codes" do | |
before do | |
@code1 = DieCode.new "3D+1" | |
@code2 = DieCode.new 13 | |
end | |
it "should be additive" do | |
(@code1 + @code2).should == DieCode.new("7D+2") | |
end | |
it "should be subtractible" do | |
(@code2 - @code1).should == DieCode.new("1D") | |
end | |
it "should be comparable" do | |
@code2.should == DieCode.new("4D+1") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment