mcc avatar mcc committed 8d9e516

Unique sids appears to work, but numbers run backward.

Comments (0)

Files changed (1)

 def randomfrom(s):
 	return s[randint(0,len(s)-1)]
 
+def randomfromdict(s):
+	return s[randomfrom(s.keys())]
+
 class Board:
 	def __init__(self, xdim = 24, ydim = 24, suppress = False):
 		self.xdim = xdim
 class Genome:
 	def __init__(self, _id):
 		self.id = _id
-		self.specs = []
+		self.specs = {} # Unordered
+		self.specs_stack = [] # Ordered
 		basic = Spec(self.id)
 		self.issue_next = 0
 		self.generation_count = 1
+		self.id_generator = 0
 		for i in range(options.specs):
+			nid = self.nextid()
 			s = basic.clone().mutate()
-			s.sid = i
-			self.specs.append(s)
+			s.sid = nid
+			self.specs[nid] = s
+			self.specs_stack.append(s)
+		self.last_valid = self.specs_stack[0]
+
+	def nextid(self):
+		self.id_generator += 1
+		return self.id_generator
 
 	def any(self):
-		if self.issue_next >= len(self.specs):
+		if len(self.specs_stack) == 0:
+			old_specs_list = self.specs.values()
+			new_specs_list = old_specs_list # Do a funny dance so we can recover if there's an exception.
+			new_specs = self.specs
 			try:
-				old_specs = self.specs
-				new_specs = [] # Do a funny dance so we can recover if there's an exception.
 				def fitness(x,y): # resort by these criteria
 					if not (x.checked or y.checked):
 						return 0
 					if x.deaths != y.deaths:
 						return cmp(x.deaths, y.deaths)
 					return cmp(x.lastf, y.lastf) # Last ditch
-				sorted_old_specs = sorted(old_specs, cmp=fitness)
-				winner1 = sorted_old_specs[0]
-				winner2 = sorted_old_specs[1]
-				winner1sid = winner1.sid # Only used for logging
-				winner2sid = winner2.sid
+				sorted_old_specs_list = sorted(old_specs_list, cmp=fitness)
+				winner1 = sorted_old_specs_list[0]
+				winner2 = sorted_old_specs_list[1]
+				candidate_specs_list = []
+				candidate_specs = {}
 				if options.debug > 1:
 					print("Recombining genome %d. Winning specs: %d, %d" % (self.id, winner1.sid, winner2.sid))
-				for i in range(len(old_specs)):
-					old_spec = old_specs[i]
+				for old_spec in old_specs_list:
 					if old_spec.checked:
 						s = winner1.clone().recombine(winner2).mutate()
+						s.sid = self.nextid()
 					else:
 						s = old_spec
 						if options.debug > 2:
 							print("Preserving spec %d" % (s.sid))
-					s.sid = i
-					new_specs.append(s)
-				self.specs = new_specs
+					candidate_specs_list.append(s)
+					candidate_specs[s.sid] = s
+				new_specs_list = candidate_specs_list
 				self.generation_count = self.generation_count + 1
 				
 				if history_file:
 					lo = history_dom.createElement("breed")
 					lo.setAttribute("gid", str(self.id))
 					lo.setAttribute("gc", str(self.generation_count))
-					lo.setAttribute("winner1", str(winner1sid))
-					lo.setAttribute("winner2", str(winner2sid))
-					for s in self.specs:
+					lo.setAttribute("winner1", str(winner1.sid))
+					lo.setAttribute("winner2", str(winner2.sid))
+					for sid,s in self.specs.iteritems():
 						s.archive_xml(history_dom, lo)
 					history_file.write(lo.toxml())
 					history_file.write("\n")
 					history_file.flush()
+				new_specs_list = candidate_specs_list
+				new_specs = candidate_specs
 			finally:
-				self.issue_next = 0
+				self.specs_stack = new_specs_list
+				self.specs = new_specs
 		
-		s = self.specs[self.issue_next]
-		self.issue_next = self.issue_next + 1
-		return s
+		return self.specs_stack.pop()
 	
 	def report(self, post_obj):
 		sid = int(post_obj.getAttribute("sid"))
 
 class Manager:
 	def __init__(self):
-		self.tanks = []
-		for i in range(options.tanks):
+		self.tanks = {}
+		for _i in range(options.tanks):
+			i = _i + 1
 			if options.debug > 0:
 				print("Generating tank %d" % i)
-			self.tanks.append(Genome(i))
+			self.tanks[i] = Genome(i)
 	
 	def any(self):
-		return randomfrom(self.tanks)
+		return randomfromdict(self.tanks)
 		
 	def report(self, post_obj):
 		for a in ["gid","sid","deaths","lastf"]:
 		try:
 			gid = int(post_obj.getAttribute("gid"))
 			self.tanks[gid].report(post_obj)
-		except ValueError, IndexError:
+		except (ValueError, IndexError, KeyError):
 			pass
 
 class LuaHandler(tornado.web.RequestHandler):
 	
 	if history_file: # initial logging
 		lo = history_dom.createElement("init")
-		for g in m.tanks:
+		for gid, g in m.tanks.iteritems():
 			lot = history_dom.createElement("tank")
-			lot.setAttribute("gid", str(g.id))
+			lot.setAttribute("gid", str(gid))
 			lot.setAttribute("gc", str(g.generation_count))
-			for s in g.specs:
+			for sid,s in g.specs.iteritems():
 				s.archive_xml(history_dom, lot)
 			lo.appendChild(lot)
 			lot = None # How aggressive is Python's gc...?
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.