From 5fdfac786365c955f0461211fb5104413bd9c7e8 Mon Sep 17 00:00:00 2001 From: johns <> Date: Sun, 28 May 2000 21:09:00 +0000 Subject: [PATCH] Units could now be stored on map, perhaps better performance than old version. --- src/include/map.h | 23 ++- src/include/unit.h | 21 ++- src/pathfinder/pathfinder.cpp | 12 +- src/unit/unit.cpp | 4 +- src/unit/unit_cache.cpp | 265 +++++++++++++++++++++++++++++++--- src/unit/unit_find.cpp | 36 +++-- 6 files changed, 304 insertions(+), 57 deletions(-) diff --git a/src/include/map.h b/src/include/map.h index 506a5bc13..151b1a49d 100644 --- a/src/include/map.h +++ b/src/include/map.h @@ -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); diff --git a/src/include/unit.h b/src/include/unit.h index 08508d1ec..345fd9525 100644 --- a/src/include/unit.h +++ b/src/include/unit.h @@ -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 diff --git a/src/pathfinder/pathfinder.cpp b/src/pathfinder/pathfinder.cpp index 78e3b02be..2db0f9f87 100644 --- a/src/pathfinder/pathfinder.cpp +++ b/src/pathfinder/pathfinder.cpp @@ -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; diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp index 032182e71..7f6a72c46 100644 --- a/src/unit/unit.cpp +++ b/src/unit/unit.cpp @@ -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, diff --git a/src/unit/unit_cache.cpp b/src/unit/unit_cache.cpp index bd6597d9d..5c1aab7c4 100644 --- a/src/unit/unit_cache.cpp +++ b/src/unit/unit_cache.cpp @@ -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 + //@} diff --git a/src/unit/unit_find.cpp b/src/unit/unit_find.cpp index 87cd29416..c99f490ea 100644 --- a/src/unit/unit_find.cpp +++ b/src/unit/unit_find.cpp @@ -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;