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