std::string Game::getSearchString(const Position& fromPos, const Position& toPos, bool fromIsCreature/* = false*/, bool toIsCreature/* = false*/)
{
/*
* When the position is on same level and 0 to 4 squares away, they are "[toIsCreature: standing] next to you"
* When the position is on same level and 5 to 100 squares away they are "to the north/west/south/east."
* When the position is on any level and 101 to 274 squares away they are "far to the north/west/south/east."
* When the position is on any level and 275+ squares away they are "very far to the north/west/south/east."
* When the position is not directly north/west/south/east of you they are "((very) far) to the north-west/south-west/south-east/north-east."
* When the position is on a lower or higher level and 5 to 100 squares away they are "on a lower (or) higher level to the north/west/south/east."
* When the position is on a lower or higher level and 0 to 4 squares away they are "below (or) above you."
*/
enum distance_t
{
DISTANCE_BESIDE,
DISTANCE_CLOSE,
DISTANCE_FAR,
DISTANCE_VERYFAR
};
enum direction_t
{
DIR_N, DIR_S, DIR_E, DIR_W,
DIR_NE, DIR_NW, DIR_SE, DIR_SW
};
enum level_t
{
LEVEL_HIGHER,
LEVEL_LOWER,
LEVEL_SAME
};
distance_t distance;
direction_t direction;
level_t level;
int32_t dx = fromPos.x - toPos.x, dy = fromPos.y - toPos.y, dz = fromPos.z - toPos.z;
if(dz > 0)
level = LEVEL_HIGHER;
else if(dz < 0)
level = LEVEL_LOWER;
else
level = LEVEL_SAME;
if(std::abs(dx) < 5 && std::abs(dy) < 5)
distance = DISTANCE_BESIDE;
else
{
int32_t tmp = dx * dx + dy * dy;
if(tmp < 10000)
distance = DISTANCE_CLOSE;
else if(tmp < 75625)
distance = DISTANCE_FAR;
else
distance = DISTANCE_VERYFAR;
}
float tan;
if(dx != 0)
tan = (float)dy / (float)dx;
else
tan = 10.;
if(std::abs(tan) < 0.4142)
{
if(dx > 0)
direction = DIR_W;
else
direction = DIR_E;
}
else if(std::abs(tan) < 2.4142)
{
if(tan > 0)
{
if(dy > 0)
direction = DIR_NW;
else
direction = DIR_SE;
}
else
{
if(dx > 0)
direction = DIR_SW;
else
direction = DIR_NE;
}
}
else
{
if(dy > 0)
direction = DIR_N;
else
direction = DIR_S;
}
std::stringstream ss;
switch(distance)
{
case DISTANCE_BESIDE:
{
switch(level)
{
case LEVEL_SAME:
{
ss << "is ";
if(toIsCreature)
ss << "standing ";
ss << "next to you";
break;
}
case LEVEL_HIGHER:
{
ss << "is above ";
if(fromIsCreature)
ss << "you";
break;
}
case LEVEL_LOWER:
{
ss << "is below ";
if(fromIsCreature)
ss << "you";
break;
}
default:
break;
}
break;
}
case DISTANCE_CLOSE:
{
switch(level)
{
case LEVEL_SAME:
ss << "is to the";
break;
case LEVEL_HIGHER:
ss << "is on a higher level to the";
break;
case LEVEL_LOWER:
ss << "is on a lower level to the";
break;
default:
break;
}
break;
}
case DISTANCE_FAR:
ss << "is far to the";
break;
case DISTANCE_VERYFAR:
ss << "is very far to the";
break;
default:
break;
}
if(distance != DISTANCE_BESIDE)
{
ss << " ";
switch(direction)
{
case DIR_N:
ss << "north";
break;
case DIR_S:
ss << "south";
break;
case DIR_E:
ss << "east";
break;
case DIR_W:
ss << "west";
break;
case DIR_NE:
ss << "north-east";
break;
case DIR_NW:
ss << "north-west";
break;
case DIR_SE:
ss << "south-east";
break;
case DIR_SW:
ss << "south-west";
break;
default:
break;
}
}
return ss.str();
}