Created
November 10, 2014 03:31
-
-
Save not522/9a398898d258b24a4512 to your computer and use it in GitHub Desktop.
ハル研プロコン
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "HPCAnswerInclude.hpp" | |
namespace { | |
using namespace hpc; | |
} | |
namespace hpc { | |
void Answer::Init(const StageAccessor& aStageAccessor) {} | |
// 自分史上最小のINF | |
const int INF = 20; | |
// このまま加速しなかった場合、目標の蓮に到達するのは何ターン後かを返す | |
// 加速無しで到達できない場合はINFを返す | |
int cross(Vec2 vec, Vec2 vel, const Vec2& flow, const Lotus& lotus) { | |
for (int i = 1; i < INF; ++i) { | |
vec -= vel + flow; | |
if (vec.length() < Parameter::CharaRadius() + lotus.radius()) return i; | |
if (vel.length() <= Parameter::CharaDecelSpeed()) return INF; | |
vel.normalize(vel.length() - Parameter::CharaDecelSpeed()); | |
} | |
return INF; | |
} | |
// 謎の便利関数 | |
// TODO ちゃんとした説明を書く | |
float len(int n) { | |
return Parameter::CharaAccelSpeed() - Parameter::CharaDecelSpeed() * (Parameter::CharaAddAccelWaitTurn + n); | |
} | |
Action Answer::GetNextAction(const StageAccessor& aStageAccessor) { | |
const Chara& player = aStageAccessor.player(); | |
const LotusCollection& lotuses = aStageAccessor.lotuses(); | |
const Lotus& lotus = lotuses[player.targetLotusNo()]; | |
const Lotus& nextL = lotuses[(player.targetLotusNo() + 1) % lotuses.count()]; | |
const Field& field = aStageAccessor.field(); | |
const EnemyAccessor& enemies = aStageAccessor.enemies(); | |
// 加速できない | |
if (player.accelCount() == 0) return Action::Wait(); | |
Vec2 vel = player.vel() + field.flowVel(); | |
Vec2 vec = lotus.pos() - player.pos(); | |
// 最後の1手 | |
if (player.roundCount() == Parameter::StageRoundCount - 1 && player.targetLotusNo() == lotuses.count() - 1) { | |
if (vec.length() - Parameter::CharaRadius() - lotus.radius() < Parameter::CharaAccelSpeed() * player.accelCount() * 10) { | |
return Action::Accel(lotus.pos()); | |
} | |
} | |
// 加速なしで目標の蓮に届く | |
// TODO 待ち過ぎ? | |
if (cross(vec, player.vel(), field.flowVel(), lotus) < INF) return Action::Wait(); | |
// 速度が落ちてたら残り加速回数を見て適宜加速する | |
// TODO たぶん流れを考慮するべき | |
if (player.accelCount() >= 9) { | |
if (vec.length() - (vec - vel).length() >= len(-1)) return Action::Wait(); | |
} else if (player.accelCount() >= 3) { | |
if (vec.length() - (vec - vel).length() >= len(0)) return Action::Wait(); | |
} else if (player.accelCount() >= 2) { | |
if (vec.length() - (vec - vel).length() >= len(2)) return Action::Wait(); | |
} else { | |
// 加速回数が残り1の場合は近づいている限り加速しない | |
if (vec.length() - (vec - vel).length() >= 0) return Action::Wait(); | |
} | |
// 次の次の蓮の方向を考慮 | |
Vec2 nextLotus = nextL.pos() - lotus.pos(); | |
nextLotus.normalize(lotus.radius()); | |
Vec2 next = vec + nextLotus; | |
next.normalize(Parameter::CharaAccelSpeed()); | |
// 流れを考慮 | |
// 2はマジックナンバーだが、ごにょごにょすると近い値が出ると信じている。 | |
// TODO 要検証 | |
// TODO 全体的に流れの扱いが雑すぎるので余裕があれば何とかする | |
next -= 2 * field.flowVel(); | |
next.normalize(Parameter::CharaAccelSpeed()); | |
Vec2 next2 = vec + nextLotus - vel; | |
next2.normalize(Parameter::CharaAccelSpeed()); | |
next2 -= 2 * field.flowVel(); | |
next2.normalize(Parameter::CharaAccelSpeed()); | |
int c1 = cross(vec, next, field.flowVel(), lotus); | |
int c2 = cross(vec - vel, next2, field.flowVel(), lotus); | |
// 加速しなくても目標の蓮に同じターン数以下で到達できるなら加速しない | |
if (c1 != INF && c1 > c2) return Action::Wait(); | |
// 加速したら次のターンで先輩忍者にぶつかる場合は加速回数が余っていない限り加速しない | |
// TODO 2ターン以上先も考慮 | |
// TODO 先輩忍者の加速を考慮 | |
if (player.accelCount() <= 5) { | |
for (int i = 0; i < enemies.count(); ++i) { | |
Chara enemy = enemies[i]; | |
Vec2 eNext = enemy.pos() + enemy.vel(); | |
if ((player.pos() + next - eNext).length() < 2 * Parameter::CharaRadius()) return Action::Wait(); | |
} | |
} | |
return Action::Accel(next + player.pos()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment