RuneCast は、 北欧 の ルーン文字 (Elder Futhark 24 文字) を 投げて 引く 占い。 石 を 転がす 演出 の あと、 正位置 / 逆位置 の 意味 と 助言 が 出ます。 引く 処理 は すべて ブラウザ の 中 で、 質問 文 も サーバー に 送られ ません。
#🎯 タロット と 同じ 作り に しない
占い 系 は これ が 何本目 か という 状態 で、 すでに 数秘術 ・ タロット ・ マヤ暦 ・ 十干十二支 ・ 西洋占星術 が 並んで いました。 一番 近い の は タロット (ArcanaFlip) です が、 同じ 「カード を めくる」 体験 を もう 一度 作って も 意味 が ありません。
ルーン に は タロット に ない 前提 が 2 つ あります。
- 文字 数 が 24 と 少なく、 1 文字 ずつ に 名前 と 意味 が ある
- 文字 の 形 が 左右対称 な もの は、 逆位置 が 存在 しない
この 2 つ目 が 決め手 でした。 78 枚 すべて に 正逆 が ある タロット と 違い、 ルーン は 形 の 都合 で 逆位置 を 持て ない もの が ある。 これ を 実装 に 落とし込む と、 それ だけ で 別 の ツール に なり ます。
#🏗️ 「逆位置 を 持て ない ルーン」 を データ に 持たせる
各 ルーン に reversible を 持たせ ました。
export interface Rune {
id: string
glyph: string // ᚠ ᚢ ᚦ …
name: string // 翻字 (Fehu / Uruz …)
jp: string // フェフ・家畜
keyword: string // 富 / 豊かさ
upright: string
reversed: string
reversible: boolean // 対称形 なら false
aett: 1 | 2 | 3 // 3 つ の アエッティル
}reversible: false に なる の は、 ハガラズ (ᚺ 雹) ・ イサ (ᛁ 氷) ・ ヤラ (ᛃ 収穫) ・ エイワズ (ᛇ イチイ) ・ ソウィロ (ᛊ 太陽) ・ ギューフ (ᚷ 贈り物) ・ イングワズ (ᛜ) ・ ダガズ (ᛞ 夜明け) — いずれ も 上下 を ひっくり返して も 同じ 形 に なる 文字 です。
引く 処理 は こう なり ます。
export function castRunes(spread: Spread): DrawnRune[] {
const pool = [...RUNES]
const out: DrawnRune[] = []
for (let i = 0; i < spread.count; i++) {
const idx = Math.floor(Math.random() * pool.length)
const rune = pool.splice(idx, 1)[0] // 重複 なし
const reversed = rune.reversible && Math.random() < 0.5
out.push({ rune, reversed, position: spread.positions[i] })
}
return out
}rune.reversible && の 一語 だけ で、 「対称 な ルーン は 何度 引いて も 必ず 正位置」 が 成立 します。 逆位置 を 持た ない ルーン に は、 「逆位置 なし」 と 明記 した うえ で 停滞 側 の 読み を 添え ました。 ハガラズ の ように もともと 試練 を 意味 する 文字 は、 正位置 の まま で 十分 厳しい ので、 無理 に 逆 を 作ら ない 方 が 伝統 に 沿い ます。
#🔑 24 文字 を 3 つ の アエッティル に 割る
Elder Futhark は 8 文字 ずつ 3 群 (アエッティル) に 分かれ ます。 第 1 が フレイヤ、 第 2 が ヘイムダル、 第 3 が テュール。 aett: 1 | 2 | 3 を 持たせて 一覧 を 区切る と、 24 個 の 羅列 が 意味 の ある 3 ブロック に 見え ます。
スプレッド は 3 種類 に 絞り ました。
| スプレッド | 枚数 | 位置 |
|---|---|---|
| 一筋 | 1 | 今 の 導き |
| 運命の三女神 | 3 | ウルド (過去) / ヴェルザンディ (現在) / スクルド (未来) |
| 五連の石 | 5 | 状況 / 障害 / 助言 / 基盤 / 結果 |
三女神 の 名前 は 北欧神話 の ノルン から 取って います。 「過去 ・ 現在 ・ 未来」 と だけ 書く より、 ウルド / ヴェルザンディ / スクルド と 併記 した 方 が 世界観 が 立ち、 検索 でも 拾わ れ ます。
#😓 苦労した ところ
引く 前 の 間 (ま)。 ボタン を 押した 瞬間 に 結果 が 出る と、 占い に なりません。 石 が 転がる 演出 を 挟んで 850ms 待ち、 その 間 は 結果 を null に 戻して います。 短すぎる と 軽く、 長すぎる と ただ の 待ち時間 に なる ので、 数字 を 何度 か 振り直し ました。
逆位置 の 表示。 逆位置 の ルーン は CSS の rotate(180deg) で 実際 に ひっくり返して います。 文字 が 上下 逆 に 見える こと 自体 が 説明 に なる ので、 ラベル より 先 に 形 で 伝わり ます。
ルーン文字 の フォント。 ᚠ ᚢ ᚦ … は 環境 に よって 豆腐 (□) に なる 可能性 が あり ます。 実機 で 確認 し、 グリフ が 出ない 場合 に 備えて 翻字 (Fehu) と 日本語 通称 (フェフ) を 必ず 併記 する 構成 に しました。
#🔭 今後 の 拡張
- 質問文 から 決定的 に 引く モード (同じ 問い なら 同じ 結果 に なる ハッシュ 方式)
- ルーン 1 文字 ずつ の 解説 ページ (24 文字 × 語源 ・ 神話 ・ 現代 の 読み)
- 引いた 履歴 を 端末 内 に 保存 して 振り返る
- 石 を 布 の 上 に 投げて 落ちた 位置 で 読む 「キャスティング」 方式
#💡 この サービス から 言える こと
題材 に 固有 の 制約 が ある なら、 それ を 実装 に 落とす と 差別化 に なり ます。 「対称 な 文字 は 逆位置 を 持た ない」 は、 知って いれば 一行 の 条件式 です が、 知ら ずに 作る と ただ の 24 枚 カード に なり ます。
占い 系 は 見た目 だけ 変えて 量産 でき て しまう 領域 です。 だ から こそ、 その 文化 の 中 で 何 が 決まって いる の か を 先 に 調べる 方 が、 結果的 に 早く 別物 に なり ました。
[ ./next_action ]
読んだら、 RuneCast を実際に動かす。
この開発ログは RuneCast をどう作ったかの記録です。 読み終わったらそのままサービス本体へ戻って、 実物で価値を確かめてください。