divicast 0.1.1__py3-none-any.whl
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.
- divicast/__init__.py +8 -0
- divicast/base/__init__.py +0 -0
- divicast/base/symbol.py +113 -0
- divicast/entities/daemon.py +21 -0
- divicast/entities/dizhi.py +78 -0
- divicast/entities/liushen.py +14 -0
- divicast/entities/relative.py +14 -0
- divicast/entities/tiangan.py +104 -0
- divicast/entities/trigram.py +193 -0
- divicast/entities/wuxing.py +56 -0
- divicast/hex.json +836 -0
- divicast/sixline/__init__.py +10 -0
- divicast/sixline/divinatory_symbol.py +663 -0
- divicast/sixline/output.py +329 -0
- divicast/sixline/schema.json +298 -0
- divicast-0.1.1.dist-info/METADATA +76 -0
- divicast-0.1.1.dist-info/RECORD +18 -0
- divicast-0.1.1.dist-info/WHEEL +4 -0
divicast/__init__.py
ADDED
|
File without changes
|
divicast/base/symbol.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Any, Iterator, List, Self, Type, TypeVar
|
|
3
|
+
|
|
4
|
+
T = TypeVar("T", bound="ValuedMultiton")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ValuedMultiton(Enum):
|
|
8
|
+
"""
|
|
9
|
+
一个功能丰富的枚举基类,旨在通过继承来使用。
|
|
10
|
+
|
|
11
|
+
它提供了多种方式来定义和访问枚举成员,每个成员都包含一个整数值和一个中文描述。
|
|
12
|
+
|
|
13
|
+
特性:
|
|
14
|
+
- 通过 `(整数, "中文名")` 的元组形式来定义成员。
|
|
15
|
+
- 实例可以通过名称、整数值或中文名进行检索。
|
|
16
|
+
- 提供了清晰的 `__str__` 和 `__repr__` 表示。
|
|
17
|
+
- 支持迭代、比较,并提供了 `next()` 方法用于循环遍历。
|
|
18
|
+
- 提供了 `all()` 和 `iterator_from()` 等便利的类方法。
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, num: int, chinese_name: str | None = None):
|
|
23
|
+
if not isinstance(num, int) or not isinstance(chinese_name, str):
|
|
24
|
+
raise TypeError(
|
|
25
|
+
"Enum members must be defined as a tuple of (int, str).")
|
|
26
|
+
self.num = num
|
|
27
|
+
self.chinese_name = chinese_name
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def _missing_(cls: Type[T], value: Any) -> T | None:
|
|
31
|
+
"""
|
|
32
|
+
实现通过整数值查找实例,例如 `Color(1)`。
|
|
33
|
+
"""
|
|
34
|
+
if isinstance(value, int):
|
|
35
|
+
for member in cls:
|
|
36
|
+
if member.num == value:
|
|
37
|
+
return member
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def from_chinese_name(cls: Type[T], chinese_name: str) -> T:
|
|
42
|
+
"""通过中文名查找枚举成员。"""
|
|
43
|
+
for member in cls:
|
|
44
|
+
if member.chinese_name == chinese_name:
|
|
45
|
+
return member
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"'{chinese_name}' is not a valid chinese_name for {cls.__name__}"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def all(cls: Type[T]) -> List[T]:
|
|
52
|
+
"""以列表形式返回所有枚举成员,按定义顺序排列。"""
|
|
53
|
+
return list(cls)
|
|
54
|
+
|
|
55
|
+
def next(self, step: int = 1) -> Self:
|
|
56
|
+
"""返回后`step`个枚举成员。如果是最后一个,则循环回到第一个。"""
|
|
57
|
+
members = self.all()
|
|
58
|
+
index = members.index(self)
|
|
59
|
+
return members[(index + step) % len(members)]
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def iterator_from(cls: Type[T], start_member: T) -> Iterator[T]:
|
|
63
|
+
"""创建一个从指定成员开始并循环一次的迭代器。"""
|
|
64
|
+
if not isinstance(start_member, cls):
|
|
65
|
+
raise TypeError(
|
|
66
|
+
f"start_member must be an instance of {cls.__name__}")
|
|
67
|
+
|
|
68
|
+
current = start_member
|
|
69
|
+
while True:
|
|
70
|
+
yield current
|
|
71
|
+
current = current.next()
|
|
72
|
+
if current == start_member:
|
|
73
|
+
break
|
|
74
|
+
|
|
75
|
+
def __str__(self) -> str:
|
|
76
|
+
"""返回用户的友好字符串表示(中文名)。"""
|
|
77
|
+
return self.chinese_name
|
|
78
|
+
|
|
79
|
+
def __repr__(self) -> str:
|
|
80
|
+
"""返回开发者的清晰、无歧义的表示。"""
|
|
81
|
+
return f"<{self.__class__.__name__}.{self.name}: {self.num} ('{self.chinese_name}')>"
|
|
82
|
+
|
|
83
|
+
def __eq__(self, other: Any) -> bool:
|
|
84
|
+
"""
|
|
85
|
+
允许枚举成员与整数值进行比较。
|
|
86
|
+
例如 `Color.RED == 1`。
|
|
87
|
+
"""
|
|
88
|
+
if isinstance(other, int):
|
|
89
|
+
return self.num == other
|
|
90
|
+
# 对于其他类型,使用 `enum.Enum` 的默认比较逻辑
|
|
91
|
+
return super().__eq__(other)
|
|
92
|
+
|
|
93
|
+
def __hash__(self) -> int:
|
|
94
|
+
"""确保枚举成员是可哈希的,以便在字典键或集合中使用。"""
|
|
95
|
+
return hash(self.num)
|
|
96
|
+
|
|
97
|
+
# --- 序列化 ---
|
|
98
|
+
|
|
99
|
+
def to_dict(self) -> str:
|
|
100
|
+
"""
|
|
101
|
+
返回一个简单的、可序列化的表示(成员名称)。
|
|
102
|
+
"""
|
|
103
|
+
return self.name
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class BelongsTo:
|
|
107
|
+
"""
|
|
108
|
+
继承此类以创建一个属于另一个类的类。
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def belongs_to(self, _: type[T], map_name: str) -> T:
|
|
112
|
+
a = getattr(self, map_name)[self]
|
|
113
|
+
return a
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from divicast.base.symbol import ValuedMultiton
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Daemon(ValuedMultiton):
|
|
5
|
+
"""
|
|
6
|
+
神煞
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
Tianyiguiren = (0, "天乙贵人")
|
|
10
|
+
Yima = (1, "驿马")
|
|
11
|
+
Taohua = (2, "桃花")
|
|
12
|
+
Wenchang = (3, "文昌")
|
|
13
|
+
Lushen = (4, "禄神")
|
|
14
|
+
Jiesha = (5, "劫煞")
|
|
15
|
+
Huagai = (6, "华盖")
|
|
16
|
+
Jiangxing = (7, "将星")
|
|
17
|
+
Tianxi = (8, "天喜")
|
|
18
|
+
Tianyi = (9, "天医")
|
|
19
|
+
Yangren = (10, "阳刃")
|
|
20
|
+
Zaisha = (11, "灾煞")
|
|
21
|
+
Mouxing = (12, "谋星")
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations # 用于前向引用
|
|
2
|
+
|
|
3
|
+
from typing import ClassVar, Dict, List
|
|
4
|
+
|
|
5
|
+
from divicast.base.symbol import ValuedMultiton
|
|
6
|
+
from divicast.entities.wuxing import *
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Dizhi(BelongsToYinYang, BelongsToWuxing, ValuedMultiton):
|
|
10
|
+
"""
|
|
11
|
+
地支
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
_WUXING_MAP: Dict['Dizhi', 'Wuxing']
|
|
15
|
+
|
|
16
|
+
Zi = (0, "子")
|
|
17
|
+
Chou = (1, "丑")
|
|
18
|
+
Yin = (2, "寅")
|
|
19
|
+
Mou = (3, "卯")
|
|
20
|
+
Chen = (4, "辰")
|
|
21
|
+
Si = (5, "巳")
|
|
22
|
+
Wu = (6, "午")
|
|
23
|
+
Wei = (7, "未")
|
|
24
|
+
Shen = (8, "申")
|
|
25
|
+
You = (9, "酉")
|
|
26
|
+
Xu = (10, "戌")
|
|
27
|
+
Hai = (11, "亥")
|
|
28
|
+
|
|
29
|
+
def is_chong(self, d: Dizhi) -> bool:
|
|
30
|
+
"""判断地支相冲"""
|
|
31
|
+
return abs(self.num - d.num) == 6
|
|
32
|
+
|
|
33
|
+
def chong(self) -> Dizhi:
|
|
34
|
+
"""返回相冲的地支"""
|
|
35
|
+
return Dizhi((self.num + 6) % 12)
|
|
36
|
+
|
|
37
|
+
def is_he(self, d: Dizhi) -> bool:
|
|
38
|
+
"""判断地支相合"""
|
|
39
|
+
return (self.num + d.num) % 12 == 1
|
|
40
|
+
|
|
41
|
+
def he(self) -> Dizhi:
|
|
42
|
+
"""返回相合的地支"""
|
|
43
|
+
return Dizhi((13 - self.num) % 12)
|
|
44
|
+
|
|
45
|
+
def belongs_to_yinyang(self) -> YinYang:
|
|
46
|
+
return YinYang((self.num+1) % 2)
|
|
47
|
+
|
|
48
|
+
def generate(self) -> List[Dizhi]:
|
|
49
|
+
r = []
|
|
50
|
+
w = self.belongs_to_wuxing().generate()
|
|
51
|
+
for d in self.all():
|
|
52
|
+
if d.belongs_to_wuxing() == w:
|
|
53
|
+
r.append(d)
|
|
54
|
+
return r
|
|
55
|
+
|
|
56
|
+
def restrain(self) -> List[Dizhi]:
|
|
57
|
+
r = []
|
|
58
|
+
w = self.belongs_to_wuxing().restrain()
|
|
59
|
+
for d in self.all():
|
|
60
|
+
if d.belongs_to_wuxing() == w:
|
|
61
|
+
r.append(d)
|
|
62
|
+
return r
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
Dizhi._WUXING_MAP = {
|
|
66
|
+
Dizhi.Zi: Wuxing.Water,
|
|
67
|
+
Dizhi.Chou: Wuxing.Earth,
|
|
68
|
+
Dizhi.Yin: Wuxing.Wood,
|
|
69
|
+
Dizhi.Mou: Wuxing.Wood,
|
|
70
|
+
Dizhi.Chen: Wuxing.Earth,
|
|
71
|
+
Dizhi.Si: Wuxing.Fire,
|
|
72
|
+
Dizhi.Wu: Wuxing.Fire,
|
|
73
|
+
Dizhi.Wei: Wuxing.Earth,
|
|
74
|
+
Dizhi.Shen: Wuxing.Metal,
|
|
75
|
+
Dizhi.You: Wuxing.Metal,
|
|
76
|
+
Dizhi.Xu: Wuxing.Earth,
|
|
77
|
+
Dizhi.Hai: Wuxing.Water,
|
|
78
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from divicast.base.symbol import ValuedMultiton
|
|
2
|
+
from divicast.entities.wuxing import Wuxing
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Relative(ValuedMultiton):
|
|
6
|
+
"""
|
|
7
|
+
六亲
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
Brother = (0, "兄弟")
|
|
11
|
+
Descendant = (1, "子孙")
|
|
12
|
+
Parent = (2, "父母")
|
|
13
|
+
Governer = (3, "官鬼")
|
|
14
|
+
Wife = (4, "妻财")
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations # 用于前向引用
|
|
2
|
+
|
|
3
|
+
from typing import ClassVar, Dict, Self
|
|
4
|
+
|
|
5
|
+
from divicast.base.symbol import ValuedMultiton
|
|
6
|
+
from divicast.entities.wuxing import (BelongsToWuxing, BelongsToYinYang,
|
|
7
|
+
Wuxing, YinYang)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Shishen(ValuedMultiton):
|
|
11
|
+
"""
|
|
12
|
+
十神
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
BiJian = (0, "比肩")
|
|
16
|
+
JieCai = (1, "劫财")
|
|
17
|
+
ShiShen = (2, "食神")
|
|
18
|
+
ShangGuan = (3, "伤官")
|
|
19
|
+
PianCai = (4, "偏财")
|
|
20
|
+
ZhengCai = (5, "正财")
|
|
21
|
+
QiSha = (6, "七杀") # 也叫偏官
|
|
22
|
+
ZhengGuan = (7, "正官")
|
|
23
|
+
PianYin = (8, "偏印") # 也叫枭神
|
|
24
|
+
ZhengYin = (9, "正印")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Tiangan(BelongsToWuxing, BelongsToYinYang, ValuedMultiton):
|
|
28
|
+
"""
|
|
29
|
+
天干
|
|
30
|
+
"""
|
|
31
|
+
_WUXING_MAP: ClassVar[Dict[Tiangan, Wuxing]]
|
|
32
|
+
|
|
33
|
+
Jia = (0, "甲")
|
|
34
|
+
Yi = (1, "乙")
|
|
35
|
+
Bing = (2, "丙")
|
|
36
|
+
Ding = (3, "丁")
|
|
37
|
+
Wu = (4, "戊")
|
|
38
|
+
Ji = (5, "己")
|
|
39
|
+
Geng = (6, "庚")
|
|
40
|
+
Xin = (7, "辛")
|
|
41
|
+
Ren = (8, "壬")
|
|
42
|
+
Gui = (9, "癸")
|
|
43
|
+
|
|
44
|
+
def belongs_to_yinyang(self) -> YinYang:
|
|
45
|
+
"""
|
|
46
|
+
获取天干所属的阴阳
|
|
47
|
+
"""
|
|
48
|
+
return YinYang((self.num+1) % 2)
|
|
49
|
+
|
|
50
|
+
def get_shishen(self, other: Self) -> Shishen:
|
|
51
|
+
"""
|
|
52
|
+
获取对应的十神
|
|
53
|
+
"""
|
|
54
|
+
if self.belongs_to_wuxing() == other.belongs_to_wuxing():
|
|
55
|
+
# 同五行
|
|
56
|
+
return (
|
|
57
|
+
Shishen.BiJian
|
|
58
|
+
if self.belongs_to_yinyang() == other.belongs_to_yinyang()
|
|
59
|
+
else Shishen.JieCai # type: ignore
|
|
60
|
+
)
|
|
61
|
+
elif self.belongs_to_wuxing().generate() == other.belongs_to_wuxing():
|
|
62
|
+
# 我生对方
|
|
63
|
+
return (
|
|
64
|
+
Shishen.ShiShen
|
|
65
|
+
if self.belongs_to_yinyang() == other.belongs_to_yinyang()
|
|
66
|
+
else Shishen.ShangGuan # type: ignore
|
|
67
|
+
)
|
|
68
|
+
elif self.belongs_to_wuxing().restrain() == other.belongs_to_wuxing():
|
|
69
|
+
# 我克对方
|
|
70
|
+
return (
|
|
71
|
+
Shishen.PianCai
|
|
72
|
+
if self.belongs_to_yinyang() == other.belongs_to_yinyang()
|
|
73
|
+
else Shishen.ZhengCai # type: ignore
|
|
74
|
+
)
|
|
75
|
+
elif self.belongs_to_wuxing() == other.belongs_to_wuxing().restrain():
|
|
76
|
+
# 对方克我
|
|
77
|
+
return (
|
|
78
|
+
Shishen.QiSha
|
|
79
|
+
if self.belongs_to_yinyang() == other.belongs_to_yinyang()
|
|
80
|
+
else Shishen.ZhengGuan # type: ignore
|
|
81
|
+
)
|
|
82
|
+
elif self.belongs_to_wuxing() == other.belongs_to_wuxing().generate():
|
|
83
|
+
# 对方生我
|
|
84
|
+
return (
|
|
85
|
+
Shishen.PianYin
|
|
86
|
+
if self.belongs_to_yinyang() == other.belongs_to_yinyang()
|
|
87
|
+
else Shishen.ZhengYin # type: ignore
|
|
88
|
+
)
|
|
89
|
+
else:
|
|
90
|
+
raise ValueError("无法计算对应的十神关系")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Tiangan._WUXING_MAP = {
|
|
94
|
+
Tiangan.Jia: Wuxing.Wood,
|
|
95
|
+
Tiangan.Yi: Wuxing.Wood,
|
|
96
|
+
Tiangan.Bing: Wuxing.Fire,
|
|
97
|
+
Tiangan.Ding: Wuxing.Fire,
|
|
98
|
+
Tiangan.Wu: Wuxing.Earth,
|
|
99
|
+
Tiangan.Ji: Wuxing.Earth,
|
|
100
|
+
Tiangan.Geng: Wuxing.Metal,
|
|
101
|
+
Tiangan.Xin: Wuxing.Metal,
|
|
102
|
+
Tiangan.Ren: Wuxing.Water,
|
|
103
|
+
Tiangan.Gui: Wuxing.Water,
|
|
104
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import ClassVar, Dict, List
|
|
4
|
+
|
|
5
|
+
from divicast.base.symbol import ValuedMultiton
|
|
6
|
+
from divicast.entities.wuxing import *
|
|
7
|
+
from divicast.entities.wuxing import Wuxing
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Line(ValuedMultiton):
|
|
11
|
+
"""
|
|
12
|
+
爻
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
YinYao = (0, "⚋")
|
|
16
|
+
YangYao = (1, "⚊")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Trigram(BelongsToWuxing, ValuedMultiton):
|
|
20
|
+
"""
|
|
21
|
+
八卦
|
|
22
|
+
"""
|
|
23
|
+
_WUXING_MAP: ClassVar[Dict[Trigram, Wuxing]]
|
|
24
|
+
_PRIMARY_IMAGE_MAP: ClassVar[Dict[Trigram, str]]
|
|
25
|
+
lines: List[Line]
|
|
26
|
+
|
|
27
|
+
Kun = (0, "坤")
|
|
28
|
+
Zhen = (1, "震")
|
|
29
|
+
Kan = (2, "坎")
|
|
30
|
+
Dui = (3, "兑")
|
|
31
|
+
Gen = (4, "艮")
|
|
32
|
+
Li = (5, "离")
|
|
33
|
+
Xun = (6, "巽")
|
|
34
|
+
Qian = (7, "乾")
|
|
35
|
+
|
|
36
|
+
def __init__(self, num: int, chinese_name: str | None = None):
|
|
37
|
+
"""
|
|
38
|
+
:param num: 0-7
|
|
39
|
+
:param name: 可选, 如果不提供则使用类名
|
|
40
|
+
:param chinese_name: 可选, 如果不提供则使用类名
|
|
41
|
+
"""
|
|
42
|
+
ValuedMultiton.__init__(self, num, chinese_name)
|
|
43
|
+
self.lines = [Line((num >> 0) & 1), Line(
|
|
44
|
+
(num >> 1) & 1), Line((num >> 2) & 1)]
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def primary_image(self) -> str:
|
|
48
|
+
"""
|
|
49
|
+
主象
|
|
50
|
+
"""
|
|
51
|
+
return self._PRIMARY_IMAGE_MAP[self]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
Trigram._WUXING_MAP = {
|
|
55
|
+
Trigram.Qian: Wuxing.Metal,
|
|
56
|
+
Trigram.Dui: Wuxing.Metal,
|
|
57
|
+
Trigram.Kan: Wuxing.Water,
|
|
58
|
+
Trigram.Gen: Wuxing.Earth,
|
|
59
|
+
Trigram.Li: Wuxing.Fire,
|
|
60
|
+
Trigram.Xun: Wuxing.Wood,
|
|
61
|
+
Trigram.Zhen: Wuxing.Wood,
|
|
62
|
+
Trigram.Kun: Wuxing.Earth,
|
|
63
|
+
}
|
|
64
|
+
Trigram._PRIMARY_IMAGE_MAP = {
|
|
65
|
+
Trigram.Qian: '天',
|
|
66
|
+
Trigram.Dui: '泽',
|
|
67
|
+
Trigram.Kan: '水',
|
|
68
|
+
Trigram.Gen: '山',
|
|
69
|
+
Trigram.Li: '火',
|
|
70
|
+
Trigram.Xun: '风',
|
|
71
|
+
Trigram.Zhen: '雷',
|
|
72
|
+
Trigram.Kun: '地'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class Hexagram(ValuedMultiton):
|
|
77
|
+
"""六十四卦"""
|
|
78
|
+
|
|
79
|
+
H63 = (63, "乾")
|
|
80
|
+
H0 = (0, "坤")
|
|
81
|
+
H17 = (17, "屯")
|
|
82
|
+
H34 = (34, "蒙")
|
|
83
|
+
H23 = (23, "需")
|
|
84
|
+
H58 = (58, "讼")
|
|
85
|
+
H2 = (2, "师")
|
|
86
|
+
H16 = (16, "比")
|
|
87
|
+
H55 = (55, "小畜")
|
|
88
|
+
H59 = (59, "履")
|
|
89
|
+
H7 = (7, "泰")
|
|
90
|
+
H56 = (56, "否")
|
|
91
|
+
H61 = (61, "同人")
|
|
92
|
+
H47 = (47, "大有")
|
|
93
|
+
H4 = (4, "谦")
|
|
94
|
+
H8 = (8, "豫")
|
|
95
|
+
H25 = (25, "随")
|
|
96
|
+
H38 = (38, "蛊")
|
|
97
|
+
H3 = (3, "临")
|
|
98
|
+
H48 = (48, "观")
|
|
99
|
+
H41 = (41, "噬嗑")
|
|
100
|
+
H37 = (37, "贲")
|
|
101
|
+
H32 = (32, "剥")
|
|
102
|
+
H1 = (1, "复")
|
|
103
|
+
H57 = (57, "无妄")
|
|
104
|
+
H39 = (39, "大畜")
|
|
105
|
+
H33 = (33, "颐")
|
|
106
|
+
H30 = (30, "大过")
|
|
107
|
+
H18 = (18, "坎")
|
|
108
|
+
H45 = (45, "离")
|
|
109
|
+
H28 = (28, "咸")
|
|
110
|
+
H14 = (14, "恒")
|
|
111
|
+
H60 = (60, "遁")
|
|
112
|
+
H15 = (15, "大壮")
|
|
113
|
+
H40 = (40, "晋")
|
|
114
|
+
H5 = (5, "明夷")
|
|
115
|
+
H53 = (53, "家人")
|
|
116
|
+
H43 = (43, "睽")
|
|
117
|
+
H20 = (20, "蹇")
|
|
118
|
+
H10 = (10, "解")
|
|
119
|
+
H35 = (35, "损")
|
|
120
|
+
H49 = (49, "益")
|
|
121
|
+
H31 = (31, "夬")
|
|
122
|
+
H62 = (62, "姤")
|
|
123
|
+
H24 = (24, "萃")
|
|
124
|
+
H6 = (6, "升")
|
|
125
|
+
H26 = (26, "困")
|
|
126
|
+
H22 = (22, "井")
|
|
127
|
+
H29 = (29, "革")
|
|
128
|
+
H46 = (46, "鼎")
|
|
129
|
+
H9 = (9, "震")
|
|
130
|
+
H36 = (36, "艮")
|
|
131
|
+
H52 = (52, "渐")
|
|
132
|
+
H11 = (11, "归妹")
|
|
133
|
+
H13 = (13, "丰")
|
|
134
|
+
H44 = (44, "旅")
|
|
135
|
+
H54 = (54, "巽")
|
|
136
|
+
H27 = (27, "兑")
|
|
137
|
+
H50 = (50, "涣")
|
|
138
|
+
H19 = (19, "节")
|
|
139
|
+
H51 = (51, "中孚")
|
|
140
|
+
H12 = (12, "小过")
|
|
141
|
+
H21 = (21, "既济")
|
|
142
|
+
H42 = (42, "未济")
|
|
143
|
+
|
|
144
|
+
def inside_trigram(self) -> Trigram:
|
|
145
|
+
return Trigram(self.num % 8)
|
|
146
|
+
|
|
147
|
+
def outside_trigram(self) -> Trigram:
|
|
148
|
+
return Trigram(self.num // 8)
|
|
149
|
+
|
|
150
|
+
def belongs_to_trigram(self) -> Trigram:
|
|
151
|
+
"""
|
|
152
|
+
归宫
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
if self.belongs_to_trigram_seq() in [1, 2, 3, 6]: # 一二三六外卦宫
|
|
156
|
+
return self.outside_trigram()
|
|
157
|
+
elif self.belongs_to_trigram_seq() in [4, 5, 7]: # 四五游魂内变更
|
|
158
|
+
return Trigram(self.inside_trigram().num ^ 0b111)
|
|
159
|
+
elif self.belongs_to_trigram_seq() == 8: # 归魂内卦是本宫
|
|
160
|
+
return self.inside_trigram()
|
|
161
|
+
else:
|
|
162
|
+
raise AssertionError("Unexpected belongs_to_trigram_seq")
|
|
163
|
+
|
|
164
|
+
def belongs_to_trigram_seq(self) -> int:
|
|
165
|
+
"""
|
|
166
|
+
归宫的序号
|
|
167
|
+
CAVEAT: 这里的序号是从1开始的, 方便口诀计算
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
_0 = (self.num & 0b000001) ^ ((self.num & 0b001000) >> 3) == 0 # 地
|
|
171
|
+
_1 = (self.num & 0b000010) ^ ((self.num & 0b010000) >> 3) == 0 # 人
|
|
172
|
+
_2 = (self.num & 0b000100) ^ ((self.num & 0b100000) >> 3) == 0 # 天
|
|
173
|
+
seq = 0
|
|
174
|
+
|
|
175
|
+
if _2 and not _1 and not _0: # 天同二世
|
|
176
|
+
seq = 2
|
|
177
|
+
elif not _2 and _1 and _0: # 天变五
|
|
178
|
+
seq = 5
|
|
179
|
+
elif not _2 and not _1 and _0: # 地同四世
|
|
180
|
+
seq = 4
|
|
181
|
+
elif _2 and _1 and not _0: # 地变一
|
|
182
|
+
seq = 1
|
|
183
|
+
elif _2 and _1 and _0: # 本宫六世
|
|
184
|
+
seq = 6
|
|
185
|
+
elif not _2 and not _1 and not _0: # 三世异
|
|
186
|
+
seq = 3
|
|
187
|
+
elif not _2 and _1 and not _0: # 人同游魂
|
|
188
|
+
seq = 7 # 游魂
|
|
189
|
+
elif _2 and not _1 and _0: # 人变归
|
|
190
|
+
seq = 8 # 归魂
|
|
191
|
+
else:
|
|
192
|
+
raise ValueError("无法判断归宫的序号")
|
|
193
|
+
return seq
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from divicast.base.symbol import BelongsTo, ValuedMultiton
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class YinYang(ValuedMultiton):
|
|
7
|
+
"""阴阳"""
|
|
8
|
+
|
|
9
|
+
Yin = (0, "阴")
|
|
10
|
+
Yang = (1, "阳")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BelongsToYinYang(BelongsTo):
|
|
14
|
+
"""
|
|
15
|
+
实现了`BelongsTo`接口的类,表示属于某个阴阳
|
|
16
|
+
通过定义`_YINYANG_MAP`,可以自动返回所属阴阳
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def belongs_to_yinyang(self) -> YinYang:
|
|
20
|
+
"""
|
|
21
|
+
默认实现,通过定义`_YINYANG_MAP`,返回所属阴阳
|
|
22
|
+
"""
|
|
23
|
+
return self.belongs_to(YinYang, "_YINYANG_MAP")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Wuxing(ValuedMultiton):
|
|
27
|
+
"""五行"""
|
|
28
|
+
|
|
29
|
+
Wood = (0, "木")
|
|
30
|
+
Fire = (1, "火")
|
|
31
|
+
Earth = (2, "土")
|
|
32
|
+
Metal = (3, "金")
|
|
33
|
+
Water = (4, "水")
|
|
34
|
+
|
|
35
|
+
def restrain(self) -> Wuxing:
|
|
36
|
+
"""
|
|
37
|
+
表示五行相克
|
|
38
|
+
"""
|
|
39
|
+
return Wuxing((self.num + 2) % 5)
|
|
40
|
+
|
|
41
|
+
def generate(self) -> Wuxing:
|
|
42
|
+
"""
|
|
43
|
+
表示五行相生
|
|
44
|
+
"""
|
|
45
|
+
return Wuxing((self.num + 1) % 5)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class BelongsToWuxing(BelongsTo):
|
|
49
|
+
"""
|
|
50
|
+
这是一个协议,它定义了一个“可以转化为五行”的契约。
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def belongs_to_wuxing(
|
|
54
|
+
self,
|
|
55
|
+
) -> Wuxing:
|
|
56
|
+
return self.belongs_to(Wuxing, "_WUXING_MAP")
|