def processIdle(conn, row): ''' Receves and processes idle animals ''' animal = eventAnimalFactory(conn, animalId = row['animalId']) animal.addCommandDefault() animal.pushData()
def selectScavengePrey(self, lvl): ''' Select the best animal to feed on we want to find the animal from which we'll find the most food in the time alotted this can either be limited by the amount of biomass, or by the animal's speed of eating ''' maxBiomass = 0.0 maxPrey = None #get all dead animals in the passed level c = db.animalData.columns statement = db.select([db.animalData], (c.animalX == lvl.cellIdX)\ & (c.animalY == lvl.cellIdY) & (c.animalZ == lvl.levelIdZ)\ & (c.state == base.States.DEAD) & ((c.attackerId == None) | (c.attackerId == self.animalId))) result = self.conn.execute(statement) rows = result.fetchall() result.close() #print "prey: " + repr(self.preySpecies) #select the best one to scavange # note: we could check here if we can break early for row in rows: #print repr(rows) #prey = base.Event(row = row, conn = self.conn) prey = top.eventAnimalFactory(self.conn, row = row) #print "species: " + repr(prey.species) if prey.species in self.preySpecies: #print "prey is a prey species" biomass = (prey.growth + prey.stored) * self.scavengeEfficiency if biomass > maxBiomass: maxBiomass = biomass maxPrey = prey #else: #print "prey is not a prey species" #can't eat more than there is room for room = self.unprocessedMax - self.unprocessed #room in it's stomach amount = min(room, maxBiomass) time = amount / self.scavengeRate if maxBiomass > room: maxBiomass = room if maxBiomass < 0.01: return False else: return (maxPrey, maxBiomass, time)
def preCommandHunt(self, preyId): ''' What to do right before a hunt command is set ''' #check that the prey.attackerId is free c = db.animalData.columns statement = db.select([db.animalData], c.animalId == preyId) result = self.conn.execute(statement) row = result.fetchone() result.close() if row == None or row['state'] == base.States.DEAD: #prey no longer exists, or is dead return False elif row['attackerId'] != None and row['attackerId'] != self.data['animalId']: #has has an attacker who isn't us return False #do the actual attack #from khopeshpy.animals import top #prey = top.event(animalId = preyId, conn = self.conn) #prey = base.Event(animalId = preyId, conn = self.conn) prey = top.eventAnimalFactory(self.conn, row = row) #first, attacker gets first strike so do that first self.stamina -= self.attackStaminaCost atkStr = self.attackStrength(self.health) prey.attacked(self.animalId, atkStr) dt = self.attackCooldown(self.stamina) self.addCommandAttackCooldown(dt, preyId) #two options if prey.health > 0.0: #print 'the prey lives' #any code to break off the attack would go here #do we need to be able to set this as un-interruptable? self.addCommandHunt(preyId, 0.0) else: #print 'the prey is dead' #set it to scavange the prey for a token amount of time self.addCommandScavenge(preyId, 1.0)
def postCommandScavenge(self, row, dt): ''' What to do after a scavenge command has compleated ''' self.markCmdFinished(row['eventId'], True) preyId = row['data'] #prey = base.Event(animalId = preyId, conn = self.conn) prey = top.eventAnimalFactory(conn = self.conn, animalId = preyId) #amount to be eaten is the least of the amount it could have eaten, the # amount there was, and the amount of room left in it's stomach room = self.unprocessedMax - self.unprocessed #room in it's stomach amountAvailable = (prey.growth + prey.stored) * self.scavengeEfficiency consumable = self.scavengeRate * dt #amount = room if room < amountAvailable else amountAvailable #amount = amount if amount < consumable else consumable amount = min(room, amountAvailable, consumable) self.stamina -= self.scavengeStaminaCost * dt self.stamina -= self.staminaDrain * dt self.unprocessed += amount prey.biomassEaten(amount / self.scavengeEfficiency) prey.attackerId = None prey.pushData() #remove our lock on the prey #c = db.animalData.columns #up = db.animalData.update().where((c.animalId == preyId)).\ #values(attackerId = None) #self.conn.execute(up) #and to remove the prey from our list self.updateStats(dt) self.scavenge += dt self.commandNext()
def processEvent(conn, row): ''' Receves and processes events from the event server ''' animal = eventAnimalFactory(conn, animalId = row['animalId']) #state check, death animal.stateCheck() #there is a problem, if say the server were left off all night # when it was restarted all animals would have massive stamina deficits # it would probably even kill everything, so we're changing this to just work # of off the anticipated time, or if the action is interrupted then # the time until it was interrupted dta = row['timeExpected']#ticks dtb = (float(time.time() - row['timeStarted']))/config.tick #ticks dt = min(dta, dtb) animal.mapPostCommand(row['command'])(row, dt) animal.pushData()
def selectHuntPrey(self, lvl, stateDiff): ''' Select the best animal to attack We want to find the animal which will give the best cost/oppertunity We have to consider how much mass we expect to get if we kill the animal vs. How much mass we'll lose to damage, energy, etc? ''' #print "stateDiff before: " + repr(stateDiff) maxBiomass = 0.0 maxPrey = None #ugh, have to pop these up to this level maxGainedBiomass = None maxNetStamina = None maxNetHealth = None maxNetTime = None #get all live animals, in the passed level, who don't have an attacker # current model can't handle multiple attackers c = db.animalData.columns statement = db.select([db.animalData], (c.animalX == lvl.cellIdX) &\ (c.animalY == lvl.cellIdY) & (c.animalZ == lvl.levelIdZ) &\ (c.state != base.States.DEAD) & (c.attackerId == None) & (c.animalId != self.animalId)) result = self.conn.execute(statement) rows = result.fetchall() result.close() #select the best one to hunt #create a dictionary of cost/advantage? for row in rows: #prey = base.Event(self.conn, animalId = row['animalId']) prey = top.eventAnimalFactory(self.conn, row = row) #only consider if it is a prey species if prey.species in self.preySpecies: #total biomass that will be available having killed the animal gainedBiomass = (prey.growth + prey.stored) * self.scavengeEfficiency #now the hard part #we want to simulate the fight and try to guess how much health we'll lose #the oppertunity cost should be absolute (ratio makes no sense) result = self.simulateFight(self, prey) if result != False: #if we didn't lose the fight lostStamina, lostHealth, lostTime = result netBiomass = gainedBiomass - (lostStamina + lostHealth) if netBiomass > maxBiomass: maxBiomass = netBiomass maxPrey = prey maxGainedBiomass = gainedBiomass maxNetStamina = lostStamina maxNetHealth = lostHealth maxNetTime = lostTime if maxPrey == None: #didn't find anything woth attacking return False #found something we want to attack, adjust the stateDiff stateDiff['stamina'] += maxNetStamina stateDiff['health'] += maxNetHealth stateDiff['time'] += maxNetTime if self.stamina + stateDiff['stamina'] <= 0.0: #ran out of stamina return False elif self.health + stateDiff['health'] <= 0.0: #ran out of health return False #now to calculate how much we gain by scavanging #only test for unprocessedMax because the hunter will be able to sit down and eat until their full #can't eat more than there is room for room = self.unprocessedMax - self.unprocessed #room in it's stomach amount = min(room, maxGainedBiomass) eatingTime = amount / self.scavengeRate #simulate eating until full stateDiff['unprocessed'] += amount stateDiff['time'] += eatingTime #print "stateDiff after: " + repr(stateDiff) totalTime = maxNetTime + eatingTime stateDiff['stamina'] -= self.staminaDrain * totalTime stateDiff['stamina'] -= self.scavengeStaminaCost * eatingTime return maxPrey.data['animalId'], totalTime