Further refinement of new ModularizedTacticalAI architecture; added plans for Crows

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6017 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
feynman
2013-04-18 20:02:54 +00:00
parent 52cb4ff424
commit 26383d83a8
22 changed files with 451 additions and 490 deletions
+11
View File
@@ -5,6 +5,9 @@
#include "random.h"
#include "Points.h"
#include <iostream>
#include <iomanip>
extern BOOLEAN gfTurnBasedAI;
@@ -104,6 +107,14 @@ enum
#undef max
#define max(a,b) ((a) > (b) ? (a) : (b))
// Added by feynman - remove all the ugly #ifdefs printf combinations for required for DebugAI
//#define DEBUGAI
#ifdef DEBUGAI
#define DEBUGAIMSG(X) std::cerr<<"AIDEBUGMSG "<<std::setw(40)<<__FILE__<<":"<<std::setw(4)<<__LINE__<<": "<< X<<std::endl
#else
#define DEBUGAIMSG(X)
#endif
typedef struct
{
SOLDIERTYPE * pOpponent;
+12 -33
View File
@@ -63,8 +63,6 @@
#include "ModularizedTacticalAI/include/Plan.h"
#include "ModularizedTacticalAI/include/PlanFactoryLibrary.h"
#include "ModularizedTacticalAI/include/AbstractPlanFactory.h"
#include <stdexcept>
#include <iostream>
#ifdef JA2UB
#include "Ja25_Tactical.h"
@@ -500,19 +498,10 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named
gubAICounter++;
if(!pSoldier->ai_masterplan_) // if the Soldier has no plan, create one
{
if(pSoldier->bAIIndex == 0) // not yet initialized, use bTeam+1 as default
pSoldier->bAIIndex = pSoldier->bTeam + 1;
AI::tactical::AIInputData ai_input;
ai_input.npc_to_plan_for_ = pSoldier;
AI::tactical::PlanFactoryLibrary* plan_lib(AI::tactical::PlanFactoryLibrary::instance());
pSoldier->ai_masterplan_ = plan_lib->create_plan(pSoldier->bAIIndex, ai_input);
}
AI::tactical::PlanInputData plan_input;
plan_input.controlled_npc_ = pSoldier;
pSoldier->ai_masterplan_->execute(gfTurnBasedAI, plan_input);
if(gfTurnBasedAI)
TurnBasedHandleNPCAI(pSoldier);
else
RTHandleAI( pSoldier );
}
else
{
@@ -1445,26 +1434,16 @@ void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier)
{
if (!(gTacticalStatus.uiFlags & ENGAGED_IN_CONV))
{
#ifdef ENABLE_ZOMBIES
if ( pSoldier->IsZombie() )
{
pSoldier->aiData.bAction = ZombieDecideAction(pSoldier);
}
else if (CREATURE_OR_BLOODCAT( pSoldier ))
#else
if (CREATURE_OR_BLOODCAT( pSoldier ))
#endif
if(!pSoldier->ai_masterplan_) // if the Soldier has no plan, create one
{
pSoldier->aiData.bAction = CreatureDecideAction( pSoldier );
}
else if (pSoldier->ubBodyType == CROW)
{
pSoldier->aiData.bAction = CrowDecideAction( pSoldier );
}
else
{
pSoldier->aiData.bAction = DecideAction(pSoldier);
if(pSoldier->bAIIndex == 0) // not yet initialized, use bTeam+1 as default
pSoldier->bAIIndex = pSoldier->bTeam + 1;
AI::tactical::AIInputData ai_input;
AI::tactical::PlanFactoryLibrary* plan_lib(AI::tactical::PlanFactoryLibrary::instance());
pSoldier->ai_masterplan_ = plan_lib->create_plan(pSoldier->bAIIndex, pSoldier, ai_input);
}
AI::tactical::PlanInputData plan_input(true, gTacticalStatus);
pSoldier->ai_masterplan_->execute(plan_input);
}
}
-88
View File
@@ -1670,91 +1670,3 @@ void CreatureDecideAlertStatus( SOLDIERTYPE *pSoldier )
}
}
INT8 CrowDecideActionRed( SOLDIERTYPE * pSoldier )
{
// OK, Fly away!
//HandleCrowFlyAway( pSoldier );
if (!gfTurnBasedAI)
{
pSoldier->aiData.usActionData = 30000;
return( AI_ACTION_WAIT );
}
else
{
return( AI_ACTION_NONE );
}
}
INT8 CrowDecideActionGreen( SOLDIERTYPE * pSoldier )
{
INT32 sCorpseGridNo;
UINT8 ubDirection;
INT16 sFacingDir;
// Look for a corse!
sCorpseGridNo = FindNearestRottingCorpse( pSoldier );
if (!TileIsOutOfBounds(sCorpseGridNo))
{
// Are we close, if so , peck!
if ( SpacesAway( pSoldier->sGridNo, sCorpseGridNo ) < 2 )
{
// Change facing
sFacingDir = GetDirectionFromGridNo( sCorpseGridNo, pSoldier );
if ( sFacingDir != pSoldier->ubDirection )
{
pSoldier->aiData.usActionData = sFacingDir;
return(AI_ACTION_CHANGE_FACING);
}
else if (!gfTurnBasedAI)
{
pSoldier->aiData.usActionData = 30000;
return( AI_ACTION_WAIT );
}
else
{
return( AI_ACTION_NONE );
}
}
else
{
// Walk to nearest one!
pSoldier->aiData.usActionData = FindGridNoFromSweetSpot( pSoldier, sCorpseGridNo, 4, &ubDirection );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
return( AI_ACTION_GET_CLOSER );
}
}
}
return( AI_ACTION_NONE );
}
INT8 CrowDecideAction( SOLDIERTYPE * pSoldier )
{
if ( pSoldier->usAnimState == CROW_FLY )
{
return( AI_ACTION_NONE );
}
switch( pSoldier->aiData.bAlertStatus )
{
case STATUS_GREEN:
case STATUS_YELLOW:
return( CrowDecideActionGreen( pSoldier ) );
case STATUS_RED:
case STATUS_BLACK:
return( CrowDecideActionRed( pSoldier ) );
default:
Assert( FALSE );
return( AI_ACTION_NONE );
}
}
-157
View File
@@ -5766,163 +5766,6 @@ INT16 ubMinAPCost;
}
INT8 DecideAction(SOLDIERTYPE *pSoldier)
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"DecideAction");
INT8 bAction=AI_ACTION_NONE;
#ifdef DEBUGDECISIONS
STR16 tempstr;
#endif
#ifdef AI_TIMING_TESTS
UINT32 uiStartTime, uiEndTime;
#endif
if ( pSoldier->bTeam != MILITIA_TEAM )
{
if ( !sniperwarning && pSoldier->aiData.bOrders == SNIPER )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_WATHCHOUTFORSNIPERS] );
sniperwarning = TRUE;
}
if (!biggunwarning && FindRocketLauncherOrCannon(pSoldier) != NO_SLOT )
{
biggunwarning = TRUE;
//TODO: don't say this again after reloading a savegame
SayQuoteFromAnyBodyInSector( QUOTE_WEARY_SLASH_SUSPUCIOUS );
}
}
// turn off cautious flag
pSoldier->aiData.fAIFlags &= (~AI_CAUTIOUS);
//reset flank count
//NumMessage("DecideAction - Guy#",pSoldier->ubID);
// if the NPC is being "ESCORTED" (seen civilians only for now)
if (pSoldier->aiData.bUnderEscort)
{
#ifdef DEBUGDECISIONS
AIPopMessage("AlertStatus = ESCORT");
#endif
//bAction = DecideActionEscort(pSoldier);
}
else // "normal" NPC AI
{
// if status over-ride is set, bypass RED/YELLOW and go directly to GREEN!
if ((pSoldier->aiData.bBypassToGreen) && (pSoldier->aiData.bAlertStatus < STATUS_BLACK))
{
bAction = DecideActionGreen(pSoldier);
if ( !gfTurnBasedAI )
{
// reset bypass now
pSoldier->aiData.bBypassToGreen = 0;
}
}
else
{
switch (pSoldier->aiData.bAlertStatus)
{
case STATUS_GREEN:
#ifdef DEBUGDECISIONS
AIPopMessage("AlertStatus = GREEN");
#endif
#ifdef AI_TIMING_TESTS
uiStartTime = GetJA2Clock();
#endif
bAction = DecideActionGreen(pSoldier);
#ifdef AI_TIMING_TESTS
uiEndTime = GetJA2Clock();
guiGreenTimeTotal += (uiEndTime - uiStartTime);
guiGreenCounter++;
#endif
break;
case STATUS_YELLOW:
#ifdef DEBUGDECISIONS
AIPopMessage("AlertStatus = YELLOW");
#endif
#ifdef AI_TIMING_TESTS
uiStartTime = GetJA2Clock();
#endif
bAction = DecideActionYellow(pSoldier);
#ifdef AI_TIMING_TESTS
uiEndTime = GetJA2Clock();
guiYellowTimeTotal += (uiEndTime - uiStartTime);
guiYellowCounter++;
#endif
break;
case STATUS_RED:
#ifdef DEBUGDECISIONS
AIPopMessage("AlertStatus = RED");
#endif
#ifdef AI_TIMING_TESTS
uiStartTime = GetJA2Clock();
#endif
bAction = DecideActionRed(pSoldier,TRUE);
#ifdef AI_TIMING_TESTS
uiEndTime = GetJA2Clock();
guiRedTimeTotal += (uiEndTime - uiStartTime);
guiRedCounter++;
#endif
break;
case STATUS_BLACK:
#ifdef DEBUGDECISIONS
AIPopMessage("AlertStatus = BLACK");
#endif
#ifdef AI_TIMING_TESTS
uiStartTime = GetJA2Clock();
#endif
bAction = DecideActionBlack(pSoldier);
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("DecideActionBlack=%d",bAction));
#ifdef AI_TIMING_TESTS
uiEndTime = GetJA2Clock();
guiBlackTimeTotal += (uiEndTime - uiStartTime);
guiBlackCounter++;
#endif
break;
}
}
}
#ifdef DEBUGDECISIONS
sprintf( tempstr,"DecideAction: selected action %d, actionData %d\n\n",bAction,pSoldier->aiData.usActionData);
DebugAI( tempstr );
#endif
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"DecideAction done");
return(bAction);
}
INT8 DecideActionEscort(SOLDIERTYPE *pSoldier)
{
#ifdef DEBUGDECISIONS
STR16 tempstr;
#endif
// if he has a place to go, and isn't already there... go!
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData) && (pSoldier->sGridNo != pSoldier->aiData.usActionData))
{
#ifdef DEBUGDECISIONS
sprintf(tempstr,"%s - ESCORTED NPC GOING to grid %d",pSoldier->name,pSoldier->aiData.usActionData);
AIPopMessage(tempstr);
#endif
return(AI_ACTION_ESCORTED_MOVE);
}
else
return(AI_ACTION_NONE);
}
void DecideAlertStatus( SOLDIERTYPE *pSoldier )
{
#ifdef DEBUGDECISIONS
+14 -65
View File
@@ -19,71 +19,11 @@
#include "Quests.h"
#include "GameSettings.h"
#endif
// needed to use the modularized tactical AI:
#include "ModularizedTacticalAI/include/Plan.h"
#include "ModularizedTacticalAI/include/PlanFactoryLibrary.h"
#include "ModularizedTacticalAI/include/AbstractPlanFactory.h"
INT8 RTPlayerDecideAction( SOLDIERTYPE * pSoldier )
{
INT8 bAction=AI_ACTION_NONE;
if (gTacticalStatus.fAutoBandageMode)
{
bAction = DecideAutoBandage( pSoldier );
}
#ifdef ENABLE_ZOMBIES
else if ( pSoldier->IsZombie() )
{
bAction = ZombieDecideAction( pSoldier );
}
#endif
else
{
bAction = DecideAction( pSoldier );
}
#ifdef DEBUGDECISIONS
STR tempstr;
sprintf(tempstr,"DecideAction: selected action %d, actionData %d\n\n",bAction,pSoldier->aiData.usActionData);
DebugAI( tempstr );
#endif
return(bAction);
}
INT8 RTDecideAction(SOLDIERTYPE *pSoldier)
{
if (CREATURE_OR_BLOODCAT( pSoldier ) )
{
return( CreatureDecideAction( pSoldier ) );
}
#ifdef ENABLE_ZOMBIES
else if ( pSoldier->IsZombie() )
{
return( ZombieDecideAction( pSoldier ) );
}
#endif
else if (pSoldier->ubBodyType == CROW)
{
return( CrowDecideAction( pSoldier ) );
}
else if (pSoldier->bTeam == gbPlayerNum)
{
return( RTPlayerDecideAction( pSoldier ) );
}
else
{
// handle traversal
if ( (pSoldier->ubProfile != NO_PROFILE) && (gMercProfiles[ pSoldier->ubProfile ].ubMiscFlags3 & PROFILE_MISC_FLAG3_HANDLE_DONE_TRAVERSAL ) )
{
TriggerNPCWithGivenApproach( pSoldier->ubProfile, APPROACH_DONE_TRAVERSAL, FALSE );
gMercProfiles[ pSoldier->ubProfile ].ubMiscFlags3 &= (~PROFILE_MISC_FLAG3_HANDLE_DONE_TRAVERSAL);
pSoldier->ubQuoteActionID = 0;
// wait a tiny bit
pSoldier->aiData.usActionData = 100;
return( AI_ACTION_WAIT );
}
return( DecideAction( pSoldier ) );
}
}
UINT16 RealtimeDelay( SOLDIERTYPE * pSoldier )
{
@@ -236,7 +176,16 @@ void RTHandleAI( SOLDIERTYPE * pSoldier )
{
if (!(gTacticalStatus.uiFlags & ENGAGED_IN_CONV))
{
pSoldier->aiData.bAction = RTDecideAction( pSoldier );
if(!pSoldier->ai_masterplan_) // if the Soldier has no plan, create one
{
if(pSoldier->bAIIndex == 0) // not yet initialized, use bTeam+1 as default
pSoldier->bAIIndex = pSoldier->bTeam + 1;
AI::tactical::AIInputData ai_input;
AI::tactical::PlanFactoryLibrary* plan_lib(AI::tactical::PlanFactoryLibrary::instance());
pSoldier->ai_masterplan_ = plan_lib->create_plan(pSoldier->bAIIndex, pSoldier, ai_input);
}
AI::tactical::PlanInputData plan_input(false, gTacticalStatus);
pSoldier->ai_masterplan_->execute(plan_input);
}
}
}