Commit before some experiments with smart argument changing
This commit is contained in:
+187
@@ -0,0 +1,187 @@
|
||||
# POSSIBLE USAGE KEYS
|
||||
# map, keymaker_position = Utils.generate_random_map()
|
||||
# proceed with map actions...
|
||||
|
||||
|
||||
import random
|
||||
from typing import (
|
||||
List,
|
||||
Tuple,
|
||||
Optional,
|
||||
Set,
|
||||
)
|
||||
|
||||
|
||||
class Utils:
|
||||
@staticmethod
|
||||
def generate_random_map() -> Tuple[List[List[str]], Optional[Tuple[int, int]]]:
|
||||
"""
|
||||
Generates a random 9x9 game map with placements of 'A', 'S', and 'P'.
|
||||
'P' placements depend on the positions of 'A' and 'S'.
|
||||
|
||||
Returns:
|
||||
A tuple containing the game map and one unoccupied square (or None if all occupied).
|
||||
"""
|
||||
# Initialize a 9x9 grid with empty strings
|
||||
game_map: List[List[str]] = [[[] for _ in range(9)] for _ in range(9)]
|
||||
all_coordinates: List[Tuple[int, int]] = [(x, y) for x in range(9) for y in range(9)]
|
||||
|
||||
def place_letter(
|
||||
letter: str,
|
||||
count: int,
|
||||
available: List[Tuple[int, int]],
|
||||
) -> List[Tuple[int, int]]:
|
||||
"""
|
||||
Places a specified letter on the game map a certain number of times.
|
||||
|
||||
Args:
|
||||
letter: The letter to place ('A' or 'S').
|
||||
count: Number of times to place the letter.
|
||||
available: List of available coordinates.
|
||||
|
||||
Returns:
|
||||
A list of coordinates where the letter was placed.
|
||||
"""
|
||||
placed: List[Tuple[int, int]] = []
|
||||
for _ in range(count):
|
||||
if not available:
|
||||
break
|
||||
x, y = random.choice(available)
|
||||
game_map[x][y] = [letter]
|
||||
placed.append((x, y))
|
||||
available.remove((x, y))
|
||||
|
||||
return placed
|
||||
|
||||
# Place "A" 0 to 3 times
|
||||
num_A: int = random.randint(0, 3)
|
||||
A_positions: List[Tuple[int, int]] = place_letter("A", num_A, all_coordinates)
|
||||
|
||||
# Place "S" 0 to 1 times
|
||||
num_S: int = random.randint(0, 1)
|
||||
S_positions: List[Tuple[int, int]] = place_letter("S", num_S, all_coordinates)
|
||||
|
||||
def get_moore_neighbors(x: int, y: int) -> List[Tuple[int, int]]:
|
||||
"""
|
||||
Retrieves all Moore neighbors (8 surrounding cells) for a given position.
|
||||
|
||||
Args:
|
||||
x: X-coordinate.
|
||||
y: Y-coordinate.
|
||||
|
||||
Returns:
|
||||
A list of neighboring coordinates within bounds.
|
||||
"""
|
||||
neighbors: List[Tuple[int, int]] = []
|
||||
for dx in [-1, 0, 1]:
|
||||
for dy in [-1, 0, 1]:
|
||||
if dx == 0 and dy == 0:
|
||||
continue
|
||||
nx, ny = x + dx, y + dy
|
||||
if 0 <= nx < 9 and 0 <= ny < 9:
|
||||
neighbors.append((nx, ny))
|
||||
|
||||
return neighbors
|
||||
|
||||
def get_von_neumann_neighbors(x: int, y: int) -> List[Tuple[int, int]]:
|
||||
"""
|
||||
Retrieves all von Neumann neighbors (4 adjacent cells) for a given position.
|
||||
|
||||
Args:
|
||||
x: X-coordinate.
|
||||
y: Y-coordinate.
|
||||
|
||||
Returns:
|
||||
A list of neighboring coordinates within bounds.
|
||||
"""
|
||||
neighbors: List[Tuple[int, int]] = []
|
||||
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
|
||||
nx, ny = x + dx, y + dy
|
||||
if 0 <= nx < 9 and 0 <= ny < 9:
|
||||
neighbors.append((nx, ny))
|
||||
|
||||
return neighbors
|
||||
|
||||
# Collect all possible P placement positions
|
||||
possible_P_positions: Set[Tuple[int, int]] = set()
|
||||
|
||||
for x, y in A_positions:
|
||||
neighbors = get_moore_neighbors(x, y)
|
||||
possible_P_positions.update(neighbors)
|
||||
|
||||
for x, y in S_positions:
|
||||
neighbors = get_von_neumann_neighbors(x, y)
|
||||
possible_P_positions.update(neighbors)
|
||||
|
||||
# Remove positions already occupied by "A" or "S"
|
||||
occupied_positions: Set[Tuple[int, int]] = set(A_positions + S_positions)
|
||||
possible_P_positions = [
|
||||
pos
|
||||
for pos in possible_P_positions
|
||||
if pos not in occupied_positions and game_map[pos[0]][pos[1]] == []
|
||||
]
|
||||
|
||||
# Place "P" in all possible positions derived from "A" and "S"
|
||||
for x, y in possible_P_positions:
|
||||
game_map[x][y] = ["P"]
|
||||
if (x, y) in all_coordinates:
|
||||
all_coordinates.remove((x, y))
|
||||
|
||||
# Select one unoccupied square
|
||||
chosen_unoccupied: Optional[Tuple[int, int]] = (
|
||||
random.choice(all_coordinates) if all_coordinates else None
|
||||
)
|
||||
|
||||
return game_map, chosen_unoccupied
|
||||
|
||||
@staticmethod
|
||||
def heuristic(pos: Tuple[int, int], goal: Tuple[int, int]) -> int:
|
||||
"""
|
||||
Calculates the Manhattan distance between two positions.
|
||||
|
||||
Args:
|
||||
pos: Current position as (x, y).
|
||||
goal: Goal position as (x, y).
|
||||
|
||||
Returns:
|
||||
The Manhattan distance as an integer.
|
||||
"""
|
||||
return abs(pos[0] - goal[0]) + abs(pos[1] - goal[1])
|
||||
|
||||
@staticmethod
|
||||
def get_directions(pos: Tuple[int, int]) -> List[Tuple[int, int]]:
|
||||
"""
|
||||
Returns possible moves (Up, Down, Left, Right) from the current position within bounds.
|
||||
|
||||
Args:
|
||||
pos: Current position as (x, y).
|
||||
|
||||
Returns:
|
||||
A list of valid adjacent positions.
|
||||
"""
|
||||
moves: List[Tuple[int, int]] = [
|
||||
(pos[0] + 1, pos[1]), # Down
|
||||
(pos[0] - 1, pos[1]), # Up
|
||||
(pos[0], pos[1] + 1), # Right
|
||||
(pos[0], pos[1] - 1), # Left
|
||||
]
|
||||
|
||||
return [move for move in moves if 0 <= move[0] <= 8 and 0 <= move[1] <= 8]
|
||||
|
||||
@staticmethod
|
||||
def get_directions_with_zones(
|
||||
pos: Tuple[int, int], enemies_perception_zones: Set[Tuple[int, int]]
|
||||
) -> List[Tuple[int, int]]:
|
||||
"""
|
||||
Returns possible moves from the current position excluding moves that are in danger zones.
|
||||
|
||||
Args:
|
||||
pos: Current position as (x, y).
|
||||
enemies_perception_zones: A set of dangerous positions.
|
||||
|
||||
Returns:
|
||||
A list of safe adjacent positions.
|
||||
"""
|
||||
moves: List[Tuple[int, int]] = Utils.get_directions(pos)
|
||||
|
||||
return [move for move in moves if move not in enemies_perception_zones]
|
||||
Reference in New Issue
Block a user