Units could now be stored on map, perhaps better performance than old version.

This commit is contained in:
johns 2000-05-28 21:09:00 +00:00
parent 865a8d3648
commit 5fdfac7863
6 changed files with 304 additions and 57 deletions

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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,

View file

@ -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
//@}

View file

@ -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;