class_name Match3Validator extends RefCounted ## Validation utilities for Match3 gameplay ## ## Static methods for validating Match3 game state and data integrity. ## Prevents crashes by checking bounds, data structures, and game logic constraints. ## ## Usage: ## if Match3Validator.is_valid_grid_position(pos, grid_size): ## # Safe to access grid[pos.y][pos.x] ## ## if Match3Validator.validate_grid_integrity(grid, grid_size): ## # Grid structure is valid for game operations static func is_valid_grid_position(pos: Vector2i, grid_size: Vector2i) -> bool: ## Check if the position is within the grid boundaries. ## ## Performs bounds checking to prevent index out of bounds errors. ## ## Args: ## pos: Grid position to validate (x, y coordinates) ## grid_size: Dimensions of the grid (width, height) ## ## Returns: ## bool: True if position is valid, False if out of bounds return ( pos.x >= 0 and pos.y >= 0 and pos.x < grid_size.x and pos.y < grid_size.y ) static func validate_grid_integrity(grid: Array, grid_size: Vector2i) -> bool: ## Verify that the grid array structure matches expected dimensions. ## ## Validates the grid's 2D array structure for safe game operations. ## Checks array types, dimensions, and structural consistency. ## ## Args: ## grid: The 2D array representing the game grid ## grid_size: Expected dimensions (width x height) ## ## Returns: ## bool: True if grid structure is valid, False if corrupted or malformed if not grid is Array: DebugManager.log_error("Grid is not an array", "Match3") return false if grid.size() != grid_size.y: DebugManager.log_error( "Grid height mismatch: %d vs %d" % [grid.size(), grid_size.y], "Match3" ) return false for y in range(grid.size()): if not grid[y] is Array: DebugManager.log_error("Grid row %d is not an array" % y, "Match3") return false if grid[y].size() != grid_size.x: DebugManager.log_error( ( "Grid row %d width mismatch: %d vs %d" % [y, grid[y].size(), grid_size.x] ), "Match3" ) return false return true static func safe_grid_access( grid: Array, pos: Vector2i, grid_size: Vector2i ) -> Node2D: # Safe grid access with comprehensive bounds checking if not is_valid_grid_position(pos, grid_size): return null if pos.y >= grid.size() or pos.x >= grid[pos.y].size(): DebugManager.log_warn( "Grid bounds exceeded: (%d,%d)" % [pos.x, pos.y], "Match3" ) return null var tile = grid[pos.y][pos.x] if not tile or not is_instance_valid(tile): return null return tile static func safe_tile_access(tile: Node2D, property: String): # Safe property access on tiles if not tile or not is_instance_valid(tile): return null if not property in tile: DebugManager.log_warn("Tile missing property: %s" % property, "Match3") return null return tile.get(property) static func are_tiles_adjacent(tile1: Node2D, tile2: Node2D) -> bool: if not tile1 or not tile2: return false var pos1 = tile1.grid_position var pos2 = tile2.grid_position var diff = abs(pos1.x - pos2.x) + abs(pos1.y - pos2.y) return diff == 1