Skip to content

Commit 5a3cda8

Browse files
authored
Merge pull request #986 from AInnuganti/distance
Add square_manhattan_distance and square_knight_distance functions
2 parents 2f7ada0 + a2f1588 commit 5a3cda8

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

chess/__init__.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,34 @@ def square_rank(square: Square) -> int:
218218

219219
def square_distance(a: Square, b: Square) -> int:
220220
"""
221-
Gets the distance (i.e., the number of king steps) from square *a* to *b*.
221+
Gets the Chebyshev distance (i.e., the number of king steps) from square *a* to *b*.
222222
"""
223223
return max(abs(square_file(a) - square_file(b)), abs(square_rank(a) - square_rank(b)))
224224

225+
def square_manhattan_distance(a: Square, b: Square) -> int:
226+
"""
227+
Gets the Manhattan/Taxicab distance (i.e., the number of orthogonal king steps) from square *a* to *b*.
228+
"""
229+
return abs(square_file(a) - square_file(b)) + abs(square_rank(a) - square_rank(b))
230+
231+
def square_knight_distance(a: Square, b: Square) -> int:
232+
"""
233+
Gets the Knight distance (i.e., the number of knight moves) from square *a* to *b*.
234+
"""
235+
dx = abs(square_file(a) - square_file(b))
236+
dy = abs(square_rank(a) - square_rank(b))
237+
238+
if dx + dy == 1:
239+
return 3
240+
elif dx == dy == 2:
241+
return 4
242+
elif dx == dy == 1:
243+
if BB_SQUARES[a] & BB_CORNERS or BB_SQUARES[b] & BB_CORNERS: # Special case only for corner squares
244+
return 4
245+
246+
m = math.ceil(max(dx / 2, dy / 2, (dx + dy) / 3))
247+
return m + ((m + dx + dy) % 2)
248+
225249
def square_mirror(square: Square) -> Square:
226250
"""Mirrors the square vertically."""
227251
return square ^ 0x38

test.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,31 @@ def test_parse_square(self):
9393
with self.assertRaises(ValueError):
9494
self.assertEqual(chess.parse_square("a0"))
9595

96+
def test_square_distance(self):
97+
self.assertEqual(chess.square_distance(chess.A1, chess.A1), 0)
98+
self.assertEqual(chess.square_distance(chess.A1, chess.H8), 7)
99+
self.assertEqual(chess.square_distance(chess.E1, chess.E8), 7)
100+
self.assertEqual(chess.square_distance(chess.A4, chess.H4), 7)
101+
self.assertEqual(chess.square_distance(chess.D4, chess.E5), 1)
102+
103+
def test_square_manhattan_distance(self):
104+
self.assertEqual(chess.square_manhattan_distance(chess.A1, chess.A1), 0)
105+
self.assertEqual(chess.square_manhattan_distance(chess.A1, chess.H8), 14)
106+
self.assertEqual(chess.square_manhattan_distance(chess.E1, chess.E8), 7)
107+
self.assertEqual(chess.square_manhattan_distance(chess.A4, chess.H4), 7)
108+
self.assertEqual(chess.square_manhattan_distance(chess.D4, chess.E5), 2)
109+
110+
def test_square_knight_distance(self):
111+
self.assertEqual(chess.square_knight_distance(chess.A1, chess.A1), 0)
112+
self.assertEqual(chess.square_knight_distance(chess.A1, chess.H8), 6)
113+
self.assertEqual(chess.square_knight_distance(chess.G1, chess.F3), 1)
114+
self.assertEqual(chess.square_knight_distance(chess.E1, chess.E8), 5)
115+
self.assertEqual(chess.square_knight_distance(chess.A4, chess.H4), 5)
116+
self.assertEqual(chess.square_knight_distance(chess.A1, chess.B1), 3)
117+
self.assertEqual(chess.square_knight_distance(chess.A1, chess.C3), 4)
118+
self.assertEqual(chess.square_knight_distance(chess.A1, chess.B2), 4)
119+
self.assertEqual(chess.square_knight_distance(chess.C1, chess.B2), 2)
120+
96121

97122
class MoveTestCase(unittest.TestCase):
98123

0 commit comments

Comments
 (0)