'RTanque' Part 4: Invincible

'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.
 So your bot will look something like this before we make your bot a brain surgeon.  
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.class

The 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" 

Crank Out RTanque Tutorials

This week has been good overall, I logged 22.5 hours of study time this week. Josh and I have published two tutorials together this week and written a third, that Josh will publish shortly on his blog. We will finish writing and I will publish the fourth tutorial this week on my blog. I had originally thought the final tutorial would cover an advanced targeting topic, dealing with smart targeting and avoiding shooting your allies. But instead we decided to cover a tutorial about using meta programming to disable your enemies. Unfortunatly while I really did crank out tutorials I slacked off and didn't complete the rest of my Weekly Agenda goals. This is being posted on Monday so I am a little late on publication, but still pretty close. My new Weekly Agenda Goals are: Watch all unwatched lecture videos. Complete hw 2 for class. Complete the the last quiz for the class. Finish writing the part 4 of the tutorial series.

Beginner's guide to 'RTanque' Part:2

The Attack of the Clones


This guide covers how to make a tank bot army in a single file with 'RTanque'

Now that you all have seen how to build a basic tank, We are going to see how to create a bunch of clones in the same file first we start with a single BasicBot
 
class BasicBot < RTanque::Bot::Brain
  NAME = 'basic_bot'
  include RTanque::Bot::BrainHelper
  def tick!
    ## 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
    self.command.fire(0.25)
  end
  def make_circles
  command.speed = MAX_BOT_SPEED # takes a value between -5 to 5 
  command.heading = sensors.heading + 0.01
  end
end  
first we copy and paste the whole BasicBot and paste it below the original and run it. Unfortunatley there is still only one bot. The problem is the class's both have the same name. So we change the second class name to Clone1 Now when we run it there will be two tanks. This is marvolous, but lets see if we can DRY up this code a little. Lets cut out all the logic for Clone1 so we have
class Clone1 < RTanque::Bot::Brain
end
When we run it again we still have two tanks but one is just sitting there still as death. The problem is Clone1's Brain doesn't have any logic. We solve that problem by letting Clone1 inherit BasicBot's Brain with
class Clone1 < BasicBot
end
Now here is my code for a basic_bot_swarm
class BasicBot < RTanque::Bot::Brain
  NAME = "#{self}"
  include RTanque::Bot::BrainHelper

def tick!
    ## 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
    self.command.fire(MIN_FIRE_POWER)
end

def make_circles
  command.speed = MAX_BOT_SPEED # takes a value between -5 to 5 
  command.heading = sensors.heading + MAX_BOT_ROTATION
end
end

class Clone1 < BasicBot
 NAME = "#{self}"
end

class Clone2 < BasicBot
 NAME = "#{self}"
end

class Clone3 < BasicBot
 NAME = "#{self}"
end

class Clone4 < BasicBot
 NAME = "#{self}"
end

class Clone5 < BasicBot 
 NAME = "#{self}"
end

class Clone6 < BasicBot
 NAME = "#{self}"
end

This is an extremely basic, easy guide to making 'RTanque' tank bot clones. If you are looking to make your tank smarter, you'll want to see part 3,  when we will deal with the subject of targeting.

This is Part 2 of a 4 part series on 'RTanque' tank bot making. Joshua Kemp @joshuakemp1 and myself  Cody Kemp @codesterkemp will be joint authors during this series.

RTanque and the Tank Wars

RTanque is a ruby based Tank duel/war simulator, that I was shown this past week. Creating my own AI for a tank was very addicting. So I have forked and cloned the Repo, to get a closer look on how to modify these tanks. So this week Josh and I will start posting a multi-part tutorial that will take you from a simple dumb tank to a relatively smart tank that can selectively target its prey and avoid targeting allies. Check out this video and screenshot of the game from Rtanque.

This past week has been great, I finished homework 1 part 2 in three hours, However I am still having trouble with homework 1 part 1, which I have completed, except for the ability to successfully transfer the comments from the one to the other without losing them. I am troubled by the autograder, not agreeing with my manual tests, but maybe I'll be able to sort it out easier when I have completely finished the assignment. I watched most of the two previous weeks of video lectures. I pushed up some more of chapter 3 from Michael Hartl's Rails Tutorial. I also spent a great deal of time trying to create the 'super' tank in rtanque. Study hours this week was at 26.5 hours, bringing my grand total to 263.25 hours. Pair programed and went to a programming Meetup.

The two Agenda goals that really did not happen, were watching last weeks video lectures and make significant progress in the Uno game. I have set the Uno game on the back burner while I crank out these RTanque Tutorials. I might even try to throw in a short screencast.

My Agenda Goals for this week.

    Complete Homework 1 part 1.
    Catch up on watching the lecture videos.
    Finish pushing up chapter 3 of Michael Hartl Rails Tutorial app.
    Crank out these RTanque Tutorials.

So here again are my Weekly Basic Goals.

    Pair program at least once a week.
    Study a minimum of 21 hours a week.
    Publish my weekly blog by the end of Sunday.
    Share it on Twitter



Legacy Code and Other Nightmares

Legacy Code - A large chunk of code some other programmer(s) wrote, that you now have to deal with.  My homework this week and the lectures from last week, deal with the subject of legacy code and while I hate trying to read another programmers mind, just by looking at code, especially when that code is several thousand lines of code.  I am grateful that I am presented with this type of challenge, While at this stage of my Learning Journey.

My Other Nightmare - Cucumber, the homework is supposed to be accomplished with Test Driven Devolpment, using Cucumber. Which I tried to do but it was very slow going and the amount of good Cucumber tutorials is underwhelming. I spent a great deal of time figuring out how to write tests using Cucumber.  Maybe I will love Cucumber once I learn how to use it... ...If I ever learn it.

This week was difficult overall,
I did not complete the homework, I feel like I have made a great deal of progress, but I have not finished it yet.
I pair programmed once this week.
I watched the lectures videos.
I created a Github Repo but only pushed up part of chapter 3 of Michael Hartl Rails Tutorial
I did add Josh as a Collaborator on Github, which I hope will allow Josh the access he needs.
I created a simple logo design  and applied it to my blog, a bit short of the goal but a step in the right direction.
I did not touch the second half of the Railscast #155 Cucumber Tutorial Substitutions.

With my basic goals, I fell short,
While I did pair program once this week, I only logged a total of 17 hours this week, for a total of 237.25 hours.  Ouch, four hours short.
It is very early Monday when I write this Blog so I am only slightly tardy on the blog and the Twitter share.

My Agenda Goals for this week.
  • Complete Last week's Homework for class.
  • Complete This week's Homework for class.
  • Watch the two previous weeks of lecture videos.
  • Watch this week's lecture videos.
  • Finish pushing up chapter 3 of Michael Hartl Rails Tutorial app.
  • Make some significant progress on my Uno Game.
So here again are my Weekly Basic Goals.
  • Pair program at least once a week.
  • Study a minimum of 21 hours a week.
  • Publish my weekly blog by the end of Sunday.
  • Share it on Twitter

200 Hour Plus Mark.

So I looked at my last blog and noticed I didn't put down my last week's study hours (18.25) for a Journey total of 201.75 study hours at the end of last week!

There is something I will mention, before I go further , First I wasn't too happy with names for my goals last week, so I have renamed "One Time Goals" to be "Weekly Agenda Goals". I have also renamed "Recurring goals" to be "Weekly Basic Goals".

This week was fairly good overall, I met all of my Basic Goals.
I pair programmed with Josh this week, and I think we will go through Michael Hartl's Rail tutorial together and push it up to Git Hub as we go. I just barely exceeded my minimum study with 19 hours of study time, for a total of 220.75 hrs for my Learning Journey.
I started writing this blog on Sunday night...  ...so close enough, and I plan to share it on Twitter right after I am finished here.
However I didn't meet two of my Agenda Goals this week.  I didn't finish the screencast tutorial, but I did work on it, and I realized I need to sharpen my Ruby skills. the second is I didn't publish the screencast I didn't finish.  However on the bright side I did finish the video lectures.

After some reviewing this week I decided to change one of my Basic Goals.  I am going to increase my minimum study time goal to 21 hours. and I probably overloaded my Agenda Goals for this week, but it will mostly depend on how long it take to do the Homework.

 So here are my Agenda Goals this week in order of importance.

  • Complete Homework for class.
  • Watch lecture videos this week.
  • Create a Github Repo and push up to chapter 3 of Michael Hartl Rails Tutorial app.
  • Add Josh as admin on that repo.
  • Create a screen cast intro. It probably will be about 5 - 10 sec, and publish it on youtube or some other video hosting service.
  • Finish the second half of the Railscast #155 Cucumber Tutorial Substitutions.
So here are my updated Weekly Basic Goals.
  • Pair program at least once a week.
  • Study a minimum of 21 hours a week.
  • Publish my weekly blog by the end of Sunday. I am late this week.
  • Share it on Twitter.