# RRobots (#59)

**URL:** <https://www.ruby-forum.com/t/rrobots-59/77406>\
**Category:** Ruby\
**Created:** [December 27, 2005, 5:44pm UTC](https://www.ruby-forum.com/t/rrobots-59/77406 "2005-12-27T17:44:57Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![horndude77](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/e480ec/32.png) [@horndude77](https://www.ruby-forum.com/u/horndude77)\
**Post date:** [December 27, 2005, 5:44pm UTC](https://www.ruby-forum.com/t/rrobots-59/77406/1 "2005-12-27T17:44:57Z")

</div>

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( 5_Math.sin( 0.5/(2_Math::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
