summaryrefslogtreecommitdiff
path: root/dartbot.rb
diff options
context:
space:
mode:
Diffstat (limited to 'dartbot.rb')
-rwxr-xr-xdartbot.rb196
1 files changed, 152 insertions, 44 deletions
diff --git a/dartbot.rb b/dartbot.rb
index 5837db8..5a61471 100755
--- a/dartbot.rb
+++ b/dartbot.rb
@@ -1,5 +1,7 @@
#!/usr/bin/env ruby
+require 'curses'
+
HORIZONTAL_STDEV = 24
VERTICAL_STDEV = 24
@@ -195,7 +197,6 @@ def play_visit(rem)
v_rem = rem
darts = []
- bust = false
3.times do
t_angle, t_radius = next_dart(v_rem, 3 - darts.length)
@@ -210,14 +211,13 @@ def play_visit(rem)
(v_rem == 0 && segment != 'BULL' && segment !~ /^D/))
v_rem = rem
- bust = true
break
end
break if v_rem.zero?
end
- [v_rem, rem - v_rem, darts, bust]
+ [v_rem, rem - v_rem, darts]
end
def colour_points(points)
@@ -240,33 +240,79 @@ def colour_points(points)
end
end
+def curses_output_points(win, points)
+ win.addstr(' ')
+
+ unless points
+ win.addstr(' ')
+ return
+ end
+
+ str = "%3s" % points
+
+ [180, 140, 100, 60, 40, 20, 1, 0].each do |pmin|
+ if points >= pmin
+ a = COLOUR_PAIRS["p#{pmin}".intern]
+
+ win.attron(a) do
+ win.addstr(str)
+ end
+ break
+ end
+ end
+end
+
+COLOURS = {
+ p180: [[82, 0], [Curses::A_BOLD]],
+ p140: [[82, 0]],
+ p100: [[154, 0]],
+ p60: [[226, 0]],
+ p40: [[214, 0]],
+ p20: [[202, 0]],
+ p1: [[196, 0]],
+ p0: [[196, 0], [Curses::A_BOLD]],
+ bw: [[0, 7]],
+ visit: [[235, 0]]
+}
+
+COLOUR_PAIRS = {}
+
+def curses_init_colours
+ COLOURS.each.with_index do |(k, v), i|
+ Curses.init_pair(i + 1, *v[0])
+ col = Curses.color_pair(i + 1)
+ if (mods = v[1])
+ mods.each { |x| col |= x }
+ end
+ COLOUR_PAIRS[k] = col
+ end
+end
+
def visit_darts(darts)
str = darts.map { |x| '%3s' % x }.join(' ')
str += ' ' * (3 - darts.length)
str
end
-def output_visit(n, rem, points = nil, darts = nil, bust = false)
+def output_visit(n, rem, points = nil, darts = nil)
str = '(%2s) %3s' % [n, rem]
str << ' %s' % colour_points(points) if points
str << " \e[38;5;235m%s\e[0m" % visit_darts(darts) if darts
- str << " \e[38;5;88mBUST\e[0m" if bust
- str << " \e[38;5;76mWIN\e[0m" if rem.zero?
puts str
end
-def output_int_visit(n, p_rem, rem, p_points = nil, points = nil, darts = nil, bust = false)
- str = '(%2s) ' % n
- str << (p_points ? colour_points(p_points) : ' ')
- str << ' %3s' % p_rem
- str << ' %3s' % rem
- str << ' %s' % colour_points(points) if points
- str << " \e[38;5;235m%s\e[0m" % visit_darts(darts) if darts
- str << " \e[38;5;88mBUST\e[0m" if bust
- str << " \e[38;5;76mWIN\e[0m" if rem.zero?
-
- puts str
+def curses_output_visit(win, n, p_rem, rem, p_points = nil, points = nil, darts = nil)
+ win.addstr('(%2s)' % n)
+ curses_output_points(win, p_points)
+ win.addstr(' %3s' % p_rem)
+ win.addstr(' %3s' % rem)
+ curses_output_points(win, points)
+ if darts
+ win.attron(COLOUR_PAIRS[:visit]) do
+ win.addstr(' %s' % visit_darts(darts))
+ end
+ end
end
def play_match(start_points = 501, output = true)
@@ -276,10 +322,10 @@ def play_match(start_points = 501, output = true)
output_visit(m_darts.length, rem) if output
while rem != 0
- rem, points, darts, bust = play_visit(rem)
+ rem, points, darts = play_visit(rem)
m_darts << darts
- output_visit(m_darts.length, rem, points, darts, bust) if output
+ output_visit(m_darts.length, rem, points, darts) if output
if rem.zero? && output
puts
@@ -292,52 +338,114 @@ def play_match(start_points = 501, output = true)
m_darts
end
-def play_int_match(start_points = 501, output = true)
+def test_average
+ avgs = (0..10000).map do |x|
+ m_darts = play_match(501, false)
+ req = (((m_darts.length - 1) * 3) + m_darts[-1].length)
+ (501.to_f / req * 3)
+ end
+
+ avg = avgs.sum / avgs.length
+ stdev = Math.sqrt(avgs.sum { |x| (x - avg) ** 2 } / (avgs.length - 1))
+
+ puts
+ puts avg
+ puts stdev
+end
+
+def play_curses_match(start_points = 501)
+ Curses.init_screen
+ Curses.start_color
+ curses_init_colours
+ Curses.curs_set(0)
+ Curses.noecho
+ win = Curses::Window.new(Curses.lines, Curses.cols, 0, 0)
+ m_lines = []
+ draw(win, m_lines)
+
p_rem = start_points
rem = start_points
m_darts = []
- output_int_visit(m_darts.length, p_rem, rem) if output
+ m_lines << [m_darts.length, p_rem, rem]
+ p_buff = ''
+
+ draw(win, m_lines)
+ status = nil
loop do
- rem, points, darts, bust = play_visit(rem)
+ p_buff = ''
+ loop do
+ c = win.getch
+ if c == Curses::Key::RESIZE
+ win.resize(Curses.lines, Curses.cols)
+ draw(win, m_lines, p_buff)
+ elsif c == 10
+ break
+ elsif c == 127
+ p_buff = p_buff[0..-2]
+ draw(win, m_lines, p_buff)
+ elsif c.chr >= '0' && c.chr <= '9'
+ p_buff << c
+ draw(win, m_lines, p_buff)
+ end
+ end
+
+ p_points = p_buff.to_i
+ p_rem -= p_points
+ m_lines << [m_darts.length + 1, p_rem, rem, p_points, nil, nil]
+ if p_rem == 0
+ status = 'You win! :)'
+ break
+ end
+
+ rem, points, darts = play_visit(rem)
m_darts << darts
+ m_lines[m_lines.length-1] = [m_darts.length, p_rem, rem, p_points, points, darts]
+ draw(win, m_lines)
- output_int_visit(m_darts.length, p_rem, rem, nil, points, darts, bust) if output
if rem == 0
- puts
- puts 'Dartbot wins. :('
+ status = 'Dartbot wins. :('
break
end
+ end
- print "Enter points: "
- p_points = gets.to_i
- p_rem -= p_points
- output_int_visit(m_darts.length, p_rem, rem, p_points, points, darts, bust) if output
- puts
- if p_rem == 0
- puts 'You win! :)'
- break
+ draw(win, m_lines, p_buff, status)
+ loop do
+ c = win.getch
+ if c == Curses::Key::RESIZE
+ win.resize(Curses.lines, Curses.cols)
+ draw(win, m_lines, p_buff, status)
end
end
m_darts
end
-def test_average
- avgs = (0..10000).map do |x|
- m_darts = play_match(501, false)
- req = (((m_darts.length - 1) * 3) + m_darts[-1].length)
- (501.to_f / req * 3)
+def draw(win, m_lines, buf = '', status = nil)
+ win.erase
+ win.box
+ win.setpos(0,2)
+ win.addstr("dartbot")
+
+ max_ml = Curses.lines - 5
+
+ m_lines.last(max_ml).each.with_index do |line, i|
+ win.setpos(2+i, 2)
+ curses_output_visit(win, *line)
end
- avg = avgs.sum / avgs.length
- stdev = Math.sqrt(avgs.sum { |x| (x - avg) ** 2 } / (avgs.length - 1))
+ win.setpos(Curses.lines - 2, 1)
+ win.attron(COLOUR_PAIRS[:bw]) do
+ if status
+ win.addstr(status.ljust(Curses.cols-2))
+ else
+ win.addstr(('Enter points: ' + buf).ljust(Curses.cols-2))
+ end
+ end
- puts
- puts avg
- puts stdev
+ win.refresh
end
-play_int_match
+play_curses_match
#test_average