diff --git a/project.godot b/project.godot index 57aa82c..4e1005f 100644 --- a/project.godot +++ b/project.godot @@ -23,3 +23,16 @@ window/size/viewport_height=720 [editor_plugins] enabled=PackedStringArray("res://addons/enhanced_gridmap/plugin.cfg") + +[input] + +grab_item={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) +] +} +put_item={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} diff --git a/scenes/main.gd b/scenes/main.gd index 14f286b..9f13dd6 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -214,37 +214,139 @@ func _on_message_input_text_submitted(new_text): $MessageInput.text = "" $MessageInput.release_focus() +# --------- +# Bot Logic +# --------- +func evaluate_bot_move(bot: Node) -> Dictionary: + var best_move = { + "action": "none", + "position": bot.current_position, + "value": -1 + } + + # If no action performed yet, prioritize grab/put + if not bot.has_performed_action: + # Check current position for grabbing + var current_cell = Vector3i(bot.current_position.x, 1, bot.current_position.y) + var current_item = bot.enhanced_gridmap.get_cell_item(current_cell) + + # Evaluate grabbing current item if it matches goals + if current_item != -1 and current_item in bot.goals and bot.playerboard.find(-1) != -1: + return { + "action": "grab", + "position": bot.current_position, + "value": 10 + } + + # Evaluate putting item from playerboard + for goal in bot.goals: + var item_index = bot.playerboard.find(goal) + if item_index != -1 and current_item == -1: + return { + "action": "put", + "position": bot.current_position, + "value": 15 + } + else: + # Bot has performed action, look for movement + var neighbors = bot.enhanced_gridmap.get_neighbors(bot.current_position, 1) + for neighbor in neighbors: + if not neighbor.is_walkable: + continue + + if not bot.is_within_movement_range(neighbor.position): + continue + + var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) + var item = bot.enhanced_gridmap.get_cell_item(cell) + + # Evaluate position for next turn + if item in bot.goals or item == -1: + var value = 8 + if value > best_move.value: + best_move = { + "action": "move", + "position": neighbor.position, + "value": value + } + + return best_move + +#func move_bot(bot_id): + #if multiplayer.is_server(): + #if moving_bots.get(bot_id, false): + #return # Skip if bot is already moving + # + #var bot = get_node(str(bot_id)) + #if bot and (turn_based_mode or not bot.is_player_moving): + #moving_bots[bot_id] = true # Mark bot as moving + #var target_position = bot.find_random_valid_position_in_range() # Use the new function + #if target_position != bot.current_position: + #var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(target_position)) + # + #if path.size() > 1: + #path.pop_front() + ## Trim path to respect movement range + #var trimmed_path = path.slice(0, bot.movement_range) + #bot.move_bot_along_path(trimmed_path, bot_id) + #else: + #print("No valid path found for bot") + #moving_bots[bot_id] = false + #if turn_based_mode: + #end_current_turn() + #else: + #print("No new valid position found for bot") + #moving_bots[bot_id] = false + #if turn_based_mode: + #end_current_turn() + #else: + #print("Bot not found or is moving") + #if turn_based_mode: + #end_current_turn() func move_bot(bot_id): if multiplayer.is_server(): if moving_bots.get(bot_id, false): - return # Skip if bot is already moving + return var bot = get_node(str(bot_id)) if bot and (turn_based_mode or not bot.is_player_moving): - moving_bots[bot_id] = true # Mark bot as moving - var target_position = bot.find_random_valid_position_in_range() # Use the new function - if target_position != bot.current_position: - var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(target_position)) - - if path.size() > 1: - path.pop_front() - # Trim path to respect movement range - var trimmed_path = path.slice(0, bot.movement_range) - bot.move_bot_along_path(trimmed_path, bot_id) - else: - print("No valid path found for bot") + moving_bots[bot_id] = true + + var best_move = evaluate_bot_move(bot) + + match best_move.action: + "grab": + if bot.grab_item(): + bot.has_performed_action = true + moving_bots[bot_id] = false + # Don't end turn, allow movement after grab + move_bot(bot_id) # Try to move after grabbing + "put": + if bot.put_item(): + bot.has_performed_action = true + moving_bots[bot_id] = false + # Don't end turn, allow movement after put + move_bot(bot_id) # Try to move after putting + "move": + if bot.has_performed_action: + var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(best_move.position)) + if path.size() > 1: + path.pop_front() + var trimmed_path = path.slice(0, bot.movement_range) + bot.rotate_towards_target(best_move.position) + bot.move_bot_along_path(trimmed_path, bot_id) + else: + moving_bots[bot_id] = false + if turn_based_mode: + end_current_turn() + else: + moving_bots[bot_id] = false + if turn_based_mode: + end_current_turn() + _: moving_bots[bot_id] = false if turn_based_mode: end_current_turn() - else: - print("No new valid position found for bot") - moving_bots[bot_id] = false - if turn_based_mode: - end_current_turn() - else: - print("Bot not found or is moving") - if turn_based_mode: - end_current_turn() # Called when a bot finishes moving func bot_movement_completed(bot_id): diff --git a/scenes/player.gd b/scenes/player.gd index 938ec2d..913cb6a 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -12,6 +12,16 @@ var is_player_moving: bool = false @export var center_y: bool = false @export var center_z: bool = false +# Goals & Playerboard Data +@export var goals: Array[int] = [0,0,0,0,0,0,0,0,0] # 9 length array for goals +@export var playerboard: Array[int] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # 25 length array for holding items +var has_performed_action: bool = false # Track if grab/put action has been done + +# Player Rotation Config +# Add these variables for rotation +var target_rotation: float = 0.0 +var rotation_speed: float = 10.0 # Adjust this to control rotation speed + @export var movement_range: int = 1 # How many blocks can be moved at once @export var use_diagonal_movement: bool = false: # Allow diagonal movement set(value): @@ -49,6 +59,13 @@ func _ready(): update_player_position(current_position) set_process_unhandled_input(is_multiplayer_authority()) + + # Initialize random goals + initialize_random_goals() + + # Initialize playerboard with -1 (empty slots) + playerboard.resize(25) + playerboard.fill(-1) func find_valid_starting_position() -> Vector2i: var rng = RandomNumberGenerator.new() @@ -106,6 +123,16 @@ func _physics_process(_delta): if is_multiplayer_authority(): rpc("remote_set_position", global_position) +# Add this to your _process function if you don't have one +func _process(delta): + if is_multiplayer_authority(): + if Input.is_action_just_pressed("grab_item"): # Define this input in project settings + if grab_item(): + rpc("display_message", "Item grabbed!") + elif Input.is_action_just_pressed("put_item"): # Define this input in project settings + if put_item(): + rpc("display_message", "Item placed!") + func _unhandled_input(event): var main = get_node("/root/Main") if not is_multiplayer_authority() or (main.turn_based_mode and (not is_my_turn or is_player_moving)): @@ -149,14 +176,44 @@ func is_within_movement_range(target_position: Vector2i) -> bool: abs(target_position.y - current_position.y) return distance <= movement_range +#func move_player_to_clicked_position(grid_position: Vector2i): + #if not is_multiplayer_authority(): + #return + # + #if is_player_moving: + #return + # + ## Check if the movement is within range + #if not is_within_movement_range(grid_position): + #print("Movement out of range") + #return + # + #var cell_item = enhanced_gridmap.get_cell_item(Vector3i(grid_position.x, 0, grid_position.y)) + # + #if cell_item in enhanced_gridmap.non_walkable_items: + #print("Cannot move to non-walkable cell") + #return + # + #var path = enhanced_gridmap.find_path(Vector2(current_position), Vector2(grid_position)) + # + #if path.size() > 1: + #path.pop_front() + #rpc("start_movement_along_path", path) + #else: + #print("No valid path found") + func move_player_to_clicked_position(grid_position: Vector2i): if not is_multiplayer_authority(): return if is_player_moving: return + + # Check if player has performed grab/put action + if not has_performed_action and current_position != grid_position: + rpc("display_message", "Must grab or place item before moving!") + return - # Check if the movement is within range if not is_within_movement_range(grid_position): print("Movement out of range") return @@ -167,6 +224,8 @@ func move_player_to_clicked_position(grid_position: Vector2i): print("Cannot move to non-walkable cell") return + rotate_towards_target(grid_position) + var path = enhanced_gridmap.find_path(Vector2(current_position), Vector2(grid_position)) if path.size() > 1: @@ -189,6 +248,7 @@ func start_movement_along_path(path: Array): tween.tween_callback(func(): current_position = Vector2i(path[-1].x, path[-1].y) is_player_moving = false + has_performed_action = false # Reset the action flag after movement enhanced_gridmap.clear_path_visualization() has_moved_this_turn = true var main = get_node("/root/Main") @@ -196,6 +256,7 @@ func start_movement_along_path(path: Array): end_turn() ) + func move_bot_along_path(path: Array, bot_id: int): if not is_multiplayer_authority(): return @@ -250,6 +311,7 @@ func grid_to_world(grid_position: Vector2i) -> Vector3: func start_turn(): has_moved_this_turn = false + has_performed_action = false # Reset action flag at start of turn is_my_turn = true if is_multiplayer_authority(): rpc("display_message", "It's your turn!") @@ -272,3 +334,87 @@ func display_message(message): await get_tree().create_timer(3).timeout $Bubble.hide() $Bubble/Message.hide() + +func initialize_random_goals(): + goals.clear() + var rng = RandomNumberGenerator.new() + rng.randomize() + + for i in range(9): + goals.append(rng.randi_range(7, 10)) + + if is_multiplayer_authority(): + rpc("sync_goals", goals) + +func grab_item() -> bool: + if not enhanced_gridmap: + return false + + var current_cell = Vector3i(current_position.x, 1, current_position.y) + var item = enhanced_gridmap.get_cell_item(current_cell) + + if item == -1: # No item to grab + return false + + var empty_slot = playerboard.find(-1) + if empty_slot == -1: # No empty slots + return false + + playerboard[empty_slot] = item + enhanced_gridmap.set_cell_item(current_cell, -1) + + if is_multiplayer_authority(): + rpc("sync_playerboard", playerboard) + + has_performed_action = true # Set action flag + return true + +func put_item() -> bool: + if not enhanced_gridmap: + return false + + var current_cell = Vector3i(current_position.x, 1, current_position.y) + if enhanced_gridmap.get_cell_item(current_cell) != -1: + return false # Cell is occupied + + var item_to_put = -1 + var item_index = -1 + + for goal in goals: + var index = playerboard.find(goal) + if index != -1: + item_to_put = goal + item_index = index + break + + if item_to_put == -1: + return false + + enhanced_gridmap.set_cell_item(current_cell, item_to_put) + playerboard[item_index] = -1 + + if is_multiplayer_authority(): + rpc("sync_playerboard", playerboard) + + has_performed_action = true # Set action flag + return true + +@rpc("any_peer", "call_local") +func sync_goals(new_goals: Array): + goals = new_goals + +@rpc("any_peer", "call_local") +func sync_playerboard(new_playerboard: Array): + playerboard = new_playerboard + +func rotate_towards_target(target_pos: Vector2i): + var direction = Vector2( + target_pos.x - current_position.x, + target_pos.y - current_position.y + ).normalized() + + target_rotation = atan2(direction.x, direction.y) + + # Create a tween for smooth rotation + var tween = create_tween() + tween.tween_property(self, "rotation:y", target_rotation, 0.2)