📄 be_ai_goal.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_ai_goal.c
*
* desc: goal AI
*
* $Archive: /MissionPack/code/botlib/be_ai_goal.c $
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_utils.h"
#include "l_libvar.h"
#include "l_memory.h"
#include "l_log.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_ai_weight.h"
#include "../game/be_ai_goal.h"
#include "../game/be_ai_move.h"
//#define DEBUG_AI_GOAL
#ifdef RANDOMIZE
#define UNDECIDEDFUZZY
#endif //RANDOMIZE
#define DROPPEDWEIGHT
//minimum avoid goal time
#define AVOID_MINIMUM_TIME 10
//default avoid goal time
#define AVOID_DEFAULT_TIME 30
//avoid dropped goal time
#define AVOID_DROPPED_TIME 10
//
#define TRAVELTIME_SCALE 0.01
//item flags
#define IFL_NOTFREE 1 //not in free for all
#define IFL_NOTTEAM 2 //not in team play
#define IFL_NOTSINGLE 4 //not in single player
#define IFL_NOTBOT 8 //bot should never go for this
#define IFL_ROAM 16 //bot roam goal
//location in the map "target_location"
typedef struct maplocation_s
{
vec3_t origin;
int areanum;
char name[MAX_EPAIRKEY];
struct maplocation_s *next;
} maplocation_t;
//camp spots "info_camp"
typedef struct campspot_s
{
vec3_t origin;
int areanum;
char name[MAX_EPAIRKEY];
float range;
float weight;
float wait;
float random;
struct campspot_s *next;
} campspot_t;
//FIXME: these are game specific
typedef enum {
GT_FFA, // free for all
GT_TOURNAMENT, // one on one tournament
GT_SINGLE_PLAYER, // single player tournament
//-- team games go after this --
GT_TEAM, // team deathmatch
GT_CTF, // capture the flag
#ifdef MISSIONPACK
GT_1FCTF,
GT_OBELISK,
GT_HARVESTER,
#endif
GT_MAX_GAME_TYPE
} gametype_t;
typedef struct levelitem_s
{
int number; //number of the level item
int iteminfo; //index into the item info
int flags; //item flags
float weight; //fixed roam weight
vec3_t origin; //origin of the item
int goalareanum; //area the item is in
vec3_t goalorigin; //goal origin within the area
int entitynum; //entity number
float timeout; //item is removed after this time
struct levelitem_s *prev, *next;
} levelitem_t;
typedef struct iteminfo_s
{
char classname[32]; //classname of the item
char name[MAX_STRINGFIELD]; //name of the item
char model[MAX_STRINGFIELD]; //model of the item
int modelindex; //model index
int type; //item type
int index; //index in the inventory
float respawntime; //respawn time
vec3_t mins; //mins of the item
vec3_t maxs; //maxs of the item
int number; //number of the item info
} iteminfo_t;
#define ITEMINFO_OFS(x) (int)&(((iteminfo_t *)0)->x)
fielddef_t iteminfo_fields[] =
{
{"name", ITEMINFO_OFS(name), FT_STRING},
{"model", ITEMINFO_OFS(model), FT_STRING},
{"modelindex", ITEMINFO_OFS(modelindex), FT_INT},
{"type", ITEMINFO_OFS(type), FT_INT},
{"index", ITEMINFO_OFS(index), FT_INT},
{"respawntime", ITEMINFO_OFS(respawntime), FT_FLOAT},
{"mins", ITEMINFO_OFS(mins), FT_FLOAT|FT_ARRAY, 3},
{"maxs", ITEMINFO_OFS(maxs), FT_FLOAT|FT_ARRAY, 3},
{0, 0, 0}
};
structdef_t iteminfo_struct =
{
sizeof(iteminfo_t), iteminfo_fields
};
typedef struct itemconfig_s
{
int numiteminfo;
iteminfo_t *iteminfo;
} itemconfig_t;
//goal state
typedef struct bot_goalstate_s
{
struct weightconfig_s *itemweightconfig; //weight config
int *itemweightindex; //index from item to weight
//
int client; //client using this goal state
int lastreachabilityarea; //last area with reachabilities the bot was in
//
bot_goal_t goalstack[MAX_GOALSTACK]; //goal stack
int goalstacktop; //the top of the goal stack
//
int avoidgoals[MAX_AVOIDGOALS]; //goals to avoid
float avoidgoaltimes[MAX_AVOIDGOALS]; //times to avoid the goals
} bot_goalstate_t;
bot_goalstate_t *botgoalstates[MAX_CLIENTS + 1]; // bk001206 - FIXME: init?
//item configuration
itemconfig_t *itemconfig = NULL; // bk001206 - init
//level items
levelitem_t *levelitemheap = NULL; // bk001206 - init
levelitem_t *freelevelitems = NULL; // bk001206 - init
levelitem_t *levelitems = NULL; // bk001206 - init
int numlevelitems = 0;
//map locations
maplocation_t *maplocations = NULL; // bk001206 - init
//camp spots
campspot_t *campspots = NULL; // bk001206 - init
//the game type
int g_gametype = 0; // bk001206 - init
//additional dropped item weight
libvar_t *droppedweight = NULL; // bk001206 - init
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
bot_goalstate_t *BotGoalStateFromHandle(int handle)
{
if (handle <= 0 || handle > MAX_CLIENTS)
{
botimport.Print(PRT_FATAL, "goal state handle %d out of range\n", handle);
return NULL;
} //end if
if (!botgoalstates[handle])
{
botimport.Print(PRT_FATAL, "invalid goal state %d\n", handle);
return NULL;
} //end if
return botgoalstates[handle];
} //end of the function BotGoalStateFromHandle
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotInterbreedGoalFuzzyLogic(int parent1, int parent2, int child)
{
bot_goalstate_t *p1, *p2, *c;
p1 = BotGoalStateFromHandle(parent1);
p2 = BotGoalStateFromHandle(parent2);
c = BotGoalStateFromHandle(child);
InterbreedWeightConfigs(p1->itemweightconfig, p2->itemweightconfig,
c->itemweightconfig);
} //end of the function BotInterbreedingGoalFuzzyLogic
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotSaveGoalFuzzyLogic(int goalstate, char *filename)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
//WriteWeightConfig(filename, gs->itemweightconfig);
} //end of the function BotSaveGoalFuzzyLogic
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotMutateGoalFuzzyLogic(int goalstate, float range)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
EvolveWeightConfig(gs->itemweightconfig);
} //end of the function BotMutateGoalFuzzyLogic
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
itemconfig_t *LoadItemConfig(char *filename)
{
int max_iteminfo;
token_t token;
char path[MAX_PATH];
source_t *source;
itemconfig_t *ic;
iteminfo_t *ii;
max_iteminfo = (int) LibVarValue("max_iteminfo", "256");
if (max_iteminfo < 0)
{
botimport.Print(PRT_ERROR, "max_iteminfo = %d\n", max_iteminfo);
max_iteminfo = 256;
LibVarSet( "max_iteminfo", "256" );
}
strncpy( path, filename, MAX_PATH );
PC_SetBaseFolder(BOTFILESBASEFOLDER);
source = LoadSourceFile( path );
if( !source ) {
botimport.Print( PRT_ERROR, "counldn't load %s\n", path );
return NULL;
} //end if
//initialize item config
ic = (itemconfig_t *) GetClearedHunkMemory(sizeof(itemconfig_t) +
max_iteminfo * sizeof(iteminfo_t));
ic->iteminfo = (iteminfo_t *) ((char *) ic + sizeof(itemconfig_t));
ic->numiteminfo = 0;
//parse the item config file
while(PC_ReadToken(source, &token))
{
if (!strcmp(token.string, "iteminfo"))
{
if (ic->numiteminfo >= max_iteminfo)
{
SourceError(source, "more than %d item info defined\n", max_iteminfo);
FreeMemory(ic);
FreeSource(source);
return NULL;
} //end if
ii = &ic->iteminfo[ic->numiteminfo];
Com_Memset(ii, 0, sizeof(iteminfo_t));
if (!PC_ExpectTokenType(source, TT_STRING, 0, &token))
{
FreeMemory(ic);
FreeMemory(source);
return NULL;
} //end if
StripDoubleQuotes(token.string);
strncpy(ii->classname, token.string, sizeof(ii->classname)-1);
if (!ReadStructure(source, &iteminfo_struct, (char *) ii))
{
FreeMemory(ic);
FreeSource(source);
return NULL;
} //end if
ii->number = ic->numiteminfo;
ic->numiteminfo++;
} //end if
else
{
SourceError(source, "unknown definition %s\n", token.string);
FreeMemory(ic);
FreeSource(source);
return NULL;
} //end else
} //end while
FreeSource(source);
//
if (!ic->numiteminfo) botimport.Print(PRT_WARNING, "no item info loaded\n");
botimport.Print(PRT_MESSAGE, "loaded %s\n", path);
return ic;
} //end of the function LoadItemConfig
//===========================================================================
// index to find the weight function of an iteminfo
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int *ItemWeightIndex(weightconfig_t *iwc, itemconfig_t *ic)
{
int *index, i;
//initialize item weight index
index = (int *) GetClearedMemory(sizeof(int) * ic->numiteminfo);
for (i = 0; i < ic->numiteminfo; i++)
{
index[i] = FindFuzzyWeight(iwc, ic->iteminfo[i].classname);
if (index[i] < 0)
{
Log_Write("item info %d \"%s\" has no fuzzy weight\r\n", i, ic->iteminfo[i].classname);
} //end if
} //end for
return index;
} //end of the function ItemWeightIndex
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void InitLevelItemHeap(void)
{
int i, max_levelitems;
if (levelitemheap) FreeMemory(levelitemheap);
max_levelitems = (int) LibVarValue("max_levelitems", "256");
levelitemheap = (levelitem_t *) GetClearedMemory(max_levelitems * sizeof(levelitem_t));
for (i = 0; i < max_levelitems-1; i++)
{
levelitemheap[i].next = &levelitemheap[i + 1];
} //end for
levelitemheap[max_levelitems-1].next = NULL;
//
freelevelitems = levelitemheap;
} //end of the function InitLevelItemHeap
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
levelitem_t *AllocLevelItem(void)
{
levelitem_t *li;
li = freelevelitems;
if (!li)
{
botimport.Print(PRT_FATAL, "out of level items\n");
return NULL;
} //end if
//
freelevelitems = freelevelitems->next;
Com_Memset(li, 0, sizeof(levelitem_t));
return li;
} //end of the function AllocLevelItem
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeLevelItem(levelitem_t *li)
{
li->next = freelevelitems;
freelevelitems = li;
} //end of the function FreeLevelItem
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AddLevelItemToList(levelitem_t *li)
{
if (levelitems) levelitems->prev = li;
li->prev = NULL;
li->next = levelitems;
levelitems = li;
} //end of the function AddLevelItemToList
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void RemoveLevelItemFromList(levelitem_t *li)
{
if (li->prev) li->prev->next = li->next;
else levelitems = li->next;
if (li->next) li->next->prev = li->prev;
} //end of the function RemoveLevelItemFromList
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotFreeInfoEntities(void)
{
maplocation_t *ml, *nextml;
campspot_t *cs, *nextcs;
for (ml = maplocations; ml; ml = nextml)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -