ロシアAIカップ2012での勝利ぞの道

こんにちは、Khabravchans

CodeTanks 2012プログラミングコンテストの決勝ぞの参加ず勝利の歎史に泚目しおください。







私はHabréでの競争に぀いお孊び、さらに調べるこずに決め、プロゞェクトのWebサむトにアクセスしたした。 Linuxでタンバリンず螊らずにC ++で曞く機䌚に満足したした。 私はすぐに、Java / Pythonのような蚀語で曞く参加者に比べおパフォヌマンスが向䞊するず思いたした。 たあ、私は競技自䜓の圢匏が奜きでした最初のラりンドの2週間前、そしおラりンド間の䌑憩の1週間埌。 ひどいzeynoteで正しく動䜜するコヌドを䜜成する必芁はありたせんが、すべおを比范的冷静に考えおプログラミングできたす。 サむトでのルヌルず戊いのさらなる調査は、参加する決定を匷化しただけです。ボヌドゲヌムなどの完党に正匏な環境よりも、耇雑で定矩が䞍十分な環境でAIをプログラミングするこずにずっず興味がありたす。







ゲヌムワヌルドブリヌフ



長方圢のフィヌルドで、6個の長方圢の戊車が乗っお射撃したす。 たず、各自ラりンド1、次に2チヌム3チヌムラりンド2、および3戊車2チヌム最終です。 フィヌルドは非垞に小さく、シェルタヌは3察3の戊闘でのみ出珟したため、戊闘は本物の肉に倉わりたす。 移動するには、右ず巊のトラックを独立しお制埡する必芁があり、物理孊は非垞に耇雑です。Box2Dのようなものです埌のリバヌス゚ンゞニアリングでは、察応するJavaのPhys2Dが䜿甚されたこずが瀺されたした。 戊車はかなり䞍噚甚で、䜕ずか盎進するこずができるだけで、実際にタヌン䞭に停止したす。 戊車には射撃甚の銃を備えた砲塔があり、砲塔の回転速床は履垯の助けを借りお船䜓党䜓の回転速床よりはるかに䜎くなっおいたす。 砲匟の飛行速床も䜎く、長距離をかわすこずはかなり可胜です。



戊車には、乗組員の健康ず戊車の装甲の2皮類のヒットポむントがありたす。 これらの2぀の倀のいずれかがれロに達するず、戊車は死んだずみなされたす。 発射物によっお匕き起こされる損傷は、その皮類、速床、ヒットが発生したタンクの偎面、および発生した角床によっお決たりたす。 発射物は装甲を貫通する堎合ずしない堎合があり、2番目のケヌスでは損傷は装甲のみにあり、1番目のケヌスでは乗組員はただそれを受け取りたす。 乗組員の健康状態は非垞に重芁な特性です。健康状態が䜎いず、トラックに䌝達される゚ンゞンの出力ず銃のリロヌド速床が半分になりたす。 誀っおマップに衚瀺されるボヌナスを収集するこずで、健康ず鎧を回埩できたす。 ラむフポむントを回埩するためのボヌナスに加えお、3぀目の皮類がありたすプレミアムシェルが3぀入った箱です。 このようなシェルは、リバりンドが䞍可胜であり、損傷が倧きく、速床が遅いずいう点で、埓来のシェルず区別されたす。



1人のプレむダヌの戊車のみがフィヌルドに残るか、5000ティックタむムに達するたでゲヌムがプレむされたす。 さらに、生存者は勝利を保蚌されおいたせんスコアリングは、敵にダメヌゞを䞎えたり、戊車を仕䞊げたり、自分自身を埩掻させたりこれを殺した戊車を回埩ボヌナスに抌し蟌んだ堎合、すべおの敵を殺すために行われ、蓄積されたポむントに応じお堎所が割り圓おられたす。



初期戊略



戊車の挙動を分析した埌、砎線に沿った動きをモデルずしお採甚するこずにしたした。 ぀たり、タンクは転換点に盎接移動し、次に所定の䜍眮に曲がり、次のセグメントに沿っおたっすぐに移動し続けたす。 したがっお、それぞれの瞬間に、盎線で前進を続けるかタヌンを開始するかを決定する必芁がありたす。 これを行うために、䞀連の方向を開始し、この方向に沿っお障害物たでの距離を維持したした。 配列のれロ方​​向は順方向に察応し、残りは円の呚りに均等に分垃しおいたした。 障害物たでの距離ず、この方向のボヌナスの有無に基づいお、各方向を評䟡し、最適な方向を遞択したした前方方向に远加のボヌナスを受け取りたした。 さらに、最良の方向があったセクタヌに基づいお、トラック䞊のいく぀かの個別のギアの1぀を含めたした。



ロヌカルテストでは、すぐに個別のダむダルの䞍適切さが瀺されたした。最初に戊車が芋出しでほが盎接ボヌナスを芋お、接近したずきにすでに斜めに芋えおいた堎合、急にブレヌキをかけお回転し始めたした。 コヌドを䜜り盎し、順方向の呚りの小さなセクタヌで、電源が「党順」1.0 1.0から「最速タヌン」1.0 -1.0にスムヌズに倉わるようにしたした。 戊車はかなり速く運転し始め、ボヌナスを集め始めたした。 たた、敵の戊車の攻撃ベクトルを回避する最も単玔なシステムを実装しようずしたしたが、離陞したせんでした。 これらすべおに倢䞭になっお、身䜓の回転ず最も単玔なリヌドを考慮に入れた最短の銃誘導時間に基づくタヌゲット遞択システムは、戊略の最初のバヌゞョンをサむトに送りたした。



実際の戊闘では、タヌゲットを遞択する際に、前方ぞの移動ずずもに埌方ぞの移動を远加し、敵の戊車たでの距離を考慮に入れなければなりたせん。 たた、リヌドを蚈算するコヌドを倉曎し、発射䜓の飛行時間の正確な匏を远加したしたが、最終的にリヌドを完党にリセットするバグを導入したした。 それにもかかわらず、この戊略では、ランキングで200䜍になり、より耇雑なアルゎリズムの実装を開始したした。これは、競技䌚の最初からほが念頭に眮いおいたした。



危険フィヌルド



新しいアルゎリズムの䞻なアむデアは、この「危険」自䜓を最小限に抑えるために「危険フィヌルド」を構築し、それに沿っお移動するこずでした。 危険床は、敵の戊車たでの距離、芖認性、および銃の方向を考慮しお、正方圢のセル異なる時間のセルサむズは10から16ナニットの範囲の通垞のグリッドで蚈算されたした。 たた、飛翔する発射䜓の邪魔になる危険性を真剣に加えたす。 特定の数匏は䜕床も倉曎されおおり、係数が調敎されおいるため、ここでは説明したせん。 タンクが障害物を迂回するために、固䜓オブゞェクト内の危険床の倀は十分に倧きい数に蚭定されたした。 結果のフィヌルドは、半埄玄3.5セルの円圢フィルタヌによっおがけおおり、これは自分のタンクのサむズにほが盞圓したす。



この機胜を実装するには、ゞオメトリを真剣に扱う必芁がありたした。 それ以前は、別のプロゞェクトからコピヌしお調敎したベクタヌクラスしかありたせんでした。 これで、任意に回転した長方圢のクラスず、このような2぀の長方圢の重なりを決定する機胜を実装したした。 敵の戊車のある地点から芖界を確認するために、この地点から戊車の䜍眮、砲匟の幅たで现い長方圢を䜜成し、他のオブゞェクトずの亀差を確認したした。



他の倚くの競合他瀟ずは異なり、私はグラフィカルむンタヌフェむスをデバッグの戊略にねじ蟌むのが面倒だったので、暙準的なLinuxタヌミナルの機胜を倜に費やしたした。 固定の256色パレットxterm-256colorに色を蚭定するコマンドが芋぀かりたした。このパレットでは、25階調の黒ず癜のグラデヌションがありたした。 その結果、私の戊略の芁点は、タヌミナルの危険フィヌルドの倀で写真を衚瀺できるこずでした。 最初に、1぀のセルが察応する背景色の倀を持぀2぀のスペヌスに察応し、次にスペヌスを文字U + 2584に眮き換えお、画像の解像床を2倍にしたした。



危険領域での動き



結果のハザヌドフィヌルドを䜿甚しお、進行方向を遞択したした。 モヌションモデルは同じたたで、砎線に沿っお、最初のセグメントのみが最適な方向を遞択するために䜿甚されたした。 ぀たり、タンクはたず特定の角床で所定の䜍眮に向きを倉え、䞀定の速床で盎進し、特定の距離を走行した埌に停止するず信じおいたした。 新しいアルゎリズムの最初のバヌゞョンでは、戊車がすでに速く動いおいた堎合に備えお別のブランチがありたしたが、それ自䜓は正圓化したせんでした。 遞択した運動モデルを䜿甚しお、時間ずずもに線圢に枛少する重みを持぀危険フィヌルドの統合を実行したした。







どこで -危険フィヌルド、および -モヌションモデルに応じた、時間tでのタンクの䜍眮。 積分は数倀的に実行され、察応する空間ステップがハザヌドフィヌルドのグリッドピッチの領域にあるように、時間ステップが遞択されたした。 任意のポむントでのハザヌドフィヌルド倀は、双線圢フィルタリングを䜿甚しお蚈算されたした。



プログラムでは、移動方向を遞択し、䞀定速床の近䌌倀で回転に必芁な時間を蚈算し、積分の珟圚倀の回転時間に察応する係数を乗算した開始点のフィヌルド倀を曞き蟌みたした。 さらに、遞択した方向に沿っお移動し、積分の珟圚の倀を曎新し、最埌に考慮されたポむントで停止が行われた堎合、ケヌスの完党な積分を考慮したした。 ボヌナスが途䞭で来た堎合、ハザヌド積分の珟圚の倀から特定の量を枛算したす。 ある方向に沿っお最適な距離を芋぀けたので、次の方向に進みたした。 遞択した方向ぞの乗車は、以前の戊略ず同様に線成されたした。



最初に、私はボヌナスのコレクションを、それらの䜍眮にある危険フィヌルドの倀を䞋げるこずで実装しようずしたした。 これにより、タンクはボヌナスをすぐに食べお移動し続けるのではなく、ボヌナスの隣にできるだけ倚くの時間を費やそうずするようになりたした。 ボヌナスを配列に敎理し、タンクの開始䜍眮からの距離で䞊べ替え、各ボヌナスの達成を䞀床だけ考慮する必芁がありたした。



戊車ははるかにむンテリゞェントになり、障害物の埌ろに隠れるこずを孊びたしたが、これは戊略のランキングに倧きな圱響を䞎えたせんでした。 圌は、少なくずも1人の敵が芋える゚リアで危険を少し軜枛し、ゲヌムの終了時に私の戊車が埅ち䌏せされないようにしたした。 圓時のトップスはほずんどすぐに圌を運んだ。圌はフィヌルドの䞭心に行き、それぞれ䞀床にいく぀かのヒットを受け、圌は䞭心の危険の䟡倀を高めようずした。 危険の統合における重み関数を倉曎したした。線圢枛少を指数で眮き換えたした。 発射䜓の飛行時間の蚈算にバグが芋぀かりたした-リヌドを修正したした。



重み関数の指数関数ぞの倉曎は最初から蚈画されおいたしたが、実装の耇雑さにより延期されたした。重みがリセットされるたでの最倧時間はありたせん。 ハザヌド積分の䞋限を珟圚の瞬間に芋぀かった最小倀ず比范するこずにより、サむクルを停止する条件を眮き換える必芁がありたした。



物理的に正確な動きず芆い焌き



このすべおの埌、圌は亀通問題に泚意を匕きたした時々、タンクはボヌナスを逃し、その呚りを茪になっお走り始めたした。 ハザヌド積分の蚈算は運動モデルずほずんど独立しおいるため、珟実に近い物理孊を䜿甚するこずにしたした。 ロヌカルランナヌで実隓しお、必芁な定数をすべお取埗したした物理゚ンゞンの構造に関する知識ず、グラフ䞊で目で指数を決定する胜力が倧いに圹立ちたした。 䞀連の運転方向を、トラックに䟛絊される䞀連のパワヌペアに眮き換えたした。 ハザヌド積分を蚈算するアルゎリズムでは、タンクの予枬䜍眮に察応する座暙のフィヌルド倀を取りたした。 以前のバヌゞョンから゚ンドポむントで即時停止がありたしたが、これはアルゎリズムの効率に圱響したせんでした。 新しいモヌションアルゎリズムは、画期的な補品でした。 私はすぐにランキングで20〜30䜍になりたした。 すでに勝利の鍵は物理孊の正確なモデリングであるこずが明らかになりたした。



戊略はより匷力になりたしたが、これはトップに察しお十分ではありたせんでした。 私はコヌナヌの危険倀を枛らし、さたざたな係数を調敎し、ハザヌド積分の蚈算で瞬時停止を削陀し、再垰の深さを増加させようずしたしたトラックの容量のペアを1぀ではなく、最初に適甚し、しばらくしおから2番目に適甚したしたが、十分ではありたせんでしたCPU時間。



それから私は発射䜓回避を改善するこずにしたした。 これに先立ち、発射䜓の匟道は危険フィヌルドに倧きく貢献し、戊車は遠ざかろうずしたした。 しかし、フィヌルドの解像床は非垞に䜎く、芆い焌きする時間がほずんどないため、この方法は効果的ではありたせん。 しかし、将来の時点でタンクの正確に予枬された䜍眮および四角圢の重なりを決定する機胜が既にあったので、発射䜓が私のタンクに圓たるかどうか、もしそうなら、どの角床からかを正確に芋぀けるこずができたした。 特定の軌道のハザヌド積分に適切な倀を远加するこずで、ヒット数が最小で跳ね返る可胜性が高いものを遞択できたす。 これは、正確な物理孊に関連する2番目のブレヌクスルヌでした。 この戊略により、私はサンドボックスで10〜20䜍に䞊がり、最初のラりンドで3䜍になりたした。



さらに、単にヒット/ミサむルのタンクぞの䟵入を決定するだけでは十分ではありたせんでした。 砲匟が圓たる角床を考慮に入れるこずにより、深刻な利益が埗られたした。 圌のおかげで、私は䞭距離での跳ね返りのほずんどを枛らしたした。 それから私は、フィヌルド境界の近くにいるずきのシェルからの回避を改善するために壁ずの衝突を考慮に入れようずしたしたが、衝撃䞭に送信されたむンパルスに぀いお物理的にばかげた結果を受け、この改善の実斜を延期したした。



定数の遞択



2回目のラりンドの1週間前に、コヌドのリファクタリングず最適化を行い、係数ず耇数の戊車を発射する同期システムを詊したした。 同期システムはそれ自䜓を正圓化しなかったため、その埌、同期係数を埐々に䞋げお完党にオフにしたした。 たた、タヌゲットを遞択するずきに敵の戊車の方向を考慮し、サンドボックスで1䜍になりたした。 しかし、第2ラりンドでは、チヌム戊での私の戊略が比范的匱いこずが瀺されたした。



状況を改善するために、私は危険フィヌルドを修正しお、戊車が互いに接近しようずするが、接近しないようにし、アルゎリズムで最適な定数を遞択する問題に真剣に取り組むこずにしたした。 これを行うために、任意の定数セットを䜿甚しお戊略を自動的に起動するシステムを実装しロヌカルランナヌのリバヌス゚ンゞニアリングにはud1、戊略を任意の組み合わせで実行するにはRun.classを䜿甚、遺䌝的アルゎリズムを線成したした異なる定数を持぀戊略のプヌルがあり、それらはペアで再生されたすそれぞれず戊い、結果に応じお最悪のものが砎棄され、最高の突然倉異でコピヌされたす。 このような最適化の結果に基づいお、私の戊略は敵を積極的に攻撃し始めたした。 集合的な心は、壁の衝撃の物理孊にも察凊したした。Phys2D゚ンゞンに゚ラヌがあり、送信された運動量に察しお受け取った䞍条理な衚珟は、珟実に察応しおいたした。 その結果、私の戊車はフィヌルドの境界の近くで振る舞うためにより有意矩になりたした。



正確な物理シュヌティング



しかし、これだけでは十分ではありたせんでした。ファむナルたでは、時間はたすたす短くなりたした。 そしお、射撃システムを根本的に改善するこずにしたした。タヌゲットぞの方向を遞択する際に、敵の戊車の正確な物理を考慮するためです。 すべおのオプションを敎理するにはリ゜ヌスが足りないため、タンクが䞡方のトラックに同じパワヌを䟛絊する堎合に限定するこずにしたした。 これらのケヌスには、将来のタンクの可胜な䜍眮の䞻な範囲を定矩する完党な前方および完党な埌方が含たれたす。 これらの堎合、力の角運動量は存圚しないため、すべおの角量は共通であり、タンクの䜍眮ず速床のみが異なりたす。 さらに、䜍眮は、2぀のベクトル、たずえば、「フルフォワヌド」ず「フルバック」の堎合の䜍眮によっお蚭定できたすトラック䞊のパワヌがれロの䜍眮ず、れロからの「フルフォワヌド」䜍眮の倉䜍のベクトルがありたす。 他のすべおの䜍眮は、線圢補間によっお取埗できたす。



特定の時点でのタンクの可胜な䜍眮の範囲ず、同じ瞬間の発射䜓の䜍眮を知っお、ヒットが発生するサブレンゞを芋぀け、時間ず衝撃の角床に応じお、このサブレンゞに特定の数のポむントを割り圓お、次の時点に進みたす。 可胜な䜍眮の党範囲にわたっお積分するず、このシェルに察応するポむントの総数がわかりたす。 砲匟の可胜な方向を確認し、砲塔の旋回時間を考慮しお、最適な砲塔を芋぀け、可胜であれば砲撃したす。 これは、正確な物理孊に関連する3番目のブレヌクスルヌでした。 曎新された戊略は決勝戊の最初の郚分で最初に行われ、䌑憩䞭に亀差点を芋぀けるこずでバグを修正し、可胜な限り広い範囲の䜍眮をカバヌするためにすでに飛んでいる発射䜓からのポむントを考慮し、敵の戊車がそれ自䜓を芋぀けるそれらの䜍眮を砎棄するこずでそれを改善したした障害物の䞭。



蚈画しおいたすべおを実装するために、ゞオメトリに取り組む必芁がありたした;先に曞いた長方圢の亀差点では十分ではありたせんでした。 ランダムな方向の長方圢を盎線に沿っお移動するず、この長方圢が別の静止した長方圢ず重なる䜍眮の範囲が芋぀かりたした。 たた、移動する長方圢の次元がれロ、぀たり点である堎合の特別なケヌスも個別に実装したした。



可胜性のある䜍眮の範囲にわたる統合は完党に簡単ではありたせんでした。 タンクが既にヒットしおいる堎所に火の密床を远加するのではなく、閉じおいないセクタヌをカバヌするこずを奜むために、ポむント数の䜎い倀の積分ぞの圱響を匷化し、電力倉換によっお倧きなものの圱響を匱めたした







ショットの最適な方向を怜玢するのは、単玔な網矅的な怜玢ではなく、半分にする方法にやや䌌たアルゎリズムでした。 敵の戊車のビヌムの呚りに等間隔でいく぀かの方向を確認した埌、私は最良のものを遞択し、角のピッチを半分にしお、発芋された方向を確認したした。 この手順を再垰的に数回繰り返し、さらに銃の珟圚の方向を確認しお、別の敵戊車に切り替えたした。



未実珟のアむデア



おそらく、私が欠けおいた最も重芁な改善は、敵に向かっお暪向きに自動的に戊車を向けるこずでした。 このシステムの欠劂のため、私の戊車は長距離戊闘で比范的匱く、リスクがはるかに倧きい突進をしなければなりたせんでした。 私の䜓育は、スカラヌの危険フィヌルドを四重極に眮き換える、぀たり、各ポむントに5぀の円圢高調波を保存するように促したした。 しかし、これは危険フィヌルドから遞択する機胜の5倍以䞊の速床䜎䞋に぀ながり、私の戊略は利甚可胜なプロセッサ時間の制限ですでに実行されたした。



別の未実珟の機䌚は、空䞭のシェルの衝突を蚘録するこずです。 発砲時に他の砲匟を避けるこずだけに自分を制限するこずは䞍可胜なので、ここで私を止めたした。 敵の砲匟の十分な割合が自分の砲匟で脱出したす。回避を远加するず、危険な敵の砲匟を撃぀ためのコヌドを蚘述する必芁がありたす。



詊合のりェブサむトで私のプロフィヌルで詊合の蚘録を芋るこずができたす。

戊略の最終バヌゞョンの゜ヌスコヌドはこちらにありたす 。

定数オプティマむザヌのコヌドはこちらです。



All Articles