-
Notifications
You must be signed in to change notification settings - Fork 14
/
match_interface.py
220 lines (179 loc) · 6.01 KB
/
match_interface.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
import os, pickle, zlib, array
try:
import match_core
except ImportError:
from . import match_core
if 'storage operations':
def clear_storage():
'''
清除双方私有存储字典
'''
match_core.STORAGE = [{}, {}]
def swap_storage():
'''
交换双方私有存储字典
玩家先后手交换时使用
'''
match_core.STORAGE = match_core.STORAGE[::-1]
# 直接调用序列化与压缩进行存储
if 'simple log':
def save_match_log(obj, path):
'''
保存比赛记录为文件
params:
obj - 待保存对象
path - 保存路径
'''
folder = os.path.dirname(path)
if folder:
os.makedirs(folder, exist_ok=True)
with open(path, 'wb') as f:
f.write(zlib.compress(pickle.dumps(obj), -1))
def load_match_log(path):
'''
读取比赛记录文件为对象
params:
path - 保存路径
'''
with open(path, 'rb') as f:
obj = pickle.loads(zlib.decompress(f.read()))
return obj
# 用于压缩/复原比赛记录
if 'replay helper':
def grab_plr_directions(frames):
'''从比赛记录读取双方玩家方向'''
players_info = [frame['players'] for frame in frames]
p1d, p2d = array.array('b'), array.array('b')
for i, ps in enumerate(players_info):
p1, p2 = ps
if i == 0:
p2d.append(p2['direction'])
p1d.append(p1['direction'])
elif i % 2:
p1d.append(p1['direction'])
else:
p2d.append(p2['direction'])
return p1d, p2d
def gen_player_module(directions):
'''创建通过方向序列重构输出的玩家模块'''
class bot_plr:
opl = directions
cp = 0
@classmethod
def play(cls, *a, **kw):
d = (cls.opl[cls.cp + 1] - cls.opl[cls.cp]) % 4
cls.cp += 1
return ' r l' [d]
return bot_plr
# 通过轨迹信息进行存储与复原
if 'compact log':
def save_compact_log(match_log, path):
'''
保存比赛记录为仅记录路径的原始文件
params:
match_log - 待保存比赛记录
path - 保存路径
'''
# 生成记录对象
compact_log = {k: v
for k, v in match_log.items()
if k != 'log'} # 排除帧序列,仅保存轨迹
compact_log['traces'] = grab_plr_directions(match_log['log'])
compact_log['init'] = [{
'x': plr['x'],
'y': plr['y'],
'init_direction': plr['direction'],
} for plr in match_log['log'][0]['players']]
# 提取耗时信息
t1, t2 = array.array('f'), array.array('f')
for frame in match_log['log']:
t_left = frame['timeleft']
t1.append(t_left[0])
t2.append(t_left[1])
compact_log['timeleft'] = (t1, t2)
# 保存
save_match_log(compact_log, path)
def load_compact_log(path):
'''
读取紧密比赛记录
params:
path - 保存路径
'''
compact_log = load_match_log(path)
# 读取参数
bot_plrs = list(map(gen_player_module, compact_log['traces']))
names = compact_log['players']
k, h = compact_log['size']
k //= 2
mturn = compact_log['maxturn']
mtime = compact_log['maxtime']
overrides = compact_log['init']
# 复原比赛
expand_log = match_core.match(bot_plrs, names, k, h, mturn, mtime,
overrides)
expand_log['result'] = compact_log['result']
for frame, tleft in zip(expand_log['log'],
zip(*compact_log['timeleft'])):
frame['timeleft'] = tleft
return expand_log
if 'samples':
def repeated_match(players,
names,
rounds,
log_record=False,
*args,
**kwargs):
'''
双方进行多次比赛
params:
players - 先后手玩家模块列表
names - 双方玩家名称
rounds - 比赛局数
log_record - 是否生成比赛记录文件,默认为否
*args, **kwargs - 比赛运行参数
return:
元组,包含比赛结果及统计
[0] - 比赛结果统计字典
0 - 先手玩家胜
1 - 后手玩家胜
None - 平局
[1] - 原始比赛结果列表
'''
# 初始化存储空间
clear_storage()
# 总初始化函数
for i in range(2):
try:
players[i].init(match_core.STORAGE[i])
except:
pass
# 初始化统计变量
result_raw = []
result_stat = {0: 0, 1: 0, None: 0}
# 运行多局比赛
for i in range(rounds):
# 获取比赛记录
match_log = match(players, names, *args, **kwargs)
# 统计结果
result = match_log['result']
result_raw.append(result)
result_stat[result[0]] += 1
# 生成比赛记录
if log_record:
log_name = 'log/%s-VS-%s_%s.zlog' % (*names, i)
save_match_log(match_log, log_name)
# 总总结函数
for i in range(2):
try:
players[i].summaryall(match_core.STORAGE[i])
except:
pass
# 返回结果
return result_stat, result_raw
if __name__ == '__main__':
from random import choice
class null_plr:
def play(stat, storage):
return choice('lrxxxx')
res = repeated_match((null_plr, null_plr), ('test1', 'test2'), 10, True)
print(res)