timesynk/old/npc.c

114 lines
3.6 KiB
C

#include "npc.h"
#include "tile.h"
#include "stubs.h" // for interface
#include "game.h" // for current_map
/**** npcThink
Catch-all function for processing each NPC's think operations - these operations include decision making and the attempt to act on that decision.
Arguments: struct Tile *npc
Returns: void
****/
void npcThink(struct Tile *npc) {
struct NpcTile *npc_data = npc->data;
struct Tile *target;
switch (npc_data->behavior) {
case BEHAVE_AGGRESSIVE:
if (!npc_data->target) { // find a player
if ((target = npcFindTile(npc, PLAYER))) {
interfacePrint("The nupi, fueled by bloodlust, shrieks in rage");
npc_data->target = target;
}
} else {
npcMoveToTarget(npc, npc_data);
}
break;
case BEHAVE_WANDER:
npcMoveRandom(npc);
break;
}
}
/**** npcMoveToTarget
Called from npcThink, this function attempts to move the given NPC to its target's location.
Arguments: struct Tile *npc, struct NpcTile *npc_tile
Returns: void
TODO: should return the change in x/y. It is redundant to pass NpcTile as well, but since parent operations hold that info as well, it makes some sense to pass it as well - not sure if this should be changed.
****/
void npcMoveToTarget(struct Tile *npc, struct NpcTile *npc_data) {
int current_x = npc->x;
int current_y = npc->y;
struct Tile *target_tile;
target_tile = npc_data->target;
if (target_tile) {
if (npc->x < target_tile->x) {
current_x++;
} else if (npc->x > target_tile->x) {
current_x--;
}
if (npc->y < target_tile->y) {
current_y++;
} else if (npc->y > target_tile->y) {
current_y--;
}
if (!gameCollision(current_x, current_y)) {
gameMoveTile(npc, current_x, current_y);
}
}
}
/**** npcMoveRandom
Simply moves the given NPC in a random direction
Arguments: struct Tile *npc
Returns: void
****/
void npcMoveRandom(struct Tile *npc) {
int target_x = npc->x + (roll(0, 2)-1);
int target_y = npc->y + (roll(0, 2)-1);
if (!gameCollision(target_x, target_y)) {
gameMoveTile(npc, target_x, target_y);
}
}
/**** npcFindTile
Dumb function that blindly iterates through a square around the NPC until a Tile of tile_type(PLAYER, ITEM, etc.) is (hopefully) found. Upon being found, returns the found Tile.
Arguments: struct Tile *npc, int tile_type
Returns: struct Tile*
TODO: This function should be removed and re-implemented in map.c as a generic findTile function that takes start x, start y, width, height (or radius?), and the target tile type.
TODO: Also should have a version that takes a Tile struct as the target instead of a type id.
****/
struct Tile *npcFindTile(struct Tile *npc, int tile_type) {
struct Tile *final_target;
struct NpcTile *npc_data = npc->data;
struct Tile *current_tile;
int step_x = npc->x - npc_data->vision;
int step_y = npc->y - npc_data->vision;
int end_x = npc->x + npc_data->vision;
int end_y = npc->y + npc_data->vision;
int found_x = 0;
int found_y = 0;
while (step_x < end_x) {
step_y = npc->y - (npc_data->vision);
while (step_y < end_y) {
if (step_x >= 0 && step_y >= 0 && step_x < current_map->width && step_y < current_map->height) {
current_tile = &current_map->matrix[step_x][step_y];
while (current_tile) {
if (current_tile->tid == tile_type) {
if ( ( (npc->x-step_x) + (npc->y-step_y)) < (npc->x-found_x + npc->y-found_y) ) {
found_x = step_x;
found_y = step_y;
final_target = current_tile;
}
}
current_tile = current_tile->next;
}
}
step_y++;
}
step_x++;
}
return final_target;
}