From e30e578f334b583f36c48123a7e0c631de25c90d Mon Sep 17 00:00:00 2001 From: Rysertio Date: Thu, 14 Mar 2024 17:37:49 +0600 Subject: [PATCH] bt and goap --- src/ai.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/src/ai.c b/src/ai.c index 984b963..62ceb37 100644 --- a/src/ai.c +++ b/src/ai.c @@ -131,3 +131,233 @@ void aStarPathfinding(GameData* map, int startX, int startY, int targetX, int ta free(openList); free(closedList); } + +// goap + +typedef struct { + int targetX, targetY; // The target position for the unit +} MoveGoal; + +typedef struct { + int unitID; // The ID of the unit to move + int targetX, targetY; // The target position +} MoveAction; + +bool canMove(GameData* gameData, MoveAction* action) { + // Find the unit in the game data + for (int i = 0; i < MAX_UNITS; i++) { + if (gameData->units[i].unitID == action->unitID) { + // Check if the unit is within range of the target + int distance = abs(gameData->units[i].x - action->targetX) + abs(gameData->units[i].y - action->targetY); + return distance <= 5; // Assuming a unit can move up to 5 tiles in one action + } + } + return false; // Unit not found +} + + +MoveAction* planMove(GameData* gameData, MoveGoal* goal) { + // For simplicity, we'll just select the first unit that can move to the goal + for (int i = 0; i < MAX_UNITS; i++) { + MoveAction action = {gameData->units[i].unitID, goal->targetX, goal->targetY}; + if (canMove(gameData, &action)) { + return &action; // Return the action + } + } + return NULL; // No action found +} + + +void updateGame(GameData* gameData) { + // Update game state... + + // Example: Plan a move for a unit + MoveGoal goal = {10, 20}; // Move to position (10, 20) + MoveAction* action = planMove(gameData, &goal); + if (action != NULL) { + // Execute the action... + } +} + +void moveUnit(Unit* unit, int targetX, int targetY) { + // Move the unit to the target position + unit->x = targetX; + unit->y = targetY; + printf("Unit %d moved to (%d, %d).\n", unit->unitID, unit->x, unit->y); +} + +// Sample GOAP planning logic for moving a unit to a target position +void planActions(GameData* gameData) { + // Assuming we want to move Unit 0 to position (10, 10) + int targetX = 10; + int targetY = 10; + + // Find the Unit with unitID 0 + Unit* unitToMove = NULL; + for (int i = 0; i < MAX_UNITS; i++) { + if (gameData->units[i].unitID == 0) { + unitToMove = &gameData->units[i]; + break; + } + } + + if (unitToMove != NULL) { + // Implement planning logic here to move the unit to the target position + printf("Planning to move Unit %d to (%d, %d)...\n", unitToMove->unitID, targetX, targetY); + + // Execute the action to move the unit + moveUnit(unitToMove, targetX, targetY); + } else { + printf("Unit with ID 0 not found.\n"); + } +} + +// behavior tree + +typedef enum { + NODE_SELECTOR, + NODE_SEQUENCE, + NODE_ACTION, + NODE_CONDITION +} NodeType; + +typedef struct Node { + NodeType type; + int (*execute)(struct Node*); +} Node; + + +int executeAction(Node* node) { + // Placeholder for action execution + return 1; // Assume action is successful +} + +int executeCondition(Node* node) { + // Placeholder for condition checking + return 1; // Assume condition is true +} + +int executeSelector(Node* node) { + // Selector node executes its children until one succeeds + for (int i = 0; i < node->numChildren; i++) { + if (node->children[i]->execute(node->children[i])) { + return 1; + } + } + return 0; +} + +int executeSequence(Node* node) { + // Sequence node executes its children in order until one fails + for (int i = 0; i < node->numChildren; i++) { + if (!node->children[i]->execute(node->children[i])) { + return 0; + } + } + return 1; +} + + +Node* createMoveToTargetBehavior() { + Node* moveToTarget = malloc(sizeof(Node)); + moveToTarget->type = NODE_ACTION; + moveToTarget->execute = executeAction; + // Additional setup for the move action... + return moveToTarget; +} + +Node* createAttackEnemyBehavior() { + Node* attackEnemy = malloc(sizeof(Node)); + attackEnemy->type = NODE_ACTION; + attackEnemy->execute = executeAction; + // Additional setup for the attack action... + return attackEnemy; +} + +Node* createPatrolAreaBehavior() { + Node* patrolArea = malloc(sizeof(Node)); + patrolArea->type = NODE_ACTION; + patrolArea->execute = executeAction; + // Additional setup for the patrol action... + return patrolArea; +} + + +Node* createBehaviorTree() { + Node* root = malloc(sizeof(Node)); + root->type = NODE_SELECTOR; + root->execute = executeSelector; + root->numChildren = 3; + root->children = malloc(sizeof(Node*) * 3); + + root->children[0] = createMoveToTargetBehavior(); + root->children[1] = createAttackEnemyBehavior(); + root->children[2] = createPatrolAreaBehavior(); + + return root; +} + + +void updateUnitBehavior(Node* behaviorTree) { + behaviorTree->execute(behaviorTree); +} + + +// Define the possible return status of a behavior node +typedef enum { + SUCCESS, + FAILURE, + RUNNING +} Status; + +// Define a function pointer type for the behavior node +typedef Status (*NodeFunction)(); + +// Behavior Tree nodes (functions) +Status sequence(); +Status selector(); +Status action1(); +Status action2(); + +// Sample action nodes +Status action1() { + printf("Executing Action 1\n"); + return SUCCESS; +} + +Status action2() { + printf("Executing Action 2\n"); + return SUCCESS; +} + +// Function to save behavior tree to a file +void saveBehaviorTreeToFile(const char* filename, NodeFunction root) { + FILE* file = fopen(filename, "wb"); + + if (file == NULL) { + printf("Error opening file for writing\n"); + return; + } + + // Write the address of the root function to the file + fwrite(&root, sizeof(NodeFunction), 1, file); + + fclose(file); +} + +// Function to load behavior tree from a file +NodeFunction loadBehaviorTreeFromFile(const char* filename) { + FILE* file = fopen(filename, "rb"); + + if (file == NULL) { + printf("Error opening file for reading\n"); + return NULL; + } + + NodeFunction root; + fread(&root, sizeof(NodeFunction), 1, file); + + fclose(file); + + return root; +} \ No newline at end of file