Browse Source

Operate directly on SOL data

pull/4745/head
Anders Jenbo 4 years ago
parent
commit
860bd1cebf
  1. 34
      Source/debug.cpp
  2. 4
      Source/diablo.cpp
  3. 4
      Source/engine/render/dun_render.cpp
  4. 79
      Source/gendung.cpp
  5. 40
      Source/gendung.h
  6. 6
      Source/lighting.cpp
  7. 40
      Source/missiles.cpp
  8. 2
      Source/monster.cpp
  9. 4
      Source/objects.cpp
  10. 4
      Source/path.cpp
  11. 8
      Source/scrollrt.cpp
  12. 8
      Source/themes.cpp
  13. 44
      test/path_test.cpp

34
Source/debug.cpp

@ -63,11 +63,9 @@ enum class DebugGridTextItem : uint16_t {
objectindex,
// take dPiece as index
nBlockTable,
nSolidTable,
nTransTable,
nMissileTable,
nTrapTable,
Solid,
Transparent,
Trap,
// megatiles
AutomapView,
@ -846,11 +844,9 @@ std::string DebugCmdShowTileData(const string_view parameter)
"coords",
"cursorcoords",
"objectindex",
"nBlockTable",
"nSolidTable",
"nTransTable",
"nMissileTable",
"nTrapTable",
"solid",
"transparent",
"trap",
"AutomapView",
"dungeon",
"pdungeon",
@ -1132,20 +1128,14 @@ bool GetDebugGridText(Point dungeonCoords, char *debugGridTextBuffer)
case DebugGridTextItem::dObject:
info = dObject[dungeonCoords.x][dungeonCoords.y];
break;
case DebugGridTextItem::nBlockTable:
info = nBlockTable[dPiece[dungeonCoords.x][dungeonCoords.y]];
case DebugGridTextItem::Solid:
info = TileHasAny(dPiece[dungeonCoords.x][dungeonCoords.y], TileProperties::Solid) << 0 | TileHasAny(dPiece[dungeonCoords.x][dungeonCoords.y], TileProperties::BlockLight) << 1 | TileHasAny(dPiece[dungeonCoords.x][dungeonCoords.y], TileProperties::BlockMissile) << 2;
break;
case DebugGridTextItem::nSolidTable:
info = nSolidTable[dPiece[dungeonCoords.x][dungeonCoords.y]];
case DebugGridTextItem::Transparent:
info = TileHasAny(dPiece[dungeonCoords.x][dungeonCoords.y], TileProperties::Transparent) << 0 | TileHasAny(dPiece[dungeonCoords.x][dungeonCoords.y], TileProperties::TransparentLeft) << 1 | TileHasAny(dPiece[dungeonCoords.x][dungeonCoords.y], TileProperties::TransparentRight) << 2;
break;
case DebugGridTextItem::nTransTable:
info = nTransTable[dPiece[dungeonCoords.x][dungeonCoords.y]];
break;
case DebugGridTextItem::nMissileTable:
info = nMissileTable[dPiece[dungeonCoords.x][dungeonCoords.y]];
break;
case DebugGridTextItem::nTrapTable:
info = nTrapTable[dPiece[dungeonCoords.x][dungeonCoords.y]];
case DebugGridTextItem::Trap:
info = TileHasAny(dPiece[dungeonCoords.x][dungeonCoords.y], TileProperties::Trap);
break;
case DebugGridTextItem::AutomapView:
info = AutomapView[megaCoords.x][megaCoords.y];

4
Source/diablo.cpp

@ -2133,7 +2133,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
if (!setlevel) {
CreateLevel(lvldir);
IncProgress();
FillSolidBlockTbls();
LoadLevelSOLData();
SetRndSeed(glSeedTbl[currlevel]);
if (leveltype != DTYPE_TOWN) {
@ -2254,7 +2254,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
IncProgress();
InitCorpses();
IncProgress();
FillSolidBlockTbls();
LoadLevelSOLData();
IncProgress();
if (lvldir == ENTRY_WARPLVL)

4
Source/engine/render/dun_render.cpp

@ -1131,12 +1131,12 @@ const std::uint32_t *GetMask(TileType tile)
return &WallMaskFullyTrasparent[TILE_HEIGHT - 1];
}
if (arch_draw_type == 1 && tile != TileType::LeftTriangle) {
if ((block_lvid[level_piece_id] & 0x01) != 0) {
if (TileHasAny(level_piece_id, TileProperties::TransparentLeft)) {
return &LeftMaskTransparent[TILE_HEIGHT - 1];
}
}
if (arch_draw_type == 2 && tile != TileType::RightTriangle) {
if ((block_lvid[level_piece_id] & 0x02) != 0) {
if (TileHasAny(level_piece_id, TileProperties::TransparentRight)) {
return &RightMaskTransparent[TILE_HEIGHT - 1];
}
}

79
Source/gendung.cpp

@ -30,12 +30,7 @@ std::optional<OwnedCelSprite> pSpecialCels;
std::unique_ptr<MegaTile[]> pMegaTiles;
std::unique_ptr<uint16_t[]> pLevelPieces;
std::unique_ptr<byte[]> pDungeonCels;
std::array<uint8_t, MAXTILES + 1> block_lvid;
std::array<bool, MAXTILES + 1> nBlockTable;
std::array<bool, MAXTILES + 1> nSolidTable;
std::array<bool, MAXTILES + 1> nTransTable;
std::array<bool, MAXTILES + 1> nMissileTable;
std::array<bool, MAXTILES + 1> nTrapTable;
std::array<TileProperties, MAXTILES> SOLData;
Point dminPosition;
Point dmaxPosition;
dungeon_type leveltype;
@ -64,30 +59,6 @@ THEME_LOC themeLoc[MAXTHEMES];
namespace {
std::unique_ptr<uint8_t[]> LoadLevelSOLData(size_t &tileCount)
{
switch (leveltype) {
case DTYPE_TOWN:
if (gbIsHellfire)
return LoadFileInMem<uint8_t>("NLevels\\TownData\\Town.SOL", &tileCount);
return LoadFileInMem<uint8_t>("Levels\\TownData\\Town.SOL", &tileCount);
case DTYPE_CATHEDRAL:
return LoadFileInMem<uint8_t>("Levels\\L1Data\\L1.SOL", &tileCount);
case DTYPE_CATACOMBS:
return LoadFileInMem<uint8_t>("Levels\\L2Data\\L2.SOL", &tileCount);
case DTYPE_CAVES:
return LoadFileInMem<uint8_t>("Levels\\L3Data\\L3.SOL", &tileCount);
case DTYPE_HELL:
return LoadFileInMem<uint8_t>("Levels\\L4Data\\L4.SOL", &tileCount);
case DTYPE_NEST:
return LoadFileInMem<uint8_t>("NLevels\\L6Data\\L6.SOL", &tileCount);
case DTYPE_CRYPT:
return LoadFileInMem<uint8_t>("NLevels\\L5Data\\L5.SOL", &tileCount);
default:
app_fatal("FillSolidBlockTbls");
}
}
bool WillThemeRoomFit(int floor, int x, int y, int minSize, int maxSize, int *width, int *height)
{
bool yFlag = true;
@ -443,19 +414,43 @@ void CreateDungeon(uint32_t rseed, lvl_entry entry)
Make_SetPC(SetPiece);
}
void FillSolidBlockTbls()
bool TileHasAny(int tileId, TileProperties property)
{
if (tileId == 0)
return false; // Change town to place 219 (218) instead of 0 and make dPiece zero indexed
return HasAnyOf(SOLData[tileId - 1], property);
}
void LoadLevelSOLData()
{
size_t tileCount;
auto pSBFile = LoadLevelSOLData(tileCount);
for (unsigned i = 0; i < tileCount; i++) {
uint8_t bv = pSBFile[i];
nSolidTable[i + 1] = (bv & 0x01) != 0;
nBlockTable[i + 1] = (bv & 0x02) != 0;
nMissileTable[i + 1] = (bv & 0x04) != 0;
nTransTable[i + 1] = (bv & 0x08) != 0;
nTrapTable[i + 1] = (bv & 0x80) != 0;
block_lvid[i + 1] = (bv & 0x30) >> 4;
switch (leveltype) {
case DTYPE_TOWN:
if (gbIsHellfire)
LoadFileInMem("NLevels\\TownData\\Town.SOL", SOLData);
else
LoadFileInMem("Levels\\TownData\\Town.SOL", SOLData);
break;
case DTYPE_CATHEDRAL:
LoadFileInMem("Levels\\L1Data\\L1.SOL", SOLData);
break;
case DTYPE_CATACOMBS:
LoadFileInMem("Levels\\L2Data\\L2.SOL", SOLData);
break;
case DTYPE_CAVES:
LoadFileInMem("Levels\\L3Data\\L3.SOL", SOLData);
break;
case DTYPE_HELL:
LoadFileInMem("Levels\\L4Data\\L4.SOL", SOLData);
break;
case DTYPE_NEST:
LoadFileInMem("NLevels\\L6Data\\L6.SOL", SOLData);
break;
case DTYPE_CRYPT:
LoadFileInMem("NLevels\\L5Data\\L5.SOL", SOLData);
break;
default:
app_fatal("LoadLevelSOLData");
}
}

40
Source/gendung.h

@ -26,7 +26,7 @@ namespace devilution {
#define MAXDUNY (16 + DMAXY * 2 + 16)
#define MAXTHEMES 50
#define MAXTILES 2048
#define MAXTILES 1376
enum _setlevels : int8_t {
SL_NONE,
@ -79,6 +79,20 @@ enum class DungeonFlag : uint8_t {
};
use_enum_as_flags(DungeonFlag);
enum class TileProperties : uint8_t {
// clang-format off
None = 0,
Solid = 1 << 0,
BlockLight = 1 << 1,
BlockMissile = 1 << 2,
Transparent = 1 << 3,
TransparentLeft = 1 << 4,
TransparentRight = 1 << 5,
Trap = 1 << 7,
// clang-format on
};
use_enum_as_flags(TileProperties);
enum _difficulty : uint8_t {
DIFF_NORMAL,
DIFF_NIGHTMARE,
@ -139,26 +153,9 @@ extern DVL_API_FOR_TEST std::unique_ptr<MegaTile[]> pMegaTiles;
extern std::unique_ptr<uint16_t[]> pLevelPieces;
extern std::unique_ptr<byte[]> pDungeonCels;
/**
* List of transparency masks to use for dPieces
*/
extern std::array<uint8_t, MAXTILES + 1> block_lvid;
/**
* List of light blocking dPieces
*/
extern std::array<bool, MAXTILES + 1> nBlockTable;
/**
* List of path blocking dPieces
*/
extern DVL_API_FOR_TEST std::array<bool, MAXTILES + 1> nSolidTable;
/**
* List of transparent dPieces
*/
extern std::array<bool, MAXTILES + 1> nTransTable;
/**
* List of missile blocking dPieces
* List tile properties
*/
extern std::array<bool, MAXTILES + 1> nMissileTable;
extern std::array<bool, MAXTILES + 1> nTrapTable;
extern std::array<TileProperties, MAXTILES> SOLData;
/** Specifies the minimum X,Y-coordinates of the map. */
extern Point dminPosition;
/** Specifies the maximum X,Y-coordinates of the map. */
@ -316,7 +313,8 @@ struct Miniset {
}
};
void FillSolidBlockTbls();
bool TileHasAny(int tileId, TileProperties property);
void LoadLevelSOLData();
void SetDungeonMicros();
void DRLG_InitTrans();
void DRLG_MRectTrans(Point origin, Point extent);

6
Source/lighting.cpp

@ -670,11 +670,11 @@ void DoVision(Point position, int nRadius, MapExplorationType doautomap, bool vi
break;
}
if (InDungeonBounds({ nCrawlX, nCrawlY })) {
nBlockerFlag = nBlockTable[dPiece[nCrawlX][nCrawlY]];
nBlockerFlag = TileHasAny(dPiece[nCrawlX][nCrawlY], TileProperties::BlockLight);
if ((InDungeonBounds({ x1adj + nCrawlX, y1adj + nCrawlY })
&& !nBlockTable[dPiece[x1adj + nCrawlX][y1adj + nCrawlY]])
&& !TileHasAny(dPiece[x1adj + nCrawlX][y1adj + nCrawlY], TileProperties::BlockLight))
|| (InDungeonBounds({ x2adj + nCrawlX, y2adj + nCrawlY })
&& !nBlockTable[dPiece[x2adj + nCrawlX][y2adj + nCrawlY]])) {
&& !TileHasAny(dPiece[x2adj + nCrawlX][y2adj + nCrawlY], TileProperties::BlockLight))) {
if (doautomap != MAP_EXP_NONE) {
if (dFlags[nCrawlX][nCrawlY] != DungeonFlag::None) {
SetAutomapView({ nCrawlX, nCrawlY }, doautomap);

40
Source/missiles.cpp

@ -69,7 +69,7 @@ bool CheckBlock(Point from, Point to)
{
while (from != to) {
from += GetDirection(from, to);
if (nSolidTable[dPiece[from.x][from.y]])
if (TileHasAny(dPiece[from.x][from.y], TileProperties::Solid))
return true;
}
@ -573,7 +573,7 @@ void AddRune(Missile &missile, Point dst, missile_id missileID)
if (TileContainsMissile(target)) {
return false;
}
if (nSolidTable[dPiece[target.x][target.y]]) {
if (TileHasAny(dPiece[target.x][target.y], TileProperties::Solid)) {
return false;
}
return true;
@ -628,7 +628,7 @@ bool GrowWall(int playerId, Point position, Point target, missile_id type, int s
int dp = dPiece[position.x][position.y];
assert(dp <= MAXTILES && dp >= 0);
if (nMissileTable[dp] || !InDungeonBounds(target)) {
if (TileHasAny(dp, TileProperties::BlockMissile) || !InDungeonBounds(target)) {
return false;
}
@ -648,12 +648,12 @@ void SpawnLightning(Missile &missile, int dam)
assert(pn >= 0 && pn <= MAXTILES);
if (!missile.IsTrap() || position != missile.position.start) {
if (nMissileTable[pn]) {
if (TileHasAny(pn, TileProperties::BlockMissile)) {
missile._mirange = 0;
}
}
if (!nMissileTable[pn]) {
if (!TileHasAny(pn, TileProperties::BlockMissile)) {
if (position != Point { missile.var1, missile.var2 } && InDungeonBounds(position)) {
missile_id type = MIS_LIGHTNING;
if (!missile.IsTrap() && missile._micaster == TARGET_PLAYERS
@ -687,7 +687,7 @@ bool IsMissileBlockedByTile(Point tile)
return true;
}
if (nMissileTable[dPiece[tile.x][tile.y]]) {
if (TileHasAny(dPiece[tile.x][tile.y], TileProperties::BlockMissile)) {
return true;
}
@ -1871,7 +1871,7 @@ void AddTown(Missile &missile, const AddMissileParameter &parameter)
}
int dp = dPiece[target.x][target.y];
if (nSolidTable[dp] || nMissileTable[dp]) {
if (TileHasAny(dp, TileProperties::Solid | TileProperties::BlockMissile)) {
return false;
}
return !CheckIfTrig(target);
@ -1988,7 +1988,7 @@ void AddGuardian(Missile &missile, const AddMissileParameter &parameter)
}
int dp = dPiece[target.x][target.y];
if (nSolidTable[dp] || nMissileTable[dp]) {
if (TileHasAny(dp, TileProperties::Solid | TileProperties::BlockMissile)) {
return false;
}
@ -2909,18 +2909,18 @@ void MI_Fireball(Missile &missile)
}
if (!TransList[dTransVal[missilePosition.x][missilePosition.y]]
|| (missile.position.velocity.deltaX < 0 && ((TransList[dTransVal[missilePosition.x][missilePosition.y + 1]] && nSolidTable[dPiece[missilePosition.x][missilePosition.y + 1]]) || (TransList[dTransVal[missilePosition.x][missilePosition.y - 1]] && nSolidTable[dPiece[missilePosition.x][missilePosition.y - 1]])))) {
|| (missile.position.velocity.deltaX < 0 && ((TransList[dTransVal[missilePosition.x][missilePosition.y + 1]] && TileHasAny(dPiece[missilePosition.x][missilePosition.y + 1], TileProperties::Solid)) || (TransList[dTransVal[missilePosition.x][missilePosition.y - 1]] && TileHasAny(dPiece[missilePosition.x][missilePosition.y - 1], TileProperties::Solid))))) {
missile.position.tile += Displacement { 1, 1 };
missile.position.offset.deltaY -= 32;
}
if (missile.position.velocity.deltaY > 0
&& ((TransList[dTransVal[missilePosition.x + 1][missilePosition.y]] && nSolidTable[dPiece[missilePosition.x + 1][missilePosition.y]])
|| (TransList[dTransVal[missilePosition.x - 1][missilePosition.y]] && nSolidTable[dPiece[missilePosition.x - 1][missilePosition.y]]))) {
&& ((TransList[dTransVal[missilePosition.x + 1][missilePosition.y]] && TileHasAny(dPiece[missilePosition.x + 1][missilePosition.y], TileProperties::Solid))
|| (TransList[dTransVal[missilePosition.x - 1][missilePosition.y]] && TileHasAny(dPiece[missilePosition.x - 1][missilePosition.y], TileProperties::Solid)))) {
missile.position.offset.deltaY -= 32;
}
if (missile.position.velocity.deltaX > 0
&& ((TransList[dTransVal[missilePosition.x][missilePosition.y + 1]] && nSolidTable[dPiece[missilePosition.x][missilePosition.y + 1]])
|| (TransList[dTransVal[missilePosition.x][missilePosition.y - 1]] && nSolidTable[dPiece[missilePosition.x][missilePosition.y - 1]]))) {
&& ((TransList[dTransVal[missilePosition.x][missilePosition.y + 1]] && TileHasAny(dPiece[missilePosition.x][missilePosition.y + 1], TileProperties::Solid))
|| (TransList[dTransVal[missilePosition.x][missilePosition.y - 1]] && TileHasAny(dPiece[missilePosition.x][missilePosition.y - 1], TileProperties::Solid)))) {
missile.position.offset.deltaX -= 32;
}
missile._mimfnum = 0;
@ -3024,13 +3024,13 @@ void MI_FireRing(Missile &missile)
if (!InDungeonBounds(target))
continue;
int dp = dPiece[target.x][target.y];
if (nSolidTable[dp])
if (TileHasAny(dp, TileProperties::Solid))
continue;
if (IsObjectAtPosition(target))
continue;
if (!LineClearMissile(missile.position.tile, target))
continue;
if (nMissileTable[dp] || missile.limitReached) {
if (TileHasAny(dp, TileProperties::BlockMissile) || missile.limitReached) {
missile.limitReached = true;
continue;
}
@ -3611,7 +3611,7 @@ void MI_Apoca(Missile &missile)
continue;
if (Monsters[mid].MType->mtype == MT_GOLEM)
continue;
if (nSolidTable[dPiece[k][j]])
if (TileHasAny(dPiece[k][j], TileProperties::Solid))
continue;
if (gbIsHellfire && !LineClearMissile(missile.position.tile, { k, j }))
continue;
@ -3640,7 +3640,7 @@ void MI_Wave(Missile &missile)
Point na = src + sd;
int pn = dPiece[na.x][na.y];
assert(pn >= 0 && pn <= MAXTILES);
if (!nMissileTable[pn]) {
if (!TileHasAny(pn, TileProperties::BlockMissile)) {
Direction pdir = Players[id]._pdir;
AddMissile(na, na + sd, pdir, MIS_FIREMOVE, TARGET_MONSTERS, id, 0, missile._mispllvl);
na += dira;
@ -3648,7 +3648,7 @@ void MI_Wave(Missile &missile)
for (int j = 0; j < (missile._mispllvl / 2) + 2; j++) {
pn = dPiece[na.x][na.y]; // BUGFIX: dPiece is accessed before check against dungeon size and 0
assert(pn >= 0 && pn <= MAXTILES);
if (nMissileTable[pn] || f1 || !InDungeonBounds(na)) {
if (TileHasAny(pn, TileProperties::BlockMissile) || f1 || !InDungeonBounds(na)) {
f1 = true;
} else {
AddMissile(na, na + sd, pdir, MIS_FIREMOVE, TARGET_MONSTERS, id, 0, missile._mispllvl);
@ -3656,7 +3656,7 @@ void MI_Wave(Missile &missile)
}
pn = dPiece[nb.x][nb.y]; // BUGFIX: dPiece is accessed before check against dungeon size and 0
assert(pn >= 0 && pn <= MAXTILES);
if (nMissileTable[pn] || f2 || !InDungeonBounds(nb)) {
if (TileHasAny(pn, TileProperties::BlockMissile) || f2 || !InDungeonBounds(nb)) {
f2 = true;
} else {
AddMissile(nb, nb + sd, pdir, MIS_FIREMOVE, TARGET_MONSTERS, id, 0, missile._mispllvl);
@ -3760,7 +3760,7 @@ void MI_Flamec(Missile &missile)
UpdateMissilePos(missile);
if (missile.position.tile != Point { missile.var1, missile.var2 }) {
int id = dPiece[missile.position.tile.x][missile.position.tile.y];
if (!nMissileTable[id]) {
if (!TileHasAny(id, TileProperties::BlockMissile)) {
AddMissile(
missile.position.tile,
missile.position.start,

2
Source/monster.cpp

@ -4405,7 +4405,7 @@ bool DirOK(int i, Direction mdir)
bool PosOkMissile(Point position)
{
return !nMissileTable[dPiece[position.x][position.y]];
return !TileHasAny(dPiece[position.x][position.y], TileProperties::BlockMissile);
}
bool LineClearMissile(Point startPoint, Point endPoint)

4
Source/objects.cpp

@ -301,7 +301,7 @@ bool RndLocOk(int xp, int yp)
return false;
if (TileContainsSetPiece({ xp, yp }))
return false;
if (nSolidTable[dPiece[xp][yp]])
if (TileHasAny(dPiece[xp][yp], TileProperties::Solid))
return false;
return IsNoneOf(leveltype, DTYPE_CATHEDRAL, DTYPE_CRYPT) || dPiece[xp][yp] <= 126 || dPiece[xp][yp] >= 144;
}
@ -313,7 +313,7 @@ bool CanPlaceWallTrap(int xp, int yp)
if (TileContainsSetPiece({ xp, yp }))
return false;
return nTrapTable[dPiece[xp][yp]];
return TileHasAny(dPiece[xp][yp], TileProperties::Trap);
}
void InitRndLocObj(int min, int max, _object_id objtype)

4
Source/path.cpp

@ -291,7 +291,7 @@ bool IsTileNotSolid(Point position)
return false;
}
return !nSolidTable[dPiece[position.x][position.y]];
return !TileHasAny(dPiece[position.x][position.y], TileProperties::Solid);
}
bool IsTileSolid(Point position)
@ -300,7 +300,7 @@ bool IsTileSolid(Point position)
return false;
}
return nSolidTable[dPiece[position.x][position.y]];
return TileHasAny(dPiece[position.x][position.y], TileProperties::Solid);
}
bool IsTileWalkable(Point position, bool ignoreDoors)

8
Source/scrollrt.cpp

@ -656,8 +656,8 @@ void DrawCell(const Surface &out, Point tilePosition, Point targetBufferPosition
{
MICROS *pMap = &dpiece_defs_map_2[tilePosition.x][tilePosition.y];
level_piece_id = dPiece[tilePosition.x][tilePosition.y];
cel_transparency_active = nTransTable[level_piece_id] && TransList[dTransVal[tilePosition.x][tilePosition.y]];
cel_foliage_active = !nSolidTable[level_piece_id];
cel_transparency_active = TileHasAny(level_piece_id, TileProperties::Transparent) && TransList[dTransVal[tilePosition.x][tilePosition.y]];
cel_foliage_active = !TileHasAny(level_piece_id, TileProperties::Solid);
for (int i = 0; i < (MicroTileLen / 2); i++) {
level_cel_block = pMap->mt[2 * i];
if (level_cel_block != 0) {
@ -930,7 +930,7 @@ void DrawFloor(const Surface &out, Point tilePosition, Point targetBufferPositio
if (InDungeonBounds(tilePosition)) {
level_piece_id = dPiece[tilePosition.x][tilePosition.y];
if (level_piece_id != 0) {
if (!nSolidTable[level_piece_id])
if (!TileHasAny(level_piece_id, TileProperties::Solid))
DrawFloor(out, tilePosition, targetBufferPosition);
} else {
world_draw_black_tile(out, targetBufferPosition.x, targetBufferPosition.y);
@ -959,7 +959,7 @@ void DrawFloor(const Surface &out, Point tilePosition, Point targetBufferPositio
}
}
#define IsWall(x, y) (dPiece[x][y] == 0 || nSolidTable[dPiece[x][y]] || dSpecial[x][y] != 0)
#define IsWall(x, y) (dPiece[x][y] == 0 || TileHasAny(dPiece[x][y], TileProperties::Solid) || dSpecial[x][y] != 0)
#define IsWalkable(x, y) (dPiece[x][y] != 0 && IsTileNotSolid({ x, y }))
/**

8
Source/themes.cpp

@ -58,7 +58,7 @@ bool TFit_Shrine(int i)
while (found == 0) {
Point testPosition { xp, yp };
if (dTransVal[xp][yp] == themes[i].ttval) {
if (nTrapTable[dPiece[xp][yp - 1]]
if (TileHasAny(dPiece[xp][yp - 1], TileProperties::Trap)
&& IsTileNotSolid(testPosition + Direction::NorthWest)
&& IsTileNotSolid(testPosition + Direction::SouthEast)
&& dTransVal[xp - 1][yp] == themes[i].ttval
@ -68,7 +68,7 @@ bool TFit_Shrine(int i)
found = 1;
}
if (found == 0
&& nTrapTable[dPiece[xp - 1][yp]]
&& TileHasAny(dPiece[xp - 1][yp], TileProperties::Trap)
&& IsTileNotSolid(testPosition + Direction::NorthEast)
&& IsTileNotSolid(testPosition + Direction::SouthWest)
&& dTransVal[xp][yp - 1] == themes[i].ttval
@ -106,7 +106,7 @@ bool TFit_Obj5(int t)
if (dTransVal[xp][yp] == themes[t].ttval && IsTileNotSolid({ xp, yp })) {
found = true;
for (int i = 0; found && i < 25; i++) {
if (nSolidTable[dPiece[xp + trm5x[i]][yp + trm5y[i]]]) {
if (TileHasAny(dPiece[xp + trm5x[i]][yp + trm5y[i]], TileProperties::Solid)) {
found = false;
}
if (dTransVal[xp + trm5x[i]][yp + trm5y[i]] != themes[t].ttval) {
@ -368,7 +368,7 @@ bool CheckThemeRoom(int tv)
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dTransVal[i][j] != tv || nSolidTable[dPiece[i][j]])
if (dTransVal[i][j] != tv || TileHasAny(dPiece[i][j], TileProperties::Solid))
continue;
if (dTransVal[i - 1][j] != tv && IsTileNotSolid({ i - 1, j }))
return false;

44
test/path_test.cpp

@ -44,13 +44,13 @@ TEST(PathTest, Heuristics)
TEST(PathTest, Solid)
{
dPiece[5][5] = 0;
nSolidTable[0] = true;
dPiece[5][5] = 1;
SOLData[0] = TileProperties::Solid;
EXPECT_TRUE(IsTileSolid({ 5, 5 })) << "Solid in-bounds tiles are solid";
EXPECT_FALSE(IsTileNotSolid({ 5, 5 })) << "IsTileNotSolid returns the inverse of IsTileSolid for in-bounds tiles";
dPiece[6][6] = 1;
nSolidTable[1] = false;
dPiece[6][6] = 2;
SOLData[1] = TileProperties::None;
EXPECT_FALSE(IsTileSolid({ 6, 6 })) << "Non-solid in-bounds tiles are not solid";
EXPECT_TRUE(IsTileNotSolid({ 6, 6 })) << "IsTileNotSolid returns the inverse of IsTileSolid for in-bounds tiles";
@ -60,18 +60,18 @@ TEST(PathTest, Solid)
TEST(PathTest, SolidPieces)
{
dPiece[0][0] = 0;
dPiece[0][1] = 0;
dPiece[1][0] = 0;
dPiece[1][1] = 0;
nSolidTable[0] = false;
dPiece[0][0] = 1;
dPiece[0][1] = 1;
dPiece[1][0] = 1;
dPiece[1][1] = 1;
SOLData[0] = TileProperties::None;
EXPECT_TRUE(path_solid_pieces({ 0, 0 }, { 1, 1 })) << "A step in open space is free of solid pieces";
EXPECT_TRUE(path_solid_pieces({ 1, 1 }, { 0, 0 })) << "A step in open space is free of solid pieces";
EXPECT_TRUE(path_solid_pieces({ 1, 0 }, { 0, 1 })) << "A step in open space is free of solid pieces";
EXPECT_TRUE(path_solid_pieces({ 0, 1 }, { 1, 0 })) << "A step in open space is free of solid pieces";
nSolidTable[1] = true;
dPiece[1][0] = 1;
SOLData[1] = TileProperties::Solid;
dPiece[1][0] = 2;
EXPECT_TRUE(path_solid_pieces({ 0, 1 }, { 1, 0 })) << "Can path to a destination which is solid";
EXPECT_TRUE(path_solid_pieces({ 1, 0 }, { 0, 1 })) << "Can path from a starting position which is solid";
EXPECT_TRUE(path_solid_pieces({ 0, 1 }, { 1, 1 })) << "Stepping in a cardinal direction ignores solid pieces";
@ -81,24 +81,24 @@ TEST(PathTest, SolidPieces)
EXPECT_FALSE(path_solid_pieces({ 0, 0 }, { 1, 1 })) << "Can't cut a solid corner";
EXPECT_FALSE(path_solid_pieces({ 1, 1 }, { 0, 0 })) << "Can't cut a solid corner";
dPiece[0][1] = 1;
dPiece[0][1] = 2;
EXPECT_FALSE(path_solid_pieces({ 0, 0 }, { 1, 1 })) << "Can't walk through the boundary between two corners";
EXPECT_FALSE(path_solid_pieces({ 1, 1 }, { 0, 0 })) << "Can't walk through the boundary between two corners";
dPiece[1][0] = 0;
dPiece[1][0] = 1;
EXPECT_FALSE(path_solid_pieces({ 0, 0 }, { 1, 1 })) << "Can't cut a solid corner";
EXPECT_FALSE(path_solid_pieces({ 1, 1 }, { 0, 0 })) << "Can't cut a solid corner";
dPiece[0][1] = 0;
dPiece[0][1] = 1;
dPiece[0][0] = 1;
dPiece[0][0] = 2;
EXPECT_FALSE(path_solid_pieces({ 1, 0 }, { 0, 1 })) << "Can't cut a solid corner";
EXPECT_FALSE(path_solid_pieces({ 0, 1 }, { 1, 0 })) << "Can't cut a solid corner";
dPiece[1][1] = 1;
dPiece[1][1] = 2;
EXPECT_FALSE(path_solid_pieces({ 1, 0 }, { 0, 1 })) << "Can't walk through the boundary between two corners";
EXPECT_FALSE(path_solid_pieces({ 0, 1 }, { 1, 0 })) << "Can't walk through the boundary between two corners";
dPiece[0][0] = 0;
dPiece[0][0] = 1;
EXPECT_FALSE(path_solid_pieces({ 1, 0 }, { 0, 1 })) << "Can't cut a solid corner";
EXPECT_FALSE(path_solid_pieces({ 0, 1 }, { 1, 0 })) << "Can't cut a solid corner";
dPiece[1][1] = 0;
dPiece[1][1] = 1;
}
void CheckPath(Point startPosition, Point destinationPosition, std::vector<int8_t> expectedSteps)
@ -139,12 +139,12 @@ TEST(PathTest, FindPath)
TEST(PathTest, Walkable)
{
dPiece[5][5] = 0;
nSolidTable[0] = true; // Doing this manually to save running through the code in gendung.cpp
dPiece[5][5] = 1;
SOLData[0] = TileProperties::Solid; // Doing this manually to save running through the code in gendung.cpp
EXPECT_FALSE(IsTileWalkable({ 5, 5 })) << "Tile which is marked as solid should be considered blocked";
EXPECT_FALSE(IsTileWalkable({ 5, 5 }, true)) << "Solid non-door tiles remain unwalkable when ignoring doors";
nSolidTable[0] = false;
SOLData[0] = TileProperties::None;
EXPECT_TRUE(IsTileWalkable({ 5, 5 })) << "Non-solid tiles are walkable";
EXPECT_TRUE(IsTileWalkable({ 5, 5 }, true)) << "Non-solid tiles remain walkable when ignoring doors";
@ -161,7 +161,7 @@ TEST(PathTest, Walkable)
EXPECT_TRUE(IsTileWalkable({ 5, 5 })) << "Tile occupied by an open door is walkable";
EXPECT_TRUE(IsTileWalkable({ 5, 5 }, true)) << "Tile occupied by a door is considered walkable when ignoring doors";
nSolidTable[0] = true;
SOLData[0] = TileProperties::Solid;
EXPECT_FALSE(IsTileWalkable({ 5, 5 })) << "Solid tiles occupied by an open door remain unwalkable";
EXPECT_TRUE(IsTileWalkable({ 5, 5 }, true)) << "Solid tiles occupied by an open door become walkable when ignoring doors";
}

Loading…
Cancel
Save