forked from ryanb/ruby-warrior
/
position.rb
86 lines (72 loc) · 2.01 KB
/
position.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
module RubyWarrior
class Position
attr_reader :floor
DIRECTIONS = [:north, :east, :south, :west]
RELATIVE_DIRECTIONS = [:forward, :right, :backward, :left]
def initialize(floor, x, y, direction = nil)
@floor = floor
@x = x
@y = y
@direction_index = DIRECTIONS.index(direction || :north)
end
def at?(x, y)
@x == x && @y == y
end
def direction
DIRECTIONS[@direction_index]
end
def rotate(amount)
@direction_index += amount
@direction_index -= 4 while @direction_index > 3
@direction_index += 4 while @direction_index < 0
end
def relative_space(forward, right = 0)
@floor.space(*translate_offset(forward, right))
end
def space
@floor.space(0, 0)
end
def move(forward, right = 0)
@x, @y = *translate_offset(forward, right)
end
def distance_from_stairs
stairs_x, stairs_y = *@floor.stairs_location
(@x - stairs_x).abs + (@y - stairs_y).abs
end
def relative_direction_of_stairs
relative_direction_of(@floor.stairs_space)
end
def relative_direction_of(space)
relative_direction(direction_of(space))
end
def direction_of(space)
stairs_x, stairs_y = *space.location
if (@x - stairs_x).abs > (@y - stairs_y).abs
if stairs_x > @x
:west
else
:east
end
elsif stairs_y > @y
:south
else
:north
end
end
def relative_direction(direction)
offset = DIRECTIONS.index(direction) - @direction_index
offset -= 4 while offset > 3
offset += 4 while offset < 0
RELATIVE_DIRECTIONS[offset]
end
private
def translate_offset(forward, right)
case direction
when :north then [@x + right, @y - forward]
when :east then [@x + forward, @y + right]
when :south then [@x - right, @y + forward]
when :west then [@x - forward, @y - right]
end
end
end
end