PostgreSQLでファイヤエフェクト！

この記事は PostgreSQL Advent Calendar 2023 19日目の記事です。

# はじめに
山田です。日本のテレコム会社でPostgreSQLのコミュニティ開発やサポートを担当しています。コミュニティ開発では[コントリビュータ](https://www.postgresql.org/community/contributors/)として認められており国内外で講演も行っています。先週は数年ぶりにPGConf.Eu 2023に参加し主催者・コミッタ・友人と旧交を温めてきました。

# エフェクトプログラムを作りたい
突然ですがエフェクトプログラムをご存知でしょうか。
XX年代に学生だった私は当時流行っていたDiabloのタイトル画面のようなエフェクトをいつか自分自身で作りたいと思っておりました[^1]。

![ファイヤエフェクトの例 Diablo2 resurrectedの公式ページより引用](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380469/e9621138-9b70-8937-3056-ac0c13c72c42.png)

[^1]: Diablo1が見つからなかったため、公式サイト https://diablo2.blizzard.com/ja-jp/ から引用。動いている炎を見たい場合は公式サイトまたは参考に記載の例にアクセスしてください

画面下部の文字から炎が燃え上がっていますね。これがファイヤエフェクトです。

きっかけが何だったのかは失念しましたが、このまま作らずに積み残しのままにしておくのは良くないと考えたため、今年の私のアドベントカレンダーは以下をテーマとしました。

　テーマ: 
 　　　　ファイヤエフェクトっぽいものをPostgreSQLの拡張機能で実現する

# 結論から言うと
作ったものはこれです。

- pg_fireリポジトリへのリンク
    https://github.com/yamatattsu/pg_fire

- デモ
実行例1: psql -c 'call pg_fire(50, 20)' 
    ![result_50_20.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380469/febb7d3b-4441-edd7-dec0-4084433a3232.gif)
実行例2: psql -c 'call pg_fire(40, 50)' 
    ![result_40_50.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380469/5a59d15a-6a81-294b-6b40-7f326da694e1.gif)

右から左に炎が燃えているのがわかります。
頭を90度左に傾ける または ディスプレイを90度右に回転させるとわかりやすいです[^2]。

たとえば、実行例2を右に90度回転させるとこうなります。燃えている感じが伝わると思います[^3]。
![result_40_50_rotate.gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380469/fc2fd0ee-0552-d379-a94e-5f0bcd2351f3.gif)

# 仕組み
- 言語はpl/pgsql
- ファイヤエフェクトのアルゴリズムは以下を参考
    - リンク: [Lode's Computer Graphics Tutorial: Fire Effect](https://lodev.org/cgtutor/fire.html)
- 画素はArray型で管理し、画素にかけるフィルタにはSQLを使用[^4]
- 画面描画には[2年前のアドベントカレンダでASCII movieプレイヤー(pg_ascii_movie)](https://qiita.com/yamatattsu/items/06c797a032b633a9fafa)を開発した経験を活かし、ESCシーケンスを使用 [^5]。

参考にしたアルゴリズムを完全移植したわけでは無いため異なる部分もありますが、それっぽい雰囲気を再現できたと思います。

[^2]: 炎は後日見直し、下->上に向けて動くようにする予定
[^3]: 本記事の冒頭で引用した画像のように文字から炎が上がるところまでは再現していません
[^4]: Cで書くのは芸が無いと思いSQLで書いてみました
[^5]: 本当はフレームバッファに描きたかったのですが難しそうだったので諦めました


# 動かしてみたい方へ
以下の環境の利用をおすすめします。

- [Microsoftのターミナル](https://github.com/microsoft/terminal/releases)
    - 256色表示が必須
    - フォントサイズは 7以下 がおすすめ
        - 設定 -> 規定値 -> フォントサイズ で変更可能
- PGのバージョン
    - 16 (開発時に利用したバージョンのため)
        - CTEのMATERIALIZEDオプション使用のため、12以降なら動くはず

# 実行方法
:::note
前提条件、留意事項
- pg_config が 必要なので PATH を通す
- fire_data, palette, tempテーブルを作成/削除するため、同名のテーブルが存在しない環境で実行
:::

手順のイメージ (各自の環境に合わせて適宜修正してください)
```sql
-- postgresユーザになる
su - postgres

-- リポジトリのクローン
git clone https://github.com/yamatattsu/pg_fire.git

-- インストール
cd pg_fire
make -s install

-- psql起動
psql

-- 拡張機能作成と実行 (psql上で実行)
create extension pg_fire;
call pg_fire(50, 20); --50列20行のサイズで表示
 とか
call pg_fire(40, 50); --40列50行でサイズで表示

-- 終了方法 (psql上で実行)
CTRL+Cで終了
```
Enjoy！

# 注意事項＆制限事項
- ジョークプログラムのようなものです。実行する際は *Do it your own risk* でお願いします
- 画面表示のサイズを増やすと処理が重たくなるため、前述の手順で示した値から試すと良いでしょう
- コードに関する改善提案がありましたら[github](https://github.com/yamatattsu/pg_fire)上でプルリクをお願いします

# おわりに
いかがだったでしょうか。
本記事では、PostgreSQLの拡張機能としてpl/pgsqlでファイヤエフェクトを実現することに成功した例を紹介しました(多少課題はありますが)。ファイヤエフェクトが動くDMBSはPostgreSQLが世界初ではないかと考えます。

個人的にはこの開発により、長年の積み残しを解消することができました。次はメタボールの実現に挑戦してみようと考えています。いつの日かPostgreSQLを使用して[Tokyo Demo Fest](https://tokyodemofest.jp/)に応募できるようになれればと思っています。

というわけで、
みなさん今年もおつかれさまでした！ 良いクリスマスをお過ごしください！

# 参考
ファイヤエフェクトのアルゴリズム解説
- [Lode's Computer Graphics Tutorial: Fire Effect](https://lodev.org/cgtutor/fire.html)

ESCシーケンス関連
- [PostgreSQL でムービーを再生してみた](https://qiita.com/yamatattsu/items/06c797a032b633a9fafa)

ファイヤエフェクトが動いている例
- [Diablo 1: Pre-Release Demo (6s～)](https://www.youtube.com/watch?v=YT-bqWvBovo)