Units could now be stored on map, perhaps better performance than old version.
This commit is contained in:
parent
865a8d3648
commit
5fdfac7863
6 changed files with 304 additions and 57 deletions
src
|
@ -44,6 +44,20 @@
|
|||
-- Map - field
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef UNIT_ON_MAP
|
||||
/**
|
||||
** All units on a map field, if more than one.
|
||||
** FIXME: unused
|
||||
*/
|
||||
typedef struct _unit_array_ {
|
||||
Unit* Building; /// Building or corpse.
|
||||
Unit* SeaUnit; /// Sea unit.
|
||||
Unit* LandUnit; /// Land unit.
|
||||
Unit* AirUnit; /// Air unit.
|
||||
} UnitArray;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Describes a field of the map.
|
||||
*/
|
||||
|
@ -61,10 +75,11 @@ typedef struct _map_field_ {
|
|||
#ifdef UNIT_ON_MAP
|
||||
union {
|
||||
Unit* Units; /// An unit on the map field.
|
||||
Unit** Array; /// More units on the map field.
|
||||
UnitArray* Array; /// More units on the map field.
|
||||
} Here; /// What is on the field.
|
||||
#endif
|
||||
#ifdef UNITS_ON_MAP
|
||||
// FIXME: Unused
|
||||
UnitRef Building; /// Building or corpse.
|
||||
UnitRef AirUnit; /// Air unit.
|
||||
UnitRef LandUnit; /// Land unit.
|
||||
|
@ -159,11 +174,11 @@ extern int ForestRegeneration;
|
|||
// in map_draw.c
|
||||
//
|
||||
/// Fast draw 32x32 tile for 32 bpp video modes.
|
||||
extern void VideoDraw32Tile32(const unsigned char* data,int x,int y);
|
||||
//extern void VideoDraw32Tile32(const unsigned char* data,int x,int y);
|
||||
/// Fast draw 32x32 tile for 16 bpp video modes.
|
||||
extern void VideoDraw16Tile32(const unsigned char* data,int x,int y);
|
||||
//extern void VideoDraw16Tile32(const unsigned char* data,int x,int y);
|
||||
/// Fast draw 32x32 tile for 8 bpp video modes.
|
||||
extern void VideoDraw8Tile32(const unsigned char* data,int x,int y);
|
||||
//extern void VideoDraw8Tile32(const unsigned char* data,int x,int y);
|
||||
|
||||
/// Called when the color cycles
|
||||
extern void MapColorCycle(void);
|
||||
|
|
|
@ -463,19 +463,21 @@ extern void SaveUnit(const Unit* unit,FILE* file); /// save unit-structure
|
|||
extern void SaveUnits(FILE* file); /// save all units
|
||||
|
||||
// in unitcache.c
|
||||
/// FIXME: more docu
|
||||
/// Insert new unit into cache.
|
||||
extern void UnitCacheInsert(Unit* unit);
|
||||
/// FIXME: more docu
|
||||
/// Remove unit from cache.
|
||||
extern void UnitCacheRemove(Unit* unit);
|
||||
/// FIXME: more docu
|
||||
/// Change unit position in cache.
|
||||
extern void UnitCacheChange(Unit* unit);
|
||||
/// FIXME: more docu
|
||||
/// Select units in range.
|
||||
extern int UnitCacheSelect(int x1,int y1,int x2,int y2,Unit** table);
|
||||
/// FIXME: more docu
|
||||
/// Select units on tile.
|
||||
extern int UnitCacheOnTile(int x,int y,Unit** table);
|
||||
/// Select unit on X,Y of type naval,fly,land.
|
||||
extern Unit* UnitCacheOnXY(int x,int y,int type);
|
||||
/// FIXME: more docu
|
||||
/// Print unit-cache statistic.
|
||||
extern void UnitCacheStatistic(void);
|
||||
/// FIXME: more docu
|
||||
/// Initialize unit-cache.
|
||||
extern void InitUnitCache(void);
|
||||
|
||||
// in map.c belongs to map or unit??
|
||||
|
@ -499,8 +501,11 @@ extern void LoadDecorations(void);
|
|||
extern void DrawUnits(void);
|
||||
|
||||
// in unit_find.c
|
||||
/// FIXME: more docu
|
||||
/// Select units in rectangle range.
|
||||
extern int SelectUnits(int x1,int y1,int x2,int y2,Unit** table);
|
||||
/// Select units on map tile.
|
||||
extern int SelectUnitsOnTile(int x,int y,Unit** table);
|
||||
|
||||
/// Find all units of this type
|
||||
extern int FindUnitsByType(const UnitType* type,Unit** table);
|
||||
/// Find all units of this type of the player
|
||||
|
|
|
@ -645,23 +645,13 @@ local int ComplexNewPath(Unit* unit,int *xdp,int* ydp)
|
|||
}
|
||||
goal=UnitCacheOnXY(x,y,unit->Type->UnitType);
|
||||
if( !goal ) {
|
||||
// Should not happen.
|
||||
DebugLevel0(__FUNCTION__
|
||||
": %p No goal for %d,%d on %d,%d?\n",
|
||||
unit,unit->X,unit->Y,x,y);
|
||||
// Clear movement flag from MovementMap
|
||||
// for this type of unit
|
||||
//TheMap.MovementMap[x+y*TheMap.Width]&=
|
||||
// ~UnitMovement(unit);
|
||||
matrix[w+1+x+y*w]=99;
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
// FIXME: Have more move actions
|
||||
if( goal->Command.Action!=UnitActionMove ) {
|
||||
matrix[w+1+x+y*w]=99;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if( !goal->Moving ) {
|
||||
matrix[w+1+x+y*w]=99;
|
||||
continue;
|
||||
|
|
|
@ -283,7 +283,7 @@ global Unit* MakeUnit(UnitType* type,Player* player)
|
|||
return NoUnitP;
|
||||
}
|
||||
UnitSlotFree=(void*)*slot;
|
||||
*slot=unit=calloc(1,sizeof(Unit));
|
||||
*slot=unit=calloc(1,sizeof(*unit));
|
||||
unit->Refs=1;
|
||||
unit->Slot=slot-UnitSlots; // back index
|
||||
}
|
||||
|
@ -1025,7 +1025,7 @@ global void RescueUnits(void)
|
|||
for( j=0; j<l; j++ ) {
|
||||
unit=table[j];
|
||||
DebugLevel3("Checking %Zd\n",UnitNumber(unit));
|
||||
// NOTE: I hope SelectUnits checks bounds?
|
||||
// FIXME: I hope SelectUnits checks bounds? NO
|
||||
n=SelectUnits(
|
||||
unit->X-1,unit->Y-1,
|
||||
unit->X+unit->Type->TileWidth+1,
|
||||
|
|
|
@ -8,27 +8,33 @@
|
|||
// T H E W A R B E G I N S
|
||||
// FreeCraft - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name unitcache.c - The unit cache.
|
||||
**
|
||||
** Cache to find units faster from position.
|
||||
** I use a radix-quad-tree for lookups.
|
||||
** Other possible data-structures:
|
||||
** Binary Space Partitioning (BSP) tree.
|
||||
** Real quad tree.
|
||||
** Priority search tree.
|
||||
*/
|
||||
/* (c) Copyright 1998-2000 by Lutz Sammer
|
||||
**
|
||||
** $Id$
|
||||
*/
|
||||
/**@name unitcache.c - The unit cache. */
|
||||
//
|
||||
// Cache to find units faster from position.
|
||||
// I use a radix-quad-tree for lookups.
|
||||
// Other possible data-structures:
|
||||
// Binary Space Partitioning (BSP) tree.
|
||||
// Real quad tree.
|
||||
// Priority search tree.
|
||||
//
|
||||
// (c) Copyright 1998-2000 by Lutz Sammer
|
||||
//
|
||||
// $Id$
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "freecraft.h"
|
||||
|
||||
#ifndef UNIT_ON_MAP // {
|
||||
|
||||
#include "video.h"
|
||||
#include "sound_id.h"
|
||||
#include "unitsound.h"
|
||||
|
@ -42,7 +48,9 @@
|
|||
// Quadtrees
|
||||
//****************************************************************************/
|
||||
|
||||
#ifdef DEBUG
|
||||
#define STATISTIC /// include statistic code
|
||||
#endif
|
||||
|
||||
//
|
||||
// Types
|
||||
|
@ -594,10 +602,12 @@ local void QuadTreePrintStatistic(QuadTree* tree)
|
|||
// Convert calls to internal
|
||||
//****************************************************************************/
|
||||
|
||||
local QuadTree* PositionCache;
|
||||
local QuadTree* PositionCache; /// My quad tree for lookup
|
||||
|
||||
/**
|
||||
** Insert new unit into cache.
|
||||
**
|
||||
** @param unit Unit pointer to place in cache.
|
||||
*/
|
||||
global void UnitCacheInsert(Unit* unit)
|
||||
{
|
||||
|
@ -607,6 +617,8 @@ global void UnitCacheInsert(Unit* unit)
|
|||
|
||||
/**
|
||||
** Remove unit from cache.
|
||||
**
|
||||
** @param unit Unit pointer to remove from cache.
|
||||
*/
|
||||
global void UnitCacheRemove(Unit* unit)
|
||||
{
|
||||
|
@ -615,7 +627,9 @@ global void UnitCacheRemove(Unit* unit)
|
|||
}
|
||||
|
||||
/**
|
||||
** Change unit in cache.
|
||||
** Change unit position in cache.
|
||||
**
|
||||
** @param unit Unit pointer to change in cache.
|
||||
*/
|
||||
global void UnitCacheChange(Unit* unit)
|
||||
{
|
||||
|
@ -624,10 +638,15 @@ global void UnitCacheChange(Unit* unit)
|
|||
}
|
||||
|
||||
/**
|
||||
** Select units in range.
|
||||
** Select units in rectangle range.
|
||||
**
|
||||
** table: contains all units in given range.
|
||||
** RETURNS:number of units in table.
|
||||
** @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)
|
||||
{
|
||||
|
@ -642,6 +661,16 @@ global int UnitCacheSelect(int x1,int y1,int x2,int y2,Unit** table)
|
|||
i=x1-4; if( i<0 ) i=0; // Only for current unit-cache !!
|
||||
j=y1-4; if( j<0 ) j=0;
|
||||
|
||||
//
|
||||
// Reduce to map limits. FIXME: should the caller check?
|
||||
//
|
||||
if( x2>TheMap.Width ) {
|
||||
x2=TheMap.Width;
|
||||
}
|
||||
if( y2>TheMap.Height ) {
|
||||
y2=TheMap.Height;
|
||||
}
|
||||
|
||||
n=QuadTreeSelect(PositionCache,i,j,x2,y2,table);
|
||||
|
||||
//
|
||||
|
@ -660,11 +689,30 @@ global int UnitCacheSelect(int x1,int y1,int x2,int y2,Unit** table)
|
|||
}
|
||||
|
||||
/**
|
||||
** Select unit on X,Y.
|
||||
** 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)
|
||||
{
|
||||
return UnitCacheSelect(x,y,x+1,y+1,table);
|
||||
}
|
||||
|
||||
/**
|
||||
** 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.
|
||||
**
|
||||
** @returns Unit, if an unit of correct type is on the field.
|
||||
*/
|
||||
global Unit* UnitCacheOnXY(int x,int y,int type)
|
||||
{
|
||||
|
||||
QuadTreeLeaf* leaf;
|
||||
|
||||
leaf=QuadTreeSearch(PositionCache,x,y);
|
||||
|
@ -715,4 +763,181 @@ global void InitUnitCache(void)
|
|||
PositionCache=NewQuadTree(l);
|
||||
}
|
||||
|
||||
#else // }{ !UNIT_ON_MAP
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include "unit.h"
|
||||
#include "map.h"
|
||||
|
||||
//*****************************************************************************
|
||||
// Store direct on map.
|
||||
//****************************************************************************/
|
||||
|
||||
//*****************************************************************************
|
||||
// Convert calls to internal
|
||||
//****************************************************************************/
|
||||
|
||||
/**
|
||||
** Insert new unit into cache.
|
||||
**
|
||||
** @param unit Unit pointer to place in cache.
|
||||
*/
|
||||
global void UnitCacheInsert(Unit* unit)
|
||||
{
|
||||
MapField* mf;
|
||||
|
||||
mf=TheMap.Fields+unit->Y*TheMap.Width+unit->X;
|
||||
unit->Next=mf->Here.Units;
|
||||
mf->Here.Units=unit;
|
||||
DebugLevel3Fn("%p %p\n",unit,unit->Next);
|
||||
}
|
||||
|
||||
/**
|
||||
** Remove unit from cache.
|
||||
**
|
||||
** @param unit Unit pointer to remove from cache.
|
||||
*/
|
||||
global void UnitCacheRemove(Unit* unit)
|
||||
{
|
||||
Unit** prev;
|
||||
|
||||
prev=&TheMap.Fields[unit->Y*TheMap.Width+unit->X].Here.Units;
|
||||
DebugCheck( !*prev );
|
||||
for( ;; ) { // find the unit
|
||||
if( *prev==unit ) {
|
||||
*prev=unit->Next;
|
||||
return;
|
||||
}
|
||||
prev=&(*prev)->Next;
|
||||
DebugCheck( !*prev );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Change unit in cache.
|
||||
**
|
||||
** @param unit Unit pointer to change in cache.
|
||||
*/
|
||||
global void UnitCacheChange(Unit* unit)
|
||||
{
|
||||
UnitCacheRemove(unit); // must remove first
|
||||
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 x;
|
||||
int y;
|
||||
int n;
|
||||
int i;
|
||||
Unit* unit;
|
||||
MapField* mf;
|
||||
|
||||
//
|
||||
// Units are inserted by origin position
|
||||
//
|
||||
x=x1-4; if( x<0 ) x=0; // Only for current unit-cache !!
|
||||
y=y1-4; if( y<0 ) y=0;
|
||||
|
||||
//
|
||||
// Reduce to map limits. FIXME: should the caller check?
|
||||
//
|
||||
if( x2>TheMap.Width ) {
|
||||
x2=TheMap.Width;
|
||||
}
|
||||
if( y2>TheMap.Height ) {
|
||||
y2=TheMap.Height;
|
||||
}
|
||||
|
||||
for( n=0; y<y2; ++y ) {
|
||||
mf=TheMap.Fields+y*TheMap.Width+x;
|
||||
for( i=x; i<x2; ++i ) {
|
||||
|
||||
for( unit=mf->Here.Units; unit; unit=unit->Next ) {
|
||||
DebugLevel3Fn("%p\n",unit);
|
||||
//
|
||||
// Remove units, outside range.
|
||||
//
|
||||
if( unit->X+unit->Type->TileWidth<=x1
|
||||
|| unit->X>x2
|
||||
|| unit->Y+unit->Type->TileHeight<=y1
|
||||
|| unit->Y>y2 ) {
|
||||
continue;
|
||||
}
|
||||
table[n++]=unit;
|
||||
}
|
||||
++mf;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return UnitCacheSelect(x,y,x+1,y+1,table);
|
||||
}
|
||||
|
||||
/**
|
||||
** 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.
|
||||
**
|
||||
** @returns Unit, if an unit of correct type is on the field.
|
||||
*/
|
||||
global Unit* UnitCacheOnXY(int x,int y,int type)
|
||||
{
|
||||
Unit* unit;
|
||||
|
||||
unit=TheMap.Fields[y*TheMap.Width+x].Here.Units;
|
||||
while( unit ) {
|
||||
if( unit->Type->UnitType==type ) {
|
||||
break;
|
||||
}
|
||||
unit=unit->Next;
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
|
||||
/**
|
||||
** Print unit-cache statistic.
|
||||
*/
|
||||
global void UnitCacheStatistic(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize unit-cache.
|
||||
*/
|
||||
global void InitUnitCache(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // } UNIT_ON_MAP
|
||||
|
||||
//@}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
** Select units in range.
|
||||
** Select units in rectangle range.
|
||||
**
|
||||
** @param x1 Left column of selection rectangle
|
||||
** @param y1 Top row of selection rectangle
|
||||
|
@ -55,6 +55,20 @@ global int SelectUnits(int x1,int y1,int x2,int y2,Unit** table)
|
|||
return UnitCacheSelect(x1,y1,x2,y2,table);
|
||||
}
|
||||
|
||||
/**
|
||||
** Select units on 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 SelectUnitsOnTile(int x,int y,Unit** table)
|
||||
{
|
||||
return UnitCacheOnTile(x,y,table);
|
||||
}
|
||||
|
||||
/**
|
||||
** Find all units of type.
|
||||
**
|
||||
|
@ -134,7 +148,7 @@ global Unit* UnitOnMapTile(unsigned tx,unsigned ty)
|
|||
int n;
|
||||
int i;
|
||||
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
// Note: this is less restrictive than UnitActionDie...
|
||||
// Is it normal?
|
||||
|
@ -161,7 +175,7 @@ global Unit* RepairableOnMapTile(unsigned tx,unsigned ty)
|
|||
int n;
|
||||
int i;
|
||||
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
if( UnitUnusable(table[i]) ) {
|
||||
continue;
|
||||
|
@ -193,8 +207,7 @@ global Unit* TargetOnMapTile(Unit* source,unsigned tx,unsigned ty)
|
|||
int n;
|
||||
int i;
|
||||
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
unit=table[i];
|
||||
// unusable unit ?
|
||||
|
@ -259,7 +272,7 @@ global Unit* GoldMineOnMap(int tx,int ty)
|
|||
int i;
|
||||
int n;
|
||||
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
if( UnitUnusable(table[i]) ) {
|
||||
continue;
|
||||
|
@ -285,8 +298,7 @@ global Unit* GoldDepositOnMap(int tx,int ty)
|
|||
int i;
|
||||
int n;
|
||||
|
||||
// FIXME: perhaps I should write a select on tile function?
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
if( UnitUnusable(table[i]) ) {
|
||||
continue;
|
||||
|
@ -312,7 +324,7 @@ global Unit* OilPatchOnMap(int tx,int ty)
|
|||
int i;
|
||||
int n;
|
||||
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
if( table[i]->Type->OilPatch ) {
|
||||
return table[i];
|
||||
|
@ -335,7 +347,7 @@ global Unit* PlatformOnMap(int tx,int ty)
|
|||
int i;
|
||||
int n;
|
||||
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
if( UnitUnusable(table[i]) ) {
|
||||
continue;
|
||||
|
@ -361,7 +373,7 @@ global Unit* OilDepositOnMap(int tx,int ty)
|
|||
int i;
|
||||
int n;
|
||||
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
if( UnitUnusable(table[i]) ) {
|
||||
continue;
|
||||
|
@ -387,7 +399,7 @@ global Unit* WoodDepositOnMap(int tx,int ty)
|
|||
int i;
|
||||
int n;
|
||||
|
||||
n=SelectUnits(tx,ty,tx+1,ty+1,table);
|
||||
n=SelectUnitsOnTile(tx,ty,table);
|
||||
for( i=0; i<n; ++i ) {
|
||||
if( UnitUnusable(table[i]) ) {
|
||||
continue;
|
||||
|
|
Loading…
Add table
Reference in a new issue