Check-in Differences
Not logged in

Difference From:

[64f5c73b88] hige moving tochu. (user: kinaba, tags: trunk, date: 2012-07-15 14:55:18)

To:

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

Deleted maps/80x60.map version [46898d6dbc3eed35]

1 ############################################################ < 2 #L\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.*.*.*.*.*.*.*.*.*.*# < 3 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.*W*.*.*.*.*.*.*.*.*.# < 4 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*# < 5 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.*W*.*.*.*.*.*.*.*.*.# < 6 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.*.*.*.*.*.*.*.*.*.*# < 7 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 8 #.\.\.\.\.\.\.\.\.@.\.\.@.\.\.\.\.\.\.\.*.*.*.*.*.*.*.*.*.*# < 9 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 10 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.*.*.*.*.*.*.*.*.*.*# < 11 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*# < 12 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.*.*.*.*.*.*.*.*.*.*# < 13 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 14 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*W*.*.*.*.*.*.*.*.*.# < 15 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.*W*.*.*.*.*.*.*.*.*.# < 16 #.\.\.\.\.\.\.\.\.\W\.\.\.\.\.\.\.\.\.\*W*.*.*.*.*.*.*.*.*.# < 17 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.**W*.*.*.*.*.*.*.*.*.# < 18 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*W*.*.*.*.*.*.*.*.*.# < 19 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.*W*.*.*.*.*.*.*.*.*.# < 20 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*W*.*.*.*.*.*.*.*.*.# < 21 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 22 #.\.\.\.\!\.\.\.\.\.\.\.\W\.\.\.\.\.\.\*!*.*.*.*.*.*.*.*.*.# < 23 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 24 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*!*.*.*.*.*.*.*.*.*.# < 25 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 26 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*!*.*.*.*.*.*.*.*.*.# < 27 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 28 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*!*.*.*.*.*.*.*.*.*.# < 29 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 30 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*!*.*.*.*.*.*.*.*.*.# < 31 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\!\.\..*.*.*.*.*.*.*.*.*.*# < 32 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*!*.*.*.*.*.*.*.*.*.# < 33 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 34 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\*!*.*.*.*.*.*.*.*.*.# < 35 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\!\.\..*.*.*.*.*.*.*.*.*.*# < 36 #.\.\.\.\.\.\.\.\W\.\.\.\.\.\.\.\.\.\.\*!*.*.*.*.*.*.*.*.*.# < 37 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 38 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 39 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 40 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 41 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 42 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 43 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 44 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 45 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 46 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 47 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 48 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 49 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 50 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 51 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 52 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 53 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 54 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 55 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 56 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 57 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\..*.*.*.*.*.*.*.*.*.*# < 58 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 59 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 60 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 61 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 62 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 63 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 64 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 65 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 66 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 67 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 68 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 69 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 70 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 71 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 72 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 73 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 74 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 75 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 76 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 77 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 78 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 79 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R*!*.*.*.*.*.*.*.*.*.# < 80 ############################################################ < 81 < 82 Flooding 80 <

Deleted maps/beard5.map version [7639fcdcf36705e1]

1 ########## < 2 ####..******#### < 3 ###.. 3ABCDEF...### < 4 ## ## < 5 ### ## < 6 ###.....\\\...\\\.....### < 7 #.. \\\ * \\\ ## < 8 ## * ## < 9 ### *** ## < 10 #*****************## < 11 ###..............## < 12 ###...........## < 13 ####WR..W#### < 14 ##L#### < 15 ..... < 16 ###### ###### < 17 ##1\! G##2 !\H## < 18 ###### ###### < 19 < 20 Trampoline A targets 1 < 21 Trampoline B targets 1 < 22 Trampoline C targets 1 < 23 Trampoline D targets 1 < 24 Trampoline E targets 1 < 25 Trampoline F targets 1 < 26 Trampoline G targets 2 < 27 Trampoline H targets 3 < 28 Growth 5 < 29 Razors 0 <

Deleted maps/horock1.map version [7e25f07bad607ab0]

1 #####L###### < 2 #....R....A# < 3 #..........# < 4 #\. #@\ ..# < 5 #\...#* ### < 6 #\.........# < 7 #\..*.@....# < 8 ####@@. ..# < 9 #....#.. ### < 10 #....#..**.# < 11 #.1..# .\\# < 12 ############ < 13 < 14 Trampoline A targets 1 <

Deleted maps/horock2.map version [2fb25272ef9314ea]

1 ################# < 2 #A .@@@@@@# < 3 # .. #*...*1# < 4 # .##########*## < 5 # ..@ \\\\#* # < 6 # ..# #####*.# < 7 # .##### * # < 8 #LR ....... . # < 9 ################# < 10 < 11 Trampoline A targets 1 < 12 Flooding 10 < 13 Water 0 <

Deleted maps/horock3.map version [d80af0f6153d8208]

1 ################# < 2 # \\\\# * * # < 3 # ## !!#..@. #### < 4 #* @...####.....# < 5 #\\ \@...........# < 6 #\ # .\@ # #.######## < 7 #\ # ..\@ # .. # < 8 #\ # .. \@ # .. # < 9 #\ # *.. \@ ####### # < 10 #\ # ### \@ # #W # < 11 ### # \@ # ##L# < 12 #...#@@**@@**\@ # < 13 #R ..........!\## < 14 ################# < 15 < 16 Growth 25 <

Modified score_memo.txt from [0e695941ab7be6d2] to [95f0626c958d6d31].

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 // 一度通り過ぎるとふさがってしまう曲がり道 | 6 contest6 737 // deadend trap 7 contest7 867? 7 contest7 867? 8 contest8 1245 // 無理ゲー | 8 contest8 1245 // tricky 9 contest9 3042? 9 contest9 3042? 10 contest10 2076 // "λの上に岩" トラップが複数 | 10 contest10 2076 // * on lambda, must move * first 11 flood1 569 // 崩すの怖がりすぎ & 一直線に並んでるのに真ん中から取るのはどうなの | 11 flood1 569 // too slow, because of 1-left danger lambda 12 flood2 280? 12 flood2 280? 13 flood3 802 // 溺死 | 13 flood3 802 // too slow, drown 14 flood4 970 // むずかしい岩崩し | 14 flood4 970 // incorrect order of digging 15 flood5 561? 15 flood5 561? 16 trampoline1 291 // むずかしい岩崩し | 16 trampoline1 291 // * on trampoline. must move * first 17 trampoline2 1728? 17 trampoline2 1728? 18 trampoline3 698 // "上に岩" ワープゾーン版 | 18 trampoline3 698 // * on trampoline target. must move * first. 19 beard1 856? 19 beard1 856? 20 beard2 2792 // 崩すの怖がりすぎて間に合わなくなって溺死 | 20 beard2 2792 // hutsu-ni muzui 21 beard3 811 // 無理ゲー:速攻で髭刈らないといけない | 21 beard3 811 // tricky. must hurry to cut hige. 22 beard4 677 // 岩が落ちてきてデッドエンド | 22 beard4 677 // deadend trap 23 beard5 665 // これクリアできるの < 24 horock1 333 < 25 horock2 235 < 26 horock3 1542 <

Modified src/Makefile from [de085b8055253640] to [01a4f7a0531dae71].

1 # To build, the following packages are needed. 1 # To build, the following packages are needed. 2 # $ wget http://ftp.digitalmars.com/dmd_2.059-0_i386.deb | 2 # wget http://ftp.digitalmars.com/dmd_2.059-0_i386.deb 3 # $ sudo apt-get install gcc gcc-multilib | 3 # sudo apt-get install gcc gcc-multilib 4 # $ sudo pkg -i dmd_2.059-0_i386.deb | 4 # sudo pkg -i dmd_2.059-0_i386.deb 5 # < 6 # Optional GUI is Windows only. Need to install DFL (http://github.com/Rayerd/df < 7 5 8 cui: < > 6 all: 9 dmd -O -release -inline -oflifter main.d driver.d game.d output.d solver | 7 dmd -O -release -inline -oflifter cui_auto_main.d driver.d game.d output 10 < 11 gui: < 12 dmd -O -release -inline -ofgui gui_main.d gui.d driver.d game.d output.d < 13 < 14 clean: < 15 rm *.obj *.o *.exe *.deps <

Added 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 }

Modified src/game.d from [189f5a19c7160df3] to [fc05481901940844].

6 { 6 { 7 public immutable int y, x; 7 public immutable int y, x; 8 mixin DeriveCreate; 8 mixin DeriveCreate; 9 mixin DeriveCompare; 9 mixin DeriveCompare; 10 mixin DeriveShow; 10 mixin DeriveShow; 11 Pos clone() const { return cast(Pos) this; } 11 Pos clone() const { return cast(Pos) this; } 12 12 13 const @property: | 13 @property: 14 Pos wait() { return this.clone(); } 14 Pos wait() { return this.clone(); } 15 Pos up() { return new Pos(y+1, x); } 15 Pos up() { return new Pos(y+1, x); } 16 Pos down() { return new Pos(y-1, x); } 16 Pos down() { return new Pos(y-1, x); } 17 Pos left() { return new Pos(y, x-1); } 17 Pos left() { return new Pos(y, x-1); } 18 Pos right() { return new Pos(y, x+1); } 18 Pos right() { return new Pos(y, x+1); } 19 alias wait W,w; 19 alias wait W,w; 20 alias up U,u; 20 alias up U,u; ................................................................................................................................................................................ 41 41 42 class Water 42 class Water 43 { 43 { 44 public immutable int base, pace; 44 public immutable int base, pace; 45 mixin DeriveCreate; 45 mixin DeriveCreate; 46 mixin DeriveCompare; 46 mixin DeriveCompare; 47 mixin DeriveShow; 47 mixin DeriveShow; 48 Water clone() const { return cast(Water) this; } | 48 Water clone() const { return cast(Water)this; } 49 49 50 static load(string[string] params) 50 static load(string[string] params) 51 { 51 { 52 return new Water(params.get("Water", "0").to!int(), 52 return new Water(params.get("Water", "0").to!int(), 53 params.get("Flooding", "0").to!int()); 53 params.get("Flooding", "0").to!int()); 54 } 54 } 55 55 56 int level(int turn) const | 56 int level(int number_of_update) const 57 { 57 { 58 return pace ? base+(turn/pace) : base; | 58 return pace ? base+(number_of_update/pace) : base; 59 } 59 } 60 60 61 int until_rise(int turn) const | 61 int until_rise(int number_of_update) const 62 { 62 { 63 return pace ? pace-turn%pace : int.max; | 63 return pace ? pace-number_of_update%pace : int.max; 64 } 64 } 65 } 65 } 66 66 67 unittest 67 unittest 68 { 68 { 69 Water w = new Water(1, 3); 69 Water w = new Water(1, 3); 70 assert( 1 == w.level(0) ); 70 assert( 1 == w.level(0) ); ................................................................................................................................................................................ 111 } 111 } 112 112 113 //////////////////////////////////////////////////////////////////////////////// 113 //////////////////////////////////////////////////////////////////////////////// 114 114 115 class Map 115 class Map 116 { 116 { 117 mixin DeriveShow; 117 mixin DeriveShow; > 118 > 119 static Map load(string[] raw_data, string[string] params, char[char] tra > 120 { > 121 // TODO: choose optimal representation. > 122 return new Map(raw_data, params, trampo); > 123 } 118 124 119 char[][] data; 125 char[][] data; 120 Pos robot; 126 Pos robot; 121 Pos lift; 127 Pos lift; 122 int waterproof; 128 int waterproof; 123 Pos[char] tr_target; 129 Pos[char] tr_target; 124 Pos[][char] tr_source; 130 Pos[][char] tr_source; 125 const(Hige) hige; 131 const(Hige) hige; 126 int razor; 132 int razor; 127 int collected_lambda; < 128 int total_lambda; < 129 bool cleared; < 130 Pos[] may_update; < 131 133 132 Map clone() const { return new Map(this); } 134 Map clone() const { return new Map(this); } 133 this(in Map m) { 135 this(in Map m) { 134 foreach(s; m.data) 136 foreach(s; m.data) 135 this.data ~= s.dup; 137 this.data ~= s.dup; 136 this.robot = m.robot.clone(); 138 this.robot = m.robot.clone(); 137 this.lift = m.lift.clone(); 139 this.lift = m.lift.clone(); 138 this.waterproof = m.waterproof; 140 this.waterproof = m.waterproof; 139 this.tr_target = cast(Pos[char])m.tr_target; 141 this.tr_target = cast(Pos[char])m.tr_target; 140 this.tr_source = cast(Pos[][char])m.tr_source; 142 this.tr_source = cast(Pos[][char])m.tr_source; 141 this.hige = m.hige.clone(); 143 this.hige = m.hige.clone(); 142 this.razor = m.razor; 144 this.razor = m.razor; 143 this.collected_lambda = m.collected_lambda; < 144 this.total_lambda = m.total_lambda; < 145 this.may_update = (cast(Map)m).may_update.dup; < 146 this.cleared = m.cleared; < 147 } 145 } 148 146 149 this(string[] raw_data, string[string] params, char[char] trampo) 147 this(string[] raw_data, string[string] params, char[char] trampo) 150 { 148 { 151 int width = 0; 149 int width = 0; 152 foreach(r; raw_data) 150 foreach(r; raw_data) 153 width = max(width, r.length); 151 width = max(width, r.length); ................................................................................................................................................................................ 159 157 160 for(int y=1; y<=H; ++y) 158 for(int y=1; y<=H; ++y) 161 for(int x=1; x<=W; ++x) { 159 for(int x=1; x<=W; ++x) { 162 if(this[y,x] == 'R') 160 if(this[y,x] == 'R') 163 this.robot = new Pos(y,x); 161 this.robot = new Pos(y,x); 164 if(this[y,x] == 'L' || this[y,x] == 'O') 162 if(this[y,x] == 'L' || this[y,x] == 'O') 165 this.lift = new Pos(y,x); 163 this.lift = new Pos(y,x); 166 if(this[y,x] == '\\' || this[y,x] == '@') < 167 total_lambda++; < 168 if(this[y,x] == '*' || this[y,x] == '@') < 169 may_update ~= new Pos(y,x); < 170 } 164 } 171 165 172 Pos[char] tr_pos; 166 Pos[char] tr_pos; 173 for(int y=1; y<=H; ++y) 167 for(int y=1; y<=H; ++y) 174 for(int x=1; x<=W; ++x) { 168 for(int x=1; x<=W; ++x) { 175 char c = this[y,x]; 169 char c = this[y,x]; 176 if('1'<=c && c<='9' || 'A'<=c&&c<='I') 170 if('1'<=c && c<='9' || 'A'<=c&&c<='I') ................................................................................................................................................................................ 231 ans ~= new Pos(y,x); 225 ans ~= new Pos(y,x); 232 return ans; 226 return ans; 233 } 227 } 234 228 235 Pos[] razors() const { return objects('!'); } 229 Pos[] razors() const { return objects('!'); } 236 Pos[] lambdas() const { return objects('\\'); } 230 Pos[] lambdas() const { return objects('\\'); } 237 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 238 bool command(char c, int turn, bool hige_day) | 241 Tuple!(int,bool) command(char c, int turn) 239 { 242 { 240 assert( this[robot] == 'R' ); 243 assert( this[robot] == 'R' ); 241 if(c=='R') return move( 0, +1, turn, hige_day); | 244 if(c=='R') return move( 0, +1, turn); 242 if(c=='L') return move( 0, -1, turn, hige_day); | 245 if(c=='L') return move( 0, -1, turn); 243 if(c=='U') return move(+1, 0, turn, hige_day); | 246 if(c=='U') return move(+1, 0, turn); 244 if(c=='D') return move(-1, 0, turn, hige_day); | 247 if(c=='D') return move(-1, 0, turn); 245 if(c=='W') return move( 0, 0, turn, hige_day); | 248 if(c=='W') return move( 0, 0, turn); 246 if(c=='S') return use_razor(turn, hige_day); | 249 if(c=='S') return use_razor(turn); 247 assert(false); 250 assert(false); 248 } 251 } 249 252 250 bool use_razor(int turn, bool hige_day) | 253 Tuple!(int, bool) use_razor(int turn) 251 { 254 { 252 if(razor) { 255 if(razor) { 253 razor--; 256 razor--; 254 for(int dy=-1; dy<=+1; ++dy) 257 for(int dy=-1; dy<=+1; ++dy) 255 for(int dx=-1; dx<=+1; ++dx) 258 for(int dx=-1; dx<=+1; ++dx) 256 if(this[robot.y+dy,robot.x+dx] == 'W') { | 259 if(this[robot.y+dy,robot.x+dx] == 'W') 257 emptified(new Pos(robot.y+dy,robot.x+dx) < 258 this[robot.y+dy,robot.x+dx] = ' '; 260 this[robot.y+dy,robot.x+dx] = ' '; 259 } < 260 } 261 } 261 262 262 return update(turn, hige_day); | 263 bool dead = update(turn); > 264 return tuple(0,dead); 263 } 265 } 264 266 265 bool rocky(char c) { return c=='*' || c=='@'; } < 266 < 267 void emptified(Pos p) { < 268 for(int dy=0; dy<=+1; ++dy) < 269 for(int dx=-1; dx<=+1; ++dx) < 270 may_update ~= new Pos(p.y+dy, p.x+dx); < 271 } < 272 < 273 bool move(int dy, int dx, int turn, bool hige_day) | 267 Tuple!(int, bool) move(int dy, int dx, int turn) 274 { 268 { 275 < 276 emptified(robot); < 277 < 278 int y = robot.y; 269 int y = robot.y; 279 int x = robot.x; 270 int x = robot.x; > 271 int lambda = 0; 280 if( '\\' == this[y+dy,x+dx] ) 272 if( '\\' == this[y+dy,x+dx] ) 281 collected_lambda++; | 273 lambda++; 282 if( '!' == this[y+dy,x+dx] ) 274 if( '!' == this[y+dy,x+dx] ) 283 razor++; 275 razor++; 284 if( 'O' == this[y+dy,x+dx] ) < 285 cleared = true; < 286 if( " \\!.O".count(this[y+dy,x+dx])==1 ) { 276 if( " \\!.O".count(this[y+dy,x+dx])==1 ) { 287 this[y,x]=' '; 277 this[y,x]=' '; 288 this[y+dy,x+dx]='R'; 278 this[y+dy,x+dx]='R'; 289 robot = new Pos(y+dy,x+dx); 279 robot = new Pos(y+dy,x+dx); 290 } else if(dy==0 && rocky(this[y+dy,x+dx]) && ' '==this[y+dy*2,x+ | 280 } else if(dy==0 && '*'==this[y+dy,x+dx] && ' '==this[y+dy*2,x+dx 291 char rock = this[y+dy,x+dx]; < 292 this[y,x]=' '; 281 this[y,x]=' '; 293 this[y+dy,x+dx]='R'; 282 this[y+dy,x+dx]='R'; 294 this[y+dy*2,x+dx*2]=rock; | 283 this[y+dy*2,x+dx*2]='*'; 295 robot = new Pos(y+dy,x+dx); 284 robot = new Pos(y+dy,x+dx); 296 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') { 285 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') { 297 this[y,x]=' '; 286 this[y,x]=' '; 298 Pos tp = tr_target[this[y+dy,x+dx]]; 287 Pos tp = tr_target[this[y+dy,x+dx]]; 299 foreach(p; tr_source[this[tp]]) { | 288 foreach(p; tr_source[this[tp]]) 300 emptified(p); < 301 this[p] = ' '; 289 this[p] = ' '; 302 } < 303 this[tp] = 'R'; 290 this[tp] = 'R'; 304 robot = tp; 291 robot = tp; 305 } 292 } 306 return update(turn, hige_day); | 293 bool dead = update(turn); > 294 return tuple(lambda,dead); 307 } 295 } 308 296 309 bool update(int turn, bool hige_day) | 297 bool update(int turn) 310 { 298 { 311 // Write after all the updates are processed. < 312 Tuple!(int,int,char)[] write_buffer; < 313 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 < 315 scope(exit) { < 316 may_update.length = 0; < 317 foreach(wr; write_buffer) { < 318 this[wr[0],wr[1]] = wr[2]; < 319 if(rocky(wr[2])) < 320 may_update ~= new Pos(wr[0],wr[1]); < 321 if(wr[2]==' ') < 322 emptified(new Pos(wr[0], wr[1])); < 323 } < 324 } < 325 < 326 if(collected_lambda == total_lambda) < 327 if(this[lift]=='L') < 328 this[lift] = 'O'; < 329 < 330 bool dead = false; 299 bool dead = false; 331 sort(may_update); < > 300 > 301 char[][] next; 332 foreach(p; may_update) { | 302 foreach(y,s; data) 333 int y = p.y, x = p.x; < 334 char rock = this[p]; | 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); 335 if(rocky(this[p])) { | 315 if(this[p]=='*') { 336 if(this[p.D]==' ') { 316 if(this[p.D]==' ') { 337 writep(p, ' '); | 317 access(p) =' '; 338 writep(p.D, (rock=='@'&&this[p.D.D]!=' ' | 318 access(p.D)='*'; 339 if(robot == p.D.D) 319 if(robot == p.D.D) 340 dead=true; 320 dead=true; 341 } 321 } 342 else if((rocky(this[p.D]) || this[p.D]=='\\') && | 322 else if((this[p.D]=='*' || this[p.D]=='\\') && t 343 writep(p, ' '); | 323 access(p)=' '; 344 writep(p.R.D,(rock=='@'&&this[p.R.D.D]!= | 324 access(p.R.D)='*'; 345 if(robot == p.R.D.D) 325 if(robot == p.R.D.D) 346 dead=true; 326 dead=true; 347 } 327 } 348 else if(rocky(this[p.D]) && this[p.L]==' ' && th | 328 else if(this[p.D]=='*' && this[p.L]==' ' && this 349 writep(p, ' '); | 329 access(p)=' '; 350 writep(p.L.D, (rock=='@'&&this[p.L.D.D]! | 330 access(p.L.D)='*'; 351 if(robot == p.L.D.D) 331 if(robot == p.L.D.D) 352 dead=true; 332 dead=true; 353 } 333 } 354 } 334 } > 335 else if(this[p]=='L') { > 336 if(!lambda) > 337 access(p) = 'O'; 355 } | 338 } 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') { | 339 else if(this[p]=='W') { > 340 if( hige.is_growing_turn(turn) ) 362 for(int dy=-1; dy<=+1; ++dy) 341 for(int dy=-1; dy<=+1; ++dy) 363 for(int dx=-1; dx<=+1; ++dx) 342 for(int dx=-1; dx<=+1; ++dx) 364 if(this[p.y+dy,p.x+dx] == ' ') 343 if(this[p.y+dy,p.x+dx] == ' ') 365 write(p.y+dy,p.x+dx,'W') | 344 access(new Pos(p.y+dy,p. 366 } 345 } 367 } 346 } 368 < > 347 data = next; 369 return dead; 348 return dead; 370 } 349 } 371 } 350 } 372 351 373 //////////////////////////////////////////////////////////////////////////////// 352 //////////////////////////////////////////////////////////////////////////////// 374 353 375 class Game 354 class Game 376 { 355 { 377 mixin DeriveShow; | 356 public: 378 < 379 this(File input) 357 this(File input) 380 { 358 { 381 string[] raw_data; | 359 // Read map data 382 string[string] params; | 360 string[] map_data_lines; 383 < 384 // Raw map data; read until empty line. < 385 for(string line; !(line=input.readln().chomp()).empty; ) 361 for(string line; !(line=input.readln().chomp()).empty; ) 386 raw_data ~= line; | 362 map_data_lines ~= line; 387 363 388 // Additional commands; read until EOF. | 364 // H*W 389 char[char] trampo; | 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 390 for(string line; !(line=input.readln()).empty; ) { | 423 for(string line; !(line=input.readln()).empty; ) > 424 { 391 string[] ss = line.split(); 425 string[] ss = line.split(); 392 if( ss.length == 2 ) 426 if( ss.length == 2 ) 393 params[ss[0]] = ss[1]; | 427 switch(ss[0]) > 428 { > 429 case "Water": water_base_ = ss[1].to!int(); > 430 case "Flooding": water_pace_ = ss[1].to!int(); > 431 case "Waterproof": max_air_ = ss[1].to!int(); > 432 case "Growth": hige_pace_ = ss[1].to!int(); > 433 case "Razors": num_razor_ = ss[1].to!int(); > 434 default: assert(false); > 435 } 394 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar 436 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar 395 trampo[ss[1][0]] = ss[3][0]; < > 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_ > 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_ : w > 462 } > 463 int water_until_rise() { > 464 return water_pace_ ? water_pace_ - turn_%water_pace_ : i > 465 } > 466 int hige_until_rise() { > 467 return hige_pace_ ? hige_pace_ - turn_%hige_pace_ : int. > 468 } > 469 bool is_hige_turn() { > 470 return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : f > 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 > 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; 396 } 497 } 397 | 498 } 398 this.map = new Map(raw_data, params, trampo); | 499 const { 399 this.water = Water.load(params); | 500 char opIndex(in Pos p) { return opIndex(p.y, p.x); } > 501 char opIndex(int y, int x) { return map_get(y, x); } 400 } 502 } 401 503 402 Game clone() const { return new Game(this); } | 504 public: 403 this(in Game g) { < 404 map = g.map.clone(); < 405 water = g.water.clone(); < 406 turn = g.turn; < 407 dead = g.dead; < 408 under_water = g.under_water; < 409 } < 410 < 411 void command(char c) 505 void command(char c) 412 { 506 { 413 assert(c != 'A'); < 414 if(dead || cleared) 507 if(dead || cleared) 415 return; 508 return; 416 509 417 // TODO: clarify the event order | 510 if(c == 'U') command_move(+1, 0); 418 bool dead_now = map.command(c, turn, map.hige.is_growing_turn(tu | 511 if(c == 'D') command_move(-1, 0); 419 if( dead_now ) | 512 if(c == 'L') command_move(0, -1); 420 dead = true; | 513 if(c == 'R') command_move(0, +1); > 514 if(c == 'S') use_razor(); > 515 if(c == 'W') {} > 516 421 if(!map.cleared) { | 517 if(!cleared) 422 if( map.robot.y <= water_level ) < > 518 { > 519 map_update(); 423 ++under_water; | 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 } 424 else 651 else 425 under_water = 0; < > 652 { 426 if( under_water > map.waterproof ) | 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] > 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 > 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) 427 dead = true; | 685 dead_ = true; 428 } 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_) 429 turn += 1; | 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; 430 } 759 } 431 760 432 Map map; | 761 private: 433 Water water; | 762 int H_; 434 int turn = 0; | 763 int W_; 435 bool dead = false; | 764 char[][] raw_data_; 436 int under_water = 0; | 765 Pos[char] trampoline_pos_; 437 // TODO: when adding members, take care of clone(). | 766 Pos[] razor_pos_; 438 // TODO: fix this poor design. | 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; 439 779 440 @property const: | 780 int turn_ = 0; 441 long score() { return map.collected_lambda*(dead?25L:cleared?7 | 781 int air_left_ = 0; 442 int water_level() { return water.level(turn); } < 443 int water_until_rise() { return water.until_rise(turn); } < 444 int hige_until_rise() { return map.hige.until_rise(turn); } < 445 int hp() { return map.waterproof - under_water; } < 446 bool cleared() { return map.cleared; } | 782 bool cleared_ = false; > 783 bool dead_ = false; > 784 bool[Pos] may_update_; 447 } 785 }

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

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.map.W, g.map.H); | 11 setup_size(g.W, g.H); 12 setup_resources(g); 12 setup_resources(g); 13 draw(g); 13 draw(g); 14 } 14 } 15 15 16 void run(void delegate(char c) command, bool automate = true) | 16 private void delegate(char c) fn; > 17 void set_fn(F)(F f) { this.fn = f; } > 18 > 19 void run(bool automate = false) 17 { 20 { 18 if(automate) { 21 if(automate) { 19 Timer t = new Timer; 22 Timer t = new Timer; 20 t.interval = 50; 23 t.interval = 50; > 24 t.tick ~= (Timer sender, EventArgs ea){ 21 t.tick ~= (Timer s, EventArgs e){command(solver.single_s | 25 fn(solver.single_step()); > 26 }; 22 t.start(); 27 t.start(); 23 this.closing ~= (Form f,CancelEventArgs c){t.stop();}; 28 this.closing ~= (Form f,CancelEventArgs c){t.stop();}; 24 } else { 29 } else { 25 setup_keyhandling(command); | 30 setup_keyhandling(); 26 } 31 } 27 Application.run(this); 32 Application.run(this); 28 } 33 } 29 34 30 override void on_game_changed(char c, in Game g, bool finished) 35 override void on_game_changed(char c, in Game g, bool finished) 31 { 36 { 32 draw(g); 37 draw(g); 33 } 38 } 34 39 35 private: 40 private: > 41 int cell; > 42 36 void setup_size(int W, int H) 43 void setup_size(int W, int H) 37 { 44 { 38 this.formBorderStyle = FormBorderStyle.FIXED_DIALOG; 45 this.formBorderStyle = FormBorderStyle.FIXED_DIALOG; 39 this.maximizeBox = false; 46 this.maximizeBox = false; 40 this.minimizeBox = false; 47 this.minimizeBox = false; 41 this.cell = min(1024/W, 640/H); 48 this.cell = min(1024/W, 640/H); 42 this.clientSize = Size(W*cell, H*cell); 49 this.clientSize = Size(W*cell, H*cell); 43 } 50 } 44 51 45 int cell; < 46 Font font; 52 Font font; 47 Color[char] colors; 53 Color[char] colors; 48 string[char] render; 54 string[char] render; 49 Graphics graphicContext; 55 Graphics graphicContext; 50 56 51 void setup_resources(in Game g) 57 void setup_resources(in Game g) 52 { 58 { 53 this.graphicContext = new MemoryGraphics(this.clientSize.width, 59 this.graphicContext = new MemoryGraphics(this.clientSize.width, 54 this.setStyle(ControlStyles.OPAQUE, true); 60 this.setStyle(ControlStyles.OPAQUE, true); 55 this.font = new Font("MS Gothic", cell-2, GraphicsUnit.PIXEL); 61 this.font = new Font("MS Gothic", cell-2, GraphicsUnit.PIXEL); 56 this.backColor = Color(255,255,255); 62 this.backColor = Color(255,255,255); 57 this.colors['#'] = 63 this.colors['#'] = 58 this.colors['.'] = Color(255,191,127); 64 this.colors['.'] = Color(255,191,127); 59 this.colors['*'] = | 65 this.colors['*'] = Color(255,127,127); 60 this.colors['@'] = Color(255,127,127); < 61 this.colors['R'] = Color(128,128,0); 66 this.colors['R'] = Color(128,128,0); 62 this.colors['r'] = Color(100,128,255); < 63 this.colors['d'] = Color(255,0,0); 67 this.colors['d'] = Color(255,0,0); 64 this.colors['\\'] = 68 this.colors['\\'] = 65 this.colors['L'] = 69 this.colors['L'] = 66 this.colors['O'] = Color(127,255,127); 70 this.colors['O'] = Color(127,255,127); 67 this.colors['w'] = Color(204,229,255); 71 this.colors['w'] = Color(204,229,255); 68 this.colors['W'] = 72 this.colors['W'] = 69 this.colors['!'] = Color(159,159,159); 73 this.colors['!'] = Color(159,159,159); 70 foreach(char c; 'A'..'J') this.colors[c] = Color(142,142,255); 74 foreach(char c; 'A'..'J') this.colors[c] = Color(142,142,255); 71 foreach(char c; '1'..':') this.colors[c] = Color(255,142,255); 75 foreach(char c; '1'..':') this.colors[c] = Color(255,142,255); 72 this.render['#'] = "■"; 76 this.render['#'] = "■"; 73 this.render['*'] = "✹"; 77 this.render['*'] = "✹"; 74 this.render['@'] = "❁"; < 75 this.render['.'] = "♒"; 78 this.render['.'] = "♒"; 76 this.render['\\'] = "λ"; 79 this.render['\\'] = "λ"; 77 this.render['R'] = "☃"; 80 this.render['R'] = "☃"; 78 this.render['r'] = "☃"; < 79 this.render['d'] = "☠"; 81 this.render['d'] = "☠"; 80 this.render['L'] = "☒"; 82 this.render['L'] = "☒"; 81 this.render['O'] = "☐"; 83 this.render['O'] = "☐"; 82 this.render['W'] = "ꔣ"; 84 this.render['W'] = "ꔣ"; 83 this.render['!'] = "✄"; 85 this.render['!'] = "✄"; 84 foreach(c,tp; g.map.tr_target) this.render[c] = [cast(dchar)('☢' | 86 foreach(char c; 'A'..'J') this.render[c] = [cast(dchar)('☢'+g.tr 85 foreach(char c; '1'..':') this.render[c] = [cast(dchar)('☢' | 87 foreach(char c; '1'..':') this.render[c] = [cast(dchar)('☢'+c-'1 86 this.paint ~= (Control c, PaintEventArgs ev) { 88 this.paint ~= (Control c, PaintEventArgs ev) { 87 graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientS 89 graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientS 88 }; 90 }; 89 } 91 } 90 92 91 void draw(in Game g) 93 void draw(in Game g) 92 { 94 { ................................................................................................................................................................................ 97 graphicContext.fillRectangle(this.backColor, Rect(0,0,scrW,scrH) 99 graphicContext.fillRectangle(this.backColor, Rect(0,0,scrW,scrH) 98 100 99 // Fill water. 101 // Fill water. 100 int w = g.water_level(); 102 int w = g.water_level(); 101 graphicContext.fillRectangle(this.colors['w'], Rect(0, scrH-cell 103 graphicContext.fillRectangle(this.colors['w'], Rect(0, scrH-cell 102 104 103 // Paint map. 105 // Paint map. 104 for(int y=1; y<=g.map.H; ++y) | 106 for(int y=1; y<=g.H; ++y) 105 for(int x=1; x<=g.map.W; ++x) { | 107 for(int x=1; x<=g.W; ++x) { 106 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); 108 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); 107 char c = g.map[y,x]; | 109 char c = g[y,x]; 108 if( c != ' ' ) { 110 if( c != ' ' ) { 109 if( c == 'R' ) | 111 if( c == 'R' && g.dead ) 110 c = (g.dead ? 'd' : g.cleared ? 'r' : 'R | 112 c = 'd'; 111 graphicContext.drawText(this.render[c], font, th 113 graphicContext.drawText(this.render[c], font, th 112 } 114 } 113 } 115 } 114 116 115 // Update textual info. 117 // Update textual info. 116 this.text = .text( 118 this.text = .text( 117 "Score: ", g.score, 119 "Score: ", g.score, 118 " Air: ", g.hp, 120 " Air: ", g.hp, 119 " Tide: ", g.water_until_rise, 121 " Tide: ", g.water_until_rise, 120 " Wadler: ", g.hige_until_rise, 122 " Wadler: ", g.hige_until_rise, 121 " Razor: ", g.map.razor); | 123 " Razor: ", g.num_razor); 122 invalidate(); 124 invalidate(); 123 } 125 } 124 126 125 private: 127 private: 126 void setup_keyhandling(void delegate(char c) command) | 128 void setup_keyhandling() 127 { 129 { 128 noMessageFilter(); 130 noMessageFilter(); 129 this.keyDown ~= (Control c, KeyEventArgs ev) { | 131 this.keyDown ~= &my_keydown; > 132 } > 133 130 void do_manual_command(char c) | 134 void do_manual_command(char c) 131 { | 135 { 132 solver.force(c); | 136 solver.force(c); 133 command(c); | 137 fn(c); 134 } | 138 } > 139 > 140 void my_keydown(Control c, KeyEventArgs ev) > 141 { 135 switch(ev.keyCode) | 142 switch(ev.keyCode) 136 { | 143 { 137 case Keys.DOWN: do_manual_command('D'); break; | 144 case Keys.DOWN: do_manual_command('D'); break; 138 case Keys.UP: do_manual_command('U'); break; | 145 case Keys.UP: do_manual_command('U'); break; 139 case Keys.LEFT: do_manual_command('L'); break; | 146 case Keys.LEFT: do_manual_command('L'); break; 140 case Keys.RIGHT: do_manual_command('R'); break; | 147 case Keys.RIGHT: do_manual_command('R'); break; 141 case Keys.W: do_manual_command('W'); break; | 148 case Keys.W: do_manual_command('W'); break; 142 case Keys.S: do_manual_command('S'); break; | 149 case Keys.S: do_manual_command('S'); break; 143 case Keys.A: do_manual_command('A'); break; | 150 case Keys.A: do_manual_command('A'); break; 144 case Keys.G: command(solver.single_step()); break; | 151 case Keys.G: fn(solver.single_step()); break; 145 default: break; | 152 default: break; 146 } | 153 } 147 }; < 148 } 154 } 149 155 150 Solver solver; 156 Solver solver; 151 } 157 }

Modified src/gui_main.d from [4124e840a1a49af9] to [05082d0f328d756c].

1 import util; < 2 import gui; 1 import gui; 3 import output; 2 import output; 4 import driver; 3 import driver; 5 import solver; 4 import solver; > 5 import std.stdio; 6 pragma(lib, "dfl.lib"); 6 pragma(lib, "dfl.lib"); 7 7 8 void main(string[] argv) | 8 void main(string[] args) 9 { 9 { 10 bool automate = (argv.length>=2 && std.string.indexOf(argv[1],"auto")>=0 < 11 < 12 auto d = new Driver(stdin); | 10 Driver d = new Driver(stdin); 13 d.addObserver!(GuardedOutput)(); 11 d.addObserver!(GuardedOutput)(); 14 d.addObserver!(GUI!MainSolver)().run(&d.command, automate); | 12 auto g = d.addObserver!(GUI!MainSolver)(); > 13 g.set_fn(&d.command); > 14 g.run(); 15 } 15 }

Deleted src/main.d version [f6cab5c23c5cba1e]

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) { fin = < 13 } < 14 < 15 void main() < 16 { < 17 auto d = new Driver(stdin); < 18 d.addObserver!(GuardedOutput)(); < 19 auto c = d.addObserver!(CUI!MainSolver)(); < 20 while(!c.fin) < 21 d.command(c.solver.single_step()); < 22 } <

Modified src/output.d from [95ed42a2d89e1fef] to [e2d0d7db868c3a44].

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.map.W*g.map.H) | 38 if(finished || log.length+1==g.W*g.H) 39 flush(); 39 flush(); 40 if(log.length+1==g.map.W*g.map.H) < 41 application_exit(); < 42 } 40 } 43 41 44 private: 42 private: 45 string log; 43 string log; 46 long[] score_log; 44 long[] score_log; 47 bool flushed; 45 bool flushed; 48 46

Modified src/solver.d from [2f1962d30be4fa0a] to [22c356ff1975e92f].

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

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

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