Check-in Differences
Not logged in

Difference From:

[fc9286dad1] uum (user: kinaba, tags: redesign, date: 2012-07-15 12:11:33)

To:

[52e6fbcc8d] Add solver.d!!! (user: kinaba, tags: trunk, date: 2012-07-14 08:58:14)

Added game.d version [7c15481493257083]

> 1 import util; > 2 import output; > 3 > 4 //////////////////////////////////////////////////////////////////////////////// > 5 > 6 class Pos > 7 { > 8 public immutable int y, x; > 9 mixin DeriveCreate; > 10 mixin DeriveCompare; > 11 mixin DeriveShow; > 12 Pos clone() { return this; } > 13 > 14 @property: > 15 Pos wait() { return this; } > 16 Pos up() { return new Pos(y+1, x); } > 17 Pos down() { return new Pos(y-1, x); } > 18 Pos left() { return new Pos(y, x-1); } > 19 Pos right() { return new Pos(y, x+1); } > 20 alias wait W,w; > 21 alias up U,u; > 22 alias down D,d; > 23 alias left L,l; > 24 alias right R,r; > 25 } > 26 > 27 unittest > 28 { > 29 assert( (new Pos(2,1)).U == new Pos(3,1) ); > 30 assert( (new Pos(0,1)).D == new Pos(-1,1) ); > 31 assert( (new Pos(2,1)).L == new Pos(2,0) ); > 32 assert( (new Pos(2,1)).R == new Pos(2,2) ); > 33 int[Pos] aa; > 34 aa[new Pos(1,2)] = 1; > 35 aa[new Pos(1,2)] = 2; > 36 aa[new Pos(2,1)] = 3; > 37 assert( aa.length==2 ); > 38 assert( aa[new Pos(1,2)]==2 ); > 39 } > 40 > 41 //////////////////////////////////////////////////////////////////////////////// > 42 > 43 class Water > 44 { > 45 public immutable int base, pace; > 46 mixin DeriveCreate; > 47 mixin DeriveCompare; > 48 mixin DeriveShow; > 49 Water clone() { return this; } > 50 > 51 static load(string[string] params) > 52 { > 53 return new Water( > 54 params.get("Water", "0").to!int(), > 55 params.get("Flooding", "0").to!int() > 56 ); > 57 } > 58 > 59 int level(int number_of_update) > 60 { > 61 return pace ? base+(number_of_update/pace) : base; > 62 } > 63 > 64 int until_rise(int number_of_update) > 65 { > 66 return pace ? pace-number_of_update%pace : int.max; > 67 } > 68 } > 69 > 70 unittest > 71 { > 72 Water w = new Water(1, 3); > 73 assert( 1 == w.level(0) ); > 74 assert( 1 == w.level(1) ); > 75 assert( 1 == w.level(2) ); > 76 assert( 2 == w.level(3) ); > 77 assert( 2 == w.level(4) ); > 78 assert( 2 == w.level(5) ); > 79 assert( 3 == w.level(6) ); > 80 > 81 w = new Water(1, 0); > 82 assert( 1 == w.level(0) ); > 83 assert( 1 == w.level(1) ); > 84 assert( 1 == w.level(2) ); > 85 assert( 1 == w.level(3) ); > 86 assert( 1 == w.level(4) ); > 87 assert( 1 == w.level(5) ); > 88 } > 89 > 90 //////////////////////////////////////////////////////////////////////////////// > 91 > 92 class Map > 93 { > 94 mixin DeriveShow; > 95 > 96 static Map load(string[] raw_data, string[string] params) > 97 { > 98 // TODO: choose optimal representation. > 99 return new Map(raw_data, params); > 100 } > 101 > 102 char[][] data; > 103 Pos robot; > 104 Pos lift; > 105 int waterproof; > 106 > 107 Map clone() { return new Map(this); } > 108 this(Map m) { > 109 foreach(s; m.data) > 110 this.data ~= s.dup; > 111 this.robot = m.robot.clone(); > 112 this.lift = m.lift.clone(); > 113 this.waterproof = m.waterproof; > 114 } > 115 > 116 this(string[] raw_data, string[string] params) > 117 { > 118 int width = 0; > 119 foreach(r; raw_data) > 120 width = max(width, r.length); > 121 foreach(r; raw_data) { > 122 this.data ~= r.dup; > 123 this.data[$-1].length = width; > 124 this.data[$-1][r.length..$] = ' '; > 125 } > 126 > 127 for(int y=1; y<=H; ++y) > 128 for(int x=1; x<=W; ++x) { > 129 if(this[y,x] == 'R') > 130 this.robot = new Pos(y,x); > 131 if(this[y,x] == 'L' || this[y,x] == 'O') > 132 this.lift = new Pos(y,x); > 133 } > 134 > 135 this.waterproof = params.get("Waterproof", "5").to!int(); > 136 } > 137 > 138 const @property { > 139 int H() { return data.length; } > 140 int W() { return data[0].length; } > 141 } > 142 > 143 char opIndex(int y, int x) > 144 { > 145 // Adjust coordinate to the spec. bottom-left is (1,1). > 146 --y, --x; > 147 if(y<0||H<=y||x<0||W<=x) > 148 return '#'; > 149 return data[H-1-y][x]; > 150 } > 151 > 152 char opIndex(Pos p) > 153 { > 154 return this[p.y, p.x]; > 155 } > 156 > 157 void opIndexAssign(char c, int y, int x) > 158 { > 159 // Adjust coordinate to the spec. bottom-left is (1,1). > 160 --y, --x; > 161 if(y<0||H<=y||x<0||W<=x) > 162 return; > 163 data[H-1-y][x] = c; > 164 } > 165 > 166 void opIndexAssign(char c, Pos p) > 167 { > 168 this[p.y, p.x] = c; > 169 } > 170 > 171 Pos[] lambdas() { > 172 Pos[] ans; > 173 for(int y=1; y<=H; ++y) > 174 for(int x=1; x<=W; ++x) > 175 if(this[y,x] == '\\') > 176 ans ~= new Pos(y,x); > 177 return ans; > 178 } > 179 > 180 bool cleared() > 181 { > 182 for(int y=1; y<=H; ++y) > 183 for(int x=1; x<=W; ++x) > 184 if(this[y,x] == 'L' || this[y,x] == 'O') > 185 return false; > 186 return true; > 187 } > 188 > 189 Tuple!(int,bool) command(char c) > 190 { > 191 if(c=='R') return move( 0, +1); > 192 if(c=='L') return move( 0, -1); > 193 if(c=='U') return move(+1, 0); > 194 if(c=='D') return move(-1, 0); > 195 if(c=='W') return move( 0, 0); > 196 assert(false); > 197 } > 198 > 199 Tuple!(int, bool) move(int dy, int dx) > 200 { > 201 int y = robot.y; > 202 int x = robot.x; > 203 assert( this[robot] == 'R' ); > 204 int lambda = 0; > 205 bool dead = false; > 206 if( '\\' == this[y+dy,x+dx] ) > 207 lambda++; > 208 if( " \\.O".count(this[y+dy,x+dx])==1 ) { > 209 this[y,x]=' '; > 210 this[y+dy,x+dx]='R'; > 211 robot = new Pos(y+dy,x+dx); > 212 } else if(dy==0 && '*'==this[y+dy,x+dx] && ' '==this[y+dy*2,x+dx > 213 this[y,x]=' '; > 214 this[y+dy,x+dx]='R'; > 215 this[y+dy*2,x+dx*2]='*'; > 216 robot = new Pos(y+dy,x+dx); > 217 } > 218 if( update() ) > 219 dead = true; > 220 return tuple(lambda,dead); > 221 } > 222 > 223 bool update() > 224 { > 225 bool dead = false; > 226 > 227 char[][] next; > 228 foreach(y,s; data) > 229 next ~= s.dup; > 230 > 231 ref char access(Pos p) { return next[H-p.y][p.x-1]; } > 232 > 233 bool lambda = false; > 234 for(int y=1; y<=H; ++y) > 235 for(int x=1; x<=W; ++x) > 236 lambda |= (this[y,x] == '\\'); > 237 > 238 for(int y=1; y<=H; ++y) > 239 for(int x=1; x<=W; ++x) { > 240 Pos p = new Pos(y,x); > 241 if(this[p]=='*') { > 242 if(this[p.D]==' ') { > 243 access(p) =' '; > 244 access(p.D)='*'; > 245 if(robot == p.D.D) > 246 dead=true; > 247 } > 248 else if((this[p.D]=='*' || this[p.D]=='\\') && t > 249 access(p)=' '; > 250 access(p.R.D)='*'; > 251 if(robot == p.R.D.D) > 252 dead=true; > 253 } > 254 else if(this[p.D]=='*' && this[p.L]==' ' && this > 255 access(p)=' '; > 256 access(p.L.D)='*'; > 257 if(robot == p.L.D.D) > 258 dead=true; > 259 } > 260 } > 261 else if(this[p]=='L') { > 262 if(!lambda) > 263 access(p) = 'O'; > 264 } > 265 } > 266 data = next; > 267 return dead; > 268 } > 269 } > 270 > 271 //////////////////////////////////////////////////////////////////////////////// > 272 > 273 class Game > 274 { > 275 mixin DeriveShow; > 276 > 277 static Game load(File input) > 278 { > 279 string[] raw_data; > 280 string[string] params; > 281 > 282 // Raw map data; read until empty line. > 283 for(string line; !(line=input.readln().chomp()).empty; ) > 284 raw_data ~= line; > 285 > 286 // Additional commands; read until EOF. > 287 for(string line; !(line=input.readln()).empty; ) { > 288 string[] ss = line.split(); > 289 if( ss.length == 2 ) > 290 params[ss[0]] = ss[1]; > 291 } > 292 > 293 return load(raw_data, params); > 294 } > 295 > 296 static Game load(string[] raw_data, string[string] params) > 297 { > 298 return new Game(raw_data, params); > 299 } > 300 > 301 this(string[] raw_data, string[string] params) > 302 { > 303 this.map = Map.load(raw_data, params); > 304 this.water = Water.load(params); > 305 this.output = new NilOutput; > 306 } > 307 > 308 Game clone() { return new Game(this); } > 309 this(Game g) { > 310 map = g.map.clone(); > 311 water = g.water.clone(); > 312 output = new NilOutput; > 313 turn = g.turn; > 314 dead = g.dead; > 315 lambda = g.lambda; > 316 exit_bonus = g.exit_bonus; > 317 under_water = g.under_water; > 318 } > 319 > 320 void set_output(Output o) { this.output = (o is null ? new NilOutput : o > 321 > 322 void command(char c) > 323 { > 324 if(dead || cleared) > 325 return; > 326 scope(exit) { > 327 if(dead || cleared) > 328 output.flush(); > 329 } > 330 this.output.command(c); > 331 > 332 if(c == 'A') > 333 { > 334 exit_bonus = 1; > 335 return; > 336 } > 337 > 338 // TODO: clarify the event order > 339 Tuple!(int,bool) ld = map.command(c); > 340 if( map.cleared() ) { > 341 exit_bonus = 2; > 342 } > 343 else { > 344 lambda += ld[0]; > 345 if( ld[1] ) { > 346 dead = true; > 347 } > 348 } > 349 if( map.robot.y <= water_level ) > 350 ++under_water; > 351 else > 352 under_water = 0; > 353 if( under_water > map.waterproof ) > 354 dead = true; > 355 turn += 1; > 356 } > 357 > 358 Map map; > 359 Water water; > 360 Output output; > 361 int turn = 0; > 362 bool dead = false; > 363 int lambda = 0; > 364 int exit_bonus = 0; > 365 int under_water = 0; > 366 // TODO: when adding members, take care of clone(). > 367 // TODO: fix this poor design. > 368 > 369 @property { > 370 long score() { return lambda*25L*(1+exit_bonus) - turn; } > 371 int water_level() { return water.level(turn); } > 372 int water_until_rise() { return water.until_rise(turn); } > 373 bool cleared() { return exit_bonus>0; } > 374 int hp() { return map.waterproof - under_water; } > 375 long score_if_abort_now() { return lambda*25*(1+max(1,exit_bonus > 376 } > 377 } > 378 > 379 unittest > 380 { > 381 Game.load(["###","...","#RL"], ["xxx":"yyy"]); > 382 }

Added gui.d version [8bca70d55515c665]

> 1 import dfl.all; > 2 import util; > 3 import game; > 4 import output; > 5 //import solver; > 6 > 7 class GUI : Form > 8 { > 9 private { > 10 Game g; > 11 int cell; > 12 int turn = 0; > 13 > 14 Font font; > 15 Color[char] colors; > 16 string[char] render; > 17 } > 18 > 19 this(Game g) > 20 { > 21 noMessageFilter(); > 22 this.setStyle(ControlStyles.OPAQUE, true); > 23 this.g = g; > 24 > 25 this.paint ~= &my_paint; > 26 this.keyDown ~= &my_keydown; > 27 > 28 this.formBorderStyle = FormBorderStyle.FIXED_DIALOG; > 29 this.maximizeBox = false; > 30 this.minimizeBox = false; > 31 this.cell = min(1024/g.map.W, 640/g.map.H); > 32 this.clientSize = Size(g.map.W*cell, g.map.H*cell); > 33 set_text(); > 34 > 35 // Resources > 36 this.font = new Font("MS Gothic", cell-2, GraphicsUnit.PIXEL); > 37 this.backColor = Color(255,255,255); > 38 this.colors['#'] = > 39 this.colors['.'] = Color(255,191,127); > 40 this.colors['*'] = Color(255,127,127); > 41 this.colors['R'] = Color(128,128,0); > 42 this.colors['D'] = Color(255,0,0); // Dead > 43 this.colors['\\'] = > 44 this.colors['L'] = > 45 this.colors['O'] = Color(127,255,127); > 46 this.colors['W'] = Color(204,229,255); // water > 47 > 48 this.render['#'] = "■"; > 49 this.render['*'] = "✹"; > 50 this.render['.'] = "♒"; > 51 this.render['\\'] = "λ"; > 52 this.render['R'] = "☃"; > 53 this.render['D'] = "☠"; > 54 this.render['L'] = "☒"; > 55 this.render['O'] = "☐"; > 56 } > 57 > 58 private: > 59 void my_paint(Control, PaintEventArgs ev) > 60 { > 61 const scrH = this.clientSize.height; > 62 const scrW = this.clientSize.width; > 63 Graphics gr = new MemoryGraphics(scrW, scrH, ev.graphics); > 64 scope(exit) { > 65 gr.copyTo(ev.graphics, Rect(0,0,scrW,scrH)); > 66 gr.dispose(); > 67 } > 68 > 69 // Fill bg. > 70 gr.fillRectangle(this.backColor, Rect(0,0,scrW,scrH)); > 71 > 72 // Fill water. > 73 int w = g.water_level(); > 74 gr.fillRectangle(this.colors['W'], Rect(0, scrH-cell*w-1, scrW, > 75 > 76 // Paint map. > 77 for(int y=1; y<=g.map.H; ++y) > 78 for(int x=1; x<=g.map.W; ++x) { > 79 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); > 80 char c = g.map[y,x]; > 81 if( c != ' ' ) { > 82 if( c == 'R' && g.dead ) > 83 c = 'D'; > 84 gr.drawText(this.render[c], font, this.colors[c] > 85 } > 86 } > 87 } > 88 > 89 void my_keydown(Control c, KeyEventArgs ev) > 90 { > 91 switch(ev.keyCode) > 92 { > 93 case Keys.DOWN: g.command('D'); break; > 94 case Keys.UP: g.command('U'); break; > 95 case Keys.LEFT: g.command('L'); break; > 96 case Keys.RIGHT: g.command('R'); break; > 97 case Keys.W: g.command('W'); break; > 98 case Keys.A: g.command('A'); break; > 99 // case Keys.G: solver.act(g); break; > 100 default: break; > 101 } > 102 if(g.cleared) > 103 Application.exit(); > 104 invalidate(); > 105 set_text(); > 106 } > 107 > 108 void set_text() { > 109 this.text = .text("Score: ", g.score, " Air: ", g.hp, " Tide: ", > 110 } > 111 } > 112 > 113 void main(string[] args) > 114 { > 115 auto g = Game.load(File(args[1])); > 116 g.set_output(new GuardedOutput(g)); > 117 auto myForm = new GUI(g); > 118 Application.run(myForm); > 119 }

Deleted icfp-96533632.tgz version [943329c30072989f]

cannot compute difference between binary files

Deleted make-submission version [bd7a911c141ae544]

1 #!/bin/sh < 2 rm -rf submission/src < 3 cp -r src submission/src < 4 tar czf icfp-96533632.tgz submission <

Deleted maps/100x100.map version [5beaf6fad4143830]

1 ################################################################################ < 2 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 3 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 4 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 5 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 6 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\L\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 7 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 8 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 9 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 10 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 11 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 12 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 13 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 14 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 15 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 16 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 17 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 18 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 19 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 20 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 21 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 22 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 23 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 24 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 25 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 26 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 27 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 28 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 29 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 30 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 31 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 32 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 33 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 34 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 35 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 36 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 37 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 38 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 39 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 40 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 41 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 42 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 43 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 44 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 45 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 46 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 47 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 48 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 49 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 50 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 51 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 52 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 53 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 54 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 55 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 56 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 57 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 58 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 59 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 60 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 61 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 62 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\R\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 63 #************************\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 64 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.********************************\.\.\.\.\.\.\.\.\. < 65 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.************* < 66 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 67 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 68 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 69 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 70 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 71 #************************\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 72 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.********************************\.\.\.\.\.\.\.\.\. < 73 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.************* < 74 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 75 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 76 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 77 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 78 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 79 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 80 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 81 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 82 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 83 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 84 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 85 #************************\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 86 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.********************************\.\.\.\.\.\.\.\.\. < 87 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.************* < 88 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 89 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 90 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 91 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 92 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 93 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 94 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 95 #************************\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 96 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.********************************\.\.\.\.\.\.\.\.\. < 97 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.************* < 98 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. < 99 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ < 100 ################################################################################ <

Deleted maps/40x40.map version [06dc362ef16f425d]

1 ######################################## < 2 #L\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 3 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 4 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*# < 5 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 6 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 7 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 8 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 9 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 10 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 11 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*# < 12 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 13 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 14 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 15 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 16 #.\.\.\.\.\.\.\.\.\W\.\.\.\.\.\.\.\.\.\# < 17 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*# < 18 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 19 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 20 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 21 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 22 #.\.\.\.\!\.\.\.\.\.\.\.\W\.\.\.\.\.\.\# < 23 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 24 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 25 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 26 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 27 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 28 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 29 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 30 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 31 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\!\.\.# < 32 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 33 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 34 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# < 35 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\!\.\.# < 36 #.\.\.\.\.\.\.\.\W\.\.\.\.\.\.\.\.\.\.\# < 37 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# < 38 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R# < 39 ######################################## < 40 < 41 Flooding 80 <

Deleted maps/beard1.map version [bb6926793a51311a]

1 ########## < 2 #** \\\\# < 3 #.R.. # < 4 # \ ..*\# < 5 #! ..*!# < 6 #### # # < 7 #\\... # L < 8 #\\.W... # < 9 #\\. # < 10 ########## < 11 < 12 Growth 15 < 13 Razors 0 <

Deleted maps/beard2.map version [2e942009c89717d7]

1 ############################## < 2 #R...........................# < 3 #.........................W..# < 4 #..\\\\\\\\\\\\\\\\\\\\\\\\..# < 5 #............................# < 6 #..*****.*\...*...*...*****..# < 7 #..*\....*\....*\*..*.\\*\\..# < 8 #..*\....****..!*!......*....# < 9 #..*\....*\....*\*..*...*....# < 10 #..*\....*\...*...*.....*....# < 11 #............................# < 12 #..\\\\\\\\\\\\\\\\\\\\\\\\..# < 13 #................ ..... .....# < 14 #................ W....L# < 15 ############################## < 16 < 17 Growth 25 < 18 Razors 10 < 19 Flooding 20 <

Deleted maps/beard3.map version [1dcab340493857d0]

1 ################ < 2 #*****#!! 1 # < 3 #..\..# # < 4 #########\\\\ # .\\\. # < 5 #.............# * # < 6 #.. .\\\#..!..#\** # < 7 #.. LW\\#W ..##### #### < 8 #..R\\\\#.. ..*\*\*W...# < 9 #.......A.. ...\.\...\\# < 10 #.......... ** # < 11 ############....\.###### < 12 #.....!# < 13 ######## < 14 < 15 Growth 10 < 16 Trampoline A targets 1 <

Deleted maps/beard4.map version [b62967eb47a5f507]

1 #################### < 2 #W\\!#\\\**.\#W\\\W# < 3 ##*######..###..\\\# < 4 #.......\.R ###...\# < 5 #####.###.#.......## < 6 #.......#.#\####.### < 7 #\\##\###\#\\#...#.L < 8 #\##\.###.####.#.#.# < 9 #\W#####.....###.W.# < 10 ####\\...\\\...#.#.# < 11 #W*######.######.#.# < 12 #\\\\\\\\\.........# < 13 ############\###\### < 14 #\\.. *..........\\# < 15 #W... #.........##W# < 16 #################### <

Deleted maps/fun1.map version [2f7f87a4d02c6448]

1 \\\\\\\\\L < 2 ********** < 3 < 4 < 5 < 6 < 7 < 8 R <

Deleted maps/trampoline1.map version [5af697c0003d5516]

1 ############ < 2 #..*.R..*..# < 3 #..A....B..###### < 4 #....2.. ..#\\\C# < 5 #......* *.#\\\1# < 6 ########L######## < 7 < 8 Trampoline A targets 1 < 9 Trampoline B targets 1 < 10 Trampoline C targets 2 <

Deleted maps/trampoline2.map version [288f9d055c2777fa]

1 ###### < 2 #....# < 3 #.**.# < 4 #.**.# < 5 #.**.# < 6 ######.\\.###### < 7 #**....*.......# < 8 #\\....L\\\....# < 9 #A......*****..# < 10 ######R.....########### < 11 ###.....*.....\\\# < 12 #\\\\#..1...\\\# < 13 #\\\\#......\\\# < 14 ################ < 15 < 16 Trampoline A targets 1 <

Deleted maps/trampoline3.map version [7fcf90c1ca373c41]

1 ####################################### < 2 #****................#..1...\\\\\\\B..# < 3 #R.......############################## < 4 #.. ..................................# < 5 #.. ........ \ ......# < 6 #.. .*. ....**.*...#....... ..........# < 7 #.. ... ....\\\\...#.A..... ..........# < 8 #.. ... ....\ .....#....... * \\..# < 9 #.. ... ....\......#....... ..........# < 10 #.. ... ....\......#....... ..........# < 11 #.. ... ...........#................**# < 12 #..\\\\\...........#................\\# < 13 ########### ############## ############ < 14 #...*.................................# < 15 #....*.................. ......# < 16 #... .*....*.............. ..... .....# < 17 #....*2*........########.. ..... .....L < 18 #...*...*.......#\\\#..... ...*.......# < 19 #.....\\\.......#\\\#....**..***......# < 20 #.... .......#\\\#*................# < 21 #...............#\\\#*...**...*.......# < 22 #...............#.....................# < 23 ###### ############## ### ####### < 24 #\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\# < 25 ####################################### < 26 < 27 Trampoline A targets 1 < 28 Trampoline B targets 2 < 29 <

Added output.d version [1b458d7cd25e92dc]

> 1 import util; > 2 import game; > 3 import core.stdc.signal; > 4 import std.c.stdlib; > 5 > 6 abstract class Output > 7 { > 8 void command(char c); > 9 void flush(); > 10 } > 11 > 12 class NilOutput : Output > 13 { > 14 override void command(char c) {} > 15 override void flush() {} > 16 } > 17 > 18 class StdOutput : Output > 19 { > 20 override void command(char c) > 21 { > 22 write(c); > 23 stdout.flush(); > 24 } > 25 override void flush() {} > 26 } > 27 > 28 // TODO: clean it up. > 29 __gshared Output g_output; > 30 > 31 class GuardedOutput : StdOutput > 32 { > 33 // Handle SIGINT: force abort and exit. > 34 static this() > 35 { > 36 signal(SIGINT, &sigint); > 37 } > 38 > 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 > 52 > 53 string log; > 54 long[] score_log; > 55 long[] ideal_log; > 56 > 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() > 65 { > 66 Tuple!(long, int, int) cand; > 67 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(); > 79 } > 80 }

Deleted score_memo.txt version [95f0626c958d6d31]

1 contest1 212! < 2 contest2 280? < 3 contest3 275! < 4 contest4 561? < 5 contest5 1281? < 6 contest6 737 // deadend trap < 7 contest7 867? < 8 contest8 1245 // tricky < 9 contest9 3042? < 10 contest10 2076 // * on lambda, must move * first < 11 flood1 569 // too slow, because of 1-left danger lambda < 12 flood2 280? < 13 flood3 802 // too slow, drown < 14 flood4 970 // incorrect order of digging < 15 flood5 561? < 16 trampoline1 291 // * on trampoline. must move * first < 17 trampoline2 1728? < 18 trampoline3 698 // * on trampoline target. must move * first. < 19 beard1 856? < 20 beard2 2792 // hutsu-ni muzui < 21 beard3 811 // tricky. must hurry to cut hige. < 22 beard4 677 // deadend trap <

Added solver.d version [2d4705e7ff103283]

> 1 import util; > 2 import game; > 3 import output; > 4 > 5 int g_wc = 0; > 6 > 7 void act(Game g) > 8 { > 9 Pos ro = g.map.robot; > 10 Pos[] la = g.map.lambdas(); > 11 Pos li = g.map.lift; > 12 > 13 char c = 'W'; > 14 if( la.empty ) { > 15 auto r = search(g, ro, li); > 16 c = r[0]; > 17 } else { > 18 Tuple!(char,int)[] cand; > 19 foreach(lam; la) > 20 cand ~= search(g, ro, lam); > 21 sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ > 22 if(c1[1] != c2[1]) > 23 return c1[1] < c2[1]; > 24 return c1[0] < c2[0]; > 25 })(cand); > 26 c = cand[0][0]; > 27 } > 28 if(c=='W') { > 29 g_wc++; > 30 if(g_wc > 10) > 31 c = 'A'; > 32 } > 33 else > 34 g_wc = 0; > 35 g.command(c); > 36 } > 37 > 38 Tuple!(char,int) search(Game g, Pos s, Pos o) > 39 { > 40 Pos[] q = [o]; > 41 bool[][] v = new bool[][](g.map.H+2, g.map.W+2); > 42 for(int step=1; q.length; ++step) { > 43 Pos[] q2; > 44 foreach(p; q) { > 45 int[] dy=[-1,+1,0,0]; > 46 int[] dx=[0,0,-1,+1]; > 47 for(int i=0; i<4; ++i) { > 48 int y = p.y+dy[i]; > 49 int x = p.x+dx[i]; > 50 if(v[y][x]) continue; > 51 if(y==s.y && x==s.x) { > 52 if(i==0) return tuple('U',step); > 53 if(i==1) return tuple('D',step); > 54 if(i==2) return tuple('R',step); > 55 if(i==3) return tuple('L',step); > 56 } else if(g.map[y,x]==' '||g.map[y,x]=='\\') { > 57 q2 ~= new Pos(y,x); > 58 v[y][x]=true; > 59 } else if(g.map[y,x]=='.' && g.map[y-1,x]!='*') > 60 q2 ~= new Pos(y,x); > 61 v[y][x]=true; > 62 } > 63 } > 64 } > 65 q = q2; > 66 } > 67 q = [o]; > 68 v = new bool[][](g.map.H+2, g.map.W+2); > 69 for(int step=1000; q.length; ++step) { > 70 Pos[] q2; > 71 foreach(p; q) { > 72 int[] dy=[-1,+1,0,0]; > 73 int[] dx=[0,0,-1,+1]; > 74 for(int i=0; i<4; ++i) { > 75 int y = p.y+dy[i]; > 76 int x = p.x+dx[i]; > 77 if(v[y][x]) continue; > 78 if(y==s.y && x==s.x) { > 79 if(i==0) return tuple('U',step); > 80 if(i==1) return tuple('D',step); > 81 if(i==2) return tuple('R',step); > 82 if(i==3) return tuple('L',step); > 83 } else if(g.map[y,x]==' '||g.map[y,x]=='\\') { > 84 q2 ~= new Pos(y,x); > 85 v[y][x]=true; > 86 } else if(g.map[y,x]=='.'/* && g[y-1,x]!='*'*/) > 87 q2 ~= new Pos(y,x); > 88 v[y][x]=true; > 89 } > 90 } > 91 } > 92 q = q2; > 93 } > 94 return tuple('W', int.max); > 95 } > 96 > 97 void main(string[] args) > 98 { > 99 auto g = Game.load(File(args[1])); > 100 g.set_output(new GuardedOutput(g)); > 101 > 102 while(!g.dead && !g.cleared) > 103 act(g); > 104 }

Deleted src/Makefile version [01a4f7a0531dae71]

1 # To build, the following packages are needed. < 2 # wget http://ftp.digitalmars.com/dmd_2.059-0_i386.deb < 3 # sudo apt-get install gcc gcc-multilib < 4 # sudo pkg -i dmd_2.059-0_i386.deb < 5 < 6 all: < 7 dmd -O -release -inline -oflifter cui_auto_main.d driver.d game.d output <

Deleted src/cui_auto_main.d version [b38d60ea39d11e6e]

1 import util; < 2 import game; < 3 import output; < 4 import driver; < 5 import solver; < 6 < 7 class CUI(Solver) : GameObserver < 8 { < 9 this(in Game g) { solver = new Solver(g); } < 10 Solver solver; < 11 bool fin; < 12 override void on_game_changed(char c, in Game g, bool finished) < 13 { < 14 fin = finished; < 15 } < 16 } < 17 < 18 void main(string[] args) < 19 { < 20 Driver d = new Driver(stdin); < 21 d.addObserver!(GuardedOutput)(); < 22 auto c = d.addObserver!(CUI!MainSolver)(); < 23 while(!c.fin) < 24 d.command(c.solver.single_step()); < 25 } <

Deleted src/driver.d version [3d15ff20e76164b8]

1 import game; < 2 import util; < 3 < 4 interface GameObserver < 5 { < 6 // this(in Game g); < 7 void on_game_changed(char c, in Game g, bool finished); < 8 } < 9 < 10 class Driver < 11 { < 12 this(Game g) { this.game = g; } < 13 this(File game_data) { this(new Game(game_data)); } < 14 < 15 void command(char c) < 16 { < 17 if( finished ) < 18 return; < 19 if( c == 'A' ) < 20 aborted = true; < 21 else < 22 game.command(c); < 23 foreach(ob; observers) < 24 ob.on_game_changed(c, game, finished); < 25 } < 26 < 27 T addObserver(T)() < 28 { < 29 T t = new T(game); < 30 observers ~= t; < 31 return t; < 32 } < 33 < 34 @property bool finished() < 35 { < 36 return game.cleared || game.dead || aborted; < 37 } < 38 < 39 private: < 40 Game game; < 41 GameObserver[] observers; < 42 bool aborted = false; < 43 } < 44 < 45 unittest < 46 { < 47 static class MockGame : Game { < 48 this() { super(null,null,null); } < 49 string log; < 50 void command(char c) { log ~= c; } < 51 } < 52 static class MockObserver : GameObserver { < 53 string log; < 54 this(in Game g) {} < 55 void on_game_changed(char c, in Game g, bool fin) { log~=c; if(f < 56 } < 57 < 58 auto g = new MockGame; < 59 auto d = new Driver(g); < 60 auto o = d.addObserver!MockObserver(); < 61 foreach(char c; "UDLRSAUDLRSA") < 62 d.command(c); < 63 assert(g.log == "UDLRS"); < 64 assert(o.log == "UDLRSA$"); < 65 } <

Deleted src/game.d version [fc05481901940844]

1 import util; < 2 < 3 //////////////////////////////////////////////////////////////////////////////// < 4 < 5 class Pos < 6 { < 7 public immutable int y, x; < 8 mixin DeriveCreate; < 9 mixin DeriveCompare; < 10 mixin DeriveShow; < 11 Pos clone() const { return cast(Pos) this; } < 12 < 13 @property: < 14 Pos wait() { return this.clone(); } < 15 Pos up() { return new Pos(y+1, x); } < 16 Pos down() { return new Pos(y-1, x); } < 17 Pos left() { return new Pos(y, x-1); } < 18 Pos right() { return new Pos(y, x+1); } < 19 alias wait W,w; < 20 alias up U,u; < 21 alias down D,d; < 22 alias left L,l; < 23 alias right R,r; < 24 } < 25 < 26 unittest < 27 { < 28 assert( (new Pos(2,1)).U == new Pos(3,1) ); < 29 assert( (new Pos(0,1)).D == new Pos(-1,1) ); < 30 assert( (new Pos(2,1)).L == new Pos(2,0) ); < 31 assert( (new Pos(2,1)).R == new Pos(2,2) ); < 32 int[Pos] aa; < 33 aa[new Pos(1,2)] = 1; < 34 aa[new Pos(1,2)] = 2; < 35 aa[new Pos(2,1)] = 3; < 36 assert( aa.length==2 ); < 37 assert( aa[new Pos(1,2)]==2 ); < 38 } < 39 < 40 //////////////////////////////////////////////////////////////////////////////// < 41 < 42 class Water < 43 { < 44 public immutable int base, pace; < 45 mixin DeriveCreate; < 46 mixin DeriveCompare; < 47 mixin DeriveShow; < 48 Water clone() const { return cast(Water)this; } < 49 < 50 static load(string[string] params) < 51 { < 52 return new Water(params.get("Water", "0").to!int(), < 53 params.get("Flooding", "0").to!int()); < 54 } < 55 < 56 int level(int number_of_update) const < 57 { < 58 return pace ? base+(number_of_update/pace) : base; < 59 } < 60 < 61 int until_rise(int number_of_update) const < 62 { < 63 return pace ? pace-number_of_update%pace : int.max; < 64 } < 65 } < 66 < 67 unittest < 68 { < 69 Water w = new Water(1, 3); < 70 assert( 1 == w.level(0) ); < 71 assert( 1 == w.level(1) ); < 72 assert( 1 == w.level(2) ); < 73 assert( 2 == w.level(3) ); < 74 assert( 2 == w.level(4) ); < 75 assert( 2 == w.level(5) ); < 76 assert( 3 == w.level(6) ); < 77 < 78 w = new Water(1, 0); < 79 assert( 1 == w.level(0) ); < 80 assert( 1 == w.level(1) ); < 81 assert( 1 == w.level(2) ); < 82 assert( 1 == w.level(3) ); < 83 assert( 1 == w.level(4) ); < 84 assert( 1 == w.level(5) ); < 85 } < 86 < 87 //////////////////////////////////////////////////////////////////////////////// < 88 < 89 class Hige < 90 { < 91 public immutable int pace; < 92 mixin DeriveCreate; < 93 mixin DeriveCompare; < 94 mixin DeriveShow; < 95 Hige clone() const { return cast(Hige)this; } < 96 < 97 static load(string[string] params) < 98 { < 99 return new Hige(params.get("Growth", "25").to!int()); < 100 } < 101 < 102 bool is_growing_turn(int turn) const < 103 { < 104 return pace ? turn%pace == pace-1 : false; < 105 } < 106 < 107 int until_rise(int turn) const < 108 { < 109 return pace ? pace-turn%pace : int.max; < 110 } < 111 } < 112 < 113 //////////////////////////////////////////////////////////////////////////////// < 114 < 115 class Map < 116 { < 117 mixin DeriveShow; < 118 < 119 static Map load(string[] raw_data, string[string] params, char[char] tra < 120 { < 121 // TODO: choose optimal representation. < 122 return new Map(raw_data, params, trampo); < 123 } < 124 < 125 char[][] data; < 126 Pos robot; < 127 Pos lift; < 128 int waterproof; < 129 Pos[char] tr_target; < 130 Pos[][char] tr_source; < 131 const(Hige) hige; < 132 int razor; < 133 < 134 Map clone() const { return new Map(this); } < 135 this(in Map m) { < 136 foreach(s; m.data) < 137 this.data ~= s.dup; < 138 this.robot = m.robot.clone(); < 139 this.lift = m.lift.clone(); < 140 this.waterproof = m.waterproof; < 141 this.tr_target = cast(Pos[char])m.tr_target; < 142 this.tr_source = cast(Pos[][char])m.tr_source; < 143 this.hige = m.hige.clone(); < 144 this.razor = m.razor; < 145 } < 146 < 147 this(string[] raw_data, string[string] params, char[char] trampo) < 148 { < 149 int width = 0; < 150 foreach(r; raw_data) < 151 width = max(width, r.length); < 152 foreach(r; raw_data) { < 153 this.data ~= r.dup; < 154 this.data[$-1].length = width; < 155 this.data[$-1][r.length..$] = ' '; < 156 } < 157 < 158 for(int y=1; y<=H; ++y) < 159 for(int x=1; x<=W; ++x) { < 160 if(this[y,x] == 'R') < 161 this.robot = new Pos(y,x); < 162 if(this[y,x] == 'L' || this[y,x] == 'O') < 163 this.lift = new Pos(y,x); < 164 } < 165 < 166 Pos[char] tr_pos; < 167 for(int y=1; y<=H; ++y) < 168 for(int x=1; x<=W; ++x) { < 169 char c = this[y,x]; < 170 if('1'<=c && c<='9' || 'A'<=c&&c<='I') < 171 tr_pos[c] = new Pos(y,x); < 172 } < 173 < 174 this.waterproof = params.get("Waterproof", "5").to!int(); < 175 foreach(fr,to; trampo) { < 176 tr_target[fr] = tr_pos[to]; < 177 if(to !in tr_source) tr_source[to] = []; < 178 tr_source[to] ~= tr_pos[fr]; < 179 } < 180 < 181 this.hige = Hige.load(params); < 182 this.razor = params.get("Razors", "0").to!int(); < 183 } < 184 < 185 const @property { < 186 int H() { return data.length; } < 187 int W() { return data[0].length; } < 188 } < 189 < 190 const { < 191 char opIndex(int y, int x) < 192 { < 193 // Adjust coordinate to the spec. bottom-left is (1,1). < 194 --y, --x; < 195 if(y<0||H<=y||x<0||W<=x) < 196 return '#'; < 197 return data[H-1-y][x]; < 198 } < 199 < 200 char opIndex(in Pos p) < 201 { < 202 return this[p.y, p.x]; < 203 } < 204 } < 205 < 206 void opIndexAssign(char c, int y, int x) < 207 { < 208 // Adjust coordinate to the spec. bottom-left is (1,1). < 209 --y, --x; < 210 if(y<0||H<=y||x<0||W<=x) < 211 return; < 212 data[H-1-y][x] = c; < 213 } < 214 < 215 void opIndexAssign(char c, in Pos p) < 216 { < 217 this[p.y, p.x] = c; < 218 } < 219 < 220 Pos[] objects(char c) const { < 221 Pos[] ans; < 222 for(int y=1; y<=H; ++y) < 223 for(int x=1; x<=W; ++x) < 224 if(this[y,x] == c) < 225 ans ~= new Pos(y,x); < 226 return ans; < 227 } < 228 < 229 Pos[] razors() const { return objects('!'); } < 230 Pos[] lambdas() const { return objects('\\'); } < 231 < 232 bool cleared() const < 233 { < 234 for(int y=1; y<=H; ++y) < 235 for(int x=1; x<=W; ++x) < 236 if(this[y,x] == 'L' || this[y,x] == 'O') < 237 return false; < 238 return true; < 239 } < 240 < 241 Tuple!(int,bool) command(char c, int turn) < 242 { < 243 assert( this[robot] == 'R' ); < 244 if(c=='R') return move( 0, +1, turn); < 245 if(c=='L') return move( 0, -1, turn); < 246 if(c=='U') return move(+1, 0, turn); < 247 if(c=='D') return move(-1, 0, turn); < 248 if(c=='W') return move( 0, 0, turn); < 249 if(c=='S') return use_razor(turn); < 250 assert(false); < 251 } < 252 < 253 Tuple!(int, bool) use_razor(int turn) < 254 { < 255 if(razor) { < 256 razor--; < 257 for(int dy=-1; dy<=+1; ++dy) < 258 for(int dx=-1; dx<=+1; ++dx) < 259 if(this[robot.y+dy,robot.x+dx] == 'W') < 260 this[robot.y+dy,robot.x+dx] = ' '; < 261 } < 262 < 263 bool dead = update(turn); < 264 return tuple(0,dead); < 265 } < 266 < 267 Tuple!(int, bool) move(int dy, int dx, int turn) < 268 { < 269 int y = robot.y; < 270 int x = robot.x; < 271 int lambda = 0; < 272 if( '\\' == this[y+dy,x+dx] ) < 273 lambda++; < 274 if( '!' == this[y+dy,x+dx] ) < 275 razor++; < 276 if( " \\!.O".count(this[y+dy,x+dx])==1 ) { < 277 this[y,x]=' '; < 278 this[y+dy,x+dx]='R'; < 279 robot = new Pos(y+dy,x+dx); < 280 } else if(dy==0 && '*'==this[y+dy,x+dx] && ' '==this[y+dy*2,x+dx < 281 this[y,x]=' '; < 282 this[y+dy,x+dx]='R'; < 283 this[y+dy*2,x+dx*2]='*'; < 284 robot = new Pos(y+dy,x+dx); < 285 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') { < 286 this[y,x]=' '; < 287 Pos tp = tr_target[this[y+dy,x+dx]]; < 288 foreach(p; tr_source[this[tp]]) < 289 this[p] = ' '; < 290 this[tp] = 'R'; < 291 robot = tp; < 292 } < 293 bool dead = update(turn); < 294 return tuple(lambda,dead); < 295 } < 296 < 297 bool update(int turn) < 298 { < 299 bool dead = false; < 300 < 301 char[][] next; < 302 foreach(y,s; data) < 303 next ~= s.dup; < 304 < 305 ref char access(Pos p) { return next[H-p.y][p.x-1]; } < 306 < 307 bool lambda = false; < 308 for(int y=1; y<=H; ++y) < 309 for(int x=1; x<=W; ++x) < 310 lambda |= (this[y,x] == '\\'); < 311 < 312 for(int y=1; y<=H; ++y) < 313 for(int x=1; x<=W; ++x) { < 314 Pos p = new Pos(y,x); < 315 if(this[p]=='*') { < 316 if(this[p.D]==' ') { < 317 access(p) =' '; < 318 access(p.D)='*'; < 319 if(robot == p.D.D) < 320 dead=true; < 321 } < 322 else if((this[p.D]=='*' || this[p.D]=='\\') && t < 323 access(p)=' '; < 324 access(p.R.D)='*'; < 325 if(robot == p.R.D.D) < 326 dead=true; < 327 } < 328 else if(this[p.D]=='*' && this[p.L]==' ' && this < 329 access(p)=' '; < 330 access(p.L.D)='*'; < 331 if(robot == p.L.D.D) < 332 dead=true; < 333 } < 334 } < 335 else if(this[p]=='L') { < 336 if(!lambda) < 337 access(p) = 'O'; < 338 } < 339 else if(this[p]=='W') { < 340 if( hige.is_growing_turn(turn) ) < 341 for(int dy=-1; dy<=+1; ++dy) < 342 for(int dx=-1; dx<=+1; ++dx) < 343 if(this[p.y+dy,p.x+dx] == ' ') < 344 access(new Pos(p.y+dy,p. < 345 } < 346 } < 347 data = next; < 348 return dead; < 349 } < 350 } < 351 < 352 //////////////////////////////////////////////////////////////////////////////// < 353 < 354 class Game < 355 { < 356 public: < 357 this(File input) < 358 { < 359 // Read map data < 360 string[] map_data_lines; < 361 for(string line; !(line=input.readln().chomp()).empty; ) < 362 map_data_lines ~= line; < 363 < 364 // H*W < 365 H_ = map_data_lines.length; < 366 W_ = 0; < 367 foreach(mdl; map_data_lines) < 368 W_ = max(W_, mdl.length); < 369 < 370 // Copy to modifiable buffer and adjust coordinates. < 371 raw_data_ = new char[][H_+1]; < 372 foreach(i,mdl; map_data_lines) { < 373 char[] buf = new char[mdl.length+1]; < 374 buf[0] = '#'; < 375 buf[1..$] = mdl[]; < 376 raw_data_[H_-i] = buf; < 377 } < 378 < 379 // Detect objects < 380 for(int y=1; y<=H_; ++y) < 381 for(int x=1; x<raw_data_[y].length; ++x) < 382 { < 383 char c = raw_data_[y][x]; < 384 switch(c) < 385 { < 386 case '#': < 387 case '.': < 388 case ' ': < 389 break; < 390 case 'L': < 391 case 'O': < 392 lift_pos_ = new Pos(y,x); < 393 break; < 394 case 'A': .. case 'I': < 395 case '1': .. case '9': < 396 trampoline_pos_[c] = new Pos(y,x); < 397 break; < 398 case '!': < 399 razor_pos_ ~= new Pos(y,x); < 400 break; < 401 case '\\': < 402 lambda_pos_ ~= new Pos(y,x); < 403 break; < 404 < 405 // Moving objects are erased from raw_data_ < 406 case 'R': < 407 robot_pos_ = new Pos(y,x); < 408 raw_data_[y][x] = ' '; < 409 break; < 410 case '*': < 411 case 'W': < 412 dynamic_objects_[new Pos(y,x)] = c; < 413 raw_data_[y][x] = ' '; < 414 if(c=='*') < 415 may_update_[new Pos(y,x)] = true; < 416 break; < 417 default: < 418 assert(false); < 419 } < 420 } < 421 < 422 // Read other parameters < 423 for(string line; !(line=input.readln()).empty; ) < 424 { < 425 string[] ss = line.split(); < 426 if( ss.length == 2 ) < 427 switch(ss[0]) < 428 { < 429 case "Water": water_base_ = ss[1].to!int(); < 430 case "Flooding": water_pace_ = ss[1].to!int(); < 431 case "Waterproof": max_air_ = ss[1].to!int(); < 432 case "Growth": hige_pace_ = ss[1].to!int(); < 433 case "Razors": num_razor_ = ss[1].to!int(); < 434 default: assert(false); < 435 } < 436 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar < 437 { < 438 char fr=ss[1][0], to=ss[3][0]; < 439 trampoline_[fr] = to; < 440 if(to !in trampoline_rev_) trampoline_rev_[to] = < 441 trampoline_rev_[to] ~= fr; < 442 } < 443 } < 444 < 445 air_left_ = max_air_; < 446 } < 447 < 448 @property const { < 449 int H() { return H_; } < 450 int W() { return W_; } < 451 char trampoline(char c) { return (c in trampoline_ ? trampoline_ < 452 const(Pos)[] trampoline_rev(char c) { < 453 const(Pos)[] pp; < 454 if(c in trampoline_rev_) { < 455 foreach(ch; trampoline_rev_[c]) < 456 pp ~= trampoline_pos_[ch]; < 457 } < 458 return pp; < 459 } < 460 int water_level() { < 461 return water_pace_ ? water_base_ + turn_/water_pace_ : w < 462 } < 463 int water_until_rise() { < 464 return water_pace_ ? water_pace_ - turn_%water_pace_ : i < 465 } < 466 int hige_until_rise() { < 467 return hige_pace_ ? hige_pace_ - turn_%hige_pace_ : int. < 468 } < 469 bool is_hige_turn() { < 470 return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : f < 471 } < 472 int hp() { return air_left_; } < 473 int num_razor() { return num_razor_; } < 474 bool cleared() { return cleared_; } < 475 bool dead() { return dead_; } < 476 long score() { return num_lambda_*(dead_ ? 25L : cleared_ ? 75L < 477 const(Pos) robot() { return robot_pos_; } < 478 const(Pos) lift() { return lift_pos_; } < 479 Pos[] lambdas() { < 480 Pos[] pp; < 481 foreach(p; lambda_pos_) < 482 pp ~= p.clone(); < 483 return pp; < 484 } < 485 Pos[] razors() { < 486 Pos[] pp; < 487 foreach(p; razor_pos_) < 488 pp ~= p.clone(); < 489 return pp; < 490 } < 491 const(Pos)[] higes() { < 492 const(Pos)[] pp; < 493 foreach(p,c; dynamic_objects_) < 494 if(c=='W') < 495 pp ~= p; < 496 return pp; < 497 } < 498 } < 499 const { < 500 char opIndex(in Pos p) { return opIndex(p.y, p.x); } < 501 char opIndex(int y, int x) { return map_get(y, x); } < 502 } < 503 < 504 public: < 505 void command(char c) < 506 { < 507 if(dead || cleared) < 508 return; < 509 < 510 if(c == 'U') command_move(+1, 0); < 511 if(c == 'D') command_move(-1, 0); < 512 if(c == 'L') command_move(0, -1); < 513 if(c == 'R') command_move(0, +1); < 514 if(c == 'S') use_razor(); < 515 if(c == 'W') {} < 516 < 517 if(!cleared) < 518 { < 519 map_update(); < 520 water_update(); < 521 } < 522 turn_ ++; < 523 } < 524 < 525 void command_move(int dy, int dx) < 526 { < 527 int y = robot_pos_.y, x = robot_pos_.x; < 528 char c = this[y+dy, x+dx]; < 529 Pos p = new Pos(y+dy, x+dx); < 530 < 531 switch(c){ < 532 case 'O': < 533 cleared_ = true; < 534 move_robot_to(p); < 535 break; < 536 case '\\': < 537 take_lambda_at(p); < 538 move_robot_to(p); < 539 break; < 540 case '!': < 541 take_razor_at(p); < 542 move_robot_to(p); < 543 break; < 544 case 'A': .. case 'I': < 545 enter_trampoline_at(p, c); < 546 break; < 547 case ' ': < 548 case '.': < 549 move_robot_to(p); < 550 break; < 551 case '*': < 552 if(dy!=0 || this[y,x+dx*2]!=' ') < 553 break; < 554 move_robot_to(p); < 555 push_rock(p, new Pos(y,x+dx*2)); < 556 break; < 557 default: < 558 break; < 559 } < 560 } < 561 < 562 void use_razor() < 563 { < 564 if(num_razor_ == 0) < 565 return; < 566 num_razor_ --; < 567 < 568 for(int dy=-1; dy<=+1; ++dy) < 569 for(int dx=-1; dx<=+1; ++dx) if(dy||dx) < 570 { < 571 Pos p = new Pos(robot_pos_.y+dy, robot_pos_.x+dx); < 572 if(auto it = p in dynamic_objects_) < 573 if(*it == 'W') { < 574 something_gone(p); < 575 dynamic_objects_.remove(p); < 576 } < 577 } < 578 } < 579 < 580 void take_lambda_at(Pos p) < 581 { < 582 map_set_empty(p); < 583 num_lambda_ ++; < 584 lambda_pos_ = lambda_pos_.erase(p); < 585 } < 586 < 587 void take_razor_at(Pos p) < 588 { < 589 map_set_empty(p); < 590 num_razor_ ++; < 591 razor_pos_ = razor_pos_.erase(p); < 592 } < 593 < 594 void enter_trampoline_at(Pos p, char c) < 595 { < 596 char d = trampoline(c); < 597 foreach(cc; trampoline_rev_[d]) { < 598 Pos pp = trampoline_pos_[cc]; < 599 something_gone(pp); < 600 map_set_empty(pp); < 601 } < 602 move_robot_to(trampoline_pos_[d]); < 603 } < 604 < 605 void move_robot_to(Pos p) < 606 { < 607 something_gone(robot_pos_); < 608 map_set_empty(p.y, p.x); < 609 robot_pos_ = p; < 610 } < 611 < 612 void push_rock(Pos fr, Pos to) < 613 { < 614 dynamic_objects_.remove(fr); < 615 dynamic_objects_[to] = '*'; < 616 may_update_[to] = true; < 617 } < 618 < 619 void something_gone(Pos p) < 620 { < 621 for(int dy=0; dy<=+1; ++dy) < 622 for(int dx=-1; dx<=+1; ++dx) if(dy||dx) < 623 may_update_[new Pos(p.y+dy,p.x+dx)] = true; < 624 } < 625 < 626 void map_update() < 627 { < 628 Pos[] may_update_list; < 629 foreach(p,_; may_update_) < 630 if(this[p] == '*') < 631 may_update_list ~= p; < 632 may_update_ = null; < 633 < 634 if( is_hige_turn() ) < 635 foreach(p,c; dynamic_objects_) < 636 if(c == 'W') < 637 may_update_list ~= p; < 638 < 639 sort(may_update_list); < 640 char[Pos] to_be_written; < 641 foreach(p; may_update_list) < 642 if(is_hige_turn() && this[p]=='W') < 643 { < 644 for(int dy=-1; dy<=+1; ++dy) < 645 for(int dx=-1; dx<=+1; ++dx) { < 646 Pos q = new Pos(p.y+dy,p.x+dx); < 647 if( this[q] == ' ' ) < 648 to_be_written[q] = 'W'; < 649 } < 650 } < 651 else < 652 { < 653 int y = p.y; < 654 int x = p.x; < 655 char below = this[y-1,x]; < 656 // * < 657 // _ < 658 if(below==' ') { < 659 Pos q = new Pos(y-1,x); < 660 to_be_written[p] = ' '; < 661 to_be_written[q] = '*'; < 662 may_update_[q] = true; < 663 } < 664 // *_ *_ < 665 // *_ or \_ < 666 else if((below=='*'||below=='\\')&&this[y-1,x+1] < 667 Pos q = new Pos(y-1,x+1); < 668 to_be_written[p] = ' '; < 669 to_be_written[q] = '*'; < 670 may_update_[q] = true; < 671 } < 672 // _* < 673 // _* < 674 else if(below=='*'&&this[y-1,x-1]==' '&&this[y,x < 675 Pos q = new Pos(y-1,x-1); < 676 to_be_written[p] = ' '; < 677 to_be_written[q] = '*'; < 678 may_update_[q] = true; < 679 } < 680 } < 681 < 682 foreach(p,c; to_be_written) { < 683 dynamic_objects_[p] = c; < 684 if(c=='*' && p.y==robot_pos_.y+1 && p.x==robot_pos_.x) < 685 dead_ = true; < 686 } < 687 < 688 if(lambda_pos_.empty) < 689 raw_data_[lift_pos_.y][lift_pos_.x] = 'O'; < 690 } < 691 < 692 void water_update() < 693 { < 694 if( robot_pos_.y <= water_level() ) < 695 air_left_ --; < 696 else < 697 air_left_ = max_air_; < 698 if( air_left_ < 0 ) < 699 dead_ = true; < 700 } < 701 < 702 private: < 703 char map_get(int y, int x) const < 704 { < 705 if( y<1 || H<y || x<1 || W<x ) return '#'; < 706 Pos p = new Pos(y,x); < 707 if(p == robot_pos_) < 708 return 'R'; < 709 if(auto it = (p in dynamic_objects_)) < 710 return *it; < 711 if( x<0 || raw_data_[y].length<=x ) return ' '; < 712 return raw_data_[y][x]; < 713 } < 714 < 715 void map_set_empty(in Pos p) < 716 { < 717 return map_set_empty(p.y, p.x); < 718 } < 719 < 720 void map_set_empty(int y, int x) < 721 { < 722 if( y<1 || H<y || x<1 || W<x ) return; < 723 if( x<0 || raw_data_[y].length<=x ) return; < 724 raw_data_[y][x] = ' '; < 725 } < 726 < 727 public: < 728 Game clone() const { return new Game(this); } < 729 this(in Game g) { < 730 H_ = g.H_; < 731 W_ = g.W_; < 732 raw_data_ = new char[][g.raw_data_.length]; < 733 foreach(i,d; g.raw_data_) raw_data_[i] = d.dup; < 734 trampoline_pos_ = cast(Pos[char]) g.trampoline_pos_; < 735 razor_pos_ = (cast(Game)g).razor_pos_.dup; < 736 lambda_pos_ = (cast(Game)g).lambda_pos_.dup; < 737 lift_pos_ = g.lift_pos_.clone(); < 738 robot_pos_ = g.robot_pos_.clone(); < 739 dynamic_objects_ = dup(g.dynamic_objects_); < 740 trampoline_ = (cast(Game)g).trampoline_; < 741 trampoline_rev_ = (cast(Game)g).trampoline_rev_; < 742 water_base_ = g.water_base_; < 743 water_pace_ = g.water_pace_; < 744 max_air_ = g.max_air_; < 745 hige_pace_ = g.hige_pace_; < 746 num_razor_ = g.num_razor_; < 747 num_lambda_ = g.num_lambda_; < 748 turn_ = g.turn_; < 749 air_left_ = g.air_left_; < 750 cleared_ = g.cleared_; < 751 dead_ = g.dead_; < 752 may_update_ = dup(g.may_update_); < 753 } < 754 < 755 V[K] dup(V,K)(in V[K] aa) { < 756 V[K] aa2; < 757 foreach(k,v; aa) aa2[k] = v; < 758 return aa2; < 759 } < 760 < 761 private: < 762 int H_; < 763 int W_; < 764 char[][] raw_data_; < 765 Pos[char] trampoline_pos_; < 766 Pos[] razor_pos_; < 767 Pos[] lambda_pos_; < 768 Pos lift_pos_; < 769 Pos robot_pos_; < 770 char[Pos] dynamic_objects_; < 771 char[char] trampoline_; < 772 char[][char] trampoline_rev_; < 773 int water_base_ = 0; < 774 int water_pace_ = 0; < 775 int max_air_ = 10; < 776 int hige_pace_ = 25; < 777 int num_razor_ = 0; < 778 int num_lambda_ = 0; < 779 < 780 int turn_ = 0; < 781 int air_left_ = 0; < 782 bool cleared_ = false; < 783 bool dead_ = false; < 784 bool[Pos] may_update_; < 785 } <

Deleted src/gui.d version [e84cacd6262f93a7]

1 import dfl.all; < 2 import util; < 3 import game; < 4 import driver; < 5 < 6 class GUI(Solver) : Form, GameObserver < 7 { < 8 this(in Game g) < 9 { < 10 this.solver = new Solver(g); < 11 setup_size(g.W, g.H); < 12 setup_resources(g); < 13 draw(g); < 14 } < 15 < 16 private void delegate(char c) fn; < 17 void set_fn(F)(F f) { this.fn = f; } < 18 < 19 void run(bool automate = false) < 20 { < 21 if(automate) { < 22 Timer t = new Timer; < 23 t.interval = 50; < 24 t.tick ~= (Timer sender, EventArgs ea){ < 25 fn(solver.single_step()); < 26 }; < 27 t.start(); < 28 this.closing ~= (Form f,CancelEventArgs c){t.stop();}; < 29 } else { < 30 setup_keyhandling(); < 31 } < 32 Application.run(this); < 33 } < 34 < 35 override void on_game_changed(char c, in Game g, bool finished) < 36 { < 37 draw(g); < 38 } < 39 < 40 private: < 41 int cell; < 42 < 43 void setup_size(int W, int H) < 44 { < 45 this.formBorderStyle = FormBorderStyle.FIXED_DIALOG; < 46 this.maximizeBox = false; < 47 this.minimizeBox = false; < 48 this.cell = min(1024/W, 640/H); < 49 this.clientSize = Size(W*cell, H*cell); < 50 } < 51 < 52 Font font; < 53 Color[char] colors; < 54 string[char] render; < 55 Graphics graphicContext; < 56 < 57 void setup_resources(in Game g) < 58 { < 59 this.graphicContext = new MemoryGraphics(this.clientSize.width, < 60 this.setStyle(ControlStyles.OPAQUE, true); < 61 this.font = new Font("MS Gothic", cell-2, GraphicsUnit.PIXEL); < 62 this.backColor = Color(255,255,255); < 63 this.colors['#'] = < 64 this.colors['.'] = Color(255,191,127); < 65 this.colors['*'] = Color(255,127,127); < 66 this.colors['R'] = Color(128,128,0); < 67 this.colors['d'] = Color(255,0,0); < 68 this.colors['\\'] = < 69 this.colors['L'] = < 70 this.colors['O'] = Color(127,255,127); < 71 this.colors['w'] = Color(204,229,255); < 72 this.colors['W'] = < 73 this.colors['!'] = Color(159,159,159); < 74 foreach(char c; 'A'..'J') this.colors[c] = Color(142,142,255); < 75 foreach(char c; '1'..':') this.colors[c] = Color(255,142,255); < 76 this.render['#'] = "■"; < 77 this.render['*'] = "✹"; < 78 this.render['.'] = "♒"; < 79 this.render['\\'] = "λ"; < 80 this.render['R'] = "☃"; < 81 this.render['d'] = "☠"; < 82 this.render['L'] = "☒"; < 83 this.render['O'] = "☐"; < 84 this.render['W'] = "ꔣ"; < 85 this.render['!'] = "✄"; < 86 foreach(char c; 'A'..'J') this.render[c] = [cast(dchar)('☢'+g.tr < 87 foreach(char c; '1'..':') this.render[c] = [cast(dchar)('☢'+c-'1 < 88 this.paint ~= (Control c, PaintEventArgs ev) { < 89 graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientS < 90 }; < 91 } < 92 < 93 void draw(in Game g) < 94 { < 95 int scrW = this.clientSize.width; < 96 int scrH = this.clientSize.height; < 97 < 98 // Fill bg. < 99 graphicContext.fillRectangle(this.backColor, Rect(0,0,scrW,scrH) < 100 < 101 // Fill water. < 102 int w = g.water_level(); < 103 graphicContext.fillRectangle(this.colors['w'], Rect(0, scrH-cell < 104 < 105 // Paint map. < 106 for(int y=1; y<=g.H; ++y) < 107 for(int x=1; x<=g.W; ++x) { < 108 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); < 109 char c = g[y,x]; < 110 if( c != ' ' ) { < 111 if( c == 'R' && g.dead ) < 112 c = 'd'; < 113 graphicContext.drawText(this.render[c], font, th < 114 } < 115 } < 116 < 117 // Update textual info. < 118 this.text = .text( < 119 "Score: ", g.score, < 120 " Air: ", g.hp, < 121 " Tide: ", g.water_until_rise, < 122 " Wadler: ", g.hige_until_rise, < 123 " Razor: ", g.num_razor); < 124 invalidate(); < 125 } < 126 < 127 private: < 128 void setup_keyhandling() < 129 { < 130 noMessageFilter(); < 131 this.keyDown ~= &my_keydown; < 132 } < 133 < 134 void do_manual_command(char c) < 135 { < 136 solver.force(c); < 137 fn(c); < 138 } < 139 < 140 void my_keydown(Control c, KeyEventArgs ev) < 141 { < 142 switch(ev.keyCode) < 143 { < 144 case Keys.DOWN: do_manual_command('D'); break; < 145 case Keys.UP: do_manual_command('U'); break; < 146 case Keys.LEFT: do_manual_command('L'); break; < 147 case Keys.RIGHT: do_manual_command('R'); break; < 148 case Keys.W: do_manual_command('W'); break; < 149 case Keys.S: do_manual_command('S'); break; < 150 case Keys.A: do_manual_command('A'); break; < 151 case Keys.G: fn(solver.single_step()); break; < 152 default: break; < 153 } < 154 } < 155 < 156 Solver solver; < 157 } <

Deleted src/gui_main.d version [05082d0f328d756c]

1 import gui; < 2 import output; < 3 import driver; < 4 import solver; < 5 import std.stdio; < 6 pragma(lib, "dfl.lib"); < 7 < 8 void main(string[] args) < 9 { < 10 Driver d = new Driver(stdin); < 11 d.addObserver!(GuardedOutput)(); < 12 auto g = d.addObserver!(GUI!MainSolver)(); < 13 g.set_fn(&d.command); < 14 g.run(); < 15 } <

Deleted src/output.d version [e2d0d7db868c3a44]

1 import util; < 2 import game; < 3 import driver; < 4 import core.stdc.signal; < 5 < 6 class NilOutput : GameObserver < 7 { < 8 this(in Game g) {} < 9 override void on_game_changed(char c, in Game g, bool finished) {} < 10 } < 11 < 12 class StdOutput : GameObserver < 13 { < 14 this(in Game g) {} < 15 override void on_game_changed(char c, in Game g, bool finished) < 16 { < 17 stdout.write(c); < 18 stdout.flush(); < 19 } < 20 } < 21 < 22 class GuardedOutput : GameObserver < 23 { < 24 this(in Game g) < 25 { < 26 setup_sigint_handling(); < 27 score_log ~= g.score; < 28 flushed = false; < 29 } < 30 < 31 override void on_game_changed(char c, in Game g, bool finished) < 32 { < 33 if(flushed) < 34 return; < 35 < 36 log ~= c; < 37 score_log ~= g.score; < 38 if(finished || log.length+1==g.W*g.H) < 39 flush(); < 40 } < 41 < 42 private: < 43 string log; < 44 long[] score_log; < 45 bool flushed; < 46 < 47 void flush() < 48 { < 49 if(flushed) < 50 return; < 51 < 52 Tuple!(long, int) cand; < 53 cand[0] = long.min; < 54 < 55 for(int i=0; i<score_log.length; ++i) < 56 if(cand[0] < score_log[i]) < 57 cand = tuple(score_log[i],i); < 58 < 59 std.c.stdio.printf("%.*sA\n", cand[1], log.ptr); < 60 std.c.stdio.fflush(std.c.stdio.stdout); < 61 flushed = true; < 62 } < 63 < 64 private: < 65 static __gshared GuardedOutput g_output; < 66 < 67 void setup_sigint_handling() < 68 { < 69 assert(g_output is null); < 70 g_output = this; < 71 extern(C) static void catch_sigint(int) { g_output.flush(); appl < 72 core.stdc.signal.signal(SIGINT, &catch_sigint); < 73 } < 74 } <

Deleted src/solver.d version [22c356ff1975e92f]

1 import util; < 2 import game; < 3 < 4 class Solver_0 < 5 { < 6 this(in Game g) {} < 7 char single_step() { return 'W'; } < 8 void force(char c) {} < 9 } < 10 < 11 class Solver_1 < 12 { < 13 int wait_count = 0; < 14 int choke_count = 0; < 15 < 16 Game g; < 17 this(in Game g) < 18 { < 19 this.g = g.clone(); < 20 forbidden_cell = new bool[][](g.H+2, g.W+2); < 21 } < 22 < 23 char single_step() < 24 { < 25 Tuple!(string,int) de = death_move(g); < 26 char c = act(g, de[0], de[1]); < 27 force(c); < 28 return c; < 29 } < 30 < 31 void force(char c) < 32 { < 33 if(c != 'A') < 34 g.command(c); < 35 } < 36 < 37 Tuple!(string,int) death_move(const(Game) g) < 38 { < 39 string death; < 40 int choice = 0; < 41 foreach(char c; "UDLRW") { < 42 Game gg = g.clone(); < 43 gg.command(c); < 44 if( !gg.cleared && gg.dead ) < 45 death ~= c; < 46 else if( gg.robot != g.robot ) < 47 choice++; < 48 else if( c != 'W' ) // meaningless move < 49 death ~= c; < 50 } < 51 return tuple(death, choice); < 52 } < 53 < 54 Tuple!(Pos, int)[] log; < 55 bool[][] forbidden_cell; < 56 < 57 char act(const(Game) g, string death, int breath) < 58 { < 59 const Pos ro = g.robot; < 60 const Pos li = g.lift; < 61 Pos[] la = g.lambdas(); < 62 sort!((Pos a,Pos b){ < 63 int ad=abs(a.y-li.y)+abs(a.x-li.x); < 64 int bd=abs(b.y-li.y)+abs(b.x-li.x); < 65 return ad>bd;; < 66 })(la); < 67 Pos[] ra = g.razors(); < 68 const(Pos)[] hi = g.higes(); < 69 < 70 Tuple!(char,int)[] cand; < 71 char c = 'W'; < 72 if( la.empty ) { < 73 cand = search(g, ro, [li], death); < 74 } else { < 75 cand ~= search(g, ro, la~ra, death); < 76 } < 77 < 78 // 'higesori' mode < 79 if( !hi.empty && g.num_razor>0 ) { < 80 int his = 0; < 81 for(int dy=-1; dy<=+1; ++dy) < 82 for(int dx=-1; dx<=+1; ++dx) < 83 if(g[ro.y+dy,ro.x+dx] == 'W') < 84 his++; < 85 < 86 if(his>=2 || his==hi.length) < 87 cand = [tuple('S',int.max)]; < 88 if(cand.empty) { < 89 const(Pos)[] tgt; < 90 for(int y=1; y<=g.H; ++y) < 91 for(int x=1; x<=g.W; ++x) < 92 if(g[y,x]=='.'||g[y,x]==' ') { < 93 his = 0; < 94 for(int dy=-1; dy<=+1; ++dy) < 95 for(int dx=-1; dx<=+1; ++dx) < 96 if(g[y+dy,x+dx] == 'W') < 97 his++; < 98 if(his>=2) < 99 tgt ~= new Pos(y,x); < 100 } < 101 cand ~= search(g, ro, tgt, death, true); < 102 } < 103 } < 104 < 105 // 'dig' mode < 106 if(cand.empty) { < 107 const(Pos)[] tgt; < 108 for(int y=1; y<=g.H; ++y) < 109 for(int x=1; x<=g.W; ++x) < 110 if(g[y,x]=='.') < 111 if(g[y+1,x]=='*'||g[y+1,x-1]=='*'||g[y+1 < 112 ||g[y,x+1]=='*'||g[y,x-1]=='*') < 113 tgt ~= new Pos(y,x); < 114 cand ~= search(g, ro, tgt, death, true); < 115 } < 116 < 117 if(cand.empty) { < 118 choke_count++; < 119 cand ~= tuple('W',int.max); < 120 } < 121 sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ < 122 if(c1[1] != c2[1]) < 123 return c1[1] < c2[1]; < 124 return c1[0] < c2[0]; < 125 })(cand); < 126 c = cand[0][0]; < 127 < 128 if(death.count(c) || wait_count>=2) { < 129 foreach(char live; "UDLRW") < 130 if(death.count(live)==0) { < 131 c=live; < 132 break; < 133 } < 134 } < 135 < 136 if(c == 'W') < 137 wait_count++; < 138 else < 139 wait_count = 0; < 140 if(choke_count >= g.H) < 141 c = 'A'; < 142 < 143 bool[char] choice; < 144 foreach(t; cand) < 145 choice[t[0]] = true; < 146 log ~= tuple(ro.clone(), cast(int)choice.length); < 147 if(log.length > 5) < 148 log = log[$-5..$]; < 149 int cnt = 0; < 150 foreach(l; log) < 151 if(l[0] == log[$-1][0]) < 152 ++cnt; < 153 if( cnt >= 3 && breath==1 ) { < 154 forbidden_cell[ro.y][ro.x] = true; < 155 } < 156 < 157 return c; < 158 } < 159 < 160 Tuple!(char,int)[] search(in Game g, in Pos s, in Pos[] gs, string death < 161 { < 162 bool danger(int y, int x) < 163 { < 164 if(g[y,x] == ' ' || g[y,x] == 'R') < 165 return false; < 166 if(g[y+1,x] == '*') < 167 return true; < 168 if(g[y+1,x-1]=='*' && (g[y,x-1]=='\\'||g[y,x-1]=='*') && < 169 return true; < 170 if(g[y+1,x+1]=='*' && (g[y,x+1]=='*') && (g[y+1,x]==' '| < 171 return true; < 172 if(g[y,x-1]=='*' && (g[y-1,x-1]=='\\'||g[y-1,x-1]=='*') < 173 return true; < 174 if(g[y,x+1]=='*' && (g[y-1,x+1]=='*') && (g[y-1,x]==' '| < 175 return true; < 176 return false; < 177 } < 178 < 179 // avoid directly below '*' < 180 Tuple!(char,int)[] tryA() { < 181 const(Pos)[] q; < 182 foreach(p; gs) < 183 if(!danger(p.y,p.x)) < 184 q ~= p; < 185 bool[][] v = new bool[][](g.H+2, g.W+2); < 186 foreach(p; q) v[p.y][p.x]=true; < 187 for(int step=1; q.length; ++step) { < 188 Pos[] q2; < 189 foreach(p; q) { < 190 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; < 191 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; < 192 for(int i=0; i<yyy.length; ++i) { < 193 int y = yyy[i]; < 194 int x = xxx[i]; < 195 if('1'<=g[y,x]&&g[y,x]<='9') { < 196 foreach(ppp; g.trampolin < 197 yyy ~= ppp.y; < 198 xxx ~= ppp.x; < 199 } < 200 continue; < 201 } < 202 if(v[y][x]) continue; < 203 if(y==s.y && x==s.x && i<4) { < 204 char c = "UDRL"[i]; < 205 if( death.count(c) == 0 < 206 return [tuple(c, < 207 } else if(forbidden_cell[y][x]){ < 208 } else if(g[y,x]==' '||g[y,x]==' < 209 if(danger(y,x)) < 210 continue; < 211 q2 ~= new Pos(y,x); < 212 v[y][x]=true; < 213 } < 214 } < 215 } < 216 q = q2; < 217 } < 218 return []; < 219 } < 220 < 221 // any empty space is my ground < 222 Tuple!(char,int)[] tryB() { < 223 const(Pos)[] q; < 224 foreach(p; gs) q ~= p; < 225 bool[][] v = new bool[][](g.H+2, g.W+2); < 226 foreach(p; q) v[p.y][p.x]=true; < 227 for(int step=10; q.length; ++step) { < 228 Pos[] q2; < 229 foreach(p; q) { < 230 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; < 231 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; < 232 for(int i=0; i<yyy.length; ++i) { < 233 int y = yyy[i]; < 234 int x = xxx[i]; < 235 if('1'<=g[y,x]&&g[y,x]<='9') { < 236 foreach(ppp; g.trampolin < 237 yyy ~= ppp.y; < 238 xxx ~= ppp.x; < 239 } < 240 continue; < 241 } < 242 if(v[y][x]) continue; < 243 if(y==s.y && x==s.x && i<4) { < 244 char c = "UDRL"[i]; < 245 if( death.count(c) == 0 < 246 return [tuple(c, < 247 } else if(forbidden_cell[y][x]){ < 248 } else if(g[y,x]==' '||g[y,x]==' < 249 q2 ~= new Pos(y,x); < 250 v[y][x]=true; < 251 } < 252 } < 253 } < 254 q = q2; < 255 } < 256 return []; < 257 } < 258 < 259 // push rocks! < 260 Tuple!(char,int)[] tryC() { < 261 const(Pos)[] q; < 262 foreach(p; gs) q ~= p; < 263 bool[][] v = new bool[][](g.H+2, g.W+2); < 264 foreach(p; q) v[p.y][p.x]=true; < 265 for(int step=20; q.length; ++step) { < 266 Pos[] q2; < 267 foreach(p; q) { < 268 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; < 269 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; < 270 for(int i=0; i<yyy.length; ++i) { < 271 int y = yyy[i]; < 272 int x = xxx[i]; < 273 if(g[p] == '*') { < 274 if(i>=4)continue; < 275 if(y!=p.y)continue; < 276 if(g[y,p.x+(p.x-x)]!=' ' < 277 } < 278 if('1'<=g[y,x]&&g[y,x]<='9') { < 279 foreach(ppp; g.trampolin < 280 yyy ~= ppp.y; < 281 xxx ~= ppp.x; < 282 } < 283 continue; < 284 } < 285 if(v[y][x]) continue; < 286 if(y==s.y && x==s.x && i<4) { < 287 char c = "UDRL"[i]; < 288 if( death.count(c) == 0 < 289 return [tuple(c, < 290 } else if(forbidden_cell[y][x]){ < 291 } else if(g[y,x]==' '||g[y,x]==' < 292 q2 ~= new Pos(y,x); < 293 v[y][x]=true; < 294 } < 295 } < 296 } < 297 q = q2; < 298 } < 299 return []; < 300 } < 301 return (danger_ok ? [] : tryA()) ~ tryB() ~ tryC(); < 302 } < 303 } < 304 < 305 class Solver_2(Solver) < 306 { < 307 string plan; < 308 bool plan_broken = true; < 309 < 310 Game g; < 311 this(in Game g) < 312 { < 313 this.g = g.clone(); < 314 make_plan(g); < 315 } < 316 < 317 Tuple!(Solver,string) run_sub_solver(in Game g) < 318 { < 319 string log; < 320 auto s = new Solver(g); < 321 while(!g.cleared && !g.dead && plan.length<=g.H*g.W) { < 322 char c = s.single_step(); < 323 if( c == 'A' ) < 324 break; < 325 log ~= c; < 326 } < 327 while(log.length>0 && log[$-1]=='W') < 328 log.length--; < 329 return tuple(s, log); < 330 } < 331 < 332 void make_plan(in Game g) { < 333 plan_broken = false; < 334 Tuple!(Solver,string) x = run_sub_solver(g); < 335 plan = x[1]; < 336 if(x[0].g.cleared) < 337 return; < 338 modify_plan(g, x[0].g.score); < 339 } < 340 < 341 void modify_plan(in Game ini, long unmod) < 342 { < 343 int bp = max(0, (cast(int)plan.length)-10); < 344 Game g = ini.clone(); < 345 for(int i=0; i<bp; ++i) g.command(plan[i]); < 346 < 347 Tuple!(string,long) cand = tuple(plan, unmod); < 348 for(int i=bp; i<plan.length; ++i) { < 349 foreach(string c; ["U","D","L","R","UD","DU","LR","RL"]) < 350 if(c[0] != plan[i]) { < 351 Tuple!(string,long) zz = try_plan(c, g); < 352 if(cand[1]<zz[1]) < 353 cand = tuple(plan[0..i]~c~zz[0], < 354 } < 355 g.command(plan[i]); < 356 } < 357 plan = cand[0]; < 358 } < 359 < 360 Tuple!(string,long) try_plan(string c, in Game g) < 361 { < 362 Game gg = g.clone(); < 363 foreach(cc;c)gg.command(cc); < 364 Tuple!(Solver, string) x = run_sub_solver(gg); < 365 return tuple(x[1], x[0].g.score); < 366 } < 367 < 368 char single_step() { < 369 if(plan_broken) < 370 make_plan(g); < 371 if(plan.empty) < 372 return 'A'; < 373 char c = plan[0]; < 374 plan = plan[1..$]; < 375 g.command(c); < 376 return c; < 377 } < 378 < 379 void force(char c) { < 380 g.command(c); < 381 if(plan.length==0 || plan[0]!=c) { < 382 plan = ""; < 383 plan_broken = true; < 384 } < 385 else < 386 plan = plan[1..$]; < 387 } < 388 } < 389 < 390 alias Solver_2!(Solver_1) MainSolver; < 391 //alias Solver_1 MainSolver; <

Deleted src/util.d version [b76be1f6ad977d56]

1 public import std.algorithm; < 2 public import std.array; < 3 public import std.conv; < 4 public import std.range; < 5 public import std.stdio; < 6 public import std.string; < 7 public import std.typecons; < 8 public import std.math; < 9 import std.c.stdlib; < 10 < 11 T[] erase(T,V)(T[] xs, V y) < 12 { < 13 foreach(i,x; xs) < 14 if(x == y) < 15 return xs[0..i]~xs[i+1..$]; < 16 return xs; < 17 } < 18 < 19 // To avoide the following ICE: < 20 // src\phobos\std\algorithm.d(4552): < 21 // Error: function std.algorithm.count!("a == b",string,char).count < 22 // compiler error, parameter 'value', bugzilla 2962? < 23 // Assertion failure: '0' on line 717 in file 'glue.c' < 24 int count(T,V)(T[] a, V v) < 25 { < 26 int cnt = 0; < 27 foreach(e; a) < 28 if(e == v) < 29 ++cnt; < 30 return cnt; < 31 } < 32 < 33 void application_exit() < 34 { < 35 std.c.stdlib.exit(0); < 36 } < 37 < 38 template DeriveCreate() < 39 { < 40 this(TS...)(TS params) < 41 { < 42 this.tupleof = params; < 43 } < 44 } < 45 < 46 template DeriveCompare() < 47 { < 48 override: < 49 bool opEquals(Object rhs) const < 50 { < 51 return tuple(this.tupleof) == tuple((cast(typeof(this))rhs).tupl < 52 } < 53 < 54 int opCmp(Object rhs) const < 55 { < 56 return tuple(this.tupleof).opCmp(tuple((cast(typeof(this))rhs).t < 57 } < 58 < 59 hash_t toHash() const < 60 { < 61 hash_t v = 0; < 62 foreach(mem; this.tupleof) { < 63 v *= 11; < 64 static if(__traits(compiles, v^=mem)) < 65 v ^= mem; < 66 else < 67 v ^= typeid(mem).getHash(&mem); < 68 } < 69 return v; < 70 } < 71 } < 72 < 73 template DeriveShow() < 74 { < 75 override: < 76 string toString() const < 77 { < 78 string str = text(typeof(this).stringof, "("); < 79 foreach(i,mem; this.tupleof) { < 80 if(i) str ~= ", "; < 81 str = text(str, this.tupleof[i].stringof[5..$], ":", me < 82 } < 83 return str ~ ")"; < 84 } < 85 } <

Deleted submission/PACKAGES version [da39a3ee5e6b4b0d]

Deleted submission/README version [9ce063855f41ff05]

1 Team: < 2 Dark Integers < 3 Member: < 4 Kazuhiro Inaba (www.kmonos.net / kiki@kmonos.net) < 5 Language: < 6 D Programming Language (dlang.org) < 7 < 8 This submission for lightning division is not particulary interseting. < 9 < 10 - Robot rushes to the nearest lambda (or the open lift) by breadth first search. < 11 - Not at all taking into account the dynamics (falling rocks, floods). < 12 - To mitigate the staticness, the robot avoids the '.' below '*' as much as < 13 possible, so that it won't fall new rocks. < 14 < 15 - Output routine is 'guarded' by a 'sudden death' or 'stray sheep' detector. < 16 That is, if the above search routine was hit by a rock or a water, or it < 17 couldn't find a way to the next target and walked in vain, the output guards < 18 trims the command history and inserts the 'A'bort at the optimal timing. < 19 This is also used for SIGINT handling. < 20 < 21 - gui.d is a windows GUI for the game, using DFL (http://github.com/Rayerd/dfl) < 22 it is not compiled into the submitted routine. This is just a helper. < 23 < 24 Stay tuned for the full submission, judges! <

Deleted submission/install version [be776bcfbc13fcbf]

1 #!/bin/sh < 2 echo "Hello, world" <

Deleted submission/lifter version [5103f55f5323fb3f]

cannot compute difference between binary files

Added test.d version [d9955daaabe58d54]

> 1 import std.algorithm; > 2 import std.array; > 3 import std.conv; > 4 import std.stdio; > 5 import std.string; > 6 import std.typecons; > 7 import core.stdc.signal; > 8 import core.stdc.stdlib; > 9 import dfl.all; > 10 > 11 class Map > 12 { > 13 private char[][] data; > 14 bool dead = false; > 15 bool cleared = false; > 16 int water = 0; > 17 int flooding = 0; > 18 int water_proof = 10; > 19 int underwater = 0; > 20 int flooding_counter = 0; > 21 > 22 this(File input) > 23 { > 24 string line; > 25 while( (line=input.readln().chomp()).length ) > 26 data ~= line.dup; > 27 > 28 int width = 0; > 29 foreach(s; data) > 30 width = max(width, s.length); > 31 > 32 // space padding and sentinels > 33 foreach(ref s; data) { > 34 int p = s.length; > 35 s.length = width; > 36 s[p..$] = ' '; > 37 s = '#' ~ s ~ '#'; > 38 } > 39 > 40 // vertical sentinel > 41 char[] sen = new char[width+2]; > 42 sen[] = '#'; > 43 data = sen.dup ~ data ~ sen; > 44 > 45 // flooding > 46 water = H-1; > 47 while( (line=input.readln()).length ) { > 48 string[] ss = line.split(); > 49 if(ss.length==2 && ss[0]=="Water") > 50 water = H-1 - ss[1].to!int(); > 51 else if(ss.length==2 && ss[0]=="Flooding") > 52 flooding = ss[1].to!int(); > 53 else if(ss.length==2 && ss[0]=="Waterproof") > 54 water_proof = ss[1].to!int(); > 55 } > 56 } > 57 > 58 @property const > 59 { > 60 int W() { return data[0].length; } > 61 int H() { return data.length; } > 62 string toString() { > 63 string result; > 64 foreach(i,s; data) { > 65 if(i) result ~= '\n'; > 66 result ~= s.idup; > 67 } > 68 return result; > 69 } > 70 } > 71 > 72 int command_R() { if(dead)return 0; write("R"); return move(0, +1); } > 73 int command_L() { if(dead)return 0; write("L"); return move(0, -1); } > 74 int command_U() { if(dead)return 0; write("U"); return move(-1, 0); } > 75 int command_D() { if(dead)return 0; write("D"); return move(+1, 0); } > 76 int wait() { if(dead)return 0; update(); write("W"); return -1; } > 77 int abort() { if(dead)return 0; cleared=true; write("A"); return gained* > 78 > 79 int move(int dy, int dx) { > 80 foreach(y,s; data) > 81 foreach(x,c; s) > 82 if(c == 'R') > 83 return move(dy, dx, y, x); > 84 assert(false); > 85 } > 86 > 87 int gained = 0; // TODO: atode naosu > 88 int move(int dy, int dx, int y, int x) { > 89 if(dead) > 90 return 0; > 91 int score = 0; > 92 if(data[y+dy][x+dx]=='\\') { > 93 score += 25; > 94 ++gained; > 95 } > 96 if(data[y+dy][x+dx]=='O') { > 97 score += gained*50; > 98 cleared = true; > 99 } > 100 > 101 if(data[y+dy][x+dx]==' ' || data[y+dy][x+dx]=='.' > 102 || data[y+dy][x+dx]=='\\' || data[y+dy][x+dx]=='O') { > 103 data[y][x]=' '; > 104 data[y+dy][x+dx]='R'; > 105 } else if(dy==0 && data[y+dy][x+dx]=='*' && data[y+2*dy][x+2*dx] > 106 data[y][x]=' '; > 107 data[y+dy][x+dx]='R'; > 108 data[y+2*dy][x+2*dx]='*'; > 109 } > 110 update(); > 111 return score-1; > 112 } > 113 > 114 void update() { > 115 char[][] next; > 116 foreach(y,s; data) > 117 next ~= s.dup; > 118 > 119 bool lambda = false; > 120 for(int y=1; y+1<H; ++y) > 121 for(int x=1; x+1<W; ++x) > 122 lambda |= (data[y][x] == '\\'); > 123 > 124 for(int y=H-2; y>=1; --y) > 125 for(int x=1; x+1<W; ++x) { > 126 if(data[y][x]=='*') { > 127 if(data[y+1][x]==' ') { > 128 next[y][x]=' '; > 129 next[y+1][x]='*'; > 130 if(next[y+2][x]=='R') > 131 dead=true; > 132 } > 133 else if(data[y+1][x]=='*' && data[y][x+1]==' ' & > 134 next[y][x]=' '; > 135 next[y+1][x+1]='*'; > 136 if(next[y+2][x+1]=='R') > 137 dead=true; > 138 } > 139 else if(data[y+1][x]=='*' && data[y][x-1]==' ' & > 140 next[y][x]=' '; > 141 next[y+1][x-1]='*'; > 142 if(next[y+2][x-1]=='R') > 143 dead=true; > 144 } > 145 else if(data[y+1][x]=='\\' && data[y][x+1]==' ' > 146 next[y][x]=' '; > 147 next[y+1][x+1]='*'; > 148 if(next[y+2][x+1]=='R') > 149 dead=true; > 150 } > 151 } > 152 else if(data[y][x]=='L') { > 153 if(!lambda) > 154 next[y][x] = 'O'; > 155 } > 156 } > 157 data = next; > 158 > 159 if(flooding) { > 160 bool wa = false; > 161 for(int y=water; y+1<H; ++y) > 162 for(int x=1; x+1<W; ++x) > 163 if(data[y][x]=='R') { > 164 wa = true; > 165 underwater++; > 166 if(underwater > water_proof) > 167 dead = true; > 168 } > 169 flooding_counter ++; > 170 if(flooding_counter == flooding) { > 171 flooding_counter = 0; > 172 water --; > 173 } > 174 } > 175 } > 176 > 177 int clever() > 178 { > 179 if(dead) > 180 return 0; > 181 int sy,sx; > 182 int[] ly,lx; > 183 int oy,ox; > 184 for(int y=0; y<H; ++y) > 185 for(int x=0; x<W; ++x) > 186 if(data[y][x]=='R') > 187 sy=y, sx=x; > 188 else if(data[y][x]=='\\') > 189 ly~=y, lx~=x; > 190 else if(data[y][x]=='O') > 191 oy=y, ox=x; > 192 if(ly.length==0) { > 193 auto r = search(sy,sx,oy,ox); > 194 switch(r[0]) { > 195 case 'D': return command_D(); > 196 case 'U': return command_U(); > 197 case 'L': return command_L(); > 198 case 'R': return command_R(); > 199 case 'A': return abort(); > 200 default: return wait(); > 201 } > 202 } else { > 203 Tuple!(char,int)[] cand; > 204 for(int i=0; i<ly.length; ++i) { > 205 auto r = search(sy,sx,ly[i],lx[i]); > 206 cand ~= r; > 207 } > 208 sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ > 209 if(c1[1] != c2[1]) > 210 return c1[1] < c2[1]; > 211 return c1[0] < c2[0]; > 212 })(cand); > 213 switch(cand[0][0]) { > 214 case 'D': return command_D(); > 215 case 'U': return command_U(); > 216 case 'L': return command_L(); > 217 case 'R': return command_R(); > 218 case 'A': return abort(); > 219 default: return wait(); > 220 } > 221 } > 222 return wait(); > 223 } > 224 Tuple!(char,int) search(int sy, int sx, int oy, int ox) > 225 { > 226 alias Tuple!(int,"y",int,"x") Pt; > 227 Pt[] q = [Pt(oy,ox)]; > 228 bool[][] v = new bool[][](H,W); > 229 for(int step=1; q.length; ++step) { > 230 Pt[] q2; > 231 foreach(p; q) { > 232 int[] dy=[-1,+1,0,0]; > 233 int[] dx=[0,0,-1,+1]; > 234 for(int i=0; i<4; ++i) { > 235 int y = p.y+dy[i]; > 236 int x = p.x+dx[i]; > 237 if(v[y][x]) continue; > 238 if(y==sy && x==sx) { > 239 if(i==0) return tuple('D',step); > 240 if(i==1) return tuple('U',step); > 241 if(i==2) return tuple('R',step); > 242 if(i==3) return tuple('L',step); > 243 } else if(data[y][x]==' '||data[y][x]==' > 244 q2 ~= Pt(y,x); > 245 v[y][x]=true; > 246 } else if(data[y][x]=='.' && data[y-1][x > 247 q2 ~= Pt(y,x); > 248 v[y][x]=true; > 249 } > 250 } > 251 } > 252 q = q2; > 253 } > 254 q = [Pt(oy,ox)]; > 255 v = new bool[][](H,W); > 256 for(int step=1<<10; q.length; ++step) { > 257 Pt[] q2; > 258 foreach(p; q) { > 259 > 260 int[] dy=[-1,+1,0,0]; > 261 int[] dx=[0,0,-1,+1]; > 262 for(int i=0; i<4; ++i) { > 263 int y = p.y+dy[i]; > 264 int x = p.x+dx[i]; > 265 if(v[y][x]) continue; > 266 if(y==sy && x==sx) { > 267 if(i==0) return tuple('D',step); > 268 if(i==1) return tuple('U',step); > 269 if(i==2) return tuple('R',step); > 270 if(i==3) return tuple('L',step); > 271 } else if(data[y][x]==' '||data[y][x]==' > 272 q2 ~= Pt(y,x); > 273 v[y][x]=true; > 274 } else if(data[y][x]=='.'/* && data[y-1] > 275 q2 ~= Pt(y,x); > 276 v[y][x]=true; > 277 } > 278 } > 279 } > 280 q = q2; > 281 } > 282 return tuple('A',int.max); > 283 } > 284 } > 285 > 286 class MyForm : Form > 287 { > 288 Map m; > 289 int score; > 290 > 291 this(Map m) > 292 { > 293 noMessageFilter(); > 294 this.m = m; > 295 this.text = .text("Score: ", score, " air[",m.water_proof-m.und > 296 this.keyDown ~= &myKey; > 297 this.score = 0; > 298 } > 299 override void onResize(EventArgs ev) { > 300 invalidate(); > 301 } > 302 override void onPaint(PaintEventArgs ev) > 303 { > 304 int Z = min(this.clientSize.width/(m.W-2), this.clientSize.heigh > 305 Font font = new Font("MS Gothic", Z-4); > 306 Graphics g = ev.graphics; > 307 g.fillRectangle(Color(0,233,255), Rect(0,Z*(m.water-1),this.clie > 308 for(int y=1; y+1<m.H; ++y) > 309 for(int x=1; x+1<m.W; ++x) { > 310 if(m.data[y][x]=='*') { > 311 g.drawText("岩", font, Color(0,0,0), Rect((x-1)*Z > 312 } > 313 if(m.data[y][x]=='\\') { > 314 g.drawText("λ", font, Color(0,255,0), Rect((x-1) > 315 } > 316 if(m.data[y][x]=='R') { > 317 if(m.dead) > 318 g.drawText("Я", font, Color(255,0,0), Re > 319 else > 320 g.drawText("R", font, Color(128,128,0), > 321 } > 322 if(m.data[y][x]=='L') { > 323 g.drawText("扉", font, Color(255,255,0), Rect((x- > 324 } > 325 if(m.data[y][x]=='O') { > 326 g.drawText("外", font, Color(255,255,0), Rect((x- > 327 } > 328 if(m.data[y][x]=='#') { > 329 g.drawText("#", font, Color(0,0,0), Rect((x-1)*Z > 330 } > 331 if(m.data[y][x]=='.') { > 332 g.drawText("・", font, Color(128,40,0), Rect((x-1 > 333 } > 334 } > 335 } > 336 void myKey(Control c, KeyEventArgs ev) > 337 { > 338 switch(ev.keyCode) > 339 { > 340 case Keys.DOWN: > 341 score += m.command_D(); > 342 stdout.flush(); > 343 break; > 344 case Keys.UP: > 345 score += m.command_U(); > 346 stdout.flush(); > 347 break; > 348 case Keys.LEFT: > 349 score += m.command_L(); > 350 stdout.flush(); > 351 break; > 352 case Keys.RIGHT: > 353 score += m.command_R(); > 354 stdout.flush(); > 355 break; > 356 case Keys.W: > 357 score += m.wait(); > 358 stdout.flush(); > 359 break; > 360 case Keys.A: > 361 score += m.abort(); > 362 stdout.flush(); > 363 break; > 364 case Keys.G: > 365 score += m.clever(); > 366 stdout.flush(); > 367 break; > 368 default: > 369 break; > 370 } > 371 if(m.cleared) { > 372 writeln(); > 373 writeln("Score: ", score); > 374 Application.exit(); > 375 } > 376 this.text = .text("Score: ", score, " air[",m.water_proof-m.und > 377 invalidate(); > 378 } > 379 } > 380 > 381 extern(C) { > 382 void sigint(int) { > 383 write("A"); > 384 stdout.flush(); > 385 exit(0); > 386 } > 387 } > 388 > 389 void main(string[] args) > 390 { > 391 signal(SIGINT, &sigint); > 392 > 393 Form myForm = new MyForm(new Map(File(args[1]))); > 394 Application.run(myForm); > 395 }

Added util.d version [8d98b81c5616ea88]

> 1 public import std.algorithm; > 2 public import std.array; > 3 public import std.conv; > 4 public import std.range; > 5 public import std.stdio; > 6 public import std.string; > 7 public import std.typecons; > 8 > 9 template DeriveCreate() > 10 { > 11 this(TS...)(TS params) > 12 { > 13 this.tupleof = params; > 14 } > 15 } > 16 > 17 template DeriveCompare() > 18 { > 19 override: > 20 bool opEquals(Object rhs) > 21 { > 22 return tuple(this.tupleof) == tuple((cast(typeof(this))rhs).tupl > 23 } > 24 > 25 int opCmp(Object rhs) > 26 { > 27 return tuple(this.tupleof).opCmp(tuple((cast(typeof(this))rhs).t > 28 } > 29 > 30 hash_t toHash() > 31 { > 32 hash_t v = 0; > 33 foreach(mem; this.tupleof) { > 34 v *= 11; > 35 static if(__traits(compiles, v^=mem)) > 36 v ^= mem; > 37 else > 38 v ^= typeid(mem).getHash(&mem); > 39 } > 40 return v; > 41 } > 42 } > 43 > 44 template DeriveShow() > 45 { > 46 override: > 47 string toString() > 48 { > 49 string str = text(typeof(this).stringof, "("); > 50 foreach(i,mem; this.tupleof) { > 51 if(i) str ~= ", "; > 52 str = text(str, this.tupleof[i].stringof[5..$], ":", me > 53 } > 54 return str ~ ")"; > 55 } > 56 }