'RTanque' Part 4: Invincible
Making Any Bot a Brain Surgeon.
How to render your opponents brainless.
Brain surgery is not simple, at least not to me. The base brain surgery code for this bot came from a bot David Bock created called the lobotomizer. I am going to show you how you can make any bot a brain surgeon like the lobotomizer by:- Adding an accessor to the Bot class.
- Adding three lines of code to your tick! method.
- Adding two private methods at the end of your code.
class YourBot < RTanque::Bot::Brain
NAME = "Your Bot's Name"
include RTanque::Bot::BrainHelper
TURRET_FIRE_RANGE = RTanque::Heading::ONE_DEGREE * 1.5
def tick!
some_function_a
some_function_b
end
def some_function_a
#logic of function a
end
def some_function_b
#logic of function b
end
end
First we will drill open the skull, by adding the following code.# drill open their skulls
class RTanque::Bot
attr_accessor :brain
end
This little bit of code reopens the Bot Class and allows you access to
That by itself won't make you a brain surgeon but it will allow you to avoid doing brain surgery on your self.
We will next edit the tick! of your bot. def tick!
first_time do
lobotomize_opponents
end
some_function_a
some_function_b
end
So now that you added this code to your bot, we also need to add the functions first_time and lobotimize_opponents that your tick! method will now call at the end of your code.private
def first_time
unless @first_time_guard
yield
@first_time_guard = "checked"
end
end
def lobotomize_opponents
ObjectSpace.each_object(RTanque::Bot) { |x|
x.brain.class.send(:define_method, :tick!) {
"#This is where you write the new tick!
#method that you will use to replace your opponents
#If you leave this blank or only comments"
} unless x.brain.class == self.class
}
end
Let me explain tick! calls first_time every time it runs.
When first_time runs for the first time will not @first_time_guard be defined so by default @first_time_guard will be nil.The unless is basically an if not so when @first_time_guard is evaluated as nil, yield will execute which means lobotomize_opponents will be called, and @first_time_guard will be assigned "checked". When tick! runs again it will still call first_time, but @first_time_guard is not false or nil, so yield will not execute again.
How lobotomize_opponents works is a little more complicated, and I do not fully understand it completely, but basically for every Bot it will redefine tick! to whatever string is inside the inner curly brackets.
unless x.brain.class == self.classThe above code, just makes sure you are not redefining your own bots tick! One important note if you try to make clones of this tank, they're likely to lobotomize each other. Here is what the BasicTargetingBot looks like after I made him a brain surgeon.
class BrainSurgeonBasicTargetingBot < RTanque::Bot::Brain
NAME = "#{self}"
include RTanque::Bot::BrainHelper
TURRET_FIRE_RANGE = RTanque::Heading::ONE_DEGREE * 1.5
# drill open their skulls
class RTanque::Bot
attr_accessor :brain
end
def tick!
first_time do
lobotomize_opponents
end
## main logic goes here
# use self.sensors to detect things
# use self.command to control tank
# self.arena contains the dimensions of the arena
self.make_circles
if we_have_target
target = we_have_target
track_target(target)
aim_at_target(target)
fire_at_target(target)
else
self.scan_with_radar
end
end
def make_circles
command.speed = MAX_BOT_SPEED # takes a value between -5 to 5
command.heading = sensors.heading + MAX_BOT_ROTATION
end
def we_have_target
self.nearest_target
end
def nearest_target
self.sensors.radar.min { |a,b| a.distance <=> b.distance }
end
def track_target(target)
self.command.radar_heading = target.heading
end
def aim_at_target(target)
self.command.turret_heading = target.heading
end
def fire_at_target(target)
if self.pointing_at_target?(target)
command.fire(MAX_FIRE_POWER)
end
end
def pointing_at_target?(target)
(target.heading.delta(sensors.turret_heading)).abs < TURRET_FIRE_RANGE
end
def scan_with_radar
self.command.radar_heading = self.sensors.radar_heading + MAX_RADAR_ROTATION
end
private
def first_time
unless @first_time_guard
yield
@first_time_guard = "checked"
end
end
def lobotomize_opponents
ObjectSpace.each_object(RTanque::Bot) { |x|
x.brain.class.send(:define_method, :tick!) {
"#This is where you write the new tick!
#method that you will use to replace your opponents
#if you leave this blank you will make him brainless"
} unless x.brain.class == self.class
}
end
end
This is a guide to making 'RTanque' tank bot brain surgeons. This is Part 4 of a 4 part series on 'RTanque' tank bot making. Joshua Kemp @joshuakemp1 and myself Cody Kemp @codesterkemp have be joint authors during this series.
We do foresee writing of future RTanque articles including "How to Avoid Brain Surgery" and "Precision Targeting"
No comments:
Post a Comment