New unit cache.
This commit is contained in:
parent
4a4b5c6f3a
commit
991579cd81
8 changed files with 270 additions and 19 deletions
|
@ -51,7 +51,7 @@ OBJDIR=@OBJDIR@
|
|||
IFLAGS= -I$(TOPDIR)/src/include $(XIFLAGS) -I$(TOPDIR)/src/movie/vp31/include
|
||||
|
||||
CFLAGS=@PROFILE_CFLAGS@ @DEBUG_CFLAGS@ $(IFLAGS) \
|
||||
-DUNIT_ON_MAP -DUSE_LIBMODPLUG -DUSE_HP_FOR_XP -DMAP_REGIONS\
|
||||
-DUSE_LIBMODPLUG -DUSE_HP_FOR_XP -DMAP_REGIONS \
|
||||
@PROFILE_CFLAGS@ @DEBUG_CFLAGS@ @VIDEO_CFLAGS@ @BZ2_CFLAGS@ \
|
||||
@OGG_CFLAGS@ @MAD_CFLAGS@ @FLAC_CFLAGS@ @CDAUDIO_CFLAGS@ \
|
||||
@LUA_CFLAGS@ $(CCL) $(VERSION) $(COMP_CFLAGS) @SOUND_CFLAGS@ @PLATFORM@ \
|
||||
|
|
|
@ -80,6 +80,9 @@ global void HandleActionDie(Unit* unit)
|
|||
MapUnmarkUnitSight(unit);
|
||||
|
||||
unit->State = unit->Type->CorpseScript;
|
||||
|
||||
DebugCheck(unit->Type->TileWidth != unit->Type->CorpseType->TileWidth ||
|
||||
unit->Type->TileHeight != unit->Type->CorpseType->TileHeight);
|
||||
unit->Type = unit->Type->CorpseType;
|
||||
|
||||
CommandStopUnit(unit); // This clears all order queues
|
||||
|
|
|
@ -77,6 +77,9 @@ global void HandleActionUpgradeTo(Unit* unit)
|
|||
unit->HP += stats->HitPoints - unit->Type->Stats[player->Player].HitPoints;
|
||||
// don't have such unit now
|
||||
player->UnitTypesCount[unit->Type->Type]--;
|
||||
|
||||
DebugCheck(unit->Type->TileWidth != type->TileWidth ||
|
||||
unit->Type->TileHeight != type->TileHeight);
|
||||
unit->Type = type;
|
||||
unit->Stats = (UnitStats*)stats;
|
||||
// and we have new one...
|
||||
|
|
|
@ -217,6 +217,9 @@ typedef struct _map_field_ {
|
|||
#ifdef UNIT_ON_MAP
|
||||
Unit* UnitCache; /// An unit on the map field
|
||||
#endif
|
||||
#ifdef NEW_UNIT_CACHE
|
||||
UnitListItem* UnitCache; /// An unit on the map field
|
||||
#endif
|
||||
#ifdef HIERARCHIC_PATHFINDER
|
||||
unsigned short RegId; /// Region to which the field belongs
|
||||
// FIXME: Johns: this values can't be placed in the map field,
|
||||
|
|
|
@ -37,6 +37,12 @@
|
|||
== Config definitions
|
||||
============================================================================*/
|
||||
|
||||
// Unit On Map cache
|
||||
#define UNIT_ON_MAP
|
||||
|
||||
// New unit cache
|
||||
// #define NEW_UNIT_CACHE
|
||||
|
||||
//
|
||||
// Default speed for many things, set it higher for faster actions.
|
||||
//
|
||||
|
|
|
@ -391,7 +391,6 @@
|
|||
|
||||
typedef struct _unit_ Unit; /// unit itself
|
||||
typedef enum _unit_action_ UnitAction; /// all possible unit actions
|
||||
|
||||
struct _spell_type_; /// base structure of a spell type
|
||||
|
||||
/**
|
||||
|
@ -490,6 +489,15 @@ enum _directions_ {
|
|||
LookingNW =7*32, /// Unit looking north west
|
||||
};
|
||||
|
||||
|
||||
/// A linked list element.
|
||||
typedef struct _unit_list_item_ UnitListItem;
|
||||
struct _unit_list_item_ {
|
||||
Unit* Unit; /// Points to the unit it links
|
||||
UnitListItem* Prev; /// Previous item.
|
||||
UnitListItem* Next; /// Next item.
|
||||
};
|
||||
|
||||
#define NextDirection 32 /// Next direction N->NE->E...
|
||||
#define UnitNotSeen 0x7fffffff /// Unit not seen, used by Unit::SeenFrame
|
||||
|
||||
|
@ -498,16 +506,20 @@ struct _unit_ {
|
|||
// NOTE: int is faster than shorts
|
||||
int Refs; /// Reference counter
|
||||
int Slot; /// Assigned slot number
|
||||
Unit** UnitSlot; /// Slot pointer of Units
|
||||
Unit** PlayerSlot; /// Slot pointer of Player->Units
|
||||
Unit** UnitSlot; /// Slot pointer of Units
|
||||
Unit** PlayerSlot; /// Slot pointer of Player->Units
|
||||
|
||||
Unit* Next; /// Generic link pointer (on map)
|
||||
Unit* Next; /// Generic link pointer (on map)
|
||||
#ifdef NEW_UNIT_CACHE
|
||||
UnitListItem* CacheLinks; /// Link nodes for unit cache
|
||||
unsigned CacheLock : 1; /// Used to lock unit out of the cache.
|
||||
#endif
|
||||
|
||||
int InsideCount; /// Number of units inside.
|
||||
Unit* UnitInside; /// Pointer to one of the units inside.
|
||||
Unit* Container; /// Pointer to the unit containing it (or 0)
|
||||
Unit* NextContained; /// Next unit in the container.
|
||||
Unit* PrevContained; /// Previous unit in the container.
|
||||
Unit* UnitInside; /// Pointer to one of the units inside.
|
||||
Unit* Container; /// Pointer to the unit containing it (or 0)
|
||||
Unit* NextContained; /// Next unit in the container.
|
||||
Unit* PrevContained; /// Previous unit in the container.
|
||||
|
||||
int X; /// Map position X
|
||||
int Y; /// Map position Y
|
||||
|
|
|
@ -280,6 +280,12 @@ local Unit *AllocUnit(void)
|
|||
*/
|
||||
global void InitUnit(Unit* unit, UnitType* type)
|
||||
{
|
||||
#ifdef NEW_UNIT_CACHE
|
||||
int i;
|
||||
#endif
|
||||
|
||||
DebugCheck(!type);
|
||||
|
||||
// Refs need to be *increased* by 1, not *set* to 1, because if InitUnit()
|
||||
// is called from game loading code, Refs can already have a nonzero
|
||||
// value (thanks to forward references in the save file). Incrementing
|
||||
|
@ -300,6 +306,14 @@ global void InitUnit(Unit* unit, UnitType* type)
|
|||
// Initialise unit structure (must be zero filled!)
|
||||
//
|
||||
unit->Type = type;
|
||||
#ifdef NEW_UNIT_CACHE
|
||||
unit->CacheLinks = (UnitListItem *)malloc(type->TileWidth * type->TileHeight * sizeof(UnitListItem));
|
||||
for (i = 0; i < type->TileWidth * type->TileHeight; ++i) {
|
||||
unit->CacheLinks[i].Prev = unit->CacheLinks[i].Next = 0;
|
||||
unit->CacheLinks[i].Unit = unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
unit->Seen.Frame = UnitNotSeen; // Unit isn't yet seen
|
||||
|
||||
unit->Frame = unit->Type->Animations->Still[0].Frame +
|
||||
|
@ -2843,6 +2857,8 @@ global void LetUnitDie(Unit* unit)
|
|||
|
||||
if (type->CorpseType) {
|
||||
unit->State = unit->Type->CorpseScript;
|
||||
DebugCheck(type->TileWidth != type->CorpseType->TileWidth ||
|
||||
type->TileHeight != type->CorpseType->TileHeight);
|
||||
type = unit->Type = type->CorpseType;
|
||||
|
||||
unit->IX = (type->Width - VideoGraphicWidth(type->Sprite)) / 2;
|
||||
|
|
|
@ -43,19 +43,10 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
|
||||
#ifdef UNIT_ON_MAP
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include "unit.h"
|
||||
#include "map.h"
|
||||
|
||||
//*****************************************************************************
|
||||
// Convert calls to internal
|
||||
//****************************************************************************/
|
||||
#ifdef UNIT_ON_MAP
|
||||
|
||||
/**
|
||||
** Insert new unit into cache.
|
||||
|
@ -236,3 +227,220 @@ global void InitUnitCache(void)
|
|||
}
|
||||
|
||||
#endif // } UNIT_ON_MAP
|
||||
|
||||
#ifdef NEW_UNIT_CACHE
|
||||
|
||||
/**
|
||||
** Insert new unit into cache.
|
||||
**
|
||||
** @param unit Unit pointer to place in cache.
|
||||
*/
|
||||
global void UnitCacheInsert(Unit* unit)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
MapField* mf;
|
||||
UnitListItem* listitem;
|
||||
|
||||
DebugLevel3Fn("%d,%d %d %s\n" _C_ unit->X _C_ unit->Y _C_ unit->Slot _C_ unit->Type->Name);
|
||||
for (i = 0; i < unit->Type->TileHeight; ++i) {
|
||||
for (j = 0; j < unit->Type->TileWidth; ++j) {
|
||||
mf = TheMap.Fields + (i + unit->Y) * TheMap.Width + j + unit->X;
|
||||
listitem = unit->CacheLinks + i * unit->Type->TileWidth + j;
|
||||
|
||||
// Always add at the start of the list.
|
||||
listitem->Next = mf->UnitCache;
|
||||
listitem->Prev = 0;
|
||||
// update Prev link if cache on tile is no empty
|
||||
if (mf->UnitCache) {
|
||||
mf->UnitCache->Prev = listitem;
|
||||
}
|
||||
mf->UnitCache = listitem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Remove unit from cache.
|
||||
**
|
||||
** @param unit Unit pointer to remove from cache.
|
||||
*/
|
||||
global void UnitCacheRemove(Unit* unit)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
MapField* mf;
|
||||
UnitListItem* listitem;
|
||||
|
||||
DebugLevel3Fn("%d,%d %d %s\n" _C_ unit->X _C_ unit->Y _C_ unit->Slot _C_ unit->Type->Name);
|
||||
for (i = 0; i < unit->Type->TileHeight; ++i) {
|
||||
for (j = 0; j < unit->Type->TileWidth; ++j) {
|
||||
mf = TheMap.Fields + (i + unit->Y) * TheMap.Width + j + unit->X;
|
||||
listitem = unit->CacheLinks + i * unit->Type->TileWidth + j;
|
||||
|
||||
if (listitem->Next) {
|
||||
listitem->Next->Prev = listitem->Prev;
|
||||
}
|
||||
if (listitem->Prev) {
|
||||
listitem->Prev->Next = listitem->Next;
|
||||
} else {
|
||||
if (mf->UnitCache != listitem) {
|
||||
DebugLevel0Fn("Try to remove unit not in cache. It's ok, mostly.\n");
|
||||
}
|
||||
// item is head of the list.
|
||||
mf->UnitCache = listitem->Next;
|
||||
DebugCheck(mf->UnitCache && mf->UnitCache->Prev);
|
||||
}
|
||||
|
||||
listitem->Next = listitem->Prev = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Change unit in cache.
|
||||
** FIXME: optimize, add destination to parameters
|
||||
**
|
||||
** @param unit Unit pointer to change in cache.
|
||||
*/
|
||||
global void UnitCacheChange(Unit* unit)
|
||||
{
|
||||
UnitCacheRemove(unit);
|
||||
UnitCacheInsert(unit);
|
||||
}
|
||||
|
||||
/**
|
||||
** Select units in rectangle range.
|
||||
**
|
||||
** @param x1 Left column of selection rectangle
|
||||
** @param y1 Top row of selection rectangle
|
||||
** @param x2 Right column of selection rectangle
|
||||
** @param y2 Bottom row of selection rectangle
|
||||
** @param table All units in the selection rectangle
|
||||
**
|
||||
** @return Returns the number of units found
|
||||
*/
|
||||
global int UnitCacheSelect(int x1, int y1, int x2, int y2, Unit** table)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int n;
|
||||
UnitListItem* listitem;
|
||||
|
||||
//
|
||||
// Reduce to map limits. FIXME: should the caller check?
|
||||
//
|
||||
if (x1 < 0) {
|
||||
x1 = 0;
|
||||
}
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
}
|
||||
if (x2 > TheMap.Width) {
|
||||
x2 = TheMap.Width;
|
||||
}
|
||||
if (y2 > TheMap.Height) {
|
||||
y2 = TheMap.Height;
|
||||
}
|
||||
DebugLevel3Fn("%d,%d %d,%d\n" _C_ x1 _C_ y1 _C_ x2 _C_ y2);
|
||||
|
||||
n = 0;
|
||||
for (i = y1; i < y2; ++i) {
|
||||
for (j = x1; j < x2; ++j) {
|
||||
listitem = TheMap.Fields[i * TheMap.Width + j].UnitCache;
|
||||
for (; listitem; listitem = listitem->Next) {
|
||||
//
|
||||
// To avoid getting an unit in multiple times we use a cache lock.
|
||||
// It should only be used in here, unless you somehow want the unit
|
||||
// to be out of cache.
|
||||
//
|
||||
if (!listitem->Unit->CacheLock) {
|
||||
listitem->Unit->CacheLock = 1;
|
||||
table[n++] = listitem->Unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Clean the cache locks, restore to original situation.
|
||||
//
|
||||
for (i = 0; i < n; ++i) {
|
||||
table[i]->CacheLock = 0;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
** Select units on map tile.
|
||||
**
|
||||
** @param x Map X tile position
|
||||
** @param y Map Y tile position
|
||||
** @param table All units in the selection rectangle
|
||||
**
|
||||
** @return Returns the number of units found
|
||||
*/
|
||||
global int UnitCacheOnTile(int x, int y, Unit** table)
|
||||
{
|
||||
UnitListItem* listitem;
|
||||
int n;
|
||||
|
||||
//
|
||||
// Unlike in UnitCacheSelect, there's no way an unit can show up twice,
|
||||
// so there is no need for Cache Locks.
|
||||
//
|
||||
n = 0;
|
||||
listitem = TheMap.Fields[y * TheMap.Width + x].UnitCache;
|
||||
for (; listitem; listitem = listitem->Next) {
|
||||
if (!listitem->Unit->CacheLock) {
|
||||
table[n++] = listitem->Unit;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
** Select unit on X,Y of type naval,fly,land.
|
||||
**
|
||||
** @param x Map X tile position.
|
||||
** @param y Map Y tile position.
|
||||
** @param type UnitType::UnitType, naval,fly,land.
|
||||
**
|
||||
** @return Unit, if an unit of correct type is on the field.
|
||||
*/
|
||||
global Unit* UnitCacheOnXY(int x, int y, unsigned type)
|
||||
{
|
||||
Unit* table[UnitMax];
|
||||
int n;
|
||||
|
||||
n = UnitCacheOnTile(x, y, table);
|
||||
while (n--) {
|
||||
if ((unsigned)table[n]->Type->UnitType == type) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n > -1) {
|
||||
return table[n];
|
||||
} else {
|
||||
return NoUnitP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Print unit-cache statistic.
|
||||
*/
|
||||
global void UnitCacheStatistic(void)
|
||||
{
|
||||
// FIXME: stats about query sizes.. you can get the rest by profiling.
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize unit-cache.
|
||||
*/
|
||||
global void InitUnitCache(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // } NEW_UNIT_CACHE
|
||||
|
|
Loading…
Reference in a new issue