はじめに
ソフトウェアエンジニアの奥谷です。ソフトウェアエンジニアを名乗っていますが、製品のコードを書くことは少なく、製品が使うデータをきれいにするために、書き捨てのコードをたまに書く程度のソフトウェアエンジニアです。
そんな私が模擬コーディング面接を社内で受けたところ、計算機科学の知識はあるしプログラムの大まかな設計はOK。でもコーディングに慣れていないと、予想通りかつ正当な評価を受けてしまいました。
もちろんコーディングに慣れた方が良さそうだけど、練習を兼ねて製品に乗るコードを書いたら負債が生まれそう……。そんなとき丁度松本さんにCodinGameを教えてもらい、Spring Challenge 2022に誘われたのでふらっと参加しました。今回は高度なデータ構造を駆使しないし、高度なアルゴリズムを書いたわけでもないです。
それでも初参加でGold Leagueに到達できたし楽しかったので、大まかな戦略とCodinGameの感想をまとめます。
CodinGame
CodinGameとは、キャラクタの動きをプログラムして、ゴールを目指したり高得点を出したりして楽しむサービスです。例えば、キャラクタの移動をプログラムして迷路を解かせたり、相手チームとサッカーをしたりルールが与えられます。1日参加しただけなので説明が偏っているとは思いますが、初参加ではこんな印象を持ちました。
私は勝つことよりもアイデアを考えるのが好きなので、自分が考えた戦法通りにキャラクタが動くことを目指しました。コーディングの慣れに繋がりそうだし、勝利よりアイデアを競う「アイデア対決」の高専ロボコンに似て楽しめます*1。
Spring Challenge 2022
Spring Challenge 2022は、以下の公式動画で紹介されているようなリアルタイム防衛対戦ゲーム(?)がテーマです。
左上と右下に各プレイヤの基地(base)があり、それぞれ3人のヒーロー(heroes)を操作するプログラムを書きます。ステージを移動するモンスター(monster)が自分の基地に到達しないようにヒーローの動きをプログラミングします。ヒーローはモンスターの2倍の速度で移動でき、近づくとそれだけでモンスターを攻撃します。
また参加者はBronze, Silver, Goldなどのリーグに分かれ、リーグを進むと可能な行動が増え、対戦相手が強くなります。私は今回Goldリーグ(入ったときは上位約10%?)まで到達できました。
参加
まずはSpring Challenge 2022の前に、チュートリアルのLoop(繰り返し動作)とCondition(条件分岐)を解きました。チュートリアルも終え*2、「CodinGame完全に理解した」ということで、早速Spring Challenge 2022に参加しました。特にお金が取られるわけではないので、皆さんも軽率に参加してしまいましょう(時間は取られます)。
Spring Challenge 2022のゲームのルールを読んでいたら、なんとスターターキットが用意されているではありませんか。とりあえずこれを送信すればキャラクターが動くので、これでスーパーエンジニア気分です。
ファイル名にはAIと書かれていても、あくまで「スターターキット」です。機能もスターターキットでしかありません。各ヒーローは適当にモンスターに向かって移動するだけで、自分の基地にモンスターが向かっていても知らんぷり……。もぬけの殻となった基地にモンスターが突っ込んで負けることも多いです。
エラーは起きてないけれど、下手なプレイを見せられると「俺ならもっとうまく動かせるはずだ」とやる気が起きます。わざと下手なプレイを見せるスマフォ広告のように、私はまんまとのせられてCodingをしてしまいます。
戦略(設計思想)・戦法(プログラム)
冒頭で述べた通り、すごいアルゴリズムよりもまずは「自分が考えた戦法通りにキャラクタが動くこと」を目指します。戦っている様子はすぐに動画で確認できるので、そこで気になった点を戦法に取り入れます。
例えば...…
ランダムでモンスターを選んで攻撃するんじゃなく、自分の基地に向かっているモンスターを優先的に攻撃したい
自分の基地に向かっているモンスター(つまり失点に繋がるモンスター)を優先的に攻撃するようにプログラムします。なんと、自分の基地に到達するかは計算しなくてもモンスターが値として持っているので、複雑な計算はいりません。
対処するモンスターがいないなら、基地を囲むようにヒーローを配置して素早く対応できるようにしたい
自分の基地に向かっているモンスターがいなかったら、ヒーローは基地を取り囲む陣形を組むようにプログラムします。
自分の基地に向かっているモンスターの中でも、自分の基地から近いモンスターを優先的に攻撃したい
自分の基地からの距離を計算する関数を実装し、モンスターを自分の基地から近い順に攻撃するようプログラムします。
とりあえず実装したのでこのコードでプレイ動画を見ると、改修前のスターターキットよりもうまく戦えていそうです。自分の基地に向かうモンスターを優先して狙うだけでも失点はかなり減り、デモプレイでの勝率も順位も上がりました。送信前にデモプレイで動きを確認できるのも、CodinGameの親切な設計だと思います。
でもまだまだプレイ中に気になる点はあります。
ヒーロは連携して、各ヒーローが近いモンスターを攻撃しに行かないと、無駄な動きが多くて気になる
モンスターまでの距離の合計が小さくなるようにし、より早くモンスターを対処させます。図で書くとこんな感じです。
自分の基地を狙っていても、遠いモンスターは、(どうせ近付いてくるんだし)近づいてから対処したい
基地に近いモンスターだけを対処すべきモンスターにします。
このようにアイデアは際限なく思いつくので、思いついた戦法を実装しては送信していると、次のリーグに進めました。リーグを進むと、色んな要素が開放され、例えば魔法が使えるようになります。
- WIND
- 自分の近くにいる全キャラクタを、指定方向に移動させる(射程=半径1280)
- CONTROL
- 特定のキャラクタ1体を、指定方向に移動させる(射程=2200)
- SHIELD
- 特定のキャラクタ1体を、今後12ターンの間は魔から守る(射程=2200)
また、これらの魔法を使うためにはマナ(mana)が10ずつ必要であり、マナはモンスターを攻撃すると手に入ります。
攻撃と防御の役割や、時間やマナの量で戦法を変えるなど、少し高度な思いつきもプログラムしました(詳細は割愛)。役割や戦法のそれぞれで10個以上の条件分岐を書き、美しくはなくても「自分が考えた通りの」戦法を実装しました。各盤面で嬉しくも悲しくも書いたとおりにヒーローは動きます。
朝5時
16時頃に始めたCodinGame、気がつけば夕飯も食べずに朝5時になっていました。それでも戦法はまだ思いつきます。
- 2人で協力してWINDをすると移動距離は足し合わされるので、相手の基地の近くで複数人同時WINDをやってみたい
- 相手のヒーローが自分の基地に近づいているかによって、戦い方を変えたい
- 2体以上のモンスターを同時に攻撃する場所にヒーローを移動させたい
- 常にモンスター方向に移動するのではなくモンスターの行き先を考慮してより早く到達させたい
もはや当日となった翌日にも用事があり、朝5時なので寝ることにしましたが、布団の中でも戦法を考えてしまいます。チャレンジ終了まで4日ほど残っていましたが、体調や生活を考えて今回のチャレンジはここでやめることにしました。正直、やめることにしても戦法を考えてしまいましたが……。
Silverリーグで終えましたが、起きたらGoldリーグに到達したメールが届いていました。800thくらいにいた気がします。(最終日には2000thくらいまで落ちていました。)
感想
初日で朝5時まで(10時間ほど)やってしまうほど楽しかったです。終わりやクリアがないのは恐ろしいと思いました。CodinGameにはクリアがあるモードもあるので、これからは、寝食を忘れないようそちらを少しずつやっていきます。(でも、チャレンジの方が100倍楽しそう)
食が好きな私でもCodinGameで1回分は寝食を忘れられました。もっと寝食を忘れられる人には適わないと思いますが、趣味でのプログラミングをほぼしてこなかった私でも1回分は寝食を忘れたので相当楽しいサービスだと思います。
振り返ってみると、「何を学べたのか?」と考える部分もありますが、これは成長を焦りすぎだと自分で感じています。今回はコーディングに慣れればそれだけで成果なのです。
namedtupleを使えたのも成果です(使いやすいだけで自然科学っぽくないと軽視していましたが、書きやすかった)。それがなくても楽しかったし、人生は楽しむためのものなので、参加するだけで得です。
最後に
estieは今回初挑戦も多いながらも会社で100位以内に入りました。初参加で個人1000位以内に入った人もいるようです。estieの人たちが日が進むにつれて私を追い抜いていくことに安心と焦りを感じながら最終日までじっと過ごしました。今はその人たちと感想戦がしたいです。
感想戦がしたい人、会社に興味を持ってくださった方はご連絡ください。