Pythonエンジニアの @kimihiro_n です。 今回は先日行った社内勉強会の話を。
社内勉強会
弊社では月1回、社内の開発者で勉強会を行っています。 内容はLT大会だったり、もくもく会だったり、ハンズオンだったりと幹事の人が好きにテーマを設定して実施しています。 おすすめの本を持ち寄ってビブリオバトル をやった時もありました。
今回、久しぶりに自分の担当が回ってきたわけですが、「AI同士の対戦」みたいなのやってみたいなーと前から思ってました。 AIというと大げさですが、各自プログラムしたゲームのCOM(CPUともいう)を持ち寄って、誰が一番強いのかを決めるみたいな内容です。 ニュースや報道の自動化を進めている弊社のエンジニアだったらゲームの自動操縦だってお手の物のはず…!
COM VS COM で一番強いチームを決める
実際にどうやってプログラム同士を戦わせるかですが、頭に浮かんだのは昔あった「カルネージハート」というゲームです。 アルゴリズムを組み込んだロボット同士を3on3で戦わせて遊ぶゲームなのですが、これがよく出来ていて一時期PSP版にハマっていました。 コーディングはテキストではなくてGUIのパネルみたいなのを並べて作るのですが、条件分岐やループ、関数的な別モジュールの利用といったようにかなり高度なことまで実装できます。 なのでカルネージハートとPSPを人数分用意して…と言いたいところですが、無理だったので代替案を考えることにしました。
ゲームを作る
Web 上でそういったプログラム同士の対戦をするサイト、どこかで見かけた覚えがあったので当初それを掘り起こして使おうと思ってました。 しかしサイト自体が閉鎖してしまったのか検索が甘かったのか、望みのものが見つかりませんでした…。 こうなったら自作するしか…ということで1人ハッカソンを始めました。
作りたいゲーム
- 操作が単純である
- ルールも単純である
- 言語に不慣れなエンジニアでも楽しめる
- 運要素が少ない(頑張ればその分勝ちやすい)
- 2人1チームでも協力できる
ぱっと浮かんだ要件は上記のような感じでした。 勉強会の枠は2時間なので、その中で準備・実装・試合をこなすにはそれなりにシンプルであることが重要です。 また開発者といっても「サーバーサイドエンジニア」「アプリエンジニア」、「MLエンジニア」のように専門がそれぞれ異なります。 普段その言語を書いているエンジニアが強くて、他のエンジニアは動かすので精一杯みたいなのだと面白みにかけてしまいます。 なので基本文法を抑えていれば楽しめるようなゲームが望ましいです。 あとはプログラムを改善した分だけ強くなれる性質があったらなー、とか2人で分担や相談できたらなーみたいなことを漠然と思っていました。
Pong ゲーム
いろいろ考えた末思い浮かんだのが Pong ゲームでした。 操作が上か下かの2択でシンプル。ルールもボールを跳ね返して相手のゴールに入れるだけで単純です。 また、複数バーを用意することでチームっぽさも出すことができます。 ボールの動きが単純なので最終的な移動地点を予測してしまえば終わってしまう欠点はあるのですが、勉強会の短い時間であればちょうどいい難易度かなというのもポイントです。
Pyxel で作る Pong ゲーム
作るものが決まったので早速実装です。 当初みんな馴染みが多いだろうと Javascript で実装する気満々だったのですが、事前アンケートを取ってみたら Python のほうが慣れてる人多くて Python で作ることにしました。
ちょうど Python で使ってみたかった Pyxel(ピクセル) というゲームエンジンがあったのでこれ幸いと利用してみることに。
サンプルにあるように
import pyxel pyxel.init(160, 120) def update(): if pyxel.btnp(pyxel.KEY_Q): pyxel.quit() def draw(): pyxel.cls(0) pyxel.rect(10, 10, 20, 20, 11) pyxel.run(update, draw)
Pyxel 初めて触ったゲームエンジンですが、updateで毎フレームの内部状態を更新して、drawでレンダリングしてあげれば利用できるというシンプルな仕組みでとても書きやすかったです。 ドット絵を描くエディタやサウンド編集ツールなんかもついていてかなり凝ったゲームも作れそうです。今回は時間なくてシンプルなドットを描画するのみにとどまりましたがいつかちゃんとしたゲーム作りもチャレンジしたいです。
で、なんとか出来た対戦ゲームがこちら。 当たり判定に若干怪しいところとかがありますが、大きな理不尽なく遊べるくらいにはなりました。 コマンドラインの引数でチームのプログラムへのモジュールパスを受け取って対戦が可能になっています。
def atk_action(self, info: GameInfo, state: State) -> int: return random.randint(-2, 2) def def_action(self, info: GameInfo, state: State) -> int: return random.randint(-1, 1)
各自に実装してもらうものも極力シンプルにしていて、毎フレームごとに呼び出される関数が何を返すかで前衛、後衛が上下に移動する仕組みになっています。 Python 不慣れでも苦なく動かせるのではないでしょうか。
pip で配布
Python で作ったゲーム、どうやって配布しようと思っていたのですが、pip で配布してしまえばいいのではという事に気づいてしまったので pongpy
という名前で登録しました。
PC ゲームつくるならこの配布方式強いですね。アプリ化とか考えると Python では鬼門ですが…。
勉強会当日
チームビルディング
事前告知してインストールに支障がないかとかを見てもらいつつ、勉強会を迎えました。 最初にペア or ソロ参戦かでチームを作ってもらい、1時間強ほど実装を進めてもらいました。
また1セットごとに左右が入れ替わって戦う仕組みをいれてあるのですが、ここへの対応をちゃんと入れないと前衛が自チーム側にボールを返して自爆してしまうみたいな罠があります。 実装の後回しになってしまいやすい部分ですがちゃんと考慮してくれたチームがいくつかあって開発者冥利に尽きました。
トーナメント
実装が出揃ったらいよいよトーナメント戦です。 GitLab にレポジトリを作って、マージリクエストという形でソースコードを出してもらいました。