Check-in Differences
Not logged in

Difference From:

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

To:

[69105bf94a] Stand alone solver. (user: kinaba, tags: trunk, date: 2012-07-14 08:55:55)

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*2]) { 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]=='\\') && this[p.R]==' ' && this[p.R.D]==' ') { 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[p.L.D]==' ') { 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)) - turn; } 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, cell*w+1)); 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], r); 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: ", g.water_until_rise); 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; g_output = this; } 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

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.d solver.d util.d

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(fin)log~="$"; } 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] trampo) 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*2]) { 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]=='\\') && this[p.R]==' ' && this[p.R.D]==' ') { 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[p.L.D]==' ') { 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.x+dx)) = 'W'; 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(); break; 430 - case "Flooding": water_pace_ = ss[1].to!int(); break; 431 - case "Waterproof": max_air_ = ss[1].to!int(); break; 432 - case "Growth": hige_pace_ = ss[1].to!int(); break; 433 - case "Razors": num_razor_ = ss[1].to!int(); break; 434 - default: assert(false); 435 - } 436 - if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="targets" ) 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_[c] : 0); } 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_ : water_base_; 462 - } 463 - int water_until_rise() { 464 - return water_pace_ ? water_pace_ - turn_%water_pace_ : int.max; 465 - } 466 - int hige_until_rise() { 467 - return hige_pace_ ? hige_pace_ - turn_%hige_pace_ : int.max; 468 - } 469 - bool is_hige_turn() { 470 - return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : false; 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 : 50L) - turn_; } 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]==' '&&this[y,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-1]==' ') { 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, this.clientSize.height); 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.trampoline(c)-'1')].to!string(); 87 - foreach(char c; '1'..':') this.render[c] = [cast(dchar)('☢'+c-'1')].to!string(); 88 - this.paint ~= (Control c, PaintEventArgs ev) { 89 - graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientSize.width,this.clientSize.height)); 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*w-1, scrW, cell*w+1)); 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, this.colors[c], r); 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(); application_exit(); } 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,x+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, bool danger_ok=false) 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]=='*') && (g[y+1,x]==' '||g[y+1,x]=='R')) 169 - return true; 170 - if(g[y+1,x+1]=='*' && (g[y,x+1]=='*') && (g[y+1,x]==' '||g[y+1,x]=='R')) 171 - return true; 172 - if(g[y,x-1]=='*' && (g[y-1,x-1]=='\\'||g[y-1,x-1]=='*') && (g[y-1,x]==' '||g[y-1,x]=='R')) 173 - return true; 174 - if(g[y,x+1]=='*' && (g[y-1,x+1]=='*') && (g[y-1,x]==' '||g[y-1,x]=='R')) 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.trampoline_rev(g[y,x])) { 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,step)]; 207 - } else if(forbidden_cell[y][x]){ 208 - } else if(g[y,x]==' '||g[y,x]=='\\'||g[y,x]=='.'||g[y,x]=='!'||i>=4) { 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.trampoline_rev(g[y,x])) { 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,step)]; 247 - } else if(forbidden_cell[y][x]){ 248 - } else if(g[y,x]==' '||g[y,x]=='\\'||g[y,x]=='.'||g[y,x]=='!'||i>=4) { 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)]!=' '&&g[y,p.x+(p.x-x)]!='R')continue; 277 - } 278 - if('1'<=g[y,x]&&g[y,x]<='9') { 279 - foreach(ppp; g.trampoline_rev(g[y,x])) { 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,step)]; 290 - } else if(forbidden_cell[y][x]){ 291 - } else if(g[y,x]==' '||g[y,x]=='\\'||g[y,x]=='.'||g[y,x]=='*'||g[y,x]=='!'||i>=4) { 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], zz[1]); 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).tupleof); 52 - } 53 - 54 - int opCmp(Object rhs) const 55 - { 56 - return tuple(this.tupleof).opCmp(tuple((cast(typeof(this))rhs).tupleof)); 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..$], ":", mem); 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*25; } 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]==' ' && data[y+1][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]==' ' && data[y+1][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]==' ' && data[y+1][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][x]!='*'*/) { 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.underwater,"]"); 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.height/(m.H-2)); 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.clientSize.width,this.clientSize.height-(Z*(m.water-1)))); 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, (y-1)*Z, Z, Z)); 312 + } 313 + if(m.data[y][x]=='\\') { 314 + g.drawText("λ", font, Color(0,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 315 + } 316 + if(m.data[y][x]=='R') { 317 + if(m.dead) 318 + g.drawText("Я", font, Color(255,0,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 319 + else 320 + g.drawText("R", font, Color(128,128,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 321 + } 322 + if(m.data[y][x]=='L') { 323 + g.drawText("扉", font, Color(255,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 324 + } 325 + if(m.data[y][x]=='O') { 326 + g.drawText("外", font, Color(255,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 327 + } 328 + if(m.data[y][x]=='#') { 329 + g.drawText("#", font, Color(0,0,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 330 + } 331 + if(m.data[y][x]=='.') { 332 + g.drawText("・", font, Color(128,40,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 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.underwater,"]"); 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).tupleof); 23 + } 24 + 25 + int opCmp(Object rhs) 26 + { 27 + return tuple(this.tupleof).opCmp(tuple((cast(typeof(this))rhs).tupleof)); 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..$], ":", mem); 53 + } 54 + return str ~ ")"; 55 + } 56 +}