def Execute(self): if self.target_id != None: self.ai.enemy_id = self.target_id # default turning on & throttle off self.ai.Throttle(0) self.ai.Turn(100) heading = self.ai.GetHeadingToID(self.target_id, False) target_loc = plus.getLocation(self.target_id) clear_path = self.ai.IsStraightPathClear(self.ai.GetLocation(), target_loc) distance = (vector3(target_loc) - vector3(self.ai.GetLocation())).length() speed = self.ai.GetSpeed() # drive forward when we're aimed at the target if abs(heading + 0.5) < 1: self.ai.Throttle(100) else: self.ai.Throttle(0) return True else: return False
def Evaluate(self): # if we're near the edge of the arena, drive to the nearest safe point self.priority = -1000 a = Arenas.currentArena loc = vector3(self.ai.GetLocation()) # check to see if we're already over dist, over, h = a.DistanceToEdge(loc.asTuple()) if over: self.priority = 1000 return # now check to see if we're heading over angle = self.ai.GetHeading(False) dir = vector3(math.sin(angle), 0, math.cos(angle)) speed = self.ai.GetSpeed() look_ahead = .5 loc += dir * speed * look_ahead dist, over, h = a.DistanceToEdge(loc.asTuple()) if over: self.priority = 1000
def Execute(self): if self.target_id != None: self.ai.enemy_id = self.target_id clear_path = False if self.regroupTime <= 0: for r in (3, -3, 2, -2, 4, -4, 1, -1, 5, -5): angle = self.ai.GetHeading(True) + r * (math.pi / 6) new_dir = vector3(math.sin(angle), 0, math.cos(angle)) dest = vector3(self.ai.GetLocation()) + new_dir * 5 clear_path = self.ai.IsStraightPathClear( dest.asTuple(), self.ai.GetLocation()) if clear_path: self.regroupPos = dest.asTuple() self.regroupDir = (abs(r) <= 3) self.regroupTime = 40 break self.ai.DriveToLocation(self.regroupPos, self.regroupDir) self.regroupTime -= 1 return True else: return False
def CanDriveUpsideDown(self, bot): MOVE_THRESHOLD = 3.0 if bot in self.upTrack: t = self.upTrack[bot] if t.invertible: return True else: # check to see if he's moved recently position = plus.getLocation(bot) time = plus.getTimeElapsed() if time - t.last_time > 10: # this record is too old to be reliable t.last_time = time t.last_position = position return False v0 = vector3(t.last_position) v1 = vector3(position) if (v1 - v0).length() > MOVE_THRESHOLD: t.invertible = True return t.invertible else: t = UpsideDownTracker() t.last_position = plus.getLocation(bot) t.last_time = plus.getTimeElapsed() self.upTrack[bot] = t return False
def StuckHandler(self): "This default generator is called when the bot is almost immobile." while 1: # back up for 2 seconds (will stop once we're not immobile) for i in range(0, 2000): pos = vector3(self.GetLocation()) dir = vector3(self.GetDirection()) self.NormalDriveToLocation((pos - dir * 3).asTuple(), True) yield 0 # go forward for 2 seconds for i in range(0, 2000): pos = vector3(self.GetLocation()) dir = vector3(self.GetDirection()) self.NormalDriveToLocation((pos + dir * 3).asTuple(), True) yield 0
def Execute(self): a = Arenas.currentArena heading = self.ai.GetHeading(False) h = a.HeadingAwayFromEdge(self.ai.GetLocation()) v_us = vector3(heading) v_away = vector3(h) dir = 1 if v_us.dot(v_away) < 0: h = -h dir = -1 self.ai.AimToHeading(-h) self.ai.Throttle(100 * dir) return True
def Execute(self): if self.target_location and self.target_id != None: self.ai.enemy_id = self.target_id e = vector3(plus.getLocation(self.target_id)) dest = vector3(self.target_location) dir = dest - e dir.y = 0 # default turning & throttle off self.ai.Throttle(0) self.ai.Turn(0) # end this action if enemy is close to destination if dir.length() < 1: return False dir.normalize() a = Arenas.currentArena # try to line up behind enemy (or to the sides as a last resort) target = e - dir * 3 clear_path = self.ai.IsStraightPathClear(self.ai.GetLocation(), target.asTuple()) if not clear_path: dir.x, dir.y, dir.z = dir.z, dir.y, dir.x target = e - dir * 3 clear_path = self.ai.IsStraightPathClear( self.ai.GetLocation(), target.asTuple()) if not clear_path: dir.x, dir.z = -dir.x, -dir.z target = e - dir * 3 if not self.ai.DriveToLocation(target.asTuple()): # TODO: head toward enemy or target location?! #h = self.ai.GetHeadingTo(e.asTuple(), False) h = self.ai.GetHeadingTo(self.target_location, False) if abs(h) > .25: self.ai.AimToHeading(h) else: # shove! self.ai.Throttle(100) return True else: return False
def Execute(self): "Try to reorient to a new attack position for a few seconds." if not self.ai.lastTactic or self.ai.lastTactic.name != "Reorient": # reorienting anew self.target_id, range = self.ai.GetNearestEnemy() self.timeStarted = plus.getTimeElapsed() self.destination = None self.bInReverse = False if self.target_id != None: # pick a location to one side of the target bot and drive to it, then attack again target = plus.getLocation(self.target_id) loc = self.ai.GetLocation() distance = (-5, 5) dir = vector3(target) - vector3(loc) dir.normalize() dir.x, dir.z = dir.z, dir.x for d in distance: # drive toward the side of the enemy for about 5 seconds dest = vector3(target) + dir * d if self.ai.IsStraightPathClear(loc, dest.asTuple()): self.destination = dest break # if the sides are unavailable, try backing up or going forward if not self.destination: distance = (-5, 5) dir.x, dir.z = dir.z, dir.x for d in distance: dest = vector3(target) + dir * d if self.ai.IsStraightPathClear(loc, dest.asTuple()): self.destination = dest if d < 0: self.bInReverse = True else: self.bInReverse = False break if self.destination != None: self.ai.DriveToLocation(self.destination.asTuple(), self.bInReverse) return True return False
def StuckHandler(self): "This default generator is called when the bot is almost immobile." while 1: self.Input("Shove", 0, 0) # go forward for ?? seconds for i in range(0, 22): self.Input("Shove", 0, 0) pos = vector3(self.GetLocation()) dir = vector3(self.GetDirection()) self.DriveToLocation((pos + dir * 3).asTuple()) yield 0 # back up for ?? seconds (will stop once we're not immobile) for i in range(0, 6): self.Input("Shove", 0, 0) pos = vector3(self.GetLocation()) dir = vector3(self.GetDirection()) self.DriveToLocation((pos - dir * 3).asTuple(), True) yield 0
def CanDriveUpsideDown(self, bot): MOVE_THRESHOLD = self.move_thresh if bot in self.upTrack: t = self.upTrack[bot] # self.tauntbox.get("taunt1").setText(str(t.contact)) # Check if we've made contact with the enemy if (self.flip == 1 or self.compinzone == 1) and t.contact == 0: t.contact = 1 # check to see if he's moved recently position = plus.getLocation(bot) time = plus.getTimeElapsed() if time - t.last_time > self.move_time: # this record is too old to be reliable t.last_time = time t.last_position = position #return False v0 = vector3(t.last_position) v1 = vector3(position) # Don't assume the enemy is immobile if we haven't made contact if (v1 - v0).length() > MOVE_THRESHOLD or t.contact == 0: # Reality check: Is the enemy actually still mobile (after a cooldown period to let them settle) - if so, reset contact if t.contact == 2 and time - t.stoptime > self.cooldown: t.contact = 0 return True else: return True # Check if we've made contact and the enemy isn't moving if (v1 - v0).length() <= MOVE_THRESHOLD and t.contact > 0: if t.contact == 1: t.contact = 2 t.stoptime = plus.getTimeElapsed() return False else: t = UpsideDownTracker() t.last_position = plus.getLocation(bot) t.last_time = plus.getTimeElapsed() t.contact = 0 t.stoptime = plus.getTimeElapsed() self.upTrack[bot] = t return False
def Tick(self): if self.emitting == True: if plus.isMatchOver(): self.FlameOff() if self.timeEmitting < 1: #flames are long enough by the end of 1 second self.timeEmitting += .25 vel = vector3(self.velocity) flamepos = vel * self.timeEmitting flamepos = flamepos + vector3(self.location) arena = Arenas.currentArena if arena: compinfo = plus.rayTest(self.adjustedLoc.asTuple(), flamepos.asTuple()) if not compinfo[ 0] == -1: # we got a valid bot and component back from the ray test if not plus.isMatchPaused() and not plus.isMatchOver(): plus.damage(compinfo[0], compinfo[1], 25, (compinfo[2], compinfo[3], compinfo[4]))
def Evaluate(self): self.priority = 0 self.target_id, range = self.ai.GetNearestEnemy() self.target_location = None if self.target_id != None: # get hazard nearest enemy a = Arenas.currentArena enemy_loc = plus.getLocation(self.target_id) hazard = a.GetNearestHazard(enemy_loc) if hazard != None: self.priority = 100 self.target_location = hazard.location # target too close to hazard = less desirable distance = (vector3(self.target_location) - vector3(enemy_loc)).length() if distance < 1: self.priority -= 75 clear_path = self.ai.IsStraightPathClear( enemy_loc, self.target_location) if not clear_path: self.priority -= 50 #d1 = vector3(self.ai.GetLocation()) - vector3(enemy_loc) d2 = vector3(enemy_loc) - vector3(self.target_location) # penalties for distance to enemy & distance from enemy to hazard self.priority -= (range * 3) self.priority -= (d2.length() * 2) else: self.priority -= 100 else: self.priority -= 100
def __init__(self, location=(0, 0, 0), velocity=(0, 0, 0), variance=(0, 0, 0), yOffset=0): Hazard.__init__(self, location) self.refcount = 0 self.velocity = velocity self.variance = variance self.emitter = plus.AddParticleEmitter(self.location, self.velocity, self.variance) self.emitting = False self.timeEmitting = 0 self.adjustedLoc = vector3(self.location) self.adjustedLoc.y += yOffset self.flamesound = plus.createSound("Sounds/flame_thrower.wav", True, self.location)
def Evaluate(self): # if we have a clean shot at an enemy near an edge, go for it self.priority = -1000 enemies = self.ai.GetEnemies() a = Arenas.currentArena threshold = 5 for enemy in enemies: self.target_id = enemy enemy_loc = plus.getLocation(enemy) dist, over, h = a.DistanceToEdge(enemy_loc) if dist < threshold: # if enemy is close to edge & we're heading toward the edge, push him push_loc = vector3(enemy_loc).move(self.ai.GetHeading(False), threshold) dist, over, h = a.DistanceToEdge(push_loc.asTuple()) if over and self.ai.IsStraightPathClear( self.ai.GetLocation(), enemy_loc): priority = 100 - 50 * abs( self.ai.GetHeadingToID(enemy, False)) if priority > self.priority: self.priority = priority
def Execute(self): if self.target_id != None: self.ai.enemy_id = self.target_id # default turning & throttle off self.ai.Throttle(0) self.ai.Turn(0) # other info heading = self.ai.GetHeadingToID(self.target_id, False) target_loc = plus.getLocation(self.target_id) clear_path = self.ai.IsStraightPathClear(self.ai.GetLocation(), target_loc) distance = (vector3(target_loc) - vector3(self.ai.GetLocation())).length() speed = self.ai.GetSpeed() # adjust sight range based on speed so we have time to react to obstacles self.sight_range = self.sight_range_base + (0.2 * abs(speed)) # keep track of points in front of and behind us for obstacle detection fx = (self.sight_range * math.sin( self.ai.GetHeading(False))) + self.ai.GetLocation()[0] fz = (self.sight_range * math.cos( self.ai.GetHeading(False))) + self.ai.GetLocation()[2] rx = (-1 * self.sight_range * math.sin( self.ai.GetHeading(False))) + self.ai.GetLocation()[0] rz = (-1 * self.sight_range * math.cos( self.ai.GetHeading(False))) + self.ai.GetLocation()[2] fry = self.ai.GetLocation()[1] forloc = (fx, fry, fz) rearloc = (rx, fry, rz) # markers for detection points #plus.emitSmoke(30, (forloc), (0, 2, 0), (3, 3, 3)) #plus.emitSmoke(30, (rearloc), (0, 2, 0), (3, 3, 3)) # are there obstacles in front of us or behind us forclear = self.ai.IsStraightPathClear(self.ai.GetLocation(), forloc) rearclear = self.ai.IsStraightPathClear(self.ai.GetLocation(), rearloc) #self.tauntbox.get("taunt1").setText("fc:" + str(forclear) + " rc:" + str(rearclear) + " reorient:" + str(self.reorient) + " BUtimer:" + str(self.backuptimer)) # if we're close to the enemy and not moving fast, try to get away for another ram if (distance < self.sight_range_base and speed > -self.threshold_speed and self.backuptimer < self.backuptime) or self.reorient == 1: # if the enemy is on our flank, turn to face them a bit better if (math.pi / 3) < abs(heading) < (2 * math.pi / 3): self.ai.AimToHeading(heading) # if we're facing the enemy and there's nothing behind us, back up as far as possible if abs(heading) <= (math.pi / 3): if rearclear: self.reorient = 1 self.ai.Turn(0) self.ai.Throttle(100) else: self.reorient = 0 # if we can't get away, push back if abs(heading) < (math.pi - 0.25): self.ai.AimToHeading(heading) else: self.ai.Throttle(100) # if we're facing away from the enemy and there's nothing in front of us, drive forward to get away if abs(heading) >= (2 * math.pi / 3): if forclear: self.reorient = 1 self.ai.Turn(0) self.ai.Throttle(-100) else: self.reorient = 0 # if we can't get away, try to turn around and push back if abs(heading) < (math.pi - 0.25): self.ai.AimToHeading(heading) else: self.ai.Throttle(100) # optional timer for bots that go crazy after too long in reverse if self.reorient == 1: self.backuptimer += 1 if self.backuptimer >= self.backuptime: self.reorient = 0 # 2 times our base sight range is far enough away if distance >= (self.sight_range_base * 2): self.backuptimer = 0 self.reorient = 0 elif (distance < self.sight_range_base and speed > -self.threshold_speed and self.backuptimer >= self.backuptime): if abs(heading) < (math.pi - 0.25): self.ai.AimToHeading(heading) else: self.ai.Throttle(100) # reset backuptimer when we hit the enemy if plus.getTimeElapsed() - self.ai.GetLastDamageDone( )[2] <= 0.5: self.backuptimer = 0 elif not clear_path: # if we don't have a clear shot, get closer self.ai.DriveToLocation(plus.getLocation(self.target_id)) else: # Ram the opponent if self.nosecone > 0: if abs(heading) < math.pi - math.tan( self.nosecone / distance): self.ai.AimToHeading(heading) else: self.ai.Throttle(100) # stop charging if we're near the edge! if plus.getGameType() == "TABLETOP": a = Arenas.currentArena loc = vector3(self.ai.GetLocation()) # check to see if we're already over dist, over, h = a.DistanceToEdge(loc.asTuple()) if over: return False # now check to see if we're heading over angle = self.ai.GetHeading(False) dir = vector3(math.sin(angle), 0, math.cos(angle)) speed = self.ai.GetSpeed() look_ahead = .5 loc += dir * speed * look_ahead dist, over, h = a.DistanceToEdge(loc.asTuple()) if over: return False # drive as fast as we can toward the target if abs(heading) < (math.pi - 0.25): self.ai.AimToHeading(heading) else: self.ai.Throttle(100) return True else: return False
def Execute(self): if self.target_id != None: self.ai.enemy_id = self.target_id # default turning & throttle off self.ai.Throttle(0) self.ai.Turn(0) heading = self.ai.GetHeadingToID(self.target_id, False) target_loc = plus.getLocation(self.target_id) clear_path = self.ai.IsStraightPathClear(self.ai.GetLocation(), target_loc) distance = (vector3(target_loc) - vector3(self.ai.GetLocation())).length() speed = self.ai.GetSpeed() # if we're close but not moving very fast, pick a new location and back toward it if (distance < 3 and speed < 2.0) or (distance < 5 and speed < 0): if self.regroupPos == None or self.regroupTime <= 0: self.regroupPos = None # pick a point near us that has a clear shot at the target? for r in (0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6): angle = self.ai.GetHeading(True) + r * (math.pi / 6) new_dir = vector3(math.sin(angle), 0, math.cos(angle)) dest = vector3(target_loc) + new_dir * 5 clear_path = self.ai.IsStraightPathClear( dest.asTuple(), target_loc) if clear_path: self.regroupPos = dest.asTuple() self.regroupDir = (abs(r) <= 3) self.regroupTime = 16 break # sanity check: if we can't find a valid position, drive forward or backward if self.regroupPos == None: self.regroupDir = not self.regroupDir range = 5 if self.regroupDir: range = -5 self.regroupPos = ( vector3(self.ai.GetLocation()) + vector3(self.ai.GetDirection()) * range).asTuple() self.regroupTime = 16 self.ai.DriveToLocation(self.regroupPos, self.regroupDir) self.regroupTime -= 1 elif distance > 3 and abs(heading) > .35 or not clear_path: # if we don't have a clear shot, get closer self.ai.DriveToLocation(plus.getLocation(self.target_id)) else: # stop charging if we're near the edge! if plus.getGameType() == "TABLETOP": a = Arenas.currentArena loc = vector3(self.ai.GetLocation()) # check to see if we're already over dist, over, h = a.DistanceToEdge(loc.asTuple()) if over: return False # now check to see if we're heading over angle = self.ai.GetHeading(False) dir = vector3(math.sin(angle), 0, math.cos(angle)) speed = self.ai.GetSpeed() look_ahead = .5 loc += dir * speed * look_ahead dist, over, h = a.DistanceToEdge(loc.asTuple()) if over: return False # drive as fast as we can toward the target self.ai.AimToHeading(heading) self.ai.Throttle(100) self.regroupPos = None return True else: return False