home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD-ROM Today (BR) Volume 4 #16
/
Cdrtv4n16.iso
/
Jogos
/
ALEXANDE
/
DEMO
/
_SETUP.1
/
BASICMAN.AI
< prev
next >
Wrap
Text File
|
1996-12-18
|
27KB
|
992 lines
import "constant.ai";
' Forward declarations
procedure AttackInZOC(movingUnit);
procedure ShootMissiles(shootingUnit);
procedure Defend(hexToDefend);
procedure RecoverUnits();
procedure Rally();
procedure PartialRecover();
procedure GetUnitsInRange();
procedure GetUnitsOutOfRange();
' GetFrontalFacings takes a list id and a facing (direction). It fills the
' list with the (2) directions of that a unit can go. It returns 1 if the
' original facing is correct, otherwise it returns 0. (NORTH and SOUTH are
' NOT valid facings).
procedure GetFrontalFacings(listID, facing)
{
var retVal;
retVal = 0;
if (facing == NORTHEAST)
{
AddToList(listID, NORTH);
AddToList(listID, NORTHEAST);
retVal = 1;
};
if (facing == EAST)
{
AddToList(listID, NORTHEAST);
AddToList(listID, SOUTHEAST);
retVal = 1;
};
if (facing == SOUTHEAST)
{
AddToList(listID, SOUTHEAST);
AddToList(listID, SOUTH);
retVal = 1;
};
if (facing == SOUTHWEST)
{
AddToList(listID, SOUTH);
AddToList(listID, SOUTHWEST);
retVal = 1;
};
if (facing == WEST)
{
AddToList(listID, SOUTHWEST);
AddToList(listID, NORTHWEST);
retVal = 1;
};
if (facing == NORTHWEST)
{
AddToList(listID, NORTHWEST);
AddToList(listID, NORTH);
retVal = 1;
};
return retVal;
};
' inProximity looks at the identifying hex lists (flank, rear, or frontal)
' to see if the hex in question is in that list. It returns TRUE if it is,
' otherwise it returns FALSE. For the identifying list types it is:
' 0 = ZOC
' 1 = flank
' 2 = rear
procedure inProximity(hexInQuestion, nation, hexType)
{
var dir, hex, hexList, retVal, unit, n, isLeader;
retVal = FALSE;
for dir = NORTH to NORTHWEST
{
hex = AdjacentHex(hexInQuestion, dir);
if (hex != -1)
{
unit = HexOccupancy(hex);
if (unit!=-1)
{
isLeader = IsLeader(unit);
if (NOT isLeader)
{
n = Query(NATION, unit);
if (n != nation)
{
hexList = GetList();
AssignList(hexList, hexType, unit); ' Assign flank hexes
if (IsMemberOf(hexList, hexInQuestion))
retVal = TRUE;
};
' ReleaseList(hexList);
};
};
};
};
return retVal;
};
'**************************************************************************
' InFlank checks to see if the hex in question is in the flank of an enemy
' unit.
procedure InFlank(hexInQuestion, nation)
{
return inProximity(hexInQuestion, nation, 1); ' 1 identifies flank hexes
};
'**************************************************************************
' InRear checks to see if the hex in question is in the rear of an enemy
' unit.
procedure InRear(hexInQuestion, nation)
{
return inProximity(hexInQuestion, nation, 2); ' 2 identifies rear hexes
};
'**************************************************************************
' InFrontal checks to see if the hex in question is in the frontal of an
' enemy unit.
procedure InFrontal(hexInQuestion, nation)
{
return inProximity(hexInQuestion, nation, 0); ' 0 identifies frontal hexes
};
'**************************************************************************
' WeightCombatPath looks at the path of a combat unit and weights it
' according to the following:
' Clear = 9
' Rear = 7
' Flank = 5
' Frontal = 2
' DS = 0
' These values may be modified in the CONSTANT.AI file.
' Currently (7/31/96), only the final hex in the path is looked at. That
' may change to be every hex is looked at.
procedure WeightCombatPath(pathID, nation)
{
var hexInQuestion, weight, w;
' Assume the path is going to be clear.
weight = CLEAR;
hexInQuestion = GetLast(pathID);
w = InFlank(hexInQuestion, nation);
if (w == TRUE)
{
weight = FLANK;
};
' A rear attack would be much more desirable than a flank attack so that
' why it is checked for after the flank
if (InRear(hexInQuestion, nation) == TRUE)
{
weight = REAR;
};
' A frontal attack is the least desirable but it needs to be checked for
' last since it is something that the unit would not want to move into
if (InFrontal(hexInQuestion, nation) == TRUE)
{
weight = FRONTAL;
};
return weight;
};
procedure GenericMove(hex);
procedure FlankingPosAcheived(hex)
{
var unit, retVal, n;
unit = HexOccupancy(hex);
retVal = False;
if (unit != -1)
{
n = Query(NATION, unit);
if (n == INDIAN)
retVal = True;
};
return retVal;
};
procedure DoNothing()
{
};
procedure GetUnitsOutOfRange(list)
{
var unit, numOutOfRange;
GroupListReset();
numOutOfRange = 0;
unit = GroupListGetNext();
while (unit != -1)
{
if (NOT InCommandRange(unit))
{
AddToList(list, unit);
numOutOfRange = numOutOfRange+1;
};
unit = GroupListGetNext();
};
return numOutOfRange;
};
procedure GetUnitsInRange(list)
{
var unit, numInRange;
GroupListReset();
numInRange = 0;
unit = GroupListGetNext();
while (unit != -1)
{
if (InCommandRange(unit))
{
AddToList(list, unit);
numInRange = numInRange+1;
};
unit = GroupListGetNext();
};
return numInRange;
};
' This procedure will tell how many of the units are engaged in battle.
' The definition of "engaged in battle" means if someone is in his ZOC OR
' he is in someone else's ZOC.
procedure GetUnitsEngagedInBattle(list)
{
var unit, nation, numEngagedInBattle, surroundingHexes, zocHexes, hex,
enemy, enemyNation, added, unitHex, leader, isLeader;
GroupListReset();
numEngagedInBattle = 0;
leader = GetLeader();
watch "Leader = " leader;
unit = GroupListGetNext();
if (unit == leader)
unit = GroupListGetNext();
while (unit != -1)
{
nation = Query(NATION, unit);
added = False;
unitHex = Query(REGION_NUM, unit);
' First, check to see if he has someone in his ZOC.
zocHexes = GetList();
AssignList(zocHexes, 0, unit); ' The 0 stands for ZOC hexes.
ResetList(zocHexes);
hex = GetNextInList(zocHexes);
while ((hex!=-1) AND (NOT added))
{
enemy = HexOccupancy(hex);
if (enemy != -1)
{
enemyNation = Query(NATION, enemy);
if (enemyNation != nation)
{
' Found an enemy in his ZOC... add him to the list.
AddToList(list, unit);
added = True;
numEngagedInBattle = numEngagedInBattle + 1;
};
};
hex = GetNextInList(zocHexes);
};
' ReleaseList(zocHexes);
' Now check to see if anyone has him in his ZOC.
surroundingHexes = GetList();
AssignList(surroundingHexes, 5, unit); ' The 5 stands for surrounding hexes.
ResetList(surroundingHexes);
hex = GetNextInList(surroundingHexes);
while ((hex != -1) AND (NOT added))
{
enemy = HexOccupancy(hex);
if (enemy != -1)
{
enemyNation = Query(NATION, enemy);
if (enemyNation != nation)
{
isLeader = IsLeader(enemy);
if (NOT isLeader)
{
ClearList(zocHexes);
AssignList(zocHexes, 0, enemy); ' The 0 stands for ZOC hexes
ResetList(zocHexes);
if (IsMemberOf(zocHexes, unitHex))
{
AddToList(list, unit);
added = True;
numEngagedInBattle = numEngagedInBattle + 1;
};
};
};
};
hex = GetNextInList(surroundingHexes);
};
' ReleaseList(surroundingHexes);
unit = GroupListGetNext();
if (unit == leader)
unit = GroupListGetNext();
};
return numEngagedInBattle;
};
procedure ParePathListDown(pathList, destHex)
{
var path, hex, shortestDist, d, tempPath, tPath;
d = SizeOfList(pathList);
ResetList(pathList);
shortestDist = 100;
path = GetNextInList(pathList);
while (path!=-1)
{
hex = GetLast(path);
d = Distance(hex, destHex);
if (d<shortestDist)
{
shortestDist = d;
' Remove all lists up to this point.
ResetList(pathList);
tempPath = GetNextInList(pathList);
while (tempPath != path)
{
tPath = tempPath;
tempPath = GetNextInList(pathList);
RemoveFromList(pathList, tPath);
' ReleaseList(tPath);
};
ResetList(pathList);
tPath = -1;
}
else
{
if (d<shortestDist)
tPath = path;
};
path = GetNextInList(pathList);
if (tPath != -1)
{
' RemoveFromList(pathList, tPath);
' ReleaseList(tPath);
};
};
d = SizeOfList(pathList);
watch "Size of pathList: " d;
};
' This procedure causes the unit to pick a hex in its ZOC and attack it.
procedure AttackFrom(unit, hex, facing)
{
var direction, zoc, d, nation, enemyNation, attacked, enemyUnit;
' Get the "pretend" ZOC of the unit.
direction = GetList();
GetFrontalFacings(direction, facing);
write "**** Here in AttackFrom ****";
watch "unit = " unit;
watch "hex = " hex;
watch "facing = " facing;
' Look at one hex and then the other one. Choose the left then the right.
ResetList(direction);
BreakPoint();
d = GetNextInList(direction);
watch "First direction = " d;
zoc = AdjacentHex(hex, d);
watch "First zoc = " zoc;
enemyUnit = HexOccupancy(zoc);
attacked = False;
nation = Query(NATION, unit);
if (enemyUnit!=-1)
{
enemyNation = Query(NATION, enemyUnit);
if (enemyNation != nation)
{
' ATTACK!
Attack(unit, zoc);
ShootMissiles(unit);
attacked = True;
};
};
d = GetNextInList(direction);
watch "Second direction = " d;
zoc = AdjacentHex(hex, d);
watch "Second zoc = " zoc;
enemyUnit = HexOccupancy(zoc);
if ( (enemyUnit != -1) AND (NOT attacked) )
{
enemyNation = Query(NATION, enemyUnit);
if (enemyNation != nation)
{
' ATTACK!
Attack(unit, zoc);
ShootMissiles(unit);
attacked = True;
};
};
return attacked;
};
' This procedure looks at the current units that can move, weights their
' paths and choose which unit to move. The units that are unable to move
' need to be passed into the unitsUnableToMove. This functions should only
' be called when the conditions are clear (no unit in the group is in
' battle). If a unit cannot move because his frontal hexes are covered (by
' friendlies), he is also not considered.
' If a unit is forced into a non-clear path, the most advantageous unit is
' moved to the most advantageous hex and assigned to combat. After that,
' this routine should NOT be called again!
procedure weightAndMove(unitsUnableToMove, destHex)
{
var whichUnitToMove, unitLookingAt, d, tempUnit, tempHex, tempDistance,
pathList, nation, shortestDist, tempPath, tPath, highPath,
highPathWeight, hex, unitHex, path, weight, unitList,
movementRemaining, movementAllowance, potentialUnitsToMove,
numUnitsToLookAt, leader, highDistance, highUnit,
unitHighPath, unitHighPathWeight, facing, retVal;
' First, create a list of units that can move. This involves checking
' the group list and NOT adding units in the "unitsUnableToMove" list
' and also excluding units that have already moved by this leader. This
' little routine also includes units that have friendlies in their
' frontal hexes
GroupListReset();
unitList = GetList();
unitLookingAt = GroupListGetNext();
while (unitLookingAt != -1)
{
if (IsMemberOf(unitsUnableToMove, unitLookingAt) == FALSE)
{
movementRemaining = Query(5, unitLookingAt);
movementAllowance = Query(4, unitLookingAt);
if (movementRemaining == movementAllowance)
{
if (CanMove(unitLookingAt))
AddToList(unitList, unitLookingAt);
};
};
unitLookingAt = GroupListGetNext();
};
whichUnitToMove = -1;
' All the units that can move are put into the 'potentialUnitsToMove'
' list. There are numUnitsToLookAt to look at. numUnitsToLookAt is
' simply the number of commands remaining for the leader.
potentialUnitsToMove = GetList();
leader = GetLeader();
numUnitsToLookAt = Query(COMMANDS_REMAINING, leader);
ResetList(unitList);
unitLookingAt = GetNextInList(unitList);
while (unitLookingAt != -1)
{
unitHex = Query(REGION_NUM, unitLookingAt);
d = Distance(unitHex, destHex);
if (SizeOfList(potentialUnitsToMove) < numUnitsToLookAt)
AddToList(potentialUnitsToMove, unitLookingAt)
else
{
' The list of potential units is full; see if the current unit will
' displace one in the list.
ResetList(potentialUnitsToMove);
tempUnit = GetNextInList(potentialUnitsToMove);
highDistance = 0;
' First, get the unit that is farthest away that already exists in
' the list of selected units.
while (tempUnit != -1)
{
tempHex = Query(REGION_NUM, tempUnit);
tempDistance = Distance(tempHex, destHex);
if (tempDistance > highDistance)
{
highDistance = tempDistance;
highUnit = tempUnit;
};
tempUnit = GetNextInList(potentialUnitsToMove);
};
' Check to see if the unit that is being looked at will replace one
' in the list.
if (d < highDistance)
{
RemoveFromList(potentialUnitsToMove, highUnit);
AddToList(potentialUnitsToMove, unitLookingAt);
};
};
unitLookingAt = GetNextInList(unitList);
};
DumpList(potentialUnitsToMove);
highPathWeight = 0;
highPath = -1;
highUnit = -1;
if (SizeOfList(potentialUnitsToMove) == 0)
{
write "No more units to move... moving the leader.";
whichUnitToMove = GetLeader();
pathList = GetList();
GetUnitPaths(whichUnitToMove, pathList);
ResetList(pathList);
highPath = GetNextInList(pathList);
watch "Leader high path = " highPath;
highPathWeight = 9; ' Force it to be 9 for now.
}
else
{
' Weight the different paths of the selected units and then move
' the one with the highest weight < 7. If all of them have 9, any one
' of them can be moved.
ResetList(potentialUnitsToMove);
unitLookingAt = GetNextInList(potentialUnitsToMove);
while (unitLookingAt != -1)
{
' Keep only the shortest paths to the dest hex. Those are most
' likely to have to keep the units from changing facing next time
' he has to move. In other words, we want him to get as close to
' the hex as possible.
nation = Query(NATION, unitLookingAt);
' Get all the potential paths that he may follow.
pathList = GetList();
GetUnitPaths(unitLookingAt, pathList);
ParePathListDown(pathList, destHex);
write "Removed some of the paths...";
' Now, weight the remaining paths and take the path of least resistance.
ResetList(pathList);
path = GetNextInList(pathList);
unitHighPath = -1;
unitHighPathWeight = -1;
while (path != -1)
{
weight = WeightCombatPath(path, nation);
if (weight > unitHighPathWeight)
{
if (unitHighPath != -1)
tPath = unitHighPath;
unitHighPath = path;
unitHighPathWeight = weight;
}
else
{
tPath = path;
};
path = GetNextInList(pathList);
if (tPath != -1)
{
' RemoveFromList(pathList, tPath);
' ReleaseList(tPath);
};
};
' I've got the unit's highest weighted path. Compare it to the
' current high path weight and replace if necessary.
if ((unitHighPathWeight > highPathWeight) AND (unitHighPathWeight != 9))
{
highPath = unitHighPath;
highPathWeight = unitHighPathWeight;
highUnit = unitLookingAt;
};
if ( (unitHighPathWeight == 9) AND (highUnit == -1) )
{
highPath = unitHighPath;
highPathWeight = unitHighPathWeight;
highUnit = unitLookingAt;
};
unitLookingAt = GetNextInList(potentialUnitsToMove);
};
' The highUnit contains the unit to move.
whichUnitToMove = highUnit;
};
write "Got the path... now moving him...";
' I have the unit, I have the path - let's move him!
hex = GetLast(highPath);
watch "The unit is moving to hex #" hex;
retVal = MoveToward(hex, whichUnitToMove);
if (retVal == 0)
{
FinishLeader();
return retVal;
};
if (highPathWeight < 9)
{
' If I get here, I need to attack somebody. There will probably be
' some logic put in here eventually to check to see if the unit
' is superior or not. If it isn't, then the attack probably won't
' happen. But, for now (8/26/96), the unit blindly attacks.
write "About to call AttackFrom...";
facing = Query(FACING, whichUnitToMove);
AttackFrom(whichUnitToMove, hex, facing);
};
' RemoveFromList(pathList, highPath);
' ReleaseList(highPath);
' ReleaseList(pathList);
' ReleaseList(potentialUnitsToMove);
};
procedure SupportMoves(battlingList, unitsOutOfRange);
procedure SupportUnit(movingUnit, unitToSupport);
procedure AttackWithSkirmishers();
procedure GenericMove(hex)
{
var outOfRangeList, battlingList, unitRallied, unitRecovered;
unitRallied = Rally();
if (unitRallied)
{
write "A unit was rallied from GenericMove";
return 1;
};
unitRecovered = PartialRecover();
if (unitRecovered)
{
write "A unit was recovered";
return 1;
};
outOfRangeList = GetList();
battlingList = GetList();
GetUnitsOutOfRange(outOfRangeList);
GetUnitsEngagedInBattle(battlingList);
' Check to see if there are no units in battle. If there aren't, weight
' units and paths and move the appropriate unit.
if (SizeOfList(battlingList) == 0)
{
' ReleaseList(battlingList);
weightAndMove(outOfRangeList, hex);
' ReleaseList(outOfRangeList);
}
else
SupportMoves(battlingList, outOfRangeList);
};
' This procedure is used for moving units to support other units already
' in combat. It should be covering a unit's flanks and his 6.
procedure SupportMoves(battlingList, unitsOutOfRange)
{
var unitList, unitLookingAt, movementRemaining, movementAllowance,
whichUnitToMove, shortestDist, unitInNeed, hex1, hex2, distance,
unitToSupport, unitType, retVal;
' Compile a list of units that can absolutely move. Units that are in
' battle are left in battle. No regard for how close a unit is to routing
' is given here.
write "Now in SupportMoves";
GroupListReset();
unitList = GetList();
unitLookingAt = GroupListGetNext();
while (unitLookingAt != -1)
{
if (IsMemberOf(battlingList, unitLookingAt) == FALSE)
{
if (IsMemberOf(unitsOutOfRange, unitLookingAt) == FALSE)
{
movementRemaining = Query(5, unitLookingAt);
movementAllowance = Query(4, unitLookingAt);
if (movementRemaining == movementAllowance)
{
if (CanMove(unitLookingAt))
{
AddToList(unitList, unitLookingAt);
};
};
};
};
unitLookingAt = GroupListGetNext();
};
' Choose which unit to move into support position. The only criteria for
' that is the two units that are closest: one is currently in battle; the
' other is capable of being moved. A more probable criteria should be
' used. This is just being used because it is simple to implement.
whichUnitToMove = -1;
unitToSupport = -1;
shortestDist = 100;
ResetList(unitList);
write "Now looking for the shortest distance between unit in need and support unit";
unitLookingAt = GetNextInList(unitList);
while (unitLookingAt != -1)
{
unitType = Query(UNIT_TYPE, unitLookingAt);
' Skirmishers can't shock so don't even consider them. If they are
' the only units left, then they will be treated extra-special later.
if (unitType != SK)
{
hex1 = Query(REGION_NUM, unitLookingAt);
ResetList(battlingList);
unitInNeed = GetNextInList(battlingList);
while (unitInNeed != -1)
{
hex2 = Query(REGION_NUM, unitInNeed);
distance = Distance(hex1,hex2);
if (distance < shortestDist)
{
shortestDist = distance;
whichUnitToMove = unitLookingAt;
unitToSupport = unitInNeed;
};
unitInNeed = GetNextInList(battlingList);
};
};
unitLookingAt = GetNextInList(unitList);
};
watch "The unit to move for support = " whichUnitToMove;
watch "Unit to be supported = " unitToSupport;
' Check to see if the unit was gotten. If not, then that means that only
' skirmishers are left and they need to be treated differently.
if (whichUnitToMove == -1)
AttackWithSkirmishers()
else
{
' Got a "real" unit. Move him appropriately...
retVal = SupportUnit(whichUnitToMove, unitToSupport);
if (retVal == 0)
FinishLeader();
};
return 1; ' What else to return?
};
procedure AttackWithSkirmishers()
{
' Just end the leader for right now.
FinishLeader();
return 1;
};
procedure SupportUnit(movingUnit, unitToSupport)
{
var flankHexes, hex1, hex2, hex1Unit, hex2Unit, occupiedHex, canAttack,
nation, unitNation, unit, zocHexes, hex, enemy, emptyHex, retVal;
write "Here in SupportUnit";
nation = Query(NATION, movingUnit);
' First, look at the flank hexes. To do that, I need to get the flank
' hexes.
write "Checking the flank hexes first.";
flankHexes = GetList();
AssignList(flankHexes, FLANK_HEXES, unitToSupport);
ResetList(flankHexes);
hex1 = GetNextInList(flankHexes);
hex2 = GetNextInList(flankHexes);
BreakPoint();
hex1Unit = HexOccupancy(hex1);
hex2Unit = HexOccupancy(hex2);
if ((hex1Unit == -1) AND (hex2Unit == -1))
{
' Both hexes are clear! Move to one of them.
write "Both flank hexes are clear, moving to one of them now...";
retVal = MoveToward(hex1, movingUnit);
if (retVal == 0)
{
FinishLeader();
return retVal;
};
' If there is someone in his ZOC, attack him...
AttackInZOC(movingUnit);
return 1;
};
' Both flank hexes are NOT clear. The priority is the second flank for
' no special reason other than it exists. But first, check to see the
' unit to see if it is an enemy or not.
occupiedHex = -1;
write "Now checking to see if they (the flanks) are occupied by enemy units";
if (hex1Unit!=-1)
{
unitNation = Query(NATION, hex1Unit);
if (unitNation != nation)
occupiedHex = hex1;
};
if (hex2Unit!=-1)
{
unitNation = Query(NATION , hex2Unit);
if (unitNation != nation)
occupiedHex = hex2;
};
if (occupiedHex != -1)
{
watch "Attacking flank hex #" occupiedHex;
' See if the hex is in his movement range, and if it is, bang it.
canAttack = CanAttack(movingUnit, occupiedHex);
if (canAttack)
{
Attack(movingUnit, occupiedHex);
ShootMissiles(movingUnit);
};
};
' There is not an enemy unit in either of the flank hexes. So, if only
' one of them is empty, move into that one.
emptyHex = -1;
if (hex1Unit == -1)
emptyHex = hex1;
if (hex2Unit == -1)
emptyHex = hex2;
if (emptyHex != -1)
{
retVal = MoveToward(emptyHex, movingUnit);
if (retVal == 0)
{
FinishLeader();
return retVal;
};
AttackInZOC(movingUnit);
return 1;
};
' If the thread of execution gets to here, its because there are two
' units flanking the target unit. Check the target's rear...
write "Now checking the rear of the unit.";
return 0;
};
procedure AttackInZOC(movingUnit)
{
var zocHexes, unit, hex, enemy;
zocHexes = GetList();
AssignList(zocHexes, ZOC_HEXES, movingUnit);
ResetList(zocHexes);
hex = GetNextInList(zocHexes);
while (hex!=-1)
{
unit = HexOccupancy(hex);
if (unit != -1)
{
enemy = IsEnemy(movingUnit, unit);
Attack(movingUnit, hex);
ShootMissiles(movingUnit);
return 1;
};
hex = GetNextInList(zocHexes);
};
};
procedure ShootMissiles(shootingUnit)
{
var zocHexes, unit, hex, enemy;
if (Query(MISSILE_CAPABLE, shootingUnit) == 0)
{
write "This unit CANNOT fire any missiles";
return 0;
};
write "This unit CAN shoot missiles";
' Look in his ZOC and just see if he can shoot somebody...
zocHexes = GetList();
AssignList(zocHexes, ZOC_HEXES, shootingUnit);
ResetList(zocHexes);
hex = GetNextInList(zocHexes);
while (hex!=-1)
{
unit = HexOccupancy(hex);
if (unit != -1)
{
enemy = IsEnemy(shootingUnit, unit);
if (enemy)
{
Fire(shootingUnit, hex);
return 1;
};
};
hex = GetNextInList(zocHexes);
};
return 0;
};
procedure Defend(hexToDefend)
{
' First, get a list of units in range and a list of units out of range.
var retVal;
write "Here in Defend";
retVal = Rally();
if (retVal)
return 1;
write "Couldn't find any units to rally!";
retVal = RecoverUnits();
if (retVal == -1)
FinishLeader();
};
procedure Rally()
{
' This function attempts to rally anyone in the leader's range.
' The return value is 1 if someone was rallied and 0 if not.
var outOfRangeUnits, numUnitsOutOfRange, routingUnitsInRange, unit, notInRange,
routing, retVal;
outOfRangeUnits = GetList();
numUnitsOutOfRange = GetUnitsOutOfRange(outOfRangeUnits);
' Get a list of units that are in range and routing...
routingUnitsInRange = GetList();
GroupListReset();
unit = GroupListGetNext();
while (unit != -1)
{
notInRange = IsMemberOf(outOfRangeUnits, unit);
routing = False;
if (NOT notInRange)
{
watch "Looking at unit " unit;
routing = Query(ROUTING, unit);
if (routing)
write "He IS routing"
else
write "He is NOT routing";
};
if (routing)
{
watch "Found a routing unit: " unit;
retVal = AttemptToRally(unit);
return retVal;
};
unit = GroupListGetNext();
};
write "Couldn't find any units to rally!";
};
procedure PartialRecover()
{
' Find any unit that is within 3 cohesion hits or routing and recover him
var unitsOutOfRange, numUnitsOutOfRange, notInRange, unit, tq, cohesionHit,
difference;
write "Here in PartialRecover";
unitsOutOfRange = GetList();
numUnitsOutOfRange = GetUnitsOutOfRange(unitsOutOfRange);
GroupListReset();
unit = GroupListGetNext();
while (unit!=-1)
{
notInRange = IsMemberOf(unitsOutOfRange, unit);
if (NOT notInRange)
{
cohesionHit = Query(COHESION_HIT, unit);
tq = Query(TROOP_Q, unit);
difference = tq-cohesionHit;
if (difference <= 3)
{
Recover(unit);
watch "Recovered unit: " unit;
return 1;
};
};
unit = GroupListGetNext();
};
return 0;
};
procedure RecoverUnits()
{
' Find all the units within range and recover he who has the most cohesion
' hits.
var unitsOutOfRange, numUnitsOutOfRange, notInRange, unit, highUnit,
highCH, cohesionHit;
write "Here in RecoverUnits";
unitsOutOfRange = GetList();
numUnitsOutOfRange = GetUnitsOutOfRange(unitsOutOfRange);
highCH = 0;
highUnit = -1;
GroupListReset();
unit = GroupListGetNext();
while (unit != -1)
{
notInRange = IsMemberOf(unitsOutOfRange, unit);
if (NOT notInRange)
{
watch "Looking at unit " unit;
cohesionHit = Query(COHESION_HIT, unit);
if (cohesionHit > highCH)
{
highCH = cohesionHit;
highUnit = unit;
watch "New high cohesion hit: " highCH;
};
};
unit = GroupListGetNext();
};
if (highUnit == -1)
{
write "There weren't any units that needed recovering...";
return -1;
};
Recover(highUnit);
return highUnit;
};