X-Git-Url: https://git.ucc.asn.au/?p=progcomp2012.git;a=blobdiff_plain;f=progcomp%2Fjudge%2Fsimulator%2Fsimulate.py;fp=progcomp%2Fjudge%2Fsimulator%2Fsimulate.py;h=8937a2b9fbb8c1fbba1a602ac7060341bd293a62;hp=32f2b4289f4372012cffcb1fd3240c4fcc118f7c;hb=baf69b8ddea3e2749f114a1e82bc1253ef062bc0;hpb=56b7e6953bb854114e145947f9cad90f16456a5f diff --git a/progcomp/judge/simulator/simulate.py b/progcomp/judge/simulator/simulate.py index 32f2b42..8937a2b 100755 --- a/progcomp/judge/simulator/simulate.py +++ b/progcomp/judge/simulator/simulate.py @@ -17,16 +17,27 @@ import os import sys +from time import time -baseDirectory = "/home/sam/Documents/progcomp2012/" +baseDirectory = "/home/sam/Documents/progcomp2012/progcomp/" resultsDirectory = baseDirectory+"results/" #Where results will go (results are in the form of text files of agent names and scores) -agentsDirectory = baseDirectory+"samples/" #Where agents are found (each agent has its own directory) +agentsDirectory = baseDirectory+"agents/" #Where agents are found (each agent has its own directory) logDirectory = baseDirectory+"log/" #Where log files go nGames = 10 #Number of games played by each agent against each opponent. Half will be played as RED, half as BLUE -managerPath = baseDirectory+"manager/stratego" #Path to the manager program +managerPath = baseDirectory+"judge/manager/stratego" #Path to the manager program +nRounds = 1 -scores = {"VICTORY":(3,1), "DEFEAT":(1,3), "SURRENDER":(0,3), "DRAW":(2,2), "DRAW_DEFAULT":(1,1), "ILLEGAL":(-1,2), "DEFAULT":(2,-1), "BOTH_ILLEGAL":(-1,-1), "INTERNAL_ERROR":(0,0)} #Score dictionary +time() + +if len(sys.argv) == 2: + nRounds = int(sys.argv[1]) +elif len(sys.argv) != 1: + print "Useage: simulate.py [nRounds]" + sys.exit(1) + + +scores = {"VICTORY":(3,1), "DEFEAT":(1,3), "SURRENDER":(0,3), "DRAW":(2,2), "DRAW_DEFAULT":(1,1), "ILLEGAL":(-1,2), "DEFAULT":(2,-1), "BOTH_ILLEGAL":(-1,-1), "INTERNAL_ERROR":(0,0), "BAD_SETUP":(0,0)} #Score dictionary verbose = True @@ -35,155 +46,177 @@ verbose = True if os.path.exists(resultsDirectory) == False: os.mkdir(resultsDirectory) #Make the results directory if it didn't exist #Identify the round number by reading the results directory -roundNumber = len(os.listdir(resultsDirectory)) + 1 -if roundNumber > 1: - roundNumber -= 1 +totalRounds = len(os.listdir(resultsDirectory)) + 1 +if totalRounds > 1: + totalRounds -= 1 if os.path.exists(logDirectory) == False: os.mkdir(logDirectory) #Make the log directory if it didn't exist +startTime = time() +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 os.path.exists(logDirectory + "round"+str(roundNumber)) == False: + os.mkdir(logDirectory + "round"+str(roundNumber)) #Check there is a directory for this round's logs -print "Simulating ROUND " +str(roundNumber) -print "Identifying possible agents in \""+agentsDirectory+"\"" - -#Get all agent names from agentsDirectory -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 + print "Simulating ROUND " +str(roundNumber) + print "Identifying possible agents in \""+agentsDirectory+"\"" + + #Get all agent names from agentsDirectory + agentNames = os.listdir(agentsDirectory) + agents = [] + for name in agentNames: + #sys.stdout.write("\nLooking at Agent: \""+ str(name)+"\"... ") if verbose: - sys.stdout.write(" Invalid! (Not a directory)\n") - continue + 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 - if verbose: - sys.stdout.write(" Valid!") - #sys.stdout.write("OK") - #Convert the array of names to an array of triples - #agents[0] - The name of the agent (its directory) - #agents[1] - The path to the program for the agent (typically agentsDirectory/agent/agent). Read from agentsDirectory/agent/info file - #agents[2] - The score the agent achieved in _this_ round. Begins at zero - agentExecutable = agentsDirectory+name+"/"+(open(agentsDirectory+name+"/info").readline().strip()) - agents.append([name, agentExecutable, 0]) - if verbose: - sys.stdout.write(" (Run program \""+agentExecutable+"\")\n") - -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... ("+str(nGames)+" games per pairing * " + str(len(agents) * len(agents)-1) + " pairings = " + str((len(agents) * len(agents)-1) * nGames) + " games)" - - -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. -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 - 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 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("Agents: \""+red[0]+"\" and \""+blue[0]+"\" playing game " + str(i) + "/"+str(nGames/2) + "... ") - logFile = logDirectory + "round"+str(roundNumber) + "/"+red[0]+"_vs_"+blue[0]+"_"+str(i) - outline = os.popen(managerPath + " -o " + logFile + " " + red[1] + " " + blue[1], "r").read() - results = outline.split(' ') - - if len(results) != 6: - if verbose: - sys.stdout.write("Garbage output! " + outline) - else: - if results[1] == "RED": - red[2] += scores[results[2]][0] - blue[2] += scores[results[2]][1] - elif results[1] == "BLUE": - red[2] += scores[results[2]][1] - blue[2] += scores[results[2]][0] - elif results[1] == "BOTH": - red[2] += scores[results[2]][0] - blue[2] += scores[results[2]][1] - red[2] += scores[results[2]][1] - blue[2] += scores[results[2]][0] + sys.stdout.write(" Invalid! (No \"info\" file found)\n") + continue + + + #Convert the array of names to an array of triples + #agents[0] - The name of the agent (its directory) + #agents[1] - The path to the program for the agent (typically agentsDirectory/agent/agent). Read from agentsDirectory/agent/info file + #agents[2] - The score the agent achieved in _this_ round. Begins at zero + agentExecutable = agentsDirectory+name+"/"+(open(agentsDirectory+name+"/info").readline().strip()) + + if os.path.exists(agentExecutable) == False: if verbose: - sys.stdout.write(" " + outline) + sys.stdout.write(" Invalid! (File \""+agentExecutable+"\" does not exist!)\n") + continue + + + if verbose: + sys.stdout.write(" Valid! (To run: \""+agentExecutable+"\")\n") + agents.append([name, agentExecutable, 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 "" + 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. + 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 + 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[0]+"\" and \""+blue[0]+"\" playing game " + str(i) + "/"+str(nGames/2) + "... ") + logFile = logDirectory + "round"+str(roundNumber) + "/"+red[0]+"_vs_"+blue[0]+"_"+str(i) + outline = os.popen(managerPath + " -o " + logFile + " " + red[1] + " " + blue[1], "r").read() + results = outline.split(' ') + + if len(results) != 6: + if verbose: + sys.stdout.write("Garbage output! \"" + outline + "\"\n") + managerErrors += 1 + else: + if results[1] == "RED": + red[2] += scores[results[2]][0] + blue[2] += scores[results[2]][1] + normalGames += 1 + elif results[1] == "BLUE": + red[2] += scores[results[2]][1] + blue[2] += scores[results[2]][0] + normalGames += 1 + elif results[1] == "BOTH": + red[2] += scores[results[2]][0] + blue[2] += scores[results[2]][1] + red[2] += scores[results[2]][1] + blue[2] += scores[results[2]][0] + draws += 1 + if verbose: + sys.stdout.write(" Result \"") + for ii in range(1, len(results)): + sys.stdout.write(results[ii].strip()) + if ii < (len(results) - 1): + sys.stdout.write(" ") + sys.stdout.write("\"\n") + -if verbose: - print "Completed combat. Total of " + str(normalGames + draws + aiErrors + managerErrors) + " games played. " -if managerErrors != 0: - print "WARNING: Recieved "+str(managerErrors)+" garbage outputs. Check the manager program." - -if verbose: - print "" -#We should now have complete score values. - -if verbose: - sys.stdout.write("Creating results files for ROUND " + str(roundNumber) + "... ") - -agents.sort(key = lambda e : e[2], reverse=True) #Sort the agents based on score - -resultsFile = open(resultsDirectory+"round"+str(roundNumber)+".results", "w") #Create a file to store all the scores for this round -for agent in agents: - resultsFile.write(agent[0] + " " + str(agent[2]) +"\n") #Write the agent names and scores into the file, in descending order - -if verbose: - sys.stdout.write(" Complete!\n") - sys.stdout.write("Updating total scores... "); + if verbose: + print "Completed combat. Total of " + str(normalGames + draws + aiErrors + managerErrors) + " games played. " + if managerErrors != 0: + print "WARNING: Recieved "+str(managerErrors)+" garbage outputs. Check the manager program." -#Now update the total scores -if os.path.exists(resultsDirectory+"total.scores"): if verbose: - sys.stdout.write(" Reading from \""+resultsDirectory+"total.scores\" to update scores... ") - totalFile = open(resultsDirectory+"total.scores", "r") #Try to open the total.scores file - for line in totalFile: #For all entries, - data = line.split(' ') - for agent in agents: - if agent[0] == data[0]: - agent.append(agent[2]) #Store the score achieved this round at the end of the list - agent[2] += int(data[1]) #Simply increment the current score by the recorded total score of the matching file entry - break - totalFile.close() #Close the file, so we can delete it - os.remove(resultsDirectory+"total.scores") #Delete the file - #Sort the agents again - agents.sort(key = lambda e : e[2], reverse=True) - -else: + print "" + #We should now have complete score values. + if verbose: - sys.stdout.write(" First round - creating \""+resultsDirectory+"total.scores\"... ") -if verbose: - sys.stdout.write(" Complete!\n") - print "Finished writing results for ROUND " + str(roundNumber) - print "" + sys.stdout.write("Creating results files for ROUND " + str(roundNumber) + "... ") + agents.sort(key = lambda e : e[2], reverse=True) #Sort the agents based on score + + resultsFile = open(resultsDirectory+"round"+str(roundNumber)+".results", "w") #Create a file to store all the scores for this round + for agent in agents: + resultsFile.write(agent[0] + " " + str(agent[2]) +"\n") #Write the agent names and scores into the file, in descending order -print "RESULTS FOR ROUND " + str(roundNumber) -print "Agent: [name, path, total_score, recent_score]" + if verbose: + sys.stdout.write(" Complete!\n") + sys.stdout.write("Updating total scores... "); + + #Now update the total scores + if os.path.exists(resultsDirectory+"total.scores"): + if verbose: + sys.stdout.write(" Reading from \""+resultsDirectory+"total.scores\" to update scores... ") + totalFile = open(resultsDirectory+"total.scores", "r") #Try to open the total.scores file + for line in totalFile: #For all entries, + data = line.split(' ') + for agent in agents: + if agent[0] == data[0]: + agent.append(agent[2]) #Store the score achieved this round at the end of the list + agent[2] += int(data[1]) #Simply increment the current score by the recorded total score of the matching file entry + break + totalFile.close() #Close the file, so we can delete it + os.remove(resultsDirectory+"total.scores") #Delete the file + #Sort the agents again + agents.sort(key = lambda e : e[2], reverse=True) + + else: + if verbose: + sys.stdout.write(" First round - creating \""+resultsDirectory+"total.scores\"... ") + if verbose: + sys.stdout.write(" Complete!\n") + print "Finished writing results for ROUND " + str(roundNumber) + print "" + + + print "RESULTS FOR ROUND " + str(roundNumber) + print "Agent: [name, path, total_score, recent_score]" -totalFile = open(resultsDirectory+"total.scores", "w") #Recreate the file -for agent in agents: - totalFile.write(agent[0] + " " + str(agent[2]) +"\n") #Write the total scores in descending order - print "Agent: " + str(agent) + totalFile = open(resultsDirectory+"total.scores", "w") #Recreate the file + for agent in agents: + totalFile.write(agent[0] + " " + str(agent[2]) +"\n") #Write the total scores in descending order + print "Agent: " + str(agent) -#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. + #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." +sys.exit(0)