extends ActionLeaf func find_best_arrangement(actor) -> Dictionary: # Convert goals to 2D array for easier comparison 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) # Find misplaced items for i in range(1, 4): # Check central 3x3 area for j in range(1, 4): var board_idx = i * 5 + j var goal_idx = (i - 1) * 3 + (j - 1) var current_item = actor.playerboard[board_idx] var goal_item = actor.goals[goal_idx] if current_item != goal_item and current_item != -1: # Find better position for this item for gi in range(3): for gj in range(3): if actor.goals[gi * 3 + gj] == current_item: var target_slot = (gi + 1) * 5 + (gj + 1) if actor.playerboard[target_slot] == -1: return { "source_slot": board_idx, "target_slot": target_slot } return {} func is_goals_achieved(actor) -> bool: # Check only central 3x3 area of playerboard against goals for i in range(3): for j in range(3): var board_idx = (i + 1) * 5 + (j + 1) var goal_idx = i * 3 + j if actor.goals[goal_idx] != -1 and actor.goals[goal_idx] != actor.playerboard[board_idx]: return false elif actor.goals[goal_idx] == -1 and actor.playerboard[board_idx] != -1: return false # Also check outside the goal area if i == 0 or i == 4 or j == 0 or j == 4: if actor.playerboard[i * 5 + j] != -1: return false return true func tick(actor: Node, blackboard: Blackboard) -> int: # First check if goals are already achieved if is_goals_achieved(actor): blackboard.set_value("current_action", "idle") return FAILURE if actor.action_points < 2: return FAILURE var arrangement = find_best_arrangement(actor) if arrangement.is_empty(): return FAILURE blackboard.set_value("source_slot", arrangement.source_slot) blackboard.set_value("target_slot", arrangement.target_slot) # Do the arrangement if actor.is_multiplayer_authority(): var item = actor.playerboard[arrangement.source_slot] actor.playerboard[arrangement.target_slot] = item actor.playerboard[arrangement.source_slot] = -1 actor.rpc("sync_playerboard", actor.playerboard) actor.has_performed_action = true actor.action_points -= 2 return SUCCESS