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