Skip to content

Commit

Permalink
feat: block horizontal movement with other pieces
Browse files Browse the repository at this point in the history
  • Loading branch information
Roland Studer committed Dec 22, 2021
1 parent b56999d commit 32a1348
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 10 deletions.
19 changes: 15 additions & 4 deletions lib/move/horizontal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@
module Move
# unlimited horizontal movement for a piece
class Horizontal
def unhindered_legal_end_positions(position)
position = Position.parse(position) if position.is_a? String
letters = ("A".."H").to_a - [position.letter]
letters.map { |l| Position.new(l, position.number) }
def legal_moves(board, position)
position = Position.parse(position)

legals = []
position.positions_to_the_left.each do |to_the_left|
legals << to_the_left
break if board.get(to_the_left).piece
end

position.positions_to_the_right.each do |to_the_right|
legals << to_the_right
break if board.get(to_the_right).piece
end

legals
end
end
end
31 changes: 28 additions & 3 deletions lib/position.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
class Position
attr :letter, :number

def self.parse(string)
letter = string.strip.chars[0].upcase
number = string.strip.chars[1].to_i
def self.parse(input)
return input.map { |pos| Position.parse(pos)} if input.is_a? Array
return input if input.is_a? Position

letter = input.strip.chars[0].upcase
number = input.strip.chars[1].to_i

return nil unless ("A".."H").include? letter
return nil unless (1..8).include? number
Expand All @@ -19,7 +22,29 @@ def initialize(letter, number)
@number = number.to_i
end

# all positions to the left, sorted by closest
def positions_to_the_left
index = ("A".."H").find_index(letter)
("A".."H").first(index).map { |l| Position.new(l, number)}.reverse
end

# all positions to the left, sorted by closest
def positions_to_the_right
index = ("A".."H").find_index(letter)
("A".."H").last(7 - index).map { |l| Position.new(l, number)}
end

def ==(other)
letter == other.letter && number == other.number
end

def ===(other)
letter == other.letter && number == other.number
end

# manhatten distance to other position
def distance_to(other)
other = Position.parse(other)
(number - other.number).abs + (letter.ord - other.letter.ord).abs
end
end
14 changes: 11 additions & 3 deletions test/move/horizontal_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,19 @@

module Move
class HorizontalTest < Minitest::Test
def test_returns_unhindered_positions
def test_legal_move_blocked_by_other_piece
board = Board.new

move = Move::Horizontal.new
assert_includes move.legal_moves(board, "C1"), Position.parse("A1")

board.place(Piece.new, "B1")
assert !move.legal_moves(board, "C1").include?(Position.parse("A1"))

assert_includes move.legal_moves(board, "C1"), Position.parse("H1")

legal_end_positions = %w[A3 B3 C3 E3 F3 G3 H3].map { |p| Position.parse(p) } # without D4
assert_equal legal_end_positions, move.unhindered_legal_end_positions("D3")
board.place(Piece.new, "F1")
assert !move.legal_moves(board, "C1").include?(Position.parse("H1"))
end
end
end
13 changes: 13 additions & 0 deletions test/position_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,17 @@ def test_positions_are_comparable
assert_equal Position.parse("G5"), Position.parse("G5")
assert_equal [Position.parse("G5")], [Position.parse("G5")]
end

def test_distance_to_other_position
assert_equal 2, Position.parse("B2").distance_to("A1")
assert_equal 12, Position.parse("B2").distance_to("H8")
end

def test_positions_to_the_left
assert_equal Position.parse(["B4", "A4"]), Position.parse("C4").positions_to_the_left
end

def test_positions_to_the_right
assert_equal Position.parse(["G4", "H4"]), Position.parse("F4").positions_to_the_right
end
end

0 comments on commit 32a1348

Please sign in to comment.