src/tron/gAIBase.cpp File Reference

#include "gAIBase.h"
#include "gArena.h"
#include "eGrid.h"
#include "ePath.h"
#include "eGameObject.h"
#include "gWall.h"
#include "gSensor.h"
#include "gCycle.h"
#include "tConsole.h"
#include "rFont.h"
#include "rScreen.h"
#include "eFloor.h"
#include "eDebugLine.h"
#include "gAICharacter.h"
#include "tReferenceHolder.h"
#include "tRandom.h"
#include "tRecorder.h"
#include <stdlib.h>
#include <cstdlib>
#include <memory>

Include dependency graph for gAIBase.cpp:

Go to the source code of this file.

Classes

class  gRandomController
class  gCycleTouchEvent
class  gCycleMemoryEntry
class  gLoopData
class  gHitData
class  gAISensor
class  gAILogEntry
class  gAILog

Defines

#define AI_REACTION   0
#define AI_EMERGENCY   1
#define AI_RANGE   2
#define AI_STATE_TRACE   3
#define AI_STATE_CLOSECOMBAT   4
#define AI_STATE_PATH   5
#define AI_LOOP   6
#define AI_ENEMY   7
#define AI_TUNNEL   8
#define AI_DETECTTRACE   9
#define AI_STARTSTATE   10
#define AI_STARTSTRAIGHT   11
#define AI_STATECHANGE   12
#define TOL   4
#define MAXAI_COLOR   13
#define REACTION   .2
#define DANGERLEVELS   4
#define LOOPLEVEL   0
#define SPACELEVEL   1
#define TRAPLEVEL   2
#define COLIDELEVEL   2
#define TEAMLEVEL   3
#define ENTRIES   10

Functions

static tCONTROLLED_PTR (gAITeam) sg_AITeam
static gAITeamAITeam ()
static void ClearAITeam ()
REAL Random ()
static REAL Delay ()
static gAICharacterBestIQ (int iq)
static bool CheckLoop (const gCycle *a, const gCycle *b, REAL bDist, int bSide, int dir, tArray< const gCycle * > &closedIn, int &winding, REAL aEndDist=0, int aEndSides=3, int aEndDir=1)
static bool IsTrapped (const gCycle *trapped, const gCycle *other)
static void CycleBlocksWayHelper (const gCycle *a, const gCycle *b, int aDir, int bDir, REAL aDist, REAL bDist, int winding)
static gAISensorsg_GetSensor (int currentDirectionNumber, gCycle const &object, int turn, REAL side, REAL range, REAL corridor, REAL &mindist)
std::ostream & operator<< (std::ostream &s, gAIPlayer::ThinkDataBase const &data)
std::istream & operator>> (std::istream &s, gAIPlayer::ThinkDataBase &data)

Variables

static tReferenceHolder
< gAIPlayer
sg_AIReferences
static nNOInitialisator< gAITeamgAITeam_init (331,"gAITeam")
static int current_ai
static REAL rgb_ai [MAXAI_COLOR][3]
static nNOInitialisator
< gAIPlayer
gAIPlayer_init (330,"gAIPlayer")
static char const * section = "AI"
const REAL relax = 25


Define Documentation

#define AI_DETECTTRACE   9

Definition at line 58 of file gAIBase.cpp.

Referenced by gAIPlayer::CycleBlocksWay().

#define AI_EMERGENCY   1

Definition at line 50 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive(), and gAIPlayer::RightBeforeDeath().

#define AI_ENEMY   7

Definition at line 56 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive().

#define AI_LOOP   6

Definition at line 55 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive(), and gAISensor::gAISensor().

#define AI_RANGE   2

Definition at line 51 of file gAIBase.cpp.

Referenced by gAISensor::gAISensor().

#define AI_REACTION   0

Definition at line 49 of file gAIBase.cpp.

Referenced by gAIPlayer::Timestep().

#define AI_STARTSTATE   10

Definition at line 59 of file gAIBase.cpp.

Referenced by gAIPlayer::NewObject().

#define AI_STARTSTRAIGHT   11

Definition at line 60 of file gAIBase.cpp.

Referenced by gAIPlayer::NewObject().

#define AI_STATE_CLOSECOMBAT   4

Definition at line 53 of file gAIBase.cpp.

Referenced by gAIPlayer::SwitchToState().

#define AI_STATE_PATH   5

Definition at line 54 of file gAIBase.cpp.

Referenced by gAIPlayer::SwitchToState().

#define AI_STATE_TRACE   3

Definition at line 52 of file gAIBase.cpp.

Referenced by gAIPlayer::SwitchToState().

#define AI_STATECHANGE   12

Definition at line 61 of file gAIBase.cpp.

Referenced by gAIPlayer::NewObject().

#define AI_TUNNEL   8

Definition at line 57 of file gAIBase.cpp.

Referenced by gAISensor::gAISensor().

#define COLIDELEVEL   2

Definition at line 1950 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive().

#define DANGERLEVELS   4

Definition at line 1946 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive(), and gAILog::Print().

#define ENTRIES   10

Definition at line 1963 of file gAIBase.cpp.

Referenced by gAILog::NextEntry().

#define LOOPLEVEL   0

Definition at line 1947 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive().

#define MAXAI_COLOR   13

Definition at line 1060 of file gAIBase.cpp.

Referenced by gAIPlayer::gAIPlayer().

#define REACTION   .2

Referenced by gAIPlayer::ThinkCloseCombat().

#define SPACELEVEL   1

Definition at line 1948 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive().

#define TEAMLEVEL   3

Definition at line 1951 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive().

#define TOL   4

Definition at line 371 of file gAIBase.cpp.

Referenced by CheckLoop(), and gAIPlayer::EmergencySurvive().

#define TRAPLEVEL   2

Definition at line 1949 of file gAIBase.cpp.

Referenced by gAIPlayer::EmergencySurvive().


Function Documentation

static gAITeam* AITeam (  )  [static]

Definition at line 98 of file gAIBase.cpp.

References tNEW.

Referenced by gAIPlayer::ClearAll(), and gAIPlayer::SetNumberOfAIs().

00099 {
00100     if ( !sg_AITeam )
00101     {
00102         sg_AITeam = tNEW( gAITeam );
00103     }
00104 
00105     return sg_AITeam;
00106 }

Here is the caller graph for this function:

static gAICharacter* BestIQ ( int  iq  )  [static]

Definition at line 162 of file gAIBase.cpp.

References ai, gAIPlayer::Character(), gAICharacter::iq, GrowingArrayBase::Len(), tListItemBase::Len(), gAICharacter::s_Characters, and se_PlayerNetIDs.

Referenced by gAITeam::BalanceWithAIs(), and gAIPlayer::SetNumberOfAIs().

00163 {
00164     int i;
00165 
00166     static tArray<bool> inGame(gAICharacter::s_Characters.Len());
00167     for (i = gAICharacter::s_Characters.Len()-1; i>=0; i--)
00168         inGame(i) = false;
00169 
00170     for (i = se_PlayerNetIDs.Len()-1; i>=0; i--)
00171     {
00172         // count the active AIs
00173         ePlayerNetID *p = se_PlayerNetIDs(i);
00174         gAIPlayer  *ai  = dynamic_cast<gAIPlayer*>(p);
00175         if (ai && ai->Character() )
00176         {
00177             int index = ai->Character() - &(gAICharacter::s_Characters(0));
00178             inGame(index) = true;
00179         }
00180     }
00181 
00182     // find the best fitting IQ that could be inserted:
00183     gAICharacter* bestIQ = 0;
00184     for (i = gAICharacter::s_Characters.Len()-1; i>=0; i--)
00185         if (!inGame(i))
00186             if (!bestIQ || fabs(bestIQ->iq - iq) > fabs(gAICharacter::s_Characters(i).iq - iq))
00187                 bestIQ = &gAICharacter::s_Characters(i);
00188 
00189     return bestIQ;
00190 }

Here is the call graph for this function:

Here is the caller graph for this function:

static bool CheckLoop ( const gCycle a,
const gCycle b,
REAL  bDist,
int  bSide,
int  dir,
tArray< const gCycle * > &  closedIn,
int &  winding,
REAL  aEndDist = 0,
int  aEndSides = 3,
int  aEndDir = 1 
) [static]

Definition at line 384 of file gAIBase.cpp.

References gCycleMemoryEntry::cycle, gCycleTouchEvent::dist, gCycleMemory::Earliest(), gCycleMovement::GetDistance(), eGameObject::Grid(), gCycleMemory::Latest(), GrowingArrayBase::Len(), gCycleMemoryEntry::max, gCycle::memory, gCycleMemoryEntry::min, gCycleTouchEvent::otherDist, gCycleTouchEvent::otherSide, REAL, tASSERT, TOL, gCycleTouchEvent::winding, and eGrid::WindingNumber().

Referenced by gAISensor::DetectLoop(), gAIPlayer::EmergencySurvive(), and IsTrapped().

00388 {
00389     tASSERT(0<= bSide && 1 >= bSide);
00390     tASSERT(0<= dir && 1 >= dir);
00391 
00392     int tries = 10;       // so long until we give up
00393     int ends  = 0;
00394 
00395     bool bClosedIn    = false;
00396 
00397     const gCycle *run = b;      // we run along this cycle's wall
00398     int end           = dir;    // and move towards this end its wall wall
00399     int side          = bSide;  // we are on this side of the cycle
00400     REAL dist         = bDist;  // and are at this distance.
00401     winding           = 0;      // the winding number we collected
00402 
00403     int turn     = a->Grid()->WindingNumber();
00404     int halfTurn = turn >> 1;
00405 
00406 
00407 #ifdef DEBUG
00408     //  con << "\n";
00409 #endif
00410 
00411     while(tries-- > 0 && run &&
00412             !(run == a &&
00413               end == aEndDir &&
00414               aEndSides & (1 << side) &&
00415               (end > 0 ? dist >= aEndDist : dist <= aEndDist ) ) )
00416     {
00417 #ifdef DEBUG
00418         //      con << "end = " << end << ", side = " << side << ", dist = " << dist
00419         //        << ", winding = " << winding << "\n";
00420 #endif
00421         if (end > 0)
00422         {
00423 
00424             // find the last connection
00425             gCycleMemoryEntry* last = run->memory.Latest(side);
00426             if (!last || last->max[side].dist <= dist + TOL)
00427             {
00428                 // no interference. We can move directly around the cylce
00429                 // and close it in.
00430 #ifdef DEBUG
00431                 //            con << "Turning around...\n";
00432 #endif
00433 
00434                 winding += halfTurn *
00435                            ( side > 0 ? -1 : 1);
00436 
00437                 end  = 0;
00438                 side = 1-side;
00439                 closedIn[closedIn.Len()] = run;
00440                 dist = run->GetDistance();
00441 
00442                 // detect early loop
00443                 if (run == b)
00444                     if (bClosedIn)
00445                     {
00446                         winding = 0;
00447                         return false;
00448                     }
00449                     else
00450                         bClosedIn = true;
00451             }
00452             else
00453             {
00454 #ifdef DEBUG
00455                 //            con << "Crossing...\n";
00456 #endif
00457 
00458                 // find the first connection
00459                 gCycleMemoryEntry* first = run->memory.Earliest(side);
00460                 if (first && first->min[side].dist >= dist + TOL)
00461                 {
00462                     // we cross the connection:
00463                     winding += first->min[side].winding;
00464                     run      = first->cycle;
00465                     end      = (side == first->min[side].otherSide) ? 1 : 0;
00466 
00467                     //            if (end == 0)
00468                     // we need to turn around to follow
00469                     winding += halfTurn * (side > 0 ? 1 : -1);
00470 
00471                     dist     = first->min[side].otherDist;
00472                     side     = first->min[side].otherSide;
00473                 }
00474                 else
00475                 {
00476                     winding = 0;
00477                     return false;
00478                 }
00479             }
00480         }
00481         else // dir = -1, we move towards the end
00482         {
00483             // find the first connection
00484             gCycleMemoryEntry* first = run->memory.Earliest(side);
00485             if (!first || first->min[side].dist >= dist - TOL)
00486             {
00487 #ifdef DEBUG
00488                 //            con << "Turning around...\n";
00489 #endif
00490 
00491 
00492                 // no interference. We can move directly around the cylce's end.
00493                 winding += halfTurn * ( side > 0 ? 1 : -1);
00494 
00495                 end  = 1;
00496                 side = 1-side;
00497                 ends++;
00498                 dist = -2 * TOL;
00499             }
00500             else
00501             {
00502 #ifdef DEBUG
00503                 //            con << "Crossing...\n";
00504 #endif
00505 
00506 
00507                 // find the latest connection
00508                 gCycleMemoryEntry* last = run->memory.Latest(side);
00509                 if (last && last->max[side].dist <= dist - TOL)
00510                 {
00511                     // we cross the connection:
00512                     winding += last->max[side].winding;
00513 
00514                     // we need to turn around to start:
00515                     winding += halfTurn * (side > 0 ? -1 : 1);
00516 
00517                     run      = last->cycle;
00518                     end      = (side == last->max[side].otherSide) ? 0 : 1;
00519 
00520                     //            if (end == 1)
00521                     // we need to turn around to follow
00522                     //            winding -= halfTurn * (side > 0 ? 1 : -1);
00523 
00524                     dist     = last->max[side].otherDist;
00525                     side     = last->max[side].otherSide;
00526                 }
00527                 else
00528                     // uh oh. we are already closed in. No chance...
00529                 {
00530                     winding = 0;
00531                     return false;
00532                 }
00533             }
00534         }
00535     }
00536 
00537 #ifdef DEBUG
00538     //      con << "end = " << end << ", side = " << side << ", dist = " << dist
00539     //    << ", winding = " << winding << "\n\n";
00540 #endif
00541 
00542     if (tries >= 0)
00543     {
00544         return true;
00545     }
00546     else
00547     {
00548         winding = 0;
00549         return false;
00550     }
00551 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void ClearAITeam (  )  [static]

Definition at line 108 of file gAIBase.cpp.

References NULL.

Referenced by gAIPlayer::ClearAll(), and gAIPlayer::SetNumberOfAIs().

00109 {
00110     sg_AITeam = NULL;
00111 }

Here is the caller graph for this function:

static void CycleBlocksWayHelper ( const gCycle a,
const gCycle b,
int  aDir,
int  bDir,
REAL  aDist,
REAL  bDist,
int  winding 
) [static]

Definition at line 951 of file gAIBase.cpp.

References gCycleTouchEvent::dist, gCycleMemoryEntry::max, gCycle::memory, gCycleMemoryEntry::min, gCycleTouchEvent::otherDist, gCycleTouchEvent::otherSide, and gCycleTouchEvent::winding.

Referenced by gAIPlayer::CycleBlocksWay().

00953 {
00954     gCycleMemoryEntry* aEntry = (const_cast<gCycleMemory&>(a->memory)).Remember(b);
00955 
00956     if (aDist > aEntry->max[aDir].dist)
00957     {
00958         aEntry->max[aDir].dist      = aDist;
00959         aEntry->max[aDir].otherSide = bDir;
00960         aEntry->max[aDir].otherDist = bDist;
00961         aEntry->max[aDir].winding   = winding;
00962     }
00963 
00964     if (aDist < aEntry->min[aDir].dist)
00965     {
00966         aEntry->min[aDir].dist      = aDist;
00967         aEntry->min[aDir].otherSide = bDir;
00968         aEntry->min[aDir].otherDist = bDist;
00969         aEntry->min[aDir].winding   = winding;
00970     }
00971 }

Here is the caller graph for this function:

static REAL Delay (  )  [static]

Definition at line 149 of file gAIBase.cpp.

References fd, REAL, se_AverageFrameTime(), and sg_delayCycle.

Referenced by gAIPlayer::EmergencySurvive(), gAIPlayer::RightBeforeDeath(), sg_GetSensor(), gAIPlayer::Think(), and gAIPlayer::ThinkTrace().

00150 {
00151     REAL delay = sg_delayCycle * .9f;
00152 
00153     REAL fd    = se_AverageFrameTime()*1.5f;
00154     if ( fd > delay)
00155         delay = fd;
00156 
00157     return delay;
00158 }

Here is the call graph for this function:

Here is the caller graph for this function:

static bool IsTrapped ( const gCycle trapped,
const gCycle other 
) [static]

Definition at line 555 of file gAIBase.cpp.

References CheckLoop(), gCycleMovement::GetDistance(), and GrowingArrayBase::Len().

Referenced by gAIPlayer::EmergencySurvive(), gAIPlayer::ThinkCloseCombat(), gAIPlayer::ThinkPath(), gAIPlayer::ThinkSurvive(), and gAIPlayer::ThinkTrace().

00556 {
00557     tArray<const gCycle*> closedIn;
00558     int winding = 0;
00559     if (CheckLoop(trapped, trapped, trapped->GetDistance(), 1, 0, closedIn, winding, trapped->GetDistance() - 1))
00560     {
00561         if (winding + 2 < 0)
00562         {
00563             // see if the other cylce is trapped with him
00564             for (int i = closedIn.Len()-1; i>=0; i--)
00565                 if (other == closedIn(i))
00566                     return false;  // we can get him!
00567 
00568             // no. trapped is trapped allone.
00569             return true;
00570         }
00571     }
00572 
00573     return false;
00574 }

Here is the call graph for this function:

Here is the caller graph for this function:

std::ostream& operator<< ( std::ostream &  s,
gAIPlayer::ThinkDataBase const &  data 
)

Definition at line 2874 of file gAIBase.cpp.

References gAIPlayer::ThinkDataBase::thinkAgain, and gAIPlayer::ThinkDataBase::turn.

02875 {
02876     s << data.turn << " " << data.thinkAgain;
02877 
02878     return s;
02879 }

std::istream& operator>> ( std::istream &  s,
gAIPlayer::ThinkDataBase data 
)

Definition at line 2881 of file gAIBase.cpp.

References gAIPlayer::ThinkDataBase::thinkAgain, and gAIPlayer::ThinkDataBase::turn.

02882 {
02883     s >> data.turn >> data.thinkAgain;
02884 
02885     return s;
02886 }

REAL Random (  ) 

Definition at line 135 of file gAIBase.cpp.

References tRandomizer::Get(), tRandomizer::GetInstance(), and gRandomController::randomizer_.

Referenced by gAISensor::gAISensor(), gAIPlayer::RightBeforeDeath(), gAIPlayer::SwitchToState(), gAIPlayer::ThinkCloseCombat(), and gAIPlayer::ThinkSurvive().

00136 {
00137     if ( gRandomController::random_ )
00138     {
00139         tRandomizer & randomizer = gRandomController::random_->randomizer_;
00140         return randomizer.Get();
00141     }
00142     else
00143     {
00144         tRandomizer & randomizer = tRandomizer::GetInstance();
00145         return randomizer.Get();
00146     }
00147 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gAISensor* sg_GetSensor ( int  currentDirectionNumber,
gCycle const &  object,
int  turn,
REAL  side,
REAL  range,
REAL  corridor,
REAL mindist 
) [static]

Definition at line 2677 of file gAIBase.cpp.

References Delay(), gAISensor::distance, eCoord, eGrid::GetDirection(), eGameObject::Position(), REAL, tNEW, and eGrid::Turn().

Referenced by gAIPlayer::Think().

02678 {
02679     // determine the current direction
02680     eGrid & grid = *object.Grid();
02681     eCoord origDir = grid.GetDirection( currentDirectionNumber );
02682 
02683     // determine sensors
02684     gAISensor * ret = 0;
02685 
02686     // turn direction
02687     int direction = currentDirectionNumber;
02688     int turns = 1;
02689     grid.Turn( direction, turn );
02690     eCoord dir = grid.GetDirection( direction );
02691     while ( !ret || ( turn * ( origDir * dir ) > .01 && currentDirectionNumber != direction ) )
02692     {
02693         // cast rays
02694         gAISensor * sensor = tNEW(gAISensor)(&object,object.Position(),dir, side, range, corridor*.5f, turn );
02695         if ( !ret || sensor->distance > ret->distance )
02696         {
02697             if ( ret )
02698             {
02699                 // calculate effective distance required to turn around in time
02700                 REAL dist = ret->distance - 1.2 * object.Speed() * Delay() * turns;
02701                 if ( mindist > dist )
02702                     mindist = dist;
02703             }
02704 
02705             delete ret;
02706             ret = sensor;
02707         }
02708         else
02709         {
02710             delete sensor;
02711         }
02712 
02713         // go on turning
02714         grid.Turn( direction, turn );
02715         dir = grid.GetDirection( direction );
02716         ++turns;
02717     }
02718 
02719     return ret;
02720 }

Here is the call graph for this function:

Here is the caller graph for this function:

static tCONTROLLED_PTR ( gAITeam   )  [static]


Variable Documentation

int current_ai [static]

Definition at line 1062 of file gAIBase.cpp.

nNOInitialisator<gAIPlayer> gAIPlayer_init(330,"gAIPlayer") [static]

Referenced by gAIPlayer::CreatorDescriptor().

nNOInitialisator<gAITeam> gAITeam_init(331,"gAITeam") [static]

Referenced by gAITeam::CreatorDescriptor().

const REAL relax = 25

Definition at line 2940 of file gAIBase.cpp.

Referenced by eCamera::Timestep().

REAL rgb_ai[MAXAI_COLOR][3] [static]

Initial value:

{
                                       {1,.2,.2},
                                       {.2,1,.2},
                                       {.2,.2,1},
                                       {1,1,.2},
                                       {1,.2,1},
                                       {.2,1,1},
                                       {1,.6,.2},
                                       {1,.2,.6},
                                       {.6,.2,1},
                                       {.2,.6,1},
                                       {1,1,1},
                                       {.2,.2,.2},
                                       {.5,.5,.5}
                                   }

Definition at line 1063 of file gAIBase.cpp.

char const* section = "AI" [static]

Definition at line 2888 of file gAIBase.cpp.

Referenced by ANET_Error(), ANET_GetHostList(), nAddress::GetHostname(), eTimer::IsSynced(), nServerInfo::Load(), login_accept_handler(), PasswordCallback(), se_SmoothTime(), nBasicNetworkSystem::Select(), nAddress::SetHostname(), sg_ArchiveCoord(), sg_ArchiveReal(), and nSocket::Write().

tReferenceHolder< gAIPlayer > sg_AIReferences [static]

Definition at line 63 of file gAIBase.cpp.


Generated on Sat Mar 15 23:14:24 2008 for Armagetron Advanced by  doxygen 1.5.4