dfhack/library/include/TileTypes.h

419 lines
13 KiB
C++

/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef TILETYPES_H_INCLUDED
#define TILETYPES_H_INCLUDED
#include "Pragma.h"
#include "Export.h"
namespace DFHack
{
// tile class -- determines the general shape of the tile
// enum and lookup table for string names created using X macros
#define TILESHAPE_MACRO \
X(EMPTY, "") \
X(WALL, "") \
X(PILLAR, "") \
X(BROOK_BED, "mineable, water-passable rock on the bottom of brook") \
X(FORTIFICATION, "") \
X(STAIR_UP, "") \
X(STAIR_DOWN, "") \
X(STAIR_UPDOWN, "") \
X(RAMP, "ramps have no direction" ) \
X(RAMP_TOP, "used for pathing?" ) \
X(FLOOR, "") \
X(BROOK_TOP, "water-passable floor on top of BROOK_BED tiles") \
X(RIVER_BED, "It's a riverbed. Basically a floor that doesn't get muddy.") \
X(POOL, "A pool. Gathers water while it's raining.'") \
X(TREE_DEAD, "") \
X(TREE_OK, "") \
X(SAPLING_DEAD, "") \
X(SAPLING_OK, "") \
X(SHRUB_DEAD, "") \
X(SHRUB_OK, "") \
X(BOULDER, "") \
X(PEBBLES, "") \
X(ENDLESS_PIT, "a fake endless pit")
//end TILESHAPE_MACRO
//define tile class enum
#define X(name,comment) name,
enum TileShape {
tileshape_invalid=-1,
TILESHAPE_MACRO
tileshape_count,
};
#undef X
DFHACK_EXPORT extern const char *TileShapeString[];
#define TILEMATERIAL_MACRO \
X(AIR, "empty" ) \
X(SOIL, "ordinary soil. material depends on geology" ) \
X(STONE, "ordinary layer stone. material depends on geology" ) \
X(FEATSTONE, "map special stone. used for things like hell, the hell temple or adamantine tubes. material depends on local/global special" ) \
X(OBSIDIAN, "lava stone created by mixing magma and water" ) \
X(VEIN, "vein stone. material depends on mineral veins present" ) \
X(ICE, "frozen water... not much to say. you can determine what was on the tile before it froze by looking into the 'ice vein' objects" ) \
X(GRASS, "light grass (has 4 variants)" ) \
X(GRASS2, "dark grass (has 4 variants)" ) \
X(GRASS_DEAD, "dead grass (has 4 variants)" ) \
X(GRASS_DRY, "dry grass (has 4 variants)" ) \
X(DRIFTWOOD, "driftwood. normally shows up on beaches" ) \
X(HFS, "the stuff demon pits are made of - this makes them different from ordinary pits." ) \
X(MAGMA, "material for semi-molten rock and 'magma flow' tiles" ) \
X(CAMPFIRE, "human armies make them when they siege. The original tile may be lost?" ) \
X(FIRE, "burning grass" ) \
X(ASHES, "what remains from a FIRE" ) \
X(CONSTRUCTED,"tile material depends on the construction present" ) \
X(CYAN_GLOW, "the glowy stuff that disappears from the demon temple when you take the sword." )
//end TILEMATERIAL_MACRO
// material enum
#define X(name,comment) name,
enum TileMaterial {
tilematerial_invalid=-1,
TILEMATERIAL_MACRO
tilematerial_count,
};
#undef X
DFHACK_EXPORT extern const char *TileMaterialString[];
// Special specials of the tile.
// Not the best way to do this, but compatible with existing code.
// When the TileType class gets created, everything should be re-thought.
#define TILESPECIAL_MACRO \
X(NORMAL, "Default for all type, nothing present" ) \
X(RIVER_SOURCE, "River Source, when it exists on a map" ) \
X(WATERFALL, "Waterfall from Nowhere, used by cave rivers back in 40d" ) \
X(CRACKED, "Partially (75%) mined walls" ) \
X(DAMAGED, "Partially (50%) mined walls" ) \
X(WORN, "Partially (25%) mined walls" ) \
X(SMOOTH, "Walls and floors." )
//end TILESPECIAL_MACRO
//special enum
#define X(name,comment) TILE_##name,
enum TileSpecial {
tilespecial_invalid=-1,
TILESPECIAL_MACRO
tilespecial_count,
};
#undef X
DFHACK_EXPORT extern const char *TileSpecialString[];
// variants are used for tiles, where there are multiple variants of the same - like grass floors
enum TileVariant
{
tilevariant_invalid=-1,
VAR_1, //Yes, the value of VAR_1 is 0. It's legacy. Deal with it.
VAR_2,
VAR_3,
VAR_4,
};
//Mainly walls and rivers
//Byte values are used because walls can have either 1 or 2 in any given direction.
const int TileDirectionCount = 4;
union TileDirection
{
uint32_t whole;
unsigned char b[TileDirectionCount];
struct
{
//Maybe should add 'up' and 'down' for Z-levels?
unsigned char north,south,west,east;
};
inline TileDirection()
{
whole = 0;
}
TileDirection( uint32_t whole_bits)
{
whole = whole_bits;
}
TileDirection( unsigned char North, unsigned char South, unsigned char West, unsigned char East )
{
north=North; south=South; east=East; west=West;
}
TileDirection( const char *dir )
{
//This one just made for fun.
//Supports N S E W
const char *p = dir;
unsigned char *l=0;
north=south=east=west=0;
if(!dir) return;
for( ;*p;++p)
{
switch(*p)
{
case 'N': //North / Up
case 'n':
++north; l=&north; break;
case 'S': //South / Down
case 's':
++south; l=&south; break;
case 'E': //East / Right
case 'e':
++east; l=&east; break;
case 'W': //West / Left
case 'w':
++west; l=&west; break;
case '-':
case ' ':
//Explicitly ensure dash and space are ignored.
//Other characters/symbols may be assigned in the future.
break;
default:
if( l && '0' <= *p && '9' >= *p )
*l += *p - '0';
break;
}
}
}
//may be useful for some situations
inline uint32_t sum() const
{
return 0L + north + south + east + west;
}
//Gives a string that represents the direction.
//This is a static string, overwritten with every call!
//Support values > 2 even though they should never happen.
//Copy string if it will be used.
inline char * getStr() const
{
static char str[16];
//type punning trick
*( (uint64_t *)str ) = *( (uint64_t *)"--------" );
str[8]=0;
#define DIRECTION(x,i,c) \
if(x){ \
str[i]=c; \
if(1==x) ; \
else if(2==x) str[i+1]=c; \
else str[i+1]='0'+x; \
}
DIRECTION(north,0,'N')
DIRECTION(south,2,'S')
DIRECTION(west,4,'W')
DIRECTION(east,6,'E')
#undef DIRECTION
return str;
}
};
struct TileRow
{
const char * name;
TileShape shape;
TileMaterial material;
TileVariant variant;
TileSpecial special;
TileDirection direction;
};
#define TILE_TYPE_ARRAY_LENGTH 520
extern DFHACK_EXPORT const TileRow tileTypeTable[];
// tile is missing a floor
inline
bool LowPassable(int16_t tiletype)
{
switch(DFHack::tileTypeTable[tiletype].shape)
{
case DFHack::EMPTY:
case DFHack::STAIR_DOWN:
case DFHack::STAIR_UPDOWN:
case DFHack::RAMP_TOP:
return true;
default:
return false;
}
};
// tile is missing a roof
inline
bool HighPassable(int16_t tiletype)
{
switch(DFHack::tileTypeTable[tiletype].shape)
{
case DFHack::EMPTY:
case DFHack::STAIR_DOWN:
case DFHack::STAIR_UPDOWN:
case DFHack::STAIR_UP:
case DFHack::RAMP:
case DFHack::RAMP_TOP:
case DFHack::FLOOR:
case DFHack::SAPLING_DEAD:
case DFHack::SAPLING_OK:
case DFHack::SHRUB_DEAD:
case DFHack::SHRUB_OK:
case DFHack::BOULDER:
case DFHack::PEBBLES:
case DFHack::RIVER_BED:
case DFHack::POOL:
case DFHack::ENDLESS_PIT:
case DFHack::BROOK_TOP:
return true;
default:
return false;
}
};
inline
bool FlowPassable(int16_t tiletype)
{
TileShape tc = tileTypeTable[tiletype].shape;
return tc != WALL && tc != PILLAR && tc != TREE_DEAD && tc != TREE_OK;
};
inline
bool isWallTerrain(int16_t tiletype)
{
return tileTypeTable[tiletype].shape >= WALL && tileTypeTable[tiletype].shape <= FORTIFICATION ;
}
inline
bool isFloorTerrain(int16_t tiletype)
{
return tileTypeTable[tiletype].shape >= FLOOR && tileTypeTable[tiletype].shape <= PEBBLES;
}
inline
bool isRampTerrain(int16_t tiletype)
{
return tileTypeTable[tiletype].shape == RAMP;
}
inline
bool isStairTerrain(int16_t tiletype)
{
return tileTypeTable[tiletype].shape >= STAIR_UP && tileTypeTable[tiletype].shape <= STAIR_UPDOWN;
}
inline
bool isOpenTerrain(int16_t tiletype)
{
return tileTypeTable[tiletype].shape == EMPTY;
}
inline
const char * tileName(int16_t tiletype)
{
return tileTypeTable[tiletype].name;
}
inline
TileShape tileShape(int16_t tiletype)
{
return tileTypeTable[tiletype].shape;
}
inline
TileSpecial tileSpecial(int16_t tiletype)
{
return tileTypeTable[tiletype].special;
}
inline
TileVariant tileVariant(int16_t tiletype)
{
return tileTypeTable[tiletype].variant;
}
inline
TileMaterial tileMaterial(int16_t tiletype)
{
return tileTypeTable[tiletype].material;
}
inline
TileDirection tileDirection(int16_t tiletype)
{
return tileTypeTable[tiletype].direction;
}
/// Safely access the tile type array.
inline const
TileRow * getTileRow(int16_t tiletype)
{
if( tiletype<0 || tiletype>=TILE_TYPE_ARRAY_LENGTH ) return 0;
return ( const TileRow * ) &tileTypeTable[tiletype];
}
/**
* zilpin: Find the first tile entry which matches the given search criteria.
* All parameters are optional.
* To omit, use the 'invalid' enum for that type (e.g. tileclass_invalid, tilematerial_invalid, etc)
* For tile directions, pass NULL to omit.
* @return matching index in tileTypeTable, or -1 if none found.
*/
inline
int16_t findTileType( const TileShape tshape, const TileMaterial tmat, const TileVariant tvar, const TileSpecial tspecial, const TileDirection tdir )
{
int16_t tt;
for(tt=0;tt<TILE_TYPE_ARRAY_LENGTH; ++tt)
{
if( tshape>-1 && tshape != tileTypeTable[tt].shape ) continue;
if( tmat>-1 && tmat != tileTypeTable[tt].material ) continue;
if( tvar>-1 && tvar != tileTypeTable[tt].variant ) continue;
if( tspecial>-1 && tspecial != tileTypeTable[tt].special ) continue;
if( tdir.whole && tdir.whole != tileTypeTable[tt].direction.whole ) continue;
//Match!
return tt;
}
return -1;
}
/**
* zilpin: Find a tile type similar to the one given, but with a different class.
* Useful for tile-editing operations.
* If no match found, returns the sourceType
*
* @todo Definitely needs improvement for wall directions, etc.
*/
DFHACK_EXPORT int16_t findSimilarTileType( const int16_t sourceTileType, const TileShape tshape );
}
#endif // TILETYPES_H_INCLUDED