137 lines
4.6 KiB
Python
137 lines
4.6 KiB
Python
from enum import Enum
|
|
from collections import deque
|
|
|
|
|
|
def get_neighbors(p, q):
|
|
directions = [(0, -1), (1, -1), (1, 0), (0, 1), (-1, 1), (-1, 0)]
|
|
return [(p + dp, q + dq) for dp, dq in directions]
|
|
|
|
|
|
class Piece:
|
|
def get_valid_jumps() -> list:
|
|
raise NotImplementedError
|
|
|
|
|
|
class Bee(Piece):
|
|
def __init__(self, board, p, q, team):
|
|
self.board = board
|
|
self.p = p
|
|
self.q = q
|
|
self.team = team # 'team' should be 'upper' or 'lower' based on the piece case.
|
|
|
|
def get_valid_jumps(self) -> list:
|
|
# The bee can move to an adjacent empty space.
|
|
valid_moves = []
|
|
for neighbor in get_neighbors(self.p, self.q):
|
|
# Check if the neighbor is within the bounds of the board and is empty
|
|
if neighbor in self.board and self.board[neighbor] == "":
|
|
valid_moves.append(neighbor)
|
|
return valid_moves
|
|
|
|
|
|
class Beetle(Piece):
|
|
def __init__(self, p, q, team):
|
|
self.p = p
|
|
self.q = q
|
|
self.team = team
|
|
|
|
def get_valid_jumps(self, board):
|
|
# The beetle can move to an adjacent space whether it is empty or not.
|
|
valid_moves = get_neighbors(self.p, self.q)
|
|
return valid_moves
|
|
|
|
|
|
class Spider(Piece):
|
|
def __init__(self, p, q, team):
|
|
self.p = p
|
|
self.q = q
|
|
self.team = team
|
|
|
|
def get_valid_jumps(self, board):
|
|
# Use BFS to find all tiles exactly three moves away
|
|
start = (self.p, self.q)
|
|
visited = set() # Keep track of visited tiles
|
|
queue = deque([(start, 0)]) # Queue of (position, distance)
|
|
valid_moves = []
|
|
|
|
while queue:
|
|
current_position, current_distance = queue.popleft()
|
|
if current_distance == 3:
|
|
# We have found a tile exactly three moves away
|
|
valid_moves.append(current_position)
|
|
continue # We don't want to move further from this tile
|
|
|
|
if current_position in visited:
|
|
continue # Already visited this tile
|
|
|
|
visited.add(current_position)
|
|
|
|
# Get all neighboring positions
|
|
for neighbor in get_neighbors(*current_position):
|
|
if (
|
|
neighbor in board
|
|
and board[neighbor] == ""
|
|
and neighbor not in visited
|
|
):
|
|
queue.append((neighbor, current_distance + 1))
|
|
|
|
return valid_moves
|
|
|
|
|
|
class Grasshopper(Piece):
|
|
def __init__(self, p, q, team):
|
|
self.p = p
|
|
self.q = q
|
|
self.team = team
|
|
|
|
def get_valid_jumps(self, board):
|
|
# Generator function to yield valid moves
|
|
def generate_moves():
|
|
# Check each direction for possible jumps
|
|
for dp, dq in get_neighbors(0, 0): # Use (0, 0) to get direction vectors
|
|
pos = (self.p + dp, self.q + dq)
|
|
# Continue in the direction until we find a piece to jump over
|
|
while pos in board and board[pos] != "":
|
|
pos = (pos[0] + dp, pos[1] + dq)
|
|
# If we jumped over at least one piece and landed on an empty space, yield the move
|
|
if (
|
|
pos in board
|
|
and board[pos] == ""
|
|
and (pos[0] != self.p or pos[1] != self.q)
|
|
):
|
|
yield pos
|
|
|
|
return list(generate_moves())
|
|
|
|
|
|
class Ant(Piece):
|
|
def __init__(self, p, q, team):
|
|
self.p = p
|
|
self.q = q
|
|
self.team = team
|
|
|
|
def get_valid_jumps(self, board):
|
|
visited = set() # Keep track of visited nodes to prevent cycles
|
|
|
|
# Recursive function to explore all valid moves
|
|
def explore(p, q):
|
|
for dp, dq in get_neighbors(0, 0): # Get direction vectors
|
|
new_p, new_q = p + dp, q + dq
|
|
next_pos = (new_p, new_q)
|
|
# Continue in this direction while there are pieces to slide around
|
|
while (
|
|
next_pos in board
|
|
and board[next_pos] != ""
|
|
and next_pos not in visited
|
|
):
|
|
visited.add(next_pos)
|
|
next_pos = (next_pos[0] + dp, next_pos[1] + dq)
|
|
# If we found an empty space, add it as a valid move and explore from there
|
|
if next_pos in board and board[next_pos] == "":
|
|
visited.add(next_pos)
|
|
yield next_pos
|
|
# Explore further moves from this new position
|
|
yield from explore(next_pos[0], next_pos[1])
|
|
|
|
# Start exploring from the Ant's current position
|
|
return list(explore(self.p, self.q))
|