自动评测教程
本教程介绍了如何使用autoMatch.py进行自动评测。协会也将使用此脚本进行评测。
使用说明
本部分仅介绍如何自动评测,具体实现原理请看运行逻辑以及函数介绍。
步骤一:
加入地图文件夹
将下载的地图文件夹,如maps_2player/3player等拖进Commander根目录,如图所示:
注:目前请不要使用自己编辑的地图。
步骤二:
修改autoMatch.py
1.matchNumber
class autoMatch(object):
matchNumber = 5
修改matchNumber可以改变对局次数,请不要超过100次.
2.AI
AI = ["Python", "Lua", "C++"]
AIwinnings = [[], [], []]
AI代表参与游戏的智能体列表,可以设置2~4个,上面的例子是设置了3个,此时会在地图中读取文件夹下的三个AI(Core.py,Core.lua,API.cpp)进行比赛。如果有相同的,如["Lua","Lua"],则两个AI逻辑相同。
AIwinnings为智能体获胜记录,数量应与上方的智能体数匹配。
3.map
# 游戏使用的地图目录,地图中玩家数应与上方的智能体数匹配
mapDict = "maps_3player"
mapName = ""
mapDict为游戏使用的地图目录,地图中玩家数应与上方的智能体数匹配,若步骤一中拖入的是maps_2player,则应修改为:mapDict = "maps_2player"。mapName会自动匹配不必修改。自动评测时会从文件夹下的第一个地图开始依次使用地图来评测。
4.saveDict
saveDict = "IGCA"
saveName = ""
saveDict存为存档文件夹名,可以自己取名。如例子中就会在Commander根目录下建立一个叫IGCA的文件夹,自动评测的结果(回放文件,胜负情况,胜率)会在其中生成。
saveName不必改动。
修改Client和Server中的main.lua
1.dt
在Client和Server文件夹下都有一个main.lua文件,其中函数love.update中都有一句注释:-- dt = dt * 10,这里可以修改时间倍率,这里建议取消注释后就使用10倍速,在笔记本电脑上较为流畅。
下面是实现原理,只是评测可以不用继续查看。
运行逻辑
循环对战的次数
定义服务端的启动选项,写入到ServerTask.txt
启动一个服务端的实例
循环AI数量-1次
定义客户端的启动选项,写入到ClientTask.txt
启动一个客户端的实例
等待直到ServerTask.txt被删除或到达超时时间
删除ClientTask.txt
读取存档文件中的steps.txt,获取胜利者
统计胜率,写入根目录下的matchResult.txt
函数介绍
所有函数都属于autoMatch类。类变量定义见注释。被注释的mapDict是评测时使用的地图目录,此处注释换成default是为了更方便地查看脚本运行是否正常。同理,自动对战超时时间设为了20秒。
1. init
def __init__(self):
self.startTime = time.strftim("%Y-%m-%d_%H:%M:%S", time.localtime())
return
此函数在类实例化时被调用,获取时间作为评测的开始时间。
2. creatClientTask
def creatClientTask(self, index):
fp = open("ClientTask.txt", 'w')
fp.write("[autoMatch]\n")
fp.write("true\n") # 是否为自动对战任务
fp.write("[timeOut]\n")
fp.write(str(self.timeOut)+"\n")
fp.write("[mapDict]\n")
fp.write(self.mapDict+"\n")
fp.write("[mapName]\n")
fp.write(self.mapName+"\n")
fp.write("[AIlang]\n")
fp.write(self.AI[index]+"\n")
fp.close()
return
此函数以写入模式打开了ClientTask.txt(若不存在将被创建,若存在将被覆盖),然后按顺序写入启动选项。此函数有一个传入参数index,决定了将要使用哪一个AI。
3. creatServerTask
def creatServerTask(self):
fp = open("ServerTask.txt", 'w')
fp.write("[autoMatch]\n")
fp.write("true\n") # 是否为自动对战任务
fp.write("[timeOut]\n")
fp.write(str(self.timeOut)+"\n")
fp.write("[mapDict]\n")
fp.write(self.mapDict+"\n")
fp.write("[mapName]\n")
fp.write(self.mapName+"\n")
fp.write("[saveName]\n")
fp.write(self.saveName+"\n")
fp.write("[saveDict]\n")
fp.write(self.saveDict+"\n")
fp.close()
return
类似creatClientTask,不过没有传入参数。
4. startMatch
def startMatch(self, index):
#self.mapName = str(index)+".map"
self.mapName = "default"
self.saveName = "round"+str(index)
self.creatServerTask()
if self.runWithConsol == True:
os.system('cd Server&start lovec .')
else:
os.system('cd Server&start love .')
time.sleep(self.timeDelay)
for i in range(len(self.AI)-1):
self.creatClientTask(i+1)
if self.runWithConsol == True:
os.system("cd Client&start lovec .")
else:
os.system("cd Client&start love .")
time.sleep(self.timeDelay)
return
创建Task文件并启动程序以开始自动对战。被注释的行会按序号加载地图,改为默认地图是为了更方便地查看脚本运行是否正常。
5. waitUntilMatchOver
def waitUntilMatchOver(self):
roundStartTime = time.time()
while True:
if os.path.exists("ServerTask.txt"):
if time.time()-roundStartTime > self.timeOut:
os.remove("ServerTask.txt")
break
time.sleep(1)
else:
break
os.remove("ClientTask.txt")
time.sleep(self.timeDelay)
return
如果ServerTask.txt中的[autoMatch]项为true,服务端将会在游戏结束后删除ServerTask.txt;脚本依此判断对战是否已经完成。对战也会因为超时而结束。结束后,脚本将删除ServerTask.txt和ClientTask.txt。
6. getMatchResult
def getMatchResult(self, index):
fp = open(self.saveDict+"/"+self.saveName+"/steps.txt", 'r')
lines = fp.readlines()
fp.close()
if lines[-1][3] == 3 and lines[-1][6] == 3:
self.AIwinnings[lines[-1][0]].append(index)
return
此函数获取输入参数index,对战的局数,然后检查steps.txt的最后一行是否为获胜信息。如果某一方获胜了,最后一行应为armyID -3 -3 0 0 0
。查询到获胜信息后将对应的局数存入对应AI的胜场列表中。因超时而结束的对局不会产生胜者。
7. saveMatchResult
def saveMatchResult(self):
self.endTime = time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())
fp = open("matchResult.txt", 'w')
fp.write("match start: "+self.startTime+"\n")
fp.write("match end: "+self.endTime+"\n")
fp.write("total round: "+str(self.matchNumber)+"\n")
fp.write("savedata: "+self.saveDict+"\n\n\n")
for i in range(len(self.AI)-1):
fp.write("armyID: "+str(i+1)+"\n")
fp.write("AI: "+self.AI[i+1]+"\n")
fp.write("winning: "+str(self.AIwinnings[i+1])+"\n")
fp.write("winning rate: " + str(len(self。AIwinnings[i+1])/self.matchNumber)+"\n\n")
fp.close()
return
此函数在所有对局结束后被调用,它将此次评测的统计信息、每个AI的胜场和胜率写入根目录下的matchResult.txt。
8. match
def match(self):
for i in range(self.matchNumber):
self.startMatch(i)
self.waitUntilMatchOver()
self.getMatchResult(i)
self.saveMatchResult()
return
此函数进行自动评测。运行时,脚本将先创建autoMatch类的实例am,然后调用am的match成员函数。