#!/usr/bin/ruby require "io/console" W = 6 H = 12 D = 0.03 T = W * 2 + 4 X = [0, 1, 0, -1] Y = [1, 0, -1, 0] class B attr_accessor :x, :y, :o, :c end def p(x, y, z) i = z.gsub(/\e\[[^m]+m/, "").length print y > 0 ? "\e[#{x}C\e[#{y}B#{z}\e[0m\e[#{x + i}D\e[#{y}A" : "\e[#{x}C#{z}\e[0m\e[#{x + i}D" end def m(t, c) ["\e[97;#{101 + c}m", "\e[#{91 + c};40m", "\e[#{31 + c};107m"][t] + "<>(){}[]"[c * 2, 2] end $h = ARGV.length > 1 ? ARGV[1, ARGV.length - 1] * "" : STDIN.isatty ? nil : STDIN.read def q(g, o, z) h = [] (H - 1).downto(0) {|y| h.push([]) W.times{|x| t = g[x][y] h[-1].push(t ? m(z[[x, y]] ? 2 : 0, t) : nil) } } if o t = [[o.x, o.y, o.c[0]], [o.x + X[o.o], o.y + Y[o.o], o.c[1]]] t[0], t[1] = t[1], t[0] if t[0][1] > t[1][1] 2.times{|i| x = t[i][0] y = t[i][1] next if x < 0 or x >= W h[H - y - 1][x] = m(0, t[i][2]) if y >= 0 and y < H y.times{|d| if d >= 0 and d < H and not h[H - d - 1][x] h[H - d - 1][x] = m(1, t[i][2]) break end } } end t = h.map{|r| r.map{|c| c or "\e[40m "} * "" } * ("\e[1B\e[#{W * 2}D") t += "\e[#{H - 1}A\e[#{W * 2}D" end def w(o, g) return 1 if o.x < 0 or o.x >= g.length or g[o.x][o.y] x1 = o.x + X[o.o] y1 = o.y + Y[o.o] (x1 < 0 or x1 >= g.length or g[x1][y1]) ? 1 : nil end S = s = (ARGV.length > 0 ? ARGV[0] : Time.now).to_i STDIN.echo=false print "\e[?25l#{(("#" * (W * 2 + 20)) + "\n") * (H + 2)}\e[#{H + 1}A\e[2C" p(T, 0, " Next: ") p(T, 4, " Block: ") p(T, 7, " Score: ") g = [] W.times{ g.push([]) } l = [] 6.times{ 4.times{|i| 4.times{|j| l.push([i, j]) } } } 4.times{|i| l.push([i, i]) } (l.length - 1).downto 1 do |i| s ^= s << 13 s &= 0x7fffffff s ^= s >> 17 s ^= s << 5 s &= 0x7fffffff j = s % (i + 1) l[i], l[j] = l[j], l[i] end f = [] u = 0 e = 0 h = "" l.length.times{|a| 2.times{|i| b = l[a + i + 1] t = b ? ["\e[40m #{m(0, b[0])}\e[40m ", "\e[40m #{m(0, b[1])}\e[40m "] : ["####"] * 2 p(T + i * 4, 1, t[1]) p(T + i * 4, 2, t[0]) } p(T, 5, "\e[97;40m #{a + 1} / #{l.length} ") p(T, 8, "\e[97;40m #{e} ") o = B.new o.x = (W - 1) / 2 o.y = H - 1 o.o = 0 o.c = l[a] break if w(o, g) while 1 print q(g, o, {}) c = nil while not c if $h break if $h.length < 1 n = $h[0] $h = $h[1, $h.length - 1] else n = STDIN.getch end c = { 'A' => 'k', 'k' => 'k', 'B' => 'j', 'j' => 'j', 'C' => 'l', 'l' => 'l', 'D' => 'h', 'h' => 'h', 'x' => 'q', 'q' => 'q' }[n] end case c when 'k' n = o.clone n.o = (n.o + 1) % 4 if w(n, g) if X[n.o] == 0 n.y += 1 else n.x -= X[n.o] n = nil if w(n, g) end end if n h += c o = n end when 'j' g[o.x][o.y] = o.c[0] g[o.x + X[o.o]][o.y + Y[o.o]] = o.c[1] h += c break when 'h', 'l' n = o.clone n.x += c == 'h' ? -1 : 1 if not w(n, g) if n.y != H - 1 d = n.clone d.y = H - 1 n = d if not w(d, g) end h += c o = n end else c = nil break end end break if not c e += 1 n = 0 while 1 print q(g, nil, {}) while 1 r = [] v = false g.length.times{|x| y = g[x].index(nil) if y r.push(g[x][0, y] + g[x][y + 1, g[x].length - 1]) v = true else r.push(g[x]) end } break if not v g = r sleep D print q(g, nil, {}) end r = [] v = {} g.length.times{|i| g[i].length.times{|j| c = g[i][j] t = [] z = [[i, j]] while z.length > 0 x, y = z.pop next if x < 0 or y < 0 or x >= g.length or y >= g[x].length or v[[x, y]] or g[x][y] != c v[[x, y]] = 1 t.push([x, y]) z.push([x + 1, y]) z.push([x - 1, y]) z.push([x, y + 1]) z.push([x, y - 1]) end r.push(t) if t.length > 3 } } break if r.length < 1 n += 1 p(T, H - 1, "\e[97;40m #{n} chain ") v = {} r.each{|t| t.each{|x| v[[x[0], x[1]]] = 1 } } x = q(g, nil, {}) y = q(g, nil, v) 10.times{ print x sleep D print y sleep D } x = 0 y = 0 z = {} r.each{|t| z[g[t[0][0]][t[0][1]]] = 1 x += t.length y += t.length > 4 ? t.length > 10 ? 10 : t.length - 3 : 0 } z = (n > 1 ? 2 * 2 ** n : 0) + [nil, 0, 3, 6, 12][z.keys.length] + y e += 10 * x * [[1, z].max, 999].min p(T, 8, "\e[97;40m #{e} ") v.each_key{|t| g[t[0]][t[1]] = nil } u += x end f.push(n) p(T, H - 1, "\e[0m" + "#" * 12) } if f.length < l.length x = "" y = "\e[91mGAME OVER" else x = "MINIMALIST" [[(l.length * 2 - W * H) * 10 + l.length, "NOVICE"], [9999, "HOBBYIST"], [19999, "ENTHUSIAST"], [49999, "PROFESSIONAL"], [99999, "MASTER"], [499999, "GRANDMASTER"]].each{|s| x = s[1] if e > s[0] } x = "rank = \e[4;1m#{x}\e[0m\n" y = "\e[92mYOU WIN :)" end STDIN.echo=true print "\e[0m\n" * (H + 2), "\e[?25h#{y}\e[0m\n\nscore = #{e}\nblocks = #{f.length} / #{l.length}\ntiles cleared = #{u}\n", x if f.length > 0 and f.max > 0 print "\nChain history:\n" y = f.max + 2 y += 1 if y % 2 == 1 until y == 0 y -= 2 x = 0 until x >= f.length v = f[x, 2].max print "8o_ "[v > y + 1 ? 0 : v == y + 1 ? 1 : y == 0 ? 2 : 3] x += 2 end print "\n" end v = f.index(f.max) print " " * (v / 2), "^\n", " " * (v / 2), "block #{v + 1} = #{f.max} chain\n" end print "\nReplay:\nruby #{$0} #{S} #{h}\n"