dsh-metaphysics 0.50.5 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1102 -1005
- package/README.md +367 -355
- package/client.almanac.js +129 -0
- package/client.bazi.js +168 -0
- package/client.chenggu.js +129 -0
- package/client.convert.js +129 -0
- package/client.daliuren.js +167 -0
- package/client.fengshui.js +128 -0
- package/client.hepan.js +167 -0
- package/client.js +638 -18939
- package/client.liuyao.js +167 -0
- package/client.mbti.js +129 -0
- package/client.name.js +129 -0
- package/client.numerology.js +129 -0
- package/client.qimen.js +167 -0
- package/client.star.js +129 -0
- package/client.tarot.js +167 -0
- package/client.trend.js +167 -0
- package/client.xiaoliuren.js +129 -0
- package/client.zeri.js +129 -0
- package/client.ziwei.js +168 -0
- package/docs/assets/verification-badge.svg +13 -0
- package/engine/almanac.js +4 -4
- package/engine/bazi.js +98 -21
- package/engine/citations.js +320 -0
- package/engine/classics.js +567 -559
- package/engine/diff.js +350 -301
- package/engine/fengshui.js +272 -28
- package/engine/fingerprint.js +76 -0
- package/engine/followup.js +31 -3
- package/engine/geju.js +531 -475
- package/engine/index.js +311 -13
- package/engine/interpret-knowledge.js +502 -484
- package/engine/interpret-plain.js +383 -383
- package/engine/interpret.js +1885 -1867
- package/engine/qimen-ganying.js +134 -0
- package/engine/qimen-interpret.js +31 -9
- package/engine/qimen.js +16 -1
- package/engine/shensha.js +6 -3
- package/engine/trace.js +456 -0
- package/engine/ziwei.js +117 -8
- package/index.js +51 -3
- package/package.json +113 -106
- package//345/221/275/347/220/206/346/216/222/347/233/230.html +9418 -7122
package/engine/trace.js
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
// A1 推导链:把排盘过程中真正用到的中间层摊开,每层给
|
|
2
|
+
// { field, rule, inputs, result, source }。
|
|
3
|
+
//
|
|
4
|
+
// 只读结果、不重算、不读时间与随机:trace 开着或关掉,盘面必须逐字节一致。
|
|
5
|
+
// 目前覆盖六爻(纳甲→六亲→世应→伏神→旺衰)、八字(旺衰分值、格局取用)、
|
|
6
|
+
// 紫微(格局命中条件)、奇门(盘面事实→用神落宫→门/星/干旺衰→宫位生克)
|
|
7
|
+
// 与大六壬(天地盘→四课→三传);其余体系不产出 trace。
|
|
8
|
+
import { PATTERN_TONE } from './ziwei.js';
|
|
9
|
+
import { yongshenOf, yongshenStrength, fushenAccess } from './liuyao.js';
|
|
10
|
+
import { qimenYongshen } from './qimen-interpret.js';
|
|
11
|
+
import { GAN_JI_GONG } from './daliuren.js';
|
|
12
|
+
|
|
13
|
+
const SYSTEM_LABEL = { liuyao: '六爻', bazi: '八字', ziwei: '紫微', qimen: '奇门', daliuren: '大六壬' };
|
|
14
|
+
|
|
15
|
+
const text = (v, fallback = '—') => {
|
|
16
|
+
if (v === undefined || v === null || v === '') return fallback;
|
|
17
|
+
return String(v);
|
|
18
|
+
};
|
|
19
|
+
const list = (v, fallback = '—') => (Array.isArray(v) ? v.filter((x) => x !== undefined && x !== null && x !== '').join('、') : '') || fallback;
|
|
20
|
+
const pairs = (rows) => rows.map(([label, value]) => ({ label: String(label), value: text(value) }));
|
|
21
|
+
const step = (key, field, rule, inputs, result, source) => ({
|
|
22
|
+
key,
|
|
23
|
+
field,
|
|
24
|
+
rule: text(rule, ''),
|
|
25
|
+
inputs: pairs(inputs),
|
|
26
|
+
result: text(result, ''),
|
|
27
|
+
source: text(source, ''),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function lineAt(lines, position) {
|
|
31
|
+
return (Array.isArray(lines) ? lines : []).find((l) => l.position === position) || null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function liuyaoTrace(r, opts = {}) {
|
|
35
|
+
const ben = r.ben && typeof r.ben === 'object' ? r.ben : {};
|
|
36
|
+
const lines = Array.isArray(ben.lines) ? ben.lines : [];
|
|
37
|
+
const bian = r.bian && typeof r.bian === 'object' ? r.bian : null;
|
|
38
|
+
const moving = Array.isArray(r.cast && r.cast.movingPositions) ? r.cast.movingPositions : [];
|
|
39
|
+
const ug = r.useGod && typeof r.useGod === 'object' ? r.useGod : null;
|
|
40
|
+
const direction = (ug && ug.direction) || opts.direction || 'general';
|
|
41
|
+
const us = r.useGodStrength && typeof r.useGodStrength === 'object' ? r.useGodStrength : null;
|
|
42
|
+
const hs = r.hexStrength && typeof r.hexStrength === 'object' ? r.hexStrength : null;
|
|
43
|
+
const fa = r.fushenAccess && typeof r.fushenAccess === 'object' ? r.fushenAccess : null;
|
|
44
|
+
const shi = lineAt(lines, ben.shi);
|
|
45
|
+
const ying = lineAt(lines, ben.ying);
|
|
46
|
+
const month = (us && us.month) || (hs && hs.month) || null;
|
|
47
|
+
const day = (us && us.day) || (hs && hs.day) || null;
|
|
48
|
+
|
|
49
|
+
const najia = step(
|
|
50
|
+
'najia',
|
|
51
|
+
'纳甲',
|
|
52
|
+
'京房纳甲:八经卦各配天干与三爻地支,内卦取前三爻、外卦取后三爻;动爻再成变卦。',
|
|
53
|
+
[
|
|
54
|
+
['本卦', `${text(ben.name)}(上${text(ben.upper)}·下${text(ben.lower)})`],
|
|
55
|
+
['动爻', moving.length ? `${moving.join('、')}爻` : '无(静卦)'],
|
|
56
|
+
['变卦', bian ? `${text(bian.name)}(上${text(bian.upper)}·下${text(bian.lower)})` : '无'],
|
|
57
|
+
],
|
|
58
|
+
lines.map((l) => `${l.position}爻 ${text(l.ganzhi)}${text(l.element)}`).join('|'),
|
|
59
|
+
'京房纳甲诀;engine/liuyao.js · NAJIA',
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const liuqin = step(
|
|
63
|
+
'liuqin',
|
|
64
|
+
'六亲',
|
|
65
|
+
'以卦宫五行为「我」:同我为兄弟、生我为父母、我生为子孙、克我为官鬼、我克为妻财。',
|
|
66
|
+
[
|
|
67
|
+
['卦宫', `${text(ben.palace)}(${text(ben.palaceElement)})`],
|
|
68
|
+
['爻五行', list([...new Set(lines.map((l) => l.element))])],
|
|
69
|
+
['日干起六神', `${text(r.dayGanZhi && r.dayGanZhi.stem)}日`],
|
|
70
|
+
],
|
|
71
|
+
lines.map((l) => `${l.position}爻 ${text(l.liuqin)}(${text(l.element)})`).join('|'),
|
|
72
|
+
'五行生克;engine/liuyao.js · liuqin()',
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const shiying = step(
|
|
76
|
+
'shiying',
|
|
77
|
+
'世应',
|
|
78
|
+
'八宫首卦世在上爻,一世至五世依次初至五爻,游魂四爻、归魂三爻;应爻与世相隔三位。',
|
|
79
|
+
[
|
|
80
|
+
['卦名', `${text(ben.name)}(${text(ben.palace)})`],
|
|
81
|
+
['世位', `${text(ben.shi)}爻`],
|
|
82
|
+
['应位', `${text(ben.ying)}爻`],
|
|
83
|
+
],
|
|
84
|
+
`${text(ben.shi)}爻${shi ? ` ${text(shi.liuqin)}·${text(shi.ganzhi)}${text(shi.element)}` : ''}为世,`
|
|
85
|
+
+ `${text(ben.ying)}爻${ying ? ` ${text(ying.liuqin)}·${text(ying.ganzhi)}${text(ying.element)}` : ''}为应`,
|
|
86
|
+
'八宫世应诀;engine/liuyao.js · SHI_POSITION',
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
let fushen;
|
|
90
|
+
if (!ug || !ug.liuqin) {
|
|
91
|
+
const why = direction === 'general'
|
|
92
|
+
? '未选询问方向(当前为综合),未取用神'
|
|
93
|
+
: '未取到用神';
|
|
94
|
+
fushen = step(
|
|
95
|
+
'fushen',
|
|
96
|
+
'伏神',
|
|
97
|
+
'用神不上卦时,回本宫首卦的同位取伏神;飞伏之间只判生克与助压。',
|
|
98
|
+
[['用神', ug && ug.ask ? ug.ask : '未取']],
|
|
99
|
+
`${why};本层不适用。`,
|
|
100
|
+
'engine/liuyao.js · yongshenOf()',
|
|
101
|
+
);
|
|
102
|
+
} else if (ug.missing) {
|
|
103
|
+
const hidden = (ug.fushen || []).map((f) => {
|
|
104
|
+
const fei = f.fei ? `${text(f.fei.ganzhi)}${text(f.fei.element)}(${text(f.fei.liuqin)})` : '—';
|
|
105
|
+
return `${f.position}爻 ${text(f.ganzhi)}${text(f.element)}(${text(f.liuqin)}),飞神 ${fei},${text(f.relation)}`;
|
|
106
|
+
}).join(';');
|
|
107
|
+
const access = fa && Array.isArray(fa.items)
|
|
108
|
+
? fa.items.map((i) => `${i.position}爻${text(i.verdict)}`).join('、')
|
|
109
|
+
: '';
|
|
110
|
+
fushen = step(
|
|
111
|
+
'fushen',
|
|
112
|
+
'伏神',
|
|
113
|
+
'用神不上卦时,回本宫首卦的同位取伏神;飞伏之间只判生克,再叠月建日辰给出伏条件,不换算应期。',
|
|
114
|
+
[
|
|
115
|
+
['用神', `${ug.liuqin}(不上卦)`],
|
|
116
|
+
['伏位', list((ug.fushen || []).map((f) => `${f.position}爻`))],
|
|
117
|
+
['月建 / 日辰', `${text(month && month.branch)} / ${text(day && day.branch)}`],
|
|
118
|
+
],
|
|
119
|
+
`${hidden || '本卦无此六亲,首卦同位也未取到伏神'}${access ? `;出伏:${access}` : ''}`,
|
|
120
|
+
'本宫首卦取伏;engine/liuyao.js · fushenAccess()',
|
|
121
|
+
);
|
|
122
|
+
} else {
|
|
123
|
+
fushen = step(
|
|
124
|
+
'fushen',
|
|
125
|
+
'伏神',
|
|
126
|
+
'用神已在卦上时不取伏神;伏神层只在本卦找不到用神时启用。',
|
|
127
|
+
[
|
|
128
|
+
['用神', ug.liuqin],
|
|
129
|
+
['在位', list((ug.found || []).map((l) => `${l.position}爻`))],
|
|
130
|
+
],
|
|
131
|
+
`用神 ${ug.liuqin} 已在 ${list((ug.found || []).map((l) => `${l.position}爻`))},无需伏神。`,
|
|
132
|
+
'engine/liuyao.js · yongshenOf()',
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const useStrength = us && Array.isArray(us.lines)
|
|
137
|
+
? us.lines.map((l) => `${l.position}爻${text(l.branch)}${text(l.element)}:月${text(l.monthState)}·${text(l.dayRelation)}`).join(';')
|
|
138
|
+
: '';
|
|
139
|
+
const wangsheng = step(
|
|
140
|
+
'wangsheng',
|
|
141
|
+
'旺衰',
|
|
142
|
+
'月建主这一段的旺衰(旺相休囚死),日辰看当天的生克扶压;只给状态标签,不折分数、不单独断吉凶。',
|
|
143
|
+
[
|
|
144
|
+
['月建', month ? `${text(month.branch)}(${text(month.element)})` : '缺'],
|
|
145
|
+
['日辰', day ? `${text(day.branch)}(${text(day.element)})` : '缺'],
|
|
146
|
+
['用神', ug && ug.liuqin ? ug.liuqin : '未取'],
|
|
147
|
+
['旬空', list(r.xunKong)],
|
|
148
|
+
],
|
|
149
|
+
[
|
|
150
|
+
useStrength ? `用神:${useStrength}${us.labels && us.labels.length ? `(${us.labels.join('、')})` : ''}` : '用神:未取,只看全卦',
|
|
151
|
+
hs && hs.labels && hs.labels.length ? `全卦:${hs.labels.join('、')}` : '',
|
|
152
|
+
].filter(Boolean).join(';'),
|
|
153
|
+
'月建主旺衰、日辰司生克;engine/liuyao.js · yongshenStrength / hexagramStrength',
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
return [najia, liuqin, shiying, fushen, wangsheng];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function baziTrace(r) {
|
|
160
|
+
const s = r.strength && typeof r.strength === 'object' ? r.strength : {};
|
|
161
|
+
const parts = s.parts && typeof s.parts === 'object' ? s.parts : {};
|
|
162
|
+
const season = parts.season && typeof parts.season === 'object' ? parts.season : {};
|
|
163
|
+
const frame = r.frame && typeof r.frame === 'object' ? r.frame : {};
|
|
164
|
+
const ys = frame.yongshen && typeof frame.yongshen === 'object' ? frame.yongshen : {};
|
|
165
|
+
const primary = frame.primary && typeof frame.primary === 'object' ? frame.primary : null;
|
|
166
|
+
const climate = r.climate && typeof r.climate === 'object' ? r.climate : {};
|
|
167
|
+
const godGroups = frame.godStats && frame.godStats.groups ? frame.godStats.groups : {};
|
|
168
|
+
|
|
169
|
+
const strength = step(
|
|
170
|
+
'strength',
|
|
171
|
+
'旺衰分值',
|
|
172
|
+
text(s.method, '月令权重 + 地支藏干通根 + 天干帮扶,量化后分档。'),
|
|
173
|
+
[
|
|
174
|
+
['日主', r.dayMaster ? `${text(r.dayMaster.stem)}(${text(r.dayMaster.element)})` : '—'],
|
|
175
|
+
['月令', `${text(season.branch)}(${text(season.element)}·${text(season.word)},权重 ${text(season.weight)})`],
|
|
176
|
+
['通根', `${list(parts.roots)}(${text(parts.rootScore)})`],
|
|
177
|
+
['合会折根', list(parts.structure, '无')],
|
|
178
|
+
['天干帮扶 / 耗泄', `帮 ${list(parts.helpers)};泄 ${list(parts.drainers)}(${text(parts.helpScore)})`],
|
|
179
|
+
['虚透', list(parts.virtualHelpers, '无')],
|
|
180
|
+
],
|
|
181
|
+
`${text(s.level)}(${text(s.score)} 分):${text(s.detail)}`,
|
|
182
|
+
'engine/bazi.js · 旺衰量化(月令权重 + 藏干通根,三会/三合/六合折根 + 天干虚透减半)',
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const primaryName = text(frame.primaryName || (primary && primary.name), '未取格局');
|
|
186
|
+
const extraGeju = list((frame.geju || []).map((g) => g && g.name).filter((name) => name && name !== primaryName), '');
|
|
187
|
+
const favor = list(ys.favor);
|
|
188
|
+
const avoid = list(ys.avoid);
|
|
189
|
+
const disputed = list((ys.disputed || []).map((d) => d && d.element), '');
|
|
190
|
+
const tiaohou = ys.tiaohou && typeof ys.tiaohou === 'object' ? ys.tiaohou : climate;
|
|
191
|
+
const need = tiaohou && tiaohou.need ? tiaohou.need : null;
|
|
192
|
+
const resultParts = [
|
|
193
|
+
primaryName === '未取格局' ? primaryName : `主格 ${primaryName}${extraGeju ? `;兼格 ${extraGeju}` : ''}`,
|
|
194
|
+
`喜 ${favor},忌 ${avoid}`,
|
|
195
|
+
disputed ? `有争议 ${disputed}` : '',
|
|
196
|
+
tiaohou && tiaohou.kind
|
|
197
|
+
? `调候 ${text(tiaohou.kind)}${need && need.element ? `,取 ${text(need.element)}` : ''}${tiaohou.avoidElement && tiaohou.avoidElement !== '—' ? `,忌 ${text(tiaohou.avoidElement)}` : ''}`
|
|
198
|
+
: '',
|
|
199
|
+
].filter(Boolean).join(';');
|
|
200
|
+
|
|
201
|
+
const geju = step(
|
|
202
|
+
'geju',
|
|
203
|
+
'格局取用',
|
|
204
|
+
text(ys.method, '先按月令与透干取格,再以扶抑为主、调候校验取用。'),
|
|
205
|
+
[
|
|
206
|
+
['月令格', primary ? `${text(primary.name)}(${text(primary.kind)})` : '—'],
|
|
207
|
+
['取格依据', primary ? text(primary.evidence) : '—'],
|
|
208
|
+
['十神分量', Object.entries(godGroups).map(([k, v]) => `${k}${v}`).join(' / ') || '—'],
|
|
209
|
+
['调候', tiaohou && tiaohou.kind ? `${text(tiaohou.kind)}${need && need.element ? ` → ${text(need.element)}` : ''}` : '—'],
|
|
210
|
+
],
|
|
211
|
+
`${resultParts}`,
|
|
212
|
+
'子平真诠 · 月令取格;engine/geju.js · yongshenOf()',
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const p = r.palaces && typeof r.palaces === 'object' ? r.palaces : {};
|
|
216
|
+
const monthBranch = r.pillars && r.pillars.month ? text(r.pillars.month.branch) : '—';
|
|
217
|
+
const hourBranch = r.pillars && r.pillars.hour ? text(r.pillars.hour.branch) : '—';
|
|
218
|
+
const palaces = p.taiyuan ? step(
|
|
219
|
+
'palaces',
|
|
220
|
+
'胎元与命身宫',
|
|
221
|
+
'胎元=月干进一、月支进三;胎息=日干五合、日支六合;命宫=27 减生月与生时支、取模后加二;身宫=11 加两支、取模后加二;干支并入六十甲子。',
|
|
222
|
+
[
|
|
223
|
+
['生月 / 生时', `${monthBranch} / ${hourBranch}`],
|
|
224
|
+
['胎元', `${text(p.taiyuan.ganzhi)}(月干进一、月支进三)`],
|
|
225
|
+
['胎息', p.taixi ? `${text(p.taixi.ganzhi)}(日干五合、日支六合)` : '—'],
|
|
226
|
+
['命宫 / 身宫', `${text(p.minggong && p.minggong.ganzhi)} / ${text(p.shengong && p.shengong.ganzhi)}`],
|
|
227
|
+
],
|
|
228
|
+
`胎元 ${text(p.taiyuan.ganzhi)};${p.taixi ? `胎息 ${text(p.taixi.ganzhi)};` : ''}命宫 ${text(p.minggong && p.minggong.ganzhi)};身宫 ${text(p.shengong && p.shengong.ganzhi)}。四宫是辅助坐标,不单独折吉凶。`,
|
|
229
|
+
'Tyme 四宫口径;engine/bazi.js · palaces',
|
|
230
|
+
) : null;
|
|
231
|
+
|
|
232
|
+
return [strength, geju, ...(palaces ? [palaces] : [])];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function ziweiTrace(r) {
|
|
236
|
+
const patterns = Array.isArray(r.patterns) ? r.patterns : [];
|
|
237
|
+
const total = Object.keys(PATTERN_TONE).length;
|
|
238
|
+
const soul = r.soul && typeof r.soul === 'object' ? r.soul : {};
|
|
239
|
+
const bureau = r.bureau && typeof r.bureau === 'object' ? r.bureau : {};
|
|
240
|
+
const hit = patterns.map((p) => `${text(p.name)}:${text(p.evidence)}`).join(';');
|
|
241
|
+
return [step(
|
|
242
|
+
'patterns',
|
|
243
|
+
'格局命中条件',
|
|
244
|
+
`已收录 ${total} 条格局,逐条校验命宫三方四正的星曜组合;只判结构成立与否,不折吉凶。`,
|
|
245
|
+
[
|
|
246
|
+
['命宫', text(soul.ganzhi)],
|
|
247
|
+
['五行局', text(bureau.name)],
|
|
248
|
+
['命主 / 身主', `${text(r.lifeMaster)} / ${text(r.bodyMaster)}`],
|
|
249
|
+
['命中数', `${patterns.length} / ${total}`],
|
|
250
|
+
],
|
|
251
|
+
patterns.length ? `命中 ${patterns.length} 条:${hit}` : '未命中已收录的格局条件(不表示命盘无结构,只是不在已收录清单内)。',
|
|
252
|
+
'紫微斗数全书 · 格局条件;engine/ziwei.js · detectPatterns()',
|
|
253
|
+
)];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function qimenTrace(r, opts = {}) {
|
|
257
|
+
const palaces = Array.isArray(r.palaces) ? r.palaces : [];
|
|
258
|
+
const month = r.month && typeof r.month === 'object' ? r.month : {};
|
|
259
|
+
const states = r.states && typeof r.states === 'object' ? r.states : {};
|
|
260
|
+
const cond = r.conditions && typeof r.conditions === 'object' ? r.conditions : {};
|
|
261
|
+
const zf = r.zhiFu && typeof r.zhiFu === 'object' ? r.zhiFu : {};
|
|
262
|
+
const zs = r.zhiShi && typeof r.zhiShi === 'object' ? r.zhiShi : {};
|
|
263
|
+
const ma = r.ma && typeof r.ma === 'object' ? r.ma : {};
|
|
264
|
+
const sz = r.siZhu && typeof r.siZhu === 'object' ? r.siZhu : {};
|
|
265
|
+
|
|
266
|
+
const facts = step(
|
|
267
|
+
'facts',
|
|
268
|
+
'盘面事实',
|
|
269
|
+
'时家转盘奇门:节气与三元定阴阳遁与局数,旬首定值符星与值使门;值符随时干落宫,八神按阴阳遁顺布或逆布。',
|
|
270
|
+
[
|
|
271
|
+
['四柱', `${text(sz.year)} ${text(sz.month)} ${text(sz.day)} ${text(sz.time)}`],
|
|
272
|
+
['节气 / 局', `${text(r.jieqi)} · ${text(r.dun)}${text(r.juNumber)}局(${text(r.juMethod)})`],
|
|
273
|
+
['旬首', text(r.xunshou)],
|
|
274
|
+
['值符 / 值使', `${text(zf.star)}落${text(zf.gong)}宫 / ${text(zs.gate)}落${text(zs.gong)}宫`],
|
|
275
|
+
['空亡 / 驿马', `${list(r.kongWang)} / ${text(ma.zhi)}${ma.gong ? `(${ma.gong}宫)` : ''}`],
|
|
276
|
+
],
|
|
277
|
+
palaces.map((p) => `${p.palace}宫 天${text(p.tianPan)}·${text(p.star)}·${text(p.gate)}·${text(p.god)}`).join('|') || '无九宫数据',
|
|
278
|
+
'engine/qimen.js · buildQimen()',
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
const ys = qimenYongshen(r, opts.direction);
|
|
282
|
+
const found = ys.rows.filter((x) => x.palace);
|
|
283
|
+
const missing = ys.rows.filter((x) => !x.palace).map((x) => x.key);
|
|
284
|
+
const primary = found[0] || null;
|
|
285
|
+
const yongshen = step(
|
|
286
|
+
'yongshen',
|
|
287
|
+
'用神落宫',
|
|
288
|
+
'按所问之事取用神:先取主用神、再取辅用神;以所落之宫的干、门、星、神整体取象,不单凭门名断事。',
|
|
289
|
+
[
|
|
290
|
+
['询问方向', ys.label],
|
|
291
|
+
['主用神', primary ? `${primary.key} → ${primary.palace.palace}宫` : '未上盘'],
|
|
292
|
+
['辅用神', found.slice(1).map((x) => `${x.key} → ${x.palace.palace}宫`).join(';') || '无'],
|
|
293
|
+
['主用神落宫', primary ? `${text(primary.palace.star)}·${text(primary.palace.gate)}·${text(primary.palace.god)}·天盘${text(primary.palace.tianPan)}` : '—'],
|
|
294
|
+
],
|
|
295
|
+
found.length
|
|
296
|
+
? `${ys.note};${found.map((x) => `${x.key} 落 ${x.palace.palace}宫(${text(x.palace.star)}·${text(x.palace.gate)}·${text(x.palace.god)})`).join(',')}`
|
|
297
|
+
+ (missing.length ? `;${missing.join('、')} 未上盘` : '')
|
|
298
|
+
: `${ys.label}的用神均未上盘,属未决项;先按值符落宫参照。`,
|
|
299
|
+
'奇门用神取象;engine/qimen-interpret.js · qimenYongshen()',
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
const order = ['旺', '相', '休', '囚', '死'];
|
|
303
|
+
const stateLine = (g) => order.filter((k) => g && Array.isArray(g[k]) && g[k].length)
|
|
304
|
+
.map((k) => `${k} ${g[k].join('、')}`).join(';') || '—';
|
|
305
|
+
const wangshuai = step(
|
|
306
|
+
'states',
|
|
307
|
+
'门/星/干旺衰',
|
|
308
|
+
'月令定五态:同月令之气为旺,月令所生为相,生月令为休,克月令为囚,月令所克为死;只判力量强弱,不合吉凶。',
|
|
309
|
+
[
|
|
310
|
+
['月令', `${text(month.branch)}(${text(month.element)})`],
|
|
311
|
+
['门', stateLine(states.gate)],
|
|
312
|
+
['星', stateLine(states.star)],
|
|
313
|
+
['天盘干', stateLine(states.stem)],
|
|
314
|
+
],
|
|
315
|
+
`门:${stateLine(states.gate)};星:${stateLine(states.star)};天盘干:${stateLine(states.stem)}`,
|
|
316
|
+
'月令五行五态;engine/qimen.js · groupByState()',
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
const forced = [];
|
|
320
|
+
const controlled = [];
|
|
321
|
+
const stemGroups = new Map();
|
|
322
|
+
for (const p of palaces) {
|
|
323
|
+
const rel = p.gateRelation || {};
|
|
324
|
+
if (rel.type === '门迫') forced.push(`${p.palace}宫${text(p.gate)}`);
|
|
325
|
+
else if (rel.type === '宫制门') controlled.push(`${p.palace}宫${text(p.gate)}`);
|
|
326
|
+
const sr = p.stemRelation || {};
|
|
327
|
+
if (p.tianPan && sr.type && sr.type !== 'unknown') {
|
|
328
|
+
if (!stemGroups.has(sr.type)) stemGroups.set(sr.type, []);
|
|
329
|
+
stemGroups.get(sr.type).push(`${p.palace}宫${p.tianPan}`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const stemOrder = ['干克宫', '宫克干', '干生宫', '宫生干', '比和'];
|
|
333
|
+
const stemLine = stemOrder.filter((k) => stemGroups.has(k))
|
|
334
|
+
.map((k) => `${k} ${stemGroups.get(k).join('、')}`).join(';') || '—';
|
|
335
|
+
const jiXing = (cond.jiXing || []).map((x) => `${x.palace}宫${text(x.stem)}`);
|
|
336
|
+
const ruMu = (cond.ruMu || []).map((x) => `${x.palace}宫${text(x.stem)}`);
|
|
337
|
+
const liuYiRuMu = (cond.liuYiRuMu || []).map((x) => `${x.palace}宫${text(x.stem)}`);
|
|
338
|
+
const ganying = palaces.filter((p) => p.ganYing)
|
|
339
|
+
.map((p) => `${p.palace}宫 ${text(p.ganYing.tian)}加${text(p.ganYing.di)} ${text(p.ganYing.name)}`).join(';');
|
|
340
|
+
const kongCells = palaces.filter((p) => p.kong).map((p) => `${p.palace}宫`);
|
|
341
|
+
|
|
342
|
+
const relations = step(
|
|
343
|
+
'relations',
|
|
344
|
+
'宫位生克',
|
|
345
|
+
'门与宫同宫论生克:门克宫为门迫,宫克门为宫制门;天盘干对宫另论生克;击刑、入墓、空亡只作宫位条件,不单独断吉凶。',
|
|
346
|
+
[
|
|
347
|
+
['门迫', forced.join('、') || '无'],
|
|
348
|
+
['宫制门', controlled.join('、') || '无'],
|
|
349
|
+
['天盘干 × 宫', stemLine],
|
|
350
|
+
['击刑 / 三奇入墓 / 六仪入墓', `${jiXing.join('、') || '无'} / ${ruMu.join('、') || '无'} / ${liuYiRuMu.join('、') || '无'}`],
|
|
351
|
+
['十干克应', ganying || '—'],
|
|
352
|
+
['空亡', kongCells.join('、') || '无'],
|
|
353
|
+
],
|
|
354
|
+
`门迫 ${forced.length} 处、宫制门 ${controlled.length} 处;天盘干与宫:${stemLine};击刑 ${jiXing.length} 处、三奇入墓 ${ruMu.length} 处、六仪入墓 ${liuYiRuMu.length} 处、落空 ${kongCells.length} 宫。十干克应:${ganying || '—'}。`,
|
|
355
|
+
'门迫/宫制门;engine/qimen.js · gatePalaceRelation() / stemPalaceRelation();十干克应 engine/qimen-ganying.js',
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
return [facts, yongshen, wangshuai, relations];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function daliurenTrace(r) {
|
|
362
|
+
const pan = Array.isArray(r.pan) ? r.pan : [];
|
|
363
|
+
const ke = Array.isArray(r.siKe) ? r.siKe : [];
|
|
364
|
+
const sc = r.sanChuan && typeof r.sanChuan === 'object' ? r.sanChuan : {};
|
|
365
|
+
const yj = r.yueJiang && typeof r.yueJiang === 'object' ? r.yueJiang : {};
|
|
366
|
+
const gr = r.guiren && typeof r.guiren === 'object' ? r.guiren : {};
|
|
367
|
+
const geju = r.geJu && typeof r.geJu === 'object' ? r.geJu : {};
|
|
368
|
+
const dayGz = text(r.dayGanZhi, '');
|
|
369
|
+
|
|
370
|
+
const tiandipan = step(
|
|
371
|
+
'tiandipan',
|
|
372
|
+
'天地盘',
|
|
373
|
+
'月将加时:中气换将,月将加于占时之上,顺布十二支成天盘;十二天将以日干昼夜贵人为起点,阳顺阴逆布于天盘。',
|
|
374
|
+
[
|
|
375
|
+
['日干支', dayGz],
|
|
376
|
+
['时支', `${text(r.hourZhi)}时`],
|
|
377
|
+
['月将', `${text(yj.zhi)}(${text(yj.name)})`],
|
|
378
|
+
['昼夜 / 贵人', `${text(r.dayNight)} / ${text(gr.zhi)}(${gr.reverse ? '逆布' : '顺布'})`],
|
|
379
|
+
],
|
|
380
|
+
pan.map((p) => `${p.di}→${p.tian}${p.jiang ? `(${text(p.jiang)})` : ''}`).join('|') || '无天地盘数据',
|
|
381
|
+
'大六壬月将加时;engine/daliuren.js · tianDiPan()',
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
const sike = step(
|
|
385
|
+
'sike',
|
|
386
|
+
'四课',
|
|
387
|
+
'四课:日干寄宫取第一课,日干上神再取第二课;日支取第三课,日支上神再取第四课;每课以上下五行论生克。',
|
|
388
|
+
[
|
|
389
|
+
['日干 / 日支', `${text(dayGz[0])} / ${text(dayGz[1])}`],
|
|
390
|
+
['日干寄宫', text(GAN_JI_GONG[dayGz[0]])],
|
|
391
|
+
['四课', ke.map((k) => `${k.position}课 ${text(k.shang)}上${text(k.xia)}下`).join(';') || '—'],
|
|
392
|
+
],
|
|
393
|
+
ke.map((k) => `${k.position}课 ${text(k.shang)}上${text(k.xia)}下${k.jiang ? `·${text(k.jiang)}` : ''}:${text(k.relation)}`).join(';') || '无四课数据',
|
|
394
|
+
'engine/daliuren.js · siKe()',
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
const chuanLine = (c) => (c
|
|
398
|
+
? `${text(c.position)}${text(c.zhi)}(${text(c.liuQin)}${c.xunKong ? '·旬空' : ''},${text(c.jiang)}${c.jiangFull ? `·${text(c.jiangFull)}` : ''})`
|
|
399
|
+
: '—');
|
|
400
|
+
const sanchuan = step(
|
|
401
|
+
'sanchuan',
|
|
402
|
+
'三传',
|
|
403
|
+
'三传:先取贼克(下贼上优先),无则比用、涉害、遥克、昴星,再八专、伏吟、返吟;初传既定,中末以天盘依次递取。',
|
|
404
|
+
[
|
|
405
|
+
['课体', `${text(geju.name)}(${text(geju.detail)})`],
|
|
406
|
+
['初传', chuanLine(sc.chu)],
|
|
407
|
+
['中传', chuanLine(sc.zhong)],
|
|
408
|
+
['末传', chuanLine(sc.mo)],
|
|
409
|
+
],
|
|
410
|
+
`${chuanLine(sc.chu)} → ${chuanLine(sc.zhong)} → ${chuanLine(sc.mo)}`,
|
|
411
|
+
'engine/daliuren.js · chuan()',
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
return [tiandipan, sike, sanchuan];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* @param {object} result compute 的结果
|
|
420
|
+
* @param {{direction?:string, gender?:string, refresh?:boolean}} [opts]
|
|
421
|
+
* refresh=true 时按当前询问方向重算六爻的用神 / 旺衰 / 伏神层(只重建 trace,不改盘面)
|
|
422
|
+
* @returns {Array<{key:string, field:string, rule:string, inputs:Array<{label:string,value:string}>, result:string, source:string}>|null}
|
|
423
|
+
*/
|
|
424
|
+
export function buildTrace(result, opts = {}) {
|
|
425
|
+
if (!result || typeof result !== 'object') return null;
|
|
426
|
+
let layers = null;
|
|
427
|
+
if (result.system === 'liuyao') {
|
|
428
|
+
let view = result;
|
|
429
|
+
// 面板改了「询问方向」但不想重摇一卦:只按新方向重算用神相关三层
|
|
430
|
+
if (opts.refresh === true) {
|
|
431
|
+
try {
|
|
432
|
+
const ug = yongshenOf(result, { direction: opts.direction, gender: opts.gender });
|
|
433
|
+
const monthBranch = (result.hexStrength && result.hexStrength.month && result.hexStrength.month.branch)
|
|
434
|
+
|| (result.useGodStrength && result.useGodStrength.month && result.useGodStrength.month.branch)
|
|
435
|
+
|| null;
|
|
436
|
+
const dayBranch = result.dayGanZhi ? result.dayGanZhi.branch : null;
|
|
437
|
+
if (ug.liuqin) {
|
|
438
|
+
const us = yongshenStrength(result, ug, { monthBranch, dayBranch });
|
|
439
|
+
const fa = fushenAccess(result, ug, { monthBranch, dayBranch });
|
|
440
|
+
view = { ...result, useGod: ug, useGodStrength: us || undefined, fushenAccess: fa || undefined };
|
|
441
|
+
} else {
|
|
442
|
+
view = { ...result, useGod: undefined, useGodStrength: undefined, fushenAccess: undefined };
|
|
443
|
+
}
|
|
444
|
+
} catch (e) {
|
|
445
|
+
view = result;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
layers = liuyaoTrace(view, opts);
|
|
449
|
+
} else if (result.system === 'bazi') layers = baziTrace(result);
|
|
450
|
+
else if (result.system === 'ziwei') layers = ziweiTrace(result);
|
|
451
|
+
else if (result.system === 'qimen') layers = qimenTrace(result, opts);
|
|
452
|
+
else if (result.system === 'daliuren') layers = daliurenTrace(result);
|
|
453
|
+
return layers && layers.length ? layers : null;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export { SYSTEM_LABEL };
|
package/engine/ziwei.js
CHANGED
|
@@ -89,6 +89,7 @@ export const ZIWEI_SCHOOL_DEFAULTS = Object.freeze({
|
|
|
89
89
|
tianshiTianshang: 'normal',
|
|
90
90
|
changshengSchool: 'yin-yang-shun-ni',
|
|
91
91
|
lateZishi: 'current-day',
|
|
92
|
+
shenzhuSchool: 'common',
|
|
92
93
|
});
|
|
93
94
|
|
|
94
95
|
export const ZIWEI_SCHOOL_OPTIONS = Object.freeze({
|
|
@@ -101,6 +102,7 @@ export const ZIWEI_SCHOOL_OPTIONS = Object.freeze({
|
|
|
101
102
|
tianshiTianshang: ['normal', 'zhongzhou'],
|
|
102
103
|
changshengSchool: ['yin-yang-shun-ni', 'shui-tu', 'huo-tu'],
|
|
103
104
|
lateZishi: ['current-day', 'next-day', 'all-current', 'day-cur-time-next'],
|
|
105
|
+
shenzhuSchool: ['common', 'verse'],
|
|
104
106
|
});
|
|
105
107
|
|
|
106
108
|
export function ziweiSchoolsOf(input = {}) {
|
|
@@ -257,10 +259,15 @@ export const MING_ZHU = {
|
|
|
257
259
|
午: '破军', 未: '武曲', 申: '廉贞', 酉: '文曲', 戌: '禄存', 亥: '巨门',
|
|
258
260
|
};
|
|
259
261
|
|
|
260
|
-
|
|
262
|
+
// 身主:按生年地支。子/午两派并存——
|
|
263
|
+
// · common(默认,通行表 / 多数排盘软件):子午皆火星;
|
|
264
|
+
// · verse(安身主诀「子午安身铃火宿」逐字配对):子铃星、午火星。
|
|
265
|
+
// 此诀见于通行安星诀;维基文库本《紫微斗数全书》卷一、卷三未见,不标作《全书》原文。
|
|
266
|
+
// 其余十支两派一致。用 shenzhuSchool 切换。
|
|
267
|
+
const SHEN_ZHU_TAIL = { 丑: '天相', 寅: '天梁', 卯: '天同', 辰: '文昌', 巳: '天机', 未: '天相', 申: '天梁', 酉: '天同', 戌: '文昌', 亥: '天机' };
|
|
261
268
|
export const SHEN_ZHU = {
|
|
262
|
-
|
|
263
|
-
|
|
269
|
+
common: { 子: '火星', 午: '火星', ...SHEN_ZHU_TAIL },
|
|
270
|
+
verse: { 子: '铃星', 午: '火星', ...SHEN_ZHU_TAIL },
|
|
264
271
|
};
|
|
265
272
|
|
|
266
273
|
// 三合局(寅午戌 / 申子辰 / 巳酉丑 / 亥卯未)
|
|
@@ -717,7 +724,13 @@ export function buildZiwei(input) {
|
|
|
717
724
|
},
|
|
718
725
|
body: { palace: '身宫', branch: BRANCHES[bodyIndex], lands: palaceNames[bodyIndex] },
|
|
719
726
|
lifeMaster: MING_ZHU[BRANCHES[soulIndex]],
|
|
720
|
-
bodyMaster: SHEN_ZHU[BRANCHES[yb]],
|
|
727
|
+
bodyMaster: SHEN_ZHU[schools.shenzhuSchool][BRANCHES[yb]],
|
|
728
|
+
bodyMasterSchool: schools.shenzhuSchool,
|
|
729
|
+
...((yb === 0 || yb === 6) ? {
|
|
730
|
+
bodyMasterNote: schools.shenzhuSchool === 'common'
|
|
731
|
+
? '子午皆火星(通行表);另有安身主诀「子午安身铃火宿」逐字取子铃星、午火星一派'
|
|
732
|
+
: '安身主诀「子午安身铃火宿」逐字:子铃星、午火星;另有子午皆火星的通行表',
|
|
733
|
+
} : {}),
|
|
721
734
|
doujun: {
|
|
722
735
|
zinian: BRANCHES[fix(hb - (lunarMonth - 1))],
|
|
723
736
|
rule: '流年支起正月,逆数至生月,再起子时顺数至生时',
|
|
@@ -741,7 +754,7 @@ export function buildZiwei(input) {
|
|
|
741
754
|
rules: {
|
|
742
755
|
ziweiPlacement: '借数法:局数除日数取商,商数自寅宫顺行,借数奇逆偶顺',
|
|
743
756
|
mutagen: '生年四化用中州派常用表;庚干可按流派切换(默认阳武阴同,另有同科阴忌、府科、府科相忌、同科相忌)',
|
|
744
|
-
schools: `流派开关:亮度 ${schools.brightnessSchool}、庚干四化 ${schools.gengYearSihua}、天马 ${schools.tianmaSchool}、天空 ${schools.tiankongSchool}、截空 ${schools.jiekongSchool}、魁钺 ${schools.kuiyueSchool}、天伤天使 ${schools.tianshiTianshang}、长生 ${schools.changshengSchool}、晚子时 ${schools.lateZishi}
|
|
757
|
+
schools: `流派开关:亮度 ${schools.brightnessSchool}、庚干四化 ${schools.gengYearSihua}、天马 ${schools.tianmaSchool}、天空 ${schools.tiankongSchool}、截空 ${schools.jiekongSchool}、魁钺 ${schools.kuiyueSchool}、天伤天使 ${schools.tianshiTianshang}、长生 ${schools.changshengSchool}、晚子时 ${schools.lateZishi}、身主 ${schools.shenzhuSchool}(common 子午皆火星 / verse 子铃午火);庚干四化只作用于生年四化`,
|
|
745
758
|
leapMonth: '闰月默认按日切分(1–15 归本月、16 起归次月,主流排盘口径);可传 leapMonth: next(整月归次月)或 prev(整月归本月),leapAsNext: true 等同 next',
|
|
746
759
|
auxStars: '火铃按年支三合起点顺数至生时;羊陀夹禄存;魁钺按年干;地空亥起子时逆行、地劫顺行;三台八座随辅弼;恩光天贵随昌曲退一位;台辅封诰按时支',
|
|
747
760
|
shensha: '长生、博士随大限顺逆;将前、岁前恒顺行;天伤恒在交友、天使恒在疾厄',
|
|
@@ -765,7 +778,10 @@ export function buildZiwei(input) {
|
|
|
765
778
|
good: chart.patterns.filter((p) => p.tone === 'good').map((p) => p.name),
|
|
766
779
|
neutral: chart.patterns.filter((p) => p.tone === 'neutral').map((p) => p.name),
|
|
767
780
|
bad: chart.patterns.filter((p) => p.tone === 'bad').map((p) => p.name),
|
|
768
|
-
|
|
781
|
+
broken: chart.patterns.filter((p) => p.status === 'broken').map((p) => p.name),
|
|
782
|
+
formed: chart.patterns.filter((p) => p.status === 'formed').map((p) => p.name),
|
|
783
|
+
notGraded: chart.patterns.filter((p) => p.status === 'n/a').map((p) => p.name),
|
|
784
|
+
note: '格局只描述结构,不作吉凶断语;同一命盘可并存吉格、中性结构与忌格。破格只判吉格是否被三方四正的煞忌空劫冲破,忌格不另判破格',
|
|
769
785
|
};
|
|
770
786
|
return chart;
|
|
771
787
|
}
|
|
@@ -908,13 +924,106 @@ export function detectPatterns(chart) {
|
|
|
908
924
|
}
|
|
909
925
|
if (soulIdx === 0 && inSoul('贪狼')) add('泛水桃花', '贪狼在子守命');
|
|
910
926
|
|
|
911
|
-
// 同名的结构只保留第一条(evidence
|
|
927
|
+
// 同名的结构只保留第一条(evidence 已足够说明),并标注倾向与破格状态
|
|
912
928
|
const seen = new Set();
|
|
929
|
+
const nearMeta = new Map();
|
|
930
|
+
for (const b of sanfang) {
|
|
931
|
+
for (const s of (palaceAt(chart, b)?.stars ?? [])) {
|
|
932
|
+
if (!nearMeta.has(s.name)) nearMeta.set(s.name, { branch: BRANCHES[b], mutagen: s.mutagen || null });
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
const nearNames = [...nearMeta.keys()];
|
|
936
|
+
const hasAny = (list) => list.filter((n) => nearMeta.has(n));
|
|
937
|
+
const withBranch = (names) => names.map((n) => `${n}(${nearMeta.get(n).branch})`).join('、');
|
|
938
|
+
const jiNames = nearNames.filter((n) => nearMeta.get(n).mutagen === '忌');
|
|
939
|
+
const breakOf = (name) => {
|
|
940
|
+
const rule = PATTERN_BREAK_RULES[name];
|
|
941
|
+
if (!rule) return { status: 'n/a', breaks: [], breakRule: '未收录破格条件', citationIds: [] };
|
|
942
|
+
if (rule.kind) return { status: 'n/a', breaks: [], breakRule: rule.note, citationIds: [] };
|
|
943
|
+
const hits = [];
|
|
944
|
+
for (const token of rule.breakers || []) {
|
|
945
|
+
if (token === 'sha') {
|
|
946
|
+
const names = hasAny(BREAK_SHA).filter((n) => !(rule.exclude || []).includes(n));
|
|
947
|
+
if (names.length) hits.push(`三方见煞星 ${withBranch(names)}`);
|
|
948
|
+
} else if (token === 'kong') {
|
|
949
|
+
const names = hasAny(BREAK_KONG);
|
|
950
|
+
if (names.length) hits.push(`三方见空劫 ${withBranch(names)}`);
|
|
951
|
+
} else if (token === 'ji') {
|
|
952
|
+
if (jiNames.length) hits.push(`三方见化忌 ${withBranch(jiNames)}`);
|
|
953
|
+
} else if (token === 'yangTuo') {
|
|
954
|
+
const names = hasAny(['擎羊', '陀罗']);
|
|
955
|
+
if (names.length) hits.push(`羊陀冲守 ${withBranch(names)}`);
|
|
956
|
+
} else if (token === 'tuo') {
|
|
957
|
+
if (nearMeta.has('陀罗')) hits.push(`陀罗同会(${nearMeta.get('陀罗').branch})`);
|
|
958
|
+
} else if (token === 'noKelu') {
|
|
959
|
+
const hasKe = nearNames.some((n) => nearMeta.get(n).mutagen === '科');
|
|
960
|
+
const hasLu = nearNames.some((n) => nearMeta.get(n).mutagen === '禄') || nearMeta.has('禄存');
|
|
961
|
+
if (!hasKe && !hasLu) hits.push('三方无化科、化禄或禄存照');
|
|
962
|
+
} else if (token.startsWith('starJi:')) {
|
|
963
|
+
const star = token.slice(7);
|
|
964
|
+
const meta = nearMeta.get(star);
|
|
965
|
+
if (meta?.mutagen === '忌') hits.push(`${star}化忌(${meta.branch})`);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
return {
|
|
969
|
+
status: hits.length ? 'broken' : 'formed',
|
|
970
|
+
breaks: hits,
|
|
971
|
+
breakRule: rule.rule || '',
|
|
972
|
+
citationIds: rule.citationIds || [],
|
|
973
|
+
};
|
|
974
|
+
};
|
|
913
975
|
return out
|
|
914
976
|
.filter((p) => (seen.has(p.name) ? false : (seen.add(p.name), true)))
|
|
915
|
-
.map((p) => ({ ...p, tone: PATTERN_TONE[p.name] || 'neutral' }));
|
|
977
|
+
.map((p) => ({ ...p, tone: PATTERN_TONE[p.name] || 'neutral', ...breakOf(p.name) }));
|
|
916
978
|
}
|
|
917
979
|
|
|
980
|
+
const BREAK_SHA = ['擎羊', '陀罗', '火星', '铃星'];
|
|
981
|
+
const BREAK_KONG = ['地空', '地劫'];
|
|
982
|
+
const GENERIC_BREAK = '命宫三方四正见煞星(擎羊、陀罗、火星、铃星)、地空地劫或化忌,吉格减色乃至不成格。';
|
|
983
|
+
const STRUCTURAL_NOTE = '这是结构标签,不是吉格,不判成格/破格。';
|
|
984
|
+
const INAUSPICIOUS_NOTE = '忌格本身就是风险结构,不再判「破格」;轻重与应期另看大限流年。';
|
|
985
|
+
|
|
986
|
+
// 34 条格局的破格条件。breakers 是可机械复算的星位/四化判据:
|
|
987
|
+
// sha 三方煞星 / kong 三方空劫 / ji 三方化忌 / yangTuo 羊陀 / tuo 陀罗 /
|
|
988
|
+
// noKelu 三方无科禄 / starJi:<星> 指定星化忌。
|
|
989
|
+
// 引文见 engine/citations.js,原文子串由 test/citations.test.mjs 核验。
|
|
990
|
+
export const PATTERN_BREAK_RULES = {
|
|
991
|
+
紫府同宫: { breakers: ['kong', 'starJi:紫微', 'starJi:天府'], rule: GENERIC_BREAK, citationIds: ['zw-poge-sanfang', 'zw-poge-ruge'] },
|
|
992
|
+
紫府朝垣: { breakers: ['sha', 'kong', 'ji'], rule: GENERIC_BREAK, citationIds: ['zw-poge-sanfang', 'zw-poge-ruge'] },
|
|
993
|
+
君臣庆会: { breakers: ['sha', 'kong', 'ji'], rule: GENERIC_BREAK, citationIds: ['zw-poge-sanfang', 'zw-poge-ruge'] },
|
|
994
|
+
极向离明: { breakers: ['sha', 'kong', 'ji'], rule: GENERIC_BREAK, citationIds: ['zw-poge-sanfang', 'zw-poge-ruge'] },
|
|
995
|
+
七杀朝斗: { breakers: ['kong', 'starJi:七杀'], rule: '七杀在子午守命而见空劫或七杀化忌,杀曜之威不聚。', citationIds: ['zw-poge-ruge'] },
|
|
996
|
+
英星入庙: { breakers: ['kong', 'starJi:破军'], rule: '破军在子午守命而见空劫或破军化忌,英星入庙减色。', citationIds: ['zw-poge-ruge'] },
|
|
997
|
+
石中隐玉: { breakers: ['noKelu', 'kong', 'starJi:巨门'], rule: '三方无化科、化禄或禄存照,或见空劫、巨门化忌,则石中隐玉不成立。', citationIds: ['zw-shiyin', 'zw-poge-ruge'] },
|
|
998
|
+
巨日同宫: { breakers: ['sha', 'kong', 'ji'], rule: '巨日同宫而三方见擎羊等煞星、空劫或化忌,光明被掩。', citationIds: ['zw-poge-sanfang', 'zw-jiju-poge'] },
|
|
999
|
+
日月夹命: { breakers: ['yangTuo', 'starJi:太阳', 'starJi:太阴'], rule: '羊陀冲守,或日月任一带化忌,夹局减色。', citationIds: ['zw-riyue-jia'] },
|
|
1000
|
+
日月对照: { breakers: ['sha', 'kong', 'starJi:太阳', 'starJi:太阴'], rule: '日月对照见煞空,或日月任一带化忌,对照不美。', citationIds: ['zw-riyue-jia', 'zw-poge-sanfang'] },
|
|
1001
|
+
左右夹命: { breakers: ['kong', 'ji'], rule: '命宫三方见空劫或化忌,辅弼之夹被冲。', citationIds: ['zw-poge-sanfang'] },
|
|
1002
|
+
昌曲夹命: { breakers: ['sha', 'kong'], rule: '三方见羊陀火铃空劫,昌曲夹命亦主虚誉。', citationIds: ['zw-changqu'] },
|
|
1003
|
+
魁钺夹命: { breakers: ['sha', 'kong'], rule: '魁钺夹命而三方杀凑,贵气减等。', citationIds: ['zw-kuiyue'] },
|
|
1004
|
+
三奇嘉会: { breakers: ['sha', 'ji'], rule: '三奇同会而兼四杀或化忌,发财功名亦多阻滞。', citationIds: ['zw-sihua-ji'] },
|
|
1005
|
+
双禄朝垣: { breakers: ['kong', 'ji'], rule: '双禄朝垣见空劫或化忌,禄被劫夺。', citationIds: ['zw-poge-sanfang'] },
|
|
1006
|
+
府相朝垣: { breakers: ['sha', 'kong', 'ji'], rule: GENERIC_BREAK, citationIds: ['zw-poge-sanfang', 'zw-poge-ruge'] },
|
|
1007
|
+
禄马交驰: { breakers: ['kong', 'sha'], rule: '禄马逢空为死马、遇陀罗为折足马,见刑杀亦减力。', citationIds: ['zw-luma'] },
|
|
1008
|
+
月朗天门: { breakers: ['kong', 'starJi:太阴'], rule: '太阴在亥守命而见空劫或太阴化忌,月被云遮。', citationIds: ['zw-poge-ruge'] },
|
|
1009
|
+
日出扶桑: { breakers: ['kong', 'starJi:太阳'], rule: '太阳在卯守命而见空劫或太阳化忌,日出扶桑减色。', citationIds: ['zw-poge-ruge'] },
|
|
1010
|
+
机月同梁: { breakers: ['sha', 'kong', 'ji'], rule: '机月同梁遇凶杀、空劫或化忌,则降为下格。', citationIds: ['zw-jiyue'] },
|
|
1011
|
+
武贪同行: { breakers: ['starJi:武曲', 'starJi:贪狼'], rule: '武贪同行须无化忌;任一颗化忌则作下格论。', citationIds: ['zw-tanwu'] },
|
|
1012
|
+
双禄交流: { breakers: ['kong', 'ji'], rule: '双禄交流见空劫或化忌,禄来难守。', citationIds: ['zw-poge-sanfang'] },
|
|
1013
|
+
火贪铃贪: { breakers: ['sha', 'kong', 'starJi:贪狼'], exclude: ['火星', '铃星'], rule: '三方有凶杀或空劫,火贪铃贪不发;贪狼化忌亦减力。', citationIds: ['zw-huotan'] },
|
|
1014
|
+
命无正曜: { kind: 'structural', note: STRUCTURAL_NOTE },
|
|
1015
|
+
杀破狼: { kind: 'structural', note: STRUCTURAL_NOTE },
|
|
1016
|
+
火铃夹命: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1017
|
+
羊陀夹命: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1018
|
+
羊陀夹忌: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1019
|
+
铃昌陀武: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1020
|
+
命里逢空: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1021
|
+
马头带箭: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1022
|
+
天罗地网: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1023
|
+
刑囚夹印: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1024
|
+
泛水桃花: { kind: 'inauspicious', note: INAUSPICIOUS_NOTE },
|
|
1025
|
+
};
|
|
1026
|
+
|
|
918
1027
|
export const PATTERN_TONE = {
|
|
919
1028
|
紫府同宫: 'good', 紫府朝垣: 'good', 君臣庆会: 'good', 极向离明: 'good',
|
|
920
1029
|
七杀朝斗: 'good', 英星入庙: 'good', 石中隐玉: 'good', 巨日同宫: 'good',
|