Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from __future__ import generators
- import plus
- import AI
- from AI import vector3
- import Arenas
- import Gooey
- import math
- import operator
- import Tactics
- import Tactics_2
- class SpinupOmni2(AI.SuperAI):
- "Waits for weapon to spin up before moving. Also reverses weapon if it gets jammed."
- name = "SpinupOmni3"
- # Update 7/24/12: Fixed AI not moving to avoid immobility when the weapon is jammed.
- # ***CUSTOMIZABLE SETTINGS*** #
- # 'ticks' sets how many times per tick the AI checks its RPM (Revolutions Per Minute) (a tick is 1/8 second). Needs to be high for accurate measurements on fast spinners, but too high causes lag. Default is 3.75 (=30 times/second).
- # ***NOTE*** RA2 can't measure times less than 1/30 second. Therefore the RPM calculator is only accurate for speeds of 1500, 750, 500, 375, 300, and <250 RPM. Speeds over 1500 RPM can't be measured, and accuracy decreases with increasing RPM.
- # 'MotorID' tells the AI which motor to measure RPM on.
- # 'Motor2ID' (Optional) Set ID for a second motor to measure RPM on.
- # 'TargetRPM' is the RPM the weapon needs to be spinning at before the AI will move. (With two motors, only one needs to exceed the target RPM.) Default is 100.
- # 'DisplayRPM' Set this to 1 to display current RPM, average RPM, and maximum RPM during battle. Use this to determine ticks and TargetRPM values.
- # 'JamTime' Sets the amount of time (in seconds) the weapon should be jammed for, before reversing the direction in an attempt to unjam it. For unidirectional weapons, just set to 999. Default is 1.5.
- def __init__(self, **args):
- AI.SuperAI.__init__(self, **args)
- self.zone = "weapon"
- self.triggers = ["Fire"]
- self.trigger2 = ["Srimech"]
- self.reloadTime = 0
- self.reloadDelay = 3
- self.tickFactor = 3.75
- self.spin_range = 3.0
- self.motorID = 2
- self.motorID2 = -1
- self.RPM = 0
- self.RPM2 = 0
- self.revolution = 0
- self.revolution2 = 0
- self.measuring = 0
- self.measuring2 = 0
- self.max_RPM = 0
- self.RPMhist = []
- self.avg_RPM = 0
- self.display = 0
- self.targetRPM = 100
- self.spin_reverse = 0
- self.jamTimer = 0
- self.raspberry = 1.5
- self.stopFunction = self.Stop
- if 'range' in args:
- self.spin_range = args.get('range')
- if 'triggers' in args: self.triggers = args['triggers']
- if 'reload' in args: self.reloadDelay = args['reload']
- if 'ticks' in args: self.tickFactor = args['ticks']
- if 'MotorID' in args: self.motorID = args['MotorID']
- if 'Motor2ID' in args: self.motorID2 = args['Motor2ID']
- if 'DisplayRPM' in args: self.display = args['DisplayRPM']
- if 'TargetRPM' in args: self.targetRPM = args['TargetRPM']
- if 'JamTime' in args: self.raspberry = args['JamTime']
- self.triggerIterator = iter(self.triggers)
- self.tactics.append(Tactics_2.Tactic_Evade(self))
- def Activate(self, active):
- plus.AI.__setattr__tickInterval__(self, 0.125/self.tickFactor)
- if active:
- if AI.SuperAI.debugging:
- self.debug = Gooey.Plain("watch", 0, 75, 100, 75)
- tbox = self.debug.addText("line0", 0, 0, 100, 15)
- tbox.setText("Throttle")
- tbox = self.debug.addText("line1", 0, 15, 100, 15)
- tbox.setText("Turning")
- tbox = self.debug.addText("line2", 0, 30, 100, 15)
- tbox.setText("")
- tbox = self.debug.addText("line3", 0, 45, 100, 15)
- tbox.setText("")
- if self.display != 0:
- self.tauntbox = Gooey.Plain("taunt", 10, 175, 640, 175)
- tbox = self.tauntbox.addText("taunt1", 10, 0, 640, 15)
- tbox.setText("")
- tbox2 = self.tauntbox.addText("taunt2", 10, 20, 640, 15)
- tbox2.setText("")
- tbox3 = self.tauntbox.addText("taunt3", 10, 40, 640, 15)
- tbox3.setText("")
- tbox4 = self.tauntbox.addText("taunt4", 10, 60, 640, 15)
- tbox4.setText("")
- self.RegisterSmartZone(self.zone, 1)
- else:
- # get rid of reference to self
- self.stopFunction = None
- return AI.SuperAI.Activate(self, active)
- def Tick(self):
- if self.display != 0:
- self.tauntbox.get("taunt1").setText(str(self.RPM) + " RPM")
- if self.motorID2 > 0:
- self.tauntbox.get("taunt2").setText(str(self.RPM2) + " RPM (Motor 2)")
- else:
- self.tauntbox.get("taunt2").setText("No motor 2.")
- self.tauntbox.get("taunt3").setText("Average RPM: "+str(self.avg_RPM))
- self.tauntbox.get("taunt4").setText("Maximum RPM: "+str(self.max_RPM))
- #Measure RPM
- if (self.GetMotorAngle(self.motorID) > math.pi/3 or self.GetMotorAngle(self.motorID) < 0) and self.measuring == 0:
- self.revolution = plus.getTimeElapsed()
- self.measuring = 1
- if 0 < self.GetMotorAngle(self.motorID) < math.pi/3 and self.measuring == 1:
- self.RPM = 50/(plus.getTimeElapsed() - self.revolution)
- if self.display != 0:
- self.RPMhist.append(self.RPM)
- if self.RPM > self.max_RPM:
- self.max_RPM = self.RPM
- self.measuring = 0
- if self.motorID2 > 0:
- #Measure RPM of second motor
- if (self.GetMotorAngle(self.motorID2) > math.pi/3 or self.GetMotorAngle(self.motorID2) < 0) and self.measuring2 == 0:
- self.revolution2 = plus.getTimeElapsed()
- self.measuring2 = 1
- if 0 < self.GetMotorAngle(self.motorID2) < math.pi/3 and self.measuring2 == 1:
- self.RPM2 = 50/(plus.getTimeElapsed() - self.revolution2)
- if self.display != 0:
- self.RPMhist.append(self.RPM2)
- if self.RPM2 > self.max_RPM:
- self.max_RPM = self.RPM2
- self.measuring2 = 0
- if len(self.RPMhist) > 0:
- self.avg_RPM = reduce(operator.add, self.RPMhist)/len(self.RPMhist)
- # fire weapon
- # spin up depending on enemy's range
- enemy, range = self.GetNearestEnemy()
- if enemy is not None and range < self.spin_range:
- if self.spin_reverse == 0:
- self.Input("Spin", 0, 100)
- if self.spin_reverse == 1:
- self.Input("Spin", 0, -100)
- elif self.GetInputStatus("Spin", 0) != 0:
- self.Input("Spin", 0, 0)
- # Optional turning control to aid in self righting
- if self.IsUpsideDown() and not self.bInvertible:
- self.Input("Sridrive", 0, 100)
- else:
- self.Input("Sridrive", 0, 0)
- # Try reversing weapons if they get jammed
- if plus.getTimeElapsed() - self.revolution > self.raspberry or (self.motorID2 > 0 and plus.getTimeElapsed() - self.revolution2 > self.raspberry):
- self.jamTimer += 1
- else:
- self.jamTimer = 0
- if self.jamTimer >= 24*self.tickFactor and self.spin_reverse == 0:
- self.spin_reverse = 1
- self.jamTimer = 0
- if self.jamTimer >= 24*self.tickFactor and self.spin_reverse == 1:
- self.spin_reverse = 0
- self.jamTimer = 0
- targets = [x for x in self.sensors.itervalues() if x.contacts > 0 \
- and not plus.isDefeated(x.robot)]
- if self.weapons:
- # slight delay between firing
- if self.reloadTime > 0: self.reloadTime -= 1
- if len(targets) > 0 and self.reloadTime <= 0:
- try:
- trigger = self.triggerIterator.next()
- except StopIteration:
- self.triggerIterator = iter(self.triggers)
- trigger = self.triggerIterator.next()
- self.Input(trigger, 0, 1)
- self.reloadTime = self.reloadDelay
- bReturn = AI.SuperAI.Tick(self)
- # call this now so it takes place after other driving commands
- if self.stopFunction: self.stopFunction(len(targets) > 0)
- return bReturn
- def Stop(self, bTarget):
- # Avoid the enemy if weapon isn't spinning fast
- if self.weapons and not self.bImmobile and (self.RPM > self.targetRPM or (self.motorID2 > 0 and self.RPM2 > self.targetRPM)):
- self.tactics.append(Tactics.Engage(self))
- if self.weapons and not self.bImmobile and (self.RPM < self.targetRPM or (self.motorID2 > 0 and self.RPM2 < self.targetRPM)):
- self.tactics.append((Tactics_2.Tactic_Evade(self))
- # stay put if the weapon is jammed, to give it a chance to unjam
- if (plus.getTimeElapsed() - self.revolution > self.raspberry or (self.motorID2 > 0 and plus.getTimeElapsed() - self.revolution2 > self.raspberry)) and not self.bImmobile:
- self.Throttle(0)
- 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, 16*self.tickFactor):
- pos = vector3(self.GetLocation())
- dir = vector3(self.GetDirection())
- self.DriveToLocation((pos - dir * 3).asTuple(), True)
- yield 0
- # go forward for 2 seconds
- for i in range(0, 16*self.tickFactor):
- pos = vector3(self.GetLocation())
- dir = vector3(self.GetDirection())
- self.DriveToLocation((pos + dir * 3).asTuple())
- yield 0
- def Think(self):
- self.Evaluate()
- self.countdownToEvaluation = 8*self.tickFactor
- # shut down motors while we think
- self.Throttle(0)
- self.Turn(0)
- def InvertHandler(self):
- # fire all weapons once per second (until we're upright!)
- while 1:
- for trigger in self.trigger2:
- self.Input(trigger, 0, 1)
- for i in range(0, 8*self.tickFactor):
- yield 0
- def LostComponent(self, id):
- # if we lose all our weapons, stop using the Engage tactic and switch to Shove
- if id in self.weapons: self.weapons.remove(id)
- if not self.weapons:
- tactic = [x for x in self.tactics if x.name == "Engage"]
- if len(tactic) > 0:
- self.tactics.remove(tactic[0])
- self.tactics.append(Tactics.Shove(self))
- self.tactics.append(Tactics.Charge(self))
- return AI.SuperAI.LostComponent(self, id)
- def DebugString(self, id, string):
- if self.debug:
- if id == 0: self.debug.get("line0").setText(string)
- elif id == 1: self.debug.get("line1").setText(string)
- elif id == 2: self.debug.get("line2").setText(string)
- elif id == 3: self.debug.get("line3").setText(string)
- AI.register(SpinupOmni2)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement