111 lines
2.9 KiB
GDScript
111 lines
2.9 KiB
GDScript
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
|