Diff
Not logged in

Differences From Artifact [1b458d7cd25e92dc]:

To Artifact [2ca374354297c908]:


1 1 import util; 2 2 import game; 3 -import core.stdc.signal; 3 +import driver; 4 4 import std.c.stdlib; 5 +import core.stdc.signal; 5 6 6 -abstract class Output 7 +class NilOutput : GameObserver 7 8 { 8 - void command(char c); 9 - void flush(); 9 + this(const(Game) g) {} 10 + override bool on_game_changed(char c, const(Game) g, bool finished) {return false;} 10 11 } 11 12 12 -class NilOutput : Output 13 +class StdOutput : GameObserver 13 14 { 14 - override void command(char c) {} 15 - override void flush() {} 16 -} 17 - 18 -class StdOutput : Output 19 -{ 20 - override void command(char c) 15 + this(const(Game) g) {} 16 + override bool on_game_changed(char c, const(Game) g, bool finished) 21 17 { 22 - write(c); 18 + stdout.write(c); 23 19 stdout.flush(); 20 + return false; 24 21 } 25 - override void flush() {} 26 22 } 27 23 28 -// TODO: clean it up. 29 -__gshared Output g_output; 30 - 31 -class GuardedOutput : StdOutput 24 +class GuardedOutput : GameObserver 32 25 { 33 - // Handle SIGINT: force abort and exit. 34 - static this() 26 + this(const(Game) g) 27 + { 28 + setup_sigint_handling(); 29 + ideal_log ~= g.score_if_abort_now; 30 + } 31 + 32 + override bool on_game_changed(char c, const(Game) g, bool finished) 35 33 { 36 - signal(SIGINT, &sigint); 34 + log ~= c; 35 + score_log ~= g.score; 36 + ideal_log ~= g.score_if_abort_now; 37 + if(finished) 38 + flush(); 39 + return false; 37 40 } 38 41 39 - extern(C) static void sigint(int) 40 - { 41 - if(g_output !is null) 42 - g_output.flush(); 43 - else { 44 - write("A"); 45 - stdout.flush(); 46 - } 47 - exit(0); 48 - } 49 - 50 - Game g; 51 - this(Game ini) { this.g = ini.clone(); ideal_log ~= g.score_if_abort_now; g_output = this; } 52 - 42 +private: 53 43 string log; 54 44 long[] score_log; 55 45 long[] ideal_log; 56 46 57 - override void command(char c) 58 - { 59 - g.command(c); 60 - log ~= c; 61 - score_log ~= g.score; 62 - ideal_log ~= g.score_if_abort_now; 63 - } 64 - override void flush() 47 + void flush() 65 48 { 66 49 Tuple!(long, int, int) cand; 67 50 cand[0] = long.min; 68 - foreach(int i, long s; score_log) 69 - if(cand[0] < s) 70 - cand = tuple(s,i,0); 71 - foreach(int i, long s; ideal_log) 72 - if(cand[0] < s) 73 - cand = tuple(s,i,1); 74 - if(cand[2]==0) 75 - writeln(log[0..cand[1]+1]); 76 - else 77 - writeln(log[0..cand[1]]~"A"); 78 - stdout.flush(); 51 + 52 + for(int i=0; i<score_log.length; ++i) 53 + if(cand[0] < score_log[i]) 54 + cand = tuple(score_log[i],i,0); 55 + for(int i=0; i<ideal_log.length; ++i) 56 + if(cand[0] < ideal_log[i]) 57 + cand = tuple(ideal_log[i],i,1); 58 + 59 + if(cand[2]==0) { 60 + string str = log[0..cand[1]+1]; 61 + std.c.stdio.printf("%.*s\n", str.length, str.ptr); 62 + } else { 63 + string str = log[0..cand[1]]; 64 + std.c.stdio.printf("%.*sA\n", str.length, str.ptr); 65 + } 66 + std.c.stdio.fflush(std.c.stdio.stdout); 67 + } 68 + 69 +private: 70 + static __gshared GuardedOutput g_output; 71 + 72 + void setup_sigint_handling() 73 + { 74 + assert(g_output is null); 75 + g_output = this; 76 + extern(C) static void catch_sigint(int) { g_output.flush(); application_exit(); } 77 + core.stdc.signal.signal(SIGINT, &catch_sigint); 79 78 } 80 79 }