RRobots (#59)

Here’s my robot solution. I still have some problems that I couldn’t
quite figure out. I’m hoping that by looking through some of the other
solutions I’ll be able to figure them out. It does a pretty good job of
avoiding, but linear targeting wasn’t working, so I commented it out.
Ok, Thanks for the quiz, I keep learning!

-----Horndude77

require ‘robot’
require ‘matrix’

class Vector
def angle
Math.atan2(self.y, self.x)
end
def x
self[0]
end
def y
self[1]
end
end

class HornRobot
include Robot

def initialize
    @pos, @vel, @opp_pos, @opp_vel, @target_pos, @target_vel =

[Vector[0,0]]*6

    @last_saw = -1000
    @radar_turn = 60
    @dist = 100000

    #where to be on wheel around opponent
    @angle = 0
end

def tick(events)
    convert(events)

    #find opponent
    if @e['robot_scanned'].empty?
        @radar_turn *= -2 if (@radar_turn.abs < 60)
        @radar_turn *= -1 if (@radar_turn == 60)
        #@opp_pos += @opp_vel
    else
        @dist = events['robot_scanned'][0][0]
        opp_heading = (radar_heading + @radar_turn/2.0).to_rad
        new_opp_pos = Vector[Math.cos(opp_heading),

Math.sin(opp_heading)]*@dist + @pos
delta_time = time - @last_saw
if(delta_time < 30 && @radar_turn < 10) then
#I don’t know what I’m doing wrong here, but this
doesn’t
#seem to be a good estimate of their velocity. I know
averaging
#over time would be better, but This should at least be
a close
#start which it’s not right now.
@opp_vel = (new_opp_pos - @opp_pos) * (1.0/delta_time)
else
@opp_vel = Vector[rand,rand]
end
@opp_pos = new_opp_pos
@radar_turn *= -0.5 if @radar_turn.abs > 0.5
@last_saw = time
end

    #Choose target position. Right now this chooses a point on
    #the circle around the opponent. Not really effective, but it
    #avoids ok.
    @angle = (@angle + 5) % 360
    t_x = 1000*Math.cos(@angle.to_rad) + @opp_pos.x
    t_y = 1000*Math.sin(@angle.to_rad) + @opp_pos.y
    t_x = 0-t_x if t_x < 0
    t_y = 0-t_y if t_y < 0
    t_x = 2*battlefield_width-t_x if t_x > battlefield_width
    t_y = 2*battlefield_width-t_y if t_y > battlefield_width
    @target_pos = Vector[t_x, t_y]

    #move to target position
    @target_vel = (@target_pos - @pos) * 0.5
    target_heading = @target_vel.angle.to_deg % 360
    #Choose turning amount. The max we need to turn is 90
    #since the bot can go forward or reverse
    heading_prime = (heading+180) % 360
    @body_turn = [target_heading-heading,
    target_heading-(heading+360),
    (target_heading+360)-heading,
    target_heading-heading_prime,
    target_heading-(heading_prime+360),
    (target_heading+360)-heading_prime].min {|a,b| a.abs <=> b.abs

}
@body_turn = 10 if @body_turn > 10
@body_turn = -10 if @body_turn < -10
#This avoids somewhat the linear targeting
accelerate( 5Math.sin( 0.5/(2Math::PI) * time) )

    #move turret
    #Linear targeting. Unfortunately my estimate of the opponent's
    #velocity is way off so this just swings the gun wildly.
    speed_b = 30.0
    d = @opp_pos - @pos
    a = d.x**2 + d.y**2
    b = 2*@opp_vel.x*d.x + 2*@opp_vel.y*d.y
    c = @opp_vel.x**2 + @opp_vel.y**2 - speed_b**2
    disc = b**2 - 4*a*c
    t = 20
    if(disc>0) then
        t = (2*a)/(-b + Math.sqrt(disc))
    end
    v_b = @opp_vel + d * (1/t)
    #target_gun_heading = v_b.angle.to_deg % 360
    #Just point the gun at the opponent instead since linear

targeting isn’t working.
target_gun_heading = (@opp_pos - @pos).angle.to_deg % 360
@gun_turn = [target_gun_heading-gun_heading,
target_gun_heading-(gun_heading+360),
(target_gun_heading+360)-gun_heading].min {|a,b| a.abs <=>
b.abs }

    #adjust movements
    gun = @gun_turn - @body_turn
    gun = 30 if gun > 30
    gun = -30 if gun < -30
    radar = @radar_turn - gun - @body_turn
    radar = 60 if radar > 60
    radar = -60 if radar < -60

    turn(@body_turn)
    turn_gun(gun)
    turn_radar(radar)
    power = 0.5
    power += 1.25/3 * @radar_turn.abs if @radar_turn < 3
    power += 1.25/700 * @dist if @dist < 1000 && @dist > 300
    fire(power)
end

#Convert to vectors
def convert(events)
    @e = events
    @pos = Vector[x, battlefield_height-y]
    @vel = Vector[Math.cos(heading.to_rad),

Math.sin(heading.to_rad)] * speed
end
end