Differences From Artifact [3fbaa7115d831a14]:
- File
src/solver.d
- 2012-07-15 23:06:48 - part of checkin [3c50d3dc78] on branch trunk - Solver_2 is fast enough. MasterSolver may not be needed. (user: kinaba) [annotate]
To Artifact [fc45f9bc575c213e]:
- File
src/solver.d
- 2012-07-16 00:21:59 - part of checkin [c5c6ef71be] on branch trunk - float up replanner. (user: kinaba) [annotate]
313 } 313 }
314 return (danger_ok ? [] : tryA()) ~ tryB() ~ tryC(); 314 return (danger_ok ? [] : tryA()) ~ tryB() ~ tryC();
315 } 315 }
316 } 316 }
317 317
318 class Solver_2(SubSolver) : Solver 318 class Solver_2(SubSolver) : Solver
319 { 319 {
> 320 // Parameters.
320 static const PredictFuture = 10; | 321 static const PredictFuture = 10;
> 322 const string[] RandomChoicePattern; // PF*RCP exhaustive search for RL s
> 323 const ReplanLength = 400; // O(PF*RCP*RL*SubSolver.single_step
321 324
322 Game current_game; 325 Game current_game;
323 SubSolver sub_solver; 326 SubSolver sub_solver;
324 327
325 enum {Tentative, Tentative_Stuck, Fixed}; 328 enum {Tentative, Tentative_Stuck, Fixed};
326 string plan; 329 string plan;
327 int plan_state; 330 int plan_state;
> 331 int replan_limit;
328 332
329 this(in Game g) 333 this(in Game g)
330 { 334 {
331 current_game = g.clone(); 335 current_game = g.clone();
332 plan = ""; 336 plan = "";
333 plan_state = Tentative; 337 plan_state = Tentative;
> 338 replan_limit = PredictFuture;
> 339 if(g.map.W*g.map.H <= 400)
> 340 RandomChoicePattern = ["UU","UD","UL","UR",
> 341 "DU","DD","DL","DR",
> 342 "LU","LD","LL","LR",
> 343 "RU","RD","RL","RR","UUU","UUUU",
> 344 else if(g.map.W*g.map.H <= 4096)
> 345 RandomChoicePattern = ["UUU","U","D","L","R","UD","DU","
> 346 else
> 347 RandomChoicePattern = ["U","D","L","R"];
334 } 348 }
335 349
336 char single_step() 350 char single_step()
337 { 351 {
338 if(current_game.dead || current_game.cleared) 352 if(current_game.dead || current_game.cleared)
339 return 'A'; 353 return 'A';
340 354
341 // Make enough prediction. 355 // Make enough prediction.
342 while( plan_state==Tentative && plan.length<PredictFuture ) | 356 while( plan_state==Tentative && plan.length<replan_limit )
343 single_step_predict(); 357 single_step_predict();
344 358
345 // If the future is bad, correct. 359 // If the future is bad, correct.
346 if( plan_state==Tentative_Stuck && plan.length<PredictFuture ) | 360 if( plan_state==Tentative_Stuck && plan.length<replan_limit )
347 replan(); 361 replan();
348 362
349 // Follow the predicted plan. 363 // Follow the predicted plan.
350 if( plan.empty ) 364 if( plan.empty )
351 return 'A'; 365 return 'A';
352 stderr.writeln(plan, " ", plan_state); 366 stderr.writeln(plan, " ", plan_state);
353 char c = plan[0]; 367 char c = plan[0];
................................................................................................................................................................................
391 } 405 }
392 406
393 void replan() 407 void replan()
394 { 408 {
395 stderr.writeln("replan!"); 409 stderr.writeln("replan!");
396 // Try to replace every step of the plan by another move. 410 // Try to replace every step of the plan by another move.
397 Game g = current_game.clone(); 411 Game g = current_game.clone();
398 Tuple!(long, SubSolver, string, int) cand = | 412 Tuple!(SubSolver, string, int) cand = tuple(sub_solver, plan, Te
399 tuple(sub_solver.g.score, sub_solver, plan, Tentative_St | 413 bool tiebreak_by_turn = false;
400 for(int i=0; i<plan.length; ++i) { 414 for(int i=0; i<plan.length; ++i) {
401 foreach(string prefix; ["U","D","L","R","UD","DU","LR"," | 415 foreach(string prefix; RandomChoicePattern)
402 if(prefix[0] != plan[i]) { 416 if(prefix[0] != plan[i]) {
403 Tuple!(long, SubSolver, string, int) r = | 417 Tuple!(SubSolver, string, int) r = try_p
404 if(cand[0] < r[0]) { <
405 r[2] = plan[0..i] ~ prefix ~ r[2 | 418 r[1] = plan[0..i] ~ prefix ~ r[1];
> 419 bool better = false, tbt=false;
406 cand = r; | 420 if(!cand[0].g.cleared && r[0].g.cleared)
> 421 better = true;
> 422 else if(cand[0].g.cleared && r[0].g.clea
> 423 better = cand[0].g.score < r[0].
> 424 }
> 425 else if(!cand[0].g.cleared && !r[0].g.cl
> 426 if(cand[0].g.map.collected_lambd
> 427 better = true;
> 428 else if(cand[0].g.map.collected_
> 429 if(cand[0].g.dead && !r[
> 430 better = true;
> 431 else if(cand[0].g.dead =
> 432 better = (cand[1
> 433 tbt = true;
> 434 }
> 435 }
407 } 436 }
> 437 if(better) {
> 438 cand = r;
> 439 tiebreak_by_turn = true;
> 440 writeln(cand);
> 441 }
408 } 442 }
409 g.command(plan[i]); 443 g.command(plan[i]);
410 } 444 }
411 445
412 sub_solver = cand[1]; | 446 sub_solver = cand[0];
413 plan = cand[2]; | 447 plan = cand[1];
414 plan_state = (plan.length < PredictFuture ? Fixed : cand[3]); | 448 plan_state = (plan.length < PredictFuture ? Fixed : cand[2]);
> 449 replan_limit = tiebreak_by_turn ? min(PredictFuture, plan.length
415 } 450 }
416 451
417 Tuple!(long, SubSolver, string, int) try_plan(in Game g, string prefix) | 452 Tuple!(SubSolver, string, int) try_plan(in Game g, string prefix)
418 { 453 {
419 SubSolver s = new SubSolver(g); 454 SubSolver s = new SubSolver(g);
420 foreach(char c; prefix) 455 foreach(char c; prefix)
421 s.force(c); 456 s.force(c);
422 string log; 457 string log;
423 int state = Tentative; 458 int state = Tentative;
424 while(!s.g.cleared && !s.g.dead && log.length<=g.map.H*g.map.W) | 459 while(!s.g.cleared && !s.g.dead && log.length<=ReplanLength && l
425 char c = s.single_step(); 460 char c = s.single_step();
426 if( c == 'A' ) { 461 if( c == 'A' ) {
427 state = Tentative_Stuck; 462 state = Tentative_Stuck;
428 break; 463 break;
429 } 464 }
430 log ~= c; 465 log ~= c;
431 } 466 }
432 if(s.g.cleared) state = Fixed; 467 if(s.g.cleared) state = Fixed;
433 else if(s.g.dead) state = Tentative_Stuck; 468 else if(s.g.dead) state = Tentative_Stuck;
434 return tuple(s.g.score, s, log, state); | 469 return tuple(s, log, state);
435 } 470 }
436 } 471 }
437 /* <
438 class MasterSolver : Solver <
439 { <
440 this(in Game g) <
441 { <
442 int SIZE = g.map.H * g.map.W; <
443 if( SIZE <= 32*32 ) <
444 sub = new Solver_2!(Solver_1)(g); <
445 else if( SIZE <= 100*100 ) <
446 sub = new Solver_1(g); <
447 else <
448 sub = new Solver_1(g); <
449 } <
450 472
451 private Solver sub; <
452 char single_step() { return sub.single_step(); } <
453 void force(char c) { sub.force(c); } <
454 } <
455 <
456 alias MasterSolver MainSolver; <
457 */ <
458 alias Solver_2!(Solver_1) MainSolver; 473 alias Solver_2!(Solver_1) MainSolver;
459 //alias Solver_1 MainSolver; 474 //alias Solver_1 MainSolver;
460 //alias Solver_0 MainSolver; 475 //alias Solver_0 MainSolver;