Class: Toybot::Bot

Inherits:
Object
  • Object
show all
Defined in:
lib/toybot/bot.rb

Constant Summary collapse

REPORT_FORMAT =

The format of the output of the ‘#report` method

"[^_^] *bip bop* -( My position is X:%d Y:%d facing %s! )"
ERROR_REPORTS =
[
  "[x_x] *tuuuuut* -( What do you mean? )",
  "[T_T] *tuuuuut* -( I can't help you, but Siri might... )",
  "[o_0] *tuuuuut* -( Bonjour, parlez vous francais? )",
]
USAGE =
<<-EOS

  Here's what you can do:
  -----------------------

  PLACE X, Y, F - Put the toy robot on the table in position X,Y
  and facing NORTH, SOUTH, EAST or WEST. If the robot is already
  placed, issuing another valid PLACE command will place the robot
  in the newly specified location

  example: PLACE 24, 42, SOUTH

  MOVE
  Moves the toy robot one unit forward in the direction it is currently
  facing.

  LEFT
  Rotates the robot 90 degrees to the left (i.e. counter-clockwise) without
  changing the position of the robot.

  RIGHT
  Rotates the robot 90 degrees to the right (i.e. clockwise) without changing
  the position of the robot.

  REPORT
  Announces the X,Y and F of the robot.

EOS
ACTIONS =

Whitelist of actions that the bot knows how to execute

[:place, :move, :left, :right, :report]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tabletop = Toybot::Tabletop.new) ⇒ Bot

Initialize a new ‘Bot` on a given `Tabletop` The bot has a default position of `0, y: 0, facing: :north`



49
50
51
52
# File 'lib/toybot/bot.rb', line 49

def initialize tabletop = Toybot::Tabletop.new
  @tabletop = tabletop
  @x, @y, @facing = 0, 0, Toybot::Direction.new(:north)
end

Class Method Details

.start(tabletop) ⇒ Object

The bot entry point. It takes a ‘Toybot::Tabletop` as the first argument.



43
44
45
# File 'lib/toybot/bot.rb', line 43

def self.start tabletop
  self.new(tabletop).run
end

Instance Method Details

#execute(action, args) ⇒ Object

It takes the action and the arguments as first and second arguments.

  1. Validate that the action is whitelisted

  2. Fire the corresponding method, with the arguments if needed.



75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/toybot/bot.rb', line 75

def execute action, args
  if ACTIONS.include? action
    if args.any?
      self.send action, *args
    else
      self.send action
    end
  else
    self.report_error
  end
rescue ArgumentError
  self.report_error
end

#leftObject



108
109
110
111
# File 'lib/toybot/bot.rb', line 108

def left
  @facing.rotate_counter_clockwise!
  self.position
end

#moveObject



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/toybot/bot.rb', line 113

def move
  case @facing.value
  when :north
    self.move_up
  when :east
    self.move_right
  when :south
    self.move_down
  when :west
    self.move_left
  end
  self.position
end

#move_downObject

Bot movement rules



136
137
138
# File 'lib/toybot/bot.rb', line 136

def move_down
  @y -= @y > 0 ? 1 : 0
end

#move_leftObject



144
145
146
# File 'lib/toybot/bot.rb', line 144

def move_left
  @x -= @x > 0 ? 1 : 0
end

#move_rightObject



148
149
150
# File 'lib/toybot/bot.rb', line 148

def move_right
  @x += @x < @tabletop.width ? 1 : 0
end

#move_upObject



140
141
142
# File 'lib/toybot/bot.rb', line 140

def move_up
  @y += @y < @tabletop.height ? 1 : 0
end

#parse_input(input) ⇒ Object

Returns the action and an array of arguments. It does not perform any validation on the input.



65
66
67
68
69
70
# File 'lib/toybot/bot.rb', line 65

def parse_input input
  input = input.chomp
  arr = input.split
  action = arr.shift || :no_action
  return action.downcase.to_sym, arr.join.split(',')
end

#place(x, y, facing) ⇒ Object

Bot actions

All bot actions return the bot position to facilitate testing.



96
97
98
99
100
101
# File 'lib/toybot/bot.rb', line 96

def place x, y, facing
  @x = x.to_i
  @y = y.to_i
  @facing.value = facing.downcase.to_sym
  self.position
end

#positionObject

Bot reporting



157
158
159
# File 'lib/toybot/bot.rb', line 157

def position
  {x: @x, y: @y, facing: @facing.value}
end

#reportObject



127
128
129
130
# File 'lib/toybot/bot.rb', line 127

def report
  puts self.to_s
  self.position
end

#report_errorObject



165
166
167
168
169
170
171
172
# File 'lib/toybot/bot.rb', line 165

def report_error
  puts
  puts "ERROR REPORT ======================================================================"
  puts ERROR_REPORTS.sample
  puts USAGE
  puts "==================================================================================="
  puts
end

#rightObject



103
104
105
106
# File 'lib/toybot/bot.rb', line 103

def right
  @facing.rotate_clockwise!
  self.position
end

#runObject

Run loop of the bot Wait for input from STDIN, parse, execute, repeat until EOF



56
57
58
59
60
61
# File 'lib/toybot/bot.rb', line 56

def run
  while (input = $stdin.gets) do
    action, args = self.parse_input(input)
    self.execute action, args unless action == :no_action
  end
end

#to_sObject



161
162
163
# File 'lib/toybot/bot.rb', line 161

def to_s
  REPORT_FORMAT % [@x, @y, @facing.to_s]
end