Plays exactly ONE round, but does not overwrite previously played rounds
eg: run once to generate round1.results, twice to generate round2.results etc
Also generates total.scores based on results from every round.
+
+ Now (sortof) generates .html files to display results in a prettiful manner.
author Sam Moore (matches) [SZM]
scores = {"VICTORY":(3,1, "DEFEAT"), "DEFEAT":(1,3, "VICTORY"), "SURRENDER":(1,3, "VICTORY"), "DRAW":(2,2, "DRAW"), "DRAW_DEFAULT":(1,1, "DRAW_DEFAULT"), "ILLEGAL":(-1,2, "DEFAULT"), "DEFAULT":(2,-1, "ILLEGAL"), "BOTH_ILLEGAL":(-1,-1, "BOTH_ILLEGAL"), "INTERNAL_ERROR":(0,0, "INTERNAL_ERROR"), "BAD_SETUP":(0,0,"BAD_SETUP")}
-#Verbose - print lots of useless stuff about what you are doing (kind of like matches in irc...)
+#Verbose - print lots of useless stuff about what you are doing (kind of like matches talking on irc...)
verbose = True
-makePrettyResults = False
+
#Check the manager program exists TODO: And is executable!
if os.path.exists(resultsDirectory) == False:
os.mkdir(resultsDirectory) #Make the results directory if it didn't exist
+'''
+ Obselete older version doesn't work with new .html files
#Identify the round number by reading the results directory
totalRounds = len(os.listdir(resultsDirectory)) + 1
if totalRounds > 1:
totalRounds -= 1
+'''
+
+totalRounds = 1
+#TODO: Fix this bit!
if os.path.exists(logDirectory) == False:
os.mkdir(logDirectory) #Make the log directory if it didn't exist
startTime = time() #Record time at which simulation starts
+if verbose:
+ if nRounds > 1:
+ print "Simulating " + str(nRounds) + " rounds (" + str(totalRounds) + " to " + str(totalRounds + nRounds-1) + ")"
+ else:
+ print "Simulating one round."
+ print ""
+ print "Identifying possible agents in \""+agentsDirectory+"\""
+
+#Get all agent names from agentsDirectory
+agentNames = os.listdir(agentsDirectory)
+agents = []
+for name in agentNames:
+ if verbose:
+ sys.stdout.write("Scan \""+name+"\"... ")
+ if os.path.isdir(agentsDirectory+name) == False: #Remove non-directories
+ if verbose:
+ sys.stdout.write(" Invalid! (Not a directory)\n")
+ continue
+
+ if os.path.exists(agentsDirectory+name+"/info") == False: #Try and find the special "info" file in each directory; ignore if it doesn't exist
+ if verbose:
+ sys.stdout.write(" Invalid! (No \"info\" file found)\n")
+ continue
+
+ agentExecutable = agentsDirectory+name+"/"+(open(agentsDirectory+name+"/info").readline().strip())
+
+ if os.path.exists(agentExecutable) == False:
+ if verbose:
+ sys.stdout.write(" Invalid! (Path: \""+agentExecutable+"\" does not exist!)\n")
+ continue
+
+
+ if verbose:
+ sys.stdout.write(" Valid! (Path: \""+agentExecutable+"\")\n")
+
+ #Convert array of valid names into array of dictionaries containing information about each agent
+ #I'm starting to like python...
+ agents.append({"name":name, "path":agentExecutable, "score":[0], "VICTORY":[], "DEFEAT":[], "DRAW":[], "ILLEGAL":[], "DEFAULT":[], "INTERNAL_ERROR":[], "SURRENDER":[], "DRAW_DEFAULT":[], "BOTH_ILLEGAL":[], "BAD_SETUP":[], "ALL":[], "totalScore":0, "Wins":0, "Losses":0, "Draws":0, "Illegal":0, "Errors":0})
+
+if len(agents) == 0:
+ print "Couldn't find any agents! Check paths (Edit this script) or generate \"info\" files for agents."
+ sys.exit(0)
+if verbose:
+ print "Total: " + str(len(agents)) + " valid agents found (From "+str(len(agentNames))+" possibilities)"
+ print ""
+
+#Prepare the pretty .html files if they don't exist
+if verbose:
+ print "Preparing .html results files..."
+htmlDir = resultsDirectory + "pretty/"
+if os.path.exists(htmlDir) == False:
+ os.mkdir(htmlDir)
+if os.path.exists(htmlDir) == False:
+ print "Couldn't create directory \""+htmlDir+"\"."
+ sys.exit(1)
+
+for agent in agents:
+ if os.path.exists(htmlDir+agent["name"] + ".html") == False:
+ agentFile = open(htmlDir+agent["name"] + ".html", "w")
+ agentFile.write("<html>\n<head>\n <title> " + agent["name"] + " results</title>\n</head>\n<body>\n<h1> Results for " + agent["name"]+" </h1>\n</body>\n</html>\n")
+ agentFile.close()
+
+ os.rename(htmlDir+agent["name"] + ".html", "tmpfile")
+
+ oldFile = open("tmpfile", "r")
+ agentFile = open(htmlDir+agent["name"] + ".html", "w")
+ line = oldFile.readline()
+ while line != "":
+ #if verbose:
+ # print "Interpreting line \"" + line.strip() + "\""
+ if line.strip() == "</body>":
+ break
+ elif line == "<tr> <th> Score </th> <th> Wins </th> <th> Losses </th> <th> Draws </th> <th> Illegal </th> <th> Errors </th></tr>\n":
+ agentFile.write(line)
+ line = oldFile.readline()
+
+ values = line.split(' ')
+ agent["totalScore"] += int(values[2].strip())
+ agent["Wins"] += int(values[5].strip())
+ agent["Losses"] += int(values[8].strip())
+ agent["Draws"] += int(values[11].strip())
+ agent["Illegal"] += int(values[14].strip())
+ agent["Errors"] += int(values[17].strip())
+ agentFile.write(line)
+ line = oldFile.readline()
+
+ if verbose:
+ print "Prepared results file \"" + htmlDir+agent["name"] + ".html\"."
+ oldFile.close()
+ agentFile.close()
+ os.remove("tmpfile")
+
+if verbose:
+ print ""
+
#Do each round...
+totalGames = nGames/2 * len(agents) * (len(agents)-1)
for roundNumber in range(totalRounds, totalRounds + nRounds):
if os.path.exists(logDirectory + "round"+str(roundNumber)) == False:
os.mkdir(logDirectory + "round"+str(roundNumber)) #Check there is a directory for this round's logs
- if verbose:
- print "Simulating ROUND " +str(roundNumber)
- print "Identifying possible agents in \""+agentsDirectory+"\""
-
- #Get all agent names from agentsDirectory
- #TODO: Move this part outside the loop? It only has to happen once
- agentNames = os.listdir(agentsDirectory)
- agents = []
- for name in agentNames:
- #sys.stdout.write("\nLooking at Agent: \""+ str(name)+"\"... ")
- if verbose:
- sys.stdout.write("Scan \""+name+"\"... ")
- if os.path.isdir(agentsDirectory+name) == False: #Remove non-directories
- if verbose:
- sys.stdout.write(" Invalid! (Not a directory)\n")
- continue
-
- if os.path.exists(agentsDirectory+name+"/info") == False: #Try and find the special "info" file in each directory; ignore if it doesn't exist
- if verbose:
- sys.stdout.write(" Invalid! (No \"info\" file found)\n")
- continue
+ for agent in agents:
+ agent.update({"name":agent["name"], "path":agent["path"], "score":[0], "VICTORY":[], "DEFEAT":[], "DRAW":[], "ILLEGAL":[], "DEFAULT":[], "INTERNAL_ERROR":[], "SURRENDER":[], "DRAW_DEFAULT":[], "BOTH_ILLEGAL":[], "BAD_SETUP":[], "ALL":[]})
-
- agentExecutable = agentsDirectory+name+"/"+(open(agentsDirectory+name+"/info").readline().strip())
-
- if os.path.exists(agentExecutable) == False:
- if verbose:
- sys.stdout.write(" Invalid! (File \""+agentExecutable+"\" does not exist!)\n")
- continue
+ print "Commencing ROUND " + str(roundNumber) + " combat!"
+ print "Total: " + str(totalGames) + " games to be played. This could take a while... (Estimate 60s/game)"
- if verbose:
- sys.stdout.write(" Valid! (To run: \""+agentExecutable+"\")\n")
-
- #Convert array of valid names into array of dictionaries containing information about each agent
- #I'm starting to like python...
- agents.append({"name":name, "path":agentExecutable,"score":[0], "totalScore":0, "VICTORY":[], "DEFEAT":[], "DRAW":[], "ILLEGAL":[], "INTERNAL_ERROR":[]})
- if len(agents) == 0:
- print "Couldn't find any agents! Check paths (Edit this script) or generate \"info\" files for agents."
- sys.exit(0)
- if verbose:
- print "Total: " + str(len(agents)) + " valid agents found (From "+str(len(agentNames))+" possibilities)"
- print ""
- print "Commencing ROUND " + str(roundNumber) + " combat! This could take a while... "
-
- normalGames = 0
- draws = 0
- aiErrors = 0
managerErrors = 0
#This double for loop simulates a round robin, with each agent getting the chance to play as both red and blue against every other agent.
- gameID = 0
+ gameNumber = 0
for red in agents: #for each agent playing as red,
for blue in agents: #against each other agent, playing as blue
if red == blue:
continue #Exclude battles against self
- gameID += 1
+ gameNumber += 1
+ gameID = str(roundNumber) + "." + str(gameNumber)
for i in range(1, nGames/2 + 1):
#Play a game and read the result. Note the game is logged to a file based on the agent's names
if verbose:
- sys.stdout.write("Agents: \""+red["name"]+"\" and \""+blue["name"]+"\" playing game " + str(i) + "/"+str(nGames/2) + "... ")
+ sys.stdout.write("Agents: \""+red["name"]+"\" and \""+blue["name"]+"\" playing game (ID: " + gameID + ") ... ")
logFile = logDirectory + "round"+str(roundNumber) + "/"+red["name"]+".vs."+blue["name"]+"."+str(i)
outline = os.popen(managerPath + " -o " + logFile + " " + red["path"] + " " + blue["path"], "r").read()
results = outline.split(' ')
if len(results) != 6:
if verbose:
sys.stdout.write("Garbage output! \"" + outline + "\"\n")
- red["manager_errors"].append((gameID, blue["name"]))
+ red["INTERNAL_ERROR"].append((blue["name"], gameID, scores["INTERNAL_ERROR"][0]))
+ blue["INTERNAL_ERROR"].append((red["name"], gameID, scores["INTERNAL_ERROR"][0]))
+ red["ALL"].append((blue["name"], gameID, scores["INTERNAL_ERROR"][0], "INTERNAL_ERROR"))
+ blue["ALL"].append((red["name"], gameID, scores["INTERNAL_ERROR"][0], "INTERNAL_ERROR"))
managerErrors += 1
else:
if results[1] == "RED":
endColour = red
otherColour = blue
+ endStr = "RED"
+ otherStr = "BLUE"
elif results[1] == "BLUE":
endColour = blue
otherColour = red
+ endStr = "BLUE"
+ otherStr = "RED"
+
+
if results[1] == "BOTH":
- pass
+ red["INTERNAL_ERROR"].append((blue["name"], gameID, scores["INTERNAL_ERROR"][0]))
+ blue["INTERNAL_ERROR"].append((red["name"], gameID, scores["INTERNAL_ERROR"][0]))
+ red["ALL"].append((blue["name"], gameID, scores["INTERNAL_ERROR"][0], "INTERNAL_ERROR", "RED"))
+ blue["ALL"].append((red["name"], gameID, scores["INTERNAL_ERROR"][0], "INTERNAL_ERROR", "BLUE"))
+ managerErrors += 1
else:
endColour["score"].insert(0,endColour["score"][0] + scores[results[2]][0])
endColour[results[2]].append((otherColour["name"], gameID, scores[results[2]][0]))
+ endColour["ALL"].append((otherColour["name"], gameID, scores[results[2]][0], results[2], endStr))
otherColour["score"].insert(0, otherColour["score"][0] + scores[results[2]][1])
otherColour[scores[results[2]][2]].append((endColour["name"], gameID, scores[results[2]][1]))
+ otherColour["ALL"].append((endColour["name"], gameID, scores[results[2]][1], scores[results[2]][2], otherStr))
+
if verbose:
sys.stdout.write(" Result \"")
for ii in range(1, len(results)):
sys.stdout.write("\"\n")
if verbose:
- print "Completed combat. Total of " + str(normalGames + draws + aiErrors + managerErrors) + " games played. "
+ print "Completed combat. Total of " + str(gameNumber) + " games played. "
if managerErrors != 0:
- print "WARNING: Recieved "+str(managerErrors)+" garbage outputs. Check the manager program."
+ print "WARNING: Registered "+str(managerErrors)+" errors. Check the manager program."
if verbose:
print ""
#We should now have complete score values.
+ '''
+ Obselete, non prettified results
if verbose:
- sys.stdout.write("Creating results files for ROUND " + str(roundNumber) + "... ")
+ sys.stdout.write("Creating raw results files for ROUND " + str(roundNumber) + "... ")
agents.sort(key = lambda e : e["score"], reverse=True) #Sort the agents based on score
sys.stdout.write(" Complete!\n")
print "Finished writing results for ROUND " + str(roundNumber)
print ""
+ '''
+ if verbose:
+ print "RESULTS FOR ROUND " + str(roundNumber)
+
+ #totalFile = open(resultsDirectory+"total.scores", "w") #Recreate the file
+ for agent in agents:
+ #totalFile.write(agent["name"] + " " + str(agent["totalScore"]) +"\n") #Write the total scores in descending order
+ #if verbose:
+ print "Agent: " + str(agent)
-
- print "RESULTS FOR ROUND " + str(roundNumber)
- totalFile = open(resultsDirectory+"total.scores", "w") #Recreate the file
+ if verbose:
+ print "Updating pretty .html files... "
+
for agent in agents:
- totalFile.write(agent["name"] + " " + str(agent["totalScore"]) +"\n") #Write the total scores in descending order
- print "Agent: " + str(agent)
+ agentFile = open(htmlDir + agent["name"]+".html", "a")
+ agentFile.write("<h2> Round " + str(roundNumber) + "</h2>\n")
+ agentFile.write("<h3> Round Overview </h3>\n")
+ agentFile.write("<table border=\"0\" cellpadding=\"10\">\n")
+ agentFile.write("<tr> <th> Score </th> <th> Wins </th> <th> Losses </th> <th> Draws </th> <th> Illegal </th> <th> Errors </th></tr>\n")
+ agentFile.write("<tr> <td> "+str(agent["score"][0])+" </td> <td> "+str(len(agent["VICTORY"]) + len(agent["DEFAULT"]))+" </td> <td> "+str(len(agent["DEFEAT"]) + len(agent["SURRENDER"]))+" </td> <td> "+str(len(agent["DRAW"]) + len(agent["DRAW_DEFAULT"]))+" </td> <td> "+str(len(agent["ILLEGAL"]) + len(agent["BOTH_ILLEGAL"]) + len(agent["BAD_SETUP"]))+" </td> <td> " +str(len(agent["INTERNAL_ERROR"]))+" </td> </tr>\n")
+
+ agentFile.write("</table>\n")
+
+ agentFile.write("<h3> Detailed </h3>\n")
+ agentFile.write("<table border=\"0\" cellpadding=\"10\">\n")
+ agentFile.write("<tr> <th> Game ID </th> <th> Opponent </th> <th> Played as </th> <th> Outcome </th> <th> Score </th> <th> Accumulated Score </th> </tr> </th>\n")
+
+ for index in range(0, len(agent["ALL"])):
+ agentFile.write("<tr> <td> " + str(agent["ALL"][index][1]) + " </td> <td> <a href="+agent["ALL"][index][0]+".html>"+agent["ALL"][index][0] + " </a> </td> <td> " + agent["ALL"][index][4] + " </td> <td> " + agent["ALL"][index][3] + " </td> <td> " + str(agent["ALL"][index][2]) + "</td> <td> " + str(agent["score"][len(agent["score"])-index -2]) + " </td> </tr> </th>\n")
+ agentFile.write("</table>\n")
+
+ agent["totalScore"] += agent["score"][0]
+ agent["Wins"] += len(agent["VICTORY"]) + len(agent["DEFAULT"])
+ agent["Losses"] += len(agent["DEFEAT"]) + len(agent["SURRENDER"])
+ agent["Draws"] += len(agent["DRAW"]) + len(agent["DRAW_DEFAULT"])
+ agent["Illegal"] += len(agent["ILLEGAL"]) + len(agent["BOTH_ILLEGAL"]) + len(agent["BAD_SETUP"])
+ agent["Errors"] += len(agent["INTERNAL_ERROR"])
+
+ agentFile.write("<h3> Accumulated Results </h3>\n")
+ agentFile.write("<table border=\"0\" cellpadding=\"10\">\n")
+ agentFile.write("<tr> <th> Score </th> <th> Wins </th> <th> Losses </th> <th> Draws </th> <th> Illegal </th> <th> Errors </th></tr>\n")
+ agentFile.write("<tr> <td> "+str(agent["totalScore"])+" </td> <td> "+str(agent["Wins"])+" </td> <td> "+str(agent["Losses"])+" </td> <td> "+str(agent["Draws"])+" </td> <td> "+str(agent["Illegal"])+" </td> <td> " +str(agent["Errors"])+" </td> </tr>\n")
+
+ agentFile.write("</table>\n")
+ agentFile.close()
+
+ #Update round file
+ roundFile = open(htmlDir + "round"+str(roundNumber)+".html", "w")
+ roundFile.write("<html>\n<head>\n <title> Round " +str(roundNumber)+ " Overview </title>\n</head>\n<body>\n")
+ roundFile.write("<h1> Round " +str(roundNumber)+ " Overview </h1>\n")
+ roundFile.write("<table border=\"0\" cellpadding=\"10\">\n")
+ roundFile.write("<tr> <th> Name </th> <th> Score </th> <th> Total Score </th> </tr>\n")
+ agents.sort(key = lambda e : e["score"][0], reverse=True)
+ for agent in agents:
+ roundFile.write("<tr> <td> <a href="+agent["name"]+".html>"+agent["name"] + " </a> </td> <td> " + str(agent["score"][0]) + " </td> <td> " + str(agent["totalScore"]) + " </td> </tr>\n")
+ roundFile.write("</table>\n</body>\n<!-- Results file for Round " + str(roundNumber) + " autogenerated by \"" + sys.argv[0] + "\" at time " + str(time()) + " -->\n</html>\n\n")
+ roundFile.close()
- #I just want to say the even though I still think python is evil, it is much better than bash. Using bash makes me cry.
+
+
-endTime = time()
-print "Completed simulating " + str(nRounds) + " rounds in " + str(endTime - startTime) + " seconds."
+if verbose:
+ print "Finalising .html files... "
+for agent in agents:
+ agentFile = open(htmlDir + agent["name"]+".html", "a")
+
+ #Write the "total" statistics
+
+ agentFile.write("</body>\n<!-- Results file for \"" + agent["name"] + "\" autogenerated by \"" + sys.argv[0] + "\" at time " + str(time()) + " -->\n</html>\n\n")
+ agentFile.close()
+
+ if os.path.exists(htmlDir + "total.html") == True:
+ os.remove(htmlDir + "total.html") #Delete the file
+
+totalFile = open(htmlDir + "total.html", "w")
+totalFile.write("<html>\n<head>\n <title> Total Overview </title>\n</head>\n<body>\n")
+totalFile.write("<h1> Total Overview </h1>\n")
+totalFile.write("<table border=\"0\" cellpadding=\"10\">\n")
+totalFile.write("<tr> <th> Name </th> <th> Total Score </th> </tr>\n")
+agents.sort(key = lambda e : e["totalScore"], reverse=True)
+for agent in agents:
+ totalFile.write("<tr> <td> <a href="+agent["name"]+".html>"+agent["name"] + " </a> </td> <td> " + str(agent["totalScore"]) + " </td> </tr>\n")
+totalFile.write("</table>\n</body>\n<!-- Total Results file autogenerated by \"" + sys.argv[0] + "\" at time " + str(time()) + " -->\n</html>\n\n")
+totalFile.close()
-if makePrettyResults:
- if verbose:
- print "Now creating prettiful .html files..."
if verbose:
print "Done!"
+
+endTime = time()
+print "Completed simulating " + str(nRounds) + " rounds in " + str(endTime - startTime) + " seconds."
sys.exit(0)