AI updates - allow enemies to flee.

This commit is contained in:
Steve 2015-11-15 13:26:34 +00:00
parent c8489e7dc6
commit 095e8b65a4
5 changed files with 121 additions and 98 deletions

View File

@ -20,15 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "ai.h"
static int aggression[][5] =
{
{60, 65, 70, 75, 80},
{50, 55, 60, 65, 70},
{40, 45, 50, 55, 60},
{30, 35, 40, 45, 50},
{15, 20, 25, 30, 35}
};
static void faceTarget(Entity *f);
static int isInFOV(Entity *f, int fov);
static void preAttack(void);
@ -44,21 +35,36 @@ static void slow(void);
static void moveToPlayer(void);
static int canAttack(Entity *f);
static int selectWeapon(int type);
static void flee(void);
static int nearExtractionPoint(void);
static int nearEnemies(void);
static void lookForPlayer(void);
static void fleeEnemies(void);
static void moveToExtractionPoint(void);
static int getActionChance(int type);
static void flee(void);
static void doFighterAI(void);
static void doCivilianAI(void);
void doAI(void)
{
if (self->flags & EF_CIVILIAN)
{
doCivilianAI();
}
else
{
doFighterAI();
}
}
static void doFighterAI(void)
{
int r;
/* don't hold a grudge against current target */
if ((self->target != NULL && self->target->health <= 0) || rand() % 2 == 0)
{
self->action = self->defaultAction;
self->action = doAI;
self->target = NULL;
}
@ -83,27 +89,27 @@ void doAI(void)
r = rand() % 100;
if (r <= aggression[self->aggression][0])
if (r <= getActionChance(AI_DODGE))
{
self->action = dodge;
self->aiActionTime = FPS;
}
else if (r <= aggression[self->aggression][1])
else if (r <= getActionChance(AI_BOOST))
{
self->action = boost;
self->aiActionTime = FPS / 2;
}
else if (r <= aggression[self->aggression][2])
else if (r <= getActionChance(AI_SLOW))
{
self->action = slow;
self->aiActionTime = FPS / 2;
}
else if (r <= aggression[self->aggression][3])
else if (r <= getActionChance(AI_STRAIGHT))
{
self->action = flyStraight;
self->aiActionTime = FPS;
}
else if (r <= aggression[self->aggression][4])
else if (r <= getActionChance(AI_HUNT))
{
self->action = huntTarget;
self->aiActionTime = FPS * 2;
@ -114,7 +120,7 @@ void doAI(void)
self->aiActionTime = FPS;
}
if (player != NULL && battle.numEnemies <= 2 && self->flags & EF_FLEES)
if ((player != NULL && battle.numEnemies <= 2 && self->flags & EF_FLEES) || (self->flags & EF_ALWAYS_FLEES))
{
self->action = flee;
self->aiActionTime = FPS * 3;
@ -126,6 +132,29 @@ void doAI(void)
}
}
static int getActionChance(int type)
{
switch (type)
{
case AI_DODGE:
return 40 - (self->aggression * 5);
case AI_BOOST:
return 50 - (self->aggression * 5);
case AI_SLOW:
return 60 - (self->aggression * 5);
case AI_STRAIGHT:
return 70 - (self->aggression * 5);
case AI_HUNT:
return 80 - (self->aggression * 5);
}
return 100;
}
static void huntTarget(void)
{
faceTarget(self->target);
@ -341,10 +370,61 @@ static void dodge(void)
nextAction();
}
static void nextAction(void)
{
if (--self->aiActionTime <= 0)
{
self->action = doAI;
}
}
static void flee(void)
{
if (!nearEnemies() && battle.extractionPoint)
{
self->target = battle.extractionPoint;
moveToExtractionPoint();
}
}
static int nearEnemies(void)
{
int i, numEnemies;
Entity *e, **candidates;
candidates = getAllEntsWithin(self->x - (self->w / 2) - 1000, self->y - (self->h / 2) - 1000, 2000, 2000, self);
self->target = NULL;
self->targetLocation.x = self->targetLocation.y = 0;
numEnemies = 0;
for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i])
{
if (e->type == ET_FIGHTER && e->side != self->side)
{
self->targetLocation.x += e->x;
self->targetLocation.y += e->y;
numEnemies++;
}
}
if (numEnemies)
{
self->targetLocation.x /= numEnemies;
self->targetLocation.y /= numEnemies;
self->action = fleeEnemies;
self->aiActionTime = FPS / 2;
return 1;
}
return 0;
}
static void fleeEnemies(void)
{
int dir;
int wantedAngle = 180 + getAngle(self->x, self->y, player->x, player->y);
int wantedAngle = 180 + getAngle(self->x, self->y, self->targetLocation.x, self->targetLocation.y);
wantedAngle %= 360;
@ -359,17 +439,14 @@ static void flee(void)
applyFighterThrust();
nextAction();
}
static void nextAction(void)
{
if (--self->aiActionTime <= 0)
{
self->action = doAI;
}
}
/* ====== Ally AI ======= */
static void moveToPlayer(void)
{
int dist = getDistance(self->x, self->y, player->x, player->y);
@ -430,64 +507,6 @@ static void moveToExtractionPoint(void)
applyFighterThrust();
}
static int nearEnemies(void)
{
int i, numEnemies;
Entity *e, **candidates;
candidates = getAllEntsWithin(self->x - (self->w / 2) - 1000, self->y - (self->h / 2) - 1000, 2000, 2000, self);
self->target = NULL;
self->targetLocation.x = self->targetLocation.y = 0;
numEnemies = 0;
for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i])
{
if (e->type == ET_FIGHTER && e->side != SIDE_ALLIES)
{
self->targetLocation.x += e->x;
self->targetLocation.y += e->y;
numEnemies++;
}
}
if (numEnemies)
{
self->targetLocation.x /= numEnemies;
self->targetLocation.y /= numEnemies;
self->action = fleeEnemies;
self->aiActionTime = FPS / 2;
return 1;
}
return 0;
}
static void fleeEnemies(void)
{
int dir;
int wantedAngle = 180 + getAngle(self->x, self->y, self->targetLocation.x, self->targetLocation.y);
wantedAngle %= 360;
if (fabs(wantedAngle - self->angle) > TURN_THRESHOLD)
{
dir = ((int)(wantedAngle - self->angle + 360)) % 360 > 180 ? -1 : 1;
self->angle += dir * TURN_SPEED;
self->angle = mod(self->angle, 360);
}
applyFighterThrust();
if (--self->aiActionTime <= 0)
{
self->action = doCivilianAI;
}
}
static void lookForPlayer(void)
{
if (player != NULL && getDistance(self->x, self->y, player->x, player->y) < 1000)

View File

@ -23,6 +23,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../defs.h"
#include "../structs.h"
#define AI_DODGE 0
#define AI_BOOST 1
#define AI_SLOW 2
#define AI_STRAIGHT 3
#define AI_HUNT 4
#define TURN_SPEED 4
#define TURN_THRESHOLD 2

View File

@ -75,15 +75,7 @@ Entity *spawnFighter(char *name, int x, int y, int side)
f->texture = getTexture("gfx/craft/civilian02.png");
}
if (f->flags & EF_CIVILIAN)
{
f->defaultAction = doCivilianAI;
}
else
{
f->defaultAction = doAI;
}
f->action = doAI;
f->die = die;
return f;
@ -193,11 +185,6 @@ void doFighter(void)
self->shieldRecharge = self->shieldRechargeRate;
}
if (self->action == NULL && self->defaultAction != NULL)
{
self->action = self->defaultAction;
}
if (self->health <= 0)
{
self->health = 0;
@ -395,7 +382,7 @@ void damageFighter(Entity *f, int amount, long flags)
if (f->systemPower == 0)
{
f->shield = f->maxShield = 0;
f->action = f->defaultAction = NULL;
f->action = NULL;
}
}
else
@ -491,3 +478,16 @@ static void straightDie(void)
playBattleSound(SND_EXPLOSION_1 + rand() % 4, self->x, self->y);
}
}
void fleeAllEnemies(void)
{
Entity *e;
for (e = battle.entityHead.next ; e != NULL ; e = e->next)
{
if (e->type == ET_FIGHTER && e->side != SIDE_ALLIES)
{
e->flags |= EF_ALWAYS_FLEES;
}
}
}

View File

@ -56,7 +56,6 @@ void initPlayer(void)
STRNCPY(player->name, "Player", MAX_NAME_LENGTH);
player->action = NULL;
player->defaultAction = NULL;
}
void doPlayer(void)

View File

@ -113,7 +113,6 @@ struct Entity {
Entity *target;
Entity *owner;
void (*action)(void);
void (*defaultAction)(void);
void (*die)(void);
SDL_Texture *texture;
Entity *next;