@@ -5,31 +5,76 @@ abstract class Output { void command(char c); + void flush(); } class NilOutput : Output { override void command(char c) {} + override void flush() {} } class StdOutput : Output { + override void command(char c) + { + write(c); + stdout.flush(); + } + override void flush() {} +} + +// TODO: clean it up. +__gshared Output g_output; + +class GuardedOutput : StdOutput +{ // Handle SIGINT: force abort and exit. static this() { signal(SIGINT, &sigint); } - extern(C) static void sigint(int) { - write("A"); - stdout.flush(); + + extern(C) static void sigint(int) + { + if(g_output !is null) + g_output.flush(); + else { + write("A"); + stdout.flush(); + } exit(0); } + Game g; + this(Game ini) { this.g = ini.clone(); ideal_log ~= g.score_if_abort_now; g_output = this; } + + string log; + long[] score_log; + long[] ideal_log; + override void command(char c) { - // TODO: optimize redundancy. - write(c); + g.command(c); + log ~= c; + score_log ~= g.score; + ideal_log ~= g.score_if_abort_now; + } + override void flush() + { + Tuple!(long, int, int) cand; + cand[0] = long.min; + foreach(int i, long s; score_log) + if(cand[0] < s) + cand = tuple(s,i,0); + foreach(int i, long s; ideal_log) + if(cand[0] < s) + cand = tuple(s,i,1); + if(cand[2]==0) + writeln(log[0..cand[1]+1]); + else + writeln(log[0..cand[1]]~"A"); stdout.flush(); } }