Merge branch 'master' of https://github.com/Wargus/stratagus
This commit is contained in:
commit
1dc013f0b1
14 changed files with 300 additions and 139 deletions
|
@ -876,6 +876,8 @@ endif()
|
|||
|
||||
if(LINUX)
|
||||
add_definitions(-DUSE_LINUX)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -ggdb")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ggdb")
|
||||
endif()
|
||||
|
||||
if(BEOS)
|
||||
|
|
|
@ -1137,7 +1137,13 @@ void AiForce::Update()
|
|||
|
||||
void AiForceManager::Update()
|
||||
{
|
||||
for (unsigned int f = 0; f < forces.size(); ++f) {
|
||||
unsigned int fsize = forces.size();
|
||||
int maxPathing = 2; // reduce load by stopping after issuing a few map searches
|
||||
for (unsigned int f = 0; f < fsize; ++f) {
|
||||
if (maxPathing < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
AiForce &force = forces[f];
|
||||
// Look if our defenders still have enemies in range.
|
||||
|
||||
|
@ -1160,6 +1166,7 @@ void AiForceManager::Update()
|
|||
if (force.Units[i]->MapDistanceTo(force.GoalPos) <= nearDist) {
|
||||
// Look if still enemies in attack range.
|
||||
const CUnit *dummy = NULL;
|
||||
maxPathing--;
|
||||
if (!AiForceEnemyFinder<AIATTACK_RANGE>(force, &dummy).found()) {
|
||||
force.ReturnToHome();
|
||||
}
|
||||
|
@ -1175,6 +1182,7 @@ void AiForceManager::Update()
|
|||
// Don't attack if there aren't our units near goal point
|
||||
std::vector<CUnit *> nearGoal;
|
||||
const Vec2i offset(15, 15);
|
||||
maxPathing--;
|
||||
Select(force.GoalPos - offset, force.GoalPos + offset, nearGoal,
|
||||
IsAnAlliedUnitOf(*force.Units[0]->Player));
|
||||
if (nearGoal.empty()) {
|
||||
|
@ -1206,6 +1214,7 @@ void AiForceManager::Update()
|
|||
}
|
||||
} else if (force.Attacking) {
|
||||
force.RemoveDeadUnit();
|
||||
maxPathing--;
|
||||
force.Update();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -459,8 +459,8 @@ extern int AiFindWall(AiForce *force);
|
|||
/// Plan the an attack
|
||||
/// Send explorers around the map
|
||||
extern void AiSendExplorers();
|
||||
/// Enemy units in distance
|
||||
extern int AiEnemyUnitsInDistance(const CPlayer &player, const CUnitType *type,
|
||||
/// Check if there are enemy units in a given range (optionally of type)
|
||||
extern bool AiEnemyUnitsInDistance(const CPlayer &player, const CUnitType *type,
|
||||
const Vec2i &pos, unsigned range);
|
||||
|
||||
//
|
||||
|
|
|
@ -169,18 +169,20 @@ static int AiCheckUnitTypeCosts(const CUnitType &type)
|
|||
return AiCheckCosts(type.Stats[AiPlayer->Player->Index].Costs);
|
||||
}
|
||||
|
||||
template <bool ignoreVisibility = false>
|
||||
class IsAEnemyUnitOf
|
||||
{
|
||||
public:
|
||||
explicit IsAEnemyUnitOf(const CPlayer &_player) : player(&_player) {}
|
||||
bool operator()(const CUnit *unit) const
|
||||
{
|
||||
return unit->IsVisibleAsGoal(*player) && unit->IsEnemy(*player);
|
||||
return (ignoreVisibility || unit->IsVisibleAsGoal(*player)) && unit->IsEnemy(*player);
|
||||
}
|
||||
private:
|
||||
const CPlayer *player;
|
||||
};
|
||||
|
||||
template <bool ignoreVisibility = false>
|
||||
class IsAEnemyUnitWhichCanCounterAttackOf
|
||||
{
|
||||
public:
|
||||
|
@ -189,7 +191,7 @@ public:
|
|||
{}
|
||||
bool operator()(const CUnit *unit) const
|
||||
{
|
||||
return unit->IsVisibleAsGoal(*player)
|
||||
return (ignoreVisibility || unit->IsVisibleAsGoal(*player))
|
||||
&& unit->IsEnemy(*player)
|
||||
&& CanTarget(*unit->Type, *type);
|
||||
}
|
||||
|
@ -199,42 +201,42 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
** Enemy units in distance.
|
||||
** Check if there are enemy units in a given range.
|
||||
**
|
||||
** @param player Find enemies of this player
|
||||
** @param type Optional unit type to check if enemy can target this
|
||||
** @param pos location
|
||||
** @param range Distance range to look.
|
||||
**
|
||||
** @return Number of enemy units.
|
||||
** @return If there are any enemy units in the range
|
||||
*/
|
||||
int AiEnemyUnitsInDistance(const CPlayer &player,
|
||||
const CUnitType *type, const Vec2i &pos, unsigned range)
|
||||
bool AiEnemyUnitsInDistance(const CPlayer &player,
|
||||
const CUnitType *type, const Vec2i &pos, unsigned range)
|
||||
{
|
||||
const Vec2i offset(range, range);
|
||||
std::vector<CUnit *> units;
|
||||
|
||||
if (type == NULL) {
|
||||
Select(pos - offset, pos + offset, units, IsAEnemyUnitOf(player));
|
||||
Select<1>(pos - offset, pos + offset, units, IsAEnemyUnitOf<true>(player));
|
||||
return static_cast<int>(units.size());
|
||||
} else {
|
||||
const Vec2i typeSize(type->TileWidth - 1, type->TileHeight - 1);
|
||||
const IsAEnemyUnitWhichCanCounterAttackOf pred(player, *type);
|
||||
const IsAEnemyUnitWhichCanCounterAttackOf<true> pred(player, *type);
|
||||
|
||||
Select(pos - offset, pos + typeSize + offset, units, pred);
|
||||
Select<1>(pos - offset, pos + typeSize + offset, units, pred);
|
||||
return static_cast<int>(units.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Enemy units in distance.
|
||||
** Check if there are enemy units in a given range.
|
||||
**
|
||||
** @param unit Find in distance for this unit.
|
||||
** @param range Distance range to look.
|
||||
**
|
||||
** @return Number of enemy units.
|
||||
** @return If there are any enemy units in the range
|
||||
*/
|
||||
int AiEnemyUnitsInDistance(const CUnit &unit, unsigned range)
|
||||
bool AiEnemyUnitsInDistance(const CUnit &unit, unsigned range)
|
||||
{
|
||||
return AiEnemyUnitsInDistance(*unit.Player, unit.Type, unit.tilePos, range);
|
||||
}
|
||||
|
|
|
@ -146,14 +146,8 @@ void StartMap(const std::string &filename, bool clean)
|
|||
UI.StatusLine.Set(NameLine);
|
||||
SetMessage("%s", _("Do it! Do it now!"));
|
||||
|
||||
long ticks = SDL_GetTicks();
|
||||
// Play the game.
|
||||
GameMainLoop();
|
||||
if (Parameters::Instance.benchmark) {
|
||||
ticks = SDL_GetTicks() - ticks;
|
||||
double fps = FrameCounter * 1000.0 / ticks;
|
||||
fprintf(stderr, "BENCHMARK RESULT: %f fps (%ldms for %ldframes)\n", fps, ticks, FrameCounter);
|
||||
}
|
||||
|
||||
// Clear screen
|
||||
Video.ClearScreen();
|
||||
|
|
|
@ -199,6 +199,8 @@ extern int AStarMovingUnitCrossingCost;
|
|||
extern bool AStarKnowUnseenTerrain;
|
||||
/// Cost of using a square we haven't seen before.
|
||||
extern int AStarUnknownTerrainCost;
|
||||
/// Maximum number of iterations of A* before giving up.
|
||||
extern int AStarMaxSearchIterations;
|
||||
|
||||
//
|
||||
// Convert heading into direction.
|
||||
|
|
|
@ -221,12 +221,14 @@ void Select(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units)
|
|||
void SelectFixed(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units);
|
||||
void SelectAroundUnit(const CUnit &unit, int range, std::vector<CUnit *> &around);
|
||||
|
||||
template <typename Pred>
|
||||
template <int selectMax = 0, typename Pred>
|
||||
void SelectFixed(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units, Pred pred)
|
||||
{
|
||||
Assert(Map.Info.IsPointOnMap(ltPos));
|
||||
Assert(Map.Info.IsPointOnMap(rbPos));
|
||||
Assert(units.empty());
|
||||
units.reserve(selectMax << 1);
|
||||
int max = selectMax || INT_MAX;
|
||||
|
||||
for (Vec2i posIt = ltPos; posIt.y != rbPos.y + 1; ++posIt.y) {
|
||||
for (posIt.x = ltPos.x; posIt.x != rbPos.x + 1; ++posIt.x) {
|
||||
|
@ -236,9 +238,17 @@ void SelectFixed(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &u
|
|||
for (size_t i = 0; i != cache.size(); ++i) {
|
||||
CUnit &unit = *cache[i];
|
||||
|
||||
if (unit.CacheLock == 0 && pred(&unit)) {
|
||||
unit.CacheLock = 1;
|
||||
units.push_back(&unit);
|
||||
if ((selectMax == 1 || unit.CacheLock == 0) && pred(&unit)) {
|
||||
if (selectMax == 1) {
|
||||
units.push_back(&unit);
|
||||
return;
|
||||
} else {
|
||||
unit.CacheLock = 1;
|
||||
units.push_back(&unit);
|
||||
if (--max == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,25 +258,25 @@ void SelectFixed(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &u
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Pred>
|
||||
void SelectAroundUnit(const CUnit &unit, int range, std::vector<CUnit *> &around, Pred pred)
|
||||
{
|
||||
const Vec2i offset(range, range);
|
||||
const Vec2i typeSize(unit.Type->TileWidth - 1, unit.Type->TileHeight - 1);
|
||||
|
||||
Select(unit.tilePos - offset,
|
||||
unit.tilePos + typeSize + offset, around,
|
||||
MakeAndPredicate(IsNotTheSameUnitAs(unit), pred));
|
||||
}
|
||||
|
||||
template <typename Pred>
|
||||
template <int selectMax = 0, typename Pred>
|
||||
void Select(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units, Pred pred)
|
||||
{
|
||||
Vec2i minPos = ltPos;
|
||||
Vec2i maxPos = rbPos;
|
||||
|
||||
Map.FixSelectionArea(minPos, maxPos);
|
||||
SelectFixed(minPos, maxPos, units, pred);
|
||||
SelectFixed<selectMax>(minPos, maxPos, units, pred);
|
||||
}
|
||||
|
||||
template <int selectMax = 0, typename Pred>
|
||||
void SelectAroundUnit(const CUnit &unit, int range, std::vector<CUnit *> &around, Pred pred)
|
||||
{
|
||||
const Vec2i offset(range, range);
|
||||
const Vec2i typeSize(unit.Type->TileWidth - 1, unit.Type->TileHeight - 1);
|
||||
|
||||
Select<selectMax>(unit.tilePos - offset,
|
||||
unit.tilePos + typeSize + offset, around,
|
||||
MakeAndPredicate(IsNotTheSameUnitAs(unit), pred));
|
||||
}
|
||||
|
||||
template <typename Pred>
|
||||
|
|
|
@ -142,6 +142,14 @@ void SetClipboard(std::string &str);
|
|||
int UTF8GetNext(const std::string &text, int curpos);
|
||||
int UTF8GetPrev(const std::string &text, int curpos);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- SIMD support
|
||||
----------------------------------------------------------------------------*/
|
||||
bool supportsSSE2();
|
||||
bool supportsAVX();
|
||||
void *aligned_malloc(size_t alignment, size_t size);
|
||||
void aligned_free(void *block);
|
||||
|
||||
//@}
|
||||
|
||||
#endif /* __UTIL_H__ */
|
||||
|
|
|
@ -51,10 +51,10 @@
|
|||
----------------------------------------------------------------------------*/
|
||||
|
||||
struct Node {
|
||||
int CostFromStart; /// Real costs to reach this point
|
||||
short int CostToGoal; /// Estimated cost to goal
|
||||
char InGoal; /// is this point in the goal
|
||||
char Direction; /// Direction for trace back
|
||||
int32_t CostFromStart; /// Real costs to reach this point
|
||||
int16_t CostToGoal; /// Estimated cost to goal
|
||||
int8_t InGoal; /// is this point in the goal
|
||||
int8_t Direction; /// Direction for trace back
|
||||
};
|
||||
|
||||
struct Open {
|
||||
|
@ -88,9 +88,6 @@ const int XY2Heading[3][3] = { {7, 6, 5}, {0, 0, 4}, {1, 2, 3}};
|
|||
static Node *AStarMatrix;
|
||||
|
||||
/// a list of close nodes, helps to speed up the matrix cleaning
|
||||
static int *CloseSet;
|
||||
static int CloseSetSize;
|
||||
static int Threshold;
|
||||
static int OpenSetMaxSize;
|
||||
static int AStarMatrixSize;
|
||||
#define MAX_CLOSE_SET_RATIO 4
|
||||
|
@ -99,6 +96,7 @@ static int AStarMatrixSize;
|
|||
/// see pathfinder.h
|
||||
int AStarFixedUnitCrossingCost;// = MaxMapWidth * MaxMapHeight;
|
||||
int AStarMovingUnitCrossingCost = 5;
|
||||
int AStarMaxSearchIterations = INT_MAX;
|
||||
bool AStarKnowUnseenTerrain = false;
|
||||
int AStarUnknownTerrainCost = 2;
|
||||
/// Used to temporary make enemy units unpassable (needs for correct path lenght calculating for automatic targeting alorithm)
|
||||
|
@ -106,6 +104,7 @@ static bool AStarFixedEnemyUnitsUnpassable = false;
|
|||
|
||||
static int AStarMapWidth;
|
||||
static int AStarMapHeight;
|
||||
static int AStarMapMax;
|
||||
|
||||
static int AStarGoalX;
|
||||
static int AStarGoalY;
|
||||
|
@ -120,8 +119,9 @@ static Open *OpenSet;
|
|||
/// The size of the open node set
|
||||
static int OpenSetSize;
|
||||
|
||||
static int *CostMoveToCache;
|
||||
static const int CacheNotSet = -5;
|
||||
static int32_t *CostMoveToCache;
|
||||
static int CostMoveToCacheSize;
|
||||
static constexpr int CacheNotSet = -1;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Profile
|
||||
|
@ -257,19 +257,23 @@ void InitAStar(int mapWidth, int mapHeight)
|
|||
|
||||
AStarMapWidth = mapWidth;
|
||||
AStarMapHeight = mapHeight;
|
||||
AStarMapMax = AStarMapWidth * AStarMapHeight;
|
||||
|
||||
AStarMatrixSize = sizeof(Node) * AStarMapWidth * AStarMapHeight;
|
||||
AStarMatrix = new Node[AStarMapWidth * AStarMapHeight];
|
||||
// align the matrix, the open set, and the cost to move cache
|
||||
// on 64-byte boundary, in case the memset/memmove operations
|
||||
// of the libc we're using has a 128/256/512bit SIMD vector
|
||||
// instruction branch, since we might be clearing 8M of
|
||||
// memory for a 2048x2048 map
|
||||
AStarMatrixSize = sizeof(Node) * AStarMapMax;
|
||||
AStarMatrix = (Node *)aligned_malloc(64, AStarMatrixSize);
|
||||
memset(AStarMatrix, 0, AStarMatrixSize);
|
||||
|
||||
Threshold = AStarMapWidth * AStarMapHeight / MAX_CLOSE_SET_RATIO;
|
||||
CloseSetSize = Threshold;
|
||||
CloseSet = new int[Threshold];
|
||||
OpenSetMaxSize = AStarMapMax / MAX_OPEN_SET_RATIO;
|
||||
OpenSet = (Open *)aligned_malloc(64, OpenSetMaxSize * sizeof(Open));
|
||||
|
||||
OpenSetMaxSize = AStarMapWidth * AStarMapHeight / MAX_OPEN_SET_RATIO;
|
||||
OpenSet = new Open[OpenSetMaxSize];
|
||||
|
||||
CostMoveToCache = new int[AStarMapWidth * AStarMapHeight];
|
||||
CostMoveToCacheSize = sizeof(int32_t) * AStarMapMax;
|
||||
CostMoveToCache = (int32_t*)aligned_malloc(64, CostMoveToCacheSize);
|
||||
memset(CostMoveToCache, CacheNotSet, CostMoveToCacheSize);
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
Heading2O[i] = Heading2Y[i] * AStarMapWidth;
|
||||
|
@ -283,15 +287,12 @@ void InitAStar(int mapWidth, int mapHeight)
|
|||
*/
|
||||
void FreeAStar()
|
||||
{
|
||||
delete[] AStarMatrix;
|
||||
aligned_free(AStarMatrix);
|
||||
AStarMatrix = NULL;
|
||||
delete[] CloseSet;
|
||||
CloseSet = NULL;
|
||||
CloseSetSize = 0;
|
||||
delete[] OpenSet;
|
||||
aligned_free(OpenSet);
|
||||
OpenSet = NULL;
|
||||
OpenSetSize = 0;
|
||||
delete[] CostMoveToCache;
|
||||
aligned_free(CostMoveToCache);
|
||||
CostMoveToCache = NULL;
|
||||
|
||||
ProfilePrint();
|
||||
|
@ -312,62 +313,14 @@ static void CostMoveToCacheCleanUp();
|
|||
static void AStarCleanUp()
|
||||
{
|
||||
ProfileBegin("AStarCleanUp");
|
||||
|
||||
if (CloseSetSize >= Threshold) {
|
||||
AStarPrepare();
|
||||
CostMoveToCacheCleanUp();
|
||||
} else {
|
||||
for (int i = 0; i < CloseSetSize; ++i) {
|
||||
AStarMatrix[CloseSet[i]].CostFromStart = 0;
|
||||
AStarMatrix[CloseSet[i]].InGoal = 0;
|
||||
CostMoveToCache[CloseSet[i]] = CacheNotSet;
|
||||
}
|
||||
}
|
||||
AStarPrepare();
|
||||
CostMoveToCacheCleanUp();
|
||||
ProfileEnd("AStarCleanUp");
|
||||
}
|
||||
|
||||
static void CostMoveToCacheCleanUp()
|
||||
{
|
||||
ProfileBegin("CostMoveToCacheCleanUp");
|
||||
int AStarMapMax = AStarMapWidth * AStarMapHeight;
|
||||
#if 1
|
||||
int *ptr = CostMoveToCache;
|
||||
#ifdef __x86_64__
|
||||
union {
|
||||
intptr_t d;
|
||||
int i[2];
|
||||
} conv;
|
||||
conv.i[0] = CacheNotSet;
|
||||
conv.i[1] = CacheNotSet;
|
||||
|
||||
if (((uintptr_t)ptr) & 4) {
|
||||
*ptr++ = CacheNotSet;
|
||||
--AStarMapMax;
|
||||
}
|
||||
#endif
|
||||
while (AStarMapMax > 3) {
|
||||
#ifdef __x86_64__
|
||||
*((intptr_t *)ptr) = conv.d;
|
||||
*((intptr_t *)(ptr + 2)) = conv.d;
|
||||
ptr += 4;
|
||||
#else
|
||||
*ptr++ = CacheNotSet;
|
||||
*ptr++ = CacheNotSet;
|
||||
*ptr++ = CacheNotSet;
|
||||
*ptr++ = CacheNotSet;
|
||||
#endif
|
||||
AStarMapMax -= 4;
|
||||
};
|
||||
while (AStarMapMax) {
|
||||
*ptr++ = CacheNotSet;
|
||||
--AStarMapMax;
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < AStarMapMax; ++i) {
|
||||
CostMoveToCache[i] = CacheNotSet;
|
||||
}
|
||||
#endif
|
||||
ProfileEnd("CostMoveToCacheCleanUp");
|
||||
memset(CostMoveToCache, CacheNotSet, CostMoveToCacheSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -496,16 +449,6 @@ static int AStarFindNode(int eo)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Add a node to the closed set
|
||||
*/
|
||||
static void AStarAddToClose(int node)
|
||||
{
|
||||
if (CloseSetSize < Threshold) {
|
||||
CloseSet[CloseSetSize++] = node;
|
||||
}
|
||||
}
|
||||
|
||||
#define GetIndex(x, y) (x) + (y) * AStarMapWidth
|
||||
|
||||
/* build-in costmoveto code */
|
||||
|
@ -605,12 +548,19 @@ static int CostMoveToCallBack_Default(unsigned int index, const CUnit &unit)
|
|||
*/
|
||||
static inline int CostMoveTo(unsigned int index, const CUnit &unit)
|
||||
{
|
||||
int *c = &CostMoveToCache[index];
|
||||
int32_t *c = &CostMoveToCache[index];
|
||||
if (*c != CacheNotSet) {
|
||||
return *c;
|
||||
// for performance reasons, CostMoveToCache uses -1 to
|
||||
// indicate it is unset, but the algorithm is simpler
|
||||
// if the range of costs is [-1, INT_MAX]. so we always
|
||||
// store everything +1
|
||||
return *c - 1;
|
||||
}
|
||||
*c = CostMoveToCallBack_Default(index, unit);
|
||||
return *c;
|
||||
*c = CostMoveToCallBack_Default(index, unit) + 1;
|
||||
#ifdef DEBUG
|
||||
Assert(c >= 0);
|
||||
#endif
|
||||
return *c - 1;
|
||||
}
|
||||
|
||||
class AStarGoalMarker
|
||||
|
@ -626,7 +576,6 @@ public:
|
|||
AStarMatrix[offset].InGoal = 1;
|
||||
*goal_reachable = true;
|
||||
}
|
||||
AStarAddToClose(offset);
|
||||
}
|
||||
private:
|
||||
const CUnit &unit;
|
||||
|
@ -957,7 +906,6 @@ int AStarFindPath(const Vec2i &startPos, const Vec2i &goalPos, int gw, int gh,
|
|||
AStarCleanUp();
|
||||
|
||||
OpenSetSize = 0;
|
||||
CloseSetSize = 0;
|
||||
|
||||
if (!AStarMarkGoal(goalPos, gw, gh, tilesizex, tilesizey, minrange, maxrange, unit)) {
|
||||
// goal is not reachable
|
||||
|
@ -981,7 +929,6 @@ int AStarFindPath(const Vec2i &startPos, const Vec2i &goalPos, int gw, int gh,
|
|||
ProfileEnd("AStarFindPath");
|
||||
return ret;
|
||||
}
|
||||
AStarAddToClose(OpenSet[0].O);
|
||||
if (AStarMatrix[eo].InGoal) {
|
||||
ret = PF_REACHED;
|
||||
ProfileEnd("AStarFindPath");
|
||||
|
@ -989,6 +936,8 @@ int AStarFindPath(const Vec2i &startPos, const Vec2i &goalPos, int gw, int gh,
|
|||
}
|
||||
Vec2i endPos;
|
||||
|
||||
int counter = AStarMaxSearchIterations;
|
||||
|
||||
// Begin search
|
||||
while (1) {
|
||||
// Find the best node of from the open set
|
||||
|
@ -1006,17 +955,13 @@ int AStarFindPath(const Vec2i &startPos, const Vec2i &goalPos, int gw, int gh,
|
|||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// If we have looked too long, then exit.
|
||||
if (!counter--) {
|
||||
// FIXME: Select a "good" point from the open set.
|
||||
// Nearest point to goal.
|
||||
// TODO: Select a "good" point from the open set.
|
||||
AstarDebugPrint("way too long\n");
|
||||
ret = PF_FAILED;
|
||||
ProfileEnd("AStarFindPath");
|
||||
return ret;
|
||||
return PF_UNREACHABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Generate successors of this node.
|
||||
|
||||
|
@ -1067,8 +1012,6 @@ int AStarFindPath(const Vec2i &startPos, const Vec2i &goalPos, int gw, int gh,
|
|||
ProfileEnd("AStarFindPath");
|
||||
return ret;
|
||||
}
|
||||
// we add the point to the close set
|
||||
AStarAddToClose(eo);
|
||||
} else if (new_cost < AStarMatrix[eo].CostFromStart) {
|
||||
// Already visited node, but we have here a better path
|
||||
// I know, it's redundant (but simpler like this)
|
||||
|
|
|
@ -93,6 +93,15 @@ static int CclAStar(lua_State *l)
|
|||
} else {
|
||||
AStarUnknownTerrainCost = i;
|
||||
}
|
||||
} else if (!strcmp(value, "max-search-iterations")) {
|
||||
++j;
|
||||
i = LuaToNumber(l, j + 1);
|
||||
if (i <= 0) {
|
||||
PrintFunction();
|
||||
fprintf(stdout, "Max A* search iterations must be strictly > 0\n");
|
||||
} else {
|
||||
AStarMaxSearchIterations = i;
|
||||
}
|
||||
} else {
|
||||
LuaError(l, "Unsupported tag: %s" _C_ value);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "ui.h"
|
||||
#include "unit.h"
|
||||
#include "video.h"
|
||||
#include "parameters.h"
|
||||
|
||||
#include <guichan.h>
|
||||
void DrawGuichanWidgets();
|
||||
|
@ -421,6 +422,8 @@ void GameMainLoop()
|
|||
|
||||
CclCommand("if (GameStarting ~= nil) then GameStarting() end");
|
||||
|
||||
long ticks = SDL_GetTicks();
|
||||
|
||||
MultiPlayerReplayEachCycle();
|
||||
|
||||
SingleGameLoop();
|
||||
|
@ -445,6 +448,12 @@ void GameMainLoop()
|
|||
NetworkQuitGame();
|
||||
EndReplayLog();
|
||||
|
||||
if (Parameters::Instance.benchmark) {
|
||||
ticks = SDL_GetTicks() - ticks;
|
||||
double fps = FrameCounter * 1000.0 / ticks;
|
||||
fprintf(stderr, "BENCHMARK RESULT: %f fps, %f cps (%ldms for %ldframes in %ldcycles)\n", fps, GameCycle * 1000.0 / ticks, ticks, FrameCounter, GameCycle);
|
||||
}
|
||||
|
||||
GameCycle = 0;
|
||||
CParticleManager::exit();
|
||||
FlagRevealMap = MapRevealModes::cHidden;
|
||||
|
|
|
@ -41,8 +41,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <malloc.h>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_STACKTRACE
|
||||
|
@ -500,3 +502,148 @@ void PrintOnStdOut(const char *format, ...)
|
|||
va_end(valist);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Check SSE/AVX support.
|
||||
This can detect the instruction support of
|
||||
SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, SSE4a, SSE5, and AVX.
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
static void __cpuid(int* cpuinfo, int info)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"xchg %%ebx, %%edi;"
|
||||
"cpuid;"
|
||||
"xchg %%ebx, %%edi;"
|
||||
:"=a" (cpuinfo[0]), "=D" (cpuinfo[1]), "=c" (cpuinfo[2]), "=d" (cpuinfo[3])
|
||||
:"0" (info)
|
||||
);
|
||||
}
|
||||
|
||||
static unsigned long long _my_xgetbv(unsigned int index)
|
||||
{
|
||||
unsigned int eax, edx;
|
||||
__asm__ __volatile__(
|
||||
"xgetbv;"
|
||||
: "=a" (eax), "=d"(edx)
|
||||
: "c" (index)
|
||||
);
|
||||
return ((unsigned long long)edx << 32) | eax;
|
||||
}
|
||||
|
||||
#else // __GNUC__
|
||||
|
||||
#define _my_xgetbv(index) _xgetbv(index)
|
||||
|
||||
#endif // __GNUC__
|
||||
|
||||
struct SIMDSupport {
|
||||
bool sseSupportted = false;
|
||||
bool sse2Supportted = false;
|
||||
bool sse3Supportted = false;
|
||||
bool ssse3Supportted = false;
|
||||
bool sse4_1Supportted = false;
|
||||
bool sse4_2Supportted = false;
|
||||
bool sse4aSupportted = false;
|
||||
bool sse5Supportted = false;
|
||||
bool avxSupportted = false;
|
||||
};
|
||||
|
||||
static struct SIMDSupport checkSIMDSupport() {
|
||||
struct SIMDSupport s;
|
||||
|
||||
int cpuinfo[4];
|
||||
__cpuid(cpuinfo, 1);
|
||||
|
||||
// Check SSE, SSE2, SSE3, SSSE3, SSE4.1, and SSE4.2 support
|
||||
s.sseSupportted = cpuinfo[3] & (1 << 25) || false;
|
||||
s.sse2Supportted = cpuinfo[3] & (1 << 26) || false;
|
||||
s.sse3Supportted = cpuinfo[2] & (1 << 0) || false;
|
||||
s.ssse3Supportted = cpuinfo[2] & (1 << 9) || false;
|
||||
s.sse4_1Supportted = cpuinfo[2] & (1 << 19) || false;
|
||||
s.sse4_2Supportted = cpuinfo[2] & (1 << 20) || false;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Check AVX support
|
||||
// References
|
||||
// http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled/
|
||||
// http://insufficientlycomplicated.wordpress.com/2011/11/07/detecting-intel-advanced-vector-extensions-avx-in-visual-studio/
|
||||
|
||||
s.avxSupportted = cpuinfo[2] & (1 << 28) || false;
|
||||
bool osxsaveSupported = cpuinfo[2] & (1 << 27) || false;
|
||||
if (osxsaveSupported && s.avxSupportted)
|
||||
{
|
||||
// _XCR_XFEATURE_ENABLED_MASK = 0
|
||||
unsigned long long xcrFeatureMask = _my_xgetbv(0);
|
||||
s.avxSupportted = (xcrFeatureMask & 0x6) == 0x6;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Check SSE4a and SSE5 support
|
||||
|
||||
// Get the number of valid extended IDs
|
||||
__cpuid(cpuinfo, 0x80000000);
|
||||
int numExtendedIds = cpuinfo[0];
|
||||
if (numExtendedIds >= 0x80000001)
|
||||
{
|
||||
__cpuid(cpuinfo, 0x80000001);
|
||||
s.sse4aSupportted = cpuinfo[2] & (1 << 6) || false;
|
||||
s.sse5Supportted = cpuinfo[2] & (1 << 11) || false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool supportsSSE2()
|
||||
{
|
||||
static struct SIMDSupport s = checkSIMDSupport();
|
||||
return s.sse2Supportted;
|
||||
}
|
||||
|
||||
bool supportsAVX()
|
||||
{
|
||||
static struct SIMDSupport s = checkSIMDSupport();
|
||||
return s.avxSupportted;
|
||||
}
|
||||
|
||||
#else // __x86_64__
|
||||
|
||||
bool supportsSSE2()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool supportsAVX()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // __x86_64__
|
||||
|
||||
void *aligned_malloc(size_t alignment, size_t size)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return _aligned_malloc(size, alignment);
|
||||
#elif _ISOC11_SOURCE
|
||||
return aligned_alloc(alignment, size);
|
||||
#else
|
||||
return memalign(alignment, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aligned_free(void *block)
|
||||
{
|
||||
#ifdef WIN32
|
||||
_aligned_free(block);
|
||||
#else
|
||||
free(block);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -719,6 +719,8 @@ const EventCallback *GetCallbacks()
|
|||
return Callbacks;
|
||||
}
|
||||
|
||||
static int SkipFrameMask = 0;
|
||||
|
||||
/**
|
||||
** Wait for interactive input event for one frame.
|
||||
**
|
||||
|
@ -738,6 +740,27 @@ void WaitEventsOneFrame()
|
|||
Uint32 ticks = SDL_GetTicks();
|
||||
if (ticks > NextFrameTicks) { // We are too slow :(
|
||||
++SlowFrameCounter;
|
||||
if (SlowFrameCounter > FRAMES_PER_SECOND) {
|
||||
unsigned long pct = (SlowFrameCounter * 100) / (FrameCounter ? FrameCounter : 1);
|
||||
bool warn = false;
|
||||
if (pct >= 40) {
|
||||
warn = (SkipFrameMask < 0b101);
|
||||
SkipFrameMask = 0b101;
|
||||
} else if (pct >= 20) {
|
||||
warn = (SkipFrameMask < 0b11);
|
||||
SkipFrameMask = 0b11;
|
||||
} else if (pct >= 10) {
|
||||
warn = (SkipFrameMask < 0b1);
|
||||
SkipFrameMask = 0b1;
|
||||
}
|
||||
if (warn) {
|
||||
fprintf(stdout, "WARNING WARNING WARNING\n"
|
||||
"Frames %lu, Slow frames %d = %lu%%, starting to render only every %d%s frame.\n",
|
||||
FrameCounter, SlowFrameCounter, pct, SkipFrameMask + 1, SkipFrameMask == 1 ? "nd" : "th");
|
||||
fflush(stdout);
|
||||
SlowFrameCounter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InputMouseTimeout(*GetCallbacks(), ticks);
|
||||
|
@ -803,6 +826,9 @@ void RealizeVideoMemory()
|
|||
if (dummyRenderer) {
|
||||
return;
|
||||
}
|
||||
if (FrameCounter & SkipFrameMask) {
|
||||
return;
|
||||
}
|
||||
if (NumRects) {
|
||||
//SDL_UpdateWindowSurfaceRects(TheWindow, Rects, NumRects);
|
||||
SDL_UpdateTexture(TheTexture, NULL, TheScreen->pixels, TheScreen->pitch);
|
||||
|
|
|
@ -201,7 +201,7 @@ void SetClipping(int left, int top, int right, int bottom)
|
|||
{
|
||||
Assert(left <= right && top <= bottom && left >= 0 && left < Video.Width
|
||||
&& top >= 0 && top < Video.Height && right >= 0
|
||||
&& right < Video.Width && bottom >= 0 && bottom < Video.Height);
|
||||
&& right <= Video.Width && bottom >= 0 && bottom <= Video.Height);
|
||||
|
||||
ClipX1 = left;
|
||||
ClipY1 = top;
|
||||
|
|
Loading…
Reference in a new issue