Forum: Ruby Thinking in OO

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
4db4d1d1782fe68a945963682b43dd3d?d=identicon&s=25 Greg Coit (Guest)
on 2006-04-22 22:41
(Received via mailing list)
Hi all,

Trying hard to get my brain wrapped around the concepts of OO (using
Ruby which i'm also new to but doesn't seem as foreign to me).  I'm
using rrobots (at rubyforge) to practice...

This is what's provided to me:

#state:
#       team
#       battlefield_height
#       battlefield_width
#       energy
#       gun_heading
#       gun_heat
#       heading
#       size
#       radar_heading
#       time
#       game_over
#       speed
#       x
#       y
#actions:
#       accelerate
#       stop
#       fire
#       turn
#       turn_gun
#       turn_radar
#       broadcast
#       say
#events:
#       broadcast
#       got_hit
#       robot_scanned

Now I've started to write a bot serveral times, but I'm thinking I need
to back up a bit and figure out who to approach this from an OO
standpoint.

Ruby reinforces the idea of passing messages to objects (right?).  My
instinct
is to write methods named turn.left, turn.right, sleep.up, speed.down,
gun.fire, radar.sweep, etc....

But maybe that's not abstract enough.  Maybe methods like evade,
attack, attacked are more inline with OO thinking?

Is there *one* best way to think about this problem?  Or am I
over-analyzing?

Thanks!

Greg
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-04-22 22:54
(Received via mailing list)
Hi --

On Sun, 23 Apr 2006, Greg Coit wrote:

> #       battlefield_height
> #       x
> #events:
> gun.fire, radar.sweep, etc....
The question you should ask is: is there an entity called a "turn" in
the universe of your application -- the domain -- which can perform an
action, or which has a property, called "left"?  I would say the
answer is no.  A turn might have a "direction" property, and that
might be "left".  But turn.left suggests that you're telling a turn to
left, or to show you its left, neither of which really fits.

(It's true that you'll see libraries that do things like:
turn.five.degrees.to.the.left, but I consider that serious dot-abuse
and would stay away from it.)

So, you're likely to see things like:

   robot.turn :direction => "left", :degrees => 5

where direction and degrees are actually hash keys that can be parsed
out in the turn method and used to modify state (x and y, I would
assume).

Anyway, for me, the main thing is that every message that goes to an
object should make sense either as a command to the object, or as a
request for information from the object.


David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" PDF now on sale!  http://www.manning.com/black
Paper version coming in early May!
4db4d1d1782fe68a945963682b43dd3d?d=identicon&s=25 Greg Coit (Guest)
on 2006-04-23 01:58
(Received via mailing list)
In my latest attempt at writing a bot, my objects are radar, gun and
tank.

methods are things like increase (scan), decrease (scan), reverse,
adjust, etc.

There's also a bit of procedural code in the main (tick) method to
know what object to call with what method.  Is that acceptable in OO?

Code follows - not the smartest bot in the world (he doesn;t even move
yet - trying to get the radar to lock-on consitently), but i'm hoping
it's a good start that I can add to.

Any/all suggestion and criticism are very welcome!

Greg

require 'robot'

#in this script, heading is absolute (0-360), dir (direction) is
relative (+- and probably no more than 60)

#available options:
#
#state:
#	team
#	battlefield_height
#	battlefield_width
#	energy
#	gun_heading
#	gun_heat
#	heading
#	size
#	radar_heading
#	time
#	game_over
#	speed
#	x
#	y
#actions:
#	accelerate
#	stop
#	fire
#	turn
#	turn_gun
#	turn_radar
#	broadcast
#	say
#events:
#	broadcast
#       got_hit
#	robot_scanned

####### Need Unit Tests!!!!!!!!

class GoofeyDuck
   include Robot

  def initialize
    @got_hit = 0
    @found
    @seen #found previous round...

    @radar = Radar.new
    @gun = Gun.new
    @tank = Tank.new


  end

  def tick(events)

    @got_hit = events['got_hit']
    @found =  events['robot_scanned'] if
(!events['robot_scanned'].empty?)

    #set radar
    if (@found)
      @radar.decrease(1) unless (@radar.dir.abs <= 1)
      @radar.reverse
      @seen = 1
      say "Locked"
    elsif (@seen)
      @radar.increase(3)
      @radar.reverse
      @seen = !@seen
      say "Dang, Lost em"
    else
      @radar.increase(2)
      say "Tracking...."
    end
    @radar.dir = verify(@radar.dir, @radar.max)

    #set gun
    @gun.adjust(@radar.mid(radar_heading), gun_heading)
    @gun.dir = verify(@gun.dir, @gun.max)

    #fire or no?
    if (@found)
      @gun.fire += 0.1
    else
      @gun.fire -= 0.1 unless (@gun.fire <= 0)
    end

    @gun.fire = verify(@gun.fire, 3)

    #pass results
    turn_radar(verify(@radar.adjust(@gun.dir), @radar.max)) #adjust
radar to gun
    turn_gun(@gun.dir)
    turn(@tank.dir)
    accelerate(@tank.vel)
    fire(@gun.fire)
    say "Uh oh" if (energy <= 10)

    puts @gun.fire

    #reset
    @found = !@found if (@found)

  end

  def verify(dir, max)
    if (dir > max)
      dir = max
    elsif (dir.abs > max)
      dir = (max * -1)
    end
  dir
  end

end

class Radar
  include Robot

  attr_reader :dir, :max
  attr_writer :dir

  def initialize
    @dir = 60
    @max = 60 #max delta
  end

  def increase(amt)
    z = @dir <=> 0
    @dir += (amt * z)
  end

  def decrease(amt)
    z = @dir <=> 0
    @dir -= (amt * z)
  end

  def reverse
    @dir *= -1
  end

  def adjust(gun)
    @dir - gun
  end

  def mid(head) #in degrees....
    head + (@dir/2)
  end

end

class Gun
  include Robot

  attr_reader :dir, :fire, :max
  attr_writer :dir, :fire

  def initialize
    @dir = 0
    @max = 30 #max delta
    @fire = 0.1
  end

  def adjust(target, gun_head)
    @dir = target - gun_head
  end

end

class Tank
  include Robot

  attr_reader :dir, :vel
  attr_writer :dir, :vel

  def initialize
    @dir = 0
    @max = 10 #max delta
    @vel = 0
  end

end
This topic is locked and can not be replied to.