自动评测教程

本教程介绍了如何使用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成员函数。

results matching ""

    No results matching ""