psql上でHit&Blow

ジョジョ、俺はソリティア社員になるぞー!

先日、某所でソリティア社員の記事を見て、カリスマ給料泥棒を目指す俺としては
そこにシビれる!あこがれるゥ!
のであったのだが、会社のPCにはソリティアがインストールされていないw
今、使っているノートPCにもたぶんインストールされていない。

だが、VM上にはPostgreSQLがインストールされている!(会社ならサーバ上にPostgreSQLがインストールされている)
ならば、PostgreSQL上で遊べるようにすればいいじゃなイカ

ということで、PostgreSQLの非同期通信機構のLISTEN/NOTIFYを使って、Hit&Blowっぽいゲームを作ってみた。

そういえばPostgreSQLの非同期通信機構って、あんまり使われてない印象があるのよね。
なので、それを勉強するって意味も(1割くらい)ある。

残念ながらLISTENをpsqlpl/pgsqlだけでハンドリングすることは出来ないので、妥協してlibpqアプリとして作成することにする。
このlibpqアプリを起動しておけば、psqlからNOTIFYコマンドを送ることで数当てが出来るようになる。

幸い、libpqアプリは src/test/examples/testlibpq2.c という良いサンプルがあるので、それをちょっと改造するだけでOK。
具体的には

  • ランダム数の生成
  • NOTIFYで送信された数のHits&Blowsを判定して、その結果をクライアントであるpsql(もちろんpsql側でも1つLISTENしておく)に送信。

だけで実装できた。

とりあえず、こんな感じ。
数当てサーバを起動する(とりあえずデバッグ用なので数当て用の数も表示している)。

$ ./hb
number=1476

この状態でpsqlを起動し、数当てサーバから通知されるチャネル(H_B_CL)をLISTENしておく。

$ psql postgres
 ┌(┌ ^o^)┐ ウィンドォ・・・

psql (9.3.0)
Type "help" for help.

postgres=# LISTEN H_B_CL;
LISTEN
postgres=# 

以降、数当てサーバでLISTENしているチャネル(H_B_SV)にNOTIFYコマンドで数字列を通知すると、サーバ側で持っている数値と比較して、Hit数とBlow数を H_B_CL チャネルに通知する("with payload"の後のメッセージがそれ)。
psqlでは、何らかのコマンドを実行した後の契機でLISTENしているチャネルに送られたメッセージを表示する。

postgres=# NOTIFY H_B_SV,'1234';;
NOTIFY
Asynchronous notification "h_b_cl" with payload "1 Hit / 1 Blow." received from server process with PID 45404.
postgres=# NOTIFY H_B_SV,'1470';;
NOTIFY
Asynchronous notification "h_b_cl" with payload "3 Hit / 0 Blow." received from server process with PID 45404.
postgres=# NOTIFY H_B_SV,'1476';;
NOTIFY
Asynchronous notification "h_b_cl" with payload "4 Hit! Conguratulatoins!, next new game." received from server process with PID 45404.
postgres=# 

4 Hit(正解)すると数当てサーバは新たに秘密数を生成する。

ゲームとしては他愛ないのだが、重要なのはpsqlコンソールから数当てが出来ることw
なので、例えばSELECT文とか \d などのコマンドの入力に紛れて、こそっとNOTIFYすればゲームが出来ることが重要なのだw
まさか、上司もpsqlを弄っている俺がゲームをしているとは思うまいwww
(このソースはもうちょっと綺麗にしてからGithubにアップする予定)

例えばこんな感じ。

postgres=# \d
No relations found.
postgres=# NOTIFY H_B_SV,'1234';
NOTIFY
postgres=# SELECT now();
              now              
-------------------------------
 2013-09-13 06:26:05.335227-07
(1 row)

Asynchronous notification "h_b_cl" with payload "0 Hit / 1 Blow." received from server process with PID 45404.
postgres=# 

この機構を使って、もっと真面目に作りこめば多人数のchatや対戦ゲームも作れるはず。
夢がひろがりんぐwww

ソリティアやってるのはバレやすいが、psqlコンソールならバレにくいし。