Check-in [e02668367d]
Not logged in
Overview
SHA1 Hash:e02668367d4b486ef984673b1470e1f20de51904
Date: 2012-07-15 21:14:10
User: kinaba
Comment:Revert redesign in the trunk.
Timelines: family | ancestors | descendants | both | trunk
Diffs: redesign
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified score_memo.txt from [95f0626c958d6d31] to [d46da9814cb8619d].

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

Deleted src/driver.d version [3d15ff20e76164b8]

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

Modified src/game.d from [eaa7866c864bed8a] to [e25c75ea96d80507].

346 } 346 } 347 data = next; 347 data = next; 348 return dead; 348 return dead; 349 } 349 } 350 } 350 } 351 351 352 //////////////////////////////////////////////////////////////////////////////// 352 //////////////////////////////////////////////////////////////////////////////// 353 /* < > 353 354 class Game 354 class Game 355 { 355 { 356 mixin DeriveShow; 356 mixin DeriveShow; 357 357 358 static Game load(File input) 358 static Game load(File input) 359 { 359 { 360 string[] raw_data; 360 string[] raw_data; ................................................................................................................................................................................ 440 long score() { return lambda*(dead ? 25L : cleared ? 75L : 50L) 440 long score() { return lambda*(dead ? 25L : cleared ? 75L : 50L) 441 int water_level() { return water.level(turn); } 441 int water_level() { return water.level(turn); } 442 int water_until_rise() { return water.until_rise(turn); } 442 int water_until_rise() { return water.until_rise(turn); } 443 int hige_until_rise() { return map.hige.until_rise(turn); } 443 int hige_until_rise() { return map.hige.until_rise(turn); } 444 int hp() { return map.waterproof - under_water; } 444 int hp() { return map.waterproof - under_water; } 445 } 445 } 446 } 446 } 447 */ < 448 < 449 //////////////////////////////////////////////////////////////////////////////// < 450 < 451 class Game < 452 { < 453 public: < 454 this(File input) < 455 { < 456 // Read map data < 457 string[] map_data_lines; < 458 for(string line; !(line=input.readln().chomp()).empty; ) < 459 map_data_lines ~= line; < 460 < 461 // H*W < 462 H_ = map_data_lines.length; < 463 W_ = 0; < 464 foreach(mdl; map_data_lines) < 465 W_ = max(W_, mdl.length); < 466 < 467 // Copy to modifiable buffer and adjust coordinates. < 468 raw_data_ = new char[][H_+1]; < 469 foreach(i,mdl; map_data_lines) { < 470 char[] buf = new char[mdl.length+1]; < 471 buf[0] = '#'; < 472 buf[1..$] = mdl[]; < 473 raw_data_[H_-i] = buf; < 474 } < 475 < 476 // Detect objects < 477 for(int y=1; y<=H_; ++y) < 478 for(int x=1; x<raw_data_[y].length; ++x) < 479 { < 480 char c = raw_data_[y][x]; < 481 switch(c) < 482 { < 483 case '#': < 484 case '.': < 485 case ' ': < 486 break; < 487 case 'L': < 488 case 'O': < 489 lift_pos_ = new Pos(y,x); < 490 break; < 491 case 'A': .. case 'I': < 492 case '1': .. case '9': < 493 trampoline_pos_[c] = new Pos(y,x); < 494 break; < 495 case '!': < 496 razor_pos_ ~= new Pos(y,x); < 497 break; < 498 case '\\': < 499 lambda_pos_ ~= new Pos(y,x); < 500 break; < 501 < 502 // Moving objects are erased from raw_data_ < 503 case 'R': < 504 robot_pos_ = new Pos(y,x); < 505 raw_data_[y][x] = ' '; < 506 break; < 507 case '*': < 508 case 'W': < 509 dynamic_objects_[new Pos(y,x)] = c; < 510 raw_data_[y][x] = ' '; < 511 if(c=='*') < 512 may_update_[new Pos(y,x)] = true; < 513 break; < 514 default: < 515 assert(false); < 516 } < 517 } < 518 < 519 // Read other parameters < 520 for(string line; !(line=input.readln()).empty; ) < 521 { < 522 string[] ss = line.split(); < 523 if( ss.length == 2 ) < 524 switch(ss[0]) < 525 { < 526 case "Water": water_base_ = ss[1].to!int(); < 527 case "Flooding": water_pace_ = ss[1].to!int(); < 528 case "Waterproof": max_air_ = ss[1].to!int(); < 529 case "Growth": hige_pace_ = ss[1].to!int(); < 530 case "Razors": num_razor_ = ss[1].to!int(); < 531 default: assert(false); < 532 } < 533 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar < 534 { < 535 char fr=ss[1][0], to=ss[3][0]; < 536 trampoline_[fr] = to; < 537 if(to !in trampoline_rev_) trampoline_rev_[to] = < 538 trampoline_rev_[to] ~= fr; < 539 } < 540 } < 541 < 542 air_left_ = max_air_; < 543 } < 544 < 545 @property const { < 546 int H() { return H_; } < 547 int W() { return W_; } < 548 char trampoline(char c) { return (c in trampoline_ ? trampoline_ < 549 const(Pos)[] trampoline_rev(char c) { < 550 const(Pos)[] pp; < 551 if(c in trampoline_rev_) { < 552 foreach(ch; trampoline_rev_[c]) < 553 pp ~= trampoline_pos_[ch]; < 554 } < 555 return pp; < 556 } < 557 int water_level() { < 558 return water_pace_ ? water_base_ + turn_/water_pace_ : w < 559 } < 560 int water_until_rise() { < 561 return water_pace_ ? water_pace_ - turn_%water_pace_ : i < 562 } < 563 int hige_until_rise() { < 564 return hige_pace_ ? hige_pace_ - turn_%hige_pace_ : int. < 565 } < 566 bool is_hige_turn() { < 567 return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : f < 568 } < 569 int hp() { return air_left_; } < 570 int num_razor() { return num_razor_; } < 571 bool cleared() { return cleared_; } < 572 bool dead() { return dead_; } < 573 long score() { return num_lambda_*(dead_ ? 25L : cleared_ ? 75L < 574 const(Pos) robot() { return robot_pos_; } < 575 const(Pos) lift() { return lift_pos_; } < 576 Pos[] lambdas() { < 577 Pos[] pp; < 578 foreach(p; lambda_pos_) < 579 pp ~= p.clone(); < 580 return pp; < 581 } < 582 Pos[] razors() { < 583 Pos[] pp; < 584 foreach(p; razor_pos_) < 585 pp ~= p.clone(); < 586 return pp; < 587 } < 588 const(Pos)[] higes() { < 589 const(Pos)[] pp; < 590 foreach(p,c; dynamic_objects_) < 591 if(c=='W') < 592 pp ~= p; < 593 return pp; < 594 } < 595 } < 596 const { < 597 char opIndex(in Pos p) { return opIndex(p.y, p.x); } < 598 char opIndex(int y, int x) { return map_get(y, x); } < 599 } < 600 < 601 public: < 602 void command(char c) < 603 { < 604 if(dead || cleared) < 605 return; < 606 < 607 if(c == 'U') command_move(+1, 0); < 608 if(c == 'D') command_move(-1, 0); < 609 if(c == 'L') command_move(0, -1); < 610 if(c == 'R') command_move(0, +1); < 611 if(c == 'S') use_razor(); < 612 if(c == 'W') {} < 613 < 614 if(!cleared) < 615 { < 616 map_update(); < 617 water_update(); < 618 } < 619 turn_ ++; < 620 } < 621 < 622 void command_move(int dy, int dx) < 623 { < 624 int y = robot_pos_.y, x = robot_pos_.x; < 625 char c = this[y+dy, x+dx]; < 626 Pos p = new Pos(y+dy, x+dx); < 627 < 628 switch(c){ < 629 case 'O': < 630 cleared_ = true; < 631 move_robot_to(p); < 632 break; < 633 case '\\': < 634 take_lambda_at(p); < 635 move_robot_to(p); < 636 break; < 637 case '!': < 638 take_razor_at(p); < 639 move_robot_to(p); < 640 break; < 641 case 'A': .. case 'I': < 642 enter_trampoline_at(p, c); < 643 break; < 644 case ' ': < 645 case '.': < 646 move_robot_to(p); < 647 break; < 648 case '*': < 649 if(dy!=0 || this[y,x+dx*2]!=' ') < 650 break; < 651 move_robot_to(p); < 652 push_rock(p, new Pos(y,x+dx*2)); < 653 break; < 654 default: < 655 break; < 656 } < 657 } < 658 < 659 void use_razor() < 660 { < 661 if(num_razor_ == 0) < 662 return; < 663 num_razor_ --; < 664 < 665 for(int dy=-1; dy<=+1; ++dy) < 666 for(int dx=-1; dx<=+1; ++dx) if(dy||dx) < 667 { < 668 Pos p = new Pos(robot_pos_.y+dy, robot_pos_.x+dx); < 669 if(auto it = p in dynamic_objects_) < 670 if(*it == 'W') { < 671 something_gone(p); < 672 dynamic_objects_.remove(p); < 673 } < 674 } < 675 } < 676 < 677 void take_lambda_at(Pos p) < 678 { < 679 map_set_empty(p); < 680 num_lambda_ ++; < 681 lambda_pos_ = lambda_pos_.erase(p); < 682 } < 683 < 684 void take_razor_at(Pos p) < 685 { < 686 map_set_empty(p); < 687 num_razor_ ++; < 688 razor_pos_ = razor_pos_.erase(p); < 689 } < 690 < 691 void enter_trampoline_at(Pos p, char c) < 692 { < 693 char d = trampoline(c); < 694 foreach(cc; trampoline_rev_[d]) { < 695 Pos pp = trampoline_pos_[cc]; < 696 something_gone(pp); < 697 map_set_empty(pp); < 698 } < 699 move_robot_to(trampoline_pos_[d]); < 700 } < 701 < 702 void move_robot_to(Pos p) < 703 { < 704 something_gone(robot_pos_); < 705 map_set_empty(p.y, p.x); < 706 robot_pos_ = p; < 707 } < 708 < 709 void push_rock(Pos fr, Pos to) < 710 { < 711 dynamic_objects_.remove(fr); < 712 dynamic_objects_[to] = '*'; < 713 may_update_[to] = true; < 714 } < 715 < 716 void something_gone(Pos p) < 717 { < 718 for(int dy=0; dy<=+1; ++dy) < 719 for(int dx=-1; dx<=+1; ++dx) if(dy||dx) < 720 may_update_[new Pos(p.y+dy,p.x+dx)] = true; < 721 } < 722 < 723 void map_update() < 724 { < 725 Pos[] may_update_list; < 726 foreach(p,_; may_update_) < 727 if(this[p] == '*') < 728 may_update_list ~= p; < 729 may_update_ = null; < 730 < 731 if( is_hige_turn() ) < 732 foreach(p,c; dynamic_objects_) < 733 if(c == 'W') < 734 may_update_list ~= p; < 735 < 736 sort(may_update_list); < 737 char[Pos] to_be_written; < 738 foreach(p; may_update_list) < 739 if(is_hige_turn() && this[p]=='W') < 740 { < 741 for(int dy=-1; dy<=+1; ++dy) < 742 for(int dx=-1; dx<=+1; ++dx) { < 743 Pos q = new Pos(p.y+dy,p.x+dx); < 744 if( this[q] == ' ' ) < 745 to_be_written[q] = 'W'; < 746 } < 747 } < 748 else < 749 { < 750 int y = p.y; < 751 int x = p.x; < 752 char below = this[y-1,x]; < 753 // * < 754 // _ < 755 if(below==' ') { < 756 Pos q = new Pos(y-1,x); < 757 to_be_written[p] = ' '; < 758 to_be_written[q] = '*'; < 759 may_update_[q] = true; < 760 } < 761 // *_ *_ < 762 // *_ or \_ < 763 else if((below=='*'||below=='\\')&&this[y-1,x+1] < 764 Pos q = new Pos(y-1,x+1); < 765 to_be_written[p] = ' '; < 766 to_be_written[q] = '*'; < 767 may_update_[q] = true; < 768 } < 769 // _* < 770 // _* < 771 else if(below=='*'&&this[y-1,x-1]==' '&&this[y,x < 772 Pos q = new Pos(y-1,x-1); < 773 to_be_written[p] = ' '; < 774 to_be_written[q] = '*'; < 775 may_update_[q] = true; < 776 } < 777 } < 778 < 779 foreach(p,c; to_be_written) { < 780 dynamic_objects_[p] = c; < 781 if(c=='*' && p.y==robot_pos_.y+1 && p.x==robot_pos_.x) < 782 dead_ = true; < 783 } < 784 < 785 if(lambda_pos_.empty) < 786 raw_data_[lift_pos_.y][lift_pos_.x] = 'O'; < 787 } < 788 < 789 void water_update() < 790 { < 791 if( robot_pos_.y <= water_level() ) < 792 air_left_ --; < 793 else < 794 air_left_ = max_air_; < 795 if( air_left_ < 0 ) < 796 dead_ = true; < 797 } < 798 < 799 private: < 800 char map_get(int y, int x) const < 801 { < 802 if( y<1 || H<y || x<1 || W<x ) return '#'; < 803 Pos p = new Pos(y,x); < 804 if(p == robot_pos_) < 805 return 'R'; < 806 if(auto it = (p in dynamic_objects_)) < 807 return *it; < 808 if( x<0 || raw_data_[y].length<=x ) return ' '; < 809 return raw_data_[y][x]; < 810 } < 811 < 812 void map_set_empty(in Pos p) < 813 { < 814 return map_set_empty(p.y, p.x); < 815 } < 816 < 817 void map_set_empty(int y, int x) < 818 { < 819 if( y<1 || H<y || x<1 || W<x ) return; < 820 if( x<0 || raw_data_[y].length<=x ) return; < 821 raw_data_[y][x] = ' '; < 822 } < 823 < 824 public: < 825 Game clone() const { return new Game(this); } < 826 this(in Game g) { < 827 H_ = g.H_; < 828 W_ = g.W_; < 829 raw_data_ = new char[][g.raw_data_.length]; < 830 foreach(i,d; g.raw_data_) raw_data_[i] = d.dup; < 831 trampoline_pos_ = cast(Pos[char]) g.trampoline_pos_; < 832 razor_pos_ = (cast(Game)g).razor_pos_.dup; < 833 lambda_pos_ = (cast(Game)g).lambda_pos_.dup; < 834 lift_pos_ = g.lift_pos_.clone(); < 835 robot_pos_ = g.robot_pos_.clone(); < 836 dynamic_objects_ = dup(g.dynamic_objects_); < 837 trampoline_ = (cast(Game)g).trampoline_; < 838 trampoline_rev_ = (cast(Game)g).trampoline_rev_; < 839 water_base_ = g.water_base_; < 840 water_pace_ = g.water_pace_; < 841 max_air_ = g.max_air_; < 842 hige_pace_ = g.hige_pace_; < 843 num_razor_ = g.num_razor_; < 844 num_lambda_ = g.num_lambda_; < 845 turn_ = g.turn_; < 846 air_left_ = g.air_left_; < 847 cleared_ = g.cleared_; < 848 dead_ = g.dead_; < 849 may_update_ = dup(g.may_update_); < 850 } < 851 < 852 V[K] dup(V,K)(in V[K] aa) { < 853 V[K] aa2; < 854 foreach(k,v; aa) aa2[k] = v; < 855 return aa2; < 856 } < 857 < 858 private: < 859 int H_; < 860 int W_; < 861 char[][] raw_data_; < 862 Pos[char] trampoline_pos_; < 863 Pos[] razor_pos_; < 864 Pos[] lambda_pos_; < 865 Pos lift_pos_; < 866 Pos robot_pos_; < 867 char[Pos] dynamic_objects_; < 868 char[char] trampoline_; < 869 char[][char] trampoline_rev_; < 870 int water_base_ = 0; < 871 int water_pace_ = 0; < 872 int max_air_ = 10; < 873 int hige_pace_ = 25; < 874 int num_razor_ = 0; < 875 int num_lambda_ = 0; < 876 < 877 int turn_ = 0; < 878 int air_left_ = 0; < 879 bool cleared_ = false; < 880 bool dead_ = false; < 881 bool[Pos] may_update_; < 882 } <

Modified src/gui.d from [e84cacd6262f93a7] to [d4577900b4db97c1].

4 import driver; 4 import driver; 5 5 6 class GUI(Solver) : Form, GameObserver 6 class GUI(Solver) : Form, GameObserver 7 { 7 { 8 this(in Game g) 8 this(in Game g) 9 { 9 { 10 this.solver = new Solver(g); 10 this.solver = new Solver(g); 11 setup_size(g.W, g.H); | 11 setup_size(g.map.W, g.map.H); 12 setup_resources(g); 12 setup_resources(g); 13 draw(g); 13 draw(g); 14 } 14 } 15 15 16 private void delegate(char c) fn; 16 private void delegate(char c) fn; 17 void set_fn(F)(F f) { this.fn = f; } 17 void set_fn(F)(F f) { this.fn = f; } 18 18 ................................................................................................................................................................................ 79 this.render['\\'] = "λ"; 79 this.render['\\'] = "λ"; 80 this.render['R'] = "☃"; 80 this.render['R'] = "☃"; 81 this.render['d'] = "☠"; 81 this.render['d'] = "☠"; 82 this.render['L'] = "☒"; 82 this.render['L'] = "☒"; 83 this.render['O'] = "☐"; 83 this.render['O'] = "☐"; 84 this.render['W'] = "ꔣ"; 84 this.render['W'] = "ꔣ"; 85 this.render['!'] = "✄"; 85 this.render['!'] = "✄"; > 86 foreach(c,tp; g.map.tr_target) { > 87 char d = g.map[tp]; 86 foreach(char c; 'A'..'J') this.render[c] = [cast(dchar)('☢'+g.tr | 88 this.render[c] = [cast(dchar)('☢'+d-'1')].to!string(); > 89 } 87 foreach(char c; '1'..':') this.render[c] = [cast(dchar)('☢'+c-'1 90 foreach(char c; '1'..':') this.render[c] = [cast(dchar)('☢'+c-'1 88 this.paint ~= (Control c, PaintEventArgs ev) { 91 this.paint ~= (Control c, PaintEventArgs ev) { 89 graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientS 92 graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientS 90 }; 93 }; 91 } 94 } 92 95 93 void draw(in Game g) 96 void draw(in Game g) ................................................................................................................................................................................ 99 graphicContext.fillRectangle(this.backColor, Rect(0,0,scrW,scrH) 102 graphicContext.fillRectangle(this.backColor, Rect(0,0,scrW,scrH) 100 103 101 // Fill water. 104 // Fill water. 102 int w = g.water_level(); 105 int w = g.water_level(); 103 graphicContext.fillRectangle(this.colors['w'], Rect(0, scrH-cell 106 graphicContext.fillRectangle(this.colors['w'], Rect(0, scrH-cell 104 107 105 // Paint map. 108 // Paint map. 106 for(int y=1; y<=g.H; ++y) | 109 for(int y=1; y<=g.map.H; ++y) 107 for(int x=1; x<=g.W; ++x) { | 110 for(int x=1; x<=g.map.W; ++x) { 108 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); 111 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); 109 char c = g[y,x]; | 112 char c = g.map[y,x]; 110 if( c != ' ' ) { 113 if( c != ' ' ) { 111 if( c == 'R' && g.dead ) 114 if( c == 'R' && g.dead ) 112 c = 'd'; 115 c = 'd'; 113 graphicContext.drawText(this.render[c], font, th 116 graphicContext.drawText(this.render[c], font, th 114 } 117 } 115 } 118 } 116 119 117 // Update textual info. 120 // Update textual info. 118 this.text = .text( 121 this.text = .text( 119 "Score: ", g.score, 122 "Score: ", g.score, 120 " Air: ", g.hp, 123 " Air: ", g.hp, 121 " Tide: ", g.water_until_rise, 124 " Tide: ", g.water_until_rise, 122 " Wadler: ", g.hige_until_rise, 125 " Wadler: ", g.hige_until_rise, 123 " Razor: ", g.num_razor); | 126 " Razor: ", g.map.razor); 124 invalidate(); 127 invalidate(); 125 } 128 } 126 129 127 private: 130 private: 128 void setup_keyhandling() 131 void setup_keyhandling() 129 { 132 { 130 noMessageFilter(); 133 noMessageFilter();

Modified src/output.d from [e2d0d7db868c3a44] to [045b845268918546].

31 override void on_game_changed(char c, in Game g, bool finished) 31 override void on_game_changed(char c, in Game g, bool finished) 32 { 32 { 33 if(flushed) 33 if(flushed) 34 return; 34 return; 35 35 36 log ~= c; 36 log ~= c; 37 score_log ~= g.score; 37 score_log ~= g.score; 38 if(finished || log.length+1==g.W*g.H) | 38 if(finished || log.length+1==g.map.W*g.map.H) 39 flush(); 39 flush(); 40 } 40 } 41 41 42 private: 42 private: 43 string log; 43 string log; 44 long[] score_log; 44 long[] score_log; 45 bool flushed; 45 bool flushed;

Modified src/solver.d from [22c356ff1975e92f] to [393baf841678f948].

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

Modified src/util.d from [b76be1f6ad977d56] to [41ba420d0c49ce8d].

4 public import std.range; 4 public import std.range; 5 public import std.stdio; 5 public import std.stdio; 6 public import std.string; 6 public import std.string; 7 public import std.typecons; 7 public import std.typecons; 8 public import std.math; 8 public import std.math; 9 import std.c.stdlib; 9 import std.c.stdlib; 10 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: 11 // To avoide the following ICE: 20 // src\phobos\std\algorithm.d(4552): 12 // src\phobos\std\algorithm.d(4552): 21 // Error: function std.algorithm.count!("a == b",string,char).count 13 // Error: function std.algorithm.count!("a == b",string,char).count 22 // compiler error, parameter 'value', bugzilla 2962? 14 // compiler error, parameter 'value', bugzilla 2962? 23 // Assertion failure: '0' on line 717 in file 'glue.c' 15 // Assertion failure: '0' on line 717 in file 'glue.c' 24 int count(T,V)(T[] a, V v) 16 int count(T,V)(T[] a, V v) 25 { 17 {