bt and goap
This commit is contained in:
parent
71025fc7fa
commit
e30e578f33
1 changed files with 230 additions and 0 deletions
230
src/ai.c
230
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;
|
||||
}
|
Loading…
Reference in a new issue