extends ActionLeaf func is_goals_achieved(actor) -> bool: # Convert goals to 2D for easier pattern matching var goals_2d = [] for i in range(3): var row = [] for j in range(3): row.append(actor.goals[i * 3 + j]) goals_2d.append(row) # Convert playerboard to 2D var board_2d = [] for i in range(5): var row = [] for j in range(5): row.append(actor.playerboard[i * 5 + j]) board_2d.append(row) # Check every possible 3x3 region in the 5x5 board for start_row in range(3): # 5-3+1 possible start rows for start_col in range(3): # 5-3+1 possible start columns var matches = true # Check if this 3x3 region matches the goals for i in range(3): for j in range(3): var board_item = board_2d[start_row + i][start_col + j] var goal_item = goals_2d[i][j] if goal_item != -1 and goal_item != board_item: matches = false break elif goal_item == -1 and board_item != -1: matches = false break if not matches: break if matches: return true return false func find_target_slot(actor, item: int) -> int: # Get the goals in 2D format (3x3) var goals_2d = [] for i in range(3): var row = [] for j in range(3): row.append(actor.goals[i * 3 + j]) goals_2d.append(row) # Convert playerboard to 2D (5x5) var board_2d = [] for i in range(5): var row = [] for j in range(5): row.append(actor.playerboard[i * 5 + j]) board_2d.append(row) # Find matching position in goals var target_positions = [] for i in range(3): for j in range(3): if goals_2d[i][j] == item: # Convert to playerboard position (centered in 5x5 grid) target_positions.append(Vector2i(j + 1, i + 1)) # Find best empty slot that matches a goal position for pos in target_positions: var slot_index = (pos.y + 1) * 5 + (pos.x + 1) if actor.playerboard[slot_index] == -1: return slot_index # If no matching position found, find any empty slot return actor.playerboard.find(-1) func tick(actor: Node, blackboard: Blackboard) -> int: # Early validation if not actor.is_bot or actor.action_points <= 0: return FAILURE var grab_position = blackboard.get_value("grab_position") if not grab_position: return FAILURE # Check if there's an item var cell = Vector3i(grab_position.x, 1, grab_position.y) var item = actor.enhanced_gridmap.get_cell_item(cell) if item == -1: return FAILURE # Find strategic slot var target_slot = find_target_slot(actor, item) if target_slot == -1: return FAILURE # Execute grab if actor.is_multiplayer_authority(): actor.playerboard[target_slot] = item actor.rpc("sync_grid_item", cell.x, cell.y, cell.z, -1) actor.rpc("sync_playerboard", actor.playerboard) actor.has_performed_action = true actor.action_points -= 1 blackboard.set_value("current_action", "idle") actor._after_action_completed() # Add this line return SUCCESS