Daydreaming in Brookline, MA

DL-12; データベースをサポート

1 はじめに

Rogue+Wizライクなゲーム(DL - Daemon Lord)を作るプロジェクトの12回目です。

githubでコードを 公開 しています。MacとLinuxで動作確認していますが、Windowsは未検証です。(いちおうWindows用のコードは入れてみました。Macは立ち上げ確認くらい。。)

2 データベース対応

2.1 DLのデータベース対応

DLはこれまでセーブデータをpickleしてファイルにセーブしていたのですが、データベースを使ってみたかったのでサポートしてみました。セーブするときには全部セーブして、ロードするときも同様という使い方なので、データベースにしたメリットは今のところほぼありません。それどころか、セーブに数秒かかるようになってしまいました。

使ったのはSQLAlchemyという有名なライブラリで、object relational mapping (ORM)を選択しました。バックエンドには設定の楽なsqlite3を使っています。

「データベースに変えたからこれまでのセーブデータは使えなくなりました」とは言えないので、DBファイルが無い時には従来のセーブファイルからデータをロードできるようにしました。

2.2 データベース/SQLAlchemyを使ってみて

SQLはLearning SQLという入門書を読んだくらいで、ネットで検索しながら基本的なSELECT * FROM <table>のようなコマンドが使える程度でした。SQLAlchemyのチュートリアルも目を通しました。

実際にPythonのオブジェクトをDBに書き込むためのテーブル構造を考えてみて、Python(だけではありませんが)とSQLの相性がとても悪いことがわかりました。SQLにはリストも配列も無いのです! いろいろ調べてみて、リストや配列等のオブジェクト間の関係を規定するデータ構造のために、テーブルを作るのが普通であることがわかりました。これはSQL初級者の私には衝撃的な気づきでした。

また、sqlite3のデータタイプが貧弱であることも驚きでした。なんと、NULL, INTEGER, REAL, TEXT, BLOB の5種類しか無いのです。ネットで調べると、BooleanはIntegerを使い、EnumはTextで表現するらしいことを知り、やはりショックを受けました。しかしここはSQLAlchemy(SA)が補強してくれていました。SAのお陰で、PythonのTrue/FalseやEnumをそのまま使えるのは非常に助かりました。

デバッグも少し大変でした。ORMを使って抽象化されたPythonオブジェクトを介してデータベースにアクセスしているのに、問題が起こると、結局はデータベースが想定通りに反映されているのかを確認するために、sqlite3のコマンドラインからSQLコマンドをたたく必要がありました。

今回はデータベースを使ってみたかったので自己満足していますが、プログラムの比較的単純なステートを永続化するためにデータベースを使うのはやりすぎ(overkill)であると思いました。フラットファイルにpickleする方が簡単だし性能もよかったです。

3 次の構想

次回作ですが、特に面白いアイデアがあるわけでも無いので、使ってみたい技術を使ってDLをマルチプレイヤー化してみたいと考えています。実はDLのデータベース化はその準備の一環です。他には、クライアント-サーバー化と、サーバーのasync対応をやりたいと考えています。ライブラリとしてはpython-socketioflask-socketioあたりに目を付けています。

WizardryクローンであるDLの戦闘はターン制なので、マルチプレイヤー化には向いていない気もしますが、逆にターン制であることをうまく生かした戦闘システムができないかを考え中です。