Diff
Not logged in

Differences From Artifact [e25c75ea96d80507]:

To Artifact [403db28cbc4609b7]:


126 Pos robot; 126 Pos robot; 127 Pos lift; 127 Pos lift; 128 int waterproof; 128 int waterproof; 129 Pos[char] tr_target; 129 Pos[char] tr_target; 130 Pos[][char] tr_source; 130 Pos[][char] tr_source; 131 const(Hige) hige; 131 const(Hige) hige; 132 int razor; 132 int razor; > 133 int collected_lambda; > 134 int total_lambda; 133 135 134 Map clone() const { return new Map(this); } 136 Map clone() const { return new Map(this); } 135 this(in Map m) { 137 this(in Map m) { 136 foreach(s; m.data) 138 foreach(s; m.data) 137 this.data ~= s.dup; 139 this.data ~= s.dup; 138 this.robot = m.robot.clone(); 140 this.robot = m.robot.clone(); 139 this.lift = m.lift.clone(); 141 this.lift = m.lift.clone(); 140 this.waterproof = m.waterproof; 142 this.waterproof = m.waterproof; 141 this.tr_target = cast(Pos[char])m.tr_target; 143 this.tr_target = cast(Pos[char])m.tr_target; 142 this.tr_source = cast(Pos[][char])m.tr_source; 144 this.tr_source = cast(Pos[][char])m.tr_source; 143 this.hige = m.hige.clone(); 145 this.hige = m.hige.clone(); 144 this.razor = m.razor; 146 this.razor = m.razor; > 147 this.collected_lambda = m.collected_lambda; > 148 this.total_lambda = m.total_lambda; 145 } 149 } 146 150 147 this(string[] raw_data, string[string] params, char[char] trampo) 151 this(string[] raw_data, string[string] params, char[char] trampo) 148 { 152 { 149 int width = 0; 153 int width = 0; 150 foreach(r; raw_data) 154 foreach(r; raw_data) 151 width = max(width, r.length); 155 width = max(width, r.length); ................................................................................................................................................................................ 157 161 158 for(int y=1; y<=H; ++y) 162 for(int y=1; y<=H; ++y) 159 for(int x=1; x<=W; ++x) { 163 for(int x=1; x<=W; ++x) { 160 if(this[y,x] == 'R') 164 if(this[y,x] == 'R') 161 this.robot = new Pos(y,x); 165 this.robot = new Pos(y,x); 162 if(this[y,x] == 'L' || this[y,x] == 'O') 166 if(this[y,x] == 'L' || this[y,x] == 'O') 163 this.lift = new Pos(y,x); 167 this.lift = new Pos(y,x); > 168 if(this[y,x] == '\\' || this[y,x] == '@') > 169 total_lambda++; 164 } 170 } 165 171 166 Pos[char] tr_pos; 172 Pos[char] tr_pos; 167 for(int y=1; y<=H; ++y) 173 for(int y=1; y<=H; ++y) 168 for(int x=1; x<=W; ++x) { 174 for(int x=1; x<=W; ++x) { 169 char c = this[y,x]; 175 char c = this[y,x]; 170 if('1'<=c && c<='9' || 'A'<=c&&c<='I') 176 if('1'<=c && c<='9' || 'A'<=c&&c<='I') ................................................................................................................................................................................ 234 for(int y=1; y<=H; ++y) 240 for(int y=1; y<=H; ++y) 235 for(int x=1; x<=W; ++x) 241 for(int x=1; x<=W; ++x) 236 if(this[y,x] == 'L' || this[y,x] == 'O') 242 if(this[y,x] == 'L' || this[y,x] == 'O') 237 return false; 243 return false; 238 return true; 244 return true; 239 } 245 } 240 246 241 Tuple!(int,bool) command(char c, int turn) | 247 bool command(char c, int turn) 242 { 248 { 243 assert( this[robot] == 'R' ); 249 assert( this[robot] == 'R' ); 244 if(c=='R') return move( 0, +1, turn); 250 if(c=='R') return move( 0, +1, turn); 245 if(c=='L') return move( 0, -1, turn); 251 if(c=='L') return move( 0, -1, turn); 246 if(c=='U') return move(+1, 0, turn); 252 if(c=='U') return move(+1, 0, turn); 247 if(c=='D') return move(-1, 0, turn); 253 if(c=='D') return move(-1, 0, turn); 248 if(c=='W') return move( 0, 0, turn); 254 if(c=='W') return move( 0, 0, turn); 249 if(c=='S') return use_razor(turn); 255 if(c=='S') return use_razor(turn); 250 assert(false); 256 assert(false); 251 } 257 } 252 258 253 Tuple!(int, bool) use_razor(int turn) | 259 bool use_razor(int turn) 254 { 260 { 255 if(razor) { 261 if(razor) { 256 razor--; 262 razor--; 257 for(int dy=-1; dy<=+1; ++dy) 263 for(int dy=-1; dy<=+1; ++dy) 258 for(int dx=-1; dx<=+1; ++dx) 264 for(int dx=-1; dx<=+1; ++dx) 259 if(this[robot.y+dy,robot.x+dx] == 'W') 265 if(this[robot.y+dy,robot.x+dx] == 'W') 260 this[robot.y+dy,robot.x+dx] = ' '; 266 this[robot.y+dy,robot.x+dx] = ' '; 261 } 267 } 262 268 263 bool dead = update(turn); | 269 return update(turn); 264 return tuple(0,dead); < 265 } 270 } 266 271 > 272 bool rocky(char c) { return c=='*' || c=='@'; } > 273 267 Tuple!(int, bool) move(int dy, int dx, int turn) | 274 bool move(int dy, int dx, int turn) 268 { 275 { 269 int y = robot.y; 276 int y = robot.y; 270 int x = robot.x; 277 int x = robot.x; 271 int lambda = 0; < 272 if( '\\' == this[y+dy,x+dx] ) 278 if( '\\' == this[y+dy,x+dx] ) 273 lambda++; | 279 collected_lambda++; 274 if( '!' == this[y+dy,x+dx] ) 280 if( '!' == this[y+dy,x+dx] ) 275 razor++; 281 razor++; 276 if( " \\!.O".count(this[y+dy,x+dx])==1 ) { 282 if( " \\!.O".count(this[y+dy,x+dx])==1 ) { 277 this[y,x]=' '; 283 this[y,x]=' '; 278 this[y+dy,x+dx]='R'; 284 this[y+dy,x+dx]='R'; 279 robot = new Pos(y+dy,x+dx); 285 robot = new Pos(y+dy,x+dx); 280 } else if(dy==0 && '*'==this[y+dy,x+dx] && ' '==this[y+dy*2,x+dx | 286 } else if(dy==0 && rocky(this[y+dy,x+dx]) && ' '==this[y+dy*2,x+ > 287 char rock = this[y+dy,x+dx]; 281 this[y,x]=' '; 288 this[y,x]=' '; 282 this[y+dy,x+dx]='R'; 289 this[y+dy,x+dx]='R'; 283 this[y+dy*2,x+dx*2]='*'; | 290 this[y+dy*2,x+dx*2]=rock; 284 robot = new Pos(y+dy,x+dx); 291 robot = new Pos(y+dy,x+dx); 285 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') { 292 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') { 286 this[y,x]=' '; 293 this[y,x]=' '; 287 Pos tp = tr_target[this[y+dy,x+dx]]; 294 Pos tp = tr_target[this[y+dy,x+dx]]; 288 foreach(p; tr_source[this[tp]]) 295 foreach(p; tr_source[this[tp]]) 289 this[p] = ' '; 296 this[p] = ' '; 290 this[tp] = 'R'; 297 this[tp] = 'R'; 291 robot = tp; 298 robot = tp; 292 } 299 } 293 bool dead = update(turn); | 300 return update(turn); 294 return tuple(lambda,dead); < 295 } 301 } 296 302 297 bool update(int turn) 303 bool update(int turn) 298 { 304 { 299 bool dead = false; 305 bool dead = false; 300 306 301 char[][] next; 307 char[][] next; 302 foreach(y,s; data) 308 foreach(y,s; data) 303 next ~= s.dup; 309 next ~= s.dup; 304 310 305 ref char access(Pos p) { return next[H-p.y][p.x-1]; } 311 ref char access(Pos p) { return next[H-p.y][p.x-1]; } 306 312 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 y=1; y<=H; ++y) 313 for(int x=1; x<=W; ++x) { 314 for(int x=1; x<=W; ++x) { 314 Pos p = new Pos(y,x); 315 Pos p = new Pos(y,x); > 316 char rock = this[p]; 315 if(this[p]=='*') { | 317 if(rocky(this[p])) { 316 if(this[p.D]==' ') { 318 if(this[p.D]==' ') { 317 access(p) =' '; 319 access(p) =' '; 318 access(p.D)='*'; | 320 access(p.D)=(rock=='@'&&this[p.D.D]!=' ' 319 if(robot == p.D.D) 321 if(robot == p.D.D) 320 dead=true; 322 dead=true; 321 } 323 } 322 else if((this[p.D]=='*' || this[p.D]=='\\') && t | 324 else if((rocky(this[p.D]) || this[p.D]=='\\') && 323 access(p)=' '; 325 access(p)=' '; 324 access(p.R.D)='*'; | 326 access(p.R.D)=(rock=='@'&&this[p.R.D.D]! 325 if(robot == p.R.D.D) 327 if(robot == p.R.D.D) 326 dead=true; 328 dead=true; 327 } 329 } 328 else if(this[p.D]=='*' && this[p.L]==' ' && this | 330 else if(rocky(this[p.D]) && this[p.L]==' ' && th 329 access(p)=' '; 331 access(p)=' '; 330 access(p.L.D)='*'; | 332 access(p.L.D)=(rock=='@'&&this[p.L.D.D]! 331 if(robot == p.L.D.D) 333 if(robot == p.L.D.D) 332 dead=true; 334 dead=true; 333 } 335 } 334 } 336 } 335 else if(this[p]=='L') { 337 else if(this[p]=='L') { 336 if(!lambda) | 338 if(collected_lambda == total_lambda) 337 access(p) = 'O'; 339 access(p) = 'O'; 338 } 340 } 339 else if(this[p]=='W') { 341 else if(this[p]=='W') { 340 if( hige.is_growing_turn(turn) ) 342 if( hige.is_growing_turn(turn) ) 341 for(int dy=-1; dy<=+1; ++dy) 343 for(int dy=-1; dy<=+1; ++dy) 342 for(int dx=-1; dx<=+1; ++dx) 344 for(int dx=-1; dx<=+1; ++dx) 343 if(this[p.y+dy,p.x+dx] == ' ') 345 if(this[p.y+dy,p.x+dx] == ' ') ................................................................................................................................................................................ 390 392 391 Game clone() const { return new Game(this); } 393 Game clone() const { return new Game(this); } 392 this(in Game g) { 394 this(in Game g) { 393 map = g.map.clone(); 395 map = g.map.clone(); 394 water = g.water.clone(); 396 water = g.water.clone(); 395 turn = g.turn; 397 turn = g.turn; 396 dead = g.dead; 398 dead = g.dead; 397 lambda = g.lambda; < 398 cleared = g.cleared; 399 cleared = g.cleared; 399 under_water = g.under_water; 400 under_water = g.under_water; 400 } 401 } 401 402 402 void command(char c) 403 void command(char c) 403 { 404 { 404 assert(c != 'A'); 405 assert(c != 'A'); 405 if(dead || cleared) 406 if(dead || cleared) 406 return; 407 return; 407 408 408 // TODO: clarify the event order 409 // TODO: clarify the event order 409 Tuple!(int,bool) ld = map.command(c, turn); | 410 bool dead_now = map.command(c, turn); 410 if( map.cleared() ) { 411 if( map.cleared() ) { 411 cleared = true; 412 cleared = true; 412 } 413 } 413 else { 414 else { 414 lambda += ld[0]; | 415 if( dead_now ) 415 if( ld[1] ) < 416 dead = true; 416 dead = true; 417 } 417 } 418 if(!cleared) { 418 if(!cleared) { 419 if( map.robot.y <= water_level ) 419 if( map.robot.y <= water_level ) 420 ++under_water; 420 ++under_water; 421 else 421 else 422 under_water = 0; 422 under_water = 0; ................................................................................................................................................................................ 426 turn += 1; 426 turn += 1; 427 } 427 } 428 428 429 Map map; 429 Map map; 430 Water water; 430 Water water; 431 int turn = 0; 431 int turn = 0; 432 bool dead = false; 432 bool dead = false; 433 int lambda = 0; < 434 int under_water = 0; 433 int under_water = 0; 435 bool cleared = false; 434 bool cleared = false; 436 // TODO: when adding members, take care of clone(). 435 // TODO: when adding members, take care of clone(). 437 // TODO: fix this poor design. 436 // TODO: fix this poor design. 438 437 439 @property const { 438 @property const { 440 long score() { return lambda*(dead ? 25L : cleared ? 75L : 50L) | 439 long score() { return map.collected_lambda*(dead ? 25L : cleared 441 int water_level() { return water.level(turn); } 440 int water_level() { return water.level(turn); } 442 int water_until_rise() { return water.until_rise(turn); } 441 int water_until_rise() { return water.until_rise(turn); } 443 int hige_until_rise() { return map.hige.until_rise(turn); } 442 int hige_until_rise() { return map.hige.until_rise(turn); } 444 int hp() { return map.waterproof - under_water; } 443 int hp() { return map.waterproof - under_water; } 445 } 444 } 446 } 445 }