6293256fec 2012-07-14 kinaba: import util; 6293256fec 2012-07-14 kinaba: import game; 6293256fec 2012-07-14 kinaba: c88611bab8 2012-07-15 kinaba: bool rocky(char c){ return c=='*'||c=='@'; } c88611bab8 2012-07-15 kinaba: 913d120d42 2012-07-15 kinaba: interface Solver 913d120d42 2012-07-15 kinaba: { 913d120d42 2012-07-15 kinaba: // this(in Game g); 913d120d42 2012-07-15 kinaba: char single_step(); 913d120d42 2012-07-15 kinaba: void force(char c); 913d120d42 2012-07-15 kinaba: } 913d120d42 2012-07-15 kinaba: 913d120d42 2012-07-15 kinaba: class Solver_0 : Solver 9d4aca73fa 2012-07-14 kinaba: { 879099f815 2012-07-15 kinaba: this(in Game g) {} 9d4aca73fa 2012-07-14 kinaba: char single_step() { return 'W'; } c2c105fda0 2012-07-15 kinaba: void force(char c) {} 9d4aca73fa 2012-07-14 kinaba: } a03584f1c6 2012-07-15 kinaba: 913d120d42 2012-07-15 kinaba: class Solver_1 : Solver 6293256fec 2012-07-14 kinaba: { c743b817b7 2012-07-14 kinaba: int wait_count = 0; ea96f24715 2012-07-14 kinaba: int choke_count = 0; 9d4aca73fa 2012-07-14 kinaba: 9d4aca73fa 2012-07-14 kinaba: Game g; 879099f815 2012-07-15 kinaba: this(in Game g) 9d4aca73fa 2012-07-14 kinaba: { 9d4aca73fa 2012-07-14 kinaba: this.g = g.clone(); e02668367d 2012-07-15 kinaba: forbidden_cell = new bool[][](g.map.H+2, g.map.W+2); 9d4aca73fa 2012-07-14 kinaba: } 9d4aca73fa 2012-07-14 kinaba: 9d4aca73fa 2012-07-14 kinaba: char single_step() 9d4aca73fa 2012-07-14 kinaba: { c4d04122d8 2012-07-14 kinaba: Tuple!(string,int) de = death_move(g); c4d04122d8 2012-07-14 kinaba: char c = act(g, de[0], de[1]); 879099f815 2012-07-15 kinaba: force(c); 9d4aca73fa 2012-07-14 kinaba: return c; c2c105fda0 2012-07-15 kinaba: } c2c105fda0 2012-07-15 kinaba: c2c105fda0 2012-07-15 kinaba: void force(char c) c2c105fda0 2012-07-15 kinaba: { 879099f815 2012-07-15 kinaba: if(c != 'A') 879099f815 2012-07-15 kinaba: g.command(c); c4d04122d8 2012-07-14 kinaba: } c4d04122d8 2012-07-14 kinaba: c4d04122d8 2012-07-14 kinaba: Tuple!(string,int) death_move(const(Game) g) b4aceba693 2012-07-14 kinaba: { b4aceba693 2012-07-14 kinaba: string death; c4d04122d8 2012-07-14 kinaba: int choice = 0; b4aceba693 2012-07-14 kinaba: foreach(char c; "UDLRW") { b4aceba693 2012-07-14 kinaba: Game gg = g.clone(); b4aceba693 2012-07-14 kinaba: gg.command(c); b4aceba693 2012-07-14 kinaba: if( !gg.cleared && gg.dead ) b4aceba693 2012-07-14 kinaba: death ~= c; e02668367d 2012-07-15 kinaba: else if( gg.map.robot != g.map.robot ) c4d04122d8 2012-07-14 kinaba: choice++; 2f2eff2f03 2012-07-14 kinaba: else if( c != 'W' ) // meaningless move 2f2eff2f03 2012-07-14 kinaba: death ~= c; b4aceba693 2012-07-14 kinaba: } c4d04122d8 2012-07-14 kinaba: return tuple(death, choice); b4aceba693 2012-07-14 kinaba: } b4aceba693 2012-07-14 kinaba: c4d04122d8 2012-07-14 kinaba: Tuple!(Pos, int)[] log; c4d04122d8 2012-07-14 kinaba: bool[][] forbidden_cell; c4d04122d8 2012-07-14 kinaba: c4d04122d8 2012-07-14 kinaba: char act(const(Game) g, string death, int breath) 9d4aca73fa 2012-07-14 kinaba: { e02668367d 2012-07-15 kinaba: const Pos ro = g.map.robot; e02668367d 2012-07-15 kinaba: const Pos li = g.map.lift; e02668367d 2012-07-15 kinaba: Pos[] la = g.map.lambdas(); 8acc8e6c78 2012-07-15 kinaba: sort!((Pos a,Pos b){ 8acc8e6c78 2012-07-15 kinaba: int ad=abs(a.y-li.y)+abs(a.x-li.x); 8acc8e6c78 2012-07-15 kinaba: int bd=abs(b.y-li.y)+abs(b.x-li.x); 8acc8e6c78 2012-07-15 kinaba: return ad>bd;; 8acc8e6c78 2012-07-15 kinaba: })(la); e02668367d 2012-07-15 kinaba: Pos[] ra = g.map.razors(); e02668367d 2012-07-15 kinaba: const(Pos)[] hi = g.map.objects('W'); 9d4aca73fa 2012-07-14 kinaba: 62a5c6c47f 2012-07-14 kinaba: Tuple!(char,int)[] cand; 9d4aca73fa 2012-07-14 kinaba: char c = 'W'; f8d6e266eb 2012-07-15 kinaba: if( g.map.collected_lambda == g.map.total_lambda ) { 901abf2f53 2012-07-14 kinaba: cand = search(g, ro, [li], death); f8d6e266eb 2012-07-15 kinaba: } else if( !la.empty ){ 34bbd14c1a 2012-07-15 kinaba: cand ~= search(g, ro, la~ra, death); 9f1a8c70cd 2012-07-15 kinaba: } 9f1a8c70cd 2012-07-15 kinaba: 9f1a8c70cd 2012-07-15 kinaba: // 'higesori' mode e02668367d 2012-07-15 kinaba: if( !hi.empty && g.map.razor>0 ) { 9f1a8c70cd 2012-07-15 kinaba: int his = 0; 9f1a8c70cd 2012-07-15 kinaba: for(int dy=-1; dy<=+1; ++dy) 9f1a8c70cd 2012-07-15 kinaba: for(int dx=-1; dx<=+1; ++dx) e02668367d 2012-07-15 kinaba: if(g.map[ro.y+dy,ro.x+dx] == 'W') 9f1a8c70cd 2012-07-15 kinaba: his++; 9f1a8c70cd 2012-07-15 kinaba: 9f1a8c70cd 2012-07-15 kinaba: if(his>=2 || his==hi.length) 9f1a8c70cd 2012-07-15 kinaba: cand = [tuple('S',int.max)]; 9f1a8c70cd 2012-07-15 kinaba: if(cand.empty) { 9f1a8c70cd 2012-07-15 kinaba: const(Pos)[] tgt; e02668367d 2012-07-15 kinaba: for(int y=1; y<=g.map.H; ++y) e02668367d 2012-07-15 kinaba: for(int x=1; x<=g.map.W; ++x) e02668367d 2012-07-15 kinaba: if(g.map[y,x]=='.'||g.map[y,x]==' ') { 9f1a8c70cd 2012-07-15 kinaba: his = 0; 9f1a8c70cd 2012-07-15 kinaba: for(int dy=-1; dy<=+1; ++dy) 9f1a8c70cd 2012-07-15 kinaba: for(int dx=-1; dx<=+1; ++dx) e02668367d 2012-07-15 kinaba: if(g.map[y+dy,x+dx] == 'W') 9f1a8c70cd 2012-07-15 kinaba: his++; 9f1a8c70cd 2012-07-15 kinaba: if(his>=2) 9f1a8c70cd 2012-07-15 kinaba: tgt ~= new Pos(y,x); 9f1a8c70cd 2012-07-15 kinaba: } 9f1a8c70cd 2012-07-15 kinaba: cand ~= search(g, ro, tgt, death, true); 9f1a8c70cd 2012-07-15 kinaba: } 2f2eff2f03 2012-07-14 kinaba: } 2f2eff2f03 2012-07-14 kinaba: 2f2eff2f03 2012-07-14 kinaba: // 'dig' mode 68c41bdbe0 2012-07-14 kinaba: if(cand.empty) { 68c41bdbe0 2012-07-14 kinaba: const(Pos)[] tgt; e02668367d 2012-07-15 kinaba: for(int y=1; y<=g.map.H; ++y) e02668367d 2012-07-15 kinaba: for(int x=1; x<=g.map.W; ++x) e02668367d 2012-07-15 kinaba: if(g.map[y,x]=='.') c88611bab8 2012-07-15 kinaba: if(rocky(g.map[y+1,x])||rocky(g.map[y+1,x-1])||rocky(g.map[y+1,x+1]) c88611bab8 2012-07-15 kinaba: ||rocky(g.map[y,x+1])||rocky(g.map[y,x-1])) 68c41bdbe0 2012-07-14 kinaba: tgt ~= new Pos(y,x); 0c10424b3c 2012-07-14 kinaba: cand ~= search(g, ro, tgt, death, true); 68c41bdbe0 2012-07-14 kinaba: } 68c41bdbe0 2012-07-14 kinaba: ea96f24715 2012-07-14 kinaba: if(cand.empty) { ea96f24715 2012-07-14 kinaba: choke_count++; 68c41bdbe0 2012-07-14 kinaba: cand ~= tuple('W',int.max); ea96f24715 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ 62a5c6c47f 2012-07-14 kinaba: if(c1[1] != c2[1]) 62a5c6c47f 2012-07-14 kinaba: return c1[1] < c2[1]; 62a5c6c47f 2012-07-14 kinaba: return c1[0] < c2[0]; 62a5c6c47f 2012-07-14 kinaba: })(cand); 62a5c6c47f 2012-07-14 kinaba: c = cand[0][0]; 62a5c6c47f 2012-07-14 kinaba: 2f2eff2f03 2012-07-14 kinaba: if(death.count(c) || wait_count>=2) { 2f2eff2f03 2012-07-14 kinaba: foreach(char live; "UDLRW") c743b817b7 2012-07-14 kinaba: if(death.count(live)==0) { c743b817b7 2012-07-14 kinaba: c=live; c743b817b7 2012-07-14 kinaba: break; c743b817b7 2012-07-14 kinaba: } 9d4aca73fa 2012-07-14 kinaba: } c743b817b7 2012-07-14 kinaba: ea96f24715 2012-07-14 kinaba: if(c == 'W') c743b817b7 2012-07-14 kinaba: wait_count++; 9d4aca73fa 2012-07-14 kinaba: else c743b817b7 2012-07-14 kinaba: wait_count = 0; 9a93aeb664 2012-07-15 kinaba: if(wait_count==2) 9a93aeb664 2012-07-15 kinaba: c = 'A'; e02668367d 2012-07-15 kinaba: if(choke_count >= g.map.H) ea96f24715 2012-07-14 kinaba: c = 'A'; c743b817b7 2012-07-14 kinaba: c4d04122d8 2012-07-14 kinaba: bool[char] choice; c4d04122d8 2012-07-14 kinaba: foreach(t; cand) c4d04122d8 2012-07-14 kinaba: choice[t[0]] = true; c4d04122d8 2012-07-14 kinaba: log ~= tuple(ro.clone(), cast(int)choice.length); c4d04122d8 2012-07-14 kinaba: if(log.length > 5) c4d04122d8 2012-07-14 kinaba: log = log[$-5..$]; c4d04122d8 2012-07-14 kinaba: int cnt = 0; c4d04122d8 2012-07-14 kinaba: foreach(l; log) c4d04122d8 2012-07-14 kinaba: if(l[0] == log[$-1][0]) c4d04122d8 2012-07-14 kinaba: ++cnt; c4d04122d8 2012-07-14 kinaba: if( cnt >= 3 && breath==1 ) { c4d04122d8 2012-07-14 kinaba: forbidden_cell[ro.y][ro.x] = true; c4d04122d8 2012-07-14 kinaba: } c4d04122d8 2012-07-14 kinaba: 5fc8a9c49b 2012-07-14 kinaba: return c; 5fc8a9c49b 2012-07-14 kinaba: } 5fc8a9c49b 2012-07-14 kinaba: 0c10424b3c 2012-07-14 kinaba: Tuple!(char,int)[] search(in Game g, in Pos s, in Pos[] gs, string death, bool danger_ok=false) 5fc8a9c49b 2012-07-14 kinaba: { 62a5c6c47f 2012-07-14 kinaba: bool danger(int y, int x) 62a5c6c47f 2012-07-14 kinaba: { e02668367d 2012-07-15 kinaba: if(g.map[y,x] == ' ' || g.map[y,x] == 'R') 0c10424b3c 2012-07-14 kinaba: return false; c88611bab8 2012-07-15 kinaba: if(rocky(g.map[y+1,x])) c88611bab8 2012-07-15 kinaba: return true; 913d120d42 2012-07-15 kinaba: if(rocky(g.map[y+1,x-1]) && (g.map[y,x-1]=='\\'||rocky(g.map[y,x-1])) 913d120d42 2012-07-15 kinaba: && (g.map[y+1,x]==' '||g.map[y+1,x]=='R')) 62a5c6c47f 2012-07-14 kinaba: return true; c88611bab8 2012-07-15 kinaba: if(rocky(g.map[y+1,x+1]) && rocky(g.map[y,x+1]) && (g.map[y+1,x]==' '||g.map[y+1,x]=='R')) 62a5c6c47f 2012-07-14 kinaba: return true; 913d120d42 2012-07-15 kinaba: if(rocky(g.map[y,x-1]) && (g.map[y-1,x-1]=='\\'||rocky(g.map[y-1,x-1])) 913d120d42 2012-07-15 kinaba: && (g.map[y-1,x]==' '||g.map[y-1,x]=='R')) 62a5c6c47f 2012-07-14 kinaba: return true; c88611bab8 2012-07-15 kinaba: if(rocky(g.map[y,x+1]) && rocky(g.map[y-1,x+1]) && (g.map[y-1,x]==' '||g.map[y-1,x]=='R')) 62a5c6c47f 2012-07-14 kinaba: return true; 62a5c6c47f 2012-07-14 kinaba: return false; 62a5c6c47f 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: 5fc8a9c49b 2012-07-14 kinaba: // avoid directly below '*' 62a5c6c47f 2012-07-14 kinaba: Tuple!(char,int)[] tryA() { 901abf2f53 2012-07-14 kinaba: const(Pos)[] q; 901abf2f53 2012-07-14 kinaba: foreach(p; gs) 901abf2f53 2012-07-14 kinaba: if(!danger(p.y,p.x)) 901abf2f53 2012-07-14 kinaba: q ~= p; e02668367d 2012-07-15 kinaba: bool[][] v = new bool[][](g.map.H+2, g.map.W+2); 901abf2f53 2012-07-14 kinaba: foreach(p; q) v[p.y][p.x]=true; 901abf2f53 2012-07-14 kinaba: for(int step=1; q.length; ++step) { 901abf2f53 2012-07-14 kinaba: Pos[] q2; 901abf2f53 2012-07-14 kinaba: foreach(p; q) { 6e4c06b018 2012-07-14 kinaba: int[] yyy=[p.y-1,p.y+1,p.y,p.y]; 6e4c06b018 2012-07-14 kinaba: int[] xxx=[p.x,p.x,p.x-1,p.x+1]; 6e4c06b018 2012-07-14 kinaba: for(int i=0; i<yyy.length; ++i) { 6e4c06b018 2012-07-14 kinaba: int y = yyy[i]; 6e4c06b018 2012-07-14 kinaba: int x = xxx[i]; e02668367d 2012-07-15 kinaba: if('1'<=g.map[y,x]&&g.map[y,x]<='9') { d40deaae5a 2012-07-15 kinaba: foreach(ppp; g.tr.source_pos(g.map[y,x])) { 6e4c06b018 2012-07-14 kinaba: yyy ~= ppp.y; 6e4c06b018 2012-07-14 kinaba: xxx ~= ppp.x; 6e4c06b018 2012-07-14 kinaba: } 6e4c06b018 2012-07-14 kinaba: continue; 6e4c06b018 2012-07-14 kinaba: } 901abf2f53 2012-07-14 kinaba: if(v[y][x]) continue; 6e4c06b018 2012-07-14 kinaba: if(y==s.y && x==s.x && i<4) { 901abf2f53 2012-07-14 kinaba: char c = "UDRL"[i]; 901abf2f53 2012-07-14 kinaba: if( death.count(c) == 0 ) 901abf2f53 2012-07-14 kinaba: return [tuple(c,step)]; 901abf2f53 2012-07-14 kinaba: } else if(forbidden_cell[y][x]){ e02668367d 2012-07-15 kinaba: } else if(g.map[y,x]==' '||g.map[y,x]=='\\'||g.map[y,x]=='.'||g.map[y,x]=='!'||i>=4) { 901abf2f53 2012-07-14 kinaba: if(danger(y,x)) 901abf2f53 2012-07-14 kinaba: continue; 901abf2f53 2012-07-14 kinaba: q2 ~= new Pos(y,x); 901abf2f53 2012-07-14 kinaba: v[y][x]=true; 62a5c6c47f 2012-07-14 kinaba: } 5fc8a9c49b 2012-07-14 kinaba: } 5fc8a9c49b 2012-07-14 kinaba: } 901abf2f53 2012-07-14 kinaba: q = q2; 5fc8a9c49b 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: return []; 5fc8a9c49b 2012-07-14 kinaba: } 5fc8a9c49b 2012-07-14 kinaba: 5fc8a9c49b 2012-07-14 kinaba: // any empty space is my ground 62a5c6c47f 2012-07-14 kinaba: Tuple!(char,int)[] tryB() { 901abf2f53 2012-07-14 kinaba: const(Pos)[] q; 901abf2f53 2012-07-14 kinaba: foreach(p; gs) q ~= p; e02668367d 2012-07-15 kinaba: bool[][] v = new bool[][](g.map.H+2, g.map.W+2); 901abf2f53 2012-07-14 kinaba: foreach(p; q) v[p.y][p.x]=true; c4d04122d8 2012-07-14 kinaba: for(int step=10; q.length; ++step) { 62a5c6c47f 2012-07-14 kinaba: Pos[] q2; 62a5c6c47f 2012-07-14 kinaba: foreach(p; q) { 6e4c06b018 2012-07-14 kinaba: int[] yyy=[p.y-1,p.y+1,p.y,p.y]; 6e4c06b018 2012-07-14 kinaba: int[] xxx=[p.x,p.x,p.x-1,p.x+1]; 6e4c06b018 2012-07-14 kinaba: for(int i=0; i<yyy.length; ++i) { 6e4c06b018 2012-07-14 kinaba: int y = yyy[i]; 6e4c06b018 2012-07-14 kinaba: int x = xxx[i]; e02668367d 2012-07-15 kinaba: if('1'<=g.map[y,x]&&g.map[y,x]<='9') { d40deaae5a 2012-07-15 kinaba: foreach(ppp; g.tr.source_pos(g.map[y,x])) { 6e4c06b018 2012-07-14 kinaba: yyy ~= ppp.y; 6e4c06b018 2012-07-14 kinaba: xxx ~= ppp.x; 6e4c06b018 2012-07-14 kinaba: } 6e4c06b018 2012-07-14 kinaba: continue; 6e4c06b018 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: if(v[y][x]) continue; 6e4c06b018 2012-07-14 kinaba: if(y==s.y && x==s.x && i<4) { 62a5c6c47f 2012-07-14 kinaba: char c = "UDRL"[i]; 62a5c6c47f 2012-07-14 kinaba: if( death.count(c) == 0 ) 62a5c6c47f 2012-07-14 kinaba: return [tuple(c,step)]; c4d04122d8 2012-07-14 kinaba: } else if(forbidden_cell[y][x]){ e02668367d 2012-07-15 kinaba: } else if(g.map[y,x]==' '||g.map[y,x]=='\\'||g.map[y,x]=='.'||g.map[y,x]=='!'||i>=4) { 62a5c6c47f 2012-07-14 kinaba: q2 ~= new Pos(y,x); 62a5c6c47f 2012-07-14 kinaba: v[y][x]=true; 62a5c6c47f 2012-07-14 kinaba: } 5fc8a9c49b 2012-07-14 kinaba: } 5fc8a9c49b 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: q = q2; 5fc8a9c49b 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: return []; 5fc8a9c49b 2012-07-14 kinaba: } 5fc8a9c49b 2012-07-14 kinaba: 5fc8a9c49b 2012-07-14 kinaba: // push rocks! 62a5c6c47f 2012-07-14 kinaba: Tuple!(char,int)[] tryC() { 901abf2f53 2012-07-14 kinaba: const(Pos)[] q; 901abf2f53 2012-07-14 kinaba: foreach(p; gs) q ~= p; e02668367d 2012-07-15 kinaba: bool[][] v = new bool[][](g.map.H+2, g.map.W+2); 901abf2f53 2012-07-14 kinaba: foreach(p; q) v[p.y][p.x]=true; c4d04122d8 2012-07-14 kinaba: for(int step=20; q.length; ++step) { 62a5c6c47f 2012-07-14 kinaba: Pos[] q2; 62a5c6c47f 2012-07-14 kinaba: foreach(p; q) { 6e4c06b018 2012-07-14 kinaba: int[] yyy=[p.y-1,p.y+1,p.y,p.y]; 6e4c06b018 2012-07-14 kinaba: int[] xxx=[p.x,p.x,p.x-1,p.x+1]; 6e4c06b018 2012-07-14 kinaba: for(int i=0; i<yyy.length; ++i) { 6e4c06b018 2012-07-14 kinaba: int y = yyy[i]; 6e4c06b018 2012-07-14 kinaba: int x = xxx[i]; c88611bab8 2012-07-15 kinaba: if(rocky(g.map[p])) { faa7422a78 2012-07-14 kinaba: if(i>=4)continue; faa7422a78 2012-07-14 kinaba: if(y!=p.y)continue; e02668367d 2012-07-15 kinaba: if(g.map[y,p.x+(p.x-x)]!=' '&&g.map[y,p.x+(p.x-x)]!='R')continue; faa7422a78 2012-07-14 kinaba: } e02668367d 2012-07-15 kinaba: if('1'<=g.map[y,x]&&g.map[y,x]<='9') { d40deaae5a 2012-07-15 kinaba: foreach(ppp; g.tr.source_pos(g.map[y,x])) { 6e4c06b018 2012-07-14 kinaba: yyy ~= ppp.y; 6e4c06b018 2012-07-14 kinaba: xxx ~= ppp.x; 6e4c06b018 2012-07-14 kinaba: } 6e4c06b018 2012-07-14 kinaba: continue; 6e4c06b018 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: if(v[y][x]) continue; 6e4c06b018 2012-07-14 kinaba: if(y==s.y && x==s.x && i<4) { 62a5c6c47f 2012-07-14 kinaba: char c = "UDRL"[i]; 62a5c6c47f 2012-07-14 kinaba: if( death.count(c) == 0 ) 62a5c6c47f 2012-07-14 kinaba: return [tuple(c,step)]; c4d04122d8 2012-07-14 kinaba: } else if(forbidden_cell[y][x]){ c88611bab8 2012-07-15 kinaba: } else if(g.map[y,x]==' '||g.map[y,x]=='\\'||g.map[y,x]=='.'||rocky(g.map[y,x])||g.map[y,x]=='!'||i>=4) { 62a5c6c47f 2012-07-14 kinaba: q2 ~= new Pos(y,x); 62a5c6c47f 2012-07-14 kinaba: v[y][x]=true; 62a5c6c47f 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: q = q2; 62a5c6c47f 2012-07-14 kinaba: } 62a5c6c47f 2012-07-14 kinaba: return []; 62a5c6c47f 2012-07-14 kinaba: } 0c10424b3c 2012-07-14 kinaba: return (danger_ok ? [] : tryA()) ~ tryB() ~ tryC(); 0c10424b3c 2012-07-14 kinaba: } 0c10424b3c 2012-07-14 kinaba: } fec7ddc502 2012-07-14 kinaba: 913d120d42 2012-07-15 kinaba: class Solver_2(SubSolver) : Solver 45b72fc54e 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: static const PredictFuture = 10; 9a93aeb664 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: Game current_game; 9a93aeb664 2012-07-15 kinaba: SubSolver sub_solver; 9a93aeb664 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: enum {Tentative, Tentative_Stuck, Fixed}; 45b72fc54e 2012-07-15 kinaba: string plan; 9a93aeb664 2012-07-15 kinaba: int plan_state; 45b72fc54e 2012-07-15 kinaba: 45b72fc54e 2012-07-15 kinaba: this(in Game g) 45b72fc54e 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: current_game = g.clone(); 9a93aeb664 2012-07-15 kinaba: plan = ""; 9a93aeb664 2012-07-15 kinaba: plan_state = Tentative; 9a93aeb664 2012-07-15 kinaba: } 9a93aeb664 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: char single_step() 9a93aeb664 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: if(current_game.dead || current_game.cleared) 9a93aeb664 2012-07-15 kinaba: return 'A'; 9a93aeb664 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: // Make enough prediction. 9a93aeb664 2012-07-15 kinaba: while( plan_state==Tentative && plan.length<PredictFuture ) 9a93aeb664 2012-07-15 kinaba: single_step_predict(); 9a93aeb664 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: // If the future is bad, correct. 9a93aeb664 2012-07-15 kinaba: if( plan_state==Tentative_Stuck && plan.length<PredictFuture ) 9a93aeb664 2012-07-15 kinaba: replan(); 9a93aeb664 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: // Follow the predicted plan. 9a93aeb664 2012-07-15 kinaba: if( plan.empty ) 9a93aeb664 2012-07-15 kinaba: return 'A'; 9a93aeb664 2012-07-15 kinaba: writeln(plan, " ", plan_state); 9a93aeb664 2012-07-15 kinaba: char c = plan[0]; 9a93aeb664 2012-07-15 kinaba: plan = plan[1..$]; 9a93aeb664 2012-07-15 kinaba: current_game.command(c); 9a93aeb664 2012-07-15 kinaba: return c; 45b72fc54e 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: void force(char c) 45b72fc54e 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: if(plan.length>0 && plan[0]==c) 9a93aeb664 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: // If matching the plan, just go forward. 9a93aeb664 2012-07-15 kinaba: plan = plan[1..$]; 9a93aeb664 2012-07-15 kinaba: } 9a93aeb664 2012-07-15 kinaba: else 9a93aeb664 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: // Discard the plan, otherwise. 9a93aeb664 2012-07-15 kinaba: plan_state = Tentative; 9a93aeb664 2012-07-15 kinaba: plan = ""; 9a93aeb664 2012-07-15 kinaba: sub_solver = null; 45b72fc54e 2012-07-15 kinaba: } 9a93aeb664 2012-07-15 kinaba: current_game.command(c); 45b72fc54e 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: void single_step_predict() 9a93aeb664 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: if(sub_solver is null) { 9a93aeb664 2012-07-15 kinaba: sub_solver = new SubSolver(current_game); 9a93aeb664 2012-07-15 kinaba: plan = ""; 9a93aeb664 2012-07-15 kinaba: } 9a93aeb664 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: char c = sub_solver.single_step(); 9a93aeb664 2012-07-15 kinaba: if(c == 'A') 9a93aeb664 2012-07-15 kinaba: plan_state = Tentative_Stuck; 9a93aeb664 2012-07-15 kinaba: else { 9a93aeb664 2012-07-15 kinaba: plan ~= c; 9a93aeb664 2012-07-15 kinaba: plan_state = (sub_solver.g.dead ? Tentative_Stuck : 9a93aeb664 2012-07-15 kinaba: sub_solver.g.cleared ? Fixed : Tentative); 9a93aeb664 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: void replan() 45b72fc54e 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: writeln("replan!"); 9a93aeb664 2012-07-15 kinaba: // Try to replace every step of the plan by another move. 9a93aeb664 2012-07-15 kinaba: Game g = current_game.clone(); 9a93aeb664 2012-07-15 kinaba: Tuple!(long, SubSolver, string, int) cand = 9a93aeb664 2012-07-15 kinaba: tuple(sub_solver.g.score, sub_solver, plan, Tentative_Stuck); 9a93aeb664 2012-07-15 kinaba: for(int i=0; i<plan.length; ++i) { 9a93aeb664 2012-07-15 kinaba: foreach(string prefix; ["U","D","L","R","UD","DU","LR","RL"]) 9a93aeb664 2012-07-15 kinaba: if(prefix[0] != plan[i]) { 9a93aeb664 2012-07-15 kinaba: Tuple!(long, SubSolver, string, int) r = try_plan(g, prefix); 9a93aeb664 2012-07-15 kinaba: if(cand[0] < r[0]) { 9a93aeb664 2012-07-15 kinaba: r[2] = plan[0..i] ~ prefix ~ r[2]; 9a93aeb664 2012-07-15 kinaba: cand = r; 9a93aeb664 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: g.command(plan[i]); 45b72fc54e 2012-07-15 kinaba: } 913d120d42 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: sub_solver = cand[1]; 9a93aeb664 2012-07-15 kinaba: plan = cand[2]; 9a93aeb664 2012-07-15 kinaba: plan_state = (plan.length < PredictFuture ? Fixed : cand[3]); 45b72fc54e 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: Tuple!(long, SubSolver, string, int) try_plan(in Game g, string prefix) 9a93aeb664 2012-07-15 kinaba: { 9a93aeb664 2012-07-15 kinaba: SubSolver s = new SubSolver(g); 9a93aeb664 2012-07-15 kinaba: foreach(char c; prefix) 9a93aeb664 2012-07-15 kinaba: s.force(c); 9a93aeb664 2012-07-15 kinaba: string log; 9a93aeb664 2012-07-15 kinaba: int state = Tentative; 9a93aeb664 2012-07-15 kinaba: while(!s.g.cleared && !s.g.dead && log.length<=g.map.H*g.map.W) { 9a93aeb664 2012-07-15 kinaba: char c = s.single_step(); 9a93aeb664 2012-07-15 kinaba: if( c == 'A' ) { 9a93aeb664 2012-07-15 kinaba: state = Tentative_Stuck; 9a93aeb664 2012-07-15 kinaba: break; 9a93aeb664 2012-07-15 kinaba: } 9a93aeb664 2012-07-15 kinaba: log ~= c; 913d120d42 2012-07-15 kinaba: } 9a93aeb664 2012-07-15 kinaba: if(s.g.cleared) state = Fixed; 9a93aeb664 2012-07-15 kinaba: else if(s.g.dead) state = Tentative_Stuck; 9a93aeb664 2012-07-15 kinaba: return tuple(s.g.score, s, log, state); 45b72fc54e 2012-07-15 kinaba: } 913d120d42 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: 913d120d42 2012-07-15 kinaba: class MasterSolver : Solver 913d120d42 2012-07-15 kinaba: { 913d120d42 2012-07-15 kinaba: this(in Game g) 913d120d42 2012-07-15 kinaba: { 913d120d42 2012-07-15 kinaba: int SIZE = g.map.H * g.map.W; 913d120d42 2012-07-15 kinaba: if( SIZE <= 32*32 ) 913d120d42 2012-07-15 kinaba: sub = new Solver_2!(Solver_1)(g); 913d120d42 2012-07-15 kinaba: else if( SIZE <= 100*100 ) 913d120d42 2012-07-15 kinaba: sub = new Solver_1(g); 913d120d42 2012-07-15 kinaba: else 913d120d42 2012-07-15 kinaba: sub = new Solver_1(g); 45b72fc54e 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: 913d120d42 2012-07-15 kinaba: private Solver sub; 913d120d42 2012-07-15 kinaba: char single_step() { return sub.single_step(); } 913d120d42 2012-07-15 kinaba: void force(char c) { sub.force(c); } 45b72fc54e 2012-07-15 kinaba: } 45b72fc54e 2012-07-15 kinaba: 9a93aeb664 2012-07-15 kinaba: //alias MasterSolver MainSolver; 9a93aeb664 2012-07-15 kinaba: alias Solver_2!(Solver_1) MainSolver; 310a3c5d41 2012-07-15 kinaba: //alias Solver_1 MainSolver; 913d120d42 2012-07-15 kinaba: //alias Solver_0 MainSolver;