Example #1
0
class Critter:
	def __init__(self, pos):
		"""
			Initializes a critter creating his brain, setting
			his energy and age using the settings functions
			and assigning it the given position

			Parameter pos is a tuple with the coordinates 
			of the critter in the world 
		"""
		self.brain  = Brain()
		self.energy = Critter_s.start_energy()
		self.age    = Critter_s.start_age()
		self.pos = pos

	def process(self, world, partners = None):
		"""
			Moves this critter, makes this critter learn and 
			returns list of children from the available partners that this
			critter decided to mate with

			Parameter world is a grid (environment.Grid) of the world
			Parameter partners is a list of critters available for mating
		"""
		sub = world.sub_grid(self.pos)

		inputs  = sub.values + [self.energy]		# list composed by what the critter sees plus its energy
		outputs = self.brain.process(inputs, 0)		# list of four values indicating the movement
		action  = parse_move(outputs)				# resulting movement vector obtained from the outputs 

		best = evaluate_move(sub, outputs)	# evaluate the best possible move
		self.brain.learn(inputs, best, 0)	# make the critter learn in case he took the wrong direction 

		# assign new position
		new_pos = [0, 0] 
		new_pos[0] = max(0, min(self.pos[0] + action[0], Environment_s.width -1))
		new_pos[1] = max(0, min(self.pos[1] + action[1], Environment_s.height -1))

		# decrease energy and increase age
		if new_pos != self.pos:
			self.energy -= Critter_s.move_cost
		else:
			self.energy -= Critter_s.stand_cost
		self.age += 1

		# move if the new position isn't occupied
		if world.access_value(new_pos[0], new_pos[1]) != Environment_s.grid_crit:
			self.pos = tuple(new_pos)
		#ToDo decide if stay, push or kill

		children = []
		if partners != None and self.age >= Critter_s.min_mate_age and self.energy >= Critter_s.mate_cost:				# if this critter is in condition to mate...
			for partner in partners:
				partner_constraints = partner.age >= Critter_s.min_mate_age2 and partner.energy >= Critter_s.mate_cost2

				inputs = [partner.energy, partner.age, self.energy]
				mate_decision = round(self.brain.process(inputs, 1)[0])

				if partner_constraints and mate_decision:																# ...the partner is in condition to mate,
					children.append(self.crossover(partner))															# and this critter wants to, then they mate 
		return children

	def crossover(self, partner):
		"""
			Returns the critters' child and decreases energy to
			this critter and the partner

			Parameter partner is the critter's partner
		"""
		self.energy    -= Critter_s.mate_cost
		partner.energy -= Critter_s.mate_cost2

		child = Critter(Critter_s.randpos())
		child.brain = self.brain.crossover(partner.brain)
		return child

	def copy(self):
		"""
			Returns a copy of this critter
		"""
		critter = Critter(self.pos)
		critter.brain  = self.brain.copy()
		critter.energy = self.energy
		critter.age    = self.age
		return critter

	def eat(self, food = Environment_s.def_food):
		"""
			Increases energy depending on the food type

			Parameter food is the food type, the constants are on the settings. Leave blank for deafult food
		"""
		self.energy += Critter_s.food_reward[food]

	def collide(self):
		"""
			Decreases energy on collision
		"""
		self.energy -= Critter_s.coll_cost
		# ToDo different kind of collisions 

	def is_dead(self):
		"""
			Checks this critter's pulse and returns whether or not his heart has stopped
		"""
		return self.energy <= 0

	def __str__(self):
		"""
			Override of the __str__ function
			used when printing or converting
			Critter to str
		"""
		return "age: " + str(self.age) + " energy: " + str(self.energy) + " position: " + str(self.pos)