-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsituation.py
247 lines (218 loc) · 10.9 KB
/
situation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
'''
Author: Paoger
Date: 2023-11-30 09:57:29
LastEditors: Paoger
LastEditTime: 2024-02-06 13:57:01
Description:
Copyright (c) 2023 by Paoger, All Rights Reserved.
'''
from kivy.logger import Logger
from kivymd.toast import toast
from global_var import g_const_S_P_ORDEER,g_const_INIT_SITUATION
from piece import Piece
#初始化全局变量g_init_situation
def init_g_init_situation(init_s):
global g_const_INIT_SITUATION
#清空,不要用={}
g_const_INIT_SITUATION.clear()
print("init_g_init_situation begin")
for i in range(0,32,1):
#print(f"{i=}")
xy = int(init_s[i*2:(i+1)*2],16)
#print(f"{xy=}")
#p = Piece(None,None,None,None)
p = None
if xy != 255:#255 0xff 无子
x = xy // 10
y = xy % 10
#print(f"{x=},{y=}")
if i < 16:#红方棋子
p = Piece('w',g_const_S_P_ORDEER[i],x,y)
else: #黑方棋子
p = Piece('b',g_const_S_P_ORDEER[i],x,y)
g_const_INIT_SITUATION[f'{x},{y}'] = p
print_situation("******初始局面******",g_const_INIT_SITUATION)
print("init_g_init_situation end")
#将初始化字符串转换为局面变量
def xqfinit2xchessinit(init_s,xchess_init):
#清空,不要用={}
xchess_init.clear()
#print("xqfinit2xchessinit begin")
for i in range(0,32,1):
#print(f"{i=}")
xy = int(init_s[i*2:(i+1)*2],16)
#print(f"{xy=}")
#p = Piece(None,None,None,None)
p = None
if xy != 255:#255 0xff 无子
x = xy // 10
y = xy % 10
#print(f"{x=},{y=}")
if i < 16:#红方棋子
p = Piece('w',g_const_S_P_ORDEER[i],x,y)
else: #黑方棋子
p = Piece('b',g_const_S_P_ORDEER[i],x,y)
xchess_init[f'{x},{y}'] = p
#print_situation("******xchess局面******",xchess_init)
#print("xqfinit2xchessinit end")
#打印局面
def print_situation(des,sit):
Logger.info(des)
for y in range(9,-1,-1):
str = ""
for x in range(0,9,1):
if f"{x},{y}" in sit:
p = sit[f'{x},{y}']
#if isinstance(p,Piece):
if p:
#print(f"网点:({x},{y}),棋子:{p.camp=},{p.identifier=},{p.x=},{p.y=},{p.pieceWidget=}")
if x == 0:
str = f"{p.camp}{p.identifier:-<8}"
else:
str = f"{str}{p.camp}{p.identifier:-<8}"
else:
if x == 0:
str = f"{'x':-<9}"
else:
str = f"{str}{'x':-<9}"
else:
if x == 0:
str = f"{'x':-<9}"
else:
str = f"{str}{'x':-<9}"
Logger.info(str)
#检查棋盘局面
def check_situation(init_s):
rst = {'result_code':True,'result_desc':'疑罪从无或者检查无误'}
#检查同一位置是否有多个棋子
#key:f'{x},{y}' value:{Piece},不需要,一个key只有1个值
#检查各棋子是否在合理的位置上
for y in range(0,10,1):
for x in range(0,9,1):
#if (f"{x},{y}" in init_s) and (isinstance(init_s[f'{x},{y}'],Piece)):
if (f"{x},{y}" in init_s) and (init_s[f'{x},{y}']):
p = init_s[f'{x},{y}']
if p.camp == 'w':#红方
if p.identifier == 'k':
if p.x < 3 or p.x > 5 or p.y < 0 or p.y > 2:
rst['result_code'] = False
rst['result_desc'] = f'帅{p.camp=},{p.identifier=}不在其位((3,0) to (5,2)):{p.x=},{p.y}'
return rst
elif p.identifier == 'a':
if not ((p.x == 3 and p.y == 0) or (p.x == 5 and p.y == 0) or (p.x == 4 and p.y == 1) or (p.x == 3 and p.y == 2) or (p.x == 5 and p.y == 2)):
rst['result_code'] = False
rst['result_desc'] = f'仕{p.camp=},{p.identifier=}不在其位:{p.x=},{p.y}'
return rst
elif p.identifier == 'b':
if not ((p.x == 2 and p.y == 0) or (p.x == 6 and p.y == 0) or (p.x == 0 and p.y == 2) or (p.x == 4 and p.y == 2) or (p.x == 8 and p.y == 2) or (p.x == 2 and p.y == 4) or (p.x == 6 and p.y == 4)):
rst['result_code'] = False
rst['result_desc'] = f'相{p.camp=},{p.identifier=}不在其位:{p.x=},{p.y}'
return rst
elif p.identifier == 'p':#兵不能在后方,或兵在己方横走
if p.y < 3 or (p.y == 3 and (p.x == 1 or p.x == 3 or p.x == 5 or p.x == 7)) or (p.y == 4 and (p.x == 1 or p.x == 3 or p.x == 5 or p.x == 7)):
rst['result_code'] = False
rst['result_desc'] = f'兵{p.camp=},{p.identifier=}不在其位:{p.x=},{p.y}'
return rst
elif p.camp == 'b':#黑方
if p.identifier == 'k':
if p.x < 3 or p.x > 5 or p.y < 7 or p.y > 9:
rst['result_code'] = False
rst['result_desc'] = f'将{p.camp=},{p.identifier=}不在其位((3,7) to (5,9)):{p.x=},{p.y}'
return rst
elif p.identifier == 'a':
if not ((p.x == 3 and p.y == 9) or (p.x == 5 and p.y == 9) or (p.x == 4 and p.y == 8) or (p.x == 3 and p.y == 7) or (p.x == 5 and p.y == 7)):
rst['result_code'] = False
rst['result_desc'] = f'士{p.camp=},{p.identifier=}不在其位:{p.x=},{p.y}'
return rst
elif p.identifier == 'b':
if not ((p.x == 2 and p.y == 9) or (p.x == 6 and p.y == 9) or (p.x == 0 and p.y == 7) or (p.x == 4 and p.y == 7) or (p.x == 8 and p.y == 7) or (p.x == 2 and p.y == 5) or (p.x == 6 and p.y == 5)):
rst['result_code'] = False
rst['result_desc'] = f'象{p.camp=},{p.identifier=}不在其位:{p.x=},{p.y}'
return rst
elif p.identifier == 'p':#兵不能在后方,或兵在己方横走
if p.y > 6 or (p.y == 6 and (p.x == 1 or p.x == 3 or p.x == 5 or p.x == 7)) or (p.y == 5 and (p.x == 1 or p.x == 3 or p.x == 5 or p.x == 7)):
rst['result_code'] = False
rst['result_desc'] = f'卒{p.camp=},{p.identifier=}不在其位:{p.x=},{p.y}'
return rst
else:
rst['result_code'] = False
rst['result_desc'] = f'旗帜要鲜明(r or b):{p.camp=}'
return rst
return rst
#转换为Fen记谱法
"rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1"
"""
国际象棋的FEN格式串是由6段ASCII字符串组成的代码(彼此5个空格隔开),这6段代码的意义依次是:
(1) 棋盘上的棋子,这是FEN格式串的主要部分;
(2) 轮到哪一方走子;
(3) 每方及该方的王翼和后翼是否还存在“王车易位”的可能;
(4) 是否存在吃过路兵的可能,过路兵是经过哪个格子的;
(5) 最近一次吃子或者进兵后棋局进行的步数(半回合数),用来判断“50回合自然限着”;
(6) 棋局的回合数。
中国象棋没有“王车易位”和“吃过路兵”的着法,所以FEN格式串的这两项空缺,以最初局面为例说明:
rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1
r:黑车 n:黑马 b:黑象 a:黑士 k:黑将 c:黑炮 p:卒
R:红车 N:红马 B:红象 A:红士 K:红将 C:红炮 P:兵
上述局面如下
9 俥傌象士将士象傌俥 ==》从左至右 :rnbakabnr
8 ......... ==》9个空子 :9
7 .砲.....砲. ==> :1c5c1
6 卒.卒.卒.卒.卒
5 .........
4 .........
3 兵.兵.兵.兵.兵
2 .炮.....炮.
1 .........
0 车马相仕帅仕相马车
abcdefghi
(1)表示棋盘布局,小写表示黑方,大写表示红方,其他规则同国际象棋的 FEN 规范。
这里要注意两点,一是中国象棋棋盘有 10行,所以要用9个“/”把每一行隔开;二是棋子名称用英文字母表示,国际象棋中没有的棋子是仕(士)和炮,这里分别用字母 A(a)和
C(c)表示。
(2)表示轮到哪一方走子,“w”表示红方,“b”表示黑方。(有人认为红方应该用“r”表示,很多象棋软件确实是这样表示的。ElephantBoard 尽管用“w
表示,但识别时采取灵活的办法,即“b”表示黑方,除此以外都表示红方。)
(3)空缺,始终用“-”表示
(4)空缺,始终用“-”表示。
(5)表示双方没有吃子的走棋步数(半回合数),通常该值达到 120就要判和(六十回合自然限着),一旦形成局面的上一步是吃子,这里就标记“0”。(这个参数对
于普通局面的意义不大,ElephantBoard的规则处理器并不是根据这一项来判断和棋的所以总是计为“0”。)
(6)表示当前的回合数,在研究中局或排局时,作为研究对象的局面,这-项可以写1,随着局势的发展逐渐增加。
"""
def sit2Fen(init_s):
str = ""
rst = check_situation(init_s)
if rst['result_code'] == False:#局面有误
toast(rst['result_desc'],duration=5)
return str
#rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR
for y in range(9,-1,-1):
for x in range(0,9,1):
#print(f"{y=},{x=}")
if (f"{x},{y}" in init_s) and (init_s[f'{x},{y}']):
p = init_s[f'{x},{y}']
fenPiece = ''
if p.identifier == 'r':
fenPiece = 'r'
elif p.identifier == 'n':
fenPiece = 'n'
elif p.identifier == 'b':
fenPiece = 'b'
elif p.identifier == 'a':
fenPiece = 'a'
elif p.identifier == 'k':
fenPiece = 'k'
elif p.identifier == 'c':
fenPiece = 'c'
elif p.identifier == 'p':
fenPiece = 'p'
else:
fenPiece = '1'
if p.camp == 'w':#红方
fenPiece = fenPiece.upper()
#print(f'{fenPiece}')
str = f'{str}{fenPiece}'
#print(f'{str=}')
else:
str = f'{str}1'
if y > 0:
str = f'{str}/'
#print(f'{str=}')
return str