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
on 2006-04-23 00:41
on 2006-04-23 00:54
Hi -- On Sun, 23 Apr 2006, Greg C. 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 (email@example.com) 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!
on 2006-04-23 03:58
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