Fixed bugs, minor changes
[progcomp2012.git] / progcomp / judge / simulator / simulate.py
index 32f2b42..8937a2b 100755 (executable)
 
 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)

UCC git Repository :: git.ucc.asn.au