#!/usr/bin/ruby require 'io/console' YO = 2.0 T = 1 / 6.0 S = 0.7 U = 0.23 Y = 2.5 A = 1.4 M = 0.5 I = 3.7 K = 0.35 O = 0.7 def D(x, y, p, q) Math.hypot(x - p, y - q) end def E(x, y, w, i, j) s = 0 n = 1e99 m = Math::PI 16.times{ t = s (-1..1).each{|d| a = s + d * m p = i * Math.cos(a) q = j * Math.sin(a) d = D(x, y - w, p, q) if n > d n = d t = a end } s = t m /= 2.0 } n end def L(x, y, i, j, p, q) p -= i q -= j n = 1e99 s = 0 t = 1 16.times{ d = D(x, y, i + p * s, j + q * s) b = D(x, y, i + p * t, j + q * t) m = (s + t) / 2.0 d < b ? (t = m) : (s = m) n = (d + b) / 2.0 } n end def F(o) o.map{|x, y| [y, x]} end def G(o) o.map{|x, y| [-y, -x]} end def V(o, p, q) o.map{|x, y| [x + p, y + q]} end def N(t, w, h, o) (t[w] ||= {})[h] ||= o end def Z(t, m, p, q) w = p while w <= m * 2 N(t, w + p, q, t[w][q] + V(t[p][q], w, 0)) w += p end end def W(m, n) t = {} (1 .. m * 2).each{|w| N(t, w, 1, (0 .. w - 1).to_a.map{|x| [x, 0]}) } s = 1 while s <= n (1 .. s).each{|h| N(t, s * 2, s + h, F(t[s][s]) + V(t[s * 2][h], 0, s) + V(G(t[s][s]), s * 2 - 1, s - 1)) Z(t, m, s * 2, s + h) } s *= 2 end s = n while s > 1 p = n - s while p > 0 q = s + p while q > 0 w = s + q h = s + p if !t[w][h] && t[s][s] && t[s + q][p] && t[s][q] N(t, w, h, F(t[s][s]) + V(t[w][p], 0, s) + V(G(t[s][q]), w - 1, s - 1)) Z(t, m, w, h) end q -= 1 end p -= 1 end s -= 1 end t end def R(t, m, n) if m * n == 0 return [] end w = m while w > 0 if t[w] && t[w][n] return t[w][n] + V(F(R(t, n, m - w)), w, 0) end w -= 1 end t[m][1] + R(t, n - 1, m).map{|x, y| [m - 1 - y, 1 + x]} end def C(m, n) m < n ? F(C(n, m)) : R(W(m, n), m, n) end J = Time.now h, w = IO.console.winsize o = C(w / 2, h / 2).map{|x, y| [2 * x, 2 * y]} w = o.map{|x, y| x}.max h = o.map{|x, y| y}.max if w && w > 1 && h > 1 m = [w, h * YO].min * U l = m * T n = m - l * 2 if (m * I + l) * 2 > w s = w / ((m * I + l) * 2.0) m *= s n *= s l *= s end a = [] (h + 2).times{ a += [Array.new(w + 2)] } print "\n" * h P = ["\e[1D", "", "\e[1C"] Q = ["\e[1B", "", "\e[1A"] d, b = o[0] c = 0 r = nil B = (30.0 - (Time.now - J)) / (o.length * 2.0) o.each{|x, y| while !r || d != x || b != y s = d < x ? 1 : d > x ? -1 : 0 t = b < y ? 1 : b > y ? -1 : 0 d += s b += t print P[s + 1], Q[t + 1] (-1 .. 1).each{|v| q = b + v t = (q - h / 2.0) * YO (-1 .. 1).each{|u| p = d + u if p >= 0 && p <= w && q >= 0 && q <= h && !a[q][p] if u == 0 && v == 0 r = ["M", "W"][(p + q) % 2] a[q][p] = r else r = " " end s = p - w / 2.0 e = m * S f = m * Y i = -m * A j = m * I k = m * M print Q[1 + v], P[1 + u], [L(s, t, -j, i, j, i), L(s, t, -j * O, i - k, -j * O, i + k), L(s, t, -j * K, i - k, -j * K, i + k), L(s, t, 0, i - k, 0, i + k), L(s, t, j * K, i - k, j * K, i + k), L(s, t, j * O, i - k, j * O, i + k), E(s, t, e, f, m), E(s, t, e, n, n)].min < l ? "\e[97;43m" : "\e[90;40m", r, "\e[1D\e[0m", P[1 - u], Q[1 - v] end } } STDOUT.flush c += 1 sleep [B * c - (Time.now - J), 0].max end } print "\n" * (o[-1][1] + 1) end