算命学ロジック完全仕様

算命学ロジック完全仕様

一言で

算命学アプリ(sanmei.takamimusubi.com)の計算ロジックを全部書き出した仕様書。別のAIがこれだけを読んで、同じ入力に同じ出力を返す実装を作れる。

付録(別ノート)

ノート 中身
付録A_データテーブルと生成スクリプト 節入り・新月満月・祝日の実データと、再生成スクリプト
付録B_鑑定レポート文章テーブル report_text.js 全文(15章の組み立てと固定文)
付録C_相性の固定文 相性の読み方の固定文(REL_TEXT ほか+aisho_detail.js)
付録D_参照実装エンジン engine.js 全文(正)
付録E_観測と調査の記録 規則を実在アプリの出力から割り出した経緯
付録F_テストベクタ 答え合わせ用データと、全量生成スクリプト

共有ページ(ブラウザで開ける)

付録A

付録B

付録C

付録D

付録E

付録F

目次

    1. このノートについて
    1. 全体像
    1. 基本定義
    1. 暦:柱の決め方
    1. 陽占(人体図)
    1. 天中殺
    1. 異常干支
    1. 位相法(支どうしの関係)
    1. 数理法・八門法
    1. 身強・身弱
    1. 行動領域(宇宙盤)
    1. 六親法(家系図)
    1. 才能(剋数・才能星・型・運)
    1. 定位置(ていいち)
    1. 教育の干支・教育の星(口伝)
    1. 大運(10年ごとの流れ)
    1. 行運(年運・月運・日運・時運)
    1. 相性(2人の比較)
    1. 暦注(吉日・凶日・祝日・月相)
    1. 検索(条件に合う日を探す)
    1. 鑑定レポート(15章)
    1. つまずきやすい所(実装の癖・既知の限界)
    1. テストベクタと検証の記録

0. このノートについて

目的

算命学アプリ(https://sanmei.takamimusubi.com ・リポジトリ名 sanmeigaku-app)が 内部でやっている計算とその順序を、すべて書き出したもの。
このノートだけを渡された別のAI(または人)が、同じ入力に同じ出力を返す実装を一から作れることを目標にしている。

0.1 何が書いてあるか・何が書いてないか

区分 内容 このノート
命式の計算 暦(年柱・月柱・日柱・時柱)、蔵干、陽占(人体図)、十二大従星、天中殺、異常干支 ✅ 全部
応用技 位相法、数理法・八門法、身強身弱、行動領域、六親法、才能(剋数・型・運)、定位置、教育の干支・教育の星 ✅ 全部
運勢の流れ 大運、行運(年運・月運・日運・時運)と一覧 ✅ 全部
相性 2人の相性(五行のかたち・天中殺・位相法・身強身弱・共通の星・干合)と、間柄別の詳しい読み ✅ 全部(本文は付録C)
暦注 吉日・凶日(天赦日・一粒万倍日・寅の日・巳の日・己巳の日・三隣亡)、祝日、新月・満月 ✅ 全部
検索 条件に合う日を探す(AND/OR条件、惜しい日、蔵干の流派違いでも成立する日) ✅ 全部
鑑定レポート 15章の組み立て条件(どの値のとき、どの固定文を選ぶか) ✅ 条件は本文、固定文の全文は付録B
データ表 節入り・新月満月・祝日 ✅ 形式と再生成の手順は本文、実データは付録A
AIの文章生成 命式をAIに渡して人物像を書かせる部分 ❌ 含めない(算命学の計算ではなくプロンプト)
姓名判断・タロット・九星気学 同じアプリの別タブ ❌ 含めない(別の占術)
画面(HTML/CSS)・ログイン・保存 UI ❌ 含めない

0.2 読み方

  1. §1〜§2 で全体と基本定義をつかむ
  2. §3 の暦の計算が土台。ここが1日ずれると全部ずれるので、§22・付録F のテストベクタで必ず確かめる
  3. 以降は依存順に並べてある(§4 陽占 → §5〜§9 → §10〜§14 応用技 → §15〜§16 運勢 → §17〜§19)
  4. 迷ったら 付録D(参照実装 engine.js の全文) を正とする。このノートと参照実装がずれていたら、参照実装が正しい。

0.3 表記

  • 擬似コードは JavaScript 風。配列の添字は 0始まり。
  • a || b は「a が偽(null・未指定・0・空文字・false)なら b」。a ?? b は「a が null・未指定のときだけ b」。オブジェクトや配列は(空でも)真。
  • mod(a, n) は 常に 0 以上 を返す剰余:((a % n) + n) % n
  • floor(x) は切り捨て。round(x) は四捨五入(x.5 は切り上げ。ただしこのアプリで round に渡る値は3で割った数なので .5 になることはない)
  • 日付はすべて グレゴリオ暦・日本標準時(JST, UTC+9)。時刻の入力は「0〜23の整数の時」だけ。
  • 「干」=天干(甲乙丙丁戊己庚辛壬癸)、「支」=地支(子丑寅卯辰巳午未申酉戌亥)。

擬似コードの日本語名と、命式 a(§1.2)のキーの対応

擬似コードの書き方 命式 a のキー
年干・年支・年柱の干支 a.pillars.year.kan / .shi / .kanshi
月干・月支・月柱の干支 a.pillars.month.kan / .shi / .kanshi
日干・日支・日柱の干支 a.pillars.day.kan / .shi / .kanshi
柱の通し番号 a.pillars.<year|month|day>.no
採用した蔵干 a.pillars.<柱>.zokan
蔵干の3段(初元・中元・本元) a.pillars.<柱>.stages
中心・社会・目上・目下・配偶者・ご先祖様の星 a.stars.center.star / .east / .north / .south / .west / .ancestor
初年・中年・晩年の従星 a.jusei.early / .mid / .late(.name・.energy・.unsei)
本人の天中殺・その2支・親の天中殺 a.tenchusatsu / a.tenchusatsuShi / a.tenchusatsuYear
時柱 a.hourPillar(出生時が無いとき null。.kan・.shi・.kanshi・.zokan・.no…)
相性の meA・meB の日干・日支・月支・年支 meA.pillars.day.kan・meA.pillars.day.shi・meA.pillars.month.shi・meA.pillars.year.shi(meB も同じ)
流派差について(最重要)

算命学は流派で結論が変わる。このアプリの規則は文献からではなく、実在する2つの算命学アプリの出力を観測して逆算している
(kantei-app.com … 陰占・陽占・大運・数理法/sanmei-stock.com の高尾式 … 伴星・六親法・才能)。
したがって「他の流派の本と違う」箇所がある(特に 蔵干の区分 と 六親法の定位置)。
別の流派に合わせたい場合は、その箇所の表だけ差し替えればよい作りになっている。

0.4 検証の状況(2026-10-05 時点)

検証 結果 今回(2026-10-05)再実行
実在アプリ kantei-app.com の出力165ケースと全項目を照合(三柱・干支番号・蔵干3段・採用蔵干・人体図5マス・従星3つ・天中殺2種・大運12本) 165/165 一致 ✅
六親法を sanmei-stock の出力と照合(規則を決めた221日×7人=1547項目、取り直した追試72日×7人=504項目。理想の干・実際の干の両方) 1547/1547、504/504 一致 ✅
吉日・凶日を暦と照合(天赦日12か月・一粒万倍日6か月・寅巳の整合60日) 一致 ✅
節入りテーブル 2,412件を sxtwl で再生成 2,412/2,412 完全一致 ✅
新月・満月テーブル 4,973件を gen_moon_table.py で再生成 完全一致 ✅
祝日テーブル 2,459件を jpholiday 1.0.3 で再生成 完全一致 ✅
才能(剋数・型・運)を sanmei-stock と照合 176日ぶん全一致(元リポジトリの記録) —
JS実装とPython実装を1950〜2040年の全33,238日で突き合わせ 完全一致(元リポジトリの記録) —
このノートだけから別のAIが再実装した結果を、参照実装のゴールデン出力と照合 §22.4 に記録 ✅

1. 全体像

1.1 入力と出力

入力   西暦 y, 月 m, 日 d                … 1901〜2100年(§3.9)
       性別 gender                       … 'male' | 'female'(大運と六親法の表示に使う)
       opts(任意。meishiki の第4引数)
         hour         … 出生時。0〜23 の整数(0 は有効)。未指定・null なら時柱は作らない
         zokanMonth   … 月支の蔵干の流派   'kantei'(既定)| 'A' | 'hongen'
         zokanYearDay … 年支・日支・時支の蔵干の流派  同上
         ijouSet      … 異常干支の説      '13'(既定)| '7'
出力   命式 a(§1.2)。そこから応用技を計算する

1.2 命式オブジェクト a(meishiki の戻り値)

a = {
  date:     'YYYY-MM-DD',
  weekday:  '月'|'火'|'水'|'木'|'金'|'土'|'日',
  setsu:    { name, jst:'YYYY-MM-DD hh:mm', keika, isSetsuiriDay },   // 直前の節。keika=節入り日を1日目とした経過日数
  pillars:  { year:P, month:P, day:P },
             // P = { kan, shi, kanshi, zokan, no, stages:{初元,中元,本元} }
             //   no=六十干支の通し番号(1〜60)、zokan=採用された蔵干、stages=蔵干3段(無い段は null)
  stars:    { ancestor, north, center, south, east, west },         // 各 { label, pos, source, kan, star }
  starSet:  [星名…],      // stars を ancestor,north,center,south,east,west の順に見て、重複を除いたもの
  jusei:    { early, mid, late },                                    // 各 { label, source, shi, name, energy, unsei }
  juseiSet: [従星名…],    // early,mid,late の順で重複を除いたもの
  totalEnergy,            // 従星3つのエネルギーの合計(3〜36)
  gogyoDist, gogyoVariety,// 主星6つ(伴星を含む)の五行の個数
  tenchusatsu,            // 本人の天中殺(日柱から)   例 '申酉天中殺'
  tenchusatsuShi,         // その2支                      例 ['申','酉']
  tenchusatsuYear,        // 親の天中殺(年柱から)
  ijou:     { year, month, day },       // '通常'|'暗合'|'異常干支'|null
  nikkanGogyo, nisshiGogyo,
  moon,                   // その日の新月・満月 {kind:'新月'|'満月', time:'HH:MM'} か null
  hourPillar              // hour を渡したときだけ。{kan,shi,kanshi,shiIndex,zokan,stages,no,ijou,jusei,shusei}
}

1.3 関数一覧(参照実装 engine.js の公開API)

関数 何をするか 節
meishiki(y,m,d,opts) 命式を作る §3〜§6
daiun(y,m,d,gender,opts) 大運(10年ごとの流れ) §15
gyoun(birth, at, opts) 指定日の年運・月運・日運・時運 §16.1
gyounList(birth, unit, anchor, opts) 行運を一覧で並べる §16.2
suurihou(a) 数理法・八門法(a は命式。参照実装は suurihou(y,m,d,{meishiki:a}) と呼ぶが、a を渡せば日付は使わない) §8
shinkyo(a) 身強・身弱 §9
koudouRyoiki(a) 行動領域(宇宙盤) §10
rokushin(a) 六親法(家系図) §11
sainou(a) 才能(剋数・才能星・型・運) §12
teiichi(a) 定位置 §13
kyouiku(a), kyouikuSei(a) 教育の干支・教育の星 §14
isou(a,b), isouInner(a) 位相法 §7
aisho(meA,meB,mode) 2人の相性 §17
kichijitsu(a), holiday(y,m,d), moonPhaseOn, moonPhases 暦注 §18
search, searchNearMiss, matches, missing 日付検索 §19
buildReport(a,gender,opts) 鑑定レポート15章(opts は未使用) §20

1.4 データフロー(依存関係)

 節入りテーブル ──┐
                ├─→ meishiki ─┬─→ 陽占(stars) ─┬─→ 定位置 / 才能 / 教育の星
 月相テーブル ───┘             │                ├─→ 六親法(蔵干の3段を使う)
                              ├─→ 従星(jusei) ──┴─→ 身強身弱 → 相性
                              ├─→ 天中殺 ──────────→ 大運天中殺 / 行運の天中殺 / 相性
                              ├─→ 数理法(stages と3支)
                              └─→ 行動領域(三柱の干支番号)
 祝日テーブル ─→ holiday / 干支+節月 → 吉日 / すべて → search → buildReport

2. 基本定義

2.1 十干・十二支・六十干支

KAN = ['甲','乙','丙','丁','戊','己','庚','辛','壬','癸']          // index 0..9
SHI = ['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥']  // index 0..11

六十干支 n = 0..59 :  KAN[n % 10] + SHI[n % 12]       // n=0 が甲子、n=59 が癸亥
通し番号 no = n + 1                                      // 1..60
kanshiIndex(kan, shi) = n   ただし  n%10 == KAN.indexOf(kan)  かつ  n%12 == SHI.indexOf(shi)
                        (そんな n が無い組み合わせ=陰陽が合わないもの は存在しない)

六十干支の一覧(通し番号・属する旬・その旬から出る天中殺・異常干支の区分。天中殺は §5、異常干支は §6)

番号(no) 干支 旬 天中殺 異常干支(13個説) 異常干支(7個説)
1 甲子 甲子旬 戌亥天中殺
2 乙丑 甲子旬 戌亥天中殺
3 丙寅 甲子旬 戌亥天中殺
4 丁卯 甲子旬 戌亥天中殺
5 戊辰 甲子旬 戌亥天中殺
6 己巳 甲子旬 戌亥天中殺
7 庚午 甲子旬 戌亥天中殺
8 辛未 甲子旬 戌亥天中殺
9 壬申 甲子旬 戌亥天中殺
10 癸酉 甲子旬 戌亥天中殺
11 甲戌 甲戌旬 申酉天中殺 通常
12 乙亥 甲戌旬 申酉天中殺 通常
13 丙子 甲戌旬 申酉天中殺
14 丁丑 甲戌旬 申酉天中殺
15 戊寅 甲戌旬 申酉天中殺
16 己卯 甲戌旬 申酉天中殺
17 庚辰 甲戌旬 申酉天中殺
18 辛巳 甲戌旬 申酉天中殺 暗合 異常干支
19 壬午 甲戌旬 申酉天中殺 暗合 異常干支
20 癸未 甲戌旬 申酉天中殺
21 甲申 甲申旬 午未天中殺
22 乙酉 甲申旬 午未天中殺
23 丙戌 甲申旬 午未天中殺 暗合
24 丁亥 甲申旬 午未天中殺 暗合 異常干支
25 戊子 甲申旬 午未天中殺 暗合 異常干支
26 己丑 甲申旬 午未天中殺
27 庚寅 甲申旬 午未天中殺
28 辛卯 甲申旬 午未天中殺
29 壬辰 甲申旬 午未天中殺
30 癸巳 甲申旬 午未天中殺 暗合 異常干支
31 甲午 甲午旬 辰巳天中殺 異常干支
32 乙未 甲午旬 辰巳天中殺
33 丙申 甲午旬 辰巳天中殺
34 丁酉 甲午旬 辰巳天中殺
35 戊戌 甲午旬 辰巳天中殺 通常
36 己亥 甲午旬 辰巳天中殺 暗合 異常干支
37 庚子 甲午旬 辰巳天中殺 通常
38 辛丑 甲午旬 辰巳天中殺
39 壬寅 甲午旬 辰巳天中殺
40 癸卯 甲午旬 辰巳天中殺
41 甲辰 甲辰旬 寅卯天中殺
42 乙巳 甲辰旬 寅卯天中殺
43 丙午 甲辰旬 寅卯天中殺
44 丁未 甲辰旬 寅卯天中殺
45 戊申 甲辰旬 寅卯天中殺
46 己酉 甲辰旬 寅卯天中殺
47 庚戌 甲辰旬 寅卯天中殺
48 辛亥 甲辰旬 寅卯天中殺 通常
49 壬子 甲辰旬 寅卯天中殺
50 癸丑 甲辰旬 寅卯天中殺
51 甲寅 甲寅旬 子丑天中殺
52 乙卯 甲寅旬 子丑天中殺
53 丙辰 甲寅旬 子丑天中殺
54 丁巳 甲寅旬 子丑天中殺 通常
55 戊午 甲寅旬 子丑天中殺
56 己未 甲寅旬 子丑天中殺
57 庚申 甲寅旬 子丑天中殺
58 辛酉 甲寅旬 子丑天中殺
59 壬戌 甲寅旬 子丑天中殺
60 癸亥 甲寅旬 子丑天中殺

2.2 五行・陰陽

GOGYO_KAN = { 甲:木, 乙:木, 丙:火, 丁:火, 戊:土, 己:土, 庚:金, 辛:金, 壬:水, 癸:水 }
GOGYO_SHI = { 子:水, 丑:土, 寅:木, 卯:木, 辰:土, 巳:火, 午:火, 未:土, 申:金, 酉:金, 戌:土, 亥:水 }
INYO_KAN  = { 甲:1, 乙:0, 丙:1, 丁:0, 戊:1, 己:0, 庚:1, 辛:0, 壬:1, 癸:0 }   // 1=陽(甲丙戊庚壬)、0=陰(乙丁己辛癸)。本書で「陽」「陰」と書くのはこの 1 と 0

SEI = ['木','火','土','金','水']            // 相生の順
sho(a, b)  := SEI[(SEI.indexOf(a)+1) % 5] == b     // a が b を生む   木→火→土→金→水→木
koku(a, b) := SEI[(SEI.indexOf(a)+2) % 5] == b     // a が b を剋す   木→土→水→火→金→木

干合(かんごう) … 甲↔己、乙↔庚、丙↔辛、丁↔壬、戊↔癸。

KANGO = { 甲:己, 己:甲, 乙:庚, 庚:乙, 丙:辛, 辛:丙, 丁:壬, 壬:丁, 戊:癸, 癸:戊 }

2.3 星の名前

十大主星 SHUSEI_LIST = ['貫索星','石門星','鳳閣星','調舒星','禄存星','司禄星','車騎星','牽牛星','龍高星','玉堂星']
  五行  STAR_GOGYO = { 貫索星:木, 石門星:木, 鳳閣星:火, 調舒星:火, 禄存星:土, 司禄星:土, 車騎星:金, 牽牛星:金, 龍高星:水, 玉堂星:水 }
  四柱推命の通変星との対応: 貫索=比肩 石門=劫財 鳳閣=食神 調舒=傷官 禄存=偏財 司禄=正財 車騎=偏官 牽牛=正官 龍高=偏印 玉堂=印綬

十二大従星 JUSEI_LIST = ['天報星','天印星','天貴星','天恍星','天南星','天禄星','天将星','天堂星','天胡星','天極星','天庫星','天馳星']

2.4 ユリウス日と曜日

日付の計算に Date は使わない(実行環境のタイムゾーンに結果が左右されないため)。整数演算だけで行う。

jdn(y, m, d):                       // グレゴリオ暦 → ユリウス日数(整数)
  a  = floor((14 - m) / 12)
  y2 = y + 4800 - a
  m2 = m + 12*a - 3
  return d + floor((153*m2 + 2)/5) + 365*y2 + floor(y2/4) - floor(y2/100) + floor(y2/400) - 32045

fromJdn(j):                         // ユリウス日数 → [y, m, d]
  a  = j + 32044
  b  = floor((4*a + 3) / 146097)
  c  = a - floor(146097*b / 4)
  d2 = floor((4*c + 3) / 1461)
  e  = c - floor(1461*d2 / 4)
  m2 = floor((5*e + 2) / 153)
  return [ 100*b + d2 - 4800 + floor(m2/10),
           m2 + 3 - 12*floor(m2/10),
           e - floor((153*m2 + 2)/5) + 1 ]

WEEKDAY = ['月','火','水','木','金','土','日']
weekday(y,m,d) = WEEKDAY[ mod(jdn(y,m,d), 7) ]
  // 検算: 2000-01-01 の jdn は 2451545。2451545 % 7 = 5 → '土'(実際に土曜日)

diffDays(fromIso, toIso) = jdn(to) - jdn(from)。


3. 暦:柱の決め方

ここが全部の土台

年柱・月柱・日柱・時柱と、蔵干の採用。ここが1日ずれると、以降の星・天中殺・大運がすべてずれる。
日単位で切り替える(時刻は使わない)のがこのアプリの設計。§3.2 を必ず読むこと。

3.1 節入りテーブル TABLE

暦の区切りは「節」(二十四節気のうち奇数番目の12個)。

TABLE = { "1900": [ [日,時,分], …12個 ], "1901": […], …, "2100": […] }
  • 年はグレゴリオ暦の西暦年。キーは文字列。1900〜2100の201年。
  • 配列の index i(0〜11)は、その年の (i+1)月 にある節。
  • 値の [日, 時, 分] は、その節に入る瞬間の JST(日にち・時・分)。分は秒の切り捨て。
index 月 節 月支
0 1月 小寒 丑
1 2月 立春 寅
2 3月 啓蟄 卯
3 4月 清明 辰
4 5月 立夏 巳
5 6月 芒種 午
6 7月 小暑 未
7 8月 立秋 申
8 9月 白露 酉
9 10月 寒露 戌
10 11月 立冬 亥
11 12月 大雪 子
SETSU_SHI  = ['丑','寅','卯','辰','巳','午','未','申','酉','戌','亥','子']   // index→月支
SETSU_NAME = ['小寒','立春','啓蟄','清明','立夏','芒種','小暑','立秋','白露','寒露','立冬','大雪']

例(1984年):[[6,12,40],[5,0,18],[5,18,24],[4,23,22],[5,16,50],[5,21,8],[7,7,29],[7,17,17],[7,20,9],[8,11,42],[7,14,45],[7,7,28]]
→ 立春は 1984-02-05 00:18 JST、寒露は 1984-10-08 11:42 JST。

実データは付録A。 データが無くても §3.1.1 の手順で再生成できる(今回、現物と2,412/2,412件の完全一致を確認)。

3.1.1 テーブルの再生成(検証済み)

節入り時刻は天文計算(太陽の見かけの黄経が 285°+30°×k になる瞬間)。
sxtwl(寿星万年暦)の getJieQiByYear(y) が返す節気時刻(北京時間 UTC+8)に1時間足して JST にし、秒を切り捨てると、現物と全件一致する。スクリプトは付録A。

  • 日付だけを使う限り、別の天文ライブラリ(ephem など)でも 2,412件すべて同じ日付になる(検証済み)。ただし分単位では最大 ±80秒ほどずれるので、時刻まで表示するなら sxtwl を使うこと。
  • このアプリの計算が使うのは 日にち([0])だけ。時・分は画面に「何時何分に節入り」と出すためのもの。

3.2 日単位で切り替える(最重要の設計判断)

時刻を使わない

節入りの日は、1日まるごと新しい月(新しい年)として扱う。 節入りの時刻が 23:59 でも 00:01 でも同じ。
「節入り時刻より前に生まれた人は前の月」とする流派があり、その場合に結果が変わりうる。
このアプリは画面に警告を出す(setsu.isSetsuiriDay が真のとき)が、計算は常に日単位。
再実装でここを時刻まで見てしまうと、節入り当日の生まれで結果が食い違う。

findSetsu(y, m, d):        // 対象日「以前」で最も新しい節
  target = jdn(y,m,d)
  best = null
  for yy in [y-1, y]:
    rows = TABLE[yy]; if rows が無ければ continue
    for i in 0..11:
      j = jdn(yy, i+1, rows[i][0])           // その節の日(時刻は見ない)
      if j <= target and (best==null or j > best.jdn):
        best = { jdn:j, year:yy, monthIndex:i, day:rows[i][0], hh:rows[i][1], mm:rows[i][2],
                 shi:SETSU_SHI[i], name:SETSU_NAME[i] }
  return best

findNextSetsu(y, m, d):    // 対象日より「後」で最も近い節(同じ日は含まない)
  yy in [y, y+1] について i in 0..11: j = jdn(yy, i+1, rows[i][0]); if j > target and 最小なら採用
  // ⚠ y+1 のテーブルが無い 2100年12月7日(最後の大雪の日)以降は null になる(§3.9)

keika = jdn(y,m,d) - findSetsu(y,m,d).jdn + 1        // 節入り日を 1日目 として数える

3.3 年柱

年は立春の日から変わる(1月1日ではない)。

kanshiYear(y, m, d):
  risshunJdn = jdn(y, 2, TABLE[y][1][0])        // その年の立春の日
  return  jdn(y,m,d) >= risshunJdn  ?  y  :  y-1

ky   = kanshiYear(y,m,d)
yidx = mod(ky - 4, 60)               // 西暦4年が甲子(n=0)
年干 = KAN[yidx % 10]   年支 = SHI[yidx % 12]    年柱の no = yidx + 1

検算:1984 → mod(1980,60)=0 → 甲子(no=1)。2026 → mod(2022,60)=42 → 丙午(no=43)。

3.4 月柱

月支は直前の節で決まる。月干は年干から五虎遁で決める。

月支 = findSetsu(y,m,d).shi

GOTORA = { 甲:丙, 己:丙, 乙:戊, 庚:戊, 丙:庚, 辛:庚, 丁:壬, 壬:壬, 戊:甲, 癸:甲 }    // 年干 → 寅月の月干
月干 = KAN[ ( KAN.indexOf(GOTORA[年干]) + mod(SHI.indexOf(月支) - 2, 12) ) % 10 ]
        // 寅=0, 卯=1, … 子=10, 丑=11 と数えたときの「寅から何番目か」を足す
月柱の no = kanshiIndex(月干, 月支) + 1

⚠ 年干 は §3.3 の立春基準の年干。1月〜立春前の生まれは前年の年干で計算する(月支は、小寒より前なら子=寅から数えて10番目、小寒以降なら丑=11番目)。

月干の早見表(年干×月支)

年干\月支 寅 卯 辰 巳 午 未 申 酉 戌 亥 子 丑
甲 丙寅 丁卯 戊辰 己巳 庚午 辛未 壬申 癸酉 甲戌 乙亥 丙子 丁丑
乙 戊寅 己卯 庚辰 辛巳 壬午 癸未 甲申 乙酉 丙戌 丁亥 戊子 己丑
丙 庚寅 辛卯 壬辰 癸巳 甲午 乙未 丙申 丁酉 戊戌 己亥 庚子 辛丑
丁 壬寅 癸卯 甲辰 乙巳 丙午 丁未 戊申 己酉 庚戌 辛亥 壬子 癸丑
戊 甲寅 乙卯 丙辰 丁巳 戊午 己未 庚申 辛酉 壬戌 癸亥 甲子 乙丑
己 丙寅 丁卯 戊辰 己巳 庚午 辛未 壬申 癸酉 甲戌 乙亥 丙子 丁丑
庚 戊寅 己卯 庚辰 辛巳 壬午 癸未 甲申 乙酉 丙戌 丁亥 戊子 己丑
辛 庚寅 辛卯 壬辰 癸巳 甲午 乙未 丙申 丁酉 戊戌 己亥 庚子 辛丑
壬 壬寅 癸卯 甲辰 乙巳 丙午 丁未 戊申 己酉 庚戌 辛亥 壬子 癸丑
癸 甲寅 乙卯 丙辰 丁巳 戊午 己未 庚申 辛酉 壬戌 癸亥 甲子 乙丑

3.5 日柱

didx = mod(jdn(y,m,d) + 49, 60)        // 甲子 = 0
日干 = KAN[didx % 10]   日支 = SHI[didx % 12]    日柱の no = didx + 1

検算:2000-01-01 → jdn=2451545 → mod(2451594,60)=54 → 戊午(実際に戊午日)。
1984-10-10 → 丁丑(no=14)。

3.6 時柱(出生時 hour を渡したときだけ)

GOSO = { 甲:甲, 己:甲, 乙:丙, 庚:丙, 丙:戊, 辛:戊, 丁:庚, 壬:庚, 戊:壬, 癸:壬 }    // 日干 → 子の刻の時干(五鼠遁)

jichu(日干, hour):
  idx  = floor( ((hour + 1) % 24) / 2 )          // 23時台と0時台はどちらも idx=0(子)、1〜2時=丑 …
  時支 = SHI[idx]
  時干 = KAN[ (KAN.indexOf(GOSO[日干]) + idx) % 10 ]
  return { kan, shi, kanshi, shiIndex: idx }
23時台は日付をまたがない

23時台を翌日の日干支で扱う流派(夜子時)もあるが、このアプリは日付をまたがない。
23時でも日干はその日のまま(GOSO[日干] を使う)。画面には警告が出る。

時柱が付くと追加で計算するもの(命式 a.hourPillar):

zokan  = zokan(時支, keika, zokanYearDay)       // §3.7(keika は日柱と同じ)
stages = zokanStages(時支)
no     = kanshiIndex(時干, 時支) + 1
ijou   = ijouKanshi(時干+時支, ijouSet)         // §6
jusei  = jusei(日干, 時支).name                  // §4.3
shusei = shusei(日干, 時干)                      // §4.1

時柱の早見表(日干×時支)

日干\時支 子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥
甲 甲子 乙丑 丙寅 丁卯 戊辰 己巳 庚午 辛未 壬申 癸酉 甲戌 乙亥
乙 丙子 丁丑 戊寅 己卯 庚辰 辛巳 壬午 癸未 甲申 乙酉 丙戌 丁亥
丙 戊子 己丑 庚寅 辛卯 壬辰 癸巳 甲午 乙未 丙申 丁酉 戊戌 己亥
丁 庚子 辛丑 壬寅 癸卯 甲辰 乙巳 丙午 丁未 戊申 己酉 庚戌 辛亥
戊 壬子 癸丑 甲寅 乙卯 丙辰 丁巳 戊午 己未 庚申 辛酉 壬戌 癸亥
己 甲子 乙丑 丙寅 丁卯 戊辰 己巳 庚午 辛未 壬申 癸酉 甲戌 乙亥
庚 丙子 丁丑 戊寅 己卯 庚辰 辛巳 壬午 癸未 甲申 乙酉 丙戌 丁亥
辛 戊子 己丑 庚寅 辛卯 壬辰 癸巳 甲午 乙未 丙申 丁酉 戊戌 己亥
壬 庚子 辛丑 壬寅 癸卯 甲辰 乙巳 丙午 丁未 戊申 己酉 庚戌 辛亥
癸 壬子 癸丑 甲寅 乙卯 丙辰 丁巳 戊午 己未 庚申 辛酉 壬戌 癸亥

3.7 蔵干

支の中に隠れている干。節入りからの経過日数 keika(節入り日=1日目) で、どの干を使うかが変わる。

3.7.1 既定の表 kantei(実在アプリの出力を1日刻みで観測して起こしたもの)

各支について [上限日数, 干] の並び。keika <= 上限 を満たす最初の行の干を採る。最後の行(99)は「それ以降すべて」。

ZOKAN_KANTEI = {
  子: [[99,'癸']],
  丑: [[10,'癸'], [13,'辛'], [99,'己']],
  寅: [[ 8,'戊'], [15,'丙'], [99,'甲']],
  卯: [[99,'乙']],
  辰: [[10,'乙'], [13,'癸'], [99,'戊']],
  巳: [[ 6,'戊'], [15,'庚'], [99,'丙']],
  午: [[20,'己'], [99,'丁']],
  未: [[10,'丁'], [13,'乙'], [99,'己']],
  申: [[11,'戊'], [14,'壬'], [99,'庚']],
  酉: [[99,'辛']],
  戌: [[10,'辛'], [13,'丁'], [99,'戊']],
  亥: [[13,'甲'], [99,'壬']],
}

支によって段数が違うのが特徴:1段(子・卯・酉)、2段(午・亥。初元を持たない)、3段(残り7支)。

日数で展開すると(keika は1から数える):

kantei(既定)

地支 節入り日を1日目とした経過日数 → 蔵干
子 1日目〜=癸
丑 1〜10日目=癸、11〜13日目=辛、14日目〜=己
寅 1〜8日目=戊、9〜15日目=丙、16日目〜=甲
卯 1日目〜=乙
辰 1〜10日目=乙、11〜13日目=癸、14日目〜=戊
巳 1〜6日目=戊、7〜15日目=庚、16日目〜=丙
午 1〜20日目=己、21日目〜=丁
未 1〜10日目=丁、11〜13日目=乙、14日目〜=己
申 1〜11日目=戊、12〜14日目=壬、15日目〜=庚
酉 1日目〜=辛
戌 1〜10日目=辛、11〜13日目=丁、14日目〜=戊
亥 1〜13日目=甲、14日目〜=壬

A(四柱推命寄り・参考)

地支 節入り日を1日目とした経過日数 → 蔵干
子 1〜9日目=壬、10日目〜=癸
丑 1〜9日目=癸、10〜12日目=辛、13日目〜=己
寅 1〜7日目=戊、8〜14日目=丙、15日目〜=甲
卯 1〜10日目=甲、11日目〜=乙
辰 1〜9日目=乙、10〜12日目=癸、13日目〜=戊
巳 1〜7日目=戊、8〜14日目=庚、15日目〜=丙
午 1〜10日目=丙、11〜19日目=己、20日目〜=丁
未 1〜9日目=丁、10〜12日目=乙、13日目〜=己
申 1〜7日目=戊、8〜14日目=壬、15日目〜=庚
酉 1〜10日目=庚、11日目〜=辛
戌 1〜9日目=辛、10〜12日目=丁、13日目〜=戊
亥 1〜7日目=戊、8〜14日目=甲、15日目〜=壬

3.7.2 他の流派(比較用に残している)

ZOKAN_A = {           // 四柱推命の月律分野蔵干に近い区分。書式は ZOKAN_KANTEI と同じ [上限日数, 干]
  子: [[ 9,'壬'], [99,'癸']],                  丑: [[ 9,'癸'], [12,'辛'], [99,'己']],
  寅: [[ 7,'戊'], [14,'丙'], [99,'甲']],        卯: [[10,'甲'], [99,'乙']],
  辰: [[ 9,'乙'], [12,'癸'], [99,'戊']],        巳: [[ 7,'戊'], [14,'庚'], [99,'丙']],
  午: [[10,'丙'], [19,'己'], [99,'丁']],        未: [[ 9,'丁'], [12,'乙'], [99,'己']],
  申: [[ 7,'戊'], [14,'壬'], [99,'庚']],        酉: [[10,'庚'], [99,'辛']],
  戌: [[ 9,'辛'], [12,'丁'], [99,'戊']],        亥: [[ 7,'戊'], [14,'甲'], [99,'壬']] }
ZOKAN_TABLES = { kantei: ZOKAN_KANTEI, A: ZOKAN_A }        // 'hongen' は表ではなく HONGEN を直接引く
HONGEN      = { 子:癸, 丑:己, 寅:甲, 卯:乙, 辰:戊, 巳:丙, 午:丁, 未:己, 申:庚, 酉:辛, 戌:戊, 亥:壬 }   // 本元だけ
zokan(shi, keika, variant):
  if variant == 'hongen': return HONGEN[shi]
  tbl = (variant == 'A') ? ZOKAN_A : ZOKAN_KANTEI          // 知らない名前は kantei
  for [lim, k] in tbl[shi]: if keika <= lim: return k
  return tbl[shi] の最後の行の干

3.7.3 どの柱にどの流派を使うか(落とし穴)

zkY = zokan(年支, keika, zokanYearDay)
zkM = zokan(月支, keika, zokanMonth)
zkD = zokan(日支, keika, zokanYearDay)
zkH = zokan(時支, keika, zokanYearDay)        // 時柱があるとき
年支・日支・時支も「月の節入りからの経過日数 keika」で引く

年支の蔵干を引くのに、年の節入り(立春)からの日数ではなく、直前の節(月の区切り)からの keika を使う。
日支・時支も同じ keika。実在アプリの出力がこうなっていたので合わせてある。
直感に反するが、ここを「正しい算命学」に直すと実在アプリと食い違う。

3.7.4 蔵干の3段 stages

流派によらず、常に ZOKAN_KANTEI から取る。

zokanStages(shi):
  kans = ZOKAN_KANTEI[shi] の各行の干
  3行 → { 初元:kans[0], 中元:kans[1], 本元:kans[2] }
  2行 → { 初元:null,    中元:kans[0], 本元:kans[1] }
  1行 → { 初元:null,    中元:null,    本元:kans[0] }
地支 初元 中元 本元
子 — — 癸
丑 癸 辛 己
寅 戊 丙 甲
卯 — — 乙
辰 乙 癸 戊
巳 戊 庚 丙
午 — 己 丁
未 丁 乙 己
申 戊 壬 庚
酉 — — 辛
戌 辛 丁 戊
亥 — 甲 壬

3.8 meishiki の手順(まとめ)

meishiki(y, m, d, opts):                                   // opts は省略可。キーは hour / zokanMonth / zokanYearDay / ijouSet
  assertInRange(y)                                        // §3.9
  hour = opts.hour                                        // 出生時 0〜23。null・未指定なら時柱なし(0 は有効)
  vm  = opts.zokanMonth   || 'kantei'
  vyd = opts.zokanYearDay || 'kantei'
  s0    = findSetsu(y,m,d)                                // §3.2
  keika = jdn(y,m,d) - s0.jdn + 1
  年柱 §3.3 / 月柱 §3.4 / 日柱 §3.5
  zkY,zkM,zkD §3.7.3
  banseiKan = KANGO[年干]                                   // 伴星(ご先祖様)の干
  stars = {  // §4.2
    ancestor: shusei(日干, banseiKan),  north: shusei(日干, 年干),  center: shusei(日干, zkM),
    south: shusei(日干, 月干),          east: shusei(日干, zkY),    west: shusei(日干, zkD) }
  jusei = { early: jusei(日干,年支), mid: jusei(日干,月支), late: jusei(日干,日支) }     // §4.3
  totalEnergy = early.energy + mid.energy + late.energy
  tenchusatsu     = TENCHUSATSU[ floor(didx/10) ]           // §5
  tenchusatsuYear = TENCHUSATSU[ floor(yidx/10) ]
  ijou = { year:  ijouKanshi(年干+年支, opts.ijouSet),       // §6。3つの柱にも時柱にも opts.ijouSet を渡す
           month: ijouKanshi(月干+月支, opts.ijouSet),
           day:   ijouKanshi(日干+日支, opts.ijouSet) }
  moon = moonPhaseOn(y,m,d)                                  // §18.3
  hourPillar = hour != null なら §3.6、なければ null

  date    = 'YYYY-MM-DD'(0詰め)          weekday = §2.4
  setsu   = { name: s0.name,
              jst:  pad4(s0.year) + '-' + pad2(s0.monthIndex + 1) + '-' + pad2(s0.day) + ' ' + pad2(s0.hh) + ':' + pad2(s0.mm),
              keika,
              isSetsuiriDay: (s0.jdn == jdn(y,m,d)) }        // keika == 1 と同じ意味
  • ⚠ setsu.jst の年は、節を引いた表の年 s0.year。1月上旬(小寒より前)に引く前年12月の大雪は 1900-12-07 21:55 のように前年の日付になる(生年ではない)。
  • 柱の no:年柱=yidx + 1、月柱=kanshiIndex(月干, 月支) + 1、日柱=didx + 1。柱ごとの zokan は採用された蔵干(zkY・zkM・zkD)、stages は §3.7.4。
  • nikkanGogyo = GOGYO_KAN[日干]、nisshiGogyo = GOGYO_SHI[日支]。

3.9 範囲と既知の限界

yearRange() = { min: 最初の年 + 1 = 1901, max: 最後の年 = 2100 }       // 参照実装では range()(Python の range と紛れるので本書ではこう書く)
assertInRange(y): y < 1901 or y > 2100 なら例外 '対応しているのは 1901年〜2100年です(節入りデータの範囲)。'
  • 1901年が下限なのは、1月上旬(小寒より前)は前年(1900年)12月の大雪を参照するため。
  • 日付の実在チェックはしない(2月30日を渡すとユリウス日の計算がそのまま進む)。呼び出し側の責任。
  • ⚠ 既知の限界:daiun(§15)が順行で findNextSetsu を呼ぶとき、2100年12月7日(最後の大雪の日。「対象日より後」の節を探すので当日も含む)以降の生まれは次の節(2101年1月)がテーブルに無く null.jdn で例外になる。命式そのもの(meishiki)は2100-12-31 まで計算できる。直すなら節入りテーブルを2101年まで延ばす。

4. 陽占(人体図)

4.1 十大主星 shusei(日干, 対象の干)

日干から見た「対象の干」との関係(五行の相生相剋)と、陰陽が同じか違うかで10通りに決まる。

shusei(nikkan, target):
  ea = GOGYO_KAN[nikkan];  eb = GOGYO_KAN[target]
  same = (INYO_KAN[nikkan] == INYO_KAN[target])
  if ea == eb:        return same ? 貫索星 : 石門星      // 同じ五行            (比肩・劫財)
  if sho(ea, eb):     return same ? 鳳閣星 : 調舒星      // 日干が対象を生む    (食神・傷官)
  if koku(ea, eb):    return same ? 禄存星 : 司禄星      // 日干が対象を剋す    (偏財・正財)
  if koku(eb, ea):    return same ? 車騎星 : 牽牛星      // 対象が日干を剋す    (偏官・正官)
  if sho(eb, ea):     return same ? 龍高星 : 玉堂星      // 対象が日干を生む    (偏印・印綬)

早見表(100セル)。行=日干、列=対象の干。表中の「貫索」は「貫索星」の略。

日干\対象の干 甲 乙 丙 丁 戊 己 庚 辛 壬 癸
甲(木・陽) 貫索 石門 鳳閣 調舒 禄存 司禄 車騎 牽牛 龍高 玉堂
乙(木・陰) 石門 貫索 調舒 鳳閣 司禄 禄存 牽牛 車騎 玉堂 龍高
丙(火・陽) 龍高 玉堂 貫索 石門 鳳閣 調舒 禄存 司禄 車騎 牽牛
丁(火・陰) 玉堂 龍高 石門 貫索 調舒 鳳閣 司禄 禄存 牽牛 車騎
戊(土・陽) 車騎 牽牛 龍高 玉堂 貫索 石門 鳳閣 調舒 禄存 司禄
己(土・陰) 牽牛 車騎 玉堂 龍高 石門 貫索 調舒 鳳閣 司禄 禄存
庚(金・陽) 禄存 司禄 車騎 牽牛 龍高 玉堂 貫索 石門 鳳閣 調舒
辛(金・陰) 司禄 禄存 牽牛 車騎 玉堂 龍高 石門 貫索 調舒 鳳閣
壬(水・陽) 鳳閣 調舒 禄存 司禄 車騎 牽牛 龍高 玉堂 貫索 石門
癸(水・陰) 調舒 鳳閣 司禄 禄存 牽牛 車騎 玉堂 龍高 石門 貫索

4.2 人体図の配置(6つの主星)

目上   north    (北方)  … 年干                         → shusei(日干, 年干)
中心   center   (中央)  … 月支の蔵干(採用された zkM) → shusei(日干, zkM)
目下   south    (南方)  … 月干                         → shusei(日干, 月干)
社会   east     (東方)  … 年支の蔵干(zkY)            → shusei(日干, zkY)
配偶者 west     (西方)  … 日支の蔵干(zkD)            → shusei(日干, zkD)
ご先祖様 ancestor (左上) … 伴星。年干の干合相手          → shusei(日干, KANGO[年干])

各マスのオブジェクト:{ label, pos, source, kan, star }。kan は上でその星を出した元の干。

key label pos source
ancestor ご先祖様 左上 '年干' + 年干 + 'の干合'(例 年干甲の干合)
north 目上 北方 年干
center 中心 中央 月支の蔵干
south 目下 南方 月干
east 社会 東方 年支の蔵干
west 配偶者 西方 日支の蔵干

label は才能(§12)の pos として使われるので文字列を変えないこと。pos・source は表示用。

画面上の並び(3×3):

 ┌────────────┬──────────┬────────────┐
 │ご先祖様(伴星)│ 目上(北)  │ 初年運(従星)│   初年運=年支の従星
 ├────────────┼──────────┼────────────┤
 │ 配偶者(西)   │ 中心(中央)│ 社会(東)    │
 ├────────────┼──────────┼────────────┤
 │ 晩年運(従星) │ 目下(南)  │ 中年運(従星)│   中年運=月支、晩年運=日支の従星
 └────────────┴──────────┴────────────┘

派生値:

starSet = stars を ancestor, north, center, south, east, west の順に走査して、星名の重複を除いたもの
gogyoDist[五行] = stars の6つ(伴星を含む)を STAR_GOGYO で五行に直した個数
                  ⚠ 個数が 0 の五行は**キーを作らない**(疎な辞書。例 {"土":1,"水":2,"金":1,"木":2})。キーの並びは出た順(比較には関係しない)
gogyoVariety = gogyoDist のキー数

4.3 十二大従星 jusei(日干, 地支)

十二運(長生〜養)を、陽干は順行・陰干は逆行で地支に当てはめ、それを従星とエネルギーに読み替える。

CHOSEI = { 甲:亥, 乙:午, 丙:寅, 丁:酉, 戊:寅, 己:酉, 庚:巳, 辛:子, 壬:申, 癸:卯 }     // 長生の位置
UNJUN  = ['長生','沐浴','冠帯','建禄','帝旺','衰','病','死','墓','絶','胎','養']

jusei(nikkan, shi):
  start = SHI.indexOf(CHOSEI[nikkan])
  pos   = SHI.indexOf(shi)
  step  = (INYO_KAN[nikkan] == 1) ? +1 : -1                  // 陽干(甲丙戊庚壬)は順行
  idx   = mod( (pos - start) * step, 12 )
  unsei = UNJUN[idx]
  return { name: JU_MAP[unsei][0], energy: JU_MAP[unsei][1], unsei }          // JU_MAP[十二運] = [従星名, 点]  例 JU_MAP['胎'] = ['天報星', 3]

十二運→従星・エネルギー(JU_MAP)

十二運 十二大従星 エネルギー
胎 天報星 3
養 天印星 6
長生 天貴星 9
沐浴 天恍星 7
冠帯 天南星 10
建禄 天禄星 11
帝旺 天将星 12
衰 天堂星 8
病 天胡星 4
死 天極星 2
墓 天庫星 5
絶 天馳星 1

(点数の合計は 3+6+9+7+10+11+12+8+4+2+5+1=78。命式の totalEnergy は3つの従星の合計なので 3〜36。)

全体の早見表(行=日干、列=地支、セル=従星名(エネルギー))

日干\地支 子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥
甲 天恍星(7) 天南星(10) 天禄星(11) 天将星(12) 天堂星(8) 天胡星(4) 天極星(2) 天庫星(5) 天馳星(1) 天報星(3) 天印星(6) 天貴星(9)
乙 天胡星(4) 天堂星(8) 天将星(12) 天禄星(11) 天南星(10) 天恍星(7) 天貴星(9) 天印星(6) 天報星(3) 天馳星(1) 天庫星(5) 天極星(2)
丙 天報星(3) 天印星(6) 天貴星(9) 天恍星(7) 天南星(10) 天禄星(11) 天将星(12) 天堂星(8) 天胡星(4) 天極星(2) 天庫星(5) 天馳星(1)
丁 天馳星(1) 天庫星(5) 天極星(2) 天胡星(4) 天堂星(8) 天将星(12) 天禄星(11) 天南星(10) 天恍星(7) 天貴星(9) 天印星(6) 天報星(3)
戊 天報星(3) 天印星(6) 天貴星(9) 天恍星(7) 天南星(10) 天禄星(11) 天将星(12) 天堂星(8) 天胡星(4) 天極星(2) 天庫星(5) 天馳星(1)
己 天馳星(1) 天庫星(5) 天極星(2) 天胡星(4) 天堂星(8) 天将星(12) 天禄星(11) 天南星(10) 天恍星(7) 天貴星(9) 天印星(6) 天報星(3)
庚 天極星(2) 天庫星(5) 天馳星(1) 天報星(3) 天印星(6) 天貴星(9) 天恍星(7) 天南星(10) 天禄星(11) 天将星(12) 天堂星(8) 天胡星(4)
辛 天貴星(9) 天印星(6) 天報星(3) 天馳星(1) 天庫星(5) 天極星(2) 天胡星(4) 天堂星(8) 天将星(12) 天禄星(11) 天南星(10) 天恍星(7)
壬 天将星(12) 天堂星(8) 天胡星(4) 天極星(2) 天庫星(5) 天馳星(1) 天報星(3) 天印星(6) 天貴星(9) 天恍星(7) 天南星(10) 天禄星(11)
癸 天禄星(11) 天南星(10) 天恍星(7) 天貴星(9) 天印星(6) 天報星(3) 天馳星(1) 天庫星(5) 天極星(2) 天胡星(4) 天堂星(8) 天将星(12)

十二運の名前だけの表(unsei):

日干\地支 子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥
甲 沐浴 冠帯 建禄 帝旺 衰 病 死 墓 絶 胎 養 長生
乙 病 衰 帝旺 建禄 冠帯 沐浴 長生 養 胎 絶 墓 死
丙 胎 養 長生 沐浴 冠帯 建禄 帝旺 衰 病 死 墓 絶
丁 絶 墓 死 病 衰 帝旺 建禄 冠帯 沐浴 長生 養 胎
戊 胎 養 長生 沐浴 冠帯 建禄 帝旺 衰 病 死 墓 絶
己 絶 墓 死 病 衰 帝旺 建禄 冠帯 沐浴 長生 養 胎
庚 死 墓 絶 胎 養 長生 沐浴 冠帯 建禄 帝旺 衰 病
辛 長生 養 胎 絶 墓 死 病 衰 帝旺 建禄 冠帯 沐浴
壬 帝旺 衰 病 死 墓 絶 胎 養 長生 沐浴 冠帯 建禄
癸 建禄 冠帯 沐浴 長生 養 胎 絶 墓 死 病 衰 帝旺

4.4 三つの時期

early (初年運) = jusei(日干, 年支)     source: 年支      // オブジェクトは { label:'初年運', source:'年支', shi, name, energy, unsei }
mid   (中年運) = jusei(日干, 月支)     source: 月支      //               { label:'中年運', source:'月支', … }
late  (晩年運) = jusei(日干, 日支)     source: 日支      //               { label:'晩年運', source:'日支', … }
totalEnergy = early.energy + mid.energy + late.energy
juseiSet = early, mid, late の順で従星名の重複を除いたもの

5. 天中殺

日柱の干支が属する旬で決まる。旬=六十干支を10個ずつ区切ったもの。

TENCHUSATSU = ['戌亥天中殺','申酉天中殺','午未天中殺','辰巳天中殺','寅卯天中殺','子丑天中殺']
本人の天中殺   tenchusatsu     = TENCHUSATSU[ floor(didx / 10) ]       // didx=日柱の n(0〜59)
親の天中殺     tenchusatsuYear = TENCHUSATSU[ floor(yidx / 10) ]       // yidx=年柱の n
didx 旬 天中殺
0〜9 甲子旬 戌亥天中殺
10〜19 甲戌旬 申酉天中殺
20〜29 甲申旬 午未天中殺
30〜39 甲午旬 辰巳天中殺
40〜49 甲辰旬 寅卯天中殺
50〜59 甲寅旬 子丑天中殺

名前→該当する2支(行運の天中殺判定に使う)

天中殺 該当する2支
子丑天中殺 子・丑
寅卯天中殺 寅・卯
辰巳天中殺 辰・巳
午未天中殺 午・未
申酉天中殺 申・酉
戌亥天中殺 戌・亥
tenchusatsuShi = TENCHUSATSU_SHI[ tenchusatsu ]      // 例 ['申','酉']

kantei-app では「天中殺」「親の天中殺」と表示される2つ。


6. 異常干支

六十干支のうち特異な働きをするとされるもの。既定は13個説(通常6+暗合7)。

IJOU_KANSHI = {
  甲戌:'通常', 乙亥:'通常', 戊戌:'通常', 庚子:'通常', 辛亥:'通常', 丁巳:'通常',
  辛巳:'暗合', 壬午:'暗合', 丁亥:'暗合', 丙戌:'暗合', 戊子:'暗合', 癸巳:'暗合', 己亥:'暗合' }
IJOU_KANSHI_7 = ['甲午','丁亥','戊子','己亥','辛巳','壬午','癸巳']       // 朱学院系の7個説(参考)

ijouKanshi(kanshi, set):
  if set == '7': return IJOU_KANSHI_7 に含まれるなら '異常干支'、なければ null
  return IJOU_KANSHI[kanshi] || null                                   // 既定の13個説

命式では ijou = { year, month, day } に各柱の結果が入る。時柱があれば hourPillar.ijou。
行運・大運の各行でもその行の干支に対して同じ関数を使う。


7. 位相法(支どうしの関係)

SHIGO = { 子:丑, 丑:子, 寅:亥, 亥:寅, 卯:戌, 戌:卯, 辰:酉, 酉:辰, 巳:申, 申:巳, 午:未, 未:午 }   // 支合
CHU   = { 子:午, 午:子, 丑:未, 未:丑, 寅:申, 申:寅, 卯:酉, 酉:卯, 辰:戌, 戌:辰, 巳:亥, 亥:巳 }   // 冲
SANGO = [['申','子','辰'], ['亥','卯','未'], ['寅','午','戌'], ['巳','酉','丑']]                    // 三合(半会に使う)
KEI3  = [['寅','巳','申'], ['丑','戌','未']]                                                       // 三刑
KEI2  = [['子','卯']]                                                                              // 相刑
JIKEI = ['辰','午','酉','亥']                                                                      // 自刑
GAI   = { 子:未, 未:子, 丑:午, 午:丑, 寅:巳, 巳:寅, 卯:辰, 辰:卯, 申:亥, 亥:申, 酉:戌, 戌:酉 }   // 害
HA    = { 子:酉, 酉:子, 丑:辰, 辰:丑, 寅:亥, 亥:寅, 卯:午, 午:卯, 巳:申, 申:巳, 未:戌, 戌:未 }   // 破

isou(a, b):          // 戻り値は「関係名」の配列。この順に追加する
  out = []
  if a == b:            out += [ JIKEI に a がある ? '自刑' : '比和' ]
  if SHIGO[a] == b:     out += ['支合']
  if CHU[a]   == b:     out += ['冲']
  for g in SANGO:       if a != b and a∈g and b∈g:   out += ['半会']
  for g in KEI3:        if a != b and a∈g and b∈g:   out += ['刑']
  for g in KEI2:        if a != b and a∈g and b∈g:   out += ['刑']
  if GAI[a]   == b:     out += ['害']
  if HA[a]    == b:     out += ['破']
  return out

isouInner(a) = {
  '日柱+月柱': isou(日支, 月支),
  '日柱+年柱': isou(日支, 年支),
  '月柱+年柱': isou(月支, 年支) }

関係はすべて a と b について対称。1つの組に複数の関係が付くことがある(例:寅と申は 冲と刑)。

12×12の全組み合わせ(行=a、列=b)

a\b 子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥
子 比和 支合 刑 半会 冲 害 半会 破
丑 支合 比和 破 半会 害 冲・刑 半会 刑
寅 比和 刑・害 半会 冲・刑 半会 支合・破
卯 刑 比和 害 破 半会 冲 支合 半会
辰 半会 破 害 自刑 半会 支合 冲
巳 半会 刑・害 比和 支合・刑・破 半会 冲
午 冲 害 半会 破 自刑 支合 半会
未 害 冲・刑 半会 支合 比和 刑・破 半会
申 半会 冲・刑 半会 支合・刑・破 比和 害
酉 破 半会 冲 支合 半会 自刑 害
戌 刑 半会 支合 冲 半会 刑・破 害 比和
亥 支合・破 半会 冲 半会 害 自刑

8. 数理法・八門法

28元(天干3つ+各支の蔵干3段)それぞれについて、命式の3つの支(年支・月支・日支)との十二大従星のエネルギーを合計する。干ごとに集計したものが数理法、五行にまとめたものが八門法。

suurihou(a):
  shis = [年支, 月支, 日支]
  gen  = [年干, 月干, 日干]                              // 天干3つ
  for 柱 in [年柱, 月柱, 日柱]:                          // この順
    for 段 in ['初元','中元','本元']:
      if 柱.stages[段] != null:  gen.append(柱.stages[段])    // 無い段は飛ばす
  byKan = { 甲:0, …, 癸:0 }
  for k in gen:                                          // 同じ干が複数回出てもそのつど足す
    byKan[k] += Σ_{sh in shis} jusei(k, sh).energy        // k を「日干」とみなして、3つの支との従星の点を足す
  byGogyo = { 木:0, 火:0, 土:0, 金:0, 水:0 }             // ⚠ 5つの五行は**常にすべてキーを持つ**(該当が無ければ 0)。gogyoDist(疎)とは逆
  for k in 甲乙丙丁戊己庚辛壬癸:  byGogyo[GOGYO_KAN[k]] += byKan[k]
  total = Σ byKan
  return { byKan, byGogyo, total, genList: gen }
  • gen の長さは 最大12(3+3段×3柱)。1段の支(子・卯・酉)は1つ、2段の支(午・亥)は2つ、3段の支は3つ足す。
  • 蔵干は常に kantei の3段(stages)。流派の指定に関わらない。
  • 「28元」は伝統的な数え方(天干3+蔵干の全段)。実装は上のとおり「存在する段だけ」を足す。
  • 八門法の画面上の並びは十字:上=火、左=木、中央=土、右=水、下=金(表示だけの話)。

9. 身強・身弱

shinkyo(a):
  e = a.totalEnergy
  names = [early.name, mid.name, late.name]
  SHINKYO_STARS  = ['天将星','天禄星','天南星','天貴星']      // 参考集計(判定には使わない)
  SHINJAKU_STARS = ['天報星','天極星','天馳星','天胡星']
  strongCount = names のうち SHINKYO_STARS にあるものの数
  weakCount   = names のうち SHINJAKU_STARS にあるものの数
  hasTenshosei = names に '天将星' がある
  label = (e >= 25) ? '身強' : (e <= 14 ? '身弱' : '中庸')
  return { energy:e, strongCount, weakCount, hasTenshosei, label }

⚠ 判定は totalEnergy だけで決まる(25以上=身強、14以下=身弱、15〜24=中庸)。strongCount/weakCount は表示用。


10. 行動領域(宇宙盤)

円周に並ぶのは十二支ではなく六十干支の通し番号(1〜60)。1番が真上、時計回りに60番まで。命式の三柱(年柱・月柱・日柱)の no を円周に打ち、三点を結ぶ。

RYOIKI = [ { no:1, name:'第一領域', title:'守備安定', desc:'知性的だが感情的でもある' },
           { no:2, name:'第二領域', title:'伝達創造', desc:'情的で庶民性がある' },
           { no:3, name:'第三領域', title:'攻撃開拓', desc:'庶民性と合理性を併せ持つ' },
           { no:4, name:'第四領域', title:'習得知恵', desc:'合理的、理屈屋、知性豊か' } ]       // キーの名前と並びもこのとおり
ryoikiOf(no) = RYOIKI[ min(3, floor((no-1)/15)) ]      // 1〜15=第一(右上) 16〜30=第二(右下) 31〜45=第三(左下) 46〜60=第四(左上)

koudouRyoiki(a):
  points = [年柱, 月柱, 日柱] それぞれについて       // 各点は { label:'年柱'|'月柱'|'日柱', no, kanshi, shi, deg, ryoiki, x, y }
    no  = その柱の no           deg = (no - 1) * 6          // 1番が0度(真上)、時計回り
    rad = (deg - 90) * π / 180   x = cos(rad)   y = sin(rad)
    ryoiki = ryoikiOf(no)
  area  = | (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y) | / 2     // 半径1の円に内接する三角形の面積
  ratio = area / π                                                         // 円に対する割合
  unique = 三点の no の種類数(重複を除く)
  sortedDegs = 三点の deg の重複を除いて昇順に並べたもの       // maxGap を出すためだけの中間変数。戻り値には入れない
  maxGap = sortedDegs が2つ以上なら、隣り合う(最後→最初は一周して) 角度差 mod 360 の最大値、1つ以下なら 0
  label  =  unique==1 ? '1点に集中(きわめて狭い)'
          : unique==2 ? '2点のみ(狭い)'
          : ratio >= 0.35 ? '広い'
          : ratio >= 0.18 ? 'ふつう'
          :                  '狭い'
  spread = 三点の ryoiki.name を points の順に重複を除いたもの
  return { points, area, ratio, unique: (no の種類数), maxGap, label, ryoiki: RYOIKI, spread }
  • 三点が正三角形に近いほど ratio は大きく、最大でも約 0.4135(3√3/4 ÷ π)。
  • maxGap: 隣り合う点の角度差は (sortedDegs[(i+1)%n] - sortedDegs[i] + 360) % 360。
  • ゴールデン(付録F)では nos = points の no、degs = points の deg(柱の順・重複あり・並べ替えなし)、ryoiki = points の ryoiki.name に直してある。上の sortedDegs とは別物。
  • 検算:1984-10-10 は 甲子(1)・甲戌(11)・丁丑(14)。deg は 0, 60, 78。すべて第一領域(右上)。

11. 六親法(家系図)

日干から家族それぞれの「理想の干」を出し、陰占(天干と蔵干)の中から実際に見つかる干を探す。どの段階で見つかったかがそのまま縁の深さの目安になる。

出典と経緯

解説ページ(sanmei-stock.com の六親法)に書かれた手順を実装したもの。観測だけからは割り出せなかった。
外しやすい点は次の3つ(これを間違えると75〜85%で頭打ち)。ほかに、後で出てくる④性別を使わない ⑤同じ干を複数の家族が使ってよい、も外しやすい:

  1. 日干のマスは「自分」なので家族に数えない
  2. 父と子供は「理想の干」ではなく「実際に見つかった干」から辿る
  3. 子供には定位置を使わない(母・父・配偶者だけが定位置まで落ちる)

「同じ干を複数の家族が使ってよい(消費しない)」点も重要。

11.1 補助関数

干を番号 i = KAN.indexOf(干)(0〜9)で扱う。

gyoOf(i)  = floor(i / 2)             // 0木 1火 2土 3金 4水   (甲乙=木, 丙丁=火, 戊己=土, 庚辛=金, 壬癸=水)
yinOf(i)  = i % 2                    // 0=陽, 1=陰   ← INYO_KAN の「1=陽」と逆なので注意
mkKan(g, y) = mod(g, 5) * 2 + y      // 五行番号 g と陰陽 y から干の番号を作る
kangoOf(i)  = (i + 5) % 10           // 干合の相手(甲0↔己5, 乙1↔庚6, …)
koibitoOf(i) = let p = kangoOf(i); (p が偶数 ? p+1 : p-1)      // 「恋人の干」=干合相手の陰陽を逆にした干

gyoOf(i) + 4 は「その五行を生む五行」(mod 5)。例:火(1)+4=5→木(0)。

11.2 陰占にある干の居場所 place

place = {}                              // 干 → 居場所のラベルの配列
for 柱 in [年, 月, 日]:
  if 柱 != 日:  place[柱.kan] += [柱の名前 + '干']                     // 年干・月干。⚠ 日干は入れない(自分だから)
  for 段 in ['初元','中元','本元']:
    if 柱.stages[段] != null:  place[柱.stages[段]] += [柱の名前 + '支の' + 段]    // 日柱の蔵干も入れる
has(k) = place に k がある

ラベル例:年干、月干、年支の初元、日支の本元。「柱の名前」は 年/月/日。

11.3 定位置 TEIICHI(陰占に決まっている家族の席)

柱 日 月 年
天干 自分 子供 父親
蔵干(本元) 配偶者 家系 母親
TEIICHI = { 母親: ['year','本元'], 父親: ['year','kan'], パートナー: ['day','本元'], 家系: ['month','本元'], 子供: ['month','kan'] }
            // [柱, 'kan'(その柱の天干)または 蔵干の段]。家系・子供は六親法の計算では引かない(表にだけある)
teiichiKan(誰): 母親 → 年柱の stages.本元
                父親 → 年柱の kan(年干)
                パートナー → 日柱の stages.本元
                (子供・家系は六親法の計算では使わない)

解説ページは本文と表が食い違っていて、実例も実際の出力も表のほうと一致したので表を採っている。

11.4 探し方 find(候補の番号の並び, 定位置の誰)

find(cands, teiichiFor):
  for i, c in cands:
    if has(KAN[c]):  return { real: KAN[c], level: (i==0 ? '理想どおり' : '第二優先') }
  if teiichiFor:
    t = teiichiKan(teiichiFor)
    if t != null and has(t):  return { real: t, level: '定位置' }
  return { real: null, level: 'なし' }

11.5 家族ごとの計算(di = 日干の番号)

記法:{ ideal: x, …find(…) } の … は展開(find が返す real・level のキーをその場に並べる)。省略記号ではない。

// ── 母親 ──
seibo = mkKan(gyoOf(di) + 4, 1 - yinOf(di))        // 正母=日干を生む五行で、日干と陰陽が逆   → 主星は玉堂星
henbo = mkKan(gyoOf(di) + 4,     yinOf(di))        // 偏母=同じ五行で陰陽が同じ               → 主星は龍高星
母親 = { ideal: KAN[seibo], …find([seibo, henbo], '母親') }

// ── 父親 ── 「実際に見つかった母の干」から辿る
mBase = 母親.real の番号(無ければ null)
父親 = mBase==null ? { ideal: KAN[kangoOf(seibo)], real:null, level:'なし' }
                   : { ideal: KAN[kangoOf(seibo)], …find([kangoOf(mBase), koibitoOf(mBase)], '父親') }
        // ideal は常に「理想の母(正母)の干合相手」。探す候補は「実際の母の干合相手」→「その恋人の干」

// ── 兄弟・姉妹 ── 代わりの干はとらない
sis = mkKan(gyoOf(di), 1 - yinOf(di))              // 姉妹=同五行で陰陽が逆
兄弟 = { ideal: 日干,       real: has(日干) ? 日干 : null,       level: has(日干) ? '理想どおり' : 'なし' }
姉妹 = { ideal: KAN[sis],   real: has(KAN[sis]) ? KAN[sis] : null, level: has(KAN[sis]) ? '理想どおり' : 'なし' }

// ── 配偶者 ── 性別によらず日干の干合相手
パートナー = { ideal: KAN[kangoOf(di)], …find([kangoOf(di), koibitoOf(di)], 'パートナー') }

// ── 子供 ── 「実際に見つかった配偶者の干(妻の干)」が生じる干。定位置は使わない
wIdeal = kangoOf(di)
wReal  = パートナー.real の番号(無ければ null)
for 子 in ['男子供', '女子供']:
  girl  = (子 == '女子供')
  ideal = KAN[ mkKan(gyoOf(wIdeal)+1, girl ? yinOf(wIdeal) : 1 - yinOf(wIdeal)) ]    // 妻の理想の干が生じる干。妻と陰陽が同じ→女児、逆→男児
  子 = wReal==null ? { ideal, real:null, level:'なし' }
                   : { ideal, …find([ mkKan(gyoOf(wReal)+1, girl ? yinOf(wReal) : 1 - yinOf(wReal)) ], null) }
性別は結果を変えない

解説には「日干が女性なら日干自身が妻」とあるが、実際の出力は女性でも配偶者の干から子供を辿っていた(女性49日で確認)。出力のほうに合わせてある。gender は六親法の計算に使わない。

11.6 戻り値

ROKUSHIN_ORDER = ['母親','父親','兄弟','姉妹','パートナー','男子供','女子供']
rows[i] = { key, star: shusei(日干, ideal), where: real の place を '・' で連結(real が無ければ ''), ideal, real, level }      // この6キーだけ
return { self: 日干, rows }
  • level は '理想どおり' | '第二優先' | '定位置' | 'なし'。
  • 母・父・パートナーは定位置まで落ちるので 'なし' にはならない。'なし' になるのは 兄弟・姉妹・男子供・女子供 だけ(父は mBase が null のときのみ'なし'だが、母は必ず見つかるので実際には起きない)。
  • where の例:年干、年支の初元・月支の中元(同じ干が複数の席にあれば全部)。

12. 才能(剋数・才能星・型・運)

12.1 剋数と才能星

keys = ['east','west','center','north','south']          // 社会・配偶者・中心・目上・目下 の順(伴星は含めない)
list = keys について { pos: stars[k].label, star: stars[k].star, gogyo: STAR_GOGYO[star] }

for r in list:                                           // r 自身との比較は「同じ要素」を除く(星の名前ではなく要素の同一性で除外)
  gives = list のうち r 以外で  koku(r.gogyo, o.gogyo)  となるものの数      // 自分が剋す
  takes = list のうち r 以外で  koku(o.gogyo, r.gogyo)  となるものの数      // 自分が剋される
  r.kokusu = gives + takes

max    = list の kokusu の最大値
talent = kokusu == max かつ max > 0 の要素の星名(list の順、重複を除く)    // 才能星

12.2 型

k = list.map(r => r.kokusu) = [東, 西, 中央, 北, 南] の剋数。

kMax = max(k)   kMin = min(k)
maxCount = kMax と等しい要素の数
second   = kMax 未満の要素のうち最大のもの(無ければ kMax)
kata =  kMax == 0                            → '無玄の型'
        kMax == kMin                         → '五宮同均の型'      (全部同じ・0以外)
        k[2](中央)== kMax かつ maxCount==1  → '了殿の型'          (中央が単独で最大)
        maxCount == 1 かつ (kMax - second) >= 2 → '点欽の型'        (中央以外が単独で最大、次点と2以上の差)
        それ以外                              → '順殿の型'

判定は上から順。型の判定は 86件を観測して起こし、全件一致を確認している。

12.3 運

水(龍高・玉堂)と火(鳳閣・調舒)の星=「考える星」が、図のどこにあるかで決まる。

isThink(g) = (g == '水' or g == '火')
eastWest   = isThink(list[0].gogyo) or isThink(list[1].gogyo)      // 社会・配偶者
center     = isThink(list[2].gogyo)                                 // 中心
northSouth = isThink(list[3].gogyo) or isThink(list[4].gogyo)      // 目上・目下
un =  center                               → '北天運'
      !eastWest and !northSouth            → '南天運'
      eastWest and northSouth              → '北天運'
      eastWest                             → '東天運'
      それ以外(northSouth のみ)           → '西天運'

戻り値:{ list, max, kata, un, kokusuOrder: list.map(r=>({pos:r.pos, kokusu:r.kokusu})), talent }。運と才能全体は 176件で全一致。


13. 定位置(ていいち)

人体図の5つのマスには、本来入るべき五行が決まっている。そこに合う五行の星が入っていると「定位置にある」。

TEIICHI_POS = {
  north:  { label:'目上(北方)',   gogyo:'水', line:'精神', stars:['龍高星','玉堂星'] },
  south:  { label:'目下(南方)',   gogyo:'火', line:'精神', stars:['鳳閣星','調舒星'] },
  east:   { label:'社会(東方)',   gogyo:'木', line:'現実', stars:['貫索星','石門星'] },
  center: { label:'中心(中央)',   gogyo:'土', line:'現実', stars:['禄存星','司禄星'] },
  west:   { label:'配偶者(西方)', gogyo:'金', line:'現実', stars:['車騎星','牽牛星'] } }

teiichi(a):
  rows = ['north','south','east','center','west'] の順に
         { key, label: TEIICHI_POS[key].label(例 '目上(北方)'), line, gogyo(そのマスの五行), home(入るべき星), star(実際の星), starGogyo, ok: home に star がある }
  count  = ok の数          keys = ok のマスの key
  spirit = line=='精神' かつ ok の数(0〜2)    real = line=='現実' かつ ok の数(0〜3)
  return { rows, count, keys, spirit, real }

ご先祖様(伴星)は見ない。 縦線(北・南)=精神星、横線(東・中央・西)=現実星。定位置の星は陽転しやすいとされる。


14. 教育の干支・教育の星(口伝)

出典の扱い

この節の規則は口伝として伝わるもので、公開資料では裏が取れていない。算命学は口伝が本体で web に出ない内容が多いので
「見つからない=誤り」とは言えないが、確立した定説として扱うのも違う。出力するときは「口伝」と明記すること。

14.1 三大教育の干支

KYOUIKU_KANSHI = {
  甲戌: '木の干が、戌という土に根を張る形。まっすぐに育てる。',
  己未: '畑の土が、夏の温かい土に置かれる形。多くを慈しみ育てる。',
  癸丑: '雨露が、冬の終わりの土を潤す形。じっくりと才能を育む。' }

kyouiku(a):
  rows = [年柱, 月柱, 日柱, 時柱(あれば)] の順に、その柱の kanshi が KYOUIKU_KANSHI にあれば { pos:'年柱'|'月柱'|'日柱'|'時柱', kanshi, note }
  return { rows, count: rows.length, onDay: 日柱が rows にあるか }

14.2 教育の星の組み合わせ

印星(学び・受信)=龍高星・玉堂星 と、漏星(食傷=表現・発信)=鳳閣星・調舒星 が命式にそろうと、教えることに向くという読み。

INSEI = ['龍高星','玉堂星']        ROSEI = ['鳳閣星','調舒星']
KYOUIKU_PAIR = {
  '玉堂星+鳳閣星': { name:'正統派の教育者',         denshou:true,  note:'玉堂星で仕入れた正しい知識を、鳳閣星でわかりやすく自然に伝える。学校の先生にいちばん多いとされる王道の組み合わせ。' },
  '龍高星+調舒星': { name:'芸術・特殊分野の指導者', denshou:true,  note:'龍高星の体験から得た知恵と、調舒星の鋭い感性。一対一で相手の才能を極限まで引き出す、職人や芸術の世界の師匠の型。' },
  '玉堂星+調舒星': { name:'専門を掘り下げて伝える型', denshou:false, note:'玉堂星の体系的な知識を、調舒星の感性で磨いて出す。大人数に教えるより、書く・作る・批評するという形で伝わる。' },
  '龍高星+鳳閣星': { name:'体験させて伝える型',     denshou:false, note:'龍高星が自分でやってみたことを、鳳閣星が構えずに渡す。座学より、やらせてみて覚えさせる実践型の教え方が合う。' } }

kyouikuSei(a):
  insei = INSEI のうち a.starSet にあるもの(INSEI の順)     rosei = ROSEI のうち a.starSet にあるもの
          // a.starSet は人体図の**6つ(伴星=ご先祖様を含む)**の星の集合。伴星なしの5つで見ない
  pairs = insei × rosei の全組(insei が外側のループ)で  key = insei + '+' + rosei  が KYOUIKU_PAIR にあるもの
          各要素は { key, insei, rosei, name, denshou, note }(KYOUIKU_PAIR[key] の中身に key・insei・rosei を足したもの)
  ok    = insei も rosei も1つ以上ある
  return { insei, rosei, pairs, ok }
  // ゴールデン(付録F)では pairs を key の文字列だけの配列に直してある

denshou:true の2つが口伝そのもの。残り2つは星の意味から導いた派生(画面でもそう明記する)。


15. 大運(10年ごとの流れ)

月柱を起点に、10年ごとに六十干支を1つずつ進める(または戻す)。進む向きと、最初の大運が何歳から始まるか(立運)は生まれた日で決まる。

15.1 手順 daiun(y, m, d, gender, opts)

count = opts.count または 12
a     = meishiki(y, m, d, opts)
male  = gender が 'male' | 1 | '男' | '男性' のどれか。それ以外('female'・未指定・空文字を含む)はすべて女性扱い

// ── 向き ──
yangYear = 年柱の天干が陽(甲・丙・戊・庚・壬)
forward  = (yangYear == male)              // 陽男・陰女 → 順行/陰男・陽女 → 逆行   (真偽値どうしの比較)

// ── 立運(最初の大運が始まる年齢) ──
target = jdn(y, m, d)
days   = forward ? (findNextSetsu(y,m,d).jdn - target)       // 順行:次の節入りまでの日数(節入り当日は含まれず、必ず1以上)
                 : (target - findSetsu(y,m,d).jdn)            // 逆行:前の節入りからの日数(節入り当日生まれは 0)
startAge = min( round(days / 3), 10 )                          // 3日=1年。四捨五入。上限10
  • findSetsu / findNextSetsu は §3.1 の日単位の節入り(時刻は見ない)。findSetsu は「対象日以前で最も新しい節」、findNextSetsu は「対象日より後で最も早い節」。
  • round(days/3) は整数 days について floor((days + 1) / 3) と同じ(端数が .5 になることがないので丸め方式による差は出ない)。早見表:
days 0 1 2〜4 5〜7 8〜10 11〜13 14〜16 17〜19 20〜22 23〜25 26〜28 29以上
startAge 0 0 1 2 3 4 5 6 7 8 9 10

節と節の間隔は29〜32日なので、上限10が効くのは days = 32(計算上は11歳)のときだけ。大運が10年周期だから、10で頭打ちにしてある(実在アプリの出力で確認)。

// ── 大運の並び ──
mIdx = kanshiIndex(月柱の干, 月柱の支)              // 0..59
for i in 0 .. count-1:
  step = forward ? (i + 1) : -(i + 1)                // 順行は月柱の次から、逆行は月柱の前から
  idx  = mod(mIdx + step, 60)                        // 負数でも 0..59 に収める
  kan  = KAN[idx % 10]     shi = SHI[idx % 12]
  age  = startAge + i * 10
  ju   = jusei(日干, shi)                             // 日干から見た、この大運の支の従星
  rows[i] = {
    age,
    year: y + age,                                    // 西暦=生年+年齢(誕生日は考慮しない)
    kanshi: kan + shi, kan, shi,
    shusei: shusei(日干, kan),                        // 日干から見た、この大運の干の主星
    jusei: ju.name, energy: ju.energy,
    tenchusatsu: TENCHUSATSU[ floor(idx / 10) ],      // この大運の干支が属する旬から出る天中殺(本人の天中殺とは別物)
    isDaiunTenchusatsu: 本人の天中殺の2支(a.tenchusatsuShi)に shi が含まれる,
    ijou: ijouKanshi(kan + shi, opts.ijouSet)
  }
return { forward, direction: forward ? '順行' : '逆行', startAge, daysToSetsu: days, rows }
  • 大運天中殺(isDaiunTenchusatsu)は、大運の支が本人の天中殺の2支に入る期間。順行・逆行とも、並びの中で天中殺の2支は連続して現れるので、10年×2=20年続く。
  • tenchusatsu(行ごと)は「その干支が属する旬の天中殺」で、isDaiunTenchusatsu が見ているのは「本人の天中殺」。混同しない。
  • year は 生年 + age。たとえば 1984-10-10 生まれの男性(年干が甲=陽なので順行)は、次の節(立冬 11-07)まで 28 日 → startAge = 9 で、最初の大運は 1993 年から。同じ日の女性は逆行で、前の節(寒露 10-08)から 2 日 → startAge = 1、最初の大運は 1985 年から。
既知の限界(再実装では直してよい)

順行で、生年月日が 2100-12-07(最後の大雪の日)以降だと「次の節」が表に無く、参照実装は Cannot read properties of null (reading 'jdn') で落ちる。 逆行は問題なく動く。
再実装では「次の節が無ければ 2101-01-05 ごろ(小寒)を仮置きする」か、明示的にエラーにするか、どちらでもよい。ゴールデン出力にはこの落ちた行も error として入っている(突き合わせでは無視してよい)。


16. 行運(年運・月運・日運・時運)

本人の日干を基準に、巡ってきた日の干支を見る。星の出し方は命式と同じ(主星=日干から見た干、従星=日干から見た支)。

引数の型:birth・at・anchor・now はすべて {y, m, d}(at だけは任意で hour を足せる)。ゴールデン(付録F)は日付を配列 [y,m,d] で持っているものがある(gyoun.json の birth・at、gyoun_list.json の birth)ので、受け取る側で {y,m,d} に直す。opts は §1.1 と同じ(ijouSet など)で、gyounList だけ count(年運の年数)と now も取る。

16.1 ある1日を見る gyoun(birth, at, opts)

me     = meishiki(birth.y, birth.m, birth.d, opts)       // 本人
target = meishiki(at.y,    at.m,    at.d,    opts)       // 見たい日(その日の三柱をそのまま使う)
dkan   = me の日干          mine = me.tenchusatsuShi      // 本人の天中殺の2支

row(label, kan, shi) = {
  label, kanshi: kan + shi, kan, shi,
  shusei: shusei(dkan, kan),
  jusei:  jusei(dkan, shi).name,   energy: jusei(dkan, shi).energy,   unsei: jusei(dkan, shi).unsei,
  isTenchusatsu: mine に shi が含まれる,
  ijou: ijouKanshi(kan + shi, opts.ijouSet)
}

return {
  tenchusatsu: me.tenchusatsu,   shi: mine,   nikkan: dkan,
  moon:  moonPhaseOn(at.y, at.m, at.d),
  year:  row('年運', target.年柱.kan, target.年柱.shi),        // 立春(日単位)で替わる年柱
  month: row('月運', target.月柱.kan, target.月柱.shi),        // 節入り(日単位)で替わる月柱
  day:   row('日運', target.日柱.kan, target.日柱.shi),
  hour:  at.hour が指定されていれば  row('時運', h.kan, h.shi)   (h = jichu(target の日干, at.hour))
         指定が無ければ null
}
  • 時運の jichu は §3.6 の五鼠遁。日干は「見たい日」の日干(本人の日干ではない)。23時台は日を進めない。

16.2 一覧で並べる gyounList(birth, unit, anchor, opts)

共通:me = meishiki(birth)、dkan・mine は 16.1 と同じ。row は 16.1 と同じ項目に extra を足したもの。now = opts.now があればそれ、なければ anchor。lim = yearRange()(§3.9:1901〜2100)。

unit 並べるもの 各行の元になる命式 label extra
'year' from = clamp(anchor.y) から to = clamp(from + count - 1) までの各年(count 既定12) meishiki(y, 6, 15) の年柱(立春を過ぎた6月15日で読む) y + '年' year: y, age: y - birth.y, isNow: y == now.y
'month' anchor.y 年の 1〜12 月(グレゴリオ暦の月) meishiki(anchor.y, m, 15) の月柱(各月15日はかならずその節月の中に入る) anchor.y + '年' + m + '月' year, month: m, isNow: anchor.y == now.y かつ m == now.m
'day' anchor.y 年 anchor.m 月 の 1日〜末日 meishiki(anchor.y, anchor.m, d) の日柱 y + '年' + m + '月' + d + '日(' + 曜日 + ')' year, month, day, isNow: (anchor が now と同じ年月)かつ d == now.d, moon: a.moon, kichi: kichijitsu(a).good, kyou: kichijitsu(a).bad, holiday: holiday(y, m, d)
'hour' anchor の日の12コマ a = meishiki(anchor.y, anchor.m, anchor.d) の日干から jichu(a.日干, h) j.shi + '(' + 範囲 + ')' hour: h, range: 範囲
clamp(y)  = min(lim.max, max(lim.min, y))                    // 'year' だけ clamp する。他の unit は範囲外なら meishiki が例外を出す
末日      = その年月の日数(うるう年を考慮。Date は使わず jdn で数えてよい)
HOUR_SLOTS(代表の時刻 h, 範囲の文字列)の順序:
  [23,'23:00〜00:59'], [1,'01:00〜02:59'], [3,'03:00〜04:59'], [5,'05:00〜06:59'],
  [7,'07:00〜08:59'], [9,'09:00〜10:59'], [11,'11:00〜12:59'], [13,'13:00〜14:59'],
  [15,'15:00〜16:59'], [17,'17:00〜18:59'], [19,'19:00〜20:59'], [21,'21:00〜22:59']
return { unit, rows, nikkan: dkan, tenchusatsu: me.tenchusatsu, shi: mine, anchor }
  • 'hour' の行は日干が同じ日の12コマ。23時のコマも「その日の日干」で数える(翌日にしない)。
  • 'year' の age は y - birth.y(誕生日を迎えたかは見ない)。
  • 一覧の行の kanshi・shusei・jusei・energy・unsei・isTenchusatsu・ijou は、すべて 16.1 の row と同じ計算。

17. 相性(2人の比較)

2人の命式 meA(あなた)・meB(相手)から、事実として計算できる項目だけを並べ、読み方の文章は固定文の組み合わせで作る(AIは使わない)。良し悪しの判定はしない。

17.1 aisho(meA, meB, mode) の計算

mode は 'general'(一般)| 'business'(事業)| 'love'(恋愛)| 'friend'(友人)。省略・'general' のときは間柄別の文を足さない。

ka = meA.日柱.kan     kb = meB.日柱.kan
ea = GOGYO_KAN[ka]    eb = GOGYO_KAN[kb]              // 日干の五行どうしを比べる

// ── 五行のかたち kind(ea≠eb のときは、生・剋のどれか一つが必ず成り立つ) ──
kind = ea == eb        → '同質'
       sho(ea, eb)     → '育てる'        // あなたが相手を生む
       sho(eb, ea)     → '支えられる'    // 相手があなたを生む
       koku(ea, eb)    → '動かす'        // あなたが相手を剋す
       それ以外         → '動かされる'    // 相手があなたを剋す
gogyoRel(説明用の文字列)=
       ea == eb     → '比和(同じ五行)'
       sho(ea,eb)   → 'あなたが相手を生む(' + ea + '生' + eb + ')'
       sho(eb,ea)   → '相手があなたを生む(' + eb + '生' + ea + ')'
       koku(ea,eb)  → 'あなたが相手を剋す(' + ea + '剋' + eb + ')'
       それ以外      → '相手があなたを剋す(' + eb + '剋' + ea + ')'

// ── 共通の星 ──
starsX = meX.stars を ancestor, north, center, south, east, west の順にたどった星名の集合(重複を除き、出た順を保つ。伴星を含む6つ分)
shared = starsA の順に並べて、starsB にも入っているもの

// ── 身強・身弱 ──
sa = shinkyo(meA)   sb = shinkyo(meB)                 // §9
skPair = sa.label と sb.label の '中庸' を '身強' に置き換え、 '身強×身弱' のように '×' でつなぐ

// ── 位相法 ──
pos = { '日柱どうし': isou(meA の日支, meB の日支),
        '月柱どうし': isou(meA の月支, meB の月支),
        '年柱どうし': isou(meA の年支, meB の年支) }    // isou は §7(A→B の順で渡す)
posAll   = pos['日柱どうし'] ++ pos['月柱どうし'] ++ pos['年柱どうし']      // 配列の連結(重複を残す)
uniqIsou = posAll から重複を除いたもの(出た順)

// ── 天中殺の絡み ──
tcsKey = meA.tenchusatsu == meB.tenchusatsu                       → 'same'
         meA.tenchusatsuShi に meB の日支 が含まれる                → 'bInA'    // 相手の日支があなたの天中殺に入る
         meB.tenchusatsuShi に meA の日支 が含まれる                → 'aInB'    // あなたの日支が相手の天中殺に入る
         それ以外                                                   → 'none'
         (判定は上から順。戻り値の tenchusatsu.bInA / aInB は排他にせず、それぞれ独立に真偽を入れる)

読み方 reading(下の7つの要素を、この順に作って、空文字を取り除いた配列)

reading = [
  REL_TEXT[kind].desc,
  mode があり mode != 'general' かつ REL_MODE_TEXT[kind][mode] があれば それ、なければ ''     // 間柄別の見どころ
  TCS_TEXT[tcsKey],
  mode があり mode != 'general' かつ TCS_MODE_TEXT[tcsKey][mode] があれば それ、なければ ''
  SHINKYO_PAIR[skPair] があればそれ、なければ ''
  uniqIsou.map(x => ISOU_TEXT[x]) のうち値があるものを '。' でつないだ文字列       // 'general' でも付く
  shared.length > 0  ? '「' + shared.join('・') + '」を2人とも持っているので、その面では話が通じやすい'
                     : '持ち味が重ならないので、補い合う形になりやすい'
].filter(空文字でないもの)
  • 固定文の本体(REL_TEXT・REL_MODE_TEXT・TCS_TEXT・TCS_MODE_TEXT・ISOU_TEXT・SHINKYO_PAIR)は 付録C_相性の固定文 に原文のまま入っている。再実装では一字一句そのまま使うこと(写しが合っているかは付録Fの「固定文の指紋」で確かめられる)。
  • ROLE_TEXT・AISHO_MODES・REL_TEXT[kind].short/.label は画面用で、aisho() の reading・detail には使わない。
  • mode が 'general'・null・知らない文字列(例 'zzz')のときは、間柄別の文(要素2・4)は付かない(REL_MODE_TEXT・TCS_MODE_TEXT にそのキーが無いため)。buildAishoDetail は 'general' として扱う。

戻り値

{ kind, kindText: REL_TEXT[kind], reading,
  gogyo:        { a: ea, b: eb, relation: gogyoRel, same: ea == eb },
  tenchusatsu:  { a: meA.tenchusatsu, b: meB.tenchusatsu, same: (a == b),
                  bInA: meA.tenchusatsuShi に meB の日支 が含まれる,  aInB: meB.tenchusatsuShi に meA の日支 が含まれる },
  sharedStars:  shared,
  shinkyo:      { a: sa, b: sb },
  isou:         pos,
  isouSummary:  posAll が空でなければ uniqIsou を '・' でつないだ文字列、空なら 'なし',
  kango:        KANGO[ka] == kb               // 日干どうしが干合しているか
}

17.2 「詳しく読む」buildAishoDetail(ai, mode)(aisho_detail.js)

ai は 17.1 の戻り値。見出し5つ×本文5つの配列 [{title, body}, …] を返す。固定文は 付録C_相性の固定文 の D_KIND・D_SK・D_BOND・D_FRICTION・D_TCS・D_TITLES。

m = D_KIND[mode] があれば mode、なければ 'general'
titles = D_TITLES[m]

side(s)  = s.label == '身弱' ? '弱' : '強'            // 中庸は「強」に寄せる
skKey    = side(ai.shinkyo.a) + side(ai.shinkyo.b)     // '強強' | '強弱' | '弱強' | '弱弱'

tcsKey   = ai.tenchusatsu.same ? 'same' : ai.tenchusatsu.bInA ? 'bInA' : ai.tenchusatsu.aInB ? 'aInB' : 'none'

rels     = ai.isou['日柱どうし'] ++ ai.isou['月柱どうし'] ++ ai.isou['年柱どうし']
HARMONY  = ['支合','半会','比和']        TENSION = ['冲','刑','害','破','自刑']
bucket   = rels に TENSION の語が1つでもある → 'tension'
           else rels に HARMONY の語が1つでもある → 'harmony'
           else 'none'                                        // tension が harmony に優先する

bond     = [ ai.sharedStars.length ? D_BOND[m].yes(ai.sharedStars.join('・')) : D_BOND[m].no ]
           ai.kango が真なら  bond に D_BOND[m].kango を追加
friction = [ D_FRICTION[m][bucket] ]
           rels.length > 0 なら  '出ている関係は「' + (rels の重複を除いたものを '・' でつなぐ) + '」。' を追加

return [ { title: titles[0], body: D_KIND[m][ai.kind] },
         { title: titles[1], body: D_SK[m][skKey] },
         { title: titles[2], body: bond.join(' ') },          // 半角スペースでつなぐ
         { title: titles[3], body: friction.join(' ') },
         { title: titles[4], body: D_TCS[m][tcsKey] } ]
  • D_BOND[m].yes は関数(s を受けて文を返す)。間柄(general・business・love・friend)ごとに別の文で、どれも星名 s を 「…」 で囲んで差し込む(原文は付録C)。

18. 暦注(吉日・凶日・祝日・月相)

18.1 吉日・凶日 kichijitsu(a)

節月と日の干支だけで機械的に決まるものだけを扱う(六曜・不成就日は旧暦が要るので入れていない)。

SETSUGETSU_SHI = ['寅','卯','辰','巳','午','未','申','酉','戌','亥','子','丑']    // 節月1〜12 の月支(1=立春から)
setsugetsu = SETSUGETSU_SHI.indexOf(a.月柱.shi) + 1                              // 1..12。月柱は日単位の節入りで決まる(§3.2)
dayShi = a.日柱.shi     dayKanshi = a.日柱.kanshi

TENSHA = [ { months:[1,2,3],   kanshi:'戊寅', season:'春' }, { months:[4,5,6],   kanshi:'甲午', season:'夏' },
           { months:[7,8,9],   kanshi:'戊申', season:'秋' }, { months:[10,11,12], kanshi:'甲子', season:'冬' } ]
ICHIRYU(一粒万倍日。節月ごとの2支。添字0=節月1)=
  [['丑','午'], ['酉','寅'], ['子','卯'], ['卯','辰'], ['巳','午'], ['酉','午'],
   ['子','未'], ['卯','申'], ['酉','午'], ['酉','戌'], ['亥','子'], ['卯','子']]
SANRINBOU(三隣亡。節月ごとの支)=
  ['亥','寅','午','亥','寅','午','亥','寅','午','亥','寅','午']

good = []   bad = []
TENSHA のうち setsugetsu を含む行の 干支 == dayKanshi            → good に '天赦日'
ICHIRYU[setsugetsu-1] に dayShi が含まれる                       → good に '一粒万倍日'
dayShi == '寅'                                                    → good に '寅の日'
dayKanshi == '己巳'                                               → good に '己巳の日'
  それ以外で dayShi == '巳'                                        → good に '巳の日'        // 己巳の日は「巳の日」を重ねて付けない
SANRINBOU[setsugetsu-1] == dayShi                                → bad に '三隣亡'
return { setsugetsu, good, bad, all: good ++ bad }

good の並びは常に 天赦日 → 一粒万倍日 → 寅の日 → 己巳の日/巳の日 の順。

18.2 祝日 holiday(y, m, d)

表 holiday_table.json(付録A_データテーブルと生成スクリプト)を引くだけ。計算はしない。

形式  { "from":1948, "to":2100, "names":[祝日名…], "years":{ "2026":[[通日, namesの番号], …], … } }
dayOfYear(y,m,d) = jdn(y,m,d) - jdn(y,1,1) + 1                    // 1月1日=1
holiday(y,m,d) = years[String(y)] の中に [dayOfYear, idx] があれば names[idx]、なければ null
                 表が無い(読み込んでいない)/その年が表に無い(1948年より前など)→ null
hasHolidayData(y) = 表があり、from <= y <= to
  • 1948-07-20(祝日法の施行)より前は祝日として扱わない。振替休日・国民の休日・一度きりの祝日(即位の礼など)も入っている(jpholiday 1.0.3 が出したもの)。
  • 春分・秋分は天体の運行で決まり、正式には前年2月の官報で告示される。先の年は計算による見込みで、数十年先は1日ずれうる。

18.3 月相(新月・満月)moonPhaseOn(y, m, d)

表 moon_table.json は JST の新月・満月の時刻を、起点からの経過分の差分で持つ。

形式  { "epoch":[1900,1,1,0,0], "step":[1372, 20476, 21975, …] }
      step[0] は起点(1900-01-01 00:00 JST)からの分。step[i] は直前の朔望との差(分)。
      偶数番目(0,2,4…)が新月、奇数番目が満月(朔望は必ず交互に来る)。

展開:
  epMin = jdn(1900,1,1) * 1440
  cum = 0
  for i, s in step:
    cum += s
    total = epMin + cum
    j   = floor(total / 1440)          // その朔望が属する日(JST)の jdn
    rem = total - j * 1440
    event[i] = { jdn: j, hh: floor(rem / 60), mm: rem % 60, kind: i % 2 == 0 ? '新月' : '満月' }

moonPhaseOn(y,m,d) = jdn(y,m,d) に一致する event があれば { kind, time:'HH:MM' }、なければ null
                     (同じ日に新月と満月が両方来ることはない)
moonPhases(from, to) = from <= 日付 <= to(**両端を含む**。from・to は 'YYYY-MM-DD' の文字列)の event を { date:'YYYY-MM-DD', time:'HH:MM', kind } で昇順に列挙。from > to なら空
  • 月相の表を渡さずに初期化すると moonPhaseOn は常に null。
  • 時刻は Meeus『Astronomical Algorithms』第49章の式(ΔT補正つき)で計算し、秒を四捨五入して分にし、+9時間して JST にしたもの(付録A_データテーブルと生成スクリプト の gen_moon_table.py)。表から日付を引く側は、再計算せず表を使えばよい。

19. 検索(条件に合う日を探す)

19.1 条件 cond

cond のキーはすべて省略可(未指定・null・空配列は「その条件なし」)。opts も省略可(maxHits・zokanMonth・zokanYearDay)。cond が {} なら全日が成立する。

cond = {
  tenchusatsu:     [天中殺名…] | null,    // いずれかに一致 (OR)      例 ['子丑天中殺']
  nikkanGogyo:     [五行…]    | null,    // 日干の五行がいずれか (OR)
  nisshiGogyo:     [五行…]    | null,    // 日支の五行がいずれか (OR)
  requireShusei:   [星名…],               // 主星に**全部**含む (AND)。人体図の6つ(伴星を含む)の星の集合 a.starSet を見る
  requireJuseiAny: [従星名…],             // 従星3つのうちいずれか (OR)。a.juseiSet を見る
  minEnergy:       数 | null,             // 従星エネルギー合計(a.totalEnergy)の下限(以上)
  robust:          真偽                   // 真なら 蔵干の流派4通りすべてで成立した日だけ返す
}

19.2 判定 matches(a, cond)

cond.tenchusatsu     が空でない  かつ  a.tenchusatsu   が含まれない     → 不成立
cond.nikkanGogyo     が空でない  かつ  a.nikkanGogyo   が含まれない     → 不成立
cond.nisshiGogyo     が空でない  かつ  a.nisshiGogyo   が含まれない     → 不成立
cond.requireShusei   の中に a.starSet に無い星が1つでもある             → 不成立
cond.requireJuseiAny が空でない  かつ  どれも a.juseiSet に無い          → 不成立
cond.minEnergy != null かつ a.totalEnergy < cond.minEnergy              → 不成立
それ以外 → 成立

空配列・null・未指定の条件は「条件なし」として素通り。

19.3 search(from, to, cond, opts)

from, to  = 'YYYY-MM-DD'(両端を含む)
lim       = yearRange()                                 // 1901〜2100(§3.9。参照実装では range())
variants  = cond.robust  ?  [['kantei','kantei'], ['A','A'], ['kantei','hongen'], ['A','hongen']]      // [月支の流派, 年支・日支の流派]
                         :  [[ opts.zokanMonth || 'kantei', opts.zokanYearDay || 'kantei' ]]
maxHits   = opts.maxHits || 500                         // 画面は {maxHits: 500} だけを渡す。件数を数えたいときは大きな値(例 100000)を渡す

hits = []
for 日 j = jdn(from) .. jdn(to):
  (y,m,d) = fromJdn(j);   y が lim の外ならスキップ
  base = null
  for [vm, vyd] in variants:
    a = meishiki(y, m, d, { zokanMonth: vm, zokanYearDay: vyd })        // ⚠ hour・ijouSet は渡さない(異常干支は既定の13個説)
    base = base ?? a                                                    // 最初の流派の命式を結果に使う
    if !matches(a, cond): この日は不成立(以降の流派は見ない)
  成立なら hits に base を追加。hits が maxHits に達したら打ち切る
return hits
  • robust は「蔵干の区分が流派で違っても成立する日」だけに絞る機能。主星の判定は蔵干に依存するので、流派を替えても残る日は確度が高い。
  • ⚠ 参照実装には、かつて検索だけ別の蔵干('A')で計算されるバグがあり、既定を 'kantei' に揃えた(上の || 'kantei')。

19.4 惜しい日 missing / searchNearMiss

missing(a, cond) = 不成立の項目名を、次の順に並べた配列
   '天中殺'(tenchusatsu 不成立)→ '日干の五行' → '日支の五行'
   → requireShusei のうち a.starSet に無い星を**1つずつ星名で**(複数あれば複数入る)
   → '従星'(requireJuseiAny 不成立)→ 'エネルギー'(minEnergy 不成立)

searchNearMiss(from, to, cond, opts):
  maxHits = opts.maxHits || 200                          // 既定の 200 は画面用(画面は {maxHits: 200} を渡す)。件数を数えるときは大きな値を渡す
  for 日 in 期間(lim の外はスキップ):
    a = meishiki(y, m, d, { zokanMonth: opts.zokanMonth || 'kantei', zokanYearDay: opts.zokanYearDay || 'kantei' })   // robust は見ない
    miss = missing(a, cond)
    miss.length == 1  なら  { meishiki: a, missing: miss[0] } を追加
    件数が maxHits に達したら打ち切る
  • ちょうど1項目だけ欠けている日だけが対象。全部成立している日(miss.length == 0)は含まない。主星が2つ欠けている日は、欠けが2項目と数えるので対象外。

19.5 画面側の追加絞り込み(UI。エンジンの外)

search の結果にさらに次の絞り込みをかける(app.js の extraFilters)。再現が必要なら以下のとおり:

絞り込み 規則
曜日 選んだ曜日(a.weekday)に一致。全部選んでいれば絞らない。0個選びはエラー
祝日を除く/祝日だけ holiday(y,m,d) が null/非 null。同時に選ぶのはエラー。祝日表は1948年以降のみ(hasHolidayData)
吉日 選んだ名前のうちどれか1つでも kichijitsu(a).good に含まれる
三隣亡を除く kichijitsu(a).bad に '三隣亡' が無い
異常干支の日 a.ijou.day が真('通常' か '暗合'。§6)
新月だけ/満月だけ a.moon.kind が一致。同時に選ぶのはエラー

入力の検証:開始日・終了日が必須/開始 ≦ 終了/範囲は 1901-01-01〜2100-12-31/期間は diffDays(開始, 終了) ≤ 366×30(diffDays は終了−開始の日数差で、両端を含む日数ではない)。エラーのときは文言を表示して処理を止める。

補足:

  • 絞り込みは search の結果(maxHits: 500 で打ち切ったあと)にだけかける。惜しい日 searchNearMiss(maxHits: 200)には絞り込みをかけない。
  • 画面は search に opts を渡さない(蔵干の流派は既定の kantei、時柱なし)。
  • 新月だけ/満月だけは、a.moon が null の日(大半の日)を「不一致」として落とす。
  • 祝日で絞るとき、開始日の年が祝日表の範囲外(1948年より前)ならエラーにする(hasHolidayData(開始年) が偽)。

20. 鑑定レポート(15章)

buildReport(a, gender, opts) は、命式 a から 15章の読み物を組み立てる。本文はすべて固定文(R_* の表)と、条件による選択・つなぎ合わせだけでできていて、AIは使っていない。同じ命式なら必ず同じ文が出る。

この章の位置づけ

文章の言い回し・句読点・全角スペース・接続の順序まで一致させるには、付録B_鑑定レポート文章テーブル の report_text.js(buildReport と R_* 表の原文)をそのまま移植するのが確実。
この章は、そのコードを読むための設計図——どの章が何を材料にし、どの条件で何を出し分けるか——を書いたもの。条件・しきい値・出す順序は、ここに書いたとおりに実装すれば一致する。 文章の中身は付録Bが正。

20.0 共通

戻り値   [ { title, lead, items:[ {h, body}, … ] }, … ]       // 15章。h=小見出し、body=本文
push(title, lead, items) … items から null と body が空文字のものを取り除いて章に積む(章そのものは残る)
入力 a   meishiki() の戻り値。ただし次の2点が必要:
           ・a.date が 'YYYY-MM-DD'(大運の再計算に使う)
           ・時柱を出したいときは meishiki に hour を渡して作ったもの(a.hourPillar)
gender   'male' / 'female'(大運の向きにだけ使う)
opts     第3引数。受け取るが**使わない**(互換のための引数。`{}` を渡してよい)
※ 章8・14 の大運は `daiun` を呼ぶので、**順行で 2100-12-07 以降の生まれは `buildReport` も落ちる**(§15.1)

先に計算しておく値(章をまたいで使う)
  sk  = shinkyo(a)               §9
  tei = teiichi(a)               §13
  su  = suurihou(a)              §8          gs = ['木','火','土','金','水']
  vals = gs の順に su.byGogyo の値            avg = su.total / 5
  kd  = koudouRyoiki(a)          §10
  rk  = rokushin(a)              §11
  du  = daiun(生年, 生月, 生日, gender, { count: 12 })       // ⚠ a を作ったときの opts(蔵干の流派・異常干支の説)は引き継がない。常に既定(kantei/13個説)で再計算する

数値の書式:toFixed(1)(小数1位に四捨五入)。平均 avg は total/5 で、小数部が .5 になる値は出ないので、言語による丸め方式の差は出ない。

しきい値の一覧(章ごとに値が違うので注意)

用途 章 判定
身強・身弱・中庸(sk.label) 1, 10, 11, 15 §9:エネルギー ≥25 身強/≤14 身弱
「エネルギーが高い・低い」の文 4, 10, 13 totalEnergy ≥30 高い/≤15 低い/それ以外 ほどよい
五行が多い・少ない(本文) 5, 11 v ≥ avg×1.3 多い/v ≤ avg×0.7 少ない
五行が多い(健康) 13 v ≥ avg×1.4
五行が少ない(健康) 13 v ≤ avg×0.7
偏りの幅 5 haba ≥ total×0.35 大きい/haba ≤ total×0.15 よく散る/他 ほどよい
行動領域の広さ 6 ratio ≥ 0.55/ratio ≤ 0.3/他。⚠ ≥0.55 は到達しない(円に内接する三角形の ratio は最大でも約0.4135)。実際に出るのは「≤0.3 か、その間」だけ
大運のエネルギー 8 R_DAIUN_E を先頭から見て energy ≤ max の最初の行(max は 3, 6, 9, 12)。無ければ最後の行

20.1 章ごとの設計

章の題(title)とリード文(lead)

15章とも題とリード文は固定(章8のリード文だけ、大運の向きと立運で変わる)。題は番号つき。

# title lead
1 1. この命式の全体像 最初に、全体を一枚で見ておく。以降の章はここを細かく分解したもの。
2 2. 陰占 ― 生まれ持った素材 干支は、その人がどんな素材でできているかを表す。三つの柱それぞれに役割がある。
3 3. 陽占 ― 表に出る性格と役割 人体図の9マスは、場面ごとの顔を表す。同じ星でも、置かれた位置で意味が変わる。
4 4. 十二大従星 ― 人生の三つの時期 従星は、その時期にどれだけの力が出せるかを表す。点数の合計が36点満点の従星エネルギー。
5 5. 数理法・八門法 ― 気の偏り 28元それぞれの点数を五行にまとめたもの。多い五行はよく使う力、少ない五行は意識して補う力。
6 6. 行動領域 ― 動ける範囲 六十干支の円に三柱を置いて結んだ図。三角形の位置が性質、広さが動ける範囲を表す。
7 7. 六親法 ― 家族との縁 日干から見た家族それぞれの干を、陰占の中から探す。どの段階で見つかったかが縁の濃さになる。
8 8. 大運 ― 10年ごとの流れ {direction}で、{startAge}歳から10年ごとに切り替わる。各期間の主星は「その10年の課題」、従星は「その10年に出せる力」を表す。
9 9. 天中殺 ― 定まらない時期の使い方 R_TCS_COMMON
10 10. 仕事と適職 社会(東方)の星が「外での立ち回り」を、力の型が「どんな立場が合うか」を表す。
11 11. お金との付き合い方 引力本能の星(禄存・司禄)と、五行の土の量から読む。
12 12. 結婚とパートナーシップ 配偶者(西方)の星が、身近な相手にどう接するかを表す。
13 13. 健康と体の使い方 五行の少ないところは、その臓腑に負担が出やすいと読む。医学的な診断ではなく、生活の目安として。
14 14. 年代別のアドバイス 大運(10年ごと)を年代に重ねたもの。いま何を優先すべきかの目安になる。
15 15. 陽転させるには R_YOUTEN_LEAD

小見出し h の全文一覧(全章。ゴールデン268件で検証済み)

{…} は値が入る場所。h は完全一致で比べられるので、一字も変えない。字種の約束:

文字 コードポイント 使われ方
  U+3000(全角スペース) 「ラベル 値」の区切り。例 日干支 甲子、領域 第一領域
U+0020(半角スペース) 平均 21.4点、従星エネルギー 27/36、円の 3.1% のように数字の前後に入る。表に書いたとおりの位置で使う
( ) U+FF08 U+FF09(全角括弧) すべての括弧
/ U+FF0F(全角スラッシュ) 27/36、定位置(2/5)、{shusei}/{jusei}
= U+FF1D(全角イコール) 社会の星=…
〜 U+301C(WAVE DASH) {year}年〜({age}歳〜)
― U+2015(HORIZONTAL BAR) 日干「甲」― 生まれ持った性質、章の題
「 」 U+300C U+300D 日干「甲」
・ U+30FB(中黒) 柱名や五行の連結
% U+0025(半角) 円の 3.1%(全角 % ではない)
. U+002E .1f の小数点(半角)
章 h(出る順) 出す条件
1 日干支 {日柱の干支}(六十干支の{no}番)/日干「{日干}」― 生まれ持った性質/日支「{日支}」― その性質が立つ土台/本質(中心の星)/この星が活きているとき/この星がこじれているとき/伸ばすときの勘どころ/力の型/天中殺/親から受けた天中殺 常に10項目
2 年柱 {干支}({no}番)/月柱 {干支}({no}番)/日柱 {干支}({no}番)/時柱 {干支}/異常干支({年柱・月柱・日柱のうち該当するものを「・」でつなぐ}) 時柱は a.hourPillar があるとき。異常干支は a.ijou の3柱のどれかが真のとき(時柱は数えない)。柱名は 年柱・月柱・日柱。時柱の h には番号を付けない
3 {R_POS[k].label} {星}({本能}・{五行}性) を center, north, south, east, west, ancestor の順に6つ/人体図全体から読めること/定位置({count}/5) 常に8項目
4 {R_JUSEI_POS[k]} {従星名}({energy}点) を early, mid, late の順に3つ/エネルギーの配分 常に4項目
5 {五行} {v}点(平均 {avg:.1f}点) を 木火土金水の順に5つ/偏りの読み方(合計 {total}点) 常に6項目
6 この図の見方/領域 {名}(kd.spread の数だけ)/広さ 円の {ratio×100:.1f}%({kd.label}) 常に(2+spread の数)項目
7 {key} {real または なし} を7人/六親法の読み方 常に8項目
8 {year}年〜({age}歳〜) {kanshi} {shusei}/{jusei} を12行 常に12項目
9 本人の天中殺 {名}/親から受けた天中殺 {名}/この期間に、やらないほうがよいこと/この期間を、何に使うとよいか/天中殺の扱い方について 常に5項目
10 向いている働き方(社会の星={workStar})/立場の選び方({sk.label})/動き方({spread[0]})/働く体力(従星エネルギー {totalEnergy}/36)/避けたほうがよい環境({中心の星}の弱点から)/中心の星から見た軸({中心の星})/星の組み合わせから見る適性({n}通り)/人を育てる適性/天中殺との関わり 適性は matchTekisei が空でないとき。人を育てるは kyouikuSei.pairs が空でないか kyouiku.count > 0(時柱の教育の干支も数える)のとき。他は常に
11 入れ方・貯め方/土の量({doV}点/平均 {avg:.1f}点)/使い方の癖(中心の星={中心の星})/力の型から見た稼ぎ方({sk.label})/天中殺との関わり 常に5項目
12 身近な人への接し方(配偶者の星={marryStar})/うまくいく距離感/相手に求めやすいもの(中心の星={中心の星})/日支「{日支}」から/六親法から見たパートナー/天中殺との関わり 常に6項目
13 {五行}が少ない(v ≤ avg×0.7 の五行ごと)または 五行の偏り/{五行}が多い(v ≥ avg×1.4 の五行ごと)/体力の型(従星エネルギー {totalEnergy}/36)/生活で気をつけること 五行の偏り は「少ない」の項目が 0件のとき(「多い」があっても出す)。並びは「少ない」の全項目 → 「多い」の全項目の順で、それぞれの中は木火土金水の順(五行ごとに少ない・多いを交互に並べるのではない)
14 {label}({age}歳{shusei}/{age}歳{shusei}/…)(括弧の中は、その区分に入る大運の全行を / でつないだもの。切り詰めない。「先頭3行」の制限は本文だけにある) その区分に大運の行があるとき(count:12 では必ずある)
15 前提/定位置の星は、放っておいても陽転しやすい/{星}({位置ラベル}) を星の数だけ/天中殺の使い方/異常干支の使い方/まとめ 異常干支は章2と同じ条件(a.ijou の3柱。時柱は数えない)。位置ラベルは youtenOrder(center, east, west, south, north, ancestor)の順に「・」でつなぐ(R_POS の並びではない)

全角スペース   と半角スペース が混在している(上の字種の表を参照)。表に書いた位置のとおりに写す。

章1 この命式の全体像(10項目)

lead:最初に、全体を一枚で見ておく。以降の章はここを細かく分解したもの。

# h 材料
1 日干支 {日柱の干支}(六十干支の{no}番) R_NIKKAN[日柱の干支] + 固定の説明
2 日干「{日干}」― 生まれ持った性質 R_KAN[日干]
3 日支「{日支}」― その性質が立つ土台 R_SHI[日支]
4 本質(中心の星) 中心の星名(五行性・本能)+ R_STAR[星].core
5〜7 この星が活きているとき/この星がこじれているとき/伸ばすときの勘どころ chousho/tansho/nobasu
8 力の型 sk.label(従星エネルギー {totalEnergy}/36)+ R_SHINKYO[label] + sk.hasTenshosei なら天将星の一文
9 天中殺 a.tenchusatsu + R_TCS[…]
10 親から受けた天中殺 a.tenchusatsuYear + 固定の説明 + R_TCS[…] の最初の一文(。で割った先頭)

章2 陰占 ― 生まれ持った素材

項目は年柱・月柱・日柱の3つ(h={年柱|月柱|日柱} {干支}({no}番))。a.hourPillar があれば 時柱 {干支} を追加。a.ijou.year / month / day のどれかが真('通常'・'暗合'など値あり。時柱は数えない)なら、最後に 異常干支({該当する柱を「・」でつないだもの})(柱名は 年柱・月柱・日柱)+ R_IJOU を追加。
各柱の本文:R_PILLAR_WHAT[柱] + 天干 R_KAN + 地支 R_SHI + 採用する蔵干(pillar.zokan)と R_ZOKAN_POS[柱] + R_KAN[蔵干] の最初の一文。

章3 陽占 ― 表に出る性格と役割(8項目)

位置の順は center, north, south, east, west, ancestor(中心→北→南→東→西→伴星)。

  • 位置ごとの項目:h={R_POS[k].label} {星}({本能}・{五行}性)、body={R_POS[k].gov}を表す位置。 + R_STAR_POS[星][k]。
  • 人体図全体から読めること:6つの星を数える。同じ星が2マス以上 → dup(出た順)。持っていない本能(ALL_H = ['守備本能','伝達本能','引力本能','攻撃本能','習得本能'] の順)→ missing。中心の星 c と社会(東)の星 e が同じか違うかで分岐。本文中の「5マス」という言い方は固定文。
  • 定位置({count}/5):tei.count と tei.rows(ok のもの/okでないもの)から文を作る。R_TEIICHI_COUNT の添字は count ≥ 3 → 'many'、count == 0 → 'none'、他 → 'few'。精神・現実の寄りの文は次のとおり(この不等式のまま):
    tei.spirit > tei.real / 1.5   → 「精神の側が定位置に寄っており…」
    それ以外で tei.real > tei.spirit * 1.5 → 「現実の側が定位置に寄っており…」
    それ以外 → (何も付けない)
    
    (spirit=1, real=1 でも最初の式が真になる点に注意。0,0 はどちらも偽。)

章4 十二大従星 ― 人生の三つの時期(4項目)

early, mid, late の順。h={R_JUSEI_POS[k]} {従星名}({energy}点)、body=R_JUSEI[名].core +  強みとして出るのは―― + tsuyomi +  気をつけたいのは―― + chuui。
最後に エネルギーの配分:3つのエネルギー e の最大の最初の位置(indexOf(max))を「いちばん力が出る時期」、最小の最初の位置を「いちばん出ない時期」とする(同点なら先頭側)。totalEnergy ≥ 30 → 高い、≤ 15 → 低い、他 → ほどよい。

章5 数理法・八門法 ― 気の偏り(6項目)

gs の順に 5項目:h={五行} {v}点(平均 {avg:.1f}点)、body=R_GOGYO_WHAT[g] +   +(lv があれば R_GOGYO_LEVEL[g][lv]、なければ「平均的な量。…」)+   + R_GOGYO_USE[g]。lv = v ≥ avg×1.3 → 'many'/v ≤ avg×0.7 → 'few'/他 null。
最後に 偏りの読み方(合計 {total}点):max・min は vals の最大・最小で、対応する五行は gs の先頭側から探した最初のもの(indexOf)。haba = max − min。分岐は §20.0 の表。末尾は R_GOGYO_MOTHER[最少の五行](最少の五行を生む五行)を増やす提案。

章6 行動領域 ― 動ける範囲

項目:この図の見方(固定)→ kd.spread の各領域名ごとに 領域 {名}(R_RYOIKI[名])→ 広さ 円の {ratio×100:.1f}%({kd.label})(R_RYOIKI_WIDTH[label] + §20.0 の3分岐)。

章7 六親法 ― 家族との縁

rk.rows の7人を順に。h={key} {real または なし}。body=理想の干は「{ideal}」({star})。 + level ごとの文(理想どおり/第二優先/定位置は where があれば ({where}) を付ける。なし は別文)+ R_ROKUSHIN_WHO[key](兄弟・姉妹・男子供・女子供はキーが無く空文字)+ real があれば実際の干の説明 + R_ROKUSHIN_LEVEL[level]。最後に 六親法の読み方(固定)。

章8 大運 ― 10年ごとの流れ(12項目)

lead:{direction}で、{startAge}歳から10年ごとに切り替わる。各期間の主星は「その10年の課題」、従星は「その10年に出せる力」を表す。
du.rows の各行:h={year}年〜({age}歳〜) {kanshi} {shusei}/{jusei}。body=R_STAR[shusei].core の最初の一文 + が課題になる10年。 + R_DAIUN_STAR[shusei] +   + R_DAIUN_E で選んだ文 + ({jusei}={R_JUSEI[jusei].core の最初の一文}) +(ijou が真で '通常' でないとき異常干支の一文)+(isDaiunTenchusatsu なら  ★ + R_DAIUN_TCS)。

  • 「最初の一文」=文字列を 。 で割った先頭要素(split('。')[0]、句点は含まない)。
  • 異常干支の一文は '暗合'(13個説)のときだけ出る(章8の du は常に13個説で再計算するため、'通常' は除外、'異常干支' は出ない)。

章9 天中殺 ― 定まらない時期の使い方(5項目)

lead:R_TCS_COMMON。項目:本人の天中殺 {名}(R_TCS)/親から受けた天中殺 {名}(tenchusatsu == tenchusatsuYear で二文に分岐)/固定3項目(やらないほうがよいこと・何に使うとよいか・扱い方について)。

章10 仕事と適職

workStar = 社会(東)の星。項目(出る順):

  1. 向いている働き方(社会の星={workStar}) … R_WORK[workStar] + chousho
  2. 立場の選び方({sk.label}) … R_WORK_SK[label]
  3. 動き方({kd.spread[0]}) … R_WORK_RYOIKI[kd.spread[0]](spread[0] は年→月→日の順で最初に出た領域)
  4. 働く体力(従星エネルギー {totalEnergy}/36) … 高い(≥30)/低い(≤15)/ほどよい +(a.jusei.mid.name == '天将星' なら一文)
  5. 避けたほうがよい環境({中心の星}の弱点から) … tansho + R_WORK_BAD[中心の星]
  6. 中心の星から見た軸({中心の星}) … workStar == 中心の星 で分岐
  7. 星の組み合わせから見る適性({n}通り) … matchTekisei(a)(§20.2)が空でなければ。空なら項目ごと出さない
  8. 人を育てる適性 … kyouikuSei(a).pairs が空で、かつ kyouiku(a).count == 0 なら出さない(どちらかが空でなければ出す)。あれば §14 の文+口伝の断り書き
  9. 天中殺との関わり …
    a.tenchusatsu == '申酉天中殺' → 申酉の一文だけ
    a.tenchusatsu == '戌亥天中殺' → 戌亥の一文だけ
    それ以外 → '仕事に直接かかる天中殺ではない。{名}の年・月は、…' + ' なお天中殺は生涯続くものではなく…'
               (⚠ 末尾の「なお…」は**この枝にだけ**付く。コードでは `else枝 + '…'` と書かれていて、三項演算子より `+` が先に結合するため)
    

章11 お金との付き合い方

hasR=a.starSet に禄存星がある、hasS=司禄星がある、doV = su.byGogyo['土']。
項目:入れ方・貯め方(R_MONEY_STAR[ both | rokuzon | shiroku | none ])/土の量({doV}点/平均 {avg:.1f}点)(R_MONEY_DO[ many(≥avg×1.3) | few(≤avg×0.7) | mid ] + 固定文)/使い方の癖(R_MONEY_CENTER[中心の星])/力の型から見た稼ぎ方(身強・身弱・それ以外)/天中殺との関わり(辰巳天中殺 なら辰巳の一文だけ。それ以外の枝にだけ「お金に直接かかる天中殺ではない。…」に続けて  借入・保証・共同出資… が付く)。

章12 結婚とパートナーシップ

marryStar = 配偶者(西)の星。項目:身近な人への接し方(R_MARRY[星] + taijin)/うまくいく距離感(R_MARRY_KYORI[星] だけ。⚠ コードには「配偶者の星=中心の星なら『外向きの顔と身近な顔が同じなので…』を足す」と書いてあるが、A || '' + (…) の形で A が常に真なので足されることはない。実機で確認済み)/相手に求めやすいもの/日支「{日支}」から/六親法から見たパートナー(rk の「パートナー」行の level で4分岐)/天中殺との関わり(午未天中殺・寅卯天中殺 はそれぞれの一文だけ。それ以外の枝にだけ「{名}の期間に結婚など…」に続けて  ただしこれは… が付く)。

章13 健康と体の使い方

  • 五行が少ない(v ≤ avg×0.7)ものごとに {五行}が少ない(R_HEALTH[g])。「少ない」が1つも無ければ 五行の偏り の1項目(「多い」があっても出す)。
  • 五行が多い(v ≥ avg×1.4)ものごとに {五行}が多い(R_HEALTH_MANY[g])。
  • 体力の型(R_HEALTH_E[ high(≥30) | mid | low(≤15) ] + 3つの従星の配分 + いちばん出ない時期)
  • 生活で気をつけること(R_HEALTH_LIFE[中心の星])

章14 年代別のアドバイス

R_AGE_BAND(5区分。from・to・label・text)の各区分について、du.rows のうち from ≤ age < to の行を集める。無ければその区分は出さない。h={label}({age}歳{shusei}/…)、body=band.text + この年代の課題は{重複を除いた主星を「と」でつなぐ}。 + 先頭3行ぶん({age}歳からの10年は{core の最初の一文}。)+ 大運天中殺が含まれれば ★…。

章15 陽転させるには

youtenOrder = center, east, west, south, north, ancestor の順に星を見て重複を除いた並び。項目:前提(R_YOUTEN_SK[sk.label])→ 定位置の星は、放っておいても陽転しやすい(tei.count の有無で分岐)→ 星ごとに {星}({その星がある位置のラベル})(ラベルは R_POS[k].label。youtenOrder の順に「・」でつなぐ。本文は 陰転すると――in 陽転すると――you 向け方:how)→ 天中殺の使い方(R_YOUTEN_TCS)→ 異常干支が1つでもあれば(章2と同じ条件:a.ijou の3柱のどれかが真。時柱は数えない)異常干支の使い方(R_YOUTEN_IJOU)→ まとめ(固定)。

20.2 星の組み合わせ適性 matchTekisei(a)

held = a.starSet                                          // 人体図6つの星(重複なし)
weight(st) = a.stars.center.star == st ? 3
           : a.stars.east.star   == st ? 2 : 1            // 中心と社会に出ている星は重く見る
R_TEKISEI(16型。各 { stars:[星, 星], name, kishitsu, ba, chuui })のうち、
   stars の2つとも held に入っているものを選ぶ
各型の score = stars の2つの weight の和
score の降順に並べる(同点は R_TEKISEI に書かれた順のまま=安定ソート)

本文では 【{name}】{星+星}。{kishitsu} 向く場:{ba} 気をつけたいこと:{chuui} を   でつなぎ、最後に R_TEKISEI_NOTE。出典は星の意味の掛け合わせであって、組み合わせ表に一本の出典があるわけではないと本文にも書く。

20.3 R_* 表の形

全表の原文は 付録B_鑑定レポート文章テーブル。再実装時に空のまま動かさないために、形だけ示す。

表 形 用途
R_STAR 10星 → {gogyo, honnou, core, chousho, tansho, shigoto, taijin, nobasu} 章1, 3, 8, 10, 12, 14
R_POS 6位置 → {label, gov} 章3, 15
R_STAR_POS 10星 → 6位置 → 文(60通り) 章3
R_JUSEI 12従星 → {e, core, tsuyomi, chuui} 章4, 8
R_JUSEI_POS early\|mid\|late → 見出し(初年期(0〜20歳ごろ) など) 章4
R_KAN / R_SHI 10干/12支 → 文 章1, 2, 7, 12
R_NIKKAN 60干支 → 文 章1
R_PILLAR_WHAT / R_ZOKAN_POS year\|month\|day → 文 章2
R_GOGYO_WHAT / R_GOGYO_USE / R_GOGYO_LEVEL / R_GOGYO_MOTHER 5五行 → 文(R_GOGYO_LEVEL は {many, few}、R_GOGYO_MOTHER は1文字) 章5
R_RYOIKI / R_RYOIKI_WIDTH 4領域/5つの広さラベル → 文 章6
R_TCS 6天中殺 → 文 章1, 9, 10, 11, 12
R_SHINKYO 身強・身弱・中庸 → 文 章1
R_DAIUN_E 配列4件 {max, text} 章8
R_DAIUN_STAR 10星 → 文 章8
R_AGE_BAND 配列5件 {from, to, label, text} 章14
R_WORK / R_WORK_SK / R_WORK_RYOIKI / R_WORK_BAD 星/身強弱/領域 → 文 章10
R_MONEY_STAR / R_MONEY_DO / R_MONEY_CENTER 条件キー/星 → 文 章11
R_MARRY / R_MARRY_KYORI 10星 → 文 章12
R_HEALTH / R_HEALTH_MANY / R_HEALTH_E / R_HEALTH_LIFE 五行/high-mid-low/星 → 文 章13
R_ROKUSHIN_WHO / R_ROKUSHIN_LEVEL キーは 母親・父親・パートナー・家系・子供 のみ/4つの level → 文 章7
R_YOUTEN / R_YOUTEN_SK 10星 → {in, you, how}/身強弱 → 文 章15
R_HONNOU_MISS 5本能 → 文 章3
R_TEIICHI_POS / R_TEIICHI_COUNT 5位置/many\|few\|none → 文 章3
R_TEKISEI 配列16件 章10
固定の長文 R_TCS_COMMON R_DAIUN_TCS R_IJOU R_YOUTEN_LEAD R_YOUTEN_TCS R_YOUTEN_IJOU R_TEIICHI_LEAD R_TEIICHI_NOTE R_TEKISEI_NOTE 各章
使われていない定数 R_MARRY_KANGO(定義だけで buildReport から参照されない。移植するなら捨てて構わない) —

21. つまずきやすい所(実装の癖・既知の限界)

再実装で一致しなくなる原因の大半は、ここに挙げたものです。迷ったらこの章を先に見る。

21.1 暦

# 癖 正しい扱い 節
1 Date を使うと実行環境のタイムゾーンで日付がずれる 日付は整数のユリウス日だけで計算する §2.4
2 節入りの時刻は結果に影響しない 節入りの日で切り替える(その日の0時から新しい月・年)。立春が 23:58 の年(2021)でも当日から新年 §3.2
3 keika(節入りからの日数)は節入り日を1日目と数える keika = 対象日 − 節入り日 + 1 §3.2
4 1月上旬の月柱・蔵干は前年12月の節を参照する 節入り表の y−1 年も引く。だから対応範囲は 1901〜2100(表は1900〜2100) §3.9
5 年柱は「同じ年の2月の立春日」と比べる(rows[1][0] = 表の2番目=立春) 1月は常に前年の年柱になる §3.3
6 1〜2月の月柱は、年干が前年のもので五虎遁を計算する 年柱を先に決めてから、その年干で月干を出す §3.4
7 蔵干の区分 keika は年支・日支・時支にも月の節からの日数を使う(それぞれの支の節ではない) 月支=zokanMonth、年・日・時=zokanYearDay。stages(3段の表示)は常に既定表 §3.7.3
8 時柱は 23時台を翌日にしない(夜子時を採らない) idx = floor(((hour+1) % 24) / 2)、日干はその日のもの。hour = 0 は有効(null だけが「時柱なし」) §3.6
9 割り算・剰余の符号 JS の % は負数で負を返すので ((x % n) + n) % n。Python の % は不要。floor は負数でも切り下げ 全般

21.2 命式・星

# 癖 正しい扱い 節
10 陰陽の向き 天干は 甲丙戊庚壬=陽。エンジン内部の番号は「陽=1」だが、六親法の補助関数 yinOf は「陽=0」(i % 2)。混ぜない §2.2, §11.1
11 従星の巡り 日干が陽なら順行、陰なら逆行。起点は日干ごとの長生の位置 §4.3
12 人体図の星は 6つ(伴星=ご先祖様を含む)。ただし 定位置・才能(剋数)は伴星を除く5つ 用途ごとに数える集合が違う §4.2, §12, §13
13 伴星 shusei(日干, KANGO[年干])(年干の干合相手の干から見る) §4.2
14 starSet の並びは ancestor, north, center, south, east, west の順(重複は初出のみ) 相性の sharedStars の並びがこれに従う §17
15 身強・身弱はエネルギー合計だけで決まる(≥25 身強/≤14 身弱)。強い星の個数は表示用 レポート本文の「高い・低い」は別のしきい値(30/15)で、混同しやすい §9, §20.0

21.3 応用技

# 癖 正しい扱い 節
16 行動領域の円に打つのは十二支ではなく六十干支の通し番号(1〜60)。1番が真上、6度ずつ時計回り deg = (no−1)×6 §10
17 六親法 ①日干の席は「自分」なので家族に数えない ②父・子は理想の干ではなく実際に見つかった干から辿る ③子供には定位置を使わない ④性別を使わない ⑤同じ干を複数の家族が使ってよい §11
18 才能の型の判定は上から順(無玄→五宮同均→了殿→点欽→順殿) 順序を入れ替えない §12.2
19 大運の立運は min(round(days/3), 10)。順行は「次の節入りまで」、逆行は「前の節入りから」。節入り当日生まれの逆行は 0 歳 順行では当日は「次の節」に数えない(厳密に後) §15
20 既知の限界:順行の大運は 2100-12-07 以降で、次の節が表に無く参照実装が落ちる 再実装では仮置き(2101-01-05)かエラーにしてよい §15.1
21 レポートの大運(buildReport 内の daiun)は、命式を作ったときの opts を引き継がない 蔵干の流派・異常干支の説は常に既定で計算される §20.0

21.4 相性・暦注・検索

# 癖 正しい扱い 節
22 相性 kind は日干の五行どうしだけで決まる(陰陽は見ない)。tcsKey の判定は same → bInA → aInB → none の順で、戻り値の bInA・aInB はそれとは別に独立した真偽 排他にしない §17.1
23 相性の reading は空文字を取り除いた配列。general では間柄別の文が入らない 配列の長さが mode で変わる §17.1
24 詳細文の身強弱は「中庸」を強として扱う。位相法はぶつかる側が調和側に優先する tension が1つでもあれば tension §17.2
25 己巳の日 は 巳の日 と重ねて付けない if 己巳 … else if 巳 §18.1
26 検索は meishiki に hour も ijouSet も渡さない(異常干支は13個説、時柱なし)。robust は蔵干4通りのすべてで成立する日だけ(1つでも不成立なら落とす=AND) ijou で絞る画面側の機能は13個説で動く §19.3
27 惜しい日は「欠けがちょうど1項目」のとき。主星が2つ欠けていれば2項目と数える missing.length == 1 §19.4
28 祝日・月相は表を引くだけ(計算しない)。表が無ければ null 表の再生成手順は付録A §18.2–3

21.5 鑑定レポート(文章の組み立て)

# 癖 正しい扱い 節
29 三項演算子の優先順位:A ? x : B ? y : z + w は、+ w が最後の枝 z にだけ付く。章10・11・12の「天中殺との関わり」は、末尾の一文が一部の枝にしか付かない 付録Bのコードの結合順を崩さずに移植する §20.1
30 章12「うまくいく距離感」は A \|\| '' + (…) の形で、A が常に真なので追加文は一度も出ない 追加文を実装しない(出してはいけない) §20.1
31 章6の ratio ≥ 0.55 の枝は到達しない(最大 約0.4135) そのまま残してよい §20.0
32 R_ROKUSHIN_WHO には「兄弟・姉妹・男子供・女子供」のキーが無く、その人の行は空文字で連結される \|\| '' §20.3
33 「最初の一文」= text.split('。')[0]。句点を含まない。文中に 。 が無ければ全文 句点を足し戻す箇所は本文側に書いてある §20.1
34 indexOf は最初の一致を返す。最大・最小が同点なら先頭側(木→火→土→金→水、初年→中年→晩年)が選ばれる 章4・5・13 §20.1
35 章3の本文には「9マス」「5マス」という固定の言い方が残っているが、実際に並べる星は6つ 文言はそのまま §20.1
36 R_MARRY_KANGO は定義だけで使われていない 捨ててよい §20.3
37 toFixed(1) は四捨五入。avg = total/5 は小数1位で割り切れるので言語差は出ないが、ratio×100 は浮動小数点なので 同じ式・同じ順序(倍精度) で計算する (ratio * 100).toFixed(1) §20.1

21.6 数値表現

  • 行動領域の area は半径1の円に内接する三角形の面積を倍精度で計算する。六十干支の番号の組み合わせは 60³=216,000 通りで、ratio がしきい値 0.35/0.18 に最も近い組でも 3.4e-4 以上離れている(実測)ので、倍精度ならどう式を書いても label は変わらない。それでも念のため cos/sin/外積の順は変えずに書く。ゴールデンでは area・ratio を小数6桁に丸めて比べている。
  • レポート章5・11・13 のしきい値は、avg = total / 5 を先に作ってから v >= avg * 1.4(または 1.3)、v <= avg * 0.7 と比べる。total が 25 の倍数のとき v がちょうど境界になる日があり(例 total=50 で avg*1.4 = 14.0)、total * 0.28 のように式を変えると浮動小数点で結果が割れる。
  • 日付は YYYY-MM-DD(ゼロ詰め)。時刻 HH:MM もゼロ詰め。

22. テストベクタと検証の記録

22.1 何が用意されているか

資料 場所 中身
作業例(中間値つき4件) 付録F_テストベクタ §F.1 ユリウス日→日柱→節→年柱→月柱→蔵干→人体図→従星→天中殺→大運を、数字を追って確かめられる形で
命式のゴールデン(41件) 付録F §F.2 範囲の端・立春前後・節入り前後・うるう日・出生時・蔵干の3流派・異常干支の2説。各行が meishiki の正規化された出力(JSON)
応用技のゴールデン(13件) 付録F §F.3 数理法・身強弱・行動領域・六親法・才能・定位置・吉日・位相法・教育の干支・教育の星・祝日
大運・行運・相性・暦・検索 付録F §F.4 大運12本×男女、行運(年・月・日・時)、行運一覧、相性(文章まで)、JDN・祝日・月相、検索10条件
全量のゴールデン生成スクリプト 付録F §F.5 参照実装から、基本 3,333 日(1901〜2100年、節入り前後と立春前後を厚く)に隅のケースを足した 11ファイル(約26MB) を一括生成する gen_golden.cjs。各ファイルの形・行数・比べ方・固定文の指紋は §F.5.1
使い方
  1. まず「作業例」を手で追い、自分の実装の中間値が合うかを見る(ここでずれたら §3 を読み直す)。
  2. 命式のゴールデンで meishiki を合わせる。この関数が合えば、以降の応用技は入力が揃う。
  3. 応用技 → 大運・行運 → 相性 → 暦 → 検索 の順に合わせる。
  4. 最後に gen_golden.cjs の全量と突き合わせる(参照実装が手元にあるとき)。

22.2 比較の方法

  • 文字列・配列・真偽値はそのまま一致させる。配列の並びも一致の対象(starSet、reading、sharedStars、talent など)。
  • 小数は area・ratio を小数6桁に丸めて比べる。
  • 大運で参照実装が落ちる行(error)は比べない。
  • 書き写した固定表は、fixed_text_hashes.json の指紋(SHA-256)で一字一句の一致を確かめる(付録F §F.5.1)。
  • report_heads.json は見出し h の並びだけ比べる(本文の長さは比べない)。

22.3 参照実装の自己検証(元のリポジトリの tests/)

スクリプト 検証内容 結果(2026-10-05 再実行の出力)
verify_kantei.cjs 実在アプリ kantei-app.com の出力165ケース(三柱・干支番号・蔵干3段・採用蔵干・人体図5マス・従星3つ・天中殺2種・大運12本) 照合ケース数: 165 / 不一致: 0 件
verify_rokushin.cjs sanmei-stock の六親法(規則を割り出した221日、追試72日) 理想の干 1547/1547 実際の干 1547/1547、理想の干 504/504 実際の干 504/504
verify_kichijitsu.cjs 吉日・凶日の規則 暦と一致(天赦日12ヶ月ぶん・一粒万倍日6ヶ月ぶん・寅巳の整合 60日)

22.4 別のAIによる再実装テスト(清書室)の記録

この仕様書が「別のAIが同じ出力を再現できる」ものになっているかを、実際に別のAIに実装させて確かめた記録(2026-10-05)。

方法

  • 隔離フォルダに、この仕様書(付録Dの engine.js は入れない)・データ表(付録A)・相性の固定文(付録C)・ゴールデンだけを置いた。参照実装は見られない。
  • 担当を4つに分けた:①コア(§2〜§9・§15・§16・§18)/②応用技(§10〜§14)/③相性と検索(§17・§19)/④鑑定レポートの構造(§20 の章の題・リード・小見出し・出す/出さない条件)。
  • 実装者は Claude Sonnet。Python 3.9 で一から書かせた。禁止事項は「参照実装を探さない」「ゴールデンの値の丸写し」「仕様書の書き換え」。仕様書を正しく読んでも答えが決まらないときだけ「仕様の不備」として報告させ、ゴールデンを見て決めた箇所は必ず明記させた。
  • 2世代行った。第1世代の指摘を仕様書・説明書・ゴールデンに反映したあと、前世代の成果物を見られない新しい実装者で全部やり直した(第2世代)。

結果

「初回」は、ゴールデンの JSON の中身を見る前に、仕様書とゴールデンの説明書だけで書いた実装を初めて走らせたときの一致率。

担当 第1世代・初回 第2世代・初回 最終(両世代とも)
① コア 100%(23,073/23,073)。ただし3か所は仕様が曖昧で、推測が当たっただけ 100%(19,238/19,238) 全件一致
② 応用技 ロジックは 100%。戻り値の形が説明書に無く、そのまま比べると 21.4%(2,243/10,482) 100%(10,482/10,482)。固定表の指紋 7/7 全件一致
③ 相性と検索 100%(1,544/1,544)。ただし searchNearMiss の maxHits を既定のままにすると 98.8% 100%(22,260 + 120 + 112)。照合スクリプトが説明書の書き不足で2回止まっただけ。指紋 14/14 全件一致
④ レポートの構造 小見出し 73.3%(2,948/4,020)。章9・11・12・13 の小見出しの全文が仕様書に無かった 100%(292/292 の5カテゴリ)。指紋 52/52 全件一致
  • 実装ミス(仕様は一意なのに読み違えた)は両世代とも 0 件。 落ちたのはすべて、仕様書・説明書の書き不足か、仕様の曖昧さだった。
  • 最終状態:両世代の8つの実装すべてが、追加ケースを足した最終のゴールデンに全件一致(コア 26,222、応用技 1,758行×6カテゴリ、相性 2,246行・検索 22行・missing 60行、レポート 292行×5カテゴリ。第2世代のコアは 19,633 + 暦・検索の追加 1,157)。
  • 書き写した固定表の指紋(SHA-256)も一致(戻り値の形が仕様書と違っていた表は、form を見て形を合わせた)。
  • 3つのデータ表(付録A)は、スクリプトからの再生成がバイト単位で元ファイルと一致。

テストで見つかり、仕様書に反映したもの(主なもの)

区分 内容
出力を変えうる曖昧さ(第1世代で発見) 異常干支の説を年・月・日の3柱にも渡す(§3.8)/gogyoDist は個数0の五行のキーを作らない(疎)が byGogyo は5キー固定(密)(§4.2・§8)/setsu.jst の年は節を引いた表の年(§3.8)/検索の robust は「蔵干4通りのすべてで」(§21.4)
仕様内の誤記 大運が落ちる境界は 2100-12-07(§3.2・§3.9 が 12-08 と書いていた)/大運の例(1984-10-10・startAge=3)は実在しない組み合わせだった(§15.1)
書き足したもの 蔵干Aの表(§3.7.2)/TEIICHI(§11.3)/戻り値の宣言(§10・§13・§14.2)/moonPhases が両端を含むこと(§18.3)/\|\| と ?? の意味(§0.3)/日本語名と命式キーの対応表(§0.3)/固定表の名前と形(INYO_KAN の 1/0、JU_MAP の配列値、TENSHA のキーなど)
レポート 小見出し h の全文一覧(§20.1)/全角・半角スペースと記号のコードポイント/章13・14・15 の並びと条件
ゴールデンの説明書 各ファイルの入力の形、derived.json の正規化後の形、search.json の opts、比べないキー、固定文の指紋
ゴールデンに足した隅のケース 2000年366日×蔵干3流派×出生時24通り/行運の異常干支7個説/2100-12 の境界/年運の頭打ち・2月(うるう年)/gender の書き方違い/robust の4流派・maxHits の打ち切り・範囲外の年/同じ日どうしの相性/六親法で同じ干が多くの席に載る日/まれなレポート分岐

限界(正直に)

  • 実装者は同じ系列のモデル(Claude Sonnet)。人間や別系列のAIでの再現は試していない。
  • 第2世代のあとに入れた修正(説明書の入力の形・指紋の form・字種の表・記法の注記など)は、さらに新しい実装者での再実装まではしていない。ただし既存の8実装は、修正後のゴールデンに全件一致している。
  • 鑑定レポートの本文(固定文の組み立て)は、このテストの対象外。構造(題・リード・小見出し・出す条件)だけを確かめた。本文は 付録B_鑑定レポート文章テーブル のコードを正とする。
  • ゴールデンが踏んでいない分岐は残っている(たとえば 2100-12-07 以降の順行の大運は、参照実装が落ちるので比べられない)。
  • 検証したのは「参照実装と同じ出力を返すか」であって、算命学として正しいかではない(流派差については §0.3・付録E_観測と調査の記録)。

22.5 エンジンを変えたときの更新手順

この仕様書は、2026-10-05 時点の engine.js・aisho_detail.js・report_text.js と3つのデータ表に対応している。参照実装を変えたら、次の順に直す。

  1. 付録D・B・C(コードの全文)を貼り替える。
  2. データ表を変えたら付録Aを貼り替え、スクリプトで再生成して元ファイルと一致することを確かめる。
  3. 付録F §F.5 の gen_golden.cjs でゴールデンを作り直し、旧版と差分を取る。差が出た箇所が、本編で直す場所。
  4. 差の出た節を本編で直す。固定文を変えたときは fixed_text_hashes.json の指紋も作り直す。
  5. 本編とゴールデンだけを新しい実装者に渡して再実装させ、照合する(§22.4 の方法)。
Share Note for Obsidian 🌓