reverse jarod commit

This commit is contained in:
nehalmistry 2004-07-09 21:39:39 +00:00
parent dbcad8c49e
commit 76a15bd92f
8 changed files with 137 additions and 107 deletions

View file

@ -152,7 +152,7 @@ void ActionStillGeneric(Unit* unit, int ground)
y = TheMap.Height - 1;
}
if (x != unit->X || y != unit->Y) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, TypeMovementMask(type))) {
// FIXME: Don't use pathfinder for this, costs too much cpu.
unit->Orders[0].Action = UnitActionMove;
Assert(!unit->Orders[0].Goal);

View file

@ -50,21 +50,44 @@
-- Functions
----------------------------------------------------------------------------*/
// Flag for searching a valid tileset for unloading
#define LandUnitMask ( \
MapFieldLandUnit | \
MapFieldBuilding | \
MapFieldWall | \
MapFieldRocks | \
MapFieldForest | \
MapFieldCoastAllowed | \
MapFieldWaterAllowed | \
MapFieldUnpassable)
#define NavalUnitMask ( \
MapFieldLandUnit | \
MapFieldBuilding | \
MapFieldWall | \
MapFieldRocks | \
MapFieldForest | \
MapFieldCoastAllowed | \
MapFieldLandAllowed | \
MapFieldUnpassable)
/**
** Find a free position close to x, y for unit.
** Find a free position close to x, y
**
** @unit Unit to unload.
** @param x Original x search position
** @param y Original y search position
** @param resx Unload x position.
** @param resy Unload y position.
** @param mask Movement mask for the unit to be droped.
**
** @return True if a position was found, False otherwise.
** @note resx and resy are undefined if a position is not found.
**
** @bug FIXME: Place unit only on fields reachable from the transporter
*/
static int FindUnloadPositionForUnit(const Unit* unit, int x, int y, int* resx, int* resy)
static int FindUnloadPosition(int x, int y, int* resx, int* resy, int mask)
{
int i;
int n;
@ -77,7 +100,7 @@ static int FindUnloadPositionForUnit(const Unit* unit, int x, int y, int* resx,
// Nobody: There was some code here to check for unloading units that can
// only go on even tiles. It's useless, since we can only unload land units.
for (i = addy; i--; ++y) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
*resx = x;
*resy = y;
return 1;
@ -85,7 +108,7 @@ static int FindUnloadPositionForUnit(const Unit* unit, int x, int y, int* resx,
}
++addx;
for (i = addx; i--; ++x) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
*resx = x;
*resy = y;
return 1;
@ -93,7 +116,7 @@ static int FindUnloadPositionForUnit(const Unit* unit, int x, int y, int* resx,
}
++addy;
for (i = addy; i--; --y) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
*resx = x;
*resy = y;
return 1;
@ -101,7 +124,7 @@ static int FindUnloadPositionForUnit(const Unit* unit, int x, int y, int* resx,
}
++addx;
for (i = addx; i--; --x) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
*resx = x;
*resy = y;
return 1;
@ -112,7 +135,6 @@ static int FindUnloadPositionForUnit(const Unit* unit, int x, int y, int* resx,
return 0;
}
/**
** Reappear unit on map.
**
@ -128,7 +150,7 @@ int UnloadUnit(Unit* unit)
int y;
Assert(unit->Removed);
if (!FindUnloadPositionForUnit(unit, unit->X, unit->Y, &x, &y)) {
if (!FindUnloadPosition(unit->X, unit->Y, &x, &y, UnitMovementMask(unit))) {
return 0;
}
unit->Wait = 1; // should be correct unit has still action
@ -146,9 +168,8 @@ int UnloadUnit(Unit* unit)
** @param resy coast y position
**
** @return 1 if a location was found, 0 otherwise
** @todo Only know area.
*/
static int ClosestFreeCoast(const Unit* unit, int x, int y, int* resx, int* resy, int mask)
static int ClosestFreeCoast(int x, int y, int* resx, int* resy)
{
int i;
int addx;
@ -158,42 +179,54 @@ static int ClosestFreeCoast(const Unit* unit, int x, int y, int* resx, int* resy
int n;
addx = addy = 1;
if ((~TheMap.Fields[x + y * TheMap.Width].Flags & mask) &&
FindUnloadPositionForUnit(unit, x, y, &nullx, &nully)) {
if (CoastOnMap(x, y) &&
FindUnloadPosition(x, y, &nullx, &nully, LandUnitMask)) {
*resx = x;
*resy = y;
return 1;
}
#ifdef shortalias
#warning // rename this define.
#endif
#define shortalias \
if (x >= 0 && y >= 0 && x < TheMap.Width && y < TheMap.Height && \
(~TheMap.Fields[x + y * TheMap.Width].Flags & mask) && !UnitOnMapTile(x, y) && \
FindUnloadPositionForUnit(unit, x, y, &nullx, &nully)) { \
*resx = x; \
*resy = y; \
return 1; \
}
--x;
// The maximum distance to the coast. We have to stop somewhere...
n = 20;
while (n--) {
for (i = addy; i--; ++y) {
shortalias;
if (x >= 0 && y >= 0 && x < TheMap.Width && y < TheMap.Height &&
CoastOnMap(x, y) && !UnitOnMapTile(x, y) &&
FindUnloadPosition(x, y, &nullx, &nully, LandUnitMask)) {
*resx = x;
*resy = y;
return 1;
}
}
++addx;
for (i = addx; i--; ++x) {
shortalias;
if (x >= 0 && y >= 0 && x < TheMap.Width && y < TheMap.Height &&
CoastOnMap(x, y) && !UnitOnMapTile(x ,y) &&
FindUnloadPosition(x, y, &nullx, &nully, LandUnitMask)) {
*resx = x;
*resy = y;
return 1;
}
}
++addy;
for (i = addy; i--; --y) {
shortalias;
if (x >= 0 && y >= 0 && x < TheMap.Width && y < TheMap.Height &&
CoastOnMap(x, y) && !UnitOnMapTile(x, y) &&
FindUnloadPosition(x, y, &nullx, &nully, LandUnitMask)) {
*resx = x;
*resy = y;
return 1;
}
}
++addx;
for (i = addx; i--; --x) {
shortalias;
if (x >= 0 && y >= 0 && x < TheMap.Width && y < TheMap.Height &&
CoastOnMap(x, y) && !UnitOnMapTile(x, y) &&
FindUnloadPosition(x, y, &nullx, &nully, LandUnitMask)) {
*resx = x;
*resy = y;
return 1;
}
}
++addy;
}
@ -240,20 +273,20 @@ static int ClosestFreeDropZone(Unit* transporter, int x, int y, int* resx, int*
switch (transporterType) {
case UnitTypeLand:
// in this case, loadedType == UnitTypeSea
return ClosestFreeCoast(transporter->UnitInside, x, y, resx, resy, MapFieldCoastAllowed);
return ClosestFreeCoast(x, y, resx, resy);
case UnitTypeNaval:
// Same ( but reversed... )
return ClosestFreeCoast(transporter, x, y, resx, resy, MapFieldCoastAllowed);
return ClosestFreeCoast(x, y, resx, resy);
case UnitTypeFly:
// Now, depend of unit inside.
return ClosestFreeCoast(transporter->UnitInside, x, y, resx, resy,
MapFieldCoastAllowed | (loadedType == UnitTypeNaval) ?
MapFieldWaterAllowed : MapFieldLandAllowed);
default :
DebugPrint("unknow type for transporter\n");
abort();
return 0;
// Here we have loadedType in [ UnitTypeLand,UnitTypeNaval ]
if (loadedType == UnitTypeLand) {
return FindUnloadPosition(x, y, resx, resy, LandUnitMask);
} else {
return FindUnloadPosition(x, y, resx, resy, NavalUnitMask);
}
}
// Just to avoid a warning
return 0;
}
/**

View file

@ -473,12 +473,12 @@ extern int ForestOnMap(int x, int y);
/// Returns true, if rock on the map tile field
extern int RockOnMap(int x, int y);
/// Returns true, if the unit-type(mask can enter field with bounds check
extern int CheckedCanMoveToMask(int x, int y, int mask);
/// Returns true, if the unit-type can enter the field
extern int UnitTypeCanMoveTo(int x, int y, const UnitType* type);
/// Returns true, if the unit can enter the field
extern int UnitCanMoveTo(const Unit* unit, int x, int y);
/// Returns true, if the unittype can enter the field
extern int UnitTypeCanMoveTo(const UnitType* type, int x, int y);
extern int UnitCanMoveTo(int x, int y, const Unit* unit);
/// Preprocess map, for internal use.
extern void PreprocessMap(void);

View file

@ -380,7 +380,7 @@ int RockOnMap(int tx, int ty)
**
** @return True if could be entered, false otherwise.
*/
static int CheckedCanMoveToMask(int x, int y, int mask)
int CheckedCanMoveToMask(int x, int y, int mask)
{
if (x < 0 || y < 0 || x >= TheMap.Width || y >= TheMap.Height) {
return 0;
@ -390,45 +390,31 @@ static int CheckedCanMoveToMask(int x, int y, int mask)
}
/**
** Can an unittype move to this point.
** Can a unit of unit-type move to this point.
**
** @param unit unit to be checked.
** @param x X map tile position.
** @param y Y map tile position.
** @param type unit-type to be checked.
**
** @return True if could be entered, false otherwise.
*/
int UnitTypeCanMoveTo(const UnitType* type, int x, int y)
int UnitTypeCanMoveTo(int x, int y, const UnitType* type)
{
int addx;
int addy;
int mask; // movement mask of the unit.
Assert(type);
mask = TypeMovementMask(type);
for (addx = 0; addx < type->TileWidth; addx++) {
for (addy = 0; addy < type->TileHeight; addy++) {
if (!CheckedCanMoveToMask(x + addx, y + addy, mask)) {
return 0;
}
}
}
return 1;
return CanMoveToMask(x, y, TypeMovementMask(type));
}
/**
** Can an unit move to this point.
**
** @param unit unit to be checked.
** @param x X map tile position.
** @param y Y map tile position.
** @param unit unit to be checked.
**
** @return True if could be entered, false otherwise.
*/
int UnitCanMoveTo(const Unit* unit, int x, int y)
int UnitCanMoveTo(int x, int y, const Unit* unit)
{
Assert(unit);
return UnitTypeCanMoveTo(unit->Type, x, y);
return CanMoveToMask(x, y, TypeMovementMask(unit->Type));
}
/**

View file

@ -300,9 +300,6 @@ static int CostMoveTo(Unit* unit, int ex, int ey, int mask, int current_cost) {
if (unit->X == ex && unit->Y == ey) {
return 0;
}
if (!UnitCanMoveTo(unit, ex, ey)) {
return -1;
}
j = TheMap.Fields[ex + ey * TheMap.Width].Flags & mask;
if( j && (AStarKnowUnknown
|| IsMapFieldExplored(unit->Player, ex, ey)) ) {
@ -755,45 +752,45 @@ int NextPathElement(Unit* unit,int* pxd,int *pyd)
// Attempt to use path cache
// FIXME: If there is a goal, it may have moved, ruining the cache
*pxd = 0;
*pyd = 0;
*pxd=0;
*pyd=0;
// Goal has moved, need to recalculate path or no cached path
if(unit->Data.Move.Length <= 0 ||
(unit->Goal && (unit->Goal->X != unit->Orders[0].X
|| unit->Goal->Y != unit->Orders[0].Y))) {
result = NewPath(unit);
if( unit->Data.Move.Length <= 0 ||
( unit->Goal && (unit->Goal->X != unit->Orders[0].X
|| unit->Goal->Y != unit->Orders[0].Y)) ) {
result=NewPath(unit);
if(result == PF_UNREACHABLE) {
unit->Data.Move.Length = 0;
if( result==PF_UNREACHABLE ) {
unit->Data.Move.Length=0;
return result;
}
if(result == PF_REACHED) {
if( result==PF_REACHED ) {
return result;
}
if(unit->Goal) {
if( unit->Goal ) {
// Update Orders
unit->Orders[0].X = unit->Goal->X;
unit->Orders[0].Y = unit->Goal->Y;
unit->Orders[0].X=unit->Goal->X;
unit->Orders[0].Y=unit->Goal->Y;
}
}
*pxd = Heading2X[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length - 1]];
*pyd = Heading2Y[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length - 1]];
result = unit->Data.Move.Length;
*pxd=Heading2X[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length-1]];
*pyd=Heading2Y[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length-1]];
result=unit->Data.Move.Length;
unit->Data.Move.Length--;
if(!UnitCanMoveTo(unit, *pxd + unit->X, *pyd + unit->Y)) {
result = NewPath(unit);
if(result > 0) {
*pxd = Heading2X[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length - 1]];
*pyd = Heading2Y[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length - 1]];
if(!UnitCanMoveTo(unit, *pxd + unit->X, *pyd + unit->Y)) {
if( !CheckedCanMoveToMask(*pxd+unit->X,*pyd+unit->Y,UnitMovementMask(unit)) ) {
result=NewPath(unit);
if( result>0 ) {
*pxd=Heading2X[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length-1]];
*pyd=Heading2Y[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length-1]];
if( !CheckedCanMoveToMask(*pxd+unit->X,*pyd+unit->Y,UnitMovementMask(unit)) ) {
// There may be unit in the way, Astar may allow you to walk onto it.
result = PF_UNREACHABLE;
*pxd = 0;
*pyd = 0;
result=PF_UNREACHABLE;
*pxd=0;
*pyd=0;
} else {
result = unit->Data.Move.Length;
result=unit->Data.Move.Length;
unit->Data.Move.Length--;
}
}

View file

@ -599,6 +599,8 @@ int CastAdjustVitals(Unit* caster, const SpellType* spell,
int CastPolymorph(Unit* caster, const SpellType* spell,
const SpellActionType* action, Unit* target, int x, int y)
{
int i;
int j;
UnitType* type;
type = action->Data.Polymorph.NewForm;
@ -623,9 +625,13 @@ int CastPolymorph(Unit* caster, const SpellType* spell,
// as said somewhere else -- no corpses :)
RemoveUnit(target, NULL);
if (!UnitTypeCanMoveTo(type, x, y)) {
PlaceUnit(target, target->X, target->Y);
return 0;
for (i = 0; i < type->TileWidth; ++i) {
for (j = 0; j < type->TileHeight; ++j) {
if (!UnitTypeCanMoveTo(x + i, y + j, type)) {
PlaceUnit(target, target->X, target->Y);
return 0;
}
}
}
caster->Mana -= spell->ManaCost;
if (action->Data.Polymorph.PlayerNeutral) {

View file

@ -1003,6 +1003,7 @@ static int CclCreateUnit(lua_State* l)
Unit* unit;
int heading;
int playerno;
int mask;
int ix;
int iy;
@ -1033,7 +1034,8 @@ static int CclCreateUnit(lua_State* l)
return 0;
}
unit = MakeUnit(unittype, &Players[playerno]);
if (UnitCanMoveTo(unit, ix, iy)) {
mask = UnitMovementMask(unit);
if (CheckedCanMoveToMask(ix, iy, mask)) {
unit->Wait = 1;
PlaceUnit(unit, ix, iy);
} else {

View file

@ -1805,6 +1805,7 @@ void DropOutOnSide(Unit* unit, int heading, int addx, int addy)
int x;
int y;
int i;
int mask;
if (unit->Container) {
x = unit->Container->X;
@ -1815,6 +1816,9 @@ void DropOutOnSide(Unit* unit, int heading, int addx, int addy)
// n0b0dy: yes, when training an unit.
}
mask = UnitMovementMask(unit);
if (heading < LookingNE || heading > LookingNW) {
x += addx - 1;
--y;
@ -1836,28 +1840,28 @@ void DropOutOnSide(Unit* unit, int heading, int addx, int addy)
for (;;) {
startw:
for (i = addy; i--; ++y) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
goto found;
}
}
++addx;
starts:
for (i = addx; i--; ++x) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
goto found;
}
}
++addy;
starte:
for (i = addy; i--; --y) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
goto found;
}
}
++addx;
startn:
for (i = addx; i--; --x) {
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
goto found;
}
}
@ -1887,6 +1891,7 @@ void DropOutNearest(Unit* unit, int gx, int gy, int addx, int addy)
int bestx;
int besty;
int bestd;
int mask;
int n;
Assert(unit->Removed);
@ -1901,6 +1906,7 @@ void DropOutNearest(Unit* unit, int gx, int gy, int addx, int addy)
}
Assert(x != -1 && y != -1);
mask = UnitMovementMask(unit);
bestd = 99999;
#ifdef DEBUG
@ -1911,7 +1917,7 @@ void DropOutNearest(Unit* unit, int gx, int gy, int addx, int addy)
--x;
for (;;) {
for (i = addy; i--; ++y) { // go down
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
n = MapDistance(gx, gy, x, y);
if (n < bestd) {
bestd = n;
@ -1922,7 +1928,7 @@ void DropOutNearest(Unit* unit, int gx, int gy, int addx, int addy)
}
++addx;
for (i = addx; i--; ++x) { // go right
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
n = MapDistance(gx, gy, x, y);
if (n < bestd) {
bestd = n;
@ -1933,7 +1939,7 @@ void DropOutNearest(Unit* unit, int gx, int gy, int addx, int addy)
}
++addy;
for (i = addy; i--; --y) { // go up
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
n = MapDistance(gx, gy, x, y);
if (n < bestd) {
bestd = n;
@ -1944,7 +1950,7 @@ void DropOutNearest(Unit* unit, int gx, int gy, int addx, int addy)
}
++addx;
for (i = addx; i--; --x) { // go left
if (UnitCanMoveTo(unit, x, y)) {
if (CheckedCanMoveToMask(x, y, mask)) {
n = MapDistance(gx, gy, x, y);
if (n < bestd) {
bestd = n;