Check-in Differences
Not logged in

Difference From:

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

To:

[bd650eb3f9] Output is now fully functional. (user: kinaba, tags: trunk, date: 2012-07-15 11:26:58)

Modified src/game.d from [fc05481901940844] to [9428bbab7d2bc9a8].

346 346 } 347 347 data = next; 348 348 return dead; 349 349 } 350 350 } 351 351 352 352 //////////////////////////////////////////////////////////////////////////////// 353 +/* 354 +class Game 355 +{ 356 + mixin DeriveShow; 357 + 358 + static Game load(File input) 359 + { 360 + string[] raw_data; 361 + string[string] params; 362 + 363 + // Raw map data; read until empty line. 364 + for(string line; !(line=input.readln().chomp()).empty; ) 365 + raw_data ~= line; 366 + 367 + // Additional commands; read until EOF. 368 + char[char] trampo; 369 + for(string line; !(line=input.readln()).empty; ) { 370 + string[] ss = line.split(); 371 + if( ss.length == 2 ) 372 + params[ss[0]] = ss[1]; 373 + if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="targets" ) 374 + trampo[ss[1][0]] = ss[3][0]; 375 + } 376 + 377 + return load(raw_data, params, trampo); 378 + } 379 + 380 + static Game load(string[] raw_data, string[string] params, char[char] trampo = null) 381 + { 382 + return new Game(raw_data, params, trampo); 383 + } 384 + 385 + this(string[] raw_data, string[string] params, char[char] trampo) 386 + { 387 + this.map = Map.load(raw_data, params, trampo); 388 + this.water = Water.load(params); 389 + } 390 + 391 + Game clone() const { return new Game(this); } 392 + this(in Game g) { 393 + map = g.map.clone(); 394 + water = g.water.clone(); 395 + turn = g.turn; 396 + dead = g.dead; 397 + lambda = g.lambda; 398 + cleared = g.cleared; 399 + under_water = g.under_water; 400 + } 401 + 402 + void command(char c) 403 + { 404 + assert(c != 'A'); 405 + if(dead || cleared) 406 + return; 407 + 408 + // TODO: clarify the event order 409 + Tuple!(int,bool) ld = map.command(c, turn); 410 + if( map.cleared() ) { 411 + cleared = true; 412 + } 413 + else { 414 + lambda += ld[0]; 415 + if( ld[1] ) 416 + dead = true; 417 + } 418 + if(!cleared) { 419 + if( map.robot.y <= water_level ) 420 + ++under_water; 421 + else 422 + under_water = 0; 423 + if( under_water > map.waterproof ) 424 + dead = true; 425 + } 426 + turn += 1; 427 + } 428 + 429 + Map map; 430 + Water water; 431 + int turn = 0; 432 + bool dead = false; 433 + int lambda = 0; 434 + int under_water = 0; 435 + bool cleared = false; 436 + // TODO: when adding members, take care of clone(). 437 + // TODO: fix this poor design. 438 + 439 + @property const { 440 + long score() { return lambda*(dead ? 25L : cleared ? 75L : 50L) - turn; } 441 + int water_level() { return water.level(turn); } 442 + int water_until_rise() { return water.until_rise(turn); } 443 + int hige_until_rise() { return map.hige.until_rise(turn); } 444 + int hp() { return map.waterproof - under_water; } 445 + } 446 +} 447 +*/ 448 + 449 +//////////////////////////////////////////////////////////////////////////////// 353 450 354 451 class Game 355 452 { 356 453 public: 357 454 this(File input) 358 455 { 359 456 // Read map data ................................................................................ 445 542 air_left_ = max_air_; 446 543 } 447 544 448 545 @property const { 449 546 int H() { return H_; } 450 547 int W() { return W_; } 451 548 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 549 int water_level() { 461 550 return water_pace_ ? water_base_ + turn_/water_pace_ : water_base_; 462 551 } 463 552 int water_until_rise() { 464 553 return water_pace_ ? water_pace_ - turn_%water_pace_ : int.max; 465 554 } 466 555 int hige_until_rise() { ................................................................................ 470 559 return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : false; 471 560 } 472 561 int hp() { return air_left_; } 473 562 int num_razor() { return num_razor_; } 474 563 bool cleared() { return cleared_; } 475 564 bool dead() { return dead_; } 476 565 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 566 } 499 567 const { 500 568 char opIndex(in Pos p) { return opIndex(p.y, p.x); } 501 569 char opIndex(int y, int x) { return map_get(y, x); } 502 570 } 503 571 504 572 public: ................................................................................ 510 578 if(c == 'U') command_move(+1, 0); 511 579 if(c == 'D') command_move(-1, 0); 512 580 if(c == 'L') command_move(0, -1); 513 581 if(c == 'R') command_move(0, +1); 514 582 if(c == 'S') use_razor(); 515 583 if(c == 'W') {} 516 584 517 - if(!cleared) 518 - { 519 - map_update(); 520 - water_update(); 521 - } 585 + if(cleared) 586 + return; 587 + 588 + map_update(); 589 + water_update(); 522 590 turn_ ++; 523 591 } 524 592 525 593 void command_move(int dy, int dx) 526 594 { 527 595 int y = robot_pos_.y, x = robot_pos_.x; 528 596 char c = this[y+dy, x+dx]; ................................................................................ 720 788 void map_set_empty(int y, int x) 721 789 { 722 790 if( y<1 || H<y || x<1 || W<x ) return; 723 791 if( x<0 || raw_data_[y].length<=x ) return; 724 792 raw_data_[y][x] = ' '; 725 793 } 726 794 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 795 private: 762 796 int H_; 763 797 int W_; 764 798 char[][] raw_data_; 765 799 Pos[char] trampoline_pos_; 766 800 Pos[] razor_pos_; 767 801 Pos[] lambda_pos_;

Modified src/gui_main.d from [05082d0f328d756c] to [372bc7cd7d19e082].

5 5 import std.stdio; 6 6 pragma(lib, "dfl.lib"); 7 7 8 8 void main(string[] args) 9 9 { 10 10 Driver d = new Driver(stdin); 11 11 d.addObserver!(GuardedOutput)(); 12 - auto g = d.addObserver!(GUI!MainSolver)(); 12 +// auto g = d.addObserver!(GUI!MainSolver)(); 13 + auto g = d.addObserver!(GUI!Solver_0)(); 13 14 g.set_fn(&d.command); 14 15 g.run(); 15 16 }

Modified src/solver.d from [22c356ff1975e92f] to [42b4ef037737dcd0].

3 3 4 4 class Solver_0 5 5 { 6 6 this(in Game g) {} 7 7 char single_step() { return 'W'; } 8 8 void force(char c) {} 9 9 } 10 - 10 +/* 11 11 class Solver_1 12 12 { 13 13 int wait_count = 0; 14 14 int choke_count = 0; 15 15 16 16 Game g; 17 17 this(in Game g) 18 18 { 19 19 this.g = g.clone(); 20 - forbidden_cell = new bool[][](g.H+2, g.W+2); 20 + forbidden_cell = new bool[][](g.map.H+2, g.map.W+2); 21 21 } 22 22 23 23 char single_step() 24 24 { 25 25 Tuple!(string,int) de = death_move(g); 26 26 char c = act(g, de[0], de[1]); 27 27 force(c); ................................................................................ 39 39 string death; 40 40 int choice = 0; 41 41 foreach(char c; "UDLRW") { 42 42 Game gg = g.clone(); 43 43 gg.command(c); 44 44 if( !gg.cleared && gg.dead ) 45 45 death ~= c; 46 - else if( gg.robot != g.robot ) 46 + else if( gg.map.robot != g.map.robot ) 47 47 choice++; 48 48 else if( c != 'W' ) // meaningless move 49 49 death ~= c; 50 50 } 51 51 return tuple(death, choice); 52 52 } 53 53 54 54 Tuple!(Pos, int)[] log; 55 55 bool[][] forbidden_cell; 56 56 57 57 char act(const(Game) g, string death, int breath) 58 58 { 59 - const Pos ro = g.robot; 60 - const Pos li = g.lift; 61 - Pos[] la = g.lambdas(); 59 + const Pos ro = g.map.robot; 60 + const Pos li = g.map.lift; 61 + Pos[] la = g.map.lambdas(); 62 62 sort!((Pos a,Pos b){ 63 63 int ad=abs(a.y-li.y)+abs(a.x-li.x); 64 64 int bd=abs(b.y-li.y)+abs(b.x-li.x); 65 65 return ad>bd;; 66 66 })(la); 67 - Pos[] ra = g.razors(); 68 - const(Pos)[] hi = g.higes(); 67 + Pos[] ra = g.map.razors(); 68 + const(Pos)[] hi = g.map.objects('W'); 69 69 70 70 Tuple!(char,int)[] cand; 71 71 char c = 'W'; 72 72 if( la.empty ) { 73 73 cand = search(g, ro, [li], death); 74 74 } else { 75 75 cand ~= search(g, ro, la~ra, death); 76 76 } 77 77 78 78 // 'higesori' mode 79 - if( !hi.empty && g.num_razor>0 ) { 79 + if( !hi.empty && g.map.razor>0 ) { 80 80 int his = 0; 81 81 for(int dy=-1; dy<=+1; ++dy) 82 82 for(int dx=-1; dx<=+1; ++dx) 83 - if(g[ro.y+dy,ro.x+dx] == 'W') 83 + if(g.map[ro.y+dy,ro.x+dx] == 'W') 84 84 his++; 85 85 86 86 if(his>=2 || his==hi.length) 87 87 cand = [tuple('S',int.max)]; 88 88 if(cand.empty) { 89 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]==' ') { 90 + for(int y=1; y<=g.map.H; ++y) 91 + for(int x=1; x<=g.map.W; ++x) 92 + if(g.map[y,x]=='.'||g.map[y,x]==' ') { 93 93 his = 0; 94 94 for(int dy=-1; dy<=+1; ++dy) 95 95 for(int dx=-1; dx<=+1; ++dx) 96 - if(g[y+dy,x+dx] == 'W') 96 + if(g.map[y+dy,x+dx] == 'W') 97 97 his++; 98 98 if(his>=2) 99 99 tgt ~= new Pos(y,x); 100 100 } 101 101 cand ~= search(g, ro, tgt, death, true); 102 102 } 103 103 } 104 104 105 105 // 'dig' mode 106 106 if(cand.empty) { 107 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]=='*') 108 + for(int y=1; y<=g.map.H; ++y) 109 + for(int x=1; x<=g.map.W; ++x) 110 + if(g.map[y,x]=='.') 111 + if(g.map[y+1,x]=='*'||g.map[y+1,x-1]=='*'||g.map[y+1,x+1]=='*' 112 + ||g.map[y,x+1]=='*'||g.map[y,x-1]=='*') 113 113 tgt ~= new Pos(y,x); 114 114 cand ~= search(g, ro, tgt, death, true); 115 115 } 116 116 117 117 if(cand.empty) { 118 118 choke_count++; 119 119 cand ~= tuple('W',int.max); ................................................................................ 133 133 } 134 134 } 135 135 136 136 if(c == 'W') 137 137 wait_count++; 138 138 else 139 139 wait_count = 0; 140 - if(choke_count >= g.H) 140 + if(choke_count >= g.map.H) 141 141 c = 'A'; 142 142 143 143 bool[char] choice; 144 144 foreach(t; cand) 145 145 choice[t[0]] = true; 146 146 log ~= tuple(ro.clone(), cast(int)choice.length); 147 147 if(log.length > 5) ................................................................................ 157 157 return c; 158 158 } 159 159 160 160 Tuple!(char,int)[] search(in Game g, in Pos s, in Pos[] gs, string death, bool danger_ok=false) 161 161 { 162 162 bool danger(int y, int x) 163 163 { 164 - if(g[y,x] == ' ' || g[y,x] == 'R') 164 + if(g.map[y,x] == ' ' || g.map[y,x] == 'R') 165 165 return false; 166 - if(g[y+1,x] == '*') 166 + if(g.map[y+1,x] == '*') 167 + return true; 168 + if(g.map[y+1,x-1]=='*' && (g.map[y,x-1]=='\\'||g.map[y,x-1]=='*') && (g.map[y+1,x]==' '||g.map[y+1,x]=='R')) 167 169 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')) 170 + if(g.map[y+1,x+1]=='*' && (g.map[y,x+1]=='*') && (g.map[y+1,x]==' '||g.map[y+1,x]=='R')) 169 171 return true; 170 - if(g[y+1,x+1]=='*' && (g[y,x+1]=='*') && (g[y+1,x]==' '||g[y+1,x]=='R')) 172 + if(g.map[y,x-1]=='*' && (g.map[y-1,x-1]=='\\'||g.map[y-1,x-1]=='*') && (g.map[y-1,x]==' '||g.map[y-1,x]=='R')) 171 173 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')) 174 + if(g.map[y,x+1]=='*' && (g.map[y-1,x+1]=='*') && (g.map[y-1,x]==' '||g.map[y-1,x]=='R')) 175 175 return true; 176 176 return false; 177 177 } 178 178 179 179 // avoid directly below '*' 180 180 Tuple!(char,int)[] tryA() { 181 181 const(Pos)[] q; 182 182 foreach(p; gs) 183 183 if(!danger(p.y,p.x)) 184 184 q ~= p; 185 - bool[][] v = new bool[][](g.H+2, g.W+2); 185 + bool[][] v = new bool[][](g.map.H+2, g.map.W+2); 186 186 foreach(p; q) v[p.y][p.x]=true; 187 187 for(int step=1; q.length; ++step) { 188 188 Pos[] q2; 189 189 foreach(p; q) { 190 190 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; 191 191 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; 192 192 for(int i=0; i<yyy.length; ++i) { 193 193 int y = yyy[i]; 194 194 int x = xxx[i]; 195 - if('1'<=g[y,x]&&g[y,x]<='9') { 196 - foreach(ppp; g.trampoline_rev(g[y,x])) { 195 + if('1'<=g.map[y,x]&&g.map[y,x]<='9') { 196 + foreach(ppp; g.map.tr_source[g.map[y,x]]) { 197 197 yyy ~= ppp.y; 198 198 xxx ~= ppp.x; 199 199 } 200 200 continue; 201 201 } 202 202 if(v[y][x]) continue; 203 203 if(y==s.y && x==s.x && i<4) { 204 204 char c = "UDRL"[i]; 205 205 if( death.count(c) == 0 ) 206 206 return [tuple(c,step)]; 207 207 } else if(forbidden_cell[y][x]){ 208 - } else if(g[y,x]==' '||g[y,x]=='\\'||g[y,x]=='.'||g[y,x]=='!'||i>=4) { 208 + } else if(g.map[y,x]==' '||g.map[y,x]=='\\'||g.map[y,x]=='.'||g.map[y,x]=='!'||i>=4) { 209 209 if(danger(y,x)) 210 210 continue; 211 211 q2 ~= new Pos(y,x); 212 212 v[y][x]=true; 213 213 } 214 214 } 215 215 } ................................................................................ 218 218 return []; 219 219 } 220 220 221 221 // any empty space is my ground 222 222 Tuple!(char,int)[] tryB() { 223 223 const(Pos)[] q; 224 224 foreach(p; gs) q ~= p; 225 - bool[][] v = new bool[][](g.H+2, g.W+2); 225 + bool[][] v = new bool[][](g.map.H+2, g.map.W+2); 226 226 foreach(p; q) v[p.y][p.x]=true; 227 227 for(int step=10; q.length; ++step) { 228 228 Pos[] q2; 229 229 foreach(p; q) { 230 230 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; 231 231 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; 232 232 for(int i=0; i<yyy.length; ++i) { 233 233 int y = yyy[i]; 234 234 int x = xxx[i]; 235 - if('1'<=g[y,x]&&g[y,x]<='9') { 236 - foreach(ppp; g.trampoline_rev(g[y,x])) { 235 + if('1'<=g.map[y,x]&&g.map[y,x]<='9') { 236 + foreach(ppp; g.map.tr_source[g.map[y,x]]) { 237 237 yyy ~= ppp.y; 238 238 xxx ~= ppp.x; 239 239 } 240 240 continue; 241 241 } 242 242 if(v[y][x]) continue; 243 243 if(y==s.y && x==s.x && i<4) { 244 244 char c = "UDRL"[i]; 245 245 if( death.count(c) == 0 ) 246 246 return [tuple(c,step)]; 247 247 } else if(forbidden_cell[y][x]){ 248 - } else if(g[y,x]==' '||g[y,x]=='\\'||g[y,x]=='.'||g[y,x]=='!'||i>=4) { 248 + } else if(g.map[y,x]==' '||g.map[y,x]=='\\'||g.map[y,x]=='.'||g.map[y,x]=='!'||i>=4) { 249 249 q2 ~= new Pos(y,x); 250 250 v[y][x]=true; 251 251 } 252 252 } 253 253 } 254 254 q = q2; 255 255 } ................................................................................ 256 256 return []; 257 257 } 258 258 259 259 // push rocks! 260 260 Tuple!(char,int)[] tryC() { 261 261 const(Pos)[] q; 262 262 foreach(p; gs) q ~= p; 263 - bool[][] v = new bool[][](g.H+2, g.W+2); 263 + bool[][] v = new bool[][](g.map.H+2, g.map.W+2); 264 264 foreach(p; q) v[p.y][p.x]=true; 265 265 for(int step=20; q.length; ++step) { 266 266 Pos[] q2; 267 267 foreach(p; q) { 268 268 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; 269 269 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; 270 270 for(int i=0; i<yyy.length; ++i) { 271 271 int y = yyy[i]; 272 272 int x = xxx[i]; 273 - if(g[p] == '*') { 273 + if(g.map[p] == '*') { 274 274 if(i>=4)continue; 275 275 if(y!=p.y)continue; 276 - if(g[y,p.x+(p.x-x)]!=' '&&g[y,p.x+(p.x-x)]!='R')continue; 276 + if(g.map[y,p.x+(p.x-x)]!=' '&&g.map[y,p.x+(p.x-x)]!='R')continue; 277 277 } 278 - if('1'<=g[y,x]&&g[y,x]<='9') { 279 - foreach(ppp; g.trampoline_rev(g[y,x])) { 278 + if('1'<=g.map[y,x]&&g.map[y,x]<='9') { 279 + foreach(ppp; g.map.tr_source[g.map[y,x]]) { 280 280 yyy ~= ppp.y; 281 281 xxx ~= ppp.x; 282 282 } 283 283 continue; 284 284 } 285 285 if(v[y][x]) continue; 286 286 if(y==s.y && x==s.x && i<4) { 287 287 char c = "UDRL"[i]; 288 288 if( death.count(c) == 0 ) 289 289 return [tuple(c,step)]; 290 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) { 291 + } else if(g.map[y,x]==' '||g.map[y,x]=='\\'||g.map[y,x]=='.'||g.map[y,x]=='*'||g.map[y,x]=='!'||i>=4) { 292 292 q2 ~= new Pos(y,x); 293 293 v[y][x]=true; 294 294 } 295 295 } 296 296 } 297 297 q = q2; 298 298 } ................................................................................ 314 314 make_plan(g); 315 315 } 316 316 317 317 Tuple!(Solver,string) run_sub_solver(in Game g) 318 318 { 319 319 string log; 320 320 auto s = new Solver(g); 321 - while(!g.cleared && !g.dead && plan.length<=g.H*g.W) { 321 + while(!g.cleared && !g.dead && plan.length<=g.map.H*g.map.W) { 322 322 char c = s.single_step(); 323 323 if( c == 'A' ) 324 324 break; 325 325 log ~= c; 326 326 } 327 327 while(log.length>0 && log[$-1]=='W') 328 328 log.length--; ................................................................................ 383 383 plan_broken = true; 384 384 } 385 385 else 386 386 plan = plan[1..$]; 387 387 } 388 388 } 389 389 390 -alias Solver_2!(Solver_1) MainSolver; 391 -//alias Solver_1 MainSolver; 390 +//alias Solver_2!(Solver_1) MainSolver; 391 +alias Solver_1 MainSolver; 392 +*/