zhongchuyi commited on
Commit
825a24e
·
1 Parent(s): 558133c

Upgrade controllable iteration: analyse mode + design log export

Browse files
Files changed (36) hide show
  1. .cache/24ecc35b8ac4f75781c1a0d45f4c623a.cache +134 -0
  2. .cache/34018faf60e95fcea73eb0e7db6062db.cache +103 -0
  3. .cache/52e20638d2becd5fed76f17ca0a00ce5.cache +130 -0
  4. .cache/5e5507ef87822c2bdd18001de5b07457.cache +117 -0
  5. .cache/6568c004b7ca983d92f8f2872440b56e.cache +130 -0
  6. .cache/6d3dd629f7c1e6ebad53764273569ef1.cache +173 -0
  7. .cache/70e7d1abaf85c9b17988d32c0bd44fc3.cache +27 -0
  8. .cache/895eeee552d81a755b71d2aaccc36998.cache +166 -0
  9. .cache/89b4366d3e4aafe8626efd543517da1c.cache +199 -0
  10. .cache/8ba0a7d9927d748478d8fac4163af8aa.cache +247 -0
  11. .cache/9080a7d7f3a4965ac1b4c5746ba490ef.cache +154 -0
  12. .cache/a72cd6d19b406f34e03bc1908e24d0dc.cache +155 -0
  13. .cache/ab4abc5772bc9251ee2f06b77178bc96.cache +161 -0
  14. .cache/abe70409f4028b5f41913146ddf036d2.cache +283 -0
  15. .cache/d124ffce9e9013b3c1f0960978ea5eb4.cache +147 -0
  16. .cache/e5d1e6efe417a200ee79ac217a2e9276.cache +119 -0
  17. .cache/f373cbfec78689ef2a023b520e02fd40.cache +140 -0
  18. .cache/f8a27e1a8a217a94e49fbc7c0a369e80.cache +173 -0
  19. .cache/fe18e3689386fc503e95de497838dcc5.cache +190 -0
  20. README.md +16 -0
  21. __pycache__/ai_service.cpython-37.pyc +0 -0
  22. __pycache__/cache_manager.cpython-37.pyc +0 -0
  23. __pycache__/config.cpython-37.pyc +0 -0
  24. __pycache__/default_content.cpython-37.pyc +0 -0
  25. __pycache__/design_state.cpython-37.pyc +0 -0
  26. __pycache__/file_handler.cpython-37.pyc +0 -0
  27. __pycache__/output_validator.cpython-37.pyc +0 -0
  28. __pycache__/reference_retriever.cpython-37.pyc +0 -0
  29. __pycache__/security.cpython-37.pyc +0 -0
  30. ai_service.py +90 -11
  31. app.py +345 -19
  32. config.py +15 -0
  33. design_state.py +173 -0
  34. m_prompt.txt +91 -8
  35. output_validator.py +119 -0
  36. reference_retriever.py +392 -0
.cache/24ecc35b8ac4f75781c1a0d45f4c623a.cache ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 两门血战麻将
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 两门血战麻将
6
+
7
+ 2. 玩家玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9筒各四张,1-9条各四张,共72张牌
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 行牌规则
36
+
37
+ 1. 可以碰牌、杠牌,不可以吃牌
38
+
39
+ 2. 胡牌规则
40
+
41
+ 1. 血战规则,可多人胡,胡过的玩家则结束当局;直到场上有还有一个玩家未胡牌或者牌墙全部摸完时,牌局结束
42
+
43
+ 3. 报叫
44
+
45
+ 1. 发完牌后,玩家起手即可报听,则可选择是否报叫,报叫为明叫,其他玩家可以看到报叫玩家的听口
46
+
47
+ 2. 报叫后不能换叫,有胡必胡
48
+
49
+ 3. 报叫中,不破坏牌型的杠可以杠
50
+
51
+ 4. 报叫没胡成,称为关死,报叫玩家赔付有叫未胡玩家最高牌型倍数
52
+
53
+ 4. 查叫
54
+
55
+ 1. 有玩家未下叫,需赔付给有叫未胡玩家最大可能的倍数
56
+
57
+ 5. 过手碰
58
+
59
+ 1. 能碰而不碰,玩家在自己下次的操作结束之前,不能再碰同一张牌
60
+
61
+ 6. 过水胡
62
+
63
+ 1. 在某一回合,若有人点炮,玩家没有胡,那此玩家在自己下次的操作结束之前,均不能胡牌,若自己自摸,则可以胡
64
+
65
+ 7. 流局
66
+
67
+ 1. 所有手牌摸完,本桌还没有玩家胡牌,即为流局,有玩家未下叫,需要赔付给有叫未胡的玩家最大可能的倍数
68
+
69
+ 8. 杠牌规则
70
+
71
+ 1. 所有杠分均为即时结算
72
+
73
+ 2. 直杠:采用擦挂规则计算,收取点杠玩家游戏基数\*2,非点杠玩家游戏基数\*1的分数
74
+
75
+ 3. 补杠:收取所有未胡玩家游戏基数\*1的分数
76
+
77
+ 4. 暗杠: 收取所有未胡玩家游戏基数\*2的分数
78
+
79
+ 9. 番型及倍数
80
+
81
+ 1. 牌型中有包含关系的不重复计算
82
+
83
+ | **番型** | **说明** | **倍数** |
84
+ | --- | --- | --- |
85
+ | 基本胡 | 普通的四坎牌外加一对将牌 | 1 |
86
+ | 卡二条 | 即玩家有1、3条,胡2条且该2条需要和1、3条组成123的一手牌 | 2 |
87
+ | 清一色 | 即一副牌均为同一花色 | 4 |
88
+ | 碰碰胡 | 由4个刻子或杠牌+1对将牌组成 | 4 |
89
+ | 七对 | 胡牌时手牌为七对牌,没有碰或杠过牌 | 4 |
90
+ | 豪华七对 | 即在七对的基础上,其中两对为相同的牌 | 8 |
91
+ | 清碰 | 即手牌为清一色的大对子 | 16 |
92
+ | 清七对 | 即手牌为清一色的七对 | 16 |
93
+
94
+ 2. 胡牌操作可叠乘
95
+
96
+ | **操作** | **说明** | **倍数** |
97
+ | --- | --- | --- |
98
+ | 自摸 | 自己摸到牌胡牌,自摸收三家分 | 2 |
99
+ | 点炮 | 胡别人打出的牌,点炮仅点炮者赔付 | 1 |
100
+ | 抢杠 | 玩家补杠的牌被人胡,杠失败,视为该玩家点炮 | 2 |
101
+ | 杠上炮 | 玩家杠牌后打出一张牌并点炮 | 2 |
102
+ | 杠上花 | 玩家杠牌后另摸一张牌并且胡牌,点杠上花收三家 | 2 |
103
+ | 地胡 | 庄家打出的第一张牌被闲家胡了 | 2 |
104
+ | 天胡 | 庄家起手拿到的14张牌就胡了 | 4 |
105
+
106
+ 3. 加番操作可叠乘
107
+
108
+
109
+ | **另加番** | **说明** | **倍数** |
110
+ | --- | --- | --- |
111
+ | 根 | 四张相同的牌为一根,根可叠乘 | 2 |
112
+ | 断幺九 | 胡牌时手中没有幺和九的条筒牌 | 2 |
113
+ | 门清 | 即玩家胡牌时没有过碰、明杠行为 | 2 |
114
+ | 报叫 | 玩家报叫后胡牌或点炮均会增加此倍数 | 16 |
115
+
116
+ 2. 行牌阶段
117
+
118
+ 1. 庄家先出牌
119
+
120
+ 2.   判定是否碰、杠、胡
121
+
122
+ 1.   否,按逆时针顺序确定下家,庄家下家摸打;
123
+
124
+ 2.   是,执行碰、杠、胡操作;
125
+
126
+ 3.   按逆时针顺序摸打,直到某个玩家胡牌;
127
+
128
+ 4.   直到牌山摸完或者有玩家胡牌,牌局结束
129
+
130
+ 3. 结算阶段
131
+
132
+ 1. 胡分={总番数(番型\*操作\*另加番)+杠分}\*游戏基数
133
+
134
+ 2. 32倍封顶
.cache/34018faf60e95fcea73eb0e7db6062db.cache ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 经典推倒胡
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 经典推倒胡
6
+
7
+ 2. 玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各四张,1-9条各四张,1-9筒各四张,8张花牌(春夏秋冬、梅兰竹菊),共116张牌
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 番型规则
36
+
37
+ 1. 胡牌如果通过以下的胡牌方式胡牌,倍数额外+1
38
+
39
+
40
+ | 胡牌方式 | 倍数 | 说明 |
41
+ | --- | --- | --- |
42
+ | 胡牌 | 1 | 符合胡牌规则胡牌 |
43
+ | 杠开 | 1 | 杠后摸起的牌正好满足胡牌 |
44
+ | 抢杠胡 | 1 | 胡别人补杠的牌 |
45
+ | 海底捞月 | 1 | 摸到牌墙的最后一张牌胡牌 |
46
+
47
+ 胡牌时,每含有1个以下胡牌番型,倍数额外+1
48
+
49
+ | 胡牌番型 | 倍数 | 说明 |
50
+ | --- | --- | --- |
51
+ | 碰碰胡 | 1 | 胡牌时,手牌全是碰、杠的形式,包含金钩钓 |
52
+ | 清一色 | 1 | 胡牌时,所有牌张为同一门花色 |
53
+ | 七对 | 1 | 胡牌时,手牌由7个对子组成,包含龙七对 |
54
+
55
+ 2. 杠分规则
56
+
57
+ 1. 杠分、补花分在游戏内及时结算,流局也有效。
58
+
59
+ 2. 补花=每人输1倍基数
60
+
61
+ 3. 补杠=每人输1倍基数
62
+
63
+ 4. 直杠=点杠人输3倍基数
64
+
65
+ 5. 暗杠=每人输2倍基数
66
+
67
+ 6. 补杠需第一时间补,后续再补只增加翻马数,没有杠分收益。
68
+
69
+ 2. 行牌阶段
70
+
71
+ 1. 可以碰牌、杠牌,不能吃、
72
+
73
+ 2. 胡牌规则
74
+
75
+ 1. 仅可自摸、杠开、抢杠胡,不能点炮胡。
76
+
77
+ 2. 多人抢杠胡时,有截胡规则,按照被抢者的位置,顺位靠前的优先胡。
78
+
79
+ 3. 翻马牌规则
80
+
81
+ 1. 胡牌后,胡牌玩家从另一副牌中翻开若干张牌,翻出序数1、5、9或者花牌,视为中马。
82
+
83
+ 2. 通过以下几种方式,可额外增加翻马牌张数:
84
+
85
+ 1. 对局开始后,牌墙每减少4张牌,所有人翻马数+1。
86
+
87
+ 2. 对局中,每碰1次,翻马张数+2。
88
+
89
+ 3. 补杠翻马张数+3,直杠+6,暗杠+9。
90
+
91
+ 4. 每补一个花,翻马张数+1。
92
+
93
+ 5. 胡牌时,根据胡牌的番型总倍数和胡牌方式,当局累计的额外翻马张数有额外倍数加成。
94
+
95
+ 3. 总翻马张数=8+(对局过程额外增加翻马牌张数)\*(胡牌倍数+胡牌番型倍数)。最多可翻48张马牌。
96
+
97
+ 3. 结算阶段
98
+
99
+ 1. 结算规则
100
+
101
+ 1. 胡牌得分=游戏基数\*中马数量。
102
+
103
+ 2. 点杠被杠开时,点杠者需承包,按照3家的输分赔付杠开者。
.cache/52e20638d2becd5fed76f17ca0a00ce5.cache ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 合肥麻将
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 合肥麻将
6
+
7
+ 2. 玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 2-8万各四张、2-8条各四张、2-8筒各四张,共84张牌
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 行牌规则
36
+
37
+ 1. 可以碰牌、杠牌,不可以吃
38
+
39
+ 2. 可明杠、暗杠、补杠
40
+
41
+ 3. 报听后,听口不变情况下,也可杠
42
+
43
+ 2. 胡牌规则
44
+
45
+ 1. 胡牌条件:任一花色达到8张及以上(包含碰杠牌张)
46
+
47
+ 2. 可以点炮(需报听)或自摸胡牌,可以抢杠胡
48
+
49
+ 3. 允许一炮多响
50
+
51
+ 3. 名词定义
52
+
53
+ 1. 报听
54
+
55
+ 1. 玩家达成 “听牌” 状态后,向其他玩家明确宣告
56
+
57
+ 2. 流局
58
+
59
+ 1. 指的是整局游戏中,所有玩家都未达成胡牌条件,且牌山中的牌已摸完(或达到规则约定的流局条件),导致本局无胜利者、直接结束的情况。
60
+
61
+ 4. 番型及倍数
62
+
63
+ 1. | 基本番型 | 嘴数 | 说明 |
64
+ | --- | --- | --- |
65
+ | 胡牌 | +15 | 只要胡牌就加15嘴 |
66
+
67
+ | 另外加番 | 嘴数 | 说明 |
68
+ | --- | --- | --- |
69
+ | 支 | +1 | 某一门有8张是胡牌的基本要求,如有9张则加1支,10张加2支,以此类推,多支多分(一支+1嘴)。 |
70
+ | 同 | +1 | 所有牌中数字一样的牌从 第4 张起数, 每多一张多+1嘴(如:3 张四万、 2 张四条、 3 张四饼的牌,则+4嘴)。 |
71
+ | 坎(暗刻) | +1 | 三张一样的牌在手,且符合基本胡牌牌型中的刻,即三张牌未分开叫做一坎,每一坎+1嘴。 |
72
+ | 庄 | +1/+2 | 点炮胡,则+1嘴\*连庄数;<br>自摸胡,则+2嘴\*连庄数。 |
73
+ | 缺门 | +2 | 胡牌时所有牌只存在有2门花色。 |
74
+ | 明双铺子 | +2 | 两个一样的顺,如345万 345万,若胡牌是胡其中的一张算明双铺,+2嘴 若不是胡其中的牌则为暗双铺+4嘴。 |
75
+ | 卡 | +4 | 只胡一张牌的牌型所胡的牌称为卡,+4嘴。(2、3胡4;7、8胡6也算卡) |
76
+ | 活(4核) | +4 | 某种牌有四张且没有开杠,只要有四张的就算活(豪华七对也算活)。 |
77
+ | 杠 | +4 | 有一杠则+4嘴 |
78
+ | 暗双铺子 | +4 | 两个一样的顺,如345万 345万,若胡牌是胡其中的一张算明双铺,+2嘴 若不是胡其中的牌则为暗双铺+4嘴。 |
79
+
80
+ 2. 七对、豪七、双豪七、三豪七这四个牌型间不叠加;其他牌型同时存在可叠加。
81
+
82
+ | 特殊牌型 | 嘴数 | 说明 |
83
+ | --- | --- | --- |
84
+ | 七对 | +10 | 手上牌为7个搭牌,此时可胡牌。 |
85
+ | 豪华七对 | +50 | 七对中有4张相同牌。 |
86
+ | 双豪华七对 | +100 | 七对中有2个4张相同牌。 |
87
+ | 清一色 | +100 | 胡牌时,手上所有的牌是同一门花色。(不计缺门) |
88
+ | 十同 | +100 | 同数字的牌张超过10张(不计同)。 |
89
+ | 三连坎 | +100 | 同花色连在一起的3个坎(不计坎)。 |
90
+ | 四暗刻 | +100 | 4坎加一个搭牌,坎牌必须是自己摸的才算,点炮不算。 |
91
+ | 三豪华七对 | +150 | 七对中有3个4张相同牌。 |
92
+
93
+ | 胡牌操作 | 嘴数 | 说明 |
94
+ | --- | --- | --- |
95
+ | 杠开 | \*2 | 开杠后,补上来的牌构成胡牌,嘴数翻倍 |
96
+ | 杠炮 | \*2 | 杠牌后打出放炮 |
97
+ | 抢杠 | \*2 | 玩家补杠,此时正好有玩家胡这张牌,胡这张牌的玩家可以点胡,算抢杠 |
98
+ | 海底捞月 | +15 | 最后通过海捞区的牌自摸 |
99
+ | 地胡 | +150 | 第一圈内,玩家A2或A3或A4自摸(其他番都不算了,要符合某一门有8张是胡牌的基本要求)。 |
100
+ | 天胡 | +200 | 庄家起���胡牌(其他番都不算了,要符合某一门有8张是胡牌的基本要求)。 |
101
+
102
+ 3. 七对,豪华七对,超豪华七对和双铺子不能共存;七对要胡的牌也算卡。
103
+
104
+ 4. 七对胡牌必须一门达到或超过8张。
105
+
106
+ 2. 对战阶段
107
+
108
+ 1. 阶段划分
109
+
110
+ 1. 行牌阶段、海捞阶段
111
+
112
+ 2. 海捞阶段
113
+
114
+ 1. 牌桌上仅剩最后4张未抓的牌时,放入“海捞区”
115
+
116
+ 2. 四家从“海捞区”各抓一张牌放入手牌中,从第一个摸牌玩家逆时针开始,如果有一个玩家胡牌,则停止海捞,进入结算
117
+
118
+ 3. 所有玩家不能再杠牌
119
+
120
+ 3. 结算阶段
121
+
122
+ 1. 结算规则
123
+
124
+ 1. 总分=基数\*总嘴数\*人数(自摸胡牌,则人数为3;点炮胡牌,则人数为1);
125
+
126
+ 2. 捉炮者由点炮者付,其余两家不用付,自摸的牌由三家付;
127
+
128
+ 3. 杠分只有胡家算,不胡的不用算;
129
+
130
+ 4. 流局不计算任何分数。
.cache/5e5507ef87822c2bdd18001de5b07457.cache ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 海底捞月
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 海底捞月
6
+
7
+ 2. 玩家
8
+
9
+ 1. 人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9 条各 12 张,字牌(东南西北中发白)各 8 张,月亮牌(万能赖子牌)12 张
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 发牌:每名玩家发 13 张牌,投骰子决定庄家。
36
+
37
+ 2. 可以碰杠,不可以吃。杠>碰>胡。
38
+
39
+ 3. 杠牌:(可自动连续杠)
40
+
41
+ 1. 杠字牌获得海底牌,杠序数牌获得倍数。
42
+
43
+ 2. 玩家每杠1张序数牌,获得月轮+1,不获得海底牌。每满5个月轮,胡牌倍数+1(倍数初始为1)
44
+
45
+ 3. 玩家每杠1张字牌,在牌库中抽取一定量的海底牌数,每多杠两次增加1张。(即:杠第1张抽1张,杠第2张抽2张,杠第3张抽2张,杠第4张抽3张,以此类推)
46
+
47
+ 4. 赖子牌:玩家初始有每人有一张赖子,且过程中不能打出。后续摸到的赖子可以进行打出或补杠的操作:
48
+
49
+ 1. 打出:进入弃牌区,不会被别人碰杠走,有其他牌时当作任意牌触发消除
50
+
51
+ 2. 补杠:已经开杠的牌,可以使用赖子补杠
52
+
53
+ 5. 消除
54
+
55
+ 1. 当玩家打出的弃牌与自己牌河中已有的牌成对,则两张一起消除,并触发一次效果选择。
56
+
57
+ 1. 可选效果3选1:倍数+2/海底牌+2/换3张
58
+
59
+ 2. 被其他玩家碰、杠的牌不在牌河中,不计数。
60
+
61
+ 3. 牌河中已触发消除的牌会消失。
62
+
63
+ 6. 胡牌
64
+
65
+ 1. 玩家每次胡牌时,会额外奖励一张海底牌。
66
+
67
+ 2. 只能自摸,不能点炮胡、一炮多响。胡牌不影响行牌顺序(即:有人胡牌后,胡牌人下家摸牌)
68
+
69
+ 3. 胡牌阶段可以继续杠牌,倍数/海底牌正常计算。
70
+
71
+ 4. 血流胡法,玩家需要一直胡牌直到淘汰其他人或摸完牌库。
72
+
73
+ 7. 番型及倍数
74
+
75
+
76
+ | 牌型 | 倍数 | 番型展示优先级 | 描述 |
77
+ | --- | --- | --- | --- |
78
+ | 碰碰胡 | 48 | | 由四个刻子/杠牌和将牌组成的胡牌 |
79
+ | 清一色 | 128 | 60 | 全部由万筒条中的一种花色组成的胡牌 |
80
+ | 孤鸿踏星 | 88 | 40 | 胡牌时有一种字牌 |
81
+ | 双帆竞流 | 128 | 50 | 胡牌时有两种字牌 |
82
+ | 众星拱月 | 168 | 70 | 胡牌时有三种字牌 |
83
+ | 四海升平 | 208 | 80 | 胡牌时有四种字牌 |
84
+ | ++字一色++ | 268 | 90 | 胡牌时所有牌均为字牌 |
85
+ | 大四喜 | 168 | 100 | 包含东南西北4组刻/杠的胡牌 |
86
+ | 大三元 | 128 | 100 | 包含中发白3组刻/杠的胡牌 |
87
+ | 三节高 | 48 | | 牌型中包含3个人同花色且点数连续的刻子/杠 |
88
+ | 四节高 | 88 | | 牌型中包含4个同花色且点数连续的刻子/杠 |
89
+ | 四季常春 | 24 | | 胡牌时有4组杠牌 |
90
+ | 三羊开泰 | 12 | | 胡牌时有3组杠牌 |
91
+ | 二分明月 | 4 | | 胡牌时有2组杠牌 |
92
+ | 一马当先 | 2 | | 胡牌时有1组杠牌 |
93
+ | 双暗刻 | 28 | | 牌型中有2个暗杠/暗刻的胡牌 |
94
+ | 三暗刻 | 38 | | 牌型中由3个暗杠/暗刻的胡牌 |
95
+ | 四暗刻 | 48 | | 牌型中有4个暗杠/暗刻 |
96
+ | 字一色 | 258 | | 胡牌时,只由东南西北中发白组成的胡牌牌型 |
97
+ | 绿一色 | 68 | | 由23468条+发财组成的胡牌 |
98
+
99
+ 2. 行牌阶段
100
+
101
+ 1. 阶段划分
102
+
103
+ 1. 换三张阶段、摸牌阶段、海底捞月阶段
104
+
105
+ 2. 换三张阶段
106
+
107
+ 1. 发牌后,玩家可选择3张手牌进行替换,由系统在牌库中重新抽牌,玩家选中的牌重新洗入牌堆。
108
+
109
+ 3. 海底牌
110
+
111
+ 1. 牌墙中所有牌摸完时,会触发“海底捞月”环节,所有玩家依据杠牌倍数从高到低进行结算。
112
+
113
+ 2. 海底牌所有可以胡牌的牌均会正常结算。如���胡到赖子牌,额外倍数x20。
114
+
115
+ 3. 结算阶段
116
+
117
+ 1. 胡牌金币数=底分x番型x胡牌倍数。
.cache/6568c004b7ca983d92f8f2872440b56e.cache ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 疯狂血战
2
+
3
+ 1. 玩法名称:疯狂血战】
4
+
5
+ 2. 玩家:
6
+
7
+ 1. 总人数:
8
+
9
+ 1. 4人
10
+
11
+ 2. 编号:
12
+
13
+ 1. 庄家记为:A1
14
+
15
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
16
+
17
+ 3. 行动模式:
18
+
19
+ 1. 依次行动(A1,A2,A3,A4)
20
+
21
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
22
+
23
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
24
+
25
+ 4. 游戏所需设备
26
+
27
+ 1. 1-9万各四张,1-9条各四张,1-9筒各四张,共108张牌
28
+
29
+ 5. 规则描述
30
+
31
+ 1. 准备阶段
32
+
33
+ 1. 行牌规则
34
+
35
+ 1. 可以碰、杠,不能吃
36
+
37
+ 2. 可以暗杠、明杠和补杠
38
+
39
+ 3. 同一张牌打出时,可同时被胡牌和碰杠
40
+
41
+ 2. 番型及倍数
42
+
43
+ 1. 基础番型及倍数
44
+
45
+ | 基础番型 | 番数 | 倍数 |
46
+ | --- | --- | --- |
47
+ | 平胡 | 0 | 1 |
48
+ | 碰碰胡 | 1 | 10 |
49
+ | 七对 | 2 | 100 |
50
+ | 清一色 | 2 | 100 |
51
+ | 金钩钓 | 2 | 100 |
52
+ | 清碰 | 3 | 1000 |
53
+ | 龙七对 | 3 | 1000 |
54
+ | 清金钩钓 | 4 | 10000 |
55
+ | 双龙七对 | 4 | 10000 |
56
+ | 清七对 | 4 | 10000 |
57
+ | 三龙七对 | 5 | 100000 |
58
+ | 清龙七对 | 5 | 100000 |
59
+ | 清双龙七对 | 6 | 1000000 |
60
+ | 十八罗汉 | 6 | 1000000 |
61
+
62
+ 2. 其他番型及倍数
63
+
64
+
65
+ | 其它番型 | 番数 | 倍数 |
66
+ | --- | --- | --- |
67
+ | 杠上开花 | 1 | 10 |
68
+ | 杠上炮 | 1 | 10 |
69
+ | 抢杠胡 | 1 | 10 |
70
+ | 根 | 1 | 10 |
71
+ | 海底捞月/炮 | 1 | 10 |
72
+ | 自摸 | 1 | 10 |
73
+
74
+ 3. 杠牌
75
+
76
+ 1. 不计杠分,无相关金流
77
+
78
+ 4. 初始手牌数量
79
+
80
+ 1. 13张
81
+
82
+ 5. 发牌及摸牌规则[请至钉钉文档查看附件《xuezhan\_fk.xlsm》](https://alidocs.dingtalk.com/i/nodes/jb9Y4gmKWr7Gwxx2fpKNjepwVGXn6lpz?doc_type=wiki_doc&iframeQuery=anchorId%3DX02mhn98lcsop813bpirjl)
83
+
84
+ 2. 对战阶段
85
+
86
+ 1. 行动阶段划分
87
+
88
+ 1. 定缺阶段、换三张阶段、行牌阶段
89
+
90
+ 2. 定缺阶段
91
+
92
+ 1. 胡牌时,手牌中不能超过2门花色
93
+
94
+ 2. 开局时玩家需要选择一门花色定为缺牌,摸到这门花色的牌一定要打出,对局中不可更改缺
95
+
96
+ 3. 换三张阶段
97
+
98
+ 1. 发完手牌后,每位玩家选择3张同花色的牌,随机与其他一位玩家交换
99
+
100
+ 2. 手牌除主花色外,其余2种花色张数均小于3张时,触发好牌不换,本局不参与换牌,其他玩家继续换牌
101
+
102
+ 3. 结算阶段
103
+
104
+ 1. 胡牌规则
105
+
106
+ 1. 可以点炮胡、抢杠胡、一炮多响
107
+
108
+ 2. 每局可有多个玩家胡牌,有玩家胡牌后,牌局继续,直到第3个玩家胡牌或摸完所有的牌,牌局结束
109
+
110
+ 3. 已胡牌的玩家不再参与牌局,可自由离开
111
+
112
+ 2. 封顶限制
113
+
114
+ 1. 无起胡倍数限制
115
+
116
+ 2. 麻友、大师封顶为4番,巅峰场封顶为5番,王者场巅峰场封顶为6番,即十八罗汉为封顶,1000000倍
117
+
118
+ 3. 摸完所有手牌时,未听牌、花猪玩家需要接受额外惩罚
119
+
120
+ 1. 查花猪 → 查大叫,同环节金流同时结算,钱不够按胡牌倍数比例分
121
+
122
+ 2. 查花猪:打出最后一张牌后,未胡牌的玩家先参与查花猪,手牌有三门花色的玩家为花猪,花猪玩家赔给其他非花猪玩家每人封顶倍
123
+
124
+ 3. 查大叫:打出最后一张牌后,未听牌玩家赔给听牌未胡玩家最大可能倍数(不包含自摸倍数)
125
+
126
+ 4. 结算公式
127
+
128
+ 1. 失败的玩家消耗的金币数量=总的番数\*房间底分-进房收取的金币数
129
+
130
+ 2. 胜利的玩家消耗的金币数量=总的番数\*房间底分+进房收取的金币数
.cache/6d3dd629f7c1e6ebad53764273569ef1.cache ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 红中麻将
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 红中麻将
6
+
7
+ 2. 玩家玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各四张,1-9条各四张,1-9筒各四张,四张红中,共112张牌
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 行牌规则
36
+
37
+ 1. 可碰牌、杠牌,不可以吃
38
+
39
+ 2. 胡牌规则
40
+
41
+ 1. 胡牌只能自摸或者抢杠
42
+
43
+ 2. 单吊红中时,可以胡已有的碰牌,如已碰3筒,单吊红中可以胡3筒
44
+
45
+ 3. 庄家起手4个红中算天胡,不算鸿运当头
46
+
47
+ 4. 一炮多响时,不扎鸟
48
+
49
+ 3. 名词定义
50
+
51
+ | **名词** | **定义** |
52
+ | --- | --- |
53
+ | 红中 | 癞子,胡牌时可充当任意牌 |
54
+ | 鸿运当头 | 特殊番型,起手4个红中可直接胡牌 |
55
+ | 满堂红 | 特殊番型,对局过程中摸到4个红中可胡牌 |
56
+ | 飘分 | 一个加倍操作 |
57
+ | 扎鸟 | 玩家胡牌后,从另一副牌翻8张牌,翻出的牌张有序数1、5、9或红中,视为中鸟,每中1鸟,胡牌得分额外加1倍。<br>若翻出的牌都没中鸟,视为全中,特殊扎鸟规则:一鸟不中,等于全中 |
58
+
59
+ 4. 红中牌规则
60
+
61
+ 1. 红中可打出,每打出1张,当局输赢的胡分翻倍
62
+
63
+ 2. 红中不能出现在碰牌中,起手摸到4张红中时不能碰
64
+
65
+ 3. 4张红中不能杠,起手摸到4张红中时不能杠
66
+
67
+ 5. 倍数说明
68
+
69
+ 1. 番型倍数
70
+
71
+ | **番型** | **倍数** | **说明** |
72
+ | --- | --- | --- |
73
+ | 平  胡 | 1 | 成牌时由4个刻子或顺子加对子组成 |
74
+ | 碰碰胡 | 2 | 成牌时有4种刻牌外加1个对子 |
75
+ | 金钩钓 | 3 | 成牌时其他牌都被碰、杠掉,手牌只剩一张牌单吊胡牌 |
76
+ | 七  对 | 3 | 成牌时由7个对子组成 |
77
+ | 龙七对 | 4 | 成牌时由5个对子和4个相同的牌组成 |
78
+ | 清一色 | 4 | 成牌时所有牌都由筒、条、万中的1种组成 |
79
+ | 清  碰 | 6 | 清一色+碰碰胡 |
80
+ | 清金钩钓 | 7 | 清一色+金钩钓 |
81
+ | 清七对 | 7 | 清一色+七对 |
82
+ | 清龙对 | 10 | 清一色+龙七对 |
83
+ | 满堂红 | 15 | 玩家手中有4张红中 |
84
+ | 鸿运当头 | 25 | 玩家起手4张红中 |
85
+ | 地胡 | 20 | 没有玩家吃、碰、杠的前提下,闲家摸第一张后胡牌 |
86
+ | 天胡 | 20 | 庄家起手直接胡牌 |
87
+
88
+ 2. 胡牌操作倍数
89
+
90
+ | **事件** | **倍数** | **说明** |
91
+ | --- | --- | --- |
92
+ | 自摸 | 1 | 胡牌玩家手牌牌型基础上加1番 |
93
+ | 杠炮 | 1 | 胡牌玩家手牌牌型基础上加1番 |
94
+ | 抢杠 | 1 | 胡牌玩家手牌牌型基础上加1番 |
95
+ | 杠上开花 | 2 | 杠开玩家手牌牌型基础上加2番 |
96
+ | 海底捞 | 2 | 海底捞玩家手牌牌型基础上加2番 |
97
+
98
+ 3. 额外加倍方式
99
+
100
+ | **事件** | **倍数** | **说明** |
101
+ | --- | --- | --- |
102
+ | 硬胡 | 1 | 胡牌时玩家手中没有红中 |
103
+ | 飞红中 | 2 | 每打出过1张红中,胡分输赢翻倍 |
104
+
105
+ 4. 飘分倍数
106
+
107
+ 1. 发牌前,所有玩家可以进行选择不同的飘分数值
108
+
109
+ 2. 飘几分,加几倍
110
+
111
+ 5. 扎鸟倍数
112
+
113
+ 1. 每中1只鸟加1倍
114
+
115
+ 2. 一炮双响不扎鸟
116
+
117
+ 3. 天胡、地胡、鸿运当头、满堂红番型不扎鸟
118
+
119
+ 2. 行牌阶段 
120
+
121
+ 1. 庄家先出牌
122
+
123
+ 2.   判定是否碰、杠、胡
124
+
125
+ 1.   否,按逆时针顺序确定下家,庄家下家摸打;
126
+
127
+ 2.   是,执行碰、杠、胡操作;
128
+
129
+ 3.   按逆时针顺序摸打,直到某个玩家胡牌;
130
+
131
+ 4.   直到牌山摸完或者有玩家胡牌,牌局结束
132
+
133
+ 3. 结算阶段
134
+
135
+ 1. 结算公式
136
+
137
+ 1. 杠分结算+胡分结算
138
+
139
+ 2. 每个玩家与其他三个玩家独立结算
140
+
141
+ 2. 杠分结算
142
+
143
+ 1. 杠分即时结算,不会退回
144
+
145
+ 2. 暗杠结算
146
+
147
+ 1. 暗杠玩家向其他3人收取相同分数
148
+
149
+ 2. 每个暗杠每人收分=基数\*2
150
+
151
+ 3. 补杠结算
152
+
153
+ 1. 补杠玩家向其他三人收取相同分数
154
+
155
+ 2. 每人补杠每人收分=基数\*1
156
+
157
+ 4. 明杠结算
158
+
159
+ 1. 明杠玩家只向点杠玩家收取分数
160
+
161
+ 2. 收分=基数\*3
162
+
163
+ 3. 倍数结算
164
+
165
+ 1. 胡自摸
166
+
167
+ 1. 胡牌玩家赢分=三个玩家输分之和
168
+
169
+ 2. 其他三人输分=基数\*(番型倍数+胡牌操作倍数+额外加倍倍数+扎鸟倍数)
170
+
171
+ 2. 胡炮胡
172
+
173
+ 1. 胡牌玩家赢分=点炮玩家输分=基数\*(番型倍数+胡牌操作倍数+额外加倍倍数+扎鸟倍数)
.cache/70e7d1abaf85c9b17988d32c0bd44fc3.cache ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 麻将机制说明
2
+
3
+ * 创新机制
4
+
5
+
6
+ | 目的 | 机制 |
7
+ | --- | --- |
8
+ | 加快玩家胡牌节奏 | 增设赖子牌,可代替任意牌/摸三打三/一炮多响/抢杠胡/限制胡牌倍数,玩家达到封顶倍数的牌型后会尽快胡牌 |
9
+ | 促进玩家做高倍数的大牌 | 限制起胡倍数/增加番型的倍数/加入功能牌,触发加倍功能/平胡只能自摸 |
10
+ | 鼓励玩家积极进攻 | 血战到底,一局能有三家胡牌,增大了赢局概率/定缺花色,胡牌前必须打出所有定缺花色的牌/查大叫:打出最后一张牌后,未听牌玩家赔给听牌未胡玩家最大可能倍数(不包含自摸倍数)/退税:打出最后一张牌后,未听牌玩家,退回全部杠牌所得 |
11
+ | 增强社交性 | 2v2,组队玩家信息共享 |
12
+ | 增强游戏的趣味性 | 加入功能牌,触发连续摸牌的功能/打出两张相同牌触发三选一/生肖麻将中点亮百景图可增加倍数 |
13
+ | 鼓励玩家尽早听牌 | 捉鸡:若在整个牌局第一次胡牌之后未听啤,需要结算鸡牌 |
14
+ | 增加单局最大输赢 | 抓码/扎鸟/买马/赖子杠倍数×10/明牌倍数×6/破封,突破倍数上限/漂分 |
15
+ | 保护小持币量玩家 | 限制封顶倍数和金币 |
16
+ | 增强游戏的策略博弈 | 与系统或其他玩家换牌/选择出牌参与比牌/玩家胡牌后无法继续飞赖子和点亮生肖/海底漫游:最后一张牌为海底牌,此时玩家可依次选择是否要这张牌/合肥麻将中的海捞阶段(不同于海底捞月番型):牌桌上仅剩最后4张未抓的牌时,放入“海捞区”,四家从“海捞区”各抓一张牌放入手牌中,从第一个摸牌玩家逆时针开始,如果有一个玩家胡牌,则停止海捞,进入结算。/玩家胡牌后无法继续飞赖子和点亮生肖/暴击:同类牌型,倍数大的玩家胜,胜者对败者触发 “暴击”,赢取额外的金币。 |
17
+
18
+ * 基础逻辑
19
+
20
+
21
+ | | 说明 |
22
+ | --- | --- |
23
+ | 摸牌-打牌循环 | 玩家轮流 “摸 1 张牌→打 1 张牌” 的基础节奏,除吃碰杠后仅需打牌、无需摸牌的情况。 |
24
+ | 手牌数量 | 标准起手牌为13张。玩家回合内摸牌后变为 14 张,打牌后回到 13 张。 |
25
+ | 吃碰杠和胡牌的优先级 | 同一轮中,胡牌>碰牌>杠牌>吃牌。仅能吃上家牌,碰 / 杠可对任意玩家。 |
26
+ | 胡牌的触发条件 | 需通过 “自摸”(自己摸牌凑成胡牌型)或 “点炮”(吃进其他玩家打出的牌)胡牌,这是胡牌的两种核心方式 |
27
+ | 玩家的行牌顺序 | 玩家按庄家-下家-对家-上家的顺序依次行牌。若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变。若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变。 |
.cache/895eeee552d81a755b71d2aaccc36998.cache ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 山西扣点麻将
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 山西扣点麻将
6
+
7
+ 2. 玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各四张、1-9条各四张、1-9筒各四张,共136张牌
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 名词定义
36
+
37
+ 1. 扣点:胡x万/筒/条,扣点是x,胡字牌,扣点10点
38
+
39
+ 2. 耗子牌:癞子,胡牌时可充当任意牌
40
+
41
+ 3. 捉耗子:勾选后,随机选择一张牌作为耗子
42
+
43
+ 4. 风耗子:勾选后随机选择一张风牌作为耗子
44
+
45
+ 5. 风嘴子:勾选后东南西北任意三风算一顺(如东南西、东南北、南西北、东西北),中发白算一顺
46
+
47
+ 6. 摸五胡六:勾选后,1、2、3、4点不能自摸也不能炮胡,5点只能自摸,6点及以上可自摸可炮胡
48
+
49
+ 2. 行牌规则
50
+
51
+ 1. 碰牌
52
+
53
+ 1. 耗子牌不能出现在碰牌中
54
+
55
+ 2. 杠牌
56
+
57
+ 1. 四张耗子牌可以杠
58
+
59
+ 3. 报听
60
+
61
+ 1. 听口中存在扣点≥6的听口,可以报听
62
+
63
+ 3. 胡牌规则
64
+
65
+ 1. 听口的扣点≥6,才可以胡炮胡
66
+
67
+ 2. 听口的扣点≥3,才可以胡自摸
68
+
69
+ 3. 可以过胡,过胡后,下一次摸牌前不能胡相同的听口
70
+
71
+
72
+ 1. 番型及倍数
73
+
74
+ 1. | **番型** | **倍数** | **说明** |
75
+ | --- | --- | --- |
76
+ | 平胡 | 1 | 普通的四种刻牌或顺子外加一对将牌 |
77
+ | 一条龙 | 2 | 胡牌牌型中有同一花色的1-9组成的123,456,789的三个顺子 |
78
+ | 清一色 | 2 | 胡牌牌型全部一个花色 |
79
+ | 七对 | 2 | 胡牌牌型是七个对子 |
80
+ | 豪华七对 | 4 | 七小对牌型中有4张相同牌 |
81
+ | 黄金七对 | 8 | 七小对牌型中有2组4张相同牌 |
82
+ | 十三幺 | 8 | 由19万,19条,19筒及东南西北中发白各1张,外加13张牌中任意一张组成的胡牌 |
83
+ | 豪华黄金七对 | 16 | 七小对牌型中有3组4张相同牌 |
84
+
85
+ 2. 番型倍数统计规则
86
+
87
+ 1. 胡牌时,若同时存在多种番型,番型倍数可以叠加,按乘法计算
88
+
89
+ 2. 事件倍数
90
+
91
+
92
+ | **事件** | **倍数** | **说明** |
93
+ | --- | --- | --- |
94
+ | 自摸 | 2 | 自摸胡牌 |
95
+ | 杠炮 | 2 | 杠后打出的牌放炮 |
96
+ | 抢杠 | 2 | 杠第四张牌时,被抢杠胡牌 |
97
+
98
+ 2. 行牌阶段
99
+
100
+ 3. 结算阶段
101
+
102
+ 1. 结算公式
103
+
104
+ 1. 每个玩家得分\=杠分结算+倍数结算
105
+
106
+ 2. 每个玩家与其他3个玩家独立结算
107
+
108
+ 2. 杠分结算
109
+
110
+ 1. 暗杠结算
111
+
112
+ 1. 暗杠玩家向其他3人收取相同分数
113
+
114
+ 2. 每个暗杠收分和杠的扣点有关
115
+
116
+ 3. 每人收分\=基数\*暗杠扣点\*2
117
+
118
+ 2. 补杠结算
119
+
120
+ 1. 补杠玩家向其他3人收取相同分数
121
+
122
+ 2. 每个补杠收分和杠的扣点有关
123
+
124
+ 3. 每人收分\=基数\*补杠扣点\*1
125
+
126
+ 3. 明杠结算
127
+
128
+ 1. 点杠玩家在报听前点炮
129
+
130
+ 1. 明杠玩家只向点杠玩家收取分数
131
+
132
+ 2. 每个明杠收分和杠的扣点有关
133
+
134
+ 3. 明杠收分\=基数\*明杠扣点\*3
135
+
136
+ 2. 点杠玩家在报听后点炮
137
+
138
+ 1. 明杠玩家向其他3人收取相同分数
139
+
140
+ 2. 每个明杠收分和杠��扣点有关
141
+
142
+ 3. 每人收分\=基数\*明杠扣点\*1
143
+
144
+ 3. 倍数结算
145
+
146
+ 1. 胡自摸
147
+
148
+ 1. 胡牌玩家赢分\=3个玩家输分之和
149
+
150
+ 2. 其他3人输分\=基数\*番型倍数\*事件倍数
151
+
152
+ 2. 胡炮胡
153
+
154
+ 1. 点炮玩家未报听
155
+
156
+ 1. 胡牌玩家赢分\=点炮玩家输分\=基数\*番型倍数\*事件倍数\*3
157
+
158
+ 2. 不存在事件倍数时,事件倍数\=1
159
+
160
+ 2. 点炮玩家报听
161
+
162
+ 1. 胡牌玩家赢分\=其他3个玩家输分
163
+
164
+ 2. 其他3人输分\=基数\*番型倍数\*事件倍数
165
+
166
+ 3. 不存在事件倍数时,事件倍数\=1
.cache/89b4366d3e4aafe8626efd543517da1c.cache ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 广东100张
2
+
3
+ 1. **玩法名称**
4
+
5
+ 1. **广东100张**
6
+
7
+ 2. **玩家玩家**
8
+
9
+ 1. **总人数**
10
+
11
+ 1. **4人**
12
+
13
+ 2. **编号**
14
+
15
+ 1. **庄家记为:A1**
16
+
17
+ 2. **下家记为:A2,对家记为:A3,上家记为:A4**
18
+
19
+ 3. **行动模式**
20
+
21
+ 1. **依次行动:(A1, A2, A3, A4)**
22
+
23
+ 2. **若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变**
24
+
25
+ 3. **若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变**
26
+
27
+ 4. **游戏所需设备**
28
+
29
+ 1. **1-9条各四张,1-9筒各四张,无万牌,东南西北中发白各4张,共计100张牌**
30
+
31
+ 5. **规则描述**
32
+
33
+ 1. **准备阶段**
34
+
35
+ 1. **行牌规则**
36
+
37
+ 1. **可碰杠、不可吃**
38
+
39
+ 2. **鸡胡只能自摸胡牌**
40
+
41
+ 3. **有鬼牌,鬼牌即万能牌,不可打出,也不可参与碰杠**
42
+
43
+ 2. **鬼牌**
44
+
45
+ 1. **分为定鬼和翻鬼,鬼牌为万能牌。鬼牌不允许打出,也不可参与碰,杠**
46
+
47
+ 2. **翻鬼:开局翻一张牌,其点数+1为鬼牌;****东南西北中发白为一组,翻出北则中为鬼牌,翻出白则东为鬼牌。**
48
+
49
+ 3. **买马**
50
+
51
+ 1. **有人胡牌后,会进行买马流程。流局不买马。**
52
+
53
+ 2. **买马人分为4人买马,胡牌买马。**
54
+
55
+ 3. **每人买马:每个玩家固定买2马,买中赢家或者输家,同赢同输**
56
+
57
+ 4. **跟庄**
58
+
59
+ 1. **开局庄家打出第一张牌,其他三名玩家都打出一样的牌,则庄家需支付闲家各一倍基数。即时结算,流局不退回,不算马分。**
60
+
61
+ 5. **杠分规则**
62
+
63
+ 1. **开杠后直接得分,即时飘分结算。**
64
+
65
+ 2. **可以开直杠不开而选择碰,那么不能立即杠。当局可以再补杠,这样补杠****不收分。能补杠不及时补杠也不收分。**
66
+
67
+
68
+ | **番型** | **简述** | **倍数** |
69
+ | --- | --- | --- |
70
+ | **点杠** | **收取放杠的玩家3分** | **3** |
71
+ | **补杠** | **收取每个玩家1分** | **1** |
72
+ | **暗杠** | **收取每个玩家2分** | **2** |
73
+
74
+ 6. **胡牌牌型及倍数**
75
+
76
+ 1. **操作类番型**
77
+
78
+ 1. | **番型** | **简述** | **倍数** |
79
+ | --- | --- | --- |
80
+ | **自摸** | **自己摸到牌胡牌** | **1** |
81
+ | **点炮** | **胡别人打出的牌,鸡胡不允许点炮胡,允许一炮多响** | **1** |
82
+ | **杠开** | **开杠后补牌正好胡牌。** | **2** |
83
+ | **抢杠胡** | **胡的那张牌正好是其他玩家补杠的牌,由补杠的玩家承包3家买马分** | **3** |
84
+
85
+ 2. **操作类番型和牌型类番型叠加为相乘**
86
+
87
+ 2. **牌型类番型**
88
+
89
+ 1. **除了无鬼能和其他番型叠加,所有牌型类番型之间都不叠加,只取最大的番型。包括七对,天地胡也不和任意牌型叠加。**
90
+
91
+ 2. **同一样番数的番型优先级按表格定,1最大,4最小。**
92
+
93
+
94
+ | **番型** | **简述** | **倍数** | **同番数优先级** |
95
+ | --- | --- | --- | --- |
96
+ | **鸡胡** | **4副顺子/刻子+1副将,其中顺子和刻子数都需要大于等于1。胡牌时手牌和副露条筒数大于等于1。** | **2** | |
97
+ | **平胡** | **4副顺子+1副将** | **3** | |
98
+ | **混一色** | **胡牌时手牌和副露是条筒其中一种花色加上字牌** | **4** | **1** |
99
+ | **碰碰胡** | **4副刻子/杠+1副将** | **4** | **2** |
100
+ | **七对** | **七个不一样的对子** | **8** | **1** |
101
+ | **清一色** | **胡牌时手牌和副露由单一条/筒组成** | **8** | **2** |
102
+ | **混碰** | **碰碰胡+混一色** | **8** | **3** |
103
+ | **豪华七对** | **七对中有1组一样的对子** | **12** | **1** |
104
+ | **混幺九** | **胡牌时手牌和副露只由幺九牌组成,1,9牌总数大于1.** | **12** | **2** |
105
+ | **清碰** | **碰碰胡+清一色** | **12** | **3** |
106
+ | **四鬼** | **4张鬼牌可以直接胡牌(非必胡)** | **18** | **1** |
107
+ | **小三元** | **中发白2副刻子/杠1副将+任意2副顺子/刻子** | **18** | **2** |
108
+ | **小四喜** | **东南西北3副刻子/杠1副将+任意顺子/刻子** | **18** | **3** |
109
+ | **天胡** | **庄家起手14张牌直接胡牌(不可暗杠)必胡** | **24** | **1** |
110
+ | **地胡** | **闲家胡自己摸的第一张牌(自己不可碰,杠)必胡** | **24** | **2** |
111
+ | **双豪华七对** | **七对中有2组一样的对子** | **24** | **3** |
112
+ | **字一色** | **胡牌时手牌和副露由单一字牌组成** | **24** | **4** |
113
+ | **大三元** | **中发白3副刻子/杠+1副将+1副顺子/刻子** | **32** | **1** |
114
+ | **大四喜** | **东南西北4副刻子/杠+1副将** | **32** | **2** |
115
+ | **三豪华七对** | **七对中有3组一样的对子** | **36** | **1** |
116
+ | **十八罗汉** | **胡牌时有4个杠** | **36** | **2** |
117
+
118
+ 3. **额外加番番型**
119
+
120
+ 1. **无鬼** 
121
+
122
+ 1.  **如果胡牌时手牌中没有鬼牌,则胡牌倍数x2**   
123
+
124
+ 7. **流局规则**
125
+
126
+ 1. **牌墙摸完则流局,流局不买马,杠分,跟庄分不会退回,无查叫。**
127
+
128
+ 8. **抢杠胡规则**
129
+
130
+ 1. **抢杠胡基础倍数按****3****算,被抢杠玩家一人出。其他玩家买中赢家正常赢马,买中输家则被抢杠玩家一人出。**
131
+
132
+ 9. **其他规则**
133
+
134
+ 1.      **过胡:在某位玩家听牌的情况下,同一轮牌中第一张出现的点炮牌他未选择胡,在其未摸牌前,又有玩家打出相同的牌张,则此时他不能胡牌。**
135
+
136
+ 2.   **承包与买马:先算完每个玩家的分数,最后再承包。例如A自摸胡牌,B承包了,买马买中C算输马。**
137
+
138
+ 3.   **碰后,只允许出牌操作,不允许进行杠操作;**
139
+
140
+ 4. **碰后如果只剩鬼牌则不允许玩家碰。**
141
+
142
+ 5. **胡任意胡时只能自摸,不能点炮胡。**
143
+
144
+ 6. **手上全是鬼牌时必胡。**
145
+
146
+ 2. **行牌阶段**
147
+
148
+
149
+ 1.   **庄家先出牌**
150
+
151
+ 2.   **判定是否碰、杠、胡**
152
+
153
+ 1.   **否,按逆时针顺序确定下家,庄家下家摸打;**
154
+
155
+ 2.   **是,执行碰、杠、胡操作;**
156
+
157
+ 3.   **按逆时针顺序摸打,直到某个玩家胡牌;**
158
+
159
+ 4.   **直到牌山摸完或者有玩家胡牌,牌局结束**
160
+
161
+ 1. **结算阶段**
162
+
163
+ 1. **结算规则**
164
+
165
+ 1. **没有胡牌的玩家,也会计算杠分。**
166
+
167
+ 2. **结算分数=基数\*(胡牌倍数+买马倍数+杠分+跟庄分),放炮输家独给,自摸三家给。**
168
+
169
+ 2. **买马规则**
170
+
171
+ 1. **有人胡牌后,会进行买马流程。流局不买马。**
172
+
173
+ 2. | **类型** | **简述** | **备注** |
174
+ | --- | --- | --- |
175
+ | **马跟底分** | **默认4家买马,每人2马,使用另外一副牌买马不占用牌堆**<br>* **有胡牌才会进行买马,流局不买马**<br> <br>* **位置与点数对应关系固定如下:**<br> <br>**庄家:1、5、9、东**<br>**庄家下家:2、6、南、中**<br>**庄家对家:3、7、西、发**<br>**庄家上家:4、8、北、白**<br>**3.马牌买中对应的玩家同赢同输(只算胡牌分,跟庄分,不算杠分)**<br>**例如庄家自摸鸡胡,每人赢2倍,庄家下家买马是4条,1万,那么4条就是买中了庄家上家,输2倍,1万则买中了庄家,赢4倍(6-2),总的庄家下家就是不赢不输。** | **金币场翻8马时,先去掉4张9筒或者9条再随机开马,避免庄家优势。** |
176
+
177
+ 3. **结算时开马展示规则**
178
+
179
+ 1. **单个马牌的赢马和输马标签是按照实际输赢情况展示,例如,****A****玩家自摸,买中了****B****玩家,此时马会展示为不赢不输,无标签。****A****玩家放炮给****C****,****A****玩家买马买中了****C****,此时马会展示为不赢不输。**
180
+
181
+ 2. **最下方的总的赢马输马计算规则也按总的输赢情况展示,例如****A****玩家一炮多响给****B****,****C****玩家,****D****玩家一批马买中了****A****,一批马买中了****B****,那么他的总输赢为负,总的会显示输马。**
182
+
183
+ 3. **承包情况也按马对单个玩家的输赢情况展示,如果****A****承包了,那么****C****买中****A****,此时这批马展示为不赢不输。因为****C****实际上不输不赢,****A****出了所有费用**
184
+
185
+ 3. **12张落地承包**
186
+
187
+ 1. **B已经碰/杠3次,A放了B第4次,若B自摸则A承包所有输分(不含杠分、跟庄分)**
188
+
189
+ 2. **暗杠也算一次落地,如果第四次落地的是暗杠那么不会有人承包。**
190
+
191
+ 3. **计算马分时,基础胡分为A输B3倍胡牌分,C,D无输赢。例如B自摸平胡,则基础胡分为A输B 6分**
192
+
193
+ 4. **杠爆全包**
194
+
195
+ 1. **A给B点杠,B杠上开花胡牌,A包3家所有输分(不含杠分、跟庄分)**
196
+
197
+ 2. **如果B杠了后再杠,杠上开花,则不算杠爆。**
198
+
199
+ 3. **计算马分时,基础胡分为A输B3倍胡牌分,C,D无输赢。例如B杠开平胡,则基础胡分为A输B 12分。**
.cache/8ba0a7d9927d748478d8fac4163af8aa.cache ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 武汉麻将
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 武汉麻将
6
+
7
+ 2. 玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各四张,1-9条各四张,1-9筒各四张,字牌(东西南北中发白)各四张
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 名词定义
36
+
37
+ | 名词 | 定义 |
38
+ | --- | --- |
39
+ | 开口 | 吃、碰、明杠称为开口 |
40
+ | 皮子 | 1. 开局前,庄家随机从牌堆中翻出1张牌,该牌及该牌点\-1的牌就叫做皮子<br> <br>2. 序数牌的顺序为1→2→3→4→5→6→7→8→9→1<br> <br>3. 字牌的顺序为东→南→西→北→中→发→白→东<br> <br>4. 红中默认也是皮子,如果翻开的牌是中则西、北是皮子 |
41
+ | 赖子 | 1. 开局前,随机从牌堆中翻出1张牌,该牌+1的牌就是“赖子”<br> <br>2. 序数牌的顺序为1→2→3→4→5→6→7→8→9→1<br> <br>3. 字牌的顺序为东→南→西→北→中→发→白→东<br> <br>4. 红中默认是皮子不能成为赖子,翻出红中需跳过,发财为赖子,西风、北风为皮子;翻出北,则发是赖子<br> <br>5. 赖子是万能牌,但是不能当作皮子使用<br> <br>6. 赖子不能与其它牌组合进行吃、碰、杠操作<br> <br>7. 赖子能作为第五张牌(自己手牌里)使用 |
42
+ | 皮子杠 | 每打出1张皮子可以作1个杠 |
43
+ | 赖子杠 | 每打出1张赖子可以作1个杠 |
44
+ | 口口番 | 一种倍数计算方式,开口数量影响倍数,每次开口加1番 |
45
+ | 开口番 | 区别于口口番,这个规则下皮子只有红中,翻出牌+1为赖子。但只有第一次开口+1番,第一次明杠或补杠在开口基础上再+1番,暗杠在开口基础上+2番,之后再有吃碰杠行为不做叠加,番数如下:<br>a.首次吃、碰+1番,后续再进行吃、碰行为不叠加番数<br>b.首次直杠,若为首次开口行为,则+2番,后续再进行直杠、补杠行为不叠加番数<br>c.首次补杠,在之前吃、碰开口行为基础上+1番,若之前已有过直杠行为,则不再叠加番数<br>d.首次暗杠,若之前未有开口行为,则+2番,若之前有过吃、碰行为,则+2番,若之前有过直杠、补杠行为,则+1番,暗杠需叠加开口番数,但对于其他吃碰杠番数不叠,后续再进行暗杠行为不叠加番数<br>e.红中杠,每打出一次+1番,可叠加<br>f.赖子杠,每打出一次+2番,可叠加 |
46
+
47
+ 2. 操作规则
48
+
49
+ 1. 摸打
50
+
51
+ 1. 皮子、赖子可以打出
52
+
53
+ 2. 剩余四张牌时,不允许明杠、补杠、暗杠、皮子杠、赖子杠,需要保留海底牌(此时赖皮杠只能打出后不补牌,不受设置限制)
54
+
55
+ 2. 吃
56
+
57
+ 1. 皮子、赖子不能出现在吃牌中
58
+
59
+ 3. 碰
60
+
61
+ 1. 皮子、赖子不能出现在碰牌中
62
+
63
+ 4. 杠
64
+
65
+ 1. 4张皮子不能杠
66
+
67
+ 2. 4张赖子不能杠
68
+
69
+ 3. 每打出1张皮子可以作1个杠
70
+
71
+ 4. 每打出1张赖子可以作1个杠
72
+
73
+ 5. 牌堆剩余4张牌时,不能进行明杠、暗杠、补杠操作
74
+
75
+ 6. 吃碰后可直接补杠或者暗杠
76
+
77
+ 3. 记分规则
78
+
79
+ 1. **番型分值**
80
+
81
+ | **小胡** | **分值** | **说明** |
82
+ | --- | --- | --- |
83
+ | 平胡 | 1 | 由4个刻子或顺子加将牌组成,需要258做将 |
84
+
85
+ | **大胡** | **分值** | **说明** |
86
+ | --- | --- | --- |
87
+ | 碰碰胡 | 10 | 由4个刻子或杠牌加将牌组成 |
88
+ | 风一色 | 10 | 手中全是东南西北中发白,无需成牌 |
89
+ | 将一色 | 10 | 手中全是2、5、8,无需成牌 |
90
+ | 清一色 | 10 | 胡牌牌型只有万条筒中的一种花色 |
91
+ | 全求人 | 10 | 吃/碰/明杠4次,手上剩1张牌抓炮/抢杠,需258做将 |
92
+ | 多个大胡同时存在时,每多1个大胡,胡牌玩家的番数+1番 | | |
93
+
94
+ 2. 事件分值
95
+
96
+ | **事件** | **分值** | **说明** |
97
+ | --- | --- | --- |
98
+ | 抢杠胡 | 10 | 补杠时,其他玩家可以抢杠胡牌 |
99
+ | 杠上花 | 10 | 杠后(包括皮子、赖子杠)补牌自摸 |
100
+ | 海底捞 | 10 | 牌底最后4张牌自摸 |
101
+
102
+ 3. 杠牌番数
103
+
104
+ | **类型** | **番数****/****个** | **说明** |
105
+ | --- | --- | --- |
106
+ | 明杠 | 1 | 杠的数量可以累加番数 |
107
+ | 补杠 | 1 |
108
+ | 暗杠 | 2 |
109
+ | 皮子杠 | 1 |
110
+ | 赖子杠 | 2 |
111
+
112
+ 4. 额外番数
113
+
114
+
115
+ | **类型** | **番数** | **说明** |
116
+ | --- | --- | --- |
117
+ | 开口 | 1 | 每次开口(吃/碰/明杠)均增加1倍,可叠 |
118
+ | 自摸 | 1 | 自摸胡牌加倍 |
119
+ | 点炮 | 1 | 点炮者结算加倍 |
120
+ | 庄 | 1 | 庄家小胡时加倍,大胡不加 |
121
+ | 硬胡 | 1 | 胡牌时没有赖子或只有一张赖子作本身使用可加倍 |
122
+ | 大胡叠加 | 1 | 胡牌玩家每多一个大胡加1倍 |
123
+ | 明杠 | 1 | 每个明杠1倍,可叠开口倍数 |
124
+ | 补杠 | 1 | 每个补杠1倍 |
125
+ | 暗杠 | 2 | 每个暗杠2倍 |
126
+ | 皮子杠 | 1 | 每个皮子杠1倍 |
127
+ | 赖子杠 | 2 | 每个赖子杠2倍 |
128
+
129
+ 4. 封顶规则
130
+
131
+ 1. 小胡10番封顶,大胡7番封顶
132
+
133
+ 2. 封顶:1个或2个玩家输分倍数超过1000倍,均按1000倍计算
134
+
135
+ 3. 金顶:3个玩家输分倍数都封顶,均按1500倍计算
136
+
137
+ 4. 阳光顶:如果有玩家未开口且未存在皮子杠、赖子杠,均按3000倍计算
138
+
139
+ 5. 三阳开泰:如果3个玩家均未开口且未存在皮子杠、赖子杠,均按6000倍计算
140
+
141
+ 5. 翻倍规则
142
+
143
+ 1. 未开口且没有杠皮子、杠赖子、暗杠的玩家,输分\*2(非金顶时);
144
+
145
+ 2. 连赖翻倍:如果本局与上局的赖子相同,则本局所有输分玩家输分\*2;
146
+
147
+ 3. 见风连赖:如果本局赖子为风牌、箭牌,则本局所有输分玩家输分\*2;
148
+
149
+ 4. 连赖翻倍和见风连赖如果同时发生也只翻倍1次,本局所有输分玩家输分\*2;
150
+
151
+ 5. 连金规则:如果A第一局金顶,第二局也金顶,则第二局其他玩家输分\*2,连续多次连金只按连一次计算;
152
+
153
+ 6. 返金规则:如果A第一局金顶,第二局B胡金顶,则A玩家输分\*2。
154
+
155
+ 6. 其他规则
156
+
157
+ 1. 同时存在多种番型时,可以叠,规则为相加
158
+
159
+ 2. 连金或返金时,先算倍数封顶,再算输分翻倍
160
+
161
+ 7.  胡
162
+
163
+ 1. 胡牌条件
164
+
165
+ 1. 必须开口,不能门清
166
+
167
+ 2. 必须无皮子,皮子需全部打出
168
+
169
+ 3. 除风一色、将一色、清一色、碰碰胡外,其他牌型必须存在2、5、8的任意1将
170
+
171
+ 4. 小胡6番起胡,大胡3番起胡
172
+
173
+ 2. 胡牌方式
174
+
175
+ 1. 可点炮、自摸,不可一炮多响,只能截胡
176
+
177
+ 3. 胡牌规则
178
+
179
+ 1. 听口是任意牌时,只能自摸或抢杠胡
180
+
181
+ 2. 不能胡他人打出的赖子
182
+
183
+ 3. 手牌中赖子数量≥2时不能胡小胡
184
+
185
+ 4. 不存在一炮多响
186
+
187
+ 5. 只有一个赖子,且赖子当原牌张使用时,算硬胡
188
+
189
+ 2. 行牌阶段
190
+
191
+ 3. 结算阶段
192
+
193
+ 1. 基本结算
194
+
195
+ 1. 玩家自摸或炮胡时,其他三家均输分,流局时无结算
196
+
197
+ 2. 胡牌玩家得分\=其他3个玩家输分
198
+
199
+
200
+ 1. 每个玩家输分\=基数\*牌型分\*2^n^
201
+
202
+ 2. 牌型分\=番型分值+事件分值
203
+
204
+ 3. n=该输分玩家与胡牌玩家的番数之和
205
+
206
+
207
+ 1. 承包结算
208
+
209
+ 1. 一种特��结算,存在承包的情况下,玩家胡牌后,可能只有1家输分
210
+
211
+ 2. 下雨定义:如果A玩家已吃、碰、明杠三口同花色牌(三口万、三口筒、三口条)/或三口2、5、8的将牌(玩家最多再吃、碰、杠1次就可以报听清一色、将一色),此时,若其他3个玩家手牌中存在跟玩家A亮明的3口牌同类型的牌时(万/筒/条/258将),必须全部打出,跟打同类牌的这种场景叫下雨
212
+
213
+ 1. 后续游戏中,只要其他3个玩家手中存在同色牌/同将牌,就需要打出
214
+
215
+ 2. 一旦有玩家手中存在同色牌/同将牌,但某回合未打出时,会中断下雨
216
+
217
+ 3. 若已存在某一类型的下雨(万/筒/条/将),该局不会再触发相同类型的下雨
218
+
219
+ 4. 多种类型的下雨同时存在时,可以先选一类型将牌全部打出后,再选其他类型
220
+
221
+ 3. 全求人承包
222
+
223
+ 1. A放炮给B,导致B胡全求人,且A不是“下雨”也不是“全手将牌”(手牌全部是258将牌,且没有皮子、赖子)时,A承包B的所有赢分
224
+
225
+ 4. 未下雨承包
226
+
227
+ 1. 只有A未下雨,导致B胡清一色/将一色,A承包3家输分
228
+
229
+ 2. 多人均未下雨,导致B胡清一色/将一色,则多人承包3家输分,B可以赢多份
230
+
231
+ 5. 三口承包
232
+
233
+ 1. 清一色三口承包:B胡清一色,B的第三次开口是A打的(非下雨),A承包
234
+
235
+ 2. 将一色三口承包:B胡将一色,B的第三次开口是A打的(非下雨),A承包
236
+
237
+ 6. 三口承包和未下雨承包可以同时存在,多人包赔则赢的玩家赢多份
238
+
239
+ 7. 抢杠胡承包:B抢杠胡A,A需承包3家输分
240
+
241
+ 1. A听牌且有多个大胡按多个大胡牌型分计算(有赖子按有赖子算番,硬胡番数+1);A若听风一色被抢杠,需赔付三家满番金顶给B
242
+
243
+ 2. A听牌且是小胡按大胡牌型分(抢杠是大胡牌型)计算(有赖子按有赖子算番,硬胡番数+1)
244
+
245
+ 3. A未听牌按有赖子大胡牌型分(抢杠是大胡牌型)计算
246
+
247
+ 4. 抢杠胡承包和其他承包同时存在时,仅抢杠胡承包使用被抢杠玩家番数计算
.cache/9080a7d7f3a4965ac1b4c5746ba490ef.cache ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 疯狂血流
2
+
3
+ # 疯狂血流
4
+
5
+ 1. 玩法名称:疯狂血流
6
+
7
+ 2.  玩家
8
+
9
+ 1. 总人数:
10
+
11
+ 1.  4人
12
+
13
+ 2. 编号:
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各4张、1-9筒各4张、1-9条各4张,6个红中,共114张牌(王者场为8个红中)
30
+
31
+ 5. 5.规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 行牌规则
36
+
37
+ 1. 可以碰、杠,不可以吃
38
+
39
+ 2. 可以暗杠、明杠和补杠
40
+
41
+ 3. 同一张牌打出时,可以同时被胡牌和碰杠
42
+
43
+ 2. 万能牌
44
+
45
+ 1. 红中视为赖子,可以当做任意牌
46
+
47
+ 2. 红中牌可打出,算红中杠,倍数为10,且补一张牌
48
+
49
+ 3. 可单吊红中胡牌
50
+
51
+ 3. 胡牌番型及倍数
52
+
53
+ 1. 大威天龙:100000  牌型仅由5个同花色序数相连牌组成
54
+
55
+ 2. 万中无双:10000    由13579万组成的胡牌
56
+
57
+ 3. 十八罗汉:10000    牌型中包含4根
58
+
59
+ 4. 绿一色:10000    由23468条组成的胡牌
60
+
61
+ 5. 大车轮:10000    由12468筒组成的胡牌
62
+
63
+ 6. 十二金钗:1000    牌型中包含3根
64
+
65
+ 7. 金钩钓:100    胡牌时,手牌只剩下一张牌单钓胡牌
66
+
67
+ 8. 清一色:100    仅由一种花色组成的牌
68
+
69
+ 9. 四节高:100    包含4个同花色且序数相连的刻(杠)
70
+
71
+ 10. 全双:10    胡牌时,所有手牌点数只有2/4/6/8
72
+
73
+ 11. 碰碰胡:10    由4个刻(杠)和将牌组成的胡牌
74
+
75
+ 12. 全单:10    胡牌时,所有手牌点数只有1/3/5/7/9
76
+
77
+ 13. 三节高:10    包含3个同花色且序数相连的刻(杠)
78
+
79
+ 14. 大于五:10    牌型中所有牌的点数都大于5
80
+
81
+ 15. 小于五:10    牌型中所有牌的点数都小于5
82
+
83
+ 16. 天胡:10000000 庄家起手胡牌
84
+
85
+ 17. 地胡:10000000 非庄家第一轮摸牌就胡牌
86
+
87
+ 4. 其他倍数
88
+
89
+ 1. 杠上开花 10 杠牌后补张胡牌
90
+
91
+ 2. 杠上炮 10  杠牌后,打出的牌给其他玩家点炮
92
+
93
+ 3. 根 10  四张相同即可,不一定非为杠
94
+
95
+ 5. 番型叠加规则
96
+
97
+ 1. 注:红色格子1代表两种番型可叠加,白色格子代表两种番型不叠加
98
+
99
+
100
+ [请至钉钉文档查看附件《疯狂血流番型叠加.xlsx》](https://alidocs.dingtalk.com/i/nodes/QG53mjyd80R7N00AtbpMOywyV6zbX04v?doc_type=wiki_doc&iframeQuery=anchorId%3DX02mhn76jzaukpl0z56x9c)
101
+
102
+ 6. 杠分
103
+
104
+ 1. 疯狂血流玩法不计杠分,无相关金流
105
+
106
+ 7. 初始手牌数量
107
+
108
+ 1. 13张
109
+
110
+ 8. 发牌规则 [请至钉钉文档查看附件《xueliu\_hz3\_v2温暖摸牌.xlsm》](https://alidocs.dingtalk.com/i/nodes/QG53mjyd80R7N00AtbpMOywyV6zbX04v?doc_type=wiki_doc&iframeQuery=anchorId%3DX02mhn51dxrr0z71ylqlbe)
111
+
112
+ 9. 摸牌规则[请至钉钉文档查看附件《疯狂血流摸牌规则.xlsm》](https://alidocs.dingtalk.com/i/nodes/QG53mjyd80R7N00AtbpMOywyV6zbX04v?doc_type=wiki_doc&iframeQuery=anchorId%3DX02mhn51dxra8banfdas6e)
113
+
114
+ 2. 对战阶段
115
+
116
+ 1. 行动阶段划分
117
+
118
+ 1. 定缺阶段、行牌阶段
119
+
120
+ 2. 定缺阶段
121
+
122
+ 1. 胡牌时,手牌中不能超过2门花色
123
+
124
+ 2. 开局时玩家需要选择一门花色定为缺牌,摸到这门花色的牌一定要打出,对局中不可更改缺
125
+
126
+ 3. 行牌阶段
127
+
128
+ 1. 可以碰、杠,不可以吃
129
+
130
+ 3. 结算阶段
131
+
132
+ 1. 胡牌规则
133
+
134
+ 1. 允许点炮、一炮多响,不允许抢杠胡
135
+
136
+ 2. 每局每个玩家可多次胡牌,直到摸完所有牌,牌局结束
137
+
138
+ 3. 胡牌不改变行牌顺序,有人点炮时,点炮者的下家摸牌,避免多次点炮
139
+
140
+ 4. 一牌多用:同一张牌打出时,可以同时被胡牌和碰杠
141
+
142
+ 2. 摸完所有手牌时,未听牌、花猪玩家需要接受额外惩罚
143
+
144
+ 1. 查花猪:打出最后一张牌后,未胡牌的玩家先参与查花猪,手牌有三门花色的玩家为花猪,花猪玩家赔给其他非花猪玩家每人该场次的封顶倍数
145
+
146
+ 2. 查大叫:打出最后一张牌后,未听牌玩家赔给听牌未胡玩家最大可能倍数(不包含自摸倍数)
147
+
148
+ 3. 结算公式
149
+
150
+ 1. 底分:1分
151
+
152
+ 2. 自摸 X 10 :(底分x倍数x10)x 3家
153
+
154
+ 3. 点炮=底分\*倍数
.cache/a72cd6d19b406f34e03bc1908e24d0dc.cache ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 幺鸡血战
2
+
3
+ 1. 玩法名称:幺鸡血战
4
+
5
+ 2. 玩家
6
+
7
+ 1. 总人数:
8
+
9
+ 1. 4人
10
+
11
+ 2. 编号:
12
+
13
+ 1. 庄家记为:A1
14
+
15
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
16
+
17
+ 3. 行动模式:
18
+
19
+ 1. 依次行动(A1,A2,A3,A4)
20
+
21
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
22
+
23
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
24
+
25
+ 4. 游戏所需设备
26
+
27
+ 1. 1-9万各四张,1-9条各四张,1-9筒各四张,共108张牌
28
+
29
+ 5. 规则描述
30
+
31
+ 1. 准备阶段
32
+
33
+ 1. 行牌规则
34
+
35
+ 1. 可以碰、杠,不能吃
36
+
37
+ 2. 可以暗杠、明杠和补杠
38
+
39
+ 3. 同一张牌打出时,可同时被胡牌和碰杠
40
+
41
+ 2. 番型及倍数
42
+
43
+ 1. 基础番型倍数
44
+
45
+ 1.  平胡:1倍
46
+
47
+ 2. 碰碰胡、杠上花、杠上炮、抢杠胡、海底捞、海底炮:2倍
48
+
49
+ 3. 七对、清一色、金钩钓:4倍
50
+
51
+ 4. 龙七对、清碰:8倍
52
+
53
+ 5. 双龙七对、清七对、清金钩钓:16倍
54
+
55
+ 6. 三龙七对、清龙七对:32倍
56
+
57
+ 7. 十八罗汉、清双龙七对:64倍
58
+
59
+ 8.  清三龙七对:128倍
60
+
61
+ 9.  清十八罗汉:256倍
62
+
63
+ 10. 地胡、天胡:封顶
64
+
65
+ 2. 其他倍数
66
+
67
+ 1. 无鸡 胡牌时,手中无幺鸡 2倍
68
+
69
+ 2. 三幺鸡 胡牌时,手中有3个幺鸡 4倍
70
+
71
+ 3. 四幺鸡  胡牌时,手中有4个幺鸡 8倍
72
+
73
+ 4. 杠上花 2倍
74
+
75
+ 5. 杠上炮 2倍
76
+
77
+ 6. 抢杠胡 2倍
78
+
79
+ 7. 根 四张相同即可,不一定非为杠 2倍
80
+
81
+ 8. 海底捞月/炮 2倍 海底炮只需要是打出的最后一张即可
82
+
83
+ 9. 金钩钓 4倍 
84
+
85
+ 3. 幺鸡
86
+
87
+ 1. 幺鸡视为赖子,可以当做任意牌
88
+
89
+ 2. 幺鸡可代替其他牌进行碰、杠操作(必须幺鸡加真实牌参与碰、杠,不允许只用幺鸡进行空碰、空杠)
90
+
91
+ 3. 若摸到与带幺鸡杠牌相同的牌张,则可以在自己回合内进行补杠,将幺鸡替换回手中,若此时可胡牌,记为杠上开花
92
+
93
+ 4. 杠牌
94
+
95
+ 1. 不计杠分,无相关金流
96
+
97
+ 5. 初始手牌数量
98
+
99
+ 1. 13张
100
+
101
+ 6. 发牌及摸牌规则[请至钉钉文档查看附件《xuezhan\_yj.xlsm》](https://alidocs.dingtalk.com/i/nodes/MNDoBb60VLrKMYYvIKNYMjl48lemrZQ3?doc_type=wiki_doc&iframeQuery=anchorId%3DX02mhn98lcsop813bpirjl)
102
+
103
+ 2. 对战阶段
104
+
105
+ 1. 行动阶段划分
106
+
107
+ 1. 定缺阶段、换三张阶段、行牌阶段
108
+
109
+ 2. 定缺阶段
110
+
111
+ 1. 胡牌时,手牌中不能超过2门花色
112
+
113
+ 2. 开局时玩家需要选择一门花色定为缺牌,摸到这门花色的牌一定要打出,对局中不可更改缺
114
+
115
+ 3. 换三张阶段
116
+
117
+ 1. 发完手牌后,每位玩家选择3张同花色的牌,随机与其他一位玩家交换
118
+
119
+ 2. 手牌除主花色外,其余2种花色张数均小于3张时,触发好牌不换,本局不参与换牌,其他玩家继续换牌
120
+
121
+ 3. 幺鸡不参与换三张
122
+
123
+ 3. 结算阶段
124
+
125
+ 1. 胡牌规则
126
+
127
+ 1. 可以点炮胡、抢杠胡、一炮多响
128
+
129
+ 2. 每局可有多个玩家胡牌,有玩家胡牌后,牌局继续,直到第3个玩家胡牌或摸完所有的牌,牌局结束
130
+
131
+ 3. 低于起胡倍数不允许胡牌,对局结束后最大可能倍数(不包含自摸倍数)未达到起胡倍数将被查大叫
132
+
133
+ 4. 胡牌时立刻结算金流
134
+
135
+ 2. 起胡&封顶倍数
136
+
137
+ 1. 起胡倍数:8倍
138
+
139
+ 2. 封顶倍数:128倍
140
+
141
+ 3. 摸完所有手牌时,未听牌、花猪玩家需要接受额外惩罚
142
+
143
+ 1. 查花猪 → 查大叫,同环节金流同时结算,钱不够按胡牌倍数比例分
144
+
145
+ 2. 查花猪:打出最后一张牌后,未胡牌的玩家先参与查花猪,手牌有三门花色的玩家为花猪,花猪玩家赔给其他非花猪玩家每人封顶倍
146
+
147
+ 3. 查大叫:打出最后一张牌后,未听牌玩家赔给听牌未胡玩家最大可能倍数(不包含自摸倍数)
148
+
149
+ 4. 结算公式
150
+
151
+ 1. 底分:1分
152
+
153
+ 2. 自摸 X 2 :(底分x倍数x2)x 3家
154
+
155
+ 3. 点炮=底分\*倍数
.cache/ab4abc5772bc9251ee2f06b77178bc96.cache ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 妙手七星
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 妙手七星
6
+
7
+ 2. 玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各4张,1-9筒各4张,1-9条各4张,东西南北中发白各4张,春夏秋冬4张赖子,共140张
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 行牌规则
36
+
37
+ 1. 手牌
38
+
39
+ 1. 每人持有一张赖子+4组不同的刻子,作为手牌。
40
+
41
+ 2. 手牌牌库为 1-9 筒、1-9 条、1-9 万各 3 张,东南西北中发白各 3 张。
42
+
43
+ 2. 公共牌
44
+
45
+ 1. 从牌堆中选出不同的七张牌作为公共牌。每轮摸打结束,所有玩家均自摸本轮的公共牌。
46
+
47
+ 2. 公共牌牌库为 1-9 筒、1-9 条、1-9 万各 1 张,东南西北中发白各 1 张
48
+
49
+ 3. ~~​~~摸牌
50
+
51
+ 1. 每次摸3张牌,选择其中一张,另外两张复制为这一张后加入手牌。
52
+
53
+ 2. 未选择的两个牌会回到牌库,仍有可能被其他玩家摸到
54
+
55
+ 4. ​出牌
56
+
57
+ 1. 每次打出一组刻,赖子牌不能打出。
58
+
59
+ 2. 打出去的牌不会点炮
60
+
61
+ 5. 和牌
62
+
63
+ 1. 每轮会进行一次和牌番型大小比较,与公共牌组成最高和牌番型的玩家胜出
64
+
65
+ 2. 多位玩家番型倍数相同时,同时胜出。
66
+
67
+ 2. 赖子牌
68
+
69
+ 1. 可以代替任意牌
70
+
71
+ 2. 可以单吊赖子牌胡牌
72
+
73
+ 3. 胡牌番型及倍数
74
+
75
+ 1. 【大威天龙】×666 胡牌时,有5个同花色且点数连续的牌
76
+
77
+ 2. 【大道无形】×399 手牌包含四组赖子刻
78
+
79
+ 3. 【九龙在天】×399 牌型包含九万、九条、九筒、白板
80
+
81
+ 4. 【大四喜】×388 胡牌时,牌型包含东、南、西、北
82
+
83
+ 5. 【火凤凰】×333 由1579条与红中组成的胡牌
84
+
85
+ 6. 【大车轮】×333 由12468筒组成的胡牌
86
+
87
+ 7. 【万中无双】×333 由13579万组成的胡牌
88
+
89
+ 8. 【绿一色】×266 由23468条与发财组成的胡牌
90
+
91
+ 9. 【大三元】×233 牌型中包含中、发、白
92
+
93
+ 10. 【全幺九】×199 所有牌点数均为1或9
94
+
95
+ 11. 【日月同辉】×88 胡牌时,牌型仅由两个序数组成
96
+
97
+ 12. 【字一色】×77 所有牌均为字牌
98
+
99
+ 13. 【清一色】×66 全部由万筒条中的一种花色组成的胡牌
100
+
101
+ 14. 【全中】×55 所有牌点数均为4、5、6
102
+
103
+ 15. 【全大】×52 所有牌点数均为7、8、9
104
+
105
+ 16. 【全小】×52 所有牌点数均为1、2、3
106
+
107
+ 17. 【四节高】×50 包含4个同花色且点数连续的刻子
108
+
109
+ 18. 【三风刻】×33 包含东、南、西、北中的三组刻
110
+
111
+ 19. 【全双刻】×22 所有牌点数均为2、4、6、8
112
+
113
+ 20. 【混幺九】×19 由点数为1或9的牌与字牌组成的胡牌
114
+
115
+ 21. 【全单刻】×17 所有牌点数均为1、3、5、7、9
116
+
117
+ 22. 【三同刻】×16 包含点数相同的三种花色的刻子
118
+
119
+ 23. 【混一色】×11 由万筒条中的一种花色+字牌组成的胡牌
120
+
121
+ 24. 【太公钓鱼】×10 所胡牌与手牌中已有的一组刻相同
122
+
123
+ 25. 【断幺九】×9 仅由序数牌2-8组成的胡牌
124
+
125
+ 26. 【三节高】×8 包含3个同花色且点数连续的刻子
126
+
127
+ 27. 【双双同刻】×7 包含两组点数相同的刻子
128
+
129
+ 28. 【双箭��】×4 牌型中包含红中、发财、白板中的两组刻
130
+
131
+ 29. 【双同刻】×2 包含点数相同的二种花色的刻子
132
+
133
+ 4. 番型比较
134
+
135
+ 1. 不同的番型比较时,按照番型倍数大小决定结果。
136
+
137
+ 2. 当玩家的牌同时满足多个番型时,仅计算最大的番型,其余番型不叠加。
138
+
139
+ 3. 真”字番型
140
+
141
+ 1. 当玩家在番型比较中胜出时(包括多家平局时胜出),如果是50倍以上的番型(包括50倍),并且公共牌区的牌恰好是手中的牌时,所胡的番型会进阶为“真”字番型,番型结算时额外乘太公钓鱼的倍数。(若番型比较未胜出则不计算)
142
+
143
+ 2. 行牌阶段
144
+
145
+ 1. 阶段划分
146
+
147
+ 1. 每回合包括确认公共牌阶段、摸牌阶段、出牌阶段、和牌阶段
148
+
149
+ 2. 游戏共七个回合
150
+
151
+ 1. 前四回合每个玩家进行一次摸牌和出牌,回合末所有玩家进行比牌,番型倍数最大的玩家和牌并赢取对应的分数。
152
+
153
+ 2. 四个回合结束后,所有玩家进入决战时刻,依次结算剩余三张公共牌。每张公共牌倍数加成2、3、5倍
154
+
155
+ 3. 结算阶段
156
+
157
+ 1. 每张公共牌进行一次结算,番型最大的玩家拿到当前牌张进行和牌,视为自摸。其余玩家不和牌,支付相应的分数。
158
+
159
+ 2. 结算分数=底分×_公共牌倍数×_番型倍数
160
+
161
+ 3. 多家平牌时,按照两两结算原则进行。
.cache/abe70409f4028b5f41913146ddf036d2.cache ADDED
@@ -0,0 +1,283 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 捉鸡麻将
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 捉鸡麻将
6
+
7
+ 2. 玩家玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各四张,1-9条各四张,1-9筒各四张,共108张牌
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 行牌规则
36
+
37
+ 1. 可以碰牌、杠牌,不可以吃牌
38
+
39
+ 2.  过碰不碰,玩家当轮未碰牌A,下次摸牌前都不能碰牌A
40
+
41
+ 2. 杠牌规则
42
+
43
+ 1. 杠后的一组牌叫做豆
44
+
45
+ 2. 报听后,无论什么情况都不可开杠
46
+
47
+ 3. 杠影响结算
48
+
49
+ 3. 报听
50
+
51
+ 1. 仅天听、地听的情况下可以报听
52
+
53
+ 2. 报听的玩家无需通行证即可胡点炮平胡,其他玩家也可胡报听玩家的点炮平胡
54
+
55
+ 3. 报听影响结算
56
+
57
+ 4. 胡
58
+
59
+ 1. 胡牌条件
60
+
61
+ 1. **点炮情况**胡**平胡**需要豆或杀报(报听玩家点炮),自摸可平胡
62
+
63
+ 2. 胡其他牌型无条件
64
+
65
+ 2. 胡牌方式
66
+
67
+ 1. 自摸、杠开
68
+
69
+ 2. 炮胡、热炮、抢杠胡
70
+
71
+ 3. 胡牌规则
72
+
73
+ 1. 过胡不胡,玩家当轮未胡炮胡,下次摸牌前不能再胡同番的炮胡,只看是否升级了炮胡操作(即过点炮不胡,可胡热炮)
74
+
75
+ 2. 天胡及地胡不能过胡,其他番型均可选择过。
76
+
77
+ 3. 存在一炮多响,一人点炮,可以多人胡牌
78
+
79
+ 5. 名词定义
80
+
81
+ 1. 重要玩法类名词
82
+
83
+ | **名词** | **定义** |
84
+ | --- | --- |
85
+ | 豆/通行证 | 杠牌,有豆/通行证才能胡点炮平胡 |
86
+ | 鸡 | 包含常鸡和翻牌鸡,结算时如果叫嘴了可向其他玩家收取对应的分数,如果未叫嘴则需包鸡 |
87
+ | 叫嘴/未叫嘴 | 听牌(胡牌的玩家也算作叫嘴)/未听牌 |
88
+ | 捉鸡牌/翻牌鸡 | 有玩家胡牌后,若牌堆仍有牌,则进行捉鸡。<br>翻开剩余牌山里的第1张牌为捉鸡牌,则捉鸡牌+1点的牌为翻牌鸡,翻牌鸡影响结算,捉鸡牌不影响结算。<br>例如:翻开的是5万,则6万为翻牌鸡<br>翻开9筒,1筒为翻牌鸡 |
89
+ | 满堂鸡 | 翻鸡牌计算玩家未打出的牌和所有打出的牌 |
90
+ | 手上鸡 | 翻鸡牌只计算玩家未打出的牌 |
91
+ | 包鸡 | 结算时如果有玩家未叫嘴,则该玩家已亮出的鸡牌(包括已打出的,碰的和杠的。**暗杠不算,翻牌鸡不算,如果是金鸡或者金乌骨鸡还是会算**)全部要赔付给其他叫嘴玩家对应番数。 |
92
+ | 包豆 | 结算时如未叫嘴玩家有豆,则该玩家需反赔给所有叫嘴玩家对应的豆分番数。 |
93
+ | 鸡、豆全烧 | 抢杠和热炮情况下,被抢杠及点热炮玩家所有的鸡、豆全部无效(如果未叫嘴还需包赔鸡分) |
94
+
95
+ 2. 鸡牌类名词
96
+
97
+ | **名词** | **定义** |
98
+ | --- | --- |
99
+ | 常鸡 | 幺鸡(1条)和乌骨鸡(8筒)每局固定 |
100
+ | 金鸡/金乌骨鸡 | 翻牌鸡是1条/8筒 |
101
+ | 冲锋鸡/冲锋乌骨鸡 | 开局后,打出的第一张未被碰或杠或胡的1条/8筒,会变成冲锋鸡/乌骨冲锋鸡 |
102
+ | 责任鸡/责任乌骨鸡 | 开局后,打出的第一张被他人碰或杠的1条/8筒,会变成责任鸡/责任乌骨鸡 |
103
+ | 银鸡 | 捉鸡牌是9万或9筒,翻牌鸡是1万或1筒 |
104
+ | 跟冲 | 如果之前有玩家第一张出牌是鸡牌且冲锋成功,那么后面玩家第一张打出一样的鸡牌也都算冲锋鸡。<br>1、只看每个玩家的首张出牌,无论中间碰杠多少次。<br>2、这张鸡之前必须冲成功。 |
105
+
106
+ 3. 其他非关键名词
107
+
108
+
109
+ | **名词** | **定义** |
110
+ | --- | --- |
111
+ | 坐庄 | 首局由系统随机选取玩家坐庄<br>首局结束后由胡牌者接庄<br>若一炮多响,由放炮玩家坐庄<br>流局后连庄 |
112
+ | 连庄 | 每连庄1次,庄家输赢额外+1番 |
113
+ | 本鸡 | 结束时翻出的那张牌也算鸡牌,每张1番 |
114
+ | 上下鸡 | 结束时翻出的那张牌-1和+1都算鸡牌,每张1番 |
115
+
116
+ 6. 倍数说明
117
+
118
+ 1. **豆分倍数**
119
+
120
+ | **类型** | **倍数****/****个** | **说明** |
121
+ | --- | --- | --- |
122
+ | 闷豆 | 3 | 收3家 |
123
+ | 爬坡豆 | 3 | 收3家 |
124
+ | 点豆 | 3 | 仅点豆者支付 |
125
+ | 憨包豆 | 0 | 只可做通行证 |
126
+ | 未叫嘴玩家的豆需要反赔给对应的叫嘴玩家对应的分数,收取变为支付 | | |
127
+
128
+ 2. **鸡牌倍数**
129
+
130
+ | **类型** | **倍数****/****个** | **说明** |
131
+ | --- | --- | --- |
132
+ | 常鸡 | 1 | 详见4.2.2鸡牌类名词解释 |
133
+ | 翻牌鸡 | 1 |
134
+ | 金鸡 | 3 |
135
+ | 金乌骨鸡 | 6 |
136
+ | 银鸡 | 2 |
137
+ | 普通冲锋鸡 | 3 |
138
+ | 金鸡冲锋鸡 | 9 |
139
+ | 金冲锋乌骨鸡 | 18 |
140
+ | 普通责任鸡 | 3 |
141
+ | 金鸡责任鸡 | 9 |
142
+ | 金责任乌骨鸡 | 18 |
143
+ | 本鸡(仅亲友房) | 1 |
144
+ | 上鸡(仅亲友房) | 1 |
145
+
146
+ 3. **番型倍数**
147
+
148
+ 1. 以下番型倍数都不叠加,仅取最大番型倍数。
149
+
150
+
151
+ | **番型** | **倍数** | **说明** |
152
+ | --- | --- | --- |
153
+ | 平胡 | 3 | 普通胡牌番型,非下列任一种牌型。 |
154
+ | 素瓜豆 | 3 | 无鸡无豆胡牌翻倍,只是自摸平胡翻倍,其他胡牌番型不翻倍。无鸡包含无翻牌鸡,无豆包含无憨包豆。 |
155
+ | 清一色 | 15 | 成牌时所有牌都由条、筒、万中的一种组成。 |
156
+ | 大对子 | 10 | 即对对胡,成牌时有4个三张相同的和1个对。 |
157
+ | 清大对 | 25 | 清一色+大对子 |
158
+ | 大对子单吊 | 15 | 碰/杠了4次后单吊胡大对子 |
159
+ | 清大对单吊 | 30 | 清一色+大对子单吊 |
160
+ | 七对 | 15 | 成牌时由7个对子组成。 |
161
+ | 清七对 | 30 | 清一色+七对 |
162
+ | 龙七对 | 30 | 成牌时由5个对子和4个相同的牌组成。 |
163
+ | 清龙背 | 45 | 清一色+龙七对 |
164
+ | 地龙 | 30 | 手牌为5对加1个碰时胡碰的那张牌 |
165
+ | 清地龙 | 45 | 清一色+地龙 |
166
+ | 天胡 | 30 | 庄家起手直接胡牌。必须胡牌。可暗杠。 |
167
+ | 地胡 | 30 | 闲家胡自己摸的第一张牌或庄家打的第一张牌。必须胡牌。可暗杠。 |
168
+
169
+ 4.  **事件倍数**
170
+
171
+ 1. 和番型倍数会叠加。 
172
+
173
+
174
+ | **事件** | **倍数** | **说明** |
175
+ | --- | --- | --- |
176
+ | 报听 | 15 | 庄家天听或闲家地听可选择报听。报听玩家胡点炮平胡可无需通行证。 |
177
+ | 杀报 | 15 | 报听玩家点炮(无需通行证)或其他玩家自摸则为杀报,报听玩家需赔杀报玩家对应番数。 |
178
+ | 自摸 | 0 | 自摸收3家牌型分 |
179
+ | 杠开 | 6 | 开杠后自摸胡牌 |
180
+ | 抢杠 | 15 | 抢补杠胡牌(无需通行证),被抢杠玩家的鸡豆全烧并赔付抢杠玩家牌型番 |
181
+ | 热炮 | 6 | 杠后打出的第一张牌点炮叫热炮(无需通行证),点热炮玩家鸡豆全烧,胡牌玩家牌型番 |
182
+
183
+ 5. 统计规则
184
+
185
+ 1.  豆的倍数:按加法计算
186
+
187
+ 2.     鸡牌倍数:按加法计算
188
+
189
+ 3.    番型倍数:番型之间不叠加,仅取最大值。
190
+
191
+ 4. 事件倍数:同时存在时,可以叠,规则为相加
192
+
193
+ 2. 行牌阶段
194
+
195
+ 1. 庄家先出牌
196
+
197
+ 2.   判定是否碰、杠、胡
198
+
199
+ 1.   否,按逆时针顺序确定下家,庄家下家摸打;
200
+
201
+ 2.   是,执行碰、杠、胡操作;
202
+
203
+ 3.   按逆时针顺序摸打,直到某个玩家胡牌;
204
+
205
+ 4.   直到牌山摸完或者有玩家胡牌,牌局结束
206
+
207
+ 3. 结算阶段
208
+
209
+ 1. 胡牌结算
210
+
211
+ 1. 有人胡牌时的结算方式,自摸和炮胡的结算逻辑相同
212
+
213
+ 2. 每个玩家得分\=豆分结算+鸡牌结算+倍数结算
214
+
215
+ 3. 玩家之间独立结算
216
+
217
+ 1. 玩家A胡牌,玩家BCD未胡牌,玩家B除与A进行结算外还需要与C和D进行结算,其他玩家同理
218
+
219
+ 2. 和他人结算时,己方的倍数为正,他人的倍数为负,求和得出该类型倍数
220
+
221
+ 4. 玩家之间进行结算时,多种结算不会全部存在
222
+
223
+ 1. 番型结算、事件结算,这2种只存在于胡牌玩家和被胡牌玩家之间
224
+
225
+ 2. 豆分结算、鸡牌结算,所有玩家之间进行结算时都可能存在
226
+
227
+ 2. 流局结算
228
+
229
+ 1. 无人胡牌时的结算方式
230
+
231
+ 2. 未听牌的包听牌玩家的理论最大番型分(不计天胡,地胡和事件倍数),并且包自己的鸡、杠分
232
+
233
+ 3. 听牌玩家的鸡、杠照常收取未听牌玩家的分数,听牌玩家之间互不收取任何分数
234
+
235
+ 3. 豆分结算
236
+
237
+ 1. 闷豆结算
238
+
239
+ 1. 闷豆玩家向其他3人收取相同分数
240
+
241
+ 2. 每人收分\=基数\*闷豆数量\*闷豆倍数
242
+
243
+ 2. 爬坡豆结算
244
+
245
+ 1. 闷豆玩家向其他3人收取相同分数
246
+
247
+ 2. 每人收分\=基数\*爬坡豆数量\*爬坡豆倍数
248
+
249
+ 3. 点豆结算
250
+
251
+ 1. 被点豆的玩家向点豆玩家收取的分数
252
+
253
+ 2. 收分\=基数\*点豆数量\*点豆倍数
254
+
255
+ 4. 鸡牌结算
256
+
257
+ 1. 胡牌玩家自己的翻牌鸡要统计已打出和未打出的
258
+
259
+ 2. AB双方进行结算时,玩家的鸡牌分\=基数\*(双方的鸡牌倍数和)
260
+
261
+ 3. 正常结算
262
+
263
+ 1. 所有玩家均听牌,只存在正常结算
264
+
265
+ 2. 玩家打出的冲锋鸡倍数为正,变为责任鸡时倍数为负
266
+
267
+ 4. 包鸡结算
268
+
269
+ 1. 有玩家未听牌时,存在包鸡结算
270
+
271
+ 2. 未听牌玩家所有已亮出的鸡牌**(不包含翻牌鸡,如果是金鸡或者金乌骨鸡需要包含)**倍数为负,听牌玩家除责任鸡外,所有鸡牌为正
272
+
273
+ 5. 倍数结算
274
+
275
+ 1. 结算条件
276
+
277
+ 1. 只有胡牌结算中存在,且只存在于胡牌玩家和未胡牌玩家之间
278
+
279
+ 2. 胡牌玩家得分\=3个未胡牌玩家的输分之和
280
+
281
+ 3.  未胡牌玩家输分\=基数\*(番型倍数+事件倍数)
282
+
283
+ 4. 自摸收3家。点炮胡仅收点炮玩家分数(仅正常分数,不会包其他2家的)
.cache/d124ffce9e9013b3c1f0960978ea5eb4.cache ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 广东鸡平胡
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 广东鸡平胡
6
+
7
+ 2. 玩家
8
+
9
+ 1. 人数    
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各四张,1-9筒各四张,1-9条各四张,字牌(东西南北中发白)各四张,共136张牌
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 杠分
36
+
37
+ 1. 杠后立刻收分,输家也计杠分。
38
+
39
+ 2. 明杠单家给3倍,补杠三家给1倍,暗杠三家给2倍。
40
+
41
+ 3. 抢杠胡:可在其他玩家补杠时抢杠胡牌;连续杠的最后一次补杠被抢杠,则所有连续杠作废;
42
+
43
+ 4. 抢杠承包:开启后抢杠胡等同自摸,由被抢杠玩家承包三家的胡牌牌型分+输马分。
44
+
45
+ 5. 杠上开花:杠后补牌胡牌;
46
+
47
+ 6. 杠爆承包:开启后假如B玩家放杠给A玩家杠开,则由B玩家承包三家的胡牌牌型分+输马分;
48
+
49
+ 7. 包杠:开启后杠爆承包后假如B玩家放杠给A玩家,A玩家补牌后的连续杠都由B玩家包杠。
50
+
51
+ 8. 碰后立即杠算明杠,可触发杠开承包;碰后过圈再杠算补杠,可触发抢杠胡及抢杠承包。
52
+
53
+ 2. 番型介绍
54
+
55
+ 1. 爆胡以内:
56
+
57
+
58
+ | 胡牌牌型 | 倍数 | 说明 |
59
+ | --- | --- | --- |
60
+ | 鸡胡 | 1 | 什么牌都可以胡,可吃碰杠(鸡胡只能自摸) |
61
+ | 平  胡 | 2 | 全是顺子没有刻子 |
62
+ | 碰碰胡 | 4 | 成牌时有4种刻牌外加1个对子 |
63
+ | 混一色 | 4 | 整副牌由字牌及另外单一花色(筒、条或万)组成 |
64
+ | 七对 | 8 | 手牌由7各对子组成 |
65
+ | 四鬼 | 8 | 手上由4张鬼牌时可直接胡;仅自摸时生效,点炮胡时仅算成牌牌型。 |
66
+
67
+ 爆胡以外(特殊牌型,不叠加):
68
+
69
+ | 胡牌牌型 | 倍数 | 说明 |
70
+ | --- | --- | --- |
71
+ | 清一色 | 16 | 整副牌由同一花色组成 |
72
+ | 豪华七对 | 16 | 手牌由5个对子以及4张相同牌组成 |
73
+ | 混碰 | 16 | 混一色+碰碰胡(不计混一色、碰碰胡) |
74
+ | 清碰 | 32 | 清一色+碰碰胡(不计清一色、碰碰胡) |
75
+ | 双豪华七对 | 32 | 手牌由3个对子以及2组4张相同牌组成 |
76
+ | 混幺九 | 32 | 由幺九牌和字牌组成的碰碰胡 |
77
+ | 小三元 | 32 | 胡牌牌型中有中、发、白组成的2种刻(杠)牌及1对将牌 |
78
+ | 小四喜 | 32 | 胡牌牌型中有东南西北组成的3种刻(杠)牌及1对将牌 |
79
+ | 三豪华七对 | 64 | 手牌由1个对子以及3组4张相同牌组成 |
80
+ | 字一色 | 64 | 由字牌组合成的刻子牌型(不计碰碰胡) |
81
+ | 清幺九 | 64 | 只由幺九两种牌组成的刻子牌型 |
82
+ | 大三元 | 64 | 胡牌时,有中、发、白三组刻子 |
83
+ | 大四喜 | 64 | 胡牌牌型中有东南西北4种刻(杠)牌(不计碰碰胡) |
84
+ | 十八罗汉 | 64 | 4个杠后胡牌 |
85
+ | 九莲宝灯 | 64 | 同种牌形成 1112345678999 ,在摸到该种牌任何一张即可胡牌(不计清一色) |
86
+ | 十三幺 | 64 | 由1、9条,1、9万,1、9筒及东南西北中发白各1张,外加以上13张牌中任意一张组成的胡牌 |
87
+
88
+ | 其他牌型 | 倍数 | 说明 |
89
+ | --- | --- | --- |
90
+ | 天胡 | 64 | 庄家起手直接胡牌 |
91
+ | 地胡 | 32 | 庄家打出的第一张或第一手摸牌后就胡牌 |
92
+ | 杠上开花 | 8 | 不满爆胡倍数的牌型,按8倍计算;大于爆胡倍数的牌型,按实际牌型计算 |
93
+ | 抢杠胡 | 8 | 不满爆胡倍数的牌型,按8倍计算;大于爆胡倍数的牌型,按实际牌型计算 |
94
+ | 杠炮 | 8 | 不满爆胡倍数的牌型,按8倍计算;大于爆胡倍数的牌型,按实际牌型计算 |
95
+ | 海底捞月 | 8 | 不满爆胡倍数的牌型,按8倍计算;大于爆胡倍数的牌型,按实际牌型计算 |
96
+ | 一炮三响 | 8 | 同时点炮三家。胡牌玩家不满爆胡倍数的牌型,按8倍计算;大于爆胡倍数的牌型,按实际牌型计算 |
97
+ | 点炮 | 1 | 点炮胡牌 |
98
+ | 自摸 | 2 | 仅在爆胡以内加倍(底分\*2) |
99
+ | 三元牌 | 2 | 中、发、白,任意一个刻子,仅在爆胡以内加倍(底分\*2) |
100
+
101
+ 3. 鬼牌
102
+
103
+ 1. 即癞子牌,仅胡牌时可充当任意牌,可打出但不能吃/碰杠/点炮。
104
+
105
+ 2. 无鬼加番:开启鬼牌玩法时,如果玩家胡牌时手牌中没有鬼牌,则加1番。
106
+
107
+ 2. 行牌阶段
108
+
109
+ 1. 可以碰牌、杠牌,不可以吃
110
+
111
+ 2. 胡牌规则
112
+
113
+ 1. 可以点炮、自摸、杠开、杠炮、抢杠
114
+
115
+ 2. 支持一炮多胡
116
+
117
+ 3. 鸡胡只能自摸
118
+
119
+ 3. 翻马牌规则
120
+
121
+ 1. 开局取马牌,即开局后,四位玩家依次从牌垛最后四张牌取牌,扣于牌桌上,胡牌后统一翻牌,与中马玩家同赢不同输。
122
+
123
+ 2. 胡牌后翻马牌,以庄家为中心计算:
124
+
125
+ 1. 玩家A1:1、5、9、东、中
126
+
127
+ 2. 玩家A2:2、6、南、发
128
+
129
+ 3. 玩家A3:3、7、西、白
130
+
131
+ 4. 玩家A4:4、8、北
132
+
133
+ 3. 结算阶段
134
+
135
+ 1. 爆胡
136
+
137
+ 1. 爆胡即为封顶3番(8倍),爆胡以内的牌型计算时加番最多不超过3番
138
+
139
+ 2. 爆胡以外的特殊牌型可突破爆胡限制,不再叠加其它番种。
140
+
141
+ 2. 结算公式
142
+
143
+ 1. 总分=(胡牌牌型分+中马分)+(杠分+跟庄分)
144
+
145
+ 2. 胡牌牌型分封顶64倍,总分无封顶。
146
+
147
+ 3. 承包玩法仅承包三家的胡牌牌型分+输马分,不承包杠分+跟庄分。流局查杠分和跟庄分。
.cache/e5d1e6efe417a200ee79ac217a2e9276.cache ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 卡五星麻将
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 卡五星麻将
6
+
7
+ 2. 玩家玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 3人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,上家记为:A3
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9条各四张,1-9筒各四张,中发白各四张,总计84张牌。
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 行牌规则
36
+
37
+ 1. 可以碰、杠,不能吃
38
+
39
+ 2. 有一炮多响
40
+
41
+ 2. 亮倒
42
+
43
+ 1. 听牌后将手牌亮出,亮倒后自动摸打胡,输赢翻倍。他人亮倒时,未亮倒的玩家不能打出炮牌(手牌全为炮张时除外)
44
+
45
+ 3. 买马
46
+
47
+ 1. 胡牌时,翻开牌墙的最后一张牌(海底胡则不翻),根据这张牌的点数额外得分
48
+
49
+ 2. 1-9点加1-9倍基数,中发白加10倍基数。
50
+
51
+ 4. 漂分
52
+
53
+ 1. 开局前玩家各自选择打漂分数,胡牌时额外结算漂分,按照基数\*(胡牌者漂分+被胡牌者漂分)计算
54
+
55
+ 5. 流局
56
+
57
+ 1. 有人亮倒且牌墙摸完时仍无人胡牌视为流局,已发生的杠分正常计算,流局时,按照下述规则进行结算
58
+
59
+ 1. 首个亮倒玩家赔付其他听牌玩家的听牌倍数
60
+
61
+ 2. 未听牌玩家赔付听牌玩家的听牌倍数
62
+
63
+ 6. 杠上杠
64
+
65
+ 1. 同一玩家,杠牌后接着开杠(暗杠、补杠),后续的杠分翻倍计算
66
+
67
+ 7. 番型及倍数
68
+
69
+ 1. 三龙七对(32倍)符合7对的胡牌牌型,且其中有3组4张相同的牌
70
+
71
+ 2. 双龙七对(16倍)符合7对的胡牌牌型,且其中有2组4张相同的牌
72
+
73
+ 3. 龙七对(8倍)符合7对的胡牌牌型,且其中有1组4张相同的牌
74
+
75
+ 4. 大三元(8倍)胡牌时,拥有中、发、白的三组刻子或杠
76
+
77
+ 1. 3张红中+3张发财+1对白板+4-6(筒子)+1对八条+1张白板
78
+
79
+ 5. 暗四归(4倍)胡的牌张能与自己手牌中的一组暗刻相同,清一色除外
80
+
81
+ 6. 清一色(4倍)胡牌时只有一门花色的牌
82
+
83
+ 7. 小三元(4倍)胡牌时,拥有中、发、白其中的两组刻子或杠以及其中的1对
84
+
85
+ 8. 手抓一(4倍)胡牌时,手牌仅有一张,其余牌张都是碰、杠(不计暗杠)的形式
86
+
87
+ 9. 七对(4倍)由7个不同的对子组成的胡牌
88
+
89
+ 10. 明四归(2倍)胡的牌张与自己碰出的一组牌相同
90
+
91
+ 11. 卡五星(2倍)胡牌时胡5条或5筒,且形式为46卡5
92
+
93
+ 12. 碰碰胡(2倍)由4组刻子或杠+1对组成的胡牌
94
+
95
+ 13. 平胡(1倍)由至少1组顺子+其他顺刻+1对组成的胡牌
96
+
97
+ 2. 行牌阶段
98
+
99
+ 1. 庄家先出牌
100
+
101
+ 2.   判定是否碰、杠、胡
102
+
103
+ 1.   否,按逆时针顺序确定下家,庄家下家摸打;
104
+
105
+ 2.   是,执行碰、杠、胡操作;
106
+
107
+ 3.   按逆时针顺序摸打,直到某个玩家胡牌;
108
+
109
+ 4.   直到牌山摸完或者有玩家胡牌,牌局结束
110
+
111
+ 3. 结算阶段
112
+
113
+ 1. 结算规则
114
+
115
+ 1. 杠分:暗杠2倍,点杠2倍,补杠1倍,连续杠牌,从第二杠起,杠分翻倍
116
+
117
+ 2. 胡牌得分=(番型1\*番型2\*...)\*亮倒倍数,封顶16倍
118
+
119
+ 3. 最终得分=杠分+胡牌分+漂分+买马分
.cache/f373cbfec78689ef2a023b520e02fd40.cache ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (game "ChangSha_Mahjong" (version "1.3.0")
2
+ ;; =========================
3
+ ;; 1. 元信息 & 概览
4
+ ;; =========================
5
+
6
+ (game_variant "round")
7
+ (rule_profile
8
+ (blood_mode "none")
9
+ (scoring_mode "hybrid") ; 混合制
10
+ (has_wildcard false)
11
+ (has_horse true) ; 扎鸟
12
+ (has_contract false)
13
+ (has_multi_round true)
14
+ (has_ting_system false)
15
+ (has_chicken_system false)
16
+ (has_bean_system false)
17
+ )
18
+
19
+ ;; =========================
20
+ ;; 2. Rule-Core:玩法本体
21
+ ;; =========================
22
+
23
+ (players 4)
24
+ (seats [ "A1" "A2" "A3" "A4" ])
25
+ (turn_order
26
+ (order cyclic A1 A2 A3 A4)
27
+ (on_peng_keep_turn true)
28
+ (on_gang_keep_turn true)
29
+ )
30
+
31
+ ;; ---- 牌组定义 ----
32
+ (tileset
33
+ (suits { "wan" "tong" "tiao" })
34
+ (ranks 1..9)
35
+ (copies 4)
36
+ (honors 0)
37
+ (flowers 0)
38
+ (total 108)
39
+ )
40
+
41
+ (phases [ "setup" "deal" "play" "sea_draw" "settle" ])
42
+
43
+ (setup
44
+ (dealer "rotate")
45
+ (initial_hand 13)
46
+ (choose_que (enabled false))
47
+ (exchange_three (enabled false))
48
+
49
+ (sea_draw
50
+ (enabled true)
51
+ (last_n 1)
52
+ (pass_cycle true)
53
+ (prohibit_kong true))
54
+ )
55
+
56
+ ;; ---- 行为权限 ----
57
+ (actions
58
+ (allow_chi true)
59
+ (allow_peng true)
60
+ (allow_gang { "concealed" "melded" "added" })
61
+ (one_tile_multi_claim true)
62
+ (claim_priority "gang>peng>bu>chi")
63
+ )
64
+
65
+ ;; ---- 胡牌规则 ----
66
+ (win_rules
67
+ (allow_self_draw_win true)
68
+ (allow_discard_win true)
69
+ (allow_gang_win true)
70
+ (allow_rob_kong true)
71
+ (allow_multi_win true)
72
+
73
+ (requirements
74
+ (small_hand_pair_must_be_258 true) ; 小胡258将
75
+ )
76
+
77
+ (post_win_continuation
78
+ (mode "round")
79
+ )
80
+ )
81
+
82
+ ;; =========================
83
+ ;; 3. Scoring:计分与番型
84
+ ;; =========================
85
+
86
+ (scoring
87
+ (mode "hybrid")
88
+ (base_point 1)
89
+ )
90
+
91
+ ;; ---- 番型表 ----
92
+ (fan_table
93
+ (stacking "multiply") ; 倍数叠乘
94
+
95
+ ;; 起手胡
96
+ (yaku qishou_sixi (mult 1) (category "special") (desc "起手四喜"))
97
+ (yaku qishou_66shun (mult 1) (category "special") (desc "起手六六顺"))
98
+ (yaku qishou_queyise (mult 1) (category "special") (desc "起手缺一色"))
99
+ (yaku qishou_banbanhu (mult 1) (category "special") (desc "起手板板胡"))
100
+
101
+ ;; 小胡
102
+ (yaku pinghu (mult 1) (category "basic") (desc "平胡"))
103
+
104
+ ;; 大胡
105
+ (yaku pengpenghu (mult 6) (category "special") (desc "碰碰胡"))
106
+ (yaku jiangjianghu (mult 6) (category "special") (desc "将将胡"))
107
+ (yaku qingyise (mult 6) (category "special") (desc "清一色"))
108
+ (yaku qidui (mult 6) (category "special") (desc "七对"))
109
+ (yaku quanqiuren (mult 6) (category "special") (desc "全求人"))
110
+ (yaku haohuaqidui (mult 12) (category "special") (desc "豪华七对"))
111
+ (yaku shuanghaoqidui (mult 18) (category "special") (desc "双豪华七对"))
112
+ (yaku sanhaoqidui (mult 24) (category "special") (desc "三豪华七对"))
113
+
114
+ ;; 事件
115
+ (yaku gangkai (mult 6) (category "event") (desc "杠开"))
116
+ (yaku qianggang (mult 6) (category "event") (desc "抢杠"))
117
+ (yaku gangpao (mult 6) (category "event") (desc "杠炮"))
118
+ (yaku haidilao (mult 6) (category "event") (desc "海底捞"))
119
+ (yaku tianhu (mult 6) (category "event") (desc "天胡"))
120
+ )
121
+
122
+ ;; =========================
123
+ ;; 4. 特殊机制
124
+ ;; =========================
125
+
126
+ ;; ---- 扎鸟 ----
127
+ (horse_rules
128
+ (enabled true)
129
+ (mode "bird")
130
+ (count 2)
131
+ (draw_from "wall_end")
132
+ (hit_mapping ("rank 1/5/9" (mult 1)))
133
+ (effect "multiplier")
134
+ )
135
+
136
+ (invariants
137
+ (tile_conservation
138
+ (formula "(+ (zone wall) ... ) = 108"))
139
+ )
140
+ )
.cache/f8a27e1a8a217a94e49fbc7c0a369e80.cache ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 长沙麻将
2
+
3
+ 1. 玩法名称
4
+
5
+ 1. 长沙麻将
6
+
7
+ 2. 玩家
8
+
9
+ 1. 总人数
10
+
11
+ 1. 4人
12
+
13
+ 2. 编号
14
+
15
+ 1. 庄家记为:A1
16
+
17
+ 2. 下家记为:A2,对家记为:A3,上家记为:A4
18
+
19
+ 3. 行动模式
20
+
21
+ 1. 依次行动:(A1, A2, A3, A4)
22
+
23
+ 2. 若一玩家有碰牌的操作,则由碰牌的玩家继续出牌,出牌顺序不变
24
+
25
+ 3. 若一玩家有杠牌的操作,则由杠牌的玩家摸牌后继续出牌,出牌顺序不变
26
+
27
+ 4. 游戏所需设备
28
+
29
+ 1. 1-9万各四张、1-9条各四张、1-9筒各四张,共108张牌
30
+
31
+ 5. 规则描述
32
+
33
+ 1. 准备阶段
34
+
35
+ 1. 行牌规则
36
+
37
+ 1. 可以碰牌、杠牌和吃
38
+
39
+ 2. 杠牌规则
40
+
41
+ 1. 长沙麻将在听牌前进行的杠牌行为都叫做“补”,补牌不进行结算且不加倍,补牌后胡牌不视为杠开。
42
+
43
+ 2. 只有在玩家听牌了且可以杠的情况下才叫做“杠”,此时杠牌不算倍数,但需要结算分数,无论是否胡牌都要进行结算。
44
+
45
+ 3. 当听牌且可杠牌的时候,可选择是否杠,若选择杠,则可以从牌墙摸4张牌:
46
+
47
+ 1. 摸上来的牌只能胡或者打出;
48
+
49
+ 2. 如果胡牌则为大胡即杠开,胡多次则计算多次大胡;
50
+
51
+ 3. 摸上来的牌若不能胡则必须打出,打出后如果点炮,则算杠炮,也为大胡,点多次炮则算多次大胡;
52
+
53
+ 4. 摸上来的牌如果自己未胡,打出后也无人能胡,则自己进入到听牌状态,只能摸打,胡牌后按照牌面结算。
54
+
55
+ 4. 杠后可继续杠,听牌过程中其他玩家打出的以及自己摸到的牌都可以进行杠的操作,且杠后都摸4张牌。
56
+
57
+ 5. 当打出的两张牌有其他玩家要执行吃碰杠操作时,只有一个玩家能进行操作,优先级为:①杠牌>碰牌>补牌>吃牌;②第一个条件无法判断时,以顺序优先,已杠牌玩家为起点,逆时针顺序判断。
58
+
59
+ 3. 名词定义
60
+
61
+ 1. 流局
62
+
63
+ 1. 指的是整局游戏中,所有玩家都未达成胡牌条件,且牌山中的牌已摸完(或达到规则约定的流局条件),导致本局无胜利者、直接结束的情况。
64
+
65
+ 4. 番型及倍数
66
+
67
+ 1. 起手胡
68
+
69
+ 1. | 胡牌牌型 | 倍数 | 说明 |
70
+ | --- | --- | --- |
71
+ | 四喜 | 1 | 手牌中4张点数一样的牌 |
72
+ | 六六顺 | 1 | 手牌有2个刻子 |
73
+ | 缺一色 | 1 | 手牌中缺筒、条、万任意一门 |
74
+ | 板板胡 | 1 | 手牌中没有点数为258的牌 |
75
+ | 单五一枝花 | 1 | 手牌中任一花色只有一张且点数为5 |
76
+ | 节节高 | 1 | 手牌中有三对相同花色连续点数的牌 |
77
+ | 三同 | 1 | 手牌中有三个花色且点数相同的对子 |
78
+ | 金童玉女 | 1 | 手牌中二筒、二条各有一对 |
79
+ | 将一枝花 | 1 | 手牌中有且只有一张258将牌 |
80
+ | 梅花三弄 | 1 | 手牌中有且只有三张5筒 |
81
+
82
+ 2. 开局手牌包含以上任意牌型,即可选择胡牌或者“过”按钮,算做小胡自摸胡牌,玩家倒牌展示即时结算,庄家出完牌后玩家立牌继续游戏。
83
+
84
+ 3. 小四喜和六六顺只展示其中满足起手胡条件的牌张,板板胡和缺一色需要展示所有手牌。
85
+
86
+ 2. 中途胡
87
+
88
+ | 胡牌牌型 | 倍数 | 说明 |
89
+ | --- | --- | --- |
90
+ | 中途四喜 | 1 | 对局中手牌中4张点数一样的牌 |
91
+ | 中途六六顺 | 1 | 对局中手牌有2个刻子 |
92
+
93
+ 3. 小胡
94
+
95
+ 1. 需要258做将牌
96
+
97
+
98
+ | 胡牌牌型 | 倍数 | 说明 |
99
+ | --- | --- | --- |
100
+ | 平胡 | 1 | 需258 作将,其余成刻子或顺子 |
101
+
102
+ 4. 大胡
103
+
104
+ | 胡牌牌型 | 倍数 | 说明 |
105
+ | --- | --- | --- |
106
+ | 碰碰胡 | 6 | 每坎牌都是三张一样的牌 |
107
+ | 七对 | 6 | 手牌都是两张一对的,无碰杠 |
108
+ | 全求人 | 6 | 所有手牌被吃、碰、明杠,只剩下一张牌单吊,点炮胡牌 |
109
+ | 清一色 | 6 | 全副牌都是一种花色 |
110
+ | 将将胡 | 6 | 手中全为258,无需成牌 |
111
+ | 豪华七对 | 12 | 手牌都是两张一对,其中2对相同 |
112
+ | 双豪华七对 | 18 | 手牌都是两张一对,其中有两组2对相同 |
113
+ | 三豪华七对 | 24 | 手牌都是两张一对,其中有三组2对相同 |
114
+
115
+ 5. 以下操作胡牌后视作大胡,但牌型是小胡时,仍需要258作将牌
116
+
117
+ | 胡牌操作 | 倍数 | 说明 |
118
+ | --- | --- | --- |
119
+ | 地胡 | 6 | 玩家A2或A3或A4起手摸到的第一张牌自摸胡牌 |
120
+ | 天胡 | 6 | 庄家起手胡牌 |
121
+ | 杠开 | 6 | 杠后摸上的牌恰好胡牌 |
122
+ | 抢杠 | 6 | 补杠时,可以胡这张牌 |
123
+ | 杠炮 | 6 | 杠牌后打出放炮 |
124
+ | 海底捞 | 6 | 最后一张自摸胡牌 |
125
+ | 海底炮 | 6 | 最后一张牌放炮 |
126
+
127
+ 6. 备注
128
+
129
+ 1. 玩家起手胡倒牌后的一轮里也需要继续摸打;
130
+
131
+ 2. 起手胡只在开局时生效,后续有这种牌型不加倍;
132
+
133
+ 3. 若存在起手胡和天胡同时存在的情况,分别结算;
134
+
135
+ 4. 若玩家A2或A3或A4起手胡,倒牌后还是按照正常顺序从庄家A1开始出牌,直到庄家出完牌后,起手胡玩家A2或A3或A4才能立牌结束展示;
136
+
137
+ 5. 自摸不算倍数。
138
+
139
+ 2. 对战阶段
140
+
141
+ 1. 阶段划分
142
+
143
+ 1. 行牌阶段、海底漫游阶段、扎鸟阶段、打骰子阶段
144
+
145
+ 2. 海底漫游阶段
146
+
147
+ 1. 最后一张牌为海底牌,此时玩家可依次选择是否要这张牌,如果轮到第一个玩家摸海底牌,第一个玩家选择不要,则可以轮到第二个玩家选择,如果该玩家选择了要牌,若胡则为海底捞月大胡(手牌为小胡牌型,还是需要258做将),若未胡打出点炮,则算海底炮大胡。
148
+
149
+ 2. 如果某玩家要了海底牌,但又不能胡牌,则必须出海底牌。
150
+
151
+ 3. 海底牌打出没人胡牌则流局,若四家都选择不要海底牌也直接流局。
152
+
153
+ 3. 扎鸟阶段
154
+
155
+ 1. 玩家胡牌后,随机从牌墙中选2张扎鸟牌。
156
+
157
+ 2. 扎鸟牌为另一副牌中随机选取;
158
+
159
+ 3. 一家胡牌时,159为扎中赢家,26为扎中其下家,37为扎中其对家,48为扎中其上家;一炮多响时,庄家扎鸟,159扎中庄家,26扎中下家,37扎中对家,48扎中上家;
160
+
161
+ 4. 若扎中胡牌者或点炮者,则输家的输分倍数×2;
162
+
163
+ 4. 打骰子阶段
164
+
165
+ 1. 玩家起手胡、中途胡后,进行打骰子操作。
166
+
167
+ 2. 只有一家胡时,赢家打骰子,159中赢家,26中下家,37中对家,48中上家;每中1次则分数\*2。
168
+
169
+ 3. .多家胡时,庄家打骰子,159中庄家,26中下家,37中对家,48中上家;每中1次则分数\*2。
170
+
171
+ 3. 结算阶段
172
+
173
+ 1. 总分=牌型倍数之和×扎鸟×基数+起手胡分数+中途胡分数
.cache/fe18e3689386fc503e95de497838dcc5.cache ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (game "Crazy_Blood_Flow" (version "1.3.0")
2
+ ;; =========================
3
+ ;; 1. 元信息 & 概览
4
+ ;; =========================
5
+
6
+ (game_variant "blood_flow")
7
+ (rule_profile
8
+ (blood_mode "xueliu") ; 血流模式:胡牌不结束,无限胡
9
+ (scoring_mode "multiplier") ; 倍数制:10进制 (1, 10, 100, 1000...)
10
+ (has_wildcard true) ; 有赖子 (红中)
11
+ (has_horse false)
12
+ (has_contract false)
13
+ (has_multi_round false)
14
+ (has_ting_system false)
15
+ (has_chicken_system false)
16
+ (has_bean_system false)
17
+ )
18
+
19
+ ;; =========================
20
+ ;; 2. Rule-Core:玩法本体
21
+ ;; =========================
22
+
23
+ (players 4)
24
+ (seats [ "A1" "A2" "A3" "A4" ])
25
+ (turn_order
26
+ (order cyclic A1 A2 A3 A4)
27
+ (on_peng_keep_turn true)
28
+ (on_gang_keep_turn true)
29
+ )
30
+
31
+ ;; ---- 牌组定义 ----
32
+ (tileset
33
+ (suits { "wan" "tong" "tiao" })
34
+ (ranks 1..9)
35
+ (copies 4)
36
+ (honors 0) (honor_copies 0)
37
+ (flowers 0)
38
+ (hongzhong 6) ; 6个红中 (王者场8个)
39
+ (total 114) ; 108 + 6 = 114张
40
+ )
41
+
42
+ (phases [ "setup" "deal" "choose_que" "play" "settle" ])
43
+
44
+ (setup
45
+ (dealer "random")
46
+ (initial_hand 13)
47
+
48
+ (choose_que
49
+ (enabled true)
50
+ (must_keep_under_two_suits_to_win true)
51
+ (lock_que true))
52
+
53
+ (exchange_three (enabled false))
54
+ )
55
+
56
+ ;; ---- 行为权限 ----
57
+ (actions
58
+ (allow_chi false)
59
+ (allow_peng true)
60
+ (allow_gang { "concealed" "melded" "added" })
61
+ (one_tile_multi_claim true) ; 一炮多响
62
+ (one_tile_multi_use true) ; 一牌多用:可同时被胡和碰杠
63
+ )
64
+
65
+ ;; ---- 胡牌规则 ----
66
+ (win_rules
67
+ (allow_self_draw_win true)
68
+ (allow_discard_win true)
69
+ (allow_gang_win true)
70
+ (allow_rob_kong false) ; 不允许抢杠胡
71
+ (allow_multi_win true)
72
+
73
+ (requirements
74
+ (must_que true)
75
+ )
76
+
77
+ ;; 血流流程
78
+ (post_win_continuation
79
+ (mode "xueliu")
80
+ (winner_exit false) ; 胡牌者不退出,继续摸打
81
+ (keep_turn_order true) ; 顺序不变
82
+ (end_when_wall_empty true) ; 牌墙摸完结束
83
+ )
84
+ )
85
+
86
+ ;; =========================
87
+ ;; 3. Scoring:计分与番型
88
+ ;; =========================
89
+
90
+ (scoring
91
+ (mode "multiplier") ; 倍数制 (10进制)
92
+ (base_point 1)
93
+ (self_draw_multiplier 10) ; 自摸 x10 (疯狂体系特征)
94
+ (discard_win_multiplier 1)
95
+ )
96
+
97
+ ;; ---- 番型表 (10进制倍数) ----
98
+ (fan_table
99
+ (stacking "multiply") ; 倍数叠乘
100
+
101
+ ;; 1番 (10倍)
102
+ (yaku pengpenghu (mult 10) (category "special") (desc "碰碰胡"))
103
+ (yaku quanshuang (mult 10) (category "special") (desc "全双(2/4/6/8)"))
104
+ (yaku quandan (mult 10) (category "special") (desc "全单(1/3/5/7/9)"))
105
+ (yaku sanjiegao (mult 10) (category "special") (desc "三节高"))
106
+ (yaku dayuwu (mult 10) (category "special") (desc "大于五"))
107
+ (yaku xiaoyuwu (mult 10) (category "special") (desc "小于五"))
108
+ (yaku gangkai (mult 10) (category "event") (desc "杠上开花"))
109
+ (yaku gangpao (mult 10) (category "event") (desc "杠上炮"))
110
+ (yaku gen (mult 10) (category "addon") (desc "根"))
111
+
112
+ ;; 2番 (100倍)
113
+ (yaku qingyise (mult 100) (category "special") (desc "清一色"))
114
+ (yaku jingoudiao (mult 100) (category "special") (desc "金钩钓"))
115
+ (yaku sijiegao (mult 100) (category "special") (desc "四节高"))
116
+
117
+ ;; 3番 (1000倍)
118
+ (yaku shierjinchai (mult 1000) (category "special") (desc "十二金钗(3根)"))
119
+
120
+ ;; 4番 (10000倍)
121
+ (yaku wanzhongwushuang (mult 10000) (category "special") (desc "万中无双(13579万)"))
122
+ (yaku shibaluohan (mult 10000) (category "special") (desc "十八罗汉(4根)"))
123
+ (yaku lvyise (mult 10000) (category "special") (desc "绿一色"))
124
+ (yaku dachelun (mult 10000) (category "special") (desc "大车轮"))
125
+
126
+ ;; 5番 (100000倍)
127
+ (yaku daweitianlong (mult 100000) (category "special") (desc "大威天龙(5个同花色序数相连)"))
128
+
129
+ ;; 7番 (10000000倍)
130
+ (yaku tianhu (mult 10000000) (category "event") (desc "天胡"))
131
+ (yaku dihu (mult 10000000) (category "event") (desc "地胡"))
132
+
133
+ ;; 基础牌型 (1倍)
134
+ (yaku pinghu (mult 1) (category "basic") (desc "平胡"))
135
+ )
136
+
137
+ ;; ---- 特殊机制 ----
138
+ (wildcard
139
+ (enabled true)
140
+ (type "hongzhong")
141
+ (as_any_tile true)
142
+ (can_discard true) ; 红中可打出
143
+ (discard_effect ; 打出红中算杠
144
+ (type "kong_score")
145
+ (mult 10)
146
+ (draw_replacement true)) ; 补一张牌
147
+ )
148
+
149
+ ;; ---- 杠分规则 ----
150
+ (kong_rules
151
+ (count_gang_point false) ; 疯狂血流不计杠分 (无金流)
152
+ )
153
+
154
+ ;; =========================
155
+ ;; 4. 结算规则
156
+ ;; =========================
157
+
158
+ (settlement
159
+ (score_formula
160
+ (胡分 = "底分 * 番型倍数 * 自摸倍数")
161
+ (自摸 "收3家")
162
+ (点炮 "点炮者付")
163
+ )
164
+
165
+ ;; 查大叫/查花猪
166
+ (on_draw
167
+ (cha_hua_zhu
168
+ (enabled true)
169
+ (penalty "cap_multiplier") ; 赔封顶倍数
170
+ (priority 1))
171
+
172
+ (cha_da_jiao
173
+ (enabled true)
174
+ (penalty "max_possible_score") ; 赔最大可能倍数
175
+ (priority 2))
176
+ )
177
+ )
178
+
179
+ ;; =========================
180
+ ;; 5. 守恒不变量
181
+ ;; =========================
182
+
183
+ (invariants
184
+ (tile_conservation
185
+ (formula "(+ (zone wall) (zone hand:A1) ... (zone discard_pile)) = 114"))
186
+ (constraints
187
+ (hongzhong_count 6)
188
+ (blood_flow_mode true))
189
+ )
190
+ )
README.md CHANGED
@@ -10,3 +10,19 @@ pinned: false
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
13
+
14
+ ## 生成质量增强开关(可选)
15
+
16
+ 本项目默认会在对话中自动注入:
17
+ - `m_prompt.txt`(系统提示词规范)
18
+ - `麻将游戏mGDL通用语法_v1.3.txt`(mGDL v1.3 语法)
19
+ - 与用户输入最相关的少量参考玩法(`.md` 主真理 + `_mGDL_v1.3.txt` 辅语法翻译)
20
+ - `麻将机制说明.md`(机制词典)
21
+
22
+ 可通过环境变量控制:
23
+ - `ENABLE_REFERENCE_RETRIEVAL=1|0`:是否启用“参考玩法检索注入”(默认 1)
24
+ - `REFERENCE_MAX_VARIANTS=3`:最多注入多少个参考玩法(默认 3)
25
+ - `INJECT_REFERENCE_MGDL=1|0`:是否注入“参考玩法 mGDL”(默认 0;通常不建议,RAG语义参考以 .md 为主)
26
+ - `INJECT_ALL_EXAMPLE_GDL=1|0`:是否额外注入全量示例 mGDL(默认 0,不推荐)
27
+ - `ENABLE_OUTPUT_VALIDATION=1|0`:是否对输出做静态校验(默认 1)
28
+ - `ENABLE_AUTO_REPAIR=1|0`:非流式路径下是否自动触发一次“最小修改修复”(默认 0)
__pycache__/ai_service.cpython-37.pyc ADDED
Binary file (7.59 kB). View file
 
__pycache__/cache_manager.cpython-37.pyc ADDED
Binary file (5.72 kB). View file
 
__pycache__/config.cpython-37.pyc ADDED
Binary file (1.5 kB). View file
 
__pycache__/default_content.cpython-37.pyc ADDED
Binary file (4.34 kB). View file
 
__pycache__/design_state.cpython-37.pyc ADDED
Binary file (4.67 kB). View file
 
__pycache__/file_handler.cpython-37.pyc ADDED
Binary file (2.87 kB). View file
 
__pycache__/output_validator.cpython-37.pyc ADDED
Binary file (3.27 kB). View file
 
__pycache__/reference_retriever.cpython-37.pyc ADDED
Binary file (10.9 kB). View file
 
__pycache__/security.cpython-37.pyc ADDED
Binary file (6.57 kB). View file
 
ai_service.py CHANGED
@@ -2,12 +2,29 @@
2
  AI 服务模块 - 处理与 AI 模型的交互(支持原生流式输出)
3
  """
4
  from openai import OpenAI
5
- from config import API_KEY, API_BASE_URL, MODEL_NAME, MAX_TOKENS, TEMPERATURE, TOP_P, SYSTEM_PROMPT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  from file_handler import load_gdl_text
7
  from cache_manager import request_cache
8
  from security import input_validator
9
  from default_content import get_default_gdl, get_default_prompt, get_default_example_gdl
10
 
 
 
 
11
  # 初始化OpenAI客户端(DeepSeek V3兼容)
12
  client = OpenAI(
13
  api_key=API_KEY,
@@ -52,15 +69,52 @@ def _prepare_messages(message, history, uploaded_files, custom_prompt_text, prom
52
  + gdl_spec + "\n</GDL_SPEC>"
53
  })
54
 
55
- # 2.5) 注入示例 GDL 文档(作为参考示例)
56
- # 🟢 自动加载示例 GDL 文档,供 AI 参考
57
- example_gdl = get_default_example_gdl()
58
- if example_gdl:
59
- messages.append({
60
- "role": "system",
61
- "content": "以下为示例 GDL 文档,供您参考设计时使用:\n<EXAMPLE_GDL>\n"
62
- + example_gdl + "\n</EXAMPLE_GDL>"
63
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  # 3) 追加历史对话
66
  for human, assistant in (history or []):
@@ -113,6 +167,27 @@ def design_mahjong_game(message, history, uploaded_files, custom_prompt_text, pr
113
 
114
  response = _call_ai_model(messages)
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  if len(history or []) == 0 and response and not response.startswith(("❌", "💥")):
117
  request_cache.set(messages, response)
118
 
@@ -226,6 +301,11 @@ def design_mahjong_game_stream(message, history, uploaded_files, custom_prompt_t
226
 
227
  # 5) 写入缓存(仅无历史 & 正常内容)
228
  full = "".join(buf).strip()
 
 
 
 
 
229
  if no_hist and full and not full.startswith(("❌", "💥")):
230
  request_cache.set(messages, full)
231
 
@@ -236,4 +316,3 @@ def design_mahjong_game_stream(message, history, uploaded_files, custom_prompt_t
236
  except Exception as e:
237
  # 这里不再抛具体 KeyError,而是把异常消息直接展示出来,避免中断生成器
238
  yield f"\n💥 流式调用失败:{type(e).__name__}: {e}"
239
-
 
2
  AI 服务模块 - 处理与 AI 模型的交互(支持原生流式输出)
3
  """
4
  from openai import OpenAI
5
+ from config import (
6
+ API_KEY,
7
+ API_BASE_URL,
8
+ MODEL_NAME,
9
+ MAX_TOKENS,
10
+ TEMPERATURE,
11
+ TOP_P,
12
+ SYSTEM_PROMPT,
13
+ ENABLE_REFERENCE_RETRIEVAL,
14
+ REFERENCE_MAX_VARIANTS,
15
+ INJECT_REFERENCE_MGDL,
16
+ INJECT_ALL_EXAMPLE_GDL,
17
+ ENABLE_OUTPUT_VALIDATION,
18
+ ENABLE_AUTO_REPAIR,
19
+ )
20
  from file_handler import load_gdl_text
21
  from cache_manager import request_cache
22
  from security import input_validator
23
  from default_content import get_default_gdl, get_default_prompt, get_default_example_gdl
24
 
25
+ from reference_retriever import build_reference_pack
26
+ from output_validator import validate_mahjong_response, format_issues_for_llm
27
+
28
  # 初始化OpenAI客户端(DeepSeek V3兼容)
29
  client = OpenAI(
30
  api_key=API_KEY,
 
69
  + gdl_spec + "\n</GDL_SPEC>"
70
  })
71
 
72
+ # 2.5) 注入参考玩法包”(RAG-lite:少量最相关示例,而不是全量堆叠
73
+ if ENABLE_REFERENCE_RETRIEVAL:
74
+ pack = build_reference_pack(
75
+ message,
76
+ max_variants=REFERENCE_MAX_VARIANTS,
77
+ include_mechanism_library=True,
78
+ include_mgdl=INJECT_REFERENCE_MGDL,
79
+ )
80
+
81
+ mech = (pack.get("mechanism_library") or "").strip()
82
+ if mech:
83
+ messages.append({
84
+ "role": "system",
85
+ "content": "以下为【麻将机制说明/机制词典】,创新时优先从中挑选可落地机制再做组合:\n"
86
+ "<MECHANISM_LIBRARY>\n" + mech + "\n</MECHANISM_LIBRARY>"
87
+ })
88
+
89
+ picked_names = (pack.get("picked_names") or "").strip()
90
+ ref_md = (pack.get("reference_md") or "").strip()
91
+ if ref_md:
92
+ messages.append({
93
+ "role": "system",
94
+ "content": "以下为【参考玩法自然语言规则(主真理)】。当参考玩法的 .md 与 .txt 有冲突时,以 .md 为准:\n"
95
+ "本轮命中参考玩法:" + (picked_names or "(未命中,使用兜底样例)") + "\n"
96
+ "<REFERENCE_VARIANTS_MD>\n" + ref_md + "\n</REFERENCE_VARIANTS_MD>"
97
+ })
98
+
99
+ # 默认不注入参考玩法 mGDL:mGDL 更适合作为语法约束与输出格式规范,语义参考以 .md 为主
100
+ if INJECT_REFERENCE_MGDL:
101
+ ref_mgdl = (pack.get("reference_mgdl") or "").strip()
102
+ if ref_mgdl:
103
+ messages.append({
104
+ "role": "system",
105
+ "content": "以下为【参考玩法 mGDL(辅语法翻译)】。仅用于学习如何用 v1.3 语法表达规则:\n"
106
+ "<REFERENCE_VARIANTS_MGDL>\n" + ref_mgdl + "\n</REFERENCE_VARIANTS_MGDL>"
107
+ })
108
+
109
+ # 可选:仍注入全量示例(不推荐:容易稀释注意力)
110
+ if INJECT_ALL_EXAMPLE_GDL:
111
+ example_gdl = get_default_example_gdl()
112
+ if example_gdl:
113
+ messages.append({
114
+ "role": "system",
115
+ "content": "以下为【全量示例 mGDL】(注意:过多示例可能稀释注意力;优先使用上面的“参考玩法包”):\n<EXAMPLE_GDL_ALL>\n"
116
+ + example_gdl + "\n</EXAMPLE_GDL_ALL>"
117
+ })
118
 
119
  # 3) 追加历史对话
120
  for human, assistant in (history or []):
 
167
 
168
  response = _call_ai_model(messages)
169
 
170
+ # 输出校验 +(可选)最小修复回路(仅非流式,避免影响实时体验)
171
+ if ENABLE_OUTPUT_VALIDATION and response and not response.startswith(("❌", "💥")):
172
+ issues = validate_mahjong_response(response)
173
+ if issues and ENABLE_AUTO_REPAIR:
174
+ fix_instructions = format_issues_for_llm(issues)
175
+ repair_messages = list(messages)
176
+ repair_messages.append({
177
+ "role": "user",
178
+ "content": "下面是你刚刚的输出。请只做【最小修改】来修复这些问题:\n"
179
+ + fix_instructions
180
+ + "\n\n【原输出】\n"
181
+ + response
182
+ + "\n\n修复要求:\n"
183
+ "1) 不要引入新机制,除非为满足守恒/模块完��性而必须。\n"
184
+ "2) 保持规则风味不变,只补齐缺失模块/替换占位符/补全必要字段。\n"
185
+ "3) 修复后重新输出完整结果(自然语言规则 + mGDL + 自检报告)。"
186
+ })
187
+ repaired = _call_ai_model(repair_messages)
188
+ if repaired and not repaired.startswith(("❌", "💥")):
189
+ response = repaired
190
+
191
  if len(history or []) == 0 and response and not response.startswith(("❌", "💥")):
192
  request_cache.set(messages, response)
193
 
 
301
 
302
  # 5) 写入缓存(仅无历史 & 正常内容)
303
  full = "".join(buf).strip()
304
+ if ENABLE_OUTPUT_VALIDATION and full and not full.startswith(("❌", "💥")):
305
+ issues = validate_mahjong_response(full)
306
+ if issues:
307
+ hint = format_issues_for_llm(issues)
308
+ yield "\n\n---\n⚠️ 输出静态校验发现潜在问题(建议让模型按最小修改修复后再导出):\n" + hint + "\n"
309
  if no_hist and full and not full.startswith(("❌", "💥")):
310
  request_cache.set(messages, full)
311
 
 
316
  except Exception as e:
317
  # 这里不再抛具体 KeyError,而是把异常消息直接展示出来,避免中断生成器
318
  yield f"\n💥 流式调用失败:{type(e).__name__}: {e}"
 
app.py CHANGED
@@ -41,6 +41,15 @@ try:
41
  except Exception:
42
  design_mahjong_game_stream = None
43
 
 
 
 
 
 
 
 
 
 
44
 
45
  # ====== 🔧 Hotfix: 兼容 gradio_client 对 additionalProperties(bool) 的解析 ======
46
  try:
@@ -286,6 +295,35 @@ def save_gdl_and_narrative(gdl_content, narrative_content):
286
  return gdl_file_path, narrative_file_path
287
 
288
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  # ==================== Gradio 界面(Mahjong Skin) ====================
290
  with gr.Blocks(
291
  theme=gr.themes.Soft(primary_hue='green', neutral_hue='slate'),
@@ -369,6 +407,36 @@ with gr.Blocks(
369
  chat_state = gr.State([]) # list[dict]: [{"role":"user","content":...}, {"role":"assistant","content":...}]
370
  gdl_file_path = gr.State("")
371
  narrative_file_path = gr.State("")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
 
373
  user_input = gr.Textbox(
374
  placeholder="例如:为4人竞速推倒胡设计番型与流程;或“做一个双人合作麻将 roguelike” …",
@@ -384,70 +452,303 @@ with gr.Blocks(
384
  stop_info = gr.Markdown("", visible=False)
385
 
386
  # ====== 核心:流式提交回调(生成器) ======
387
- def on_submit(user_text, history_msgs, files, custom_prompt, mode):
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  user_text = (user_text or "").strip()
389
  if not user_text:
390
  # 不提交空消息:输出不变
391
- yield history_msgs, "", history_msgs, "", "" # 🟩【修改】输出数量改为5个
392
  return
393
 
394
  # 立即显示“用户消息”
395
  history = list(history_msgs or [])
396
  history.append({"role": "user", "content": user_text})
397
- yield history, "", history, "", ""
398
 
399
  # 添加空的助手气泡,用于逐步填充
400
  history.append({"role": "assistant", "content": ""})
401
- yield history, "", history, "", ""
402
 
403
  # 流式生成内容
404
  tuples_hist = _messages_to_tuples(history)
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  if design_mahjong_game_stream is not None:
407
  try:
408
- for piece in design_mahjong_game_stream(user_text, tuples_hist, files, custom_prompt, mode):
409
  if not piece:
410
  continue
411
  history[-1]["content"] += str(piece)
412
- yield history, "", history, "", ""
413
  except Exception as e:
414
  history[-1]["content"] += f"\n(流式出错){type(e).__name__}: {e}"
415
- yield history, "", history, "", ""
416
  else:
417
  try:
418
- full = design_mahjong_game(user_text, tuples_hist, files, custom_prompt, mode)
419
  except Exception as e:
420
  full = f"(出错){type(e).__name__}: {e}"
421
  for piece in _chunk_fake_stream(str(full), step=40):
422
  history[-1]["content"] += piece
423
- yield history, "", history, "", ""
424
 
425
  # 提取 GDL 和自然语言描述并保存
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
  try:
 
 
 
 
 
427
  gdl_content, narrative_content = extract_gdl_and_narrative(history[-1]["content"])
 
428
 
429
  # 保存 GDL 和自然语言文件
430
  gdl_path, narrative_path = save_gdl_and_narrative(gdl_content, narrative_content)
 
431
 
432
  # 返回文件路径,以便下载
433
- yield history, "", history, gdl_path, narrative_path # 🟩【修改】返回文件路径
434
  except Exception as e:
435
  print(f"保存GDL和自然语言文件时出错: {e}")
436
- yield history, "", history, "", "" # 🟩【修改】返回空路径
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
 
438
  # 绑定:回车提交(Enter=提交;Shift+Enter=换行由浏览器处理)
439
  user_input.submit(
440
  fn=on_submit,
441
- inputs=[user_input, chat_state, file_uploader, custom_prompt_box, prompt_mode],
442
- outputs=[chatbot, user_input, chat_state, gdl_file_path, narrative_file_path], # 🟩【修改】输出改为5个
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  preprocess=True,
444
  )
445
 
446
  # 绑定:点击"发送"
447
  send_btn.click(
448
  fn=on_submit,
449
- inputs=[user_input, chat_state, file_uploader, custom_prompt_box, prompt_mode],
450
- outputs=[chatbot, user_input, chat_state, gdl_file_path, narrative_file_path], # 🟩【修改】输出改为5个
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451
  preprocess=True,
452
  )
453
 
@@ -461,22 +762,37 @@ with gr.Blocks(
461
  clear_dialog_btn = gr.Button("清空对话", variant="secondary")
462
 
463
  def _clear_chat():
464
- return [], "", [], "", ""
465
 
466
  clear_dialog_btn.click(
467
  fn=_clear_chat,
468
  inputs=None,
469
- outputs=[chatbot, user_input, chat_state, gdl_file_path, narrative_file_path], # 🟩【修改】输出改为5个
 
 
 
 
 
 
 
 
 
 
 
 
 
470
  )
471
 
472
  # ==================== 下载按钮部分 ====================
473
  with gr.Row():
474
- gr.Markdown("### 下载 GDL 和自然语言描述")
475
  download_gdl_btn = gr.Button("下载 GDL 文件", variant="secondary") # 下载 GDL 按钮
476
  download_narrative_btn = gr.Button("下载自然语言文件", variant="secondary") # 下载自然语言按钮
 
477
 
478
  download_gdl_file = gr.File(label="GDL 文件", interactive=False) # 文件下载区域
479
  download_narrative_file = gr.File(label="自然语言文件", interactive=False) # 文件下载区域
 
480
 
481
  # 🟩【修改】绑定下载按钮与文件路径 - 修复版本
482
  def get_gdl_file(gdl_path):
@@ -489,6 +805,11 @@ with gr.Blocks(
489
  return narrative_path
490
  return None
491
 
 
 
 
 
 
492
  # 绑定下载按钮与文件路径
493
  download_gdl_btn.click(
494
  fn=get_gdl_file,
@@ -502,6 +823,12 @@ with gr.Blocks(
502
  outputs=[download_narrative_file]
503
  )
504
 
 
 
 
 
 
 
505
  # ==================== 事件绑定(左侧) ====================
506
  clear_cache_btn.click(fn=clear_cache, outputs=[cache_status])
507
  clear_files_btn.click(fn=clear_files, outputs=[file_uploader])
@@ -534,4 +861,3 @@ if __name__ == "__main__":
534
  # 某些版本 queue() 可能参数或签名不同,直接跳过即可
535
  app = demo
536
  app.launch(share=True, show_api=False)
537
-
 
41
  except Exception:
42
  design_mahjong_game_stream = None
43
 
44
+ from design_state import (
45
+ extract_design_state,
46
+ extract_ready_to_generate,
47
+ summarize_design_state,
48
+ diff_keys,
49
+ diff_mechanics,
50
+ is_change_within_scope,
51
+ )
52
+
53
 
54
  # ====== 🔧 Hotfix: 兼容 gradio_client 对 additionalProperties(bool) 的解析 ======
55
  try:
 
295
  return gdl_file_path, narrative_file_path
296
 
297
 
298
+ def extract_design_log(content):
299
+ """
300
+ 提取“设计日志(创新推演摘要)”段落,用于单独导出。
301
+ 规则:从标题行开始,截到下一个同级标题(###)或文件结尾。
302
+ """
303
+ import re
304
+
305
+ if not content:
306
+ return ""
307
+
308
+ m = re.search(r"^###\\s*设计日志(创新推演摘要)\\s*$", content, re.MULTILINE)
309
+ if not m:
310
+ return ""
311
+ start = m.start()
312
+
313
+ m2 = re.search(r"^###\\s+.+$", content[m.end():], re.MULTILINE)
314
+ end = (m.end() + m2.start()) if m2 else len(content)
315
+ return content[start:end].strip()
316
+
317
+
318
+ def save_design_log(design_log_content):
319
+ export_dir = os.path.join("exports")
320
+ os.makedirs(export_dir, exist_ok=True)
321
+ design_log_file_path = os.path.join(export_dir, "design_log_output.txt")
322
+ with open(design_log_file_path, "w", encoding="utf-8") as f:
323
+ f.write(design_log_content or "")
324
+ return design_log_file_path
325
+
326
+
327
  # ==================== Gradio 界面(Mahjong Skin) ====================
328
  with gr.Blocks(
329
  theme=gr.themes.Soft(primary_hue='green', neutral_hue='slate'),
 
407
  chat_state = gr.State([]) # list[dict]: [{"role":"user","content":...}, {"role":"assistant","content":...}]
408
  gdl_file_path = gr.State("")
409
  narrative_file_path = gr.State("")
410
+ design_log_file_path = gr.State("")
411
+ design_state_raw = gr.State("") # 上一次可机读 DesignState(JSON) 原文
412
+ design_state_obj = gr.State({}) # 解析后的 dict(用于显示与对比)
413
+ design_state_version = gr.State(0) # 版本号(每次成功提取 +1)
414
+ ready_to_generate = gr.State(False)
415
+
416
+ with gr.Group(elem_classes="side-card"):
417
+ gr.Markdown("### 可控迭代(推荐)")
418
+ iterative_mode = gr.Checkbox(
419
+ label="启用可控迭代:基于上轮 DesignState 做最小修改",
420
+ value=True,
421
+ )
422
+ analyse_mode = gr.Checkbox(
423
+ label="Analyse 模式:单问题迭代完善需求(不生成mGDL)",
424
+ value=False,
425
+ )
426
+ ready_status = gr.Markdown("READY_TO_GENERATE:未知", elem_classes="hint")
427
+ iteration_scope = gr.Dropdown(
428
+ label="本轮允许修改范围",
429
+ choices=[
430
+ "自由迭代(仍保最小修改)",
431
+ "仅优化创新机制",
432
+ "仅优化计分与番型",
433
+ "仅优化流程与阶段",
434
+ "仅修复校验问题",
435
+ ],
436
+ value="仅优化创新机制",
437
+ )
438
+ generate_from_state_btn = gr.Button("基于当前 DesignState 生成完整玩法", variant="primary")
439
+ design_state_status = gr.Markdown("DesignState:未建立(先生成一版玩法)", elem_classes="hint")
440
 
441
  user_input = gr.Textbox(
442
  placeholder="例如:为4人竞速推倒胡设计番型与流程;或“做一个双人合作麻将 roguelike” …",
 
452
  stop_info = gr.Markdown("", visible=False)
453
 
454
  # ====== 核心:流式提交回调(生成器) ======
455
+ def on_submit(
456
+ user_text,
457
+ history_msgs,
458
+ files,
459
+ custom_prompt,
460
+ mode,
461
+ iterative_enabled,
462
+ analyse_enabled,
463
+ scope,
464
+ ds_raw_prev,
465
+ ds_obj_prev,
466
+ ds_ver_prev,
467
+ ready_prev,
468
+ ):
469
  user_text = (user_text or "").strip()
470
  if not user_text:
471
  # 不提交空消息:输出不变
472
+ yield history_msgs, "", history_msgs, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:未变更", ready_prev, "READY_TO_GENERATE:未知"
473
  return
474
 
475
  # 立即显示“用户消息”
476
  history = list(history_msgs or [])
477
  history.append({"role": "user", "content": user_text})
478
+ yield history, "", history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:处理中…", ready_prev, "READY_TO_GENERATE:未知"
479
 
480
  # 添加空的助手气泡,用于逐步填充
481
  history.append({"role": "assistant", "content": ""})
482
+ yield history, "", history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:处理中…", ready_prev, "READY_TO_GENERATE:未知"
483
 
484
  # 流式生成内容
485
  tuples_hist = _messages_to_tuples(history)
486
 
487
+ # 可控迭代:基于上轮 DesignState 做“最小修改”,并尽量减少历史噪声
488
+ iterative_enabled = bool(iterative_enabled)
489
+ analyse_enabled = bool(analyse_enabled)
490
+ scope = (scope or "").strip()
491
+ effective_user_text = user_text
492
+ tuples_to_send = tuples_hist
493
+ status_hint = "DesignState:未变更"
494
+ ready_to_gen = ready_prev if isinstance(ready_prev, bool) else False
495
+ ready_md = "READY_TO_GENERATE:未知"
496
+
497
+ if analyse_enabled:
498
+ tuples_to_send = [] # Analyse 模式不吃长history,避免漂移
499
+ effective_user_text = (
500
+ "<ANALYSE_MODE>true</ANALYSE_MODE>\n"
501
+ "你正在进行【Analyse 模式】(单问题迭代)。\n"
502
+ "目标:通过多轮问答把需求场景收敛到可生成完整玩法。\n"
503
+ "限制:本轮禁止输出 mGDL/完整规则/自检报告。\n\n"
504
+ "当前已有 DesignState(如为空表示尚未建立初版):\n"
505
+ "<DESIGN_STATE_JSON>\n{ds}\n</DESIGN_STATE_JSON>\n\n"
506
+ "用户本轮补充信息:\n{req}\n"
507
+ ).format(ds=(ds_raw_prev or "{}").strip(), req=user_text)
508
+ status_hint = "DesignState:Analyse模式中…"
509
+ elif iterative_enabled and (ds_raw_prev or "").strip():
510
+ tuples_to_send = [] # 用“当前 DesignState”替代长历史,减少漂移
511
+ effective_user_text = (
512
+ "你正在进行【可控迭代】。请基于下方 DesignState(JSON) 对方案做【最小修改】。\n"
513
+ "本轮允许修改范围:{scope}\n"
514
+ "硬约束:\n"
515
+ "1) 除允许范围外的字段一律保持不变;若必须改动范围外字段,先提出澄清问题并停止输出 mGDL。\n"
516
+ "2) 必须输出新的 DesignState(JSON)(合法JSON、无注释)+ 变更摘要(列出改动点)。\n"
517
+ "3) 仍需按 m_prompt 输出完整结果(规则 + mGDL + 自检)。\n\n"
518
+ "<DESIGN_STATE_JSON>\n{ds}\n</DESIGN_STATE_JSON>\n\n"
519
+ "【用户本轮优化要求】\n{req}\n"
520
+ ).format(scope=scope or "自由迭代(仍保最小修改)", ds=ds_raw_prev.strip(), req=user_text)
521
+ status_hint = "DesignState:可控迭代中…"
522
+
523
  if design_mahjong_game_stream is not None:
524
  try:
525
+ for piece in design_mahjong_game_stream(effective_user_text, tuples_to_send, files, custom_prompt, mode):
526
  if not piece:
527
  continue
528
  history[-1]["content"] += str(piece)
529
+ yield history, "", history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, status_hint, ready_to_gen, ready_md
530
  except Exception as e:
531
  history[-1]["content"] += f"\n(流式出错){type(e).__name__}: {e}"
532
+ yield history, "", history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:流式出错(未变更)", ready_to_gen, "READY_TO_GENERATE:未知"
533
  else:
534
  try:
535
+ full = design_mahjong_game(effective_user_text, tuples_to_send, files, custom_prompt, mode)
536
  except Exception as e:
537
  full = f"(出错){type(e).__name__}: {e}"
538
  for piece in _chunk_fake_stream(str(full), step=40):
539
  history[-1]["content"] += piece
540
+ yield history, "", history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, status_hint, ready_to_gen, ready_md
541
 
542
  # 提取 GDL 和自然语言描述并保存
543
+ new_ds_obj, new_ds_raw = extract_design_state(history[-1]["content"])
544
+ ready_flag = extract_ready_to_generate(history[-1]["content"])
545
+ ds_ver = int(ds_ver_prev or 0)
546
+ ds_status = "DesignState:未变更"
547
+ if new_ds_obj and new_ds_raw:
548
+ ds_ver = ds_ver + 1
549
+ ds_status = "DesignState:v{0} 已更新 | {1}".format(ds_ver, summarize_design_state(new_ds_obj))
550
+ if isinstance(ready_flag, bool):
551
+ ready_to_gen = ready_flag
552
+ ready_md = "READY_TO_GENERATE:{0}".format("true" if ready_flag else "false")
553
+
554
+ # 可控迭代:做一个“范围越界”软检查(不阻断,只提示)
555
+ if iterative_enabled and ds_obj_prev and isinstance(ds_obj_prev, dict) and scope:
556
+ changed = diff_keys(ds_obj_prev, new_ds_obj)
557
+ mech_changes = diff_mechanics(ds_obj_prev, new_ds_obj)
558
+ if not is_change_within_scope(changed, scope):
559
+ history[-1]["content"] += (
560
+ "\n\n---\n⚠️ 可控迭代检查:检测到可能超出允许范围的改动。\n"
561
+ "允许范围:{scope}\n"
562
+ "顶层变更字段:{keys}\n"
563
+ "机制变更:{mech}\n"
564
+ "建议:请重新执行一次迭代,明确只改允许范围内字段,或切换为“自由迭代”。\n"
565
+ ).format(
566
+ scope=scope,
567
+ keys=",".join(changed) if changed else "(无)",
568
+ mech="; ".join(mech_changes) if mech_changes else "(无)",
569
+ )
570
+
571
  try:
572
+ # Analyse 模式不产出完整规则,不导出GDL/自然语言文件
573
+ if analyse_enabled:
574
+ yield history, "", history, "", "", "", (new_ds_raw or ds_raw_prev), (new_ds_obj or ds_obj_prev), ds_ver, ds_status, ready_to_gen, ready_md
575
+ return
576
+
577
  gdl_content, narrative_content = extract_gdl_and_narrative(history[-1]["content"])
578
+ design_log_content = extract_design_log(history[-1]["content"])
579
 
580
  # 保存 GDL 和自然语言文件
581
  gdl_path, narrative_path = save_gdl_and_narrative(gdl_content, narrative_content)
582
+ design_log_path = save_design_log(design_log_content)
583
 
584
  # 返回文件路径,以便下载
585
+ yield history, "", history, gdl_path, narrative_path, design_log_path, (new_ds_raw or ds_raw_prev), (new_ds_obj or ds_obj_prev), ds_ver, ds_status, ready_to_gen, ready_md
586
  except Exception as e:
587
  print(f"保存GDL和自然语言文件时出错: {e}")
588
+ yield history, "", history, "", "", "", (new_ds_raw or ds_raw_prev), (new_ds_obj or ds_obj_prev), ds_ver, ds_status, ready_to_gen, ready_md
589
+
590
+ def on_generate_from_state(
591
+ history_msgs,
592
+ files,
593
+ custom_prompt,
594
+ mode,
595
+ ds_raw_prev,
596
+ ds_obj_prev,
597
+ ds_ver_prev,
598
+ ready_prev,
599
+ ):
600
+ if not (ds_raw_prev or "").strip():
601
+ yield history_msgs, history_msgs, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:未建立(先生成一版玩法)", ready_prev, "READY_TO_GENERATE:未知"
602
+ return
603
+
604
+ history = list(history_msgs or [])
605
+ user_text = "基于当前 DesignState 生成完整玩法(自然语言规则 + mGDL + 自检报告)。"
606
+ history.append({"role": "user", "content": user_text})
607
+ yield history, history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:生成中…", ready_prev, "READY_TO_GENERATE:未知"
608
+
609
+ history.append({"role": "assistant", "content": ""})
610
+ yield history, history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:生成中…", ready_prev, "READY_TO_GENERATE:未知"
611
+
612
+ effective_user_text = (
613
+ "请基于下方 DesignState(JSON) 生成完整的麻将新玩法交付物:\n"
614
+ "1) 自然语言规则说明(含机制声明表)\n"
615
+ "2) 完整 mGDL v1.3(按 m_prompt 格式)\n"
616
+ "3) 自检报告\n"
617
+ "要求:保持 DesignState 的核心设定不漂移;若发现 DesignState 信息不足,请先提出澄清问题并停止输出 mGDL。\n\n"
618
+ "<DESIGN_STATE_JSON>\n{ds}\n</DESIGN_STATE_JSON>\n"
619
+ ).format(ds=ds_raw_prev.strip())
620
+
621
+ tuples_to_send = []
622
+ buf = []
623
+ try:
624
+ if design_mahjong_game_stream is not None:
625
+ for piece in design_mahjong_game_stream(effective_user_text, tuples_to_send, files, custom_prompt, mode):
626
+ if not piece:
627
+ continue
628
+ s = str(piece)
629
+ buf.append(s)
630
+ history[-1]["content"] += s
631
+ yield history, history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:生成中…", ready_prev, "READY_TO_GENERATE:未知"
632
+ else:
633
+ full = design_mahjong_game(effective_user_text, tuples_to_send, files, custom_prompt, mode)
634
+ buf.append(str(full))
635
+ for piece in _chunk_fake_stream(str(full), step=40):
636
+ history[-1]["content"] += piece
637
+ yield history, history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:生成中…", ready_prev, "READY_TO_GENERATE:未知"
638
+ except Exception as e:
639
+ history[-1]["content"] += f"\n(生成出错){type(e).__name__}: {e}"
640
+ yield history, history, "", "", "", ds_raw_prev, ds_obj_prev, ds_ver_prev, "DesignState:生成出错", ready_prev, "READY_TO_GENERATE:未知"
641
+ return
642
+
643
+ new_ds_obj, new_ds_raw = extract_design_state(history[-1]["content"])
644
+ ds_ver = int(ds_ver_prev or 0)
645
+ ds_status = "DesignState:未变更"
646
+ if new_ds_obj and new_ds_raw:
647
+ ds_ver += 1
648
+ ds_status = "DesignState:v{0} 已更新 | {1}".format(ds_ver, summarize_design_state(new_ds_obj))
649
+
650
+ try:
651
+ gdl_content, narrative_content = extract_gdl_and_narrative(history[-1]["content"])
652
+ design_log_content = extract_design_log(history[-1]["content"])
653
+ gdl_path, narrative_path = save_gdl_and_narrative(gdl_content, narrative_content)
654
+ design_log_path = save_design_log(design_log_content)
655
+ yield history, history, gdl_path, narrative_path, design_log_path, (new_ds_raw or ds_raw_prev), (new_ds_obj or ds_obj_prev), ds_ver, ds_status, ready_prev, "READY_TO_GENERATE:未知"
656
+ except Exception:
657
+ yield history, history, "", "", "", (new_ds_raw or ds_raw_prev), (new_ds_obj or ds_obj_prev), ds_ver, ds_status, ready_prev, "READY_TO_GENERATE:未知"
658
 
659
  # 绑定:回车提交(Enter=提交;Shift+Enter=换行由浏览器处理)
660
  user_input.submit(
661
  fn=on_submit,
662
+ inputs=[
663
+ user_input,
664
+ chat_state,
665
+ file_uploader,
666
+ custom_prompt_box,
667
+ prompt_mode,
668
+ iterative_mode,
669
+ analyse_mode,
670
+ iteration_scope,
671
+ design_state_raw,
672
+ design_state_obj,
673
+ design_state_version,
674
+ ready_to_generate,
675
+ ],
676
+ outputs=[
677
+ chatbot,
678
+ user_input,
679
+ chat_state,
680
+ gdl_file_path,
681
+ narrative_file_path,
682
+ design_log_file_path,
683
+ design_state_raw,
684
+ design_state_obj,
685
+ design_state_version,
686
+ design_state_status,
687
+ ready_to_generate,
688
+ ready_status,
689
+ ],
690
  preprocess=True,
691
  )
692
 
693
  # 绑定:点击"发送"
694
  send_btn.click(
695
  fn=on_submit,
696
+ inputs=[
697
+ user_input,
698
+ chat_state,
699
+ file_uploader,
700
+ custom_prompt_box,
701
+ prompt_mode,
702
+ iterative_mode,
703
+ analyse_mode,
704
+ iteration_scope,
705
+ design_state_raw,
706
+ design_state_obj,
707
+ design_state_version,
708
+ ready_to_generate,
709
+ ],
710
+ outputs=[
711
+ chatbot,
712
+ user_input,
713
+ chat_state,
714
+ gdl_file_path,
715
+ narrative_file_path,
716
+ design_log_file_path,
717
+ design_state_raw,
718
+ design_state_obj,
719
+ design_state_version,
720
+ design_state_status,
721
+ ready_to_generate,
722
+ ready_status,
723
+ ],
724
+ preprocess=True,
725
+ )
726
+
727
+ generate_from_state_btn.click(
728
+ fn=on_generate_from_state,
729
+ inputs=[
730
+ chat_state,
731
+ file_uploader,
732
+ custom_prompt_box,
733
+ prompt_mode,
734
+ design_state_raw,
735
+ design_state_obj,
736
+ design_state_version,
737
+ ready_to_generate,
738
+ ],
739
+ outputs=[
740
+ chatbot,
741
+ chat_state,
742
+ gdl_file_path,
743
+ narrative_file_path,
744
+ design_log_file_path,
745
+ design_state_raw,
746
+ design_state_obj,
747
+ design_state_version,
748
+ design_state_status,
749
+ ready_to_generate,
750
+ ready_status,
751
+ ],
752
  preprocess=True,
753
  )
754
 
 
762
  clear_dialog_btn = gr.Button("清空对话", variant="secondary")
763
 
764
  def _clear_chat():
765
+ return [], "", [], "", "", "", "", {}, 0, "DesignState:未建立(先生成一版玩法)", False, "READY_TO_GENERATE:未知"
766
 
767
  clear_dialog_btn.click(
768
  fn=_clear_chat,
769
  inputs=None,
770
+ outputs=[
771
+ chatbot,
772
+ user_input,
773
+ chat_state,
774
+ gdl_file_path,
775
+ narrative_file_path,
776
+ design_log_file_path,
777
+ design_state_raw,
778
+ design_state_obj,
779
+ design_state_version,
780
+ design_state_status,
781
+ ready_to_generate,
782
+ ready_status,
783
+ ],
784
  )
785
 
786
  # ==================== 下载按钮部分 ====================
787
  with gr.Row():
788
+ gr.Markdown("### 下载输出文件")
789
  download_gdl_btn = gr.Button("下载 GDL 文件", variant="secondary") # 下载 GDL 按钮
790
  download_narrative_btn = gr.Button("下载自然语言文件", variant="secondary") # 下载自然语言按钮
791
+ download_design_log_btn = gr.Button("下载思维日志文件", variant="secondary")
792
 
793
  download_gdl_file = gr.File(label="GDL 文件", interactive=False) # 文件下载区域
794
  download_narrative_file = gr.File(label="自然语言文件", interactive=False) # 文件下载区域
795
+ download_design_log_file = gr.File(label="思维日志文件", interactive=False)
796
 
797
  # 🟩【修改】绑定下载按钮与文件路径 - 修复版本
798
  def get_gdl_file(gdl_path):
 
805
  return narrative_path
806
  return None
807
 
808
+ def get_design_log_file(design_log_path):
809
+ if design_log_path and os.path.exists(design_log_path):
810
+ return design_log_path
811
+ return None
812
+
813
  # 绑定下载按钮与文件路径
814
  download_gdl_btn.click(
815
  fn=get_gdl_file,
 
823
  outputs=[download_narrative_file]
824
  )
825
 
826
+ download_design_log_btn.click(
827
+ fn=get_design_log_file,
828
+ inputs=[design_log_file_path],
829
+ outputs=[download_design_log_file],
830
+ )
831
+
832
  # ==================== 事件绑定(左侧) ====================
833
  clear_cache_btn.click(fn=clear_cache, outputs=[cache_status])
834
  clear_files_btn.click(fn=clear_files, outputs=[file_uploader])
 
861
  # 某些版本 queue() 可能参数或签名不同,直接跳过即可
862
  app = demo
863
  app.launch(share=True, show_api=False)
 
config.py CHANGED
@@ -32,3 +32,18 @@ APP_TITLE = "🀄️ 麻将玩法创意工坊"
32
  CHATBOT_HEIGHT = 640
33
  MIN_WIDTH_LEFT = 320
34
  MIN_WIDTH_RIGHT = 640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  CHATBOT_HEIGHT = 640
33
  MIN_WIDTH_LEFT = 320
34
  MIN_WIDTH_RIGHT = 640
35
+
36
+ # ==================== 生成质量增强(可开关) ====================
37
+ # 是否启用“参考玩法检索注入”(只注入与用户需求最相关的少量参考,而不是全量示例堆叠)
38
+ ENABLE_REFERENCE_RETRIEVAL = (os.getenv("ENABLE_REFERENCE_RETRIEVAL") or "1").strip() == "1"
39
+ # 最多注入多少个参考玩法(每个玩法会注入 .md(主) + 对应 mGDL(辅))
40
+ REFERENCE_MAX_VARIANTS = int((os.getenv("REFERENCE_MAX_VARIANTS") or "3").strip())
41
+ # 是否注入“参考玩法 mGDL”(默认关闭;mGDL更适合做语法约束而非RAG语义参考)
42
+ INJECT_REFERENCE_MGDL = (os.getenv("INJECT_REFERENCE_MGDL") or "0").strip() == "1"
43
+ # 是否仍注入全量示例 mGDL(不推荐,容易稀释注意力)
44
+ INJECT_ALL_EXAMPLE_GDL = (os.getenv("INJECT_ALL_EXAMPLE_GDL") or "0").strip() == "1"
45
+
46
+ # 是否对模型输出做静态校验(缺模块/占位符/缺少 mGDL 等)
47
+ ENABLE_OUTPUT_VALIDATION = (os.getenv("ENABLE_OUTPUT_VALIDATION") or "1").strip() == "1"
48
+ # 非流式路径下:校验失败时是否自动追加一次“最小修改修复”调用(成本更高,但更稳)
49
+ ENABLE_AUTO_REPAIR = (os.getenv("ENABLE_AUTO_REPAIR") or "0").strip() == "1"
design_state.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ DesignState 解析与差分(用于“多轮可控迭代”)。
3
+
4
+ 约定:
5
+ - 模型需在回答中输出一个 ```json ...``` 代码块作为 DesignState
6
+ - 该 JSON 应包含 new_variant_name / mechanics 等关键字段
7
+ """
8
+
9
+ import json
10
+ import re
11
+ from typing import Any, Dict, List, Optional, Tuple
12
+
13
+
14
+ _JSON_FENCE_RE = re.compile(r"```json\s*(\{.*?\})\s*```", re.DOTALL | re.IGNORECASE)
15
+ _READY_RE = re.compile(r"READY_TO_GENERATE\s*:\s*(true|false)", re.IGNORECASE)
16
+
17
+
18
+ def extract_design_state(text: str) -> Tuple[Optional[Dict[str, Any]], str]:
19
+ """
20
+ 返回:(state_dict_or_none, raw_json_or_empty)
21
+ """
22
+ if not text:
23
+ return None, ""
24
+
25
+ candidates = _JSON_FENCE_RE.findall(text)
26
+ if not candidates:
27
+ return None, ""
28
+
29
+ # 选择“最像 DesignState”的 JSON:包含几个关键字段
30
+ best_raw = ""
31
+ best_score = -1
32
+ best_obj = None
33
+ for raw in candidates:
34
+ raw = (raw or "").strip()
35
+ try:
36
+ obj = json.loads(raw)
37
+ except Exception:
38
+ continue
39
+
40
+ score = 0
41
+ for k in ["new_variant_name", "mechanics", "tileset", "game_variant", "scoring_mode"]:
42
+ if k in obj:
43
+ score += 1
44
+ if score > best_score:
45
+ best_score = score
46
+ best_raw = raw
47
+ best_obj = obj
48
+
49
+ return best_obj, best_raw
50
+
51
+
52
+ def extract_ready_to_generate(text: str) -> Optional[bool]:
53
+ """
54
+ 从文本中提取 READY_TO_GENERATE: true/false
55
+ 返回 None 表示未提供该标记。
56
+ """
57
+ if not text:
58
+ return None
59
+ m = _READY_RE.search(text)
60
+ if not m:
61
+ return None
62
+ return m.group(1).lower() == "true"
63
+
64
+
65
+ def summarize_design_state(state: Dict[str, Any]) -> str:
66
+ if not state:
67
+ return ""
68
+ name = str(state.get("new_variant_name") or "").strip()
69
+ base = state.get("base_variants") or []
70
+ fusion = state.get("fusion_variants") or []
71
+ mechanics = state.get("mechanics") or []
72
+ return "玩法:{0} | 底座:{1} | 融合:{2} | 机制数:{3}".format(
73
+ name or "(未命名)",
74
+ ",".join(base) if isinstance(base, list) else str(base),
75
+ ",".join(fusion) if isinstance(fusion, list) else str(fusion),
76
+ len(mechanics) if isinstance(mechanics, list) else 0,
77
+ )
78
+
79
+
80
+ def diff_keys(prev: Dict[str, Any], cur: Dict[str, Any]) -> List[str]:
81
+ """
82
+ 粗粒度:仅比较顶层 key 的变化(新增/删除/值变更)。
83
+ """
84
+ if prev is None or cur is None:
85
+ return []
86
+
87
+ changed = set()
88
+ prev_keys = set(prev.keys())
89
+ cur_keys = set(cur.keys())
90
+ for k in prev_keys.symmetric_difference(cur_keys):
91
+ changed.add(k)
92
+ for k in prev_keys.intersection(cur_keys):
93
+ if prev.get(k) != cur.get(k):
94
+ changed.add(k)
95
+ return sorted(changed)
96
+
97
+
98
+ def diff_mechanics(prev: Dict[str, Any], cur: Dict[str, Any]) -> List[str]:
99
+ """
100
+ 简单机制差分:按 mechanic.name 对齐,输出变更摘要字符串列表。
101
+ """
102
+ prev_list = prev.get("mechanics") if isinstance(prev, dict) else None
103
+ cur_list = cur.get("mechanics") if isinstance(cur, dict) else None
104
+ if not isinstance(prev_list, list) or not isinstance(cur_list, list):
105
+ return []
106
+
107
+ def to_map(lst: List[Dict[str, Any]]) -> Dict[str, Dict[str, Any]]:
108
+ out = {}
109
+ for it in lst:
110
+ if not isinstance(it, dict):
111
+ continue
112
+ name = str(it.get("name") or "").strip()
113
+ if not name:
114
+ continue
115
+ out[name] = it
116
+ return out
117
+
118
+ pm = to_map(prev_list)
119
+ cm = to_map(cur_list)
120
+ changes = []
121
+
122
+ for name in sorted(set(pm.keys()) | set(cm.keys())):
123
+ if name not in pm:
124
+ changes.append("新增机制: {0}".format(name))
125
+ continue
126
+ if name not in cm:
127
+ changes.append("删除机制: {0}".format(name))
128
+ continue
129
+ if pm[name] == cm[name]:
130
+ continue
131
+ # 只输出变了哪些字段(不展开值)
132
+ fields = sorted(set(pm[name].keys()) | set(cm[name].keys()))
133
+ touched = [f for f in fields if pm[name].get(f) != cm[name].get(f)]
134
+ changes.append("机制变更: {0} 字段={1}".format(name, ",".join(touched)))
135
+
136
+ return changes
137
+
138
+
139
+ def is_change_within_scope(changed_top_keys: List[str], scope: str) -> bool:
140
+ """
141
+ 软约束:判断顶层改动是否落在预设范围内。
142
+ """
143
+ if not scope or scope == "自由迭代(仍保最小修改)":
144
+ return True
145
+
146
+ allowed = set()
147
+ if scope == "仅优化创新机制":
148
+ allowed.update(["mechanics", "open_questions", "core_constraints"])
149
+ elif scope == "仅优化计分与番型":
150
+ allowed.update(["scoring_mode"])
151
+ elif scope == "仅优化流程与阶段":
152
+ allowed.update(["game_variant"])
153
+ elif scope == "仅修复校验问题":
154
+ # 允许改动更宽一些:常见缺失字段补齐
155
+ allowed.update([
156
+ "mechanics",
157
+ "tileset",
158
+ "core_constraints",
159
+ "players",
160
+ "game_variant",
161
+ "scoring_mode",
162
+ ])
163
+ else:
164
+ return True
165
+
166
+ # 名称/来源类字段默认不允许在“仅优化”里被改(除非自由迭代)
167
+ forbidden = {"new_variant_name", "base_variants", "fusion_variants"}
168
+ for k in changed_top_keys:
169
+ if k in forbidden:
170
+ return False
171
+ if k not in allowed:
172
+ return False
173
+ return True
m_prompt.txt CHANGED
@@ -17,11 +17,12 @@
17
  你是一位专业的麻将游戏设计专家,精通血战麻将、血流麻将、广东鸡平胡、武汉麻将等各类麻将变体的规则设计。你的任务是严格按照四步流程,输出一个完整、合规、创新的麻将新玩法方案,包含:
18
 
19
  1. **思考与自检过程**(含自检报告与修复轨迹)
20
- 2. **游戏名称与理念**
21
- 3. **符合 mGDL 规范的完整 mGDL 描述(带中文注释)**
22
- 4. **对应的自然语言则说明**含机制声明、流程、得分、番型等
23
- 5. **平衡性分析**
24
- 6. **术语词典**
 
25
 
26
  ## 核心参照资源
27
 
@@ -63,8 +64,14 @@
63
  5. **主次分明原则(Primary-Auxiliary Principle)**:
64
  - **当同时存在自然语言文档(.md)和 mGDL 文件(.txt)时**:
65
  - **主文档(Primary)= 自然语言文档 (.md)**:它是**内容真理**。玩法的风味、设计初衷、非数值体验、特殊规则描述以 .md 为准。
66
- - **辅文档(Auxiliary)= mGDL 文件 (.txt)**:它是**语法参考**。仅用于参考如何用合法的 v1.3 语法将 .md 中的规则“翻译”成代码,**严禁**因为 mGDL 文件中缺少某个细节而丢弃 .md 中的设计。
 
 
 
67
  - **冲突解决**:若 .md 说“摸2打1”,而 .txt 示例说“摸1打1”,**以 .md 为准**,必须编写出支持“摸2打1”的新 mGDL 代码,而不是照抄旧代码。
 
 
 
68
 
69
  ## 统一约定(强制)
70
 
@@ -758,6 +765,29 @@
758
  ## 输出格式
759
  请严格按照以下格式输出:
760
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
761
  ### 思考与自检过程
762
  请在此处用自然语言描述:
763
  - 你执行了哪些关键检查
@@ -765,6 +795,58 @@
765
  - 如何按"最小修改优先级"进行修复
766
  - 最终确认所有项已通过:(无需包含结构化 [PASS/FAIL] 表格)
767
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
768
  ### 游戏名称
769
  [游戏名称]
770
 
@@ -814,8 +896,9 @@
814
 
815
  #### 生成策略:
816
  1. 先在心中构建完整的游戏逻辑
817
- 2. 参考通用语规范确定语法正确性
818
- 3. 参考示例文件保每个模块的详细程度
 
819
  4. 逐模块编写,每个模块的细节要合理、充分、符合逻辑
820
  5. 严禁为了"节省篇幅"而省略任何模块的详细定义
821
 
 
17
  你是一位专业的麻将游戏设计专家,精通血战麻将、血流麻将、广东鸡平胡、武汉麻将等各类麻将变体的规则设计。你的任务是严格按照四步流程,输出一个完整、合规、创新的麻将新玩法方案,包含:
18
 
19
  1. **思考与自检过程**(含自检报告与修复轨迹)
20
+ 2. **设计日志(创新推演摘要)**:输出“候选方案对比 + 取舍理由 + 推演摘要 + 落地映射”,用于审核“创新不是文本拼接”
21
+ 3. **游戏名称与理念**
22
+ 4. **符合 mGDL 范的完整 mGDL 描述带中文注释**
23
+ 5. **对应的自然语言规则说明**(含机制声明、流程、得分、番型等)
24
+ 6. **平衡性分析**
25
+ 7. **术语词典**
26
 
27
  ## 核心参照资源
28
 
 
64
  5. **主次分明原则(Primary-Auxiliary Principle)**:
65
  - **当同时存在自然语言文档(.md)和 mGDL 文件(.txt)时**:
66
  - **主文档(Primary)= 自然语言文档 (.md)**:它是**内容真理**。玩法的风味、设计初衷、非数值体验、特殊规则描述以 .md 为准。
67
+ - **辅文档(Auxiliary)= mGDL 文件 (.txt)**:它是**语法/结构参考**,不是规则真理。仅用于参考如何用合法的 v1.3 语法将 .md 中的规则“翻译”成代码
68
+ - ✅ 允许参考:模块结构、字段写法、合法枚举、注释风格、invariants 写法模板
69
+ - ❌ 严禁参考:把示例中的具体数值/倍数/牌数/限制条件当作新玩法规则依据(除非 .md 也明确这样写)
70
+ - ❌ 严禁推断:不得仅凭 mGDL 示例“猜测”规则细节(尤其是牌组构成、发牌/摸牌节奏、结算公式)
71
  - **冲突解决**:若 .md 说“摸2打1”,而 .txt 示例说“摸1打1”,**以 .md 为准**,必须编写出支持“摸2打1”的新 mGDL 代码,而不是照抄旧代码。
72
+ - **RAG 上下文使用规则(重要)**:
73
+ - 若系统注入了参考玩法 `.md`,你必须将其视为“规则真理片段”,并在融合分析中明确引用其机制点(无需逐行引用)。
74
+ - 若系统注入了参考玩法 mGDL(可能默认不注入),你只能把它当作“语法写法范例”,不得把它当作规则来源。
75
 
76
  ## 统一约定(强制)
77
 
 
765
  ## 输出格式
766
  请严格按照以下格式输出:
767
 
768
+ ## 可控迭代:Analyse 模式(单问题迭代,强制)
769
+
770
+ 当且仅当用户输入中包含:
771
+ `<ANALYSE_MODE>true</ANALYSE_MODE>`
772
+
773
+ 你必须进入【Analyse 模式】,遵守以下规则(用于多轮可控迭代,而不是一次性生成大稿):
774
+ 1. **只允许做需求澄清与方案收敛**:不输出 mGDL、不输出完整自然语言规则、不输出自检报告。
775
+ 2. **严格单问题迭代**:每轮只能问 1 个“当前最重要”的澄清问题;禁止一次列出多个问题。
776
+ 3. **每轮必须输出更新后的 DesignState(JSON)**:把你已确认的信息写入 JSON;未知信息写入 `open_questions`。
777
+ 4. **退出条件**:当 `open_questions` 为空,或只剩“用户可选项”(非阻塞)时,输出一句 `READY_TO_GENERATE: true`;否则 `READY_TO_GENERATE: false`。
778
+
779
+ Analyse 模式下的输出格式固定为:
780
+ - 一句话总结当前理解(≤60字)
781
+ - 本轮唯一问题(只问1个)
782
+ - 思维日志(本轮增量,≤200字):只解释“本轮为什么问这个问题/它影响哪些设计选择/你打算如何收敛创新”,不得展开完整规则
783
+ - ```json DesignState ```(合法JSON)
784
+ - `READY_TO_GENERATE: true/false`
785
+
786
+ **⚠️ Analyse 模式的思维日志要求(硬性)**
787
+ - 必须明确:本轮问题的“目的”(解决哪个不确定点)
788
+ - 必须明确:它将影响的“创新旋钮”(触发/代价/收益/反制/计分/流程中的哪一处)
789
+ - 必须避免:给出两条以上的新问题,或提前输出完整规则细节
790
+
791
  ### 思考与自检过程
792
  请在此处用自然语言描述:
793
  - 你执行了哪些关键检查
 
795
  - 如何按"最小修改优先级"进行修复
796
  - 最终确认所有项已通过:(无需包含结构化 [PASS/FAIL] 表格)
797
 
798
+ ### 设计日志(创新推演摘要)
799
+ 请用“可审核的决策记录”替代泛泛的灵感描述,必须包含:
800
+ 1. **目标体验**:你希望新玩法比底座玩法多出什么“策略选择/互动张力”(≤80字)
801
+ 2. **约束清单**:列出 5 条不可破坏约束(例如:手牌守恒、计分体系统一、牌墙不为负、核心机���≤2 等)
802
+ 3. **候选创新方案 A/B/C(至少2个)**:每个方案必须写清:
803
+ - 状态变量(≤2个) / 触发条件 / 代价 / 奖励或惩罚 / 反制或风险 / 影响的决策点(摸/打/吃碰杠/听/胡/结算)
804
+ 4. **选择理由**:你最终选用哪个方案,为什么放弃其他方案(必须引用上面的约束与风险)
805
+ 5. **推演摘要**:给出 1 个具体回合示例(玩家选择→对手应对→为何分数/胜负成立)
806
+ 6. **落地映射(Crosswalk)**:列出“创新机制名 → mGDL_path → transfer_path(若有)”的对照表,确保可实体化
807
+
808
+ ### DesignState(JSON,可机读)
809
+ 请输出一个 JSON 作为“中间表示”,用于后续多轮迭代的定向修改。要求:
810
+ 1. 必须是合法 JSON(不要写注释,不要用省略号)
811
+ 2. 字段尽量完整,未知时填空字符串或空数组
812
+ 3. `mechanics[].mgdl_path` 必须是点号路径(不要写到 mGDL 代码里)
813
+
814
+ ```json
815
+ {
816
+ "base_variants": ["底座玩法名"],
817
+ "fusion_variants": ["融合玩法名"],
818
+ "new_variant_name": "新玩法名",
819
+ "game_variant": "blood_war|blood_flow|round|multi_round|custom",
820
+ "players": 4,
821
+ "scoring_mode": "multiplier|fan_system|hybrid",
822
+ "tileset": {
823
+ "suits": ["wan","tong","tiao"],
824
+ "honors": 0,
825
+ "special_tiles": [{"name":"红中","count":6}],
826
+ "total": 114
827
+ },
828
+ "core_constraints": [
829
+ "手牌守恒:回合结束回到13张",
830
+ "牌数守恒:所有区域之和=TotalTiles"
831
+ ],
832
+ "mechanics": [
833
+ {
834
+ "name": "机制名",
835
+ "type": "core|aux",
836
+ "state_vars": ["变量1"],
837
+ "phase": "setup|play|settle|global",
838
+ "trigger": "触发条件(确定性)",
839
+ "cost": "代价/限制(确定性)",
840
+ "reward_or_penalty": "奖励/惩罚(可量化)",
841
+ "counterplay": "对手如何应对/反制",
842
+ "mgdl_path": "extensions.special_mechanics.mechanic_cards.<ID>",
843
+ "transfer_path": "from: X to: Y|none"
844
+ }
845
+ ],
846
+ "open_questions": []
847
+ }
848
+ ```
849
+
850
  ### 游戏名称
851
  [游戏名称]
852
 
 
896
 
897
  #### 生成策略:
898
  1. 先在心中构建完整的游戏逻辑
899
+ 2. 先从参考 .md 中抽取:牌组、流程、胡牌、计分、特殊机制与限制(内容真理)
900
+ 3. 参考通用语法规范定 mGDL 语法正确性(语法约束)
901
+ 4. 最后(可选)参考 mGDL 示例确保每个模块的“结构完整度”,但不得照抄规则数值(语法范式)
902
  4. 逐模块编写,每个模块的细节要合理、充分、符合逻辑
903
  5. 严禁为了"节省篇幅"而省略任何模块的详细定义
904
 
output_validator.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ 对模型输出做轻量静态校验(不依赖外部库)。
3
+
4
+ 目标:
5
+ - 提前发现“缺少 mGDL / 缺少核心模块 / 输出里存在占位符”等高频失败
6
+ - 为“最小修改修复”提供结构化的 FAIL 列表
7
+ """
8
+
9
+ import re
10
+ from typing import Dict, List, Optional, Tuple
11
+
12
+
13
+ _FENCE_RE = re.compile(r"```(?:[a-zA-Z0-9_-]+)?\n(.*?)```", re.DOTALL)
14
+
15
+
16
+ def _extract_mgdl_block(text: str) -> str:
17
+ """
18
+ 尝试从回答中提取最像 mGDL 的代码块(优先含 (game ... ))。
19
+ """
20
+ if not text:
21
+ return ""
22
+
23
+ blocks = _FENCE_RE.findall(text)
24
+ if not blocks:
25
+ # 没有代码块时,退化为全文搜索
26
+ return text if "(game " in text else ""
27
+
28
+ best = ""
29
+ for b in blocks:
30
+ b_strip = (b or "").strip()
31
+ if "(game " in b_strip:
32
+ return b_strip
33
+ if b_strip.startswith("(game ") or b_strip.startswith("(define_game"):
34
+ best = b_strip
35
+ return best
36
+
37
+
38
+ def validate_mahjong_response(text: str) -> List[Dict[str, str]]:
39
+ issues: List[Dict[str, str]] = []
40
+ if not text or not text.strip():
41
+ return [{"code": "EMPTY", "level": "error", "message": "模型返回空内容"}]
42
+
43
+ # 1) 占位符检查(m_prompt 强制禁止)
44
+ if any(token in text for token in ["<PID>", "<NextPID>", "<Variant_Name>", "<custom>"]):
45
+ issues.append({
46
+ "code": "PLACEHOLDER",
47
+ "level": "error",
48
+ "message": "输出包含占位符(如 <PID>/<Variant_Name>),需展开为实际值(A1/A2/A3/A4 等)。"
49
+ })
50
+
51
+ mgdl = _extract_mgdl_block(text)
52
+ if not mgdl:
53
+ issues.append({
54
+ "code": "NO_MGDL",
55
+ "level": "error",
56
+ "message": "未检测到 mGDL 代码块或 (game ...) 根节点。"
57
+ })
58
+ return issues
59
+
60
+ # 0.5) 思维日志(设计日志)检查:生成模式下应包含“设计日志(创新推演摘要)”
61
+ # 这是你们的关键交付:创新不是堆叠,需要可审核的决策记录。
62
+ if "设计日志(创新推演摘要)" not in text:
63
+ issues.append({
64
+ "code": "NO_DESIGN_LOG",
65
+ "level": "warning",
66
+ "message": "未检测到“设计日志(创新推演摘要)”段落;建议补齐候选方案/取舍/推演摘要/落地映射。"
67
+ })
68
+
69
+ # 2) 核心模块检查(按 m_prompt 的“零容忍项”)
70
+ required_markers = [
71
+ "(game_variant",
72
+ "(players",
73
+ "(tileset",
74
+ "(extensions",
75
+ "(seats",
76
+ "(turn_order",
77
+ "(setup",
78
+ "(actions",
79
+ "(win_rules",
80
+ "(scoring",
81
+ "(fan_table",
82
+ "(settlement",
83
+ "(invariants",
84
+ ]
85
+
86
+ missing = [m for m in required_markers if m not in mgdl]
87
+ if missing:
88
+ issues.append({
89
+ "code": "MISSING_MODULES",
90
+ "level": "error",
91
+ "message": "mGDL 缺少核心模块: {0}".format(", ".join(missing))
92
+ })
93
+
94
+ # 3) special_mechanics 注册点(你们工程关键)
95
+ if "(special_mechanics" not in mgdl and "extensions.special_mechanics" in text:
96
+ issues.append({
97
+ "code": "SPECIAL_MECH_MISMATCH",
98
+ "level": "warning",
99
+ "message": "自然语言提到 special_mechanics,但 mGDL 中未出现 (special_mechanics ...) 或 extensions.special_mechanics 结构。"
100
+ })
101
+
102
+ # 4) 简单守恒提示:total 字段存在性(无法保证正确,但能抓掉一批缺失)
103
+ if "(total" not in mgdl:
104
+ issues.append({
105
+ "code": "NO_TILE_TOTAL",
106
+ "level": "warning",
107
+ "message": "tileset 中未检测到 (total N),容易导致牌数不自洽。"
108
+ })
109
+
110
+ return issues
111
+
112
+
113
+ def format_issues_for_llm(issues: List[Dict[str, str]]) -> str:
114
+ if not issues:
115
+ return ""
116
+ lines = []
117
+ for idx, it in enumerate(issues, start=1):
118
+ lines.append("{0}. [{1}] {2}".format(idx, it.get("code"), it.get("message")))
119
+ return "\n".join(lines).strip()
reference_retriever.py ADDED
@@ -0,0 +1,392 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ 参考玩法检索注入(RAG-lite)
3
+
4
+ 目标:
5
+ - 用本地示例玩法库(.md 主真理 + _mGDL_v1.3.txt 辅语法翻译)为当前用户需求挑选少量最相关参考
6
+ - 避免把所有示例全量注入导致注意力稀释
7
+ """
8
+
9
+ import os
10
+ import re
11
+ from typing import Dict, List, Optional, Tuple
12
+
13
+ from cache_manager import file_cache
14
+
15
+
16
+ _MGDL_SUFFIX_RE = re.compile(r"^(?P<name>.+?)_mGDL_v1\.3\.txt$")
17
+ _CJK_RUN_RE = re.compile(r"[\u4e00-\u9fff]+")
18
+
19
+ # 非严格停用词:用于降低“通用词”对关键词召回的干扰(可按需要继续补充)
20
+ _STOP_TERMS = {
21
+ "麻将", "玩法", "规则", "玩家", "游戏", "进行", "阶段", "流程", "说明", "机制",
22
+ "可以", "允许", "是否", "如果", "那么", "以及", "但是", "因为", "所以", "同时",
23
+ "庄家", "闲家", "手牌", "摸牌", "打牌", "出牌", "胡牌", "自摸", "点炮", "一炮",
24
+ "结算", "得分", "倍数", "番型", "番数", "牌墙", "弃牌", "顺序", "回合", "开始", "结束",
25
+ "默认", "配置", "支持", "包含", "采用", "需要", "必须", "不得",
26
+ # 更偏“功能词/口水词”的补充(避免成为锚点)
27
+ "一个", "做一", "做个", "加入", "增加", "带有", "希望", "想要", "想做", "更快", "更刺激",
28
+ }
29
+
30
+ # 锚点词的“领域提示字”:让锚点更偏向机制/规则名词,而不是偶然出现的通用短语
31
+ # 说明:这是启发式,但比“硬编码某个玩法/某个术语”更普适。
32
+ _ANCHOR_HINT_CHARS = set("鸟马赖鬼杠胡听鸡豆缺换海捞承包庄风中发白炮分番倍封顶")
33
+
34
+
35
+ def _cjk_ngrams(text: str, min_n: int = 2, max_n: int = 4) -> List[str]:
36
+ """
37
+ 从文本中提取 CJK n-gram(用于关键词召回;无外部依赖,适合小规模本地样例库)。
38
+ """
39
+ s = (text or "").strip()
40
+ if not s:
41
+ return []
42
+
43
+ grams = []
44
+ for run in _CJK_RUN_RE.findall(s):
45
+ if not run:
46
+ continue
47
+ # 对超长段落,限制采样长度,避免构造过多 n-gram
48
+ run = run[:2000]
49
+ L = len(run)
50
+ for i in range(L):
51
+ for n in range(min_n, max_n + 1):
52
+ j = i + n
53
+ if j > L:
54
+ continue
55
+ g = run[i:j]
56
+ if g in _STOP_TERMS:
57
+ continue
58
+ grams.append(g)
59
+
60
+ # 去重保持顺序(小规模即可)
61
+ seen = set()
62
+ uniq = []
63
+ for g in grams:
64
+ if g not in seen:
65
+ seen.add(g)
66
+ uniq.append(g)
67
+ return uniq
68
+
69
+
70
+ def _base_dir() -> str:
71
+ return os.path.dirname(__file__)
72
+
73
+
74
+ def _read_text(path: str) -> str:
75
+ cached = file_cache.get(path)
76
+ if cached is not None:
77
+ return cached
78
+ try:
79
+ with open(path, "r", encoding="utf-8", errors="ignore") as f:
80
+ txt = f.read()
81
+ file_cache.set(path, txt)
82
+ return txt
83
+ except Exception:
84
+ return ""
85
+
86
+
87
+ def _build_variant_index() -> Dict[str, Dict[str, str]]:
88
+ """
89
+ 返回:
90
+ {
91
+ "疯狂血战": {"md": "...", "mgdl": "..."},
92
+ ...
93
+ }
94
+ """
95
+ base = _base_dir()
96
+ index: Dict[str, Dict[str, str]] = {}
97
+
98
+ try:
99
+ for filename in os.listdir(base):
100
+ if filename.endswith(".md") and filename != "README.md":
101
+ name = filename[:-3]
102
+ index.setdefault(name, {})["md_path"] = os.path.join(base, filename)
103
+ elif filename.endswith("_mGDL_v1.3.txt"):
104
+ m = _MGDL_SUFFIX_RE.match(filename)
105
+ if not m:
106
+ continue
107
+ name = m.group("name")
108
+ index.setdefault(name, {})["mgdl_path"] = os.path.join(base, filename)
109
+ except Exception:
110
+ return {}
111
+
112
+ # 只保留至少有 md 或 mgdl 的条目
113
+ cleaned: Dict[str, Dict[str, str]] = {}
114
+ for name, entry in index.items():
115
+ md_path = entry.get("md_path")
116
+ mgdl_path = entry.get("mgdl_path")
117
+ if not md_path and not mgdl_path:
118
+ continue
119
+ cleaned[name] = {}
120
+ if md_path:
121
+ cleaned[name]["md_path"] = md_path
122
+ if mgdl_path:
123
+ cleaned[name]["mgdl_path"] = mgdl_path
124
+ return cleaned
125
+
126
+
127
+ def _find_mentions(text: str, candidates: List[str]) -> List[str]:
128
+ """
129
+ 朴素子串匹配(中文玩法名通常稳定),返回按“更长优先”的去重命中列表。
130
+ """
131
+ s = (text or "").strip()
132
+ if not s:
133
+ return []
134
+
135
+ hits: List[str] = []
136
+ # 长词优先,避免“血战”误命中“疯狂血战”
137
+ for name in sorted(candidates, key=lambda x: len(x), reverse=True):
138
+ if name and name in s:
139
+ hits.append(name)
140
+
141
+ # 去重保持顺序
142
+ seen = set()
143
+ uniq: List[str] = []
144
+ for h in hits:
145
+ if h not in seen:
146
+ seen.add(h)
147
+ uniq.append(h)
148
+ return uniq
149
+
150
+
151
+ _TERM_CACHE: Optional[Dict[str, set]] = None
152
+ _TERM_DF: Optional[Dict[str, int]] = None
153
+ _TERM_POSTINGS: Optional[Dict[str, List[str]]] = None
154
+ _DOMAIN_TERMS: Optional[set] = None
155
+
156
+
157
+ def _build_domain_terms() -> set:
158
+ """
159
+ 构建“领域词表”用于过滤用户 n-gram(降低把通用词当成锚点的概率)。
160
+
161
+ 策略:
162
+ - 不引入外部依赖(如 jieba)
163
+ - 直接从“所有玩法 .md 的关键词集合并集”构建 domain_terms(足够泛化)
164
+ """
165
+ global _DOMAIN_TERMS
166
+ if _DOMAIN_TERMS is not None:
167
+ return _DOMAIN_TERMS
168
+
169
+ index = _build_variant_index()
170
+ domain = set()
171
+ for name, entry in index.items():
172
+ if name == "麻将机制说明":
173
+ continue
174
+ md_path = entry.get("md_path")
175
+ if not md_path or not os.path.exists(md_path):
176
+ continue
177
+ md_txt = _read_text(md_path)
178
+ if not md_txt.strip():
179
+ continue
180
+ domain.update(_cjk_ngrams(md_txt, min_n=2, max_n=4))
181
+
182
+ _DOMAIN_TERMS = domain
183
+ return domain
184
+
185
+
186
+ def _build_variant_term_cache() -> Dict[str, set]:
187
+ """
188
+ 为每个玩法构建关键词特征(来自 .md,必要时可扩展到 mgdl)。
189
+ 返回:{variant_name: {term1, term2, ...}}
190
+ """
191
+ global _TERM_CACHE, _TERM_DF, _TERM_POSTINGS
192
+ if _TERM_CACHE is not None and _TERM_DF is not None:
193
+ return _TERM_CACHE
194
+
195
+ index = _build_variant_index()
196
+ cache: Dict[str, set] = {}
197
+ for name, entry in index.items():
198
+ # 机制词典单独注入,不把它当“参考玩法”候选
199
+ if name == "麻将机制说明":
200
+ continue
201
+ md_path = entry.get("md_path")
202
+ if not md_path or not os.path.exists(md_path):
203
+ continue
204
+
205
+ md_txt = _read_text(md_path)
206
+ if not md_txt.strip():
207
+ continue
208
+
209
+ # 只从 md 抽关键词:它是“内容真理”,且比 mGDL 更接近用户描述的术语
210
+ cache[name] = set(_cjk_ngrams(md_txt, min_n=2, max_n=4))
211
+
212
+ # 计算 df(每个 term 在多少个玩法中出现),用于稀有词加权(IDF-lite)
213
+ df: Dict[str, int] = {}
214
+ postings: Dict[str, List[str]] = {}
215
+ for _, terms in cache.items():
216
+ for t in terms:
217
+ df[t] = df.get(t, 0) + 1
218
+ for variant, terms in cache.items():
219
+ for t in terms:
220
+ postings.setdefault(t, []).append(variant)
221
+
222
+ _TERM_CACHE = cache
223
+ _TERM_DF = df
224
+ _TERM_POSTINGS = postings
225
+ return cache
226
+
227
+
228
+ def _score_by_terms(message: str, term_cache: Dict[str, set]) -> List[Tuple[str, int]]:
229
+ """
230
+ 基于关键词重叠给玩法打分(分数越高越相关)。
231
+ """
232
+ global _TERM_DF
233
+ domain = _build_domain_terms()
234
+ user_terms = set(_cjk_ngrams(message, min_n=2, max_n=4))
235
+ # 仅保留“在领域词表中出现过”的词(否则很多通用 n-gram 会干扰)
236
+ user_terms = {t for t in user_terms if t in domain}
237
+ if not user_terms:
238
+ return []
239
+
240
+ scored: List[Tuple[str, int]] = []
241
+ for variant, terms in term_cache.items():
242
+ if not terms:
243
+ continue
244
+ inter = user_terms.intersection(terms)
245
+ if not inter:
246
+ continue
247
+ # 稀有词(df低)更有区分度:用 IDF-lite 加权,避免“通用词重叠”淹没关键术语(如“扎鸟”)
248
+ score = 0
249
+ for t in inter:
250
+ df = (_TERM_DF or {}).get(t, 9999)
251
+ # df=1 → 权重最高;df越大权重越低
252
+ score += int((len(t) * 100) / max(1, df))
253
+ scored.append((variant, score))
254
+
255
+ scored.sort(key=lambda x: x[1], reverse=True)
256
+ return scored
257
+
258
+
259
+ def _pick_anchor_terms(message: str, max_terms: int = 3) -> List[str]:
260
+ """
261
+ 从用户输入中挑选“高区分度锚点词”(通用、可解释、无需硬编码具体玩法/术语)。
262
+
263
+ 规则:
264
+ - 仅使用领域词表命中的词
265
+ - 优先 df 小(更稀有)+ 词更长(更具体)
266
+ """
267
+ global _TERM_DF, _TERM_POSTINGS
268
+ _build_variant_term_cache()
269
+ domain = _build_domain_terms()
270
+ terms = set(_cjk_ngrams(message, min_n=2, max_n=4))
271
+ terms = {t for t in terms if t in domain and t not in _STOP_TERMS}
272
+ if not terms:
273
+ return []
274
+
275
+ def _is_informative_anchor(term: str) -> bool:
276
+ if not term or term in _STOP_TERMS:
277
+ return False
278
+ return any(ch in _ANCHOR_HINT_CHARS for ch in term)
279
+
280
+ ranked = []
281
+ for t in terms:
282
+ df = (_TERM_DF or {}).get(t)
283
+ if not df:
284
+ continue
285
+ # df=1 最佳;长度越长越好
286
+ if not _is_informative_anchor(t):
287
+ continue
288
+ ranked.append((t, df, len(t)))
289
+ ranked.sort(key=lambda x: (x[1], -x[2], x[0])) # df asc, len desc
290
+ return [t for t, _, _ in ranked[: max(1, max_terms)]]
291
+
292
+
293
+ def pick_reference_variants(
294
+ message: str,
295
+ max_variants: int = 3,
296
+ fallback: Optional[List[str]] = None,
297
+ ) -> List[str]:
298
+ """
299
+ 依据用户输入挑选参考玩法名(仅返回玩法名,不读文件)。
300
+ """
301
+ index = _build_variant_index()
302
+ names = list(index.keys())
303
+
304
+ mentions = _find_mentions(message, names)
305
+ if mentions:
306
+ return mentions[: max(1, max_variants)]
307
+
308
+ # 用户未显式说玩法名:走关键词召回(例如提到“扎鸟/买马/承包”等术语)
309
+ term_cache = _build_variant_term_cache()
310
+ scored = _score_by_terms(message, term_cache)
311
+ anchor_terms = _pick_anchor_terms(message, max_terms=3)
312
+ postings = _TERM_POSTINGS or {}
313
+
314
+ # 将“锚点命中”作为加权 boost,而不是简单强制放前面截断
315
+ base_scores = {name: score for name, score in scored}
316
+ boost_scores: Dict[str, int] = {}
317
+ for t in anchor_terms:
318
+ df = (_TERM_DF or {}).get(t, 9999)
319
+ w = int((len(t) * 100) / max(1, df))
320
+ for v in postings.get(t, []):
321
+ boost_scores[v] = boost_scores.get(v, 0) + w
322
+
323
+ if scored or boost_scores:
324
+ candidates = set(base_scores.keys()) | set(boost_scores.keys())
325
+ ranked = []
326
+ for v in candidates:
327
+ base = base_scores.get(v, 0)
328
+ boost = boost_scores.get(v, 0)
329
+ ranked.append((v, base + boost))
330
+ ranked.sort(key=lambda x: x[1], reverse=True)
331
+ return [v for v, _ in ranked[: max(1, max_variants)]]
332
+
333
+ if fallback:
334
+ return fallback[: max(1, max_variants)]
335
+
336
+ # 默认兜底:覆盖不同体系,给模型“底座参考面”
337
+ default_pool = [
338
+ "疯狂血战",
339
+ "疯狂血流",
340
+ "广东100张",
341
+ "贵州捉鸡麻将",
342
+ "妙手七星",
343
+ ]
344
+ return [n for n in default_pool if n in names][: max(1, max_variants)]
345
+
346
+
347
+ def build_reference_pack(
348
+ message: str,
349
+ max_variants: int = 3,
350
+ include_mechanism_library: bool = True,
351
+ include_mgdl: bool = False,
352
+ ) -> Dict[str, str]:
353
+ """
354
+ 返回可注入到 system message 的多段文本。
355
+ """
356
+ index = _build_variant_index()
357
+ picked = pick_reference_variants(message, max_variants=max_variants)
358
+
359
+ parts: Dict[str, str] = {}
360
+
361
+ if include_mechanism_library:
362
+ mech_path = os.path.join(_base_dir(), "麻将机制说明.md")
363
+ if os.path.exists(mech_path):
364
+ mech_txt = _read_text(mech_path).strip()
365
+ if mech_txt:
366
+ parts["mechanism_library"] = mech_txt
367
+
368
+ md_chunks: List[str] = []
369
+ mgdl_chunks: List[str] = []
370
+ for name in picked:
371
+ entry = index.get(name) or {}
372
+ md_path = entry.get("md_path")
373
+ mgdl_path = entry.get("mgdl_path")
374
+
375
+ if md_path and os.path.exists(md_path):
376
+ txt = _read_text(md_path).strip()
377
+ if txt:
378
+ md_chunks.append("\n# FILE: {0}\n{1}\n".format(os.path.basename(md_path), txt))
379
+
380
+ if include_mgdl and mgdl_path and os.path.exists(mgdl_path):
381
+ txt = _read_text(mgdl_path).strip()
382
+ if txt:
383
+ mgdl_chunks.append("\n# FILE: {0}\n{1}\n".format(os.path.basename(mgdl_path), txt))
384
+
385
+ if md_chunks:
386
+ parts["reference_md"] = "\n".join(md_chunks).strip()
387
+ if mgdl_chunks:
388
+ parts["reference_mgdl"] = "\n".join(mgdl_chunks).strip()
389
+
390
+ # 透传“本轮选了哪些参考”,便于模型更聚焦
391
+ parts["picked_names"] = ", ".join(picked)
392
+ return parts