1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#!/usr/bin/env ruby
module Term
CSI = "["
def sgr(*code)
"#{CSI}#{code.join(?;)}m"
end
module_function :sgr
RESET = sgr(0)
BOLD = sgr(1, 97)
RED = sgr(31)
GREEN = sgr(32)
YELLOW = sgr(33)
BLUE = sgr(34)
PURPLE = sgr(35)
end
class Roll
def initialize(res, cuts)
@res = res
@cuts = cuts
end
def twist?
@res.tally.values.max > 1
end
def read_cuts
Roll.read(@cuts)
end
def read
Roll.read(@res)
end
def interpret
outcome = case @res.max
when 1,2,3
"#{Term::RED}disaster#{Term::RESET}"
when 4,5
"#{Term::YELLOW}conflict#{Term::RESET}"
when 6
"#{Term::GREEN}triumph#{Term::RESET}"
end
"#{outcome}#{" with a #{Term::BLUE}twist#{Term::RESET}" if twist?}"
end
def cut_twist
(1...@res.length).map do |i|
res = Roll.new(@res[0...-i], @res[-i..-1] + @cuts)
next if res.twist?
return [i, res]
end
end
def self.roll(number, cuts)
res = self.roll_dice(number)
new(*self.split(res, cuts))
end
def self.read(ary)
numword = {
1 => "a",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
6 => "six"
}
readres = ""
ary.tally.each do |val, num|
readres += "#{numword[num]} #{Term::BOLD}#{val}#{Term::RESET}#{?s if num > 1}, "
end
readres = readres[0...-2]
readres.sub!(/.*\K, /, " and ")
readres
end
def self.roll_dice(num)
Array.new(num) { rand(6) + 1 }.sort
end
def self.split(res, cutn)
cuts = cutn > 0 ? res[-cutn..-1] : []
res = res[0...-cutn] if cutn > 0
[res, cuts]
end
end
def prompt(msg)
print Term::PURPLE
print msg
print ?? unless msg[-1] == ??
print ?\s
print Term::RESET
gets.to_i
end
trap("INT") do
puts
exit
end
loop do
number = prompt "How many dice"
break if number == 0
cuts = prompt "How many cuts"
roll = Roll.roll(number, cuts)
if cuts > 0
print " After cutting #{roll.read_cuts}, y"
else
print " Y"
end
print "ou rolled #{roll.read}. "
puts "That's a #{roll.interpret}."
if roll.twist?
i, cutroll = roll.cut_twist
puts " If you chose to cut #{i}#{" more" if cuts > 0}, it would just be a #{cutroll.interpret}."
end
end
|