LifeGameをSQLで


先日(12/03)にcoderetreatというイベントに参加してきた。参加の感想は別途ブログに書くかもしれないとして、お題となったライフゲームは、参加して初めて知った。


6人の方とペアプロでこのお題に取り組んだが、すべてPHPで書いた。次回参戦する機会があれば別の言語でチャレンジしてみたい。


このお題を3回くらいペアプロした後で、ゲームのロジック(死活判定)をSQLでできないかなと思ったので書いてみた。
コードの汚さやSQLの美しくなさはご容赦いただきたいが、隣接するマスを表現するのにSpatial Informationを使えないかなと思って書いてみた。
⇒コードはこちら
※ちなみに20x20位のマップで激遅になるので10x5位で動かしてみてほしい。



MySQLにはOpenGIS準拠のSpatial Informationの実装があるが、一部インプリメントされていないfunctionもある。
サンプルコードではマスを座標(POINT)として表現して、2つの座標を持つ線(LineString Class)を作り、長さがルート2以下であると判定しているが、本来は Distance(lg1.p,lg2.p)として計算したかった。
また、更新対象のテーブルをサブクエリに収めてあげないと、自己相関サブクエリによるUPDATEができないのでコピーが必要になったのもちょっと残念。


さらに、マスと考えるならPolygon Classを利用してMBRTouchesとか使えると直感てきだとも考えた。マス表現が GeomFromText(Polygon(0 0,0 1,1 1,1 0,0 0)) として、MBRTouches(lg1.p,lg2.p)で抽出する。


座標計算をして対象を中心とした9マスのPolygonを作成して MBRWithin で抽出する方法も考えたが、GeomFromTextやPolygonの引数をダイナミックな値をCONCATして渡すことができなかった(Illegal value)のであきらめた。時間があったらチャレンジしてみたい。


今回の方法なら、x,yをint型の別カラムにして
(POW(lg1.x-lg2.x,2)+POW(lg1.y-lg2.y))<=2
でも同じことなんだが、せっかくSpatial Informationを使おうと思ったので....