Diff
Not logged in

Differences From Artifact [189f5a19c7160df3]:

To Artifact [7a4ec50fc295cb1f]:


118 118 119 char[][] data; 119 char[][] data; 120 Pos robot; 120 Pos robot; 121 Pos lift; 121 Pos lift; 122 int waterproof; 122 int waterproof; 123 Pos[char] tr_target; 123 Pos[char] tr_target; 124 Pos[][char] tr_source; 124 Pos[][char] tr_source; 125 const(Hige) hige; < 126 int razor; 125 int razor; 127 int collected_lambda; 126 int collected_lambda; 128 int total_lambda; 127 int total_lambda; 129 bool cleared; 128 bool cleared; 130 Pos[] may_update; 129 Pos[] may_update; 131 130 132 Map clone() const { return new Map(this); } 131 Map clone() const { return new Map(this); } ................................................................................................................................................................................ 134 foreach(s; m.data) 133 foreach(s; m.data) 135 this.data ~= s.dup; 134 this.data ~= s.dup; 136 this.robot = m.robot.clone(); 135 this.robot = m.robot.clone(); 137 this.lift = m.lift.clone(); 136 this.lift = m.lift.clone(); 138 this.waterproof = m.waterproof; 137 this.waterproof = m.waterproof; 139 this.tr_target = cast(Pos[char])m.tr_target; 138 this.tr_target = cast(Pos[char])m.tr_target; 140 this.tr_source = cast(Pos[][char])m.tr_source; 139 this.tr_source = cast(Pos[][char])m.tr_source; 141 this.hige = m.hige.clone(); < 142 this.razor = m.razor; 140 this.razor = m.razor; 143 this.collected_lambda = m.collected_lambda; 141 this.collected_lambda = m.collected_lambda; 144 this.total_lambda = m.total_lambda; 142 this.total_lambda = m.total_lambda; 145 this.may_update = (cast(Map)m).may_update.dup; 143 this.may_update = (cast(Map)m).may_update.dup; 146 this.cleared = m.cleared; 144 this.cleared = m.cleared; 147 } 145 } 148 146 ................................................................................................................................................................................ 180 this.waterproof = params.get("Waterproof", "5").to!int(); 178 this.waterproof = params.get("Waterproof", "5").to!int(); 181 foreach(fr,to; trampo) { 179 foreach(fr,to; trampo) { 182 tr_target[fr] = tr_pos[to]; 180 tr_target[fr] = tr_pos[to]; 183 if(to !in tr_source) tr_source[to] = []; 181 if(to !in tr_source) tr_source[to] = []; 184 tr_source[to] ~= tr_pos[fr]; 182 tr_source[to] ~= tr_pos[fr]; 185 } 183 } 186 184 187 this.hige = Hige.load(params); < 188 this.razor = params.get("Razors", "0").to!int(); 185 this.razor = params.get("Razors", "0").to!int(); 189 } 186 } 190 187 191 const @property { 188 const @property { 192 int H() { return data.length; } 189 int H() { return data.length; } 193 int W() { return data[0].length; } 190 int W() { return data[0].length; } 194 } 191 } ................................................................................................................................................................................ 234 231 235 Pos[] razors() const { return objects('!'); } 232 Pos[] razors() const { return objects('!'); } 236 Pos[] lambdas() const { return objects('\\'); } 233 Pos[] lambdas() const { return objects('\\'); } 237 234 238 bool command(char c, int turn, bool hige_day) 235 bool command(char c, int turn, bool hige_day) 239 { 236 { 240 assert( this[robot] == 'R' ); 237 assert( this[robot] == 'R' ); 241 if(c=='R') return move( 0, +1, turn, hige_day); | 238 if(c=='R') return move( 0, +1, hige_day); 242 if(c=='L') return move( 0, -1, turn, hige_day); | 239 if(c=='L') return move( 0, -1, hige_day); 243 if(c=='U') return move(+1, 0, turn, hige_day); | 240 if(c=='U') return move(+1, 0, hige_day); 244 if(c=='D') return move(-1, 0, turn, hige_day); | 241 if(c=='D') return move(-1, 0, hige_day); 245 if(c=='W') return move( 0, 0, turn, hige_day); | 242 if(c=='W') return move( 0, 0, hige_day); 246 if(c=='S') return use_razor(turn, hige_day); | 243 if(c=='S') return use_razor(hige_day); 247 assert(false); 244 assert(false); 248 } 245 } 249 246 250 bool use_razor(int turn, bool hige_day) | 247 bool use_razor(bool hige_day) 251 { 248 { 252 if(razor) { 249 if(razor) { 253 razor--; 250 razor--; 254 for(int dy=-1; dy<=+1; ++dy) 251 for(int dy=-1; dy<=+1; ++dy) 255 for(int dx=-1; dx<=+1; ++dx) 252 for(int dx=-1; dx<=+1; ++dx) 256 if(this[robot.y+dy,robot.x+dx] == 'W') { 253 if(this[robot.y+dy,robot.x+dx] == 'W') { 257 emptified(new Pos(robot.y+dy,robot.x+dx) 254 emptified(new Pos(robot.y+dy,robot.x+dx) 258 this[robot.y+dy,robot.x+dx] = ' '; 255 this[robot.y+dy,robot.x+dx] = ' '; 259 } 256 } 260 } 257 } 261 258 262 return update(turn, hige_day); | 259 return update(hige_day); 263 } 260 } 264 261 265 bool rocky(char c) { return c=='*' || c=='@'; } 262 bool rocky(char c) { return c=='*' || c=='@'; } 266 263 267 void emptified(Pos p) { 264 void emptified(Pos p) { 268 for(int dy=0; dy<=+1; ++dy) 265 for(int dy=0; dy<=+1; ++dy) 269 for(int dx=-1; dx<=+1; ++dx) 266 for(int dx=-1; dx<=+1; ++dx) 270 may_update ~= new Pos(p.y+dy, p.x+dx); 267 may_update ~= new Pos(p.y+dy, p.x+dx); 271 } 268 } 272 269 273 bool move(int dy, int dx, int turn, bool hige_day) | 270 bool move(int dy, int dx, bool hige_day) 274 { 271 { 275 < 276 emptified(robot); 272 emptified(robot); 277 273 278 int y = robot.y; 274 int y = robot.y; 279 int x = robot.x; 275 int x = robot.x; 280 if( '\\' == this[y+dy,x+dx] ) 276 if( '\\' == this[y+dy,x+dx] ) 281 collected_lambda++; 277 collected_lambda++; 282 if( '!' == this[y+dy,x+dx] ) 278 if( '!' == this[y+dy,x+dx] ) ................................................................................................................................................................................ 299 foreach(p; tr_source[this[tp]]) { 295 foreach(p; tr_source[this[tp]]) { 300 emptified(p); 296 emptified(p); 301 this[p] = ' '; 297 this[p] = ' '; 302 } 298 } 303 this[tp] = 'R'; 299 this[tp] = 'R'; 304 robot = tp; 300 robot = tp; 305 } 301 } 306 return update(turn, hige_day); | 302 return update(hige_day); 307 } 303 } 308 304 309 bool update(int turn, bool hige_day) | 305 bool update(bool hige_day) 310 { 306 { 311 // Write after all the updates are processed. 307 // Write after all the updates are processed. 312 Tuple!(int,int,char)[] write_buffer; 308 Tuple!(int,int,char)[] write_buffer; 313 void write(int y, int x, char c) { write_buffer ~= tuple(y,x,c); 309 void write(int y, int x, char c) { write_buffer ~= tuple(y,x,c); 314 void writep(Pos p, char c) { write_buffer ~= tuple(0+p.y,0+p.x,c 310 void writep(Pos p, char c) { write_buffer ~= tuple(0+p.y,0+p.x,c 315 scope(exit) { 311 scope(exit) { 316 may_update.length = 0; 312 may_update.length = 0; ................................................................................................................................................................................ 324 } 320 } 325 321 326 if(collected_lambda == total_lambda) 322 if(collected_lambda == total_lambda) 327 if(this[lift]=='L') 323 if(this[lift]=='L') 328 this[lift] = 'O'; 324 this[lift] = 'O'; 329 325 330 bool dead = false; 326 bool dead = false; > 327 if( hige_day ) { > 328 for(int y=1; y<=H; ++y) > 329 for(int x=1; x<=W; ++x) > 330 if(this[y,x]=='W') > 331 may_update ~= new Pos(y,x); > 332 } > 333 331 sort(may_update); 334 sort(may_update); 332 foreach(p; may_update) { 335 foreach(p; may_update) { 333 int y = p.y, x = p.x; 336 int y = p.y, x = p.x; 334 char rock = this[p]; 337 char rock = this[p]; 335 if(rocky(this[p])) { 338 if(rocky(this[p])) { 336 if(this[p.D]==' ') { 339 if(this[p.D]==' ') { 337 writep(p, ' '); 340 writep(p, ' '); ................................................................................................................................................................................ 348 else if(rocky(this[p.D]) && this[p.L]==' ' && th 351 else if(rocky(this[p.D]) && this[p.L]==' ' && th 349 writep(p, ' '); 352 writep(p, ' '); 350 writep(p.L.D, (rock=='@'&&this[p.L.D.D]! 353 writep(p.L.D, (rock=='@'&&this[p.L.D.D]! 351 if(robot == p.L.D.D) 354 if(robot == p.L.D.D) 352 dead=true; 355 dead=true; 353 } 356 } 354 } 357 } 355 } < 356 < 357 if( hige_day ) < 358 for(int y=1; y<=H; ++y) < 359 for(int x=1; x<=W; ++x) { < 360 Pos p = new Pos(y,x); < 361 if(this[p]=='W') { | 358 else if(this[p]=='W') { > 359 if(hige_day) { 362 for(int dy=-1; dy<=+1; ++dy) 360 for(int dy=-1; dy<=+1; ++dy) 363 for(int dx=-1; dx<=+1; ++dx) 361 for(int dx=-1; dx<=+1; ++dx) 364 if(this[p.y+dy,p.x+dx] == ' ') 362 if(this[p.y+dy,p.x+dx] == ' ') 365 write(p.y+dy,p.x+dx,'W') 363 write(p.y+dy,p.x+dx,'W') > 364 } 366 } 365 } 367 } 366 } 368 367 369 return dead; 368 return dead; 370 } 369 } 371 } 370 } 372 371 ................................................................................................................................................................................ 393 params[ss[0]] = ss[1]; 392 params[ss[0]] = ss[1]; 394 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar 393 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar 395 trampo[ss[1][0]] = ss[3][0]; 394 trampo[ss[1][0]] = ss[3][0]; 396 } 395 } 397 396 398 this.map = new Map(raw_data, params, trampo); 397 this.map = new Map(raw_data, params, trampo); 399 this.water = Water.load(params); 398 this.water = Water.load(params); > 399 this.hige = Hige.load(params); 400 } 400 } 401 401 402 Game clone() const { return new Game(this); } 402 Game clone() const { return new Game(this); } 403 this(in Game g) { 403 this(in Game g) { 404 map = g.map.clone(); 404 map = g.map.clone(); 405 water = g.water.clone(); 405 water = g.water.clone(); > 406 hige = g.hige.clone(); 406 turn = g.turn; 407 turn = g.turn; 407 dead = g.dead; 408 dead = g.dead; 408 under_water = g.under_water; 409 under_water = g.under_water; 409 } 410 } 410 411 411 void command(char c) 412 void command(char c) 412 { 413 { 413 assert(c != 'A'); 414 assert(c != 'A'); 414 if(dead || cleared) 415 if(dead || cleared) 415 return; 416 return; 416 417 417 // TODO: clarify the event order 418 // TODO: clarify the event order 418 bool dead_now = map.command(c, turn, map.hige.is_growing_turn(tu | 419 bool dead_now = map.command(c, turn, hige.is_growing_turn(turn)) 419 if( dead_now ) 420 if( dead_now ) 420 dead = true; 421 dead = true; 421 if(!map.cleared) { 422 if(!map.cleared) { 422 if( map.robot.y <= water_level ) 423 if( map.robot.y <= water_level ) 423 ++under_water; 424 ++under_water; 424 else 425 else 425 under_water = 0; 426 under_water = 0; ................................................................................................................................................................................ 427 dead = true; 428 dead = true; 428 } 429 } 429 turn += 1; 430 turn += 1; 430 } 431 } 431 432 432 Map map; 433 Map map; 433 Water water; 434 Water water; > 435 Hige hige; 434 int turn = 0; 436 int turn = 0; 435 bool dead = false; 437 bool dead = false; 436 int under_water = 0; 438 int under_water = 0; 437 // TODO: when adding members, take care of clone(). 439 // TODO: when adding members, take care of clone(). 438 // TODO: fix this poor design. 440 // TODO: fix this poor design. 439 441 440 @property const: 442 @property const: 441 long score() { return map.collected_lambda*(dead?25L:cleared?7 443 long score() { return map.collected_lambda*(dead?25L:cleared?7 442 int water_level() { return water.level(turn); } 444 int water_level() { return water.level(turn); } 443 int water_until_rise() { return water.until_rise(turn); } 445 int water_until_rise() { return water.until_rise(turn); } 444 int hige_until_rise() { return map.hige.until_rise(turn); } | 446 int hige_until_rise() { return hige.until_rise(turn); } 445 int hp() { return map.waterproof - under_water; } 447 int hp() { return map.waterproof - under_water; } 446 bool cleared() { return map.cleared; } 448 bool cleared() { return map.cleared; } 447 } 449 }