Index: score_memo.txt ================================================================== --- score_memo.txt +++ score_memo.txt @@ -1,26 +1,26 @@ contest1 212! -contest2 280? +contest2 281! contest3 275! contest4 561? contest5 1281? contest6 737 // 一度通り過ぎるとふさがってしまう曲がり道 contest7 867? contest8 1245 // 無理ゲー contest9 3042? contest10 2076 // "λの上に岩" トラップが複数 flood1 569 // 崩すの怖がりすぎ & 一直線に並んでるのに真ん中から取るのはどうなの -flood2 280? +flood2 281! flood3 802 // 溺死 flood4 970 // むずかしい岩崩し flood5 561? trampoline1 291 // むずかしい岩崩し -trampoline2 1728? +trampoline2 1732? trampoline3 698 // "上に岩" ワープゾーン版 beard1 856? beard2 2792 // 崩すの怖がりすぎて間に合わなくなって溺死 beard3 811 // 無理ゲー:速攻で髭刈らないといけない beard4 1950 // 髭を解放しないように動くゲー beard5 665 // これクリアできるの horock1 333 horock2 235 horock3 1542 Index: src/solver.d ================================================================== --- src/solver.d +++ src/solver.d @@ -335,25 +335,30 @@ this(in Game g) { current_game = g.clone(); plan = ""; plan_state = Tentative; - replan_limit = PredictFuture; - if(g.map.W*g.map.H <= 400) + if(g.map.W*g.map.H <= 400) { RandomChoicePattern = ["UU","UD","UL","UR", "DU","DD","DL","DR", "LU","LD","LL","LR", "RU","RD","RL","RR","UUU","UUUU","UUUUU"]; - else if(g.map.W*g.map.H <= 4096) + PredictFuture = 20; + clear_improvement = 3; + } + else if(g.map.W*g.map.H <= 4096) { RandomChoicePattern = ["UUU","U","D","L","R","UD","DU","LR","RL"]; - else + PredictFuture = 10; + clear_improvement = 0; + } + else { RandomChoicePattern = ["U","D","L","R"]; - - if(g.map.W*g.map.H <= 400) - PredictFuture = 20; - else PredictFuture = 10; + clear_improvement = 0; + } + + replan_limit = PredictFuture; } char single_step() { if(current_game.dead || current_game.cleared) @@ -407,12 +412,20 @@ char c = sub_solver.single_step(); if(c == 'A') plan_state = Tentative_Stuck; else { plan ~= c; - plan_state = (sub_solver.g.dead ? Tentative_Stuck : - sub_solver.g.cleared ? Fixed : Tentative); + if(sub_solver.g.cleared) { + if(clear_improvement-->0) { + plan_state = Tentative_Stuck; + replan_limit = min(plan.length-plan.length/(clear_improvement+1), PredictFuture); + } else { + plan_state = Fixed; + } + } else { + plan_state = (sub_solver.g.dead ? Tentative_Stuck : Tentative); + } } } void replan() { @@ -421,14 +434,17 @@ Game g = current_game.clone(); Tuple!(SubSolver, string, int) cand = tuple(sub_solver, plan, Tentative_Stuck); int insertion_point = plan.length; writeln(cand, " ", cand[0].g.map.collected_lambda); bool tiebreak_by_turn = false; + int consider_length = min(ReplanLength, g.map.W*g.map.H); + if(cand[0].g.cleared) consider_length = min(consider_length, cand[1].length); + for(int i=0; i0) { sub_solver = cand[0]; plan = cand[1]; plan_state = Tentative_Stuck; - replan_limit = (plan.length - insertion_point); + replan_limit = min(plan.length - insertion_point, PredictFuture); lambda_getter = current_game.map.collected_lambda < cand[0].g.map.collected_lambda; } else { sub_solver = cand[0]; plan = cand[1]; plan_state = (plan.length < PredictFuture ? Fixed : cand[2]); - replan_limit = tiebreak_by_turn ? min(PredictFuture, plan.length/2) : PredictFuture; + replan_limit = tiebreak_by_turn ? min(PredictFuture, (plan.length+1)/2) : PredictFuture; lambda_getter = current_game.map.collected_lambda < cand[0].g.map.collected_lambda; } } - Tuple!(SubSolver, string, int) try_plan(in Game g, string prefix) + Tuple!(SubSolver, string, int) try_plan(in Game g, string prefix, int consider_length) { + if(consider_length<=0) consider_length = 2; + SubSolver s = new SubSolver(g); foreach(char c; prefix) s.force(c); string log; int state = Tentative; - while(!s.g.cleared && !s.g.dead && log.length<=ReplanLength && log.length<=g.map.W*g.map.H) { + while(!s.g.cleared && !s.g.dead && log.length<=consider_length) { char c = s.single_step(); if( c == 'A' ) { state = Tentative_Stuck; break; }