Matrix Games Forums

Forums  Register  Login  Photo Gallery  Member List  Search  Calendars  FAQ 

My Profile  Inbox  Address Book  My Subscription  My Forums  Log Out

RE: I believe this game will never happen

 
View related threads: (in this forum | in all forums)

Logged in as: Guest
Users viewing this topic: none
  Printable Version
All Forums >> [New Releases from Matrix Games] >> World in Flames >> RE: I believe this game will never happen Page: <<   < prev  1 2 [3] 4   next >   >>
Login
Message << Older Topic   Newer Topic >>
RE: I believe this game will never happen - 6/12/2013 7:51:56 PM   
Shannon V. OKeets

 

Posts: 22095
Joined: 5/19/2005
From: Honolulu, Hawaii
Status: offline
quote:

ORIGINAL: Extraneous

quote:

ORIGINAL: Shannon V. OKeets

My 10 years of playing WIF over the board yielded "very little knowledge"????


And here I thought when we started you were new at WiF.


quote:

ORIGINAL: Centuur

I think that a sane programmer who didn't play WiF over the board wouldn't start coding it... He would read the rulebook and throw the whole thing directly into a wastebucket. Far to difficult... That's why I love the fact that there is a madman here who played the game and is a skilled games programmer too...


Evidently you wouldn't pass the aptitude test for programming (yes there was/is one).

I find it laughable the way you all assume programming is such a hard thing to do.


Here is how it works in the real world.

A Systems analyst is given the project and meets with the user to define the specifications of the project

The Systems analyst then assigns Programmers from their group deadlines to write programs (executables, modules, or etc.) for the project.

The Programmers are to code and desk check their programs as completely as possible before submitting their programs to the test group.

The test group submits reports on errors found in the programs to the Systems analyst.

The Systems analyst returns the error report to the correct programmer for corrections.

The Systems analyst is responsible for seeing that all programmers provide documentation of their work, that the programmers are notified of changes from the user, and for the final presentation of the finished product.

Simple huh.

(Substitute: Developer for Systems analyst, game for project, rules for user, beta testers for test group and you have an Idea how a system design works.)

You keep assuming you know more about a topic because you've read something about it. People who work in the field have several orders of magnitude more knowledge than someone who has merely read up on a subject.

Here is some "simple programming" for you to critique. This is an excerpt of ~4000 lines of code from a module of 11,000 lines. There are ~250 modules in MWIF, totaling over 400,000 lines of code.

The following code (which references hundreds of code segments in other modules) is to determine if a stack of units that the player has picked up can move to the hex over which the player has moved the cursor. This executes in real time as the player moves the mouse over the map. For each hex the cursor passes over, a message is shown on the Main form telling the player whether the move is legal - and if not, why not. The cursor itself is also updated to either a target icon (ok move) or an X (move illegal).

By the way, the above paragraph IS the program specification for this function. It might also include a reference to the Rules as Written document for determining whether a stack of units can move to a hex. And RAW is perfectly clear in all particulars.

EDITED: For grammar and to add the last paragraph above.

---

// ****************************************************************************
function TMovingStack.CanMoveTo(const MULF: TUnitLocationFull;
var Disrupt: Boolean;
const CheckIfValid: Boolean = True;
const CheckShift: Boolean = True): TMoveResult;
var
U: TUnit;
FirstMU: TUnit; // First Moving Unit in Self.
C: TMajorCountry;
HexMP: TMajorCountry;
MPow: TMajorCountry;
Index: Longint;
RR: TRailHexData;
Old: TUnitLocationFull;
HS: THexsideRange;
MapHex: TMapStack;
SAStack: TUnitStack;
RefC: Integer; // Reference hex for sea area.
RefR: Integer;
Good: Boolean;
HasAir: Boolean;
Res: TMoveResult;
AHR: TAirHexRecord;
LHR: TLandHexRecord;
HR: TNavalHexRecord;
SectionSet: set of TSectionRange;
HQAdjacent: Boolean;
HQSameHex: Boolean;
MC: TGovernedArea;
HexHomeC: TMinorCountry;
MajC: TMajorCountry;
HexC: TMajorCountry;
HexMinC: TMinorCountry;
AirMaxRange: Integer;
ADistance: Integer;
HDistance: Integer;
CR: TLandCombatHex;
CR2: TLandCombatHex;
SameHex: Boolean;
MoveToSameHexNotOk: Boolean;
NavalUnitCounts: array [TMajorCountries] of Word;
Bombers: array [TMajorCountries] of Word;
LandUnits: array [TMajorCountries] of Word;
AirUnits: array [TMajorCountries] of Word;
MPI: TMajorCountries;
CCCount: Integer;
CCIndex: Integer; // Index for looking for Communist Chinese units.
CCUnit: TUnit;
CCFound: Boolean;
Coop: Boolean;
RebaseRangeMS: Integer;
// DistToHex: Integer;
CheckExtended: Boolean;
DoubleRange: Integer;
Shift: TShiftState;
MaxRange: Integer;
EastPol: Boolean;
BalticStat: Boolean;
F1stMovSUIndx2: Integer;
F1stMovSUni2: TUnit;
FoundMovSUni2: TUnit;
F1stMovSUIndx4: Integer;
F1stMovSUni4: TNavalUnit;
FoundMovSUni4: TNavalUnit;
CantTravel: Boolean;
Cargo: TUnit;
First: TUnit;
Second: TUnit;

procedure CheckUsingSetupTray;
begin
// ****************************************************************************
// Check for placing units on the map from the setup tray.
// ****************************************************************************
MapHex := MapStacks[MULF.Column, MULF.Row]; // Map stack of destination.
Result := CanSetup(MULF.Column, MULF.Row); // CanMoveTo.

if Result = mvOK then Result := CanStack(MapHex); // Setup stacking limits.

if (Result = mvStackingAir) and
(not MULF.AtSea) and
(UnitCount(UFilterCarrierAirUnit) = 1) then
begin
UFUnit := FindUnit(UFilterCarrierAirUnit);
UFPhase := Game.Phase;
UFSubPhase := aspNone;

if MapHex.HasUnit(UFilterCarrierCanLoadPlane) then Result := mvOK;
end;
end; // End of CheckUsingSetupTray.

function MovingNeutral: Boolean;
begin
// ****************************************************************************
// Check for neutral country trying to move.
// ****************************************************************************
Result := False;
F1stMovSUIndx2 := 0;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if F1stMovSUni2.NeutralProhibitedHex(MULF.Column, MULF.Row) then
begin
CanMoveTo := mvNeutralMove;
Result := True;
Exit;
end;

Inc(F1stMovSUIndx2);
end;
end;

function FTCFails: Boolean;
// ****************************************************************************
// Under very special circumstances, check for foreign troop commitment.
// ****************************************************************************
function NotEnoughMPOrRange: Boolean;
var
Index: Integer;
HRMP: TnavalHexRecord;
begin // Test if range and movement points permit a naval move.
Result :=
(not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index, HRMP)) or
(MaxNavalRange - HRMP.AvoidRange <= 0) or
(MaxNavalMovement - HRMP.AvoidMP <= 0);
end;

begin // FTCFails.
Result := False;

if (HexC <> nil) and // Hex must have an owner.
(FirstMU.Side = HexC.Side) and // Moving unit & hex on same side.
(HexMP <> nil) and
(HexMP.ID = HexC.ID) and
((not CheckShift) or
(not (ssCtrl in Shift)) or
(Game.Phase <> pNavalMovement) or
LoadedInPort or
NotEnoughMPOrRange) and // Use NavalHexList to check MPs and range.
(not CanMoveToCountry(Map.HexFTCCountry[MULF.Column, MULF.Row])) then
begin // 'The foreign troop commitment limit for %s will not be satisfied.'
(*
ShowMessageOK('[TMovingStack.CanMoveTo] FTCFails' +
'. HexMP = ' + HexMP.Name +
'. FirstMU''s country = ' +
Countries[FirstMU.Country].Name );
*)
CanMoveTo := mvForeignCommitment;
Result := True;
end;
end; // End of FTCFails.

function InvalidNavalGroup: Boolean;
begin
Result := False;
SectionSet := [];

if HasSurfaceAndSubs then
begin
CanMoveTo := mvSurfaceSubs; // Cannot move surface naval & subs together.
Result := True;
Exit;
end
else
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if (SectionSet <> []) and (not(F1stMovSUni2.Section in SectionSet)) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end
else
Include(SectionSet, F1stMovSUni2.Section);

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 <> nil then
begin // Units can't start in different sections.
CanMoveTo := mvNotAllSameSection;
Result := True;
Exit;
end;
end;
end; // End of InvalidNavalGroup.

function IllegalPartisanMove: Boolean;
begin
Result := False;
F1stMovSUIndx2 := 0;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if (F1stMovSUni2.UnitType = utPartisan) and
(MULF.AtSea or (Map.HexHomeCountry[MULF.Column,
MULF.Row] <> UnitHomeCountry(F1stMovSUni2))) then
begin
CanMoveTo := mvPartisan;
Result := True; // True means the the partisan was moved illegally.
Exit;
end;

Inc(F1stMovSUIndx2);
end;
end; // End of IllegalPartisanMove.

function IllegalWarlordMove: Boolean;

function CheckWarlord(var U: TUnit): Boolean;
var
Hx: TSmallPoint;
begin // True means the the warlord was moved illegally.
Result := (U.UnitType = utWarlord);

if Result then
begin
Hx := SmallPoint(TLandUnit(U).CityColumn, TLandUnit(U).CityRow);

Result := MULF.AtSea or (TGameMapArea.HexDistance(MULF, Hx) > 6);
end;
end;

begin // IllegalWarlordMove.
Result := False;
F1stMovSUIndx2 := 0;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if CheckWarlord(F1stMovSUni2) then
begin
CanMoveTo := mvWarlordRange; // Moving a warlord unit illegally.
Result := True;
Exit;
end;

Inc(F1stMovSUIndx2);
end;
end; // End of IllegalWarlordMove.

procedure ComputeUnits;
var
MStckIndx: Integer;
MStckUni: TUnit;
// ****************************************************************************
// Count the number of limited moves needed to move the stack.
// ****************************************************************************
var
MCCounter: TMajorCountries;
ConvoyPts: array [TMajorCountries] of Word; // Convoys are worth 1/2.

procedure CountUnit(var U: TUnit);
var
MCi: TMajorCountries;
begin
MCi := UnitControllingMajorCountry(U).Value;

if UFilterStackingNonConvoyNavalUnit(U) then
Inc(NavalUnitCounts[MCi])
else if UFilterConvoyUnit(U) then
Inc(ConvoyPts[MCi], TNavalUnit(U).Convoy)
else if UFilterAirUnit(U) then
begin
Inc(AirUnits[MCi]);

if UFilterBomber(U) then
Inc(Bombers[MCi]);
end
else if UFilterLandUnit(U) and (not U.LandMovesForFree) then
Inc(LandUnits[MCi]);
end;

begin // ComputeUnits.
FillChar(NavalUnitCounts, SizeOf(NavalUnitCounts), 0); // Naval unit moves.
FillChar(ConvoyPts, SizeOf(ConvoyPts), 0); // Convoys = 1/2.
FillChar(Bombers, SizeOf(Bombers), 0); // Bombing missions.
FillChar(LandUnits, SizeOf(LandUnits), 0); // Land unit moves.
FillChar(AirUnits, SizeOf(LandUnits), 0); // Air unit moves.
MStckIndx := 0;

while MStckIndx < Count do
begin
MStckUni := TUnit(Item[MStckIndx]);
CountUnit(MStckUni);
Inc(MStckIndx);
end;
// ****************************************************************************
// For every 2 convoys add 1 naval move.
// ****************************************************************************
for MCCounter := Low(TMajorCountries) to High(TMajorCountries) do
Inc(NavalUnitCounts[MCCounter], Succ(ConvoyPts[MCCounter]) div 2);
end; // End of ComputeUnits.

function RestrictedReinforcement: Boolean;
// ****************************************************************************
// Check if the player is trying to move units to reinforce an area in the
// Pacific in violation of the US Entry options/restrictions.
// ****************************************************************************
function CheckReinforcing(var U: TUnit): Boolean;
var
Loc: TSetupLocation;
begin
Result := True; // Default is violation occurs.
// ****************************************************************************
// US Entry option #26, US relocates fleet to Pearl Harbor.
// Only US naval transports and convoys can base at Honolulu or Pago Pago unless
// option #26 has been chosen.
// ****************************************************************************
if (EqualSmallPt(MULF.Hex, Honolulu) or
EqualSmallPt(MULF.Hex, PagoPago)) and
(not USEntry.OptionChosen(useRelocate)) and
UFilterUSNotPearlHarbor(U) then
begin
CanMoveTo := mvUSPearlHarbor; // Assign result for function CanMoveTo.
Exit;
end;
// ****************************************************************************
// Allied land and aircraft units are prohibited from entering certain areas of
// the map until US entry options have been taken, or the Axis has moved there.
// ****************************************************************************
if UFilterAlliedAirNotOnCarrierOrLandUnit(U) then
begin
// ****************************************************************************
// US Entry option #43, CW reinforces the NEI.
// Only NEI land and air units can enter NEI until (1) the Comonwealth and Japan
// are at war, or (2) option #43 has been selected, or (3) an axis land unit has
// entered NEI. All 3 of these are kept track of with CWCanReinforceNEI.
// ****************************************************************************
if (MC = NEI) and // MC is the country of the hex under the cursor.
(U.SourceCountry <> NEI.ID) and (not CWCanReinforceNEI) then
begin
CanMoveTo := mvCWNEI; // Assign result for function CanMoveTo.
Exit;
end;
// ****************************************************************************
// US Entry option #36, CW reinforces the Pacific.
// Allied land and air units can not enter Hong Kong or any Commonwealth
// controlled territory in the Pacific until (1) The Comonwealth and Japan are
// at war, (2) option #36 has been selected, or (3) an Axis land unit has
// entered Hong Kong or a Commonwealth controlled territory in the Pacific. All
// 3 of these are kept track of with CWCanReinforcePacific.
// ****************************************************************************
if ((MC = HongKong) or
((MC.ControllingMajorPower = Commonwealth) and
(MC.ClassType = TGovernedArea) and
MC.Pacific)) and
(not CWCanReinforcePacific) then
begin
CanMoveTo := mvCWPacific; // Assign result for function CanMoveTo.
Exit;
end;
// ****************************************************************************
// US Entry option #40, USA reinforces Guam.
// USA land and air units can not enter Guam until (1) option #40 has been
// selected or (2) an Axis land unit has entered Guam or the Marshalls. Both of
// these are kept track of with USCanReinforceGuam.
// ****************************************************************************
if EqualSmallPt(MULF.Hex, Guam) and (not USCanReinforceGuam) then
begin
CanMoveTo := mvUSGuam; // Assign result for function CanMoveTo.
Exit;
end;
// ****************************************************************************
// US Entry option #41, US reinforces the Philippines.
// USA land and air units can not enter the Philippines until (1) option #40 has
// been selected or (2) an Axis land unit has entered the Philippines. Both of
// these are kept track of with USCanReinforcePhilippines.
// In some scenarios the US starts with units in the Philippines. An exception
// is made to permit those units to relocate within the Philippines.
// Territorial units are not subject to this rule.
// ****************************************************************************
if (MC = Philippines) and
(U.SourceCountry <> Philippines.ID) and
(not USCanReinforcePhilippines) and
((not PickUpPoint.OnMap) or
(Map.HexCountry[PickUpPoint.Column, PickUpPoint.Row] <>
Philippines)) then
begin
// ****************************************************************************
// Unit's SetupGroupIndex - 1 is the index into SULocations.
// ****************************************************************************
if (Game.Phase = pSetup) and EqualSmallPt(MULF.Hex, Manila) then
begin
Loc := SULocations[U.SetupGroupIndex - 1];

if String(Loc.CityName) <> rsManila then
begin
CanMoveTo := mvUSPhilippines; // Result for function CanMoveTo.
Exit;
end;
end
else
begin
CanMoveTo := mvUSPhilippines; // Result for function CanMoveTo.
Exit;
end;
end;
end;

Result := False; // No violation occurred.
end;

begin // RestrictedReinforcement.
Result := False;
// ****************************************************************************
// Restrictions on setting up do not apply to later scenarios.
// ****************************************************************************
if CurrScenario in [scGuadalCanal, scBruteForce, scDarkness,
scDeclineAndFall] then
Exit;

if (MC <> nil) and (not HasAllUnit(UFilterPartisan)) then
begin
F1stMovSUIndx2 := 0;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if CheckReinforcing(F1stMovSUni2) then
begin
Result := True; // Move will violate restricted reinforcement.
Exit;
end;

Inc(F1stMovSUIndx2);
end;
end;
end; // End of RestrictedReinforcement.

function InsufficientAirMissions: Boolean;
var
MPIndex: TMajorCountries;
begin
Result := False;
// ****************************************************************************
// Check for exceeding air mission limits.
// ****************************************************************************
if HasAir then
begin
// ****************************************************************************
// Compare the number of bombers in the moving stack to the air mission limits
// for the owning major power.
// ****************************************************************************
for MPIndex := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPIndex];

if MPow.LegalCountry and
(MPow.CurrLimits.AirMissions <> aUnlimited) and
(Bombers[MPIndex] > MPow.CurrLimits.AirMissions) then
begin
CanMoveTo := mvAirMissions;
Result := True;
Exit;
end;
end;
end;
end; // End of InsufficientAirMissions.

function NoCooperationWithTarget: Boolean;
// ****************************************************************************
// This routine returns True if there is no cooperation or if the target is out
// of range. Otherwise it sets Good depending on the target hex's terrain.
// ****************************************************************************
function CheckForNoBombers: Boolean;
var
NoNeedToCheck: Boolean;
// ****************************************************************************
// This routine returns True if there no bombers in the target hex and a fighter
// is attempting to fly to the hex.
// ****************************************************************************
begin
// ****************************************************************************
// There is no need to check for bombers during:
// AspCAP,
// during any subphase except AspFlyA of non-GroundSupport air missions,
// during any subphase except AspFlyA and AspFlyD of Ground Support missions.
// ****************************************************************************
NoNeedToCheck := (Game.AirSubPhase = AspCAP) or
((Game.Phase <> pGroundSupport) and
(Game.AirSubPhase <> AspFlyA)) or
((Game.Phase = pGroundSupport) and
(not (Game.AirSubPhase in [AspFlyA, AspFlyD])));

if NoNeedToCheck then
begin
Result := False;
Exit;
end;
// ****************************************************************************
// Check for fighter flying day missions.
// ****************************************************************************
Result := HasUnit(UFilterFighterDayMission) and
(not HasUnit(UFilterBomberDayMission)) and // No bomber in stack.
(((Game.AirSubPhase = AspFlyA) and // No bomber in hex.
(not MapHex.HasUnit(UFilterBomberFlyingDayMission))) or
((Game.AirSubPhase = AspFlyD) and
(not OtherStackFilter(MapHex,
UFilterFriendlyBomberFlyingDayMission))
and
((not OtherStackFilter(MapHex,
UFilterEnemyFlyingDayMission)) or
(Self.AirDistanceFromTo(PickUpPoint, MULF.Hex, MaxRange) >
MaxRange))));

if Result then Exit;
// ****************************************************************************
// Check for bombers flying night missions.
// ****************************************************************************
Result := HasUnit(UFilterFighterNightMission) and
(not HasUnit(UFilterBomberNightMission)) and // No bomber in stack.
(((Game.AirSubPhase = AspFlyA) and // No bomber in hex.
(not MapHex.HasUnit(UFilterBomberFlyingNightMission))) or
((Game.AirSubPhase = AspFlyD) and
(not OtherStackFilter(MapHex,
UFilterFriendlyBomberFlyingNightMission))
and
((not OtherStackFilter(MapHex,
UFilterEnemyFlyingNightMission)) or
(Self.AirDistanceFromTo(PickUpPoint, MULF.Hex, MaxRange) >
Values.ARngMax))));
end;

begin
// ****************************************************************************
// NoCooperationWithTarget.
// Set cooperation with target units during ground strikes and ground support.
// Check artillery too if ground strike or ground support phase.
// ****************************************************************************
if HasAir or (Game.Phase in [pGroundSupport, pGroundStrike]) then
begin
if Game.Phase in [pGroundSupport, pGroundStrike] then
begin
if Side = Game.PhasingSide then // Non-phasing side is ok.
begin
LandCombatHexes.Search(MULF.Hex, Index, CR); // Land combat hex.

if CR = nil then Coop := CooperatesFlying(MapHex)
else Coop := CooperatesNotFlying(CR.CombatHexUnits) and
CooperatesFlying(MapHex);
end // Non-phasing side in ground support and ground strike.
else Coop := Cooperates(MapHex);
end
else Coop := CooperatesFlying(MapHex);
end
else Coop := True;
// ****************************************************************************
// Set MaxRange for ground support to ???
// ****************************************************************************
if Game.Phase = pGroundSupport then MaxRange := (Values.ARngMin + 1) div 2
else MaxRange := 0;
// ****************************************************************************
// Check that bombers (and artillery) correctly cooperate and are within range.
// ****************************************************************************
Result := False;

if (not Coop) or (not Self.Cooperates(Self)) then
begin
CanMoveTo := mvStackingNoCoop; // NoCooperationWithTarget.
Result := True;
end
else if CheckForNoBombers then
begin // No bombers when one must be present.
CanMoveTo := mvAirNoBombers;
Result := True;
end
else
begin
// ****************************************************************************
// Determine terrain conditions in target hex.
// ****************************************************************************
case Map.WeatherTerrain[MULF.Column, MULF.Row] of
teSea: Good := False;

teLake: Good := HasAir;

else Good := True;
end;
end; // End of non-cooperation.
end; // End of NoCooperationWithTarget.

function UnableToFlyToHex: Boolean;
begin // Called for each of the 8 air mission phases.
Result := False;

if HasAir then
begin
if (ADistance > AirMaxRange) and
// ****************************************************************************
// More severe restrictions than simply being within range apply during port
// attacks by air units that started at sea. They must be in a sea area that is
// adjacent to the port.
// ****************************************************************************
((Game.Phase <> pPortAttack) or
(not StartedAtSea) or
(ADistance > 1) or
(Map.Port[MULF.Column, MULF.Row] = ptNone)) then
begin
CanMoveTo := mvOutOfRange; // 8 air mission phases.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: UnableToFlyToHex ' +
'ADistance = ' + IntToStr(ADistance) +
'. AirMaxRange = ' + IntToStr(AirMaxRange));
*)
Result := True;
end
else if not (Game.AirSubPhase in [aspReturnA, aspReturnD]) then
begin
// ****************************************************************************
// Check for permission to fly given bad weather in the destination hex.
// ****************************************************************************
if Map.HexWeather[MULF.Column, MULF.Row] in NoAirFactorsWeather then
begin
CanMoveTo := mvAirWeather;
Result := True;
end
// ****************************************************************************
// Record aircraft that are flying at extended range.
// ****************************************************************************
else if ((Game.Phase <> pPortAttack) or
(not StartedAtSea) or
(ADistance > 1)) and
((ADistance > AirNormalRange) or
HasUnit(UFilterForceExtendedUnit)) then
begin
CanMoveTo := mvDisruptedExt;
end;
end;
end; // End of HasAir.
end; // End of UnableToFlyToHex.

function IsInTargetRange(var TargetRangeUnit: TUnit): Boolean;
begin // TargetRangeUnit is a unit in the moving stack.
Result := UnitInTargetRange(TargetRangeUnit, Game.AirSubPhase, MULF.Hex);
end;

function CantInterceptA: Boolean;
begin
Result := False;
Good := OtherStackFilter(MapHex, UFilterSelectedEnemyAirUnitMissionTime);
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: AspInterceptA ' +
'. Good = ' + BoolToStr(Good));
*)
if Good then
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if IsInTargetRange(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 = nil then
begin
CanMoveTo := mvNoTarget;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: AspInterceptA ' +
'. Failed target in range.');
*)
Exit;
end;
end;

if not Cooperates(MapHex) then // CantInterceptA.
begin
CanMoveTo := mvStackingNoCoop;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: AspInterceptA ' +
'. Failed Cooperates.');
*)
end;
end; // End of CantInterceptA.

function CantInterceptD: Boolean;
begin
Result := False;
Good := OtherStackFilter(MapHex, UFilterSelectedEnemyAirUnitMissionTime);

if Good then
begin
if (Game.Phase = pStrategicBombardment) and
MapHex.UnitsSurpriseHex then // Air interception.
begin
CanMoveTo := mvAirSurprisedHex;
Result := True;
Exit;
end
else if MapHex.SurprisedStack(Self, Game.NonPhasingSide, UFilterFlying,
UFilterAirUnit) or
((Game.Phase in [pPortAttack, pCarpetBombing, pGroundStrike,
pGroundSupport]) and
MapHex.SurprisedStack(MapHex, Game.NonPhasingSide,
UFilterFlying)) then
begin
CanMoveTo := mvAirSurprisedIntercept;
Result := True;
Exit;
end
else
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if IsInTargetRange(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 = nil then
begin
CanMoveTo := mvNoTarget;
Result := True;
Exit;
end;
end;

if not Cooperates(MapHex) then // CantInterceptD.
begin
CanMoveTo := mvStackingNoCoop;
Result := True;
end;
end;
end; // End of CantInterceptD.

function CantReturnAD: Boolean;
var
MovRes: TMoveResult;
begin // Air units only.
Result := False;
// ****************************************************************************
// When OptRules.Internment is active, air units belonging to minor countries
// can fly into neutral minor countries to be interned. This can happen at any
// time that the air unit can fly (e.g., return to base, forced rebase, etc.).
// The following conditionals permit these moves.
// ****************************************************************************
Good := OptRules.Internment and
(FirstMU is TAirUnit) and
(UnitHomeCountryCommonwealth(FirstMU).ClassType = TMinorCountry) and
MULF.OnLand and
(Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.ClassType =
TMinorCountry) and
(not Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.Conquered)
and
Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.Neutral;

if not Good then
begin
Good := FriendlyHex(MULF.Column, MULF.Row);

if not Good then
begin
CanMoveTo := mvNotAFriendlyHex;
Result := True;
end
else
begin
if EnemyStack(MapHex) then
begin
CanMoveTo := mvEnemyUnit;
Result := True;
end
else
begin
MovRes := CanStack(MapHex, False, nil, False, True); // Air units only.
CanMoveTo := MovRes;
Result := MovRes <> mvOK;
end;
end;
end;
end; // End of CantReturnAD.

function InvalidNavalMove: Boolean;
var
MovRes: TMoveResult;
begin
Result := False;
// ****************************************************************************
// Test stacking limits for moving naval units.
// ****************************************************************************
// if Game.DigressionInProgress or
// (Game.Phase in [pReturnToBaseA, pReturnToBaseD]) then
// begin
MovRes := CanStack(MapHex);

if MovRes <> mvOK then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = MovRes.');
*)
if MULF.OnLand and (Map.Port[MULF.Column, MULF.Row] = ptNone) then
begin
CanMoveTo := mvNoPort;
Result := True;
Exit;
end
else
begin
if MULF.OnLand and
(Map.Port[MULF.Column, MULF.Row] <> ptNone) and
(MovRes in [mvStackingLand, mvStackingAir, mvStackingFlyingBoat,
mvStackingNaval]) then
begin // Nothing needs to be done here?

end
else
begin
CanMoveTo := MovRes;
Result := True;
Exit;
end;
end;
end;
// ****************************************************************************
// Test moving naval units during Vichy formation.
// In the Vichy subphases vspMoveFrenchAtSea, vspMoveFrenchNavalAxis, and
// vspMoveFrenchNavalAllied NearHexes stores the legal hex destinations.
// ****************************************************************************
if (Game.Phase = pVichy) and
(Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied]) then
begin
if NearHexes.Empty then
begin
CanMoveTo := mvNoAbortPort;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove NearHexes ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNoAbortPort.');
*)
end
else if not NearHexes.Search(MULF.Column, MULF.Row) then
begin
CanMoveTo := mvNotClosest;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNotClosest.');
*)
end;
end
// ****************************************************************************
// Test whether the hex is a valid destination or waypoint. This sets HR.
// ****************************************************************************
else if not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index, HR) then
begin
if MULF.AtSea and
(CurrScenario <> scGuadalCanal) and
(not SeaAreas[MULF.SeaAreaID].LegalSeaArea) then
begin // Barbarossa and half map scenarios only.
CanMoveTo := mvIllegalSeaArea;
Result := True;
end
else if StartedAtSea and
MULF.AtSea and
((Old.SeaAreaID <> MULF.SeaAreaID) or
// ****************************************************************************
// A stack can't move into the sea area where it started if interception is
// possible. So, if you leave a sea area (S) and then return to S, and enemy
// units can intercept the moving stack in S, then S is not a valid destination.
// ****************************************************************************
(HR.DirectMP > 0)) then
begin
CanMoveTo := mvNoSeaArea;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNoSeaArea.');
*)
end
else if Game.DigressionInProgress and
(Game.CurrentDigression = digOverrun) then
begin
CanMoveTo := mvMoveToPortWithinRange;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvMoveToPortWithinRange.');
*)
end
else if Game.Phase = pNavalMovement then
begin
CanMoveTo := mvMP;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvMP' +
'. NavalHexList count = ' + IntToStr(NavalHexList.Count));
*)
end
else if NavalHexList.Empty then
begin
CanMoveTo := mvNoAbortPort;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove NavalHexList ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNoAbortPort.');
*)
end
else
begin
CanMoveTo := mvMoveToPort;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvMoveToPort.');
*)
end;
end
else
// ****************************************************************************
// Even though the sea area in is NavalHexList, you may only be allowed to move
// there if using control-left-click. It cannot be a final stopping place.
// ****************************************************************************
begin
if MULF.AtSea and
(Shift * [ssCtrl] = []) and // Not Ctrl-Left-Shift.
((Game.DigressionInProgress and
(not HR.EnemyZOC)) or // Must end in a port.
// ****************************************************************************
// A stack can only end its move in the sea area where it started if it hasn't
// moved.
// ****************************************************************************
(StartedAtSea and
((Old.SeaAreaID <> MULF.SeaAreaID) or
((Old.SeaAreaID = MULF.SeaAreaID) and
(MPUsedSoFar > 0))))) then
begin
CanMoveTo := mvPassThruSeaArea;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvPassThruSeaArea.' +
'. Old sea area = ' + SeaAreas[Old.SeaAreaID].Name +
'. New sea area = ' + SeaAreas[MULF.SeaAreaID].Name +
'. DirectMP = ' + IntToStr(HR.DirectMP));
*)
end;
end;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. About to call CheckIfValid.');
*)
// ****************************************************************************
// Not Result means the move is ok to make.
// ****************************************************************************
if (not Result) and
CheckIfValid and
(not HR.ValidMove) and
(not (Game.VichySubPhase in [vspMoveFrenchAtSea, vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied])) then
begin
CanMoveTo := mvMoveThroughEnemySeaArea;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvMoveThroughEnemySeaArea.');
*)
end;
// end;
end; // End of InvalidNavalMove.

function InvalidNavalAirNavalMission: Boolean;
begin
Result := False;

if HasUnit(UFilterNightMission) then
begin
CanMoveTo := mvNightNavalAir; // Naval Air night missions not permitted.
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalAirNavalMission ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNightNavalAir.');
*)
end
else
begin
if (Map.HexWeather[MULF.Column, MULF.Row] in NoAirFactorsWeather) then
begin
CanMoveTo := mvAirWeather; // Flights not permitted into bad weather.
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalAirNavalMission ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvAirWeather.');
*)
end;
end;
end;

function InvalidNavalAirSupport: Boolean;
begin
Result := False;
// ****************************************************************************
// Check for trying to move the stack to a hex not in the sea area where the
// current naval combat is occurring.
// ****************************************************************************
if (not MULF.AtSea) or
(MULF.SeaAreaID <> Game.CurrNavalCombat.NCHSeaArea.ID) then
begin
CanMoveTo := mvCombatSeaArea;
Result := True;
end;
end;
(*
if ((Game.Phase in [pReturnToBaseA, pReturnToBaseD]) or
Game.NavalCombatAbortDigress) or
(P in [pNavalAir, pNavalCombatA, pNavalCombatD]) then
end;
*)
function InvalidDestination(const CanUseDoubleRange: Boolean = True): Boolean;
var // Only air units. Not used for the 8 air missions or air rebases.
MovRes: TMoveResult;
MaximumRange: Integer;
begin
Result := False;

if not (FirstMU is TAirUnit) then Exit;

if MULF.AtSea then
begin // Moving to a sea area.
UFUnit := FirstMU;

if StartedAtSea then
begin
if (Game.Phase in ReturnToBasePhases) or
Game.NavalCombatAbortDigress or
(MULF.SeaAreaID <> PickUpPoint.SeaAreaID) then
begin
CanMoveTo := mvNavalAirOtherSeaArea;
Result := True; // Cannot fly Naval Air into a different sea area.
end
else
begin
// ****************************************************************************
// rsNavalAirSection0 = 'You can only fly to the same sea area if you can ' +
// 'move to a lower section'. This is not possible from section zero.
// ****************************************************************************
if FirstMU.Section = 0 then
begin
CanMoveTo := mvNavalAirSection0;
Result := True;
end;
end;
end;
end
else
begin // Moving to a land hex.
C := TMajorCountry(Countries[FirstMU.ControllingMajorCountry]);

if ((Game.Phase <> pVichy) or
(not (Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied]))) and
((HexC <> nil) and
(HexC.Side = OtherSide(C.Side))) then
begin
CanMoveTo := mvHexControl;

// ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidDestination ');

Result := True;
end
else if EnemyStack(MapHex) then
begin
CanMoveTo := mvEnemyUnit;
Result := True;
end;
end; // End of moving to a land hex.

if not Result then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: Range check.');

// ****************************************************************************
// If the air unit is at sea flying at extended range, then it can use extended
// range to return to base.
// ****************************************************************************
if CanUseDoubleRange or (TAirUnit(FirstMU).FlyingExtended) then
MaximumRange := AirMaxRange * 2
else
MaximumRange := AirMaxRange;

if Map.AirDistance(Game.Phase, FirstMU, PickUpPoint, MULF.Hex,
UnitHomeCountryCommonwealth(FirstMU),
MaximumRange) +
(Ord(Game.SectionRangePhase or
((Game.DigressionInProgress) and
(Game.CurrentDigression = digReturnToBase))) *
SeaAreaRange[FirstMU.Section]) >
MaximumRange then
begin
CanMoveTo := mvOutOfRange; // Not used for the air missions or rebases.

// ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidDestination ' +
// 'MaximumRange = ' + IntToStr(MaximumRange));

Result := True;
end;
end;

if not Result then
begin
MovRes := CanStack(MapHex);

if MovRes <> mvOK then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidDestination ' +
// 'Can not stack in hex.');

CanMoveTo := MovRes;
Result := True;
end;
end;
end;

function NotLoaded(var U: TUnit): Boolean;
var
AU: TAirUnit;
begin
AU := TAirUnit(U);
Result := (U is TAirUnit) and AU.Bomber and (AU.TransportingTotal = 0);
end;

function NotSupplyLoaded(var U: TUnit): Boolean;
var
AU: TAirUnit;
begin
Result := False;
AU := TAirUnit(U);

if (U is TAirUnit) and
AU.Bomber and
(AU.AirTransport = atrNormal) and
(AU.TransportingTotal = 1) and
(AU.TransLink[1].UnitType in LargeAirTransportSet) then
begin // LargeAirTransportSet = [utArmoredParatroop, utSupply].
Cargo := AU.TransLink[1]; // AU's cargo.

// ShowMessageOK('[TMovingStack.CanMoveTo] NotSupplyLoaded with Cargo = ' +
// Cargo.ViewName);

First := Cargo.TransportedByWhom; // First transport carrying Cargo.
Second := Cargo.TransLink[2]; // Cargo stores 2nd transporting unit.
Result := (First = nil) or
(Second = nil) or
(IndexOf(Second) = tbNone) or
(IndexOf(First) = tbNone);
end;
end;

function IsAirLandingUnit(var U: TUnit): Boolean;
begin
Result := (U.UnitType = utAirLanding) and U.AboardTransport;
end;

function IsParatroopUnit(var PU: TUnit): Boolean;
begin
Result := (PU.UnitType = utParatroop)
and PU.AboardTransport and PU.Cooperates(U);
end;

function NoAttack(var U: TUnit): Boolean;
var
CR3: TLandCombatHex;
UIndx: Integer;
UInStack: TUnit;
MPCont: TMajorCountry;
begin
if U.Country = CommunistChina.ID then
begin
if CCLimitsCurr.LandAttacks = aUnlimited then
begin
Result := False; // Unlimited attacks permitted.
Exit;
end;

if LandCombatHexes.Search(MULF.Hex, Index, CR3) then
begin
for UIndx := 0 to CR3.CombatHexUnits.Count - 1 do
begin
UInStack := CR3.CombatHexUnits[UIndx];

if UInStack.Country = CommunistChina.ID then
begin
Result := False; // Another CC unit added to existing attack.
Exit;
end;
end;

Result := CCLimitsCurr.LandAttacks = 0; // New attack needed.
end
else
Result := CCLimitsCurr.LandAttacks = 0; // New attack needed.
end
else
begin // Not a Communist Chinese unit.
MPCont := UnitControllingMajorCountry(U);

if MPCont.CurrLimits.LandAttacks = aUnlimited then
begin
Result := False; // Unlimited attacks permitted.
Exit;
end;

if LandCombatHexes.Search(MULF.Hex, Index, CR3) and
(MPCont.Value in CR3.AttLandMPs) then
Result := False// Another MPCont unit added to existing attack.
else
Result := MPCont.CurrLimits.LandAttacks = 0; // New attack needed.
end;
end;

function NoSB(var U: TNavalUnit): Boolean;
begin // SB = Shore Bombardment.
Result := not U.CanShoreBombardHex(MULF.Column, MULF.Row,
Game.Phase = pShoreBombardmentA);
end;

function NoSBFactors(var U: TNavalUnit): Boolean;
begin // SB = Shore Bombardment.
Result := U.BombardmentHex[MULF.Column, MULF.Row] = 0;
end;

function AnyWillBeDisrupted: Boolean;
var
F1stMovSUIndx: Integer;
F1stMovSUni: TLandUnit;
FoundMovSUni: TLandUnit;
begin
F1stMovSUIndx := 0;
FoundMovSUni := nil;

while F1stMovSUIndx < Count do
begin
F1stMovSUni := TLandUnit(Item[F1stMovSUIndx]);

if F1stMovSUni.TerrainMP[MULF.Column, MULF.Row] >
F1stMovSUni.CurrMove then
begin
FoundMovSUni := F1stMovSUni;
Break;
end;

Inc(F1stMovSUIndx);
end;

Result := FoundMovSUni <> nil;
end;

function DoesntCooperatesWithHex(const SelfU: TUnit): Boolean;
begin
(*
if HexMinC = nil then
MainForm.DebugPanel.Caption :=
'[TMovingStack.CanMoveTo]: DoesntCooperatesWithHex ' +
HexName(MULF.Hex) + '. HexMinC is nil.'
else
MainForm.DebugPanel.Caption :=
'[TMovingStack.CanMoveTo]: DoesntCooperatesWithHex ' +
HexName(MULF.Hex) + '. ' + HexMinC.Name;
*)
Result := (HexMinC <> nil) and (not HexMinC.CooperatesWith(SelfU.Country));
end;

function DoesCooperate(var U: TUnit): Boolean;
var // This routine is only called when flying CAP.
F1stMovSUIndx: Integer;
F1stMovSUni: TUnit;
FoundMovSUni: TUnit;
// ****************************************************************************
// Returns True if U cooperates with any units in Self.
// ****************************************************************************
function CooperatesWithUnit(var SelfU: TUnit): Boolean;
var
MinC2: TMinorCountry;
begin
MinC2 := Countries[SelfU.Country].HomeCountryCommonwealth;
Result := MinC2.CooperatesWith(U.Country);
end;

begin // DoesCooperate.
Result := Game.NonPhasingSide = U.Side; // Only check units on non-phasing side.

if Result then
begin
F1stMovSUIndx := 0;
FoundMovSUni := nil;

while F1stMovSUIndx < Count do
begin
F1stMovSUni := TUnit(Item[F1stMovSUIndx]);

if CooperatesWithUnit(F1stMovSUni) then
begin
FoundMovSUni := F1stMovSUni;
Break;
end;

Inc(F1stMovSUIndx);
end;

Result := FoundMovSUni <> nil;
end;
end;

begin
// ****************************************************************************
// TMovingStack.CanMoveTo.
// ****************************************************************************
Disrupt := False; // Initialize var parameter.
// ****************************************************************************
// No units may enter the Qattara Depression.
// ****************************************************************************
if Map.Terrain[MULF.Column, MULF.Row] = teQattaraDepression then
begin
Result := mvQattara;
Exit;
end;
// ****************************************************************************
// Switch the meaning of Left-Control-Click and Left-Click.
// ****************************************************************************
if CheckShift then
begin
Shift := CurrentShiftState;

if MoveCtrlKey then
begin
if Shift * [ssLeft, ssCtrl] = [ssLeft, ssCtrl] then Exclude(Shift, ssLeft)
else if ssLeft in Shift then Include(Shift, ssCtrl);
end;
end;
// ****************************************************************************
// Perform distance calculations which may be needed later in several places.
// HDistance is the Hex distance from PickUpPoint to MULF.
// ADistance is the Air distance from PickUpPoint to MULF (needs AirMaxRange).
// First check if the PickupPoint is on the map.
// ****************************************************************************
if PickUpPoint.OnMap then
begin
if (Game.Phase = pAirRebase) or
(Game.DigressionInProgress and
(Game.CurrentDigression = digOverrun)) then
AirMaxRange := TAirUnit(FirstMovingUnit).RebaseRange(CheckExtended,
DoubleRange)
else
AirMaxRange := AirRangeOfStack; // Minimum range of all units in stack.

// ShowMessageOK('[TMovingStack.CanMoveTo]: A ' +
// 'AirMaxRange = ' + IntToStr(AirMaxRange));

ADistance := AirDistanceFromTo(PickUpPoint, MULF.Hex, AirMaxRange);
HDistance := TGameMapArea.HexDistance(PickUpPoint, MULF.Hex);
end
else
begin // The next 3 lines of code are for the compiler.
AirMaxRange := 255;
ADistance := 0;
HDistance := 0;
end;
// ****************************************************************************
// Begin validation of move.
// ****************************************************************************
MapHex := MapStacks[MULF.Column, MULF.Row]; // Map stack at destination.
FirstMU := FirstMovingUnit;

if MULF.AtSea then
begin
SAStack := SeaAreas[MULF.SeaAreaID].SeaStack;

if FirstMU.Side = sdAxis then
begin
RefC := SeaAreas[MULF.SeaAreaID].AxisBoxZero.X;
RefR := SeaAreas[MULF.SeaAreaID].AxisBoxZero.Y;
end
else
begin
RefC := SeaAreas[MULF.SeaAreaID].AlliedBoxZero.X;
RefR := SeaAreas[MULF.SeaAreaID].AlliedBoxZero.Y;
end;
end
else
begin
SAStack := nil;
RefC := 0; // Not used.
RefR := 0;
end;

Old := PickUpPoint;
SameHex := ExactSameLocation(PickUpPoint, MULF);
Result := mvOK; // Default is that it's an ok move.
// ****************************************************************************
// Check for trying to move to the starting location for the moving stack, which
// is ok most of the time, but may be illegal in cases listed below.
// ****************************************************************************
MoveToSameHexNotOk := (Game.DigressionInProgress and
// ****************************************************************************
// May not relocate or abort to the same hex.
// ****************************************************************************
(Game.CurrentDigression = digRelocate)) or
Game.NavalCombatAbortDigress or
// ****************************************************************************
// May not fly some air phases/subphases to same hex.
// ****************************************************************************
((Game.Phase in [pPortAttack, pStrategicBombardment,
pCarpetBombing, pGroundStrike,
pParadrop]) and
(Game.AirSubPhase in [AspFlyA, AspInterceptA,
AspAntiAirA, AspReturnA])) or
// ****************************************************************************
// Air units can never fly air missions to all sea hexes.
// ****************************************************************************
((Game.Phase in AirPhases) and
MULF.AtSea);
// ****************************************************************************
// If trying to move to the same hex and that is ok, then we are done.
// ****************************************************************************
if SameHex and (not MoveToSameHexNotOk) then Exit; // Note negative.
// ****************************************************************************
// MC is the governed area that geographically owns the destination hex.
// HexHomeC converts subcountries (e.g., Transylvania) to its parent country.
// HexC is the major power that controls the destination hex.
// We may want to know the minor country that controls the hex (HexMinC).
// ****************************************************************************
MC := Map.HexCountry[MULF.Column, MULF.Row];
HexHomeC := Map.HexHomeCountry[MULF.Column, MULF.Row];
HexC := Map.HexControlMajorCountry[MULF.Column, MULF.Row];
HexMinC := Map.HexControlHex[MULF.Hex];
// ****************************************************************************
// HexMP is the major power that controls the country (governed area) that
// geographically owns the destination hex. HexMP does not necessarily = HexC.
// ****************************************************************************
if MC = nil then HexMP := nil
else HexMP := MC.ControllingMajorPower;
// ****************************************************************************
// Check for legal country (in the game).
// ****************************************************************************
if (MC <> nil) and (not (MC.ID in LegalCountries)) then
begin
Result := mvIllegalCountry;
Exit;
end;
// ****************************************************************************
// Check for neutral country trying to move. If MovingNeutral returns True,
// then the Result = mvNeutralMove.
// ****************************************************************************
if (MC <> nil) and (not Game.InSettingUpPhase) and MovingNeutral then Exit;

// ShowMessageOK('[TMovingStack.CanMoveTo]: mvNeutral check point A.');

// ****************************************************************************
// Check for moving into a neutral country.
// ****************************************************************************
if (MC <> nil) and
(not Game.InSettingUpPhase) and
(not MULF.AtSea) and
NeutralHex(MULF.Hex) and
((Map.HexControlMajorCountry[MULF.Column, MULF.Row] = nil) or
(Map.HexControlMajorCountry[MULF.Column, MULF.Row].ID <>
Self.StackControllingMP(False, True))) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: mvNeutral check point B.');

EastPol := MC.ID = EasternPoland.ID;
BalticStat := ((MC.ID = Estonia.ID) and
(Estonia.NeverInWar)) or
((MC.ID = Latvia.ID) and
(Latvia.NeverInWar)) or
((MC.ID = Lithuania.ID) and
(Lithuania.NeverInWar));
// ****************************************************************************
// Move is ok if the USSR is occupying Eastern Poland or the Baltic States.
// ****************************************************************************
if (not ((FirstMU.Country in [USSR.ID, Siberia.ID]) and
EastPol and
(not EasternPolandOccupied) and
(not Poland.Conquered))) and
(not ((FirstMU.Country in [USSR.ID, Siberia.ID]) and
EasternPolandOccupied and
BalticStat and
(not BalticStatesOccupied))) and
// ****************************************************************************
// When OptRules.Internment is active, air units belonging to minor countries
// can fly into neutral minor countries to be interned. This can happen at any
// time that the air unit can fly (e.g., return to base, forced rebase, etc.).
// The following conditionals permit these moves.
// ****************************************************************************
(not (OptRules.Internment and
(FirstMU is TAirUnit) and
(UnitHomeCountryCommonwealth(FirstMU).ClassType = TMinorCountry) and
(MC.HomeCountry.ClassType = TMinorCountry) and
MULF.OnLand and
(Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.ClassType =
TMinorCountry) and
(not Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.Conquered)
and
Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.Neutral)) and
// ****************************************************************************
// Move is ok to enter a neutral (e.g., Vichy France) when returning French air
// and naval units to base, or rebasing French naval units outside of French
// possessions, or moving French units back into French territories.
// ****************************************************************************
(not ((Game.Phase = pVichy) and
(Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchLandAirAxis,
vspMoveFrenchLandAirAllied,
vspMoveFrenchNavalAllied]))) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: mvNeutral check point C.');

Result := mvNeutral;
Exit;
end;
end; // End of checking for neutral country.
// ****************************************************************************
// RAC 17.4: Vichy units may only enter a hex outside Vichy France is it is
// controlled by an enemy major power.
//
// Check for moving Vichy units into hexes controlled by neither Vichy nor a
// major power at war with Vichy.
// ****************************************************************************
if (MC <> nil) and
(not MULF.AtSea) and
(FirstMU.Country = VichyFrance.ID) and
(HexC <> VichyFrance) and
(HexC <> nil) and
(HexC.Relations[VichyFrance.ID] <> crWar) then
begin
Result := mvVichyOutsideVichy;
Exit;
end;
// ++++++++++++++++++++++++++
// Process digressions first.
// ++++++++++++++++++++++++++
// ****************************************************************************
if Game.DigressionInProgress then
begin
case Game.CurrentDigression of
// ****************************************************************************
// Moving units on the map does not occur.
// ****************************************************************************
digNavalInterception, digFixOverstacking, digCollapseVichy: ;
// ****************************************************************************
// Check for relocating units to the nearest legal hex.
// ****************************************************************************
digRelocate:
begin
if NearHexes.Empty then
Result := mvNoRelocateHex
else if not NearHexes.Search(MULF.Column, MULF.Row) then
Result := mvNotClosest
else if (Game.Phase = pVichy) and
(Game.VichySubPhase in [vspMoveFrenchLandAirAxis,
vspMoveFrenchLandAirAllied]) then
Exit
else if FTCFails or RestrictedReinforcement then
Exit
else if MULF.OnLand and EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl; // digRelocate.

// ShowMessageOK('[TMovingStack.CanMoveTo]: digRelocate.');

end;
end;
// ****************************************************************************
// Check for rebasing units due to overrun or return to base digression.
// ****************************************************************************
digOverrun, digReturnToBase:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: digOverrun, digReturnToBase.');

if FTCFails or RestrictedReinforcement then Exit;
// ****************************************************************************
// Check naval group for illegal combintations.
// ****************************************************************************
if (FirstMU is TNavalUnit) and
(InvalidNavalGroup or
InvalidNavalMove) then
Exit;
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] digOverrun, digReturnToBase ' +
// 'FTC failure.');

if CantTravel then Result := mvMinorLimit // digOverrun, digReturnToBase.
else Result := mvForeignCommitment;

Exit;
end;

if ((Game.Phase <> pVichy) or
(not (Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied]))) and
InvalidDestination(Game.CurrentDigression = digOverrun) then
Exit;

if MULF.AtSea then
begin // Moving to a sea area.
UFUnit := FirstMU;

if FirstMU.UnitType = utCarrierAir then
begin
if not MapHex.HasUnit(UFilterCarrierCanLoadPlane) then
Result := mvNoCarrier; // No carrier available in sea area.
end
else if FirstMU is TAirUnit then
Result := mvLandAirInSeaArea // Only carrier air units RTB at sea.
else if (FirstMU is TNavalUnit) and
(not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index,
HR)) then
begin
if FirstMU.UnitType <> utCarrierAir then
Result := mvLandAirInSeaArea
// Only carrier air units RTB at sea.
else if not MapHex.HasUnit(UFilterCarrierCanLoadPlane) then
Result := mvNoCarrier; // No carrier available in sea area.
end;
end
else
// ****************************************************************************
// One possibility is that naval units have a viable return to base hex but in
// order to reach it, they have to pass through a sea area where they can be
// intercepted by enemy units. In that case, they are allowed to enter the sea
// area.
// ****************************************************************************
begin // Moving to a land hex.
if (Game.Phase = pVichy) and
(Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied]) then
begin // Returning French units to base during Vichy declaration.
if NearHexes.Empty then
begin
if Game.VichySubPhase = vspMoveFrenchAtSea then
Result := mvNoRelocateHex
else
Result := mvNoAbortPort;
end
else if not NearHexes.Search(MULF.Column, MULF.Row) then
Result := mvOutOfRange // French returning from sea.
else
begin
(*
if Game.VichySubPhase = vspMoveFrenchAtSea then
MainForm.DebugPanel.Caption :=
'[TMovingStack.CanMoveTo]: Ok to move to ' +
HexName(MULF.Hex);
*)
end;
end
else if EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl; // digOverrun, digReturnToBase.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: digOverrun, ' +
' digReturnToBase EnemyStackOrHex');
*)
end
else
begin
C := TMajorCountry(Countries[FirstMU.ControllingMajorCountry]);

if (HexC = nil) or (HexC.Side <> C.Side) then
begin
Result := mvHexControl; // digOverrun, digReturnToBase.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: digOverrun, ' +
' digReturnToBase Enemy controlled hex.');
*)
end
else if EnemyStack(MapHex) then
Result := mvEnemyUnit; // An enemy unit is in the hex.
end;
end;

if Result = mvOK then
begin // Check if the destination is in the predetermined list.
if (Game.Phase <> pVichy) or
(not (Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied])) then
begin
if (Game.CurrentDigression = digOverrun) or
(FirstMU is TNavalUnit) then
begin
if (FirstMU is TNavalUnit) and
(not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index,
HR)) then
Result := mvOutOfRange // Overrun naval units.
else if (FirstMU is TAirUnit) and
(not AirHexList.Search(MULF.RefCol, MULF.RefRow, Index,
AHR)) then
begin
if ADistance > AirMaxRange then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: Air unit, ' +
FirstMU.ViewName +
', in digOverrun. ADistance = ' +
IntToStr(ADistance) +
' is greater than AirMaxRange = ' +
IntToStr(AirMaxRange));
*)
Result := mvOutOfRange; // Air unit; digOverrun.
end
else
begin
Good := FriendlyHex(MULF.Column, MULF.Row);

if Good then
begin
if EnemyStack(MapHex) then Result := mvEnemyUnit
else Result := CanStack(MapHex, False, nil, False, True);
end;
end;
end;
end
else
begin // Air unit returning to base due to abort result/choice.
if ADistance > AirMaxRange then
Result := mvOutOfRange // // Air unit; digReturnToBase.
else
begin
Good := FriendlyHex(MULF.Column, MULF.Row);

if Good then
begin
if EnemyStack(MapHex) then Result := mvEnemyUnit
else Result := CanStack(MapHex, False, nil, False, True);
end;
end;
end;
end;
end;
// ****************************************************************************
// Check if move is within legal stacking limits.
// ****************************************************************************
// if Result = mvOK then Result := CanStack(MapHex);
end; // End of digOverrun, digReturnToBase.

digNavalCombatAbort:
begin
if HasAirAndNaval then
Result := mvAbortAirNaval// Cannot move air & naval together.
else if MULF.OnLand and EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl; // digNavalCombatAbort.

// ShowMessageOK('[TMovingStack.CanMoveTo]: digNavalCombatAbort ');

end
else if FTCFails or RestrictedReinforcement then
Exit
// ****************************************************************************
// Check naval group for illegal combintations.
// ****************************************************************************
else if (FirstMU is TNavalUnit) and
(InvalidNavalGroup or
InvalidNavalMove) then
Exit// Trying to move to an all-sea hex.
else if InvalidDestination then Exit;

if MULF.AtSea then
begin // Moving to a sea area.
UFUnit := FirstMU;
// ****************************************************************************
// One possibility is that naval units do have a viable return to base hex but
// in order to reach it, they have to pass through a sea area where they can be
// intercepted by enemy units. In that case, they are allowed to enter the sea
// area.
// ****************************************************************************
if (not (FirstMU is TNavalUnit)) or
(not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index, HR)) then
begin
if FirstMU.UnitType <> utCarrierAir then
Result := mvLandAirInSeaArea
// Only carrier air units RTB at sea.
else if not MapHex.HasUnit(UFilterCarrierCanLoadPlane) then
Result := mvNoCarrier; // No carrier available in sea area.
end;
end
else
begin // Moving to a land hex.
if EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl; // digNavalCombatAbort.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: digNavalCombatAbort ' +
' EnemyStackOrHex');
*)
end
else
begin
C := TMajorCountry(Countries[FirstMU.ControllingMajorCountry]);

if (HexC = nil) or (HexC.Side <> C.Side) then
begin
Result := mvHexControl; // digNavalCombatAbort.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: digNavalCombatAbort ' +
' Enemy controlled hex.');
*)
end
else if EnemyStack(MapHex) then
Result := mvEnemyUnit; // An enemy unit is in the hex.
end;
end;
end; // End of digNavalCombatAbort.
end; // End of case Game.CurrenntDigression.

Exit; // Exit after every digression.
end
else
// ****************************************************************************
// +++++++++++++++++++++++++++++
// Process by phase of the game.
// +++++++++++++++++++++++++++++
// ****************************************************************************
begin
case Game.Phase of
// ****************************************************************************
// In many phases, units can not be 'moved'. Those are listed first since they
// should never be encountered by this routine.
// ****************************************************************************
pLending, pInitiative, pWeather, pChooseAction, pIgnoreNotional,
pEmergencyHQSupply, pHQReorganization, pTRSSupply, pEndOfAction,
pEntry, pUSEntry, pProdPlanningPrelim, pStayAtSeaA, pStayAtSeaD,
pUseOil, pFinalReorganization, pBreakDown, pProdPlanningFinal,
pSearchAndSeizure, pScrapDestroyed, pNavalRepair, pProduction,
pReform, pIntelligence, pUkraine, pConquest, pMutualPeace,
pLiberation, pSurrender, pMinorSupport, pFactoryDestruction,
pVictory, pGameEnd, pQuit, pNone:
Exit;

pSetup:
begin
if RestrictedReinforcement then Exit;

if MULF.OnLand and EnemyStackOrHex(MapHex) and
(not SettingUpPartisans) then
Result := mvHexControl
else
CheckUsingSetupTray;
end;

pReinforcement:
begin
if Game.Phase_Reinforce.CurrentSubPhase[Game.LocalDeciderMP] =
RspPlaceUnits then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pReinforcement ' +
// 'Result at A = ' + IntToStr(Ord(Result)));

if MULF.OnLand and EnemyStackOrHex(MapHex) then
Result := mvHexControl
else if RestrictedReinforcement then Exit;
// ****************************************************************************
// Check for placing reinforcement units on the map from the setup tray.
// ****************************************************************************
MapHex := MapStacks[MULF.Column, MULF.Row]; // Destination MapStack.
Result := CanSetup(MULF.Column, MULF.Row); // CanMoveTo.
(*
if not (Result in [mvOK, mvWarlordHex]) then
ShowMessageOK('[TMovingStack.CanMoveTo]: pReinforcement ' +
'Result at B = ' + IntToStr(Ord(Result)));
*)
if Result = mvOK then
Result := CanStack(MapHex); // MapStack stacking limits for setup phases.
(*
if not (Result in [mvOK, mvWarlordHex]) then
ShowMessageOK('[TMovingStack.CanMoveTo]: pReinforcement ' +
'Result at C = ' + IntToStr(Ord(Result)));
*)
if (Result = mvStackingAir) and
(not MULF.AtSea) and
(UnitCount(UFilterCarrierAirUnit) = 1) then
begin
UFUnit := FindUnit(UFilterCarrierAirUnit);
UFPhase := Game.Phase;
UFSubPhase := aspNone;

if MapHex.HasUnit(UFilterCarrierCanLoadPlane) then
Result := mvOK;
end;
end;
end; // End of pReinforcement.

pDeclareWar:
begin
CheckUsingSetupTray;
end;

pPortAttack:
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if RestrictedReinforcement or UnableToFlyToHex then Exit;
// ****************************************************************************
// Check for attempting to port attack at night - which is forbidden.
// ****************************************************************************
if HasUnit(UFilterNightMission) then
begin
Result := mvNightPortAttack; // No night missions for port attacks.
Exit;
end;
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
AspCAP:
begin
UFSide := Game.PhasingSide;
Good := MapHex.HasUnit(UFilterPortAttackTargetCooperates);
end;

AspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

if Good then Good := MapHex.HasUnit(UFilterPortAttackTargetEnemy);
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end;

if not Good then Result := mvNoTarget;
end; // End of pPortAttack.

pNavalAir: // CanMoveTo.
begin
ComputeUnits; // Count the # of limited activities needed to move stack.

if RestrictedReinforcement or InvalidNavalAirNavalMission then Exit;

if (MULF.OnLand and
PickUpPoint.OnLand) or
(MULF.AtSea and
PickUpPoint.AtSea and
(MULF.SeaAreaID <> PickUpPoint.SeaAreaID)) then
begin
Result := mvNavalAirNotSeaArea;
Exit;
end;

if InvalidDestination(False) then Exit;
// ****************************************************************************
// Check for available air missions for all air units in the moving stack. Even
// fighters count during the Naval Air phase.
// ****************************************************************************
for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.AirMissions <> aUnlimited) and
(AirUnits[MPI] > MPow.CurrLimits.AirMissions) then
begin
Result := mvAirMissions;
Break;
end;
end;
end; // End of pNavalAir.

pNavalMovement: // CanMoveTo.
begin
if FTCFails or
InvalidNavalGroup or
RestrictedReinforcement or
InvalidNavalMove then // Trying to move to an all-sea hex.
Exit;

// ShowMessageOK('[TMovingStack.CanMoveTo] pNavalMovement A.');

ComputeUnits; // Count the # of limited activities needed to move stack.

// ShowMessageOK('[TMovingStack.CanMoveTo] pNavalMovement B.');

if MULF.OnLand and EnemyStackOrHex(MapHex) then Result := mvHexControl
// ****************************************************************************
// Moving into a sea area in order to fight through, does not count as a naval
// move.
// ****************************************************************************
else if (not SameHex) and (not Game.NavalInterceptionDigression) then
begin // Check for exceeding naval move limits.
for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];
MajC := UnitControllingMajorCountry(FirstMU);

if MajC = VichyFrance then MPow := Game.VichyFranceController
else MPow := MajC;
// ****************************************************************************
// This routine is for neutral major powers only.
// ****************************************************************************
if MPow.LegalCountry and
(MPow.CurrLimits.NavalMoves <> aUnlimited) and // CanMoveTo.
MajC.NeutralNavalMoves and // 1 move/unit.
(NavalUnitCounts[MPI] > MPow.CurrLimits.NavalMoves) then
begin
Result := mvNavalMoves; // Insufficient naval moves for neutral.
Break;
end;
end;
end;

// ShowMessageOK('[TMovingStack.CanMoveTo] pNavalMovement C.');

end;

pNavalCombatA, pNavalCombatD: // CanMoveTo.
begin
if Game.NCSubPhase in [NCspNavalAirSupportA, NCspNavalAirSupportD] then
begin
if InvalidNavalAirSupport or InvalidDestination(False) then Exit;
end;
end;

pStrategicBombardment: // CanMoveTo.
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

// ShowMessageOK('[TMovingStack.CanMoveTo]: pStrategicBombardment A.');

if UnableToFlyToHex then Exit;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pStrategicBombardment B.');

// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;
// ****************************************************************************
// Set UFSide to the enemy side except during a CAP subphase.
// ****************************************************************************
case Game.AirSubPhase of
aspCAP:
begin
UFSide := Game.PhasingSide;
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if DoesntCooperatesWithHex(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if Good then
Good := (FoundMovSUni2 = nil) and
((Map.FactoryList.FactoryTargetCount[MULF.Column,
MULF.Row] > 0) or
(Map.OilTargetCount[MULF.Column, MULF.Row] > 0) or
(Map.SavedBuildTargetCount[MULF.Column, MULF.Row] > 0) or
(Map.SavedOilTargetCount[MULF.Column, MULF.Row] > 0) or
MapHex.HasUnit(UFilterSynthOilUnitNotLost));
end;

aspFlyA:
begin
UFSide := Game.NonPhasingSide;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pStrategicBombardment ' +
// 'AspFlyA C.');
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pStrategicBombardment ' +
// 'AspFlyA D.');

if Good then
Good := EnemyHex(MULF.Column, MULF.Row) and
((Map.FactoryList.FactoryTargetCount[MULF.Column,
MULF.Row] > 0) or
(Map.OilTargetCount[MULF.Column, MULF.Row] > 0) or
(Map.SavedBuildTargetCount[MULF.Column, MULF.Row] > 0) or
(Map.SavedOilTargetCount[MULF.Column, MULF.Row] > 0) or
MapHex.HasUnit(UFilterSynthOilUnitNotLost));
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

aspReturnA, aspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pStrategicBombardment.

pCarpetBombing:
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit;
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
AspCAP:
begin
UFSide := Game.PhasingSide;
Good := MapHex.HasUnit(UFilterCarpetBombingTargetCooperates);
end;

AspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;
// ****************************************************************************
// It is possible to carpetbomb a unit on the other side even if you are not at
// war with its controlling major power, if it is in a hex controlled by a
// country with which you are at war.
// ****************************************************************************
UFSide := Game.NonPhasingSide; // Has to be reset.

if Good then
Good := (EnemyHex(MULF.Column, MULF.Row) and
MapHex.HasUnit(UFilterCarpetBombingTargetSide)) or
MapHex.HasUnit(UFilterCarpetBombingTargetEnemy);
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pCarpetBombing.

pGroundStrike:
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit; // Only air units are checked.
// ****************************************************************************
// Set Good which indicates whether the unit can ground strike depending on the
// target units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
aspCAP:
begin
UFSide := Game.PhasingSide;
Good := LandCombatHexes.Search(MULF.Hex, Index, CR) and
FriendlyStack(MapHex) and
MapHex.HasUnit(UFilterGroundStrikeTargetCooperates);
// ****************************************************************************
// Check to see if UTarget is surprised. If it is, it cannot fly CAP.
// ****************************************************************************
// (not UTarget.SurprisedBy(UAttacker)) then
end;

aspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;
// ****************************************************************************
// It is possible to ground strike a unit on the other side even if you are not
// at war with its controlling major power, if it is in a hex controlled by a
// country with which you are at war.
// ****************************************************************************
UFSide := Game.NonPhasingSide; // Has to be reset.

if Good then
Good := (EnemyHex(MULF.Column, MULF.Row) and
MapHex.HasUnit(UFilterGroundStrikeTargetSide)) or
MapHex.HasUnit(UFilterGroundStrikeTargetEnemy);
(*
if EnemyHex(MULF.Column, MULF.Row) and
(not MapHex.HasUnit(UFilterGroundStrikeTargetSide)) then
begin
ShowMessageOK('[TMovingStack.CanMoveTo]: pGroundStrike ' +
'AspFlyA UFilterGroundStrikeTargetSide ' +
' failed.');
end
else if not Good then
ShowMessageOK('[TMovingStack.CanMoveTo]: pGroundStrike ' +
'AspFlyA UFilterGroundStrikeTargetEnemy ' +
' failed.');
*)
// ****************************************************************************
// This final check is for artillery units that are bombarding.
// ****************************************************************************
if Good and (not HasAir) then
begin
UFSide := Game.NonPhasingSide; // Has to be reset.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pGroundStrike ' +
'AspFlyA HDistance = ' + IntToStr(HDistance));
*)
if (HDistance > 1) or
(EnemyHex(MULF.Column, MULF.Row) and
(not MapHex.HasUnit(UFilterGroundStrikeTargetSide))) or
((not EnemyHex(MULF.Column, MULF.Row)) and
(not MapHex.HasUnit(UFilterGroundStrikeTargetEnemy))) then
begin
Result := mvBombardAdjacent;
end
else if Map.HexWeather[MULF.Column, MULF.Row] in
NoAirFactorsWeather then
Result := mvBombardWeather
else if Map.HexsideTerrain[PickUpPoint.Column, PickUpPoint.Row,
THexArea.ConnectingHexsideRange(PickUpPoint.Hex,
MULF.Hex), hsAlpine] then
Result := mvBombardAlpine;
end;
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pGroundStrike.
// ****************************************************************************
// Check rail movement.
// ****************************************************************************
pRailMovement: // TMovingStack.CanMoveTo.
begin
if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement then
Exit;
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] pRailMovement ' +
// 'FTC failure.');

if CantTravel then Result := mvMinorLimit // pRailMovement.
else Result := mvForeignCommitment;

Exit;
end;

ComputeUnits; // Count the # of limited activities needed to move stack.
RR := Map.RailHexes.Search(MULF.Column, MULF.Row);

if EnemyStackOrHex(MapHex) then Result := mvHexControl
else if (RR = nil) or (not RR.RInclude) then Result := mvNoRailMove
else
begin
if (FirstMU.UnitType = utFactory) and
((Map.City[MULF.Column, MULF.Row] = cyNone) or
(Map.HexHomeCountryCommonwealth[MULF.Column, MULF.Row] <>
UnitControllingMajorCountry(FirstMU))) then
Result := mvNoHomeCity
// ****************************************************************************
// There is a limit of 2 non-red factories and 3 total factories in a hex.
// ****************************************************************************
else if (FirstMU.UnitType = utFactory) and
Map.NoRoomForFactory(MULF.Column, MULF.Row) then
Result := mvCityCapacityFactory
// ****************************************************************************
// HQ units and Railway guns can move to any rail hex. The hex does not have to
// be a station.
// ****************************************************************************
else if (not (FirstMU.UnitType in HeadquartersSet + [utRailwayGun]))
and
(not Map.IsStationHex(MULF.Column, MULF.Row)) then
Result := mvNoStation
else
begin
if (FirstMU.RailMoveCost(RR.RHexCount) >
UnitControllingMajorCountry(FirstMU).CurrLimits.RailMoves) or
((FirstMU.Country = CommunistChina.ID) and
(FirstMU.RailMoveCost(RR.RHexCount) >
CCLimitsCurr.RailMoves)) then
Result := mvRailMoves
else
Result := CanStack(MapHex); // Rail movement.
end;
end;
end; // End of pRailMovement.
// ****************************************************************************
// Check land movement (including advance after combat).
// ****************************************************************************
pLandMovement:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] pLandMovement A.');

if MULF.AtSea then Result := mvNoLandMove
else if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement then
Exit
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
else if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] pLandMovement ' +
// 'FTC failure after call to CanMoveMinor.');

if CantTravel then Result := mvMinorLimit // pLandMovement.
else Result := mvForeignCommitment;

Exit;
end
else
begin
ComputeUnits; // Count the # of activities needed to move the stack.

if not CanMove(MULF.Column, MULF.Row, Disrupt) then
begin // Move fails. Determine why for error message.
UFSide := Game.PhasingSide;

if EnemyStack(MapHex) or
(EnemyHex(MULF.Column, MULF.Row) and
MapHex.HasUnit(UFilterNotSide)) then
begin
if ((HDistance = 1) and
(FirstMU.HexsideMP[PickUpPoint.Hex, MULF.Hex] <>
ProhibitedTerrain)) then
Result := mvNoOverrun
else
Result := mvOverrunAdjacent;
end
else if InEnemyZOC and (not FirstMove) then
Result := mvEnemyZOC
else if MapHex.HasUnit(UFilterNotSide) and
(not EnemyHex(MULF.Column, MULF.Row)) then
Result := mvNeutralNotAtWar
else if MajPower(FirstMU).HexViolatesPact(MULF.Hex) then
Result := mvPact
else
begin
Result := CanStack(MapHex); // Land movement.

if Result = mvOK then Result := mvMP; // Land movement.
end;
end
else
begin // Legal move, check against action limits.
for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves)
and UnitsNotMoved then
begin
Result := mvLandMoves;
Break;
end;
end;
// ****************************************************************************
// Perform another check of all the units in Self to see how many Communist
// Chinese units are in the stack.
// ****************************************************************************
CCCount := 0;

for CCIndex := 0 to Self.Count - 1 do
begin
CCUnit := Self[CCIndex];

if CCUnit.Country = CommunistChina.ID then
Inc(CCCount);
end;
// ****************************************************************************
// If Self has a CC unit, then check available CCLimitsCurr.LandMoves.
// ****************************************************************************
if (CCCount > 0) and (CCLimitsCurr.LandMoves <> aUnlimited) and
(CCCount > CCLimitsCurr.LandMoves) then
Result := mvLandMoves;
end;

if Result = mvOK then
begin // Determine HR. Check for stacking limits.
LandHexList.Search(MULF.RefCol, MULF.RefRow, Index, LHR);
Result := CanStack(MapHex, False, nil, False, False, Side);

if (Result = mvOK) and Disrupt then
Result := mvDisruptedExt;
end;
end;
end; // End of pLandMovement.

pAirTransport:
begin
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement or
UnableToFlyToHex then
Exit;
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] pAirTransport ' +
// 'FTC failure.');

if CantTravel then Result := mvMinorLimit // pAirTransport.
else Result := mvForeignCommitment;

Exit;
end;

ComputeUnits; // Count the # of limited activities needed to move stack.
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
aspCAP:
begin
UFSide := Game.PhasingSide;
Good := EnemyHex(MULF.Column, MULF.Row);
end;

aspFlyA:
begin
// ****************************************************************************
// First check for a transport in the moving stack that is carrying half of a
// unit in the LargeAirTransportSet, while a second transport, which is not in
// the moving stack is carrying the other half. If this condition is detected,
// then automatically add the second transport to the moving stack.
// ****************************************************************************
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);
// ****************************************************************************
// Check if Cargo is being carried by another ATR (Second, which is not in the
// moving stack).
// ****************************************************************************
if NotSupplyLoaded(F1stMovSUni2) then
begin
if Second <> nil then
begin
PickingUpMultipleUnits := False;
AddToMovingStack(Second);
end;

if First <> nil then
begin
PickingUpMultipleUnits := False;
AddToMovingStack(First);
end;
end;

Inc(F1stMovSUIndx2);
end; // End of while.

UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves) then
begin // Insufficient land moves available.
Result := mvLandMoves;
Break;
end;
end;

if Result = mvOK then
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NotSupplyLoaded(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end; // End of while.

if FoundMovSUni2 <> nil then Result := mvNotSupplyLoaded
else
begin
Res := CanStack(MapHex); // Air transport.

if Res = mvOK then
begin
if Good then Good := FriendlyHex(MULF.Column, MULF.Row);
// ****************************************************************************
// It is a friendly hex. Check if this is an attempt to fly to a hex that has a
// unit which can be loaded onto an air transport. For example, the ATR can not
// fly to an empty hex unless it is already carrying a unit it loaded before it
// took to the air.
// ****************************************************************************
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NotLoaded(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if Good and
(not AirTransportReturn) and
(FoundMovSUni2 <> nil) then
begin
UFPhase := Game.Phase;
UFSubPhase := Game.AirSubPhase;
Good := OtherStackFilter(MapHex, UFilterLoadable);
end;
end // End of Res = mvOK.
else Result := Res;
end; // End of FoundMovSUni2 = nil.
end; // End of Result = mvOK.
end; // End of AspFlyA.

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
// ****************************************************************************
// First check for a transport in the moving stack that is carrying half of a
// unit in the LargeAirTransportSet, while a second transport, which is not in
// the moving stack is carrying the other half. If this condition is detected,
// then automatically add the second transport to the moving stack.
// ****************************************************************************
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);
// ****************************************************************************
// Check if Cargo is being carried by another ATR (Second, which is not in the
// moving stack).
// ****************************************************************************
if NotSupplyLoaded(F1stMovSUni2) then
begin
if Second <> nil then
begin
PickingUpMultipleUnits := False;
AddToMovingStack(Second);
end;

if First <> nil then
begin
PickingUpMultipleUnits := False;
AddToMovingStack(First);
end;
end;

Inc(F1stMovSUIndx2);
end; // End of while.

CantReturnAD;
Exit;
end;
end; // End of Case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pAirTransport.
// ****************************************************************************
// Check unloading land units from a sea area into a friendly land hex.
// ****************************************************************************
pUnloadLandUnits:
begin
if FTCFails or RestrictedReinforcement then Exit;

ComputeUnits; // Count the # of limited activities needed to move stack.

if MULF.OnLand and EnemyStackOrHex(MapHex) then Result := mvHexControl
else Result := CanStack(MapHex); // Unloading land units.

if Result = mvOK then
begin
if not FirstMU.CanUnloadIntoHex(MULF.Hex) then Result := mvNoDebark
else
begin
for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves) then
begin
Result := mvLandMoves;
Break;
end;
end;

if (Result = mvOK) and AnyWillBeDisrupted then
Result := mvDisruptedExt;
end;
end;
end;
// ****************************************************************************
// Check invasion.
// ****************************************************************************
pInvasion:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion A.');

ComputeUnits; // Count the # of limited activities needed to move stack.
Result := CanStack(MapHex, True); // Invasion.

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion B.');

if Result = mvOK then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion C.');

if not FirstMU.CanInvadeIntoHex(MULF.Hex) then Result := mvNoInvasion
else
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion D.');

for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves) then
begin
Result := mvLandMoves;
Break;
end;
end;
end;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion E.');

if Result = mvOK then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion F.');

F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NoAttack(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 <> nil then Result := mvLandAttacks;
end;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion G.');

if (Result = mvOK) and AnyWillBeDisrupted then
Result := mvDisruptedExt;
end;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion H.');

end;

pParadrop:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pParadrop A.');

ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit;
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pParadrop B.');

case Game.AirSubPhase of
aspCAP:
begin
UFSide := Game.PhasingSide;
LandCombatHexes.Search(MULF.Hex, Index, CR);
Good := ((CR = nil) or
(not CR.CombatHexUnits.SurprisedStack(MapHex,
Game.NonPhasingSide)))
and
FriendlyHex(MULF.Column, MULF.Row);

if Good then
begin
if MapHex.Empty then
begin
// ****************************************************************************
// If the hex is empty, then all units in Self need to cooperate with the
// notional unit (i.e., whoever controls the hex).
// ****************************************************************************
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if DoesntCooperatesWithHex(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

Good := FoundMovSUni2 = nil;
end
else
// ****************************************************************************
// If the hex contains units, Self has to cooperate with all the friendly units
// in the hex.
// ****************************************************************************
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < MapHex.Count do
begin
F1stMovSUni2 := TUnit(MapHex.Item[F1stMovSUIndx2]);

if not DoesCooperate(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

Good := FoundMovSUni2 = nil;
end;
end; // End of Good so far.
end; // End of AspCAP.

aspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

if Map.WeatherTerrain[MULF.Column, MULF.Row] in [teSea,
teLake] then
Result := mvNoTarget
else
Result := CanStack(MapHex, True); // Paradrop.

if Result = mvOK then
begin
CR := LandCombatHexes.FindCombat(MULF.Hex);

for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if not MPow.LegalCountry then Continue;

UFCountry := MPow.ID;

if (MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves) then
Result := mvLandMoves
else if (LandUnits[MPI] > 0) and
(MPow.CurrLimits.LandAttacks = 0) and
((CR = nil) or
(not (CR.CombatHexUnits.HasUnit
(UFilterControllingMajorCountry)))) then
Result := mvLandAttacks;

if Result <> mvOK then Break;
end; // End of for each major power.
// ****************************************************************************
// Perform another check of all the units in Self to see if a Communist Chinese
// unit is part of the attack. If so, then see if a Communist Chinese unit is
// already in CR.CombatHexUnits.
// ****************************************************************************
CCCount := 0;

for CCIndex := 0 to Self.Count - 1 do
begin
CCUnit := Self[CCIndex];
// CC unit in Self.
if CCUnit.Country = CommunistChina.ID then Inc(CCCount);
end;
// ****************************************************************************
// If Self has a CC unit, then a check has to be made for both
// CCLimitsCurr.LandMoves and CCLimitsCurr.LandAttacks.
// ****************************************************************************
if CCCount > 0 then
begin
if (CCLimitsCurr.LandMoves <> aUnlimited) and
(CCCount > CCLimitsCurr.LandMoves) then
Result := mvLandMoves
else
begin // Enough land moves available.
if CCLimitsCurr.LandAttacks = 0 then
begin // Check existing attack.
if (CR = nil) then Result := mvLandAttacks
else
begin
CCFound := False;

for CCIndex := 0 to CR.CombatHexUnits.Count - 1 do
begin
CCUnit := CR.CombatHexUnits[CCIndex];

if CCUnit.Country = CommunistChina.ID then
begin
CCFound := True;
Break; // CC unit already in the attack.
end;
end;

if not CCFound then Result := mvLandAttacks;
end;
end; // End of CCLimitsCurr.LandAttacks = 0.
end; // End of enough land moves available.
end; // End of CCCount > 0.

if Result = mvOK then
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NotLoaded(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 <> nil then Result := mvNotLoaded
else
begin
F1stMovSUIndx2 := 0;
U := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if IsAirLandingUnit(F1stMovSUni2) then
begin
U := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;
// ****************************************************************************
// If there is no air landing unit in the stack, just check for an enemy hex.
// ****************************************************************************
if U = nil then Good := EnemyHex(MULF.Column, MULF.Row)
else
// ****************************************************************************
// If an air landing unit has been found (U <> nil), then check for an
// accompanying paratroop unit in the moving stack or in the hex.
// ****************************************************************************
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;
// ****************************************************************************
// Moving stack check for accompanying paratroop unit.
// ****************************************************************************
while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if IsParatroopUnit(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;
// ****************************************************************************
// If there is paradrop unit in the stack, check for an enemy hex.
// ****************************************************************************
if FoundMovSUni2 <> nil then
Good := EnemyHex(MULF.Column, MULF.Row)
else
// ****************************************************************************
// Check for an accompanying paratroop unit in the hex.
// ****************************************************************************
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < MapHex.Count do
begin
F1stMovSUni2 := TUnit(MapHex.Item[F1stMovSUIndx2]);

if IsParatroopUnit(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 = nil then
Result := mvNoExistingPara
// ****************************************************************************
// Friendly paratroop unit found in hex.
// ****************************************************************************
else Good := EnemyHex(MULF.Column, MULF.Row);
end;
end;
end;
end;
end;
end; // End AspFlyA.

AspInterceptA:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pParadrop AspInterceptA.');

if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of Case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pParadrop.
// ****************************************************************************
// Check land combat declaration.
// ****************************************************************************
pLandCombatDeclaration: // CanMoveTo.
begin
ComputeUnits; // Count the # of limited activities needed to move stack.

if not CanMove(MULF.Column, MULF.Row, Disrupt) then
Result := mvAttack // No.
else
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NoAttack(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 <> nil then
Result := mvLandAttacks // No.
else if LandCombatHexes.Search(MULF.Hex, Index, CR) and
((not CooperatesNotFlying(Self)) or
(not CooperatesNotFlying(CR.CombatHexUnits))) then
Result := mvAttackNoCoop; // No.
end;
end;
// ****************************************************************************
// Check shore bombardment.
// ****************************************************************************
pShoreBombardmentA, pShoreBombardmentD:
begin
F1stMovSUIndx4 := 0;
FoundMovSUni4 := nil;

while F1stMovSUIndx4 < Count do
begin
F1stMovSUni4 := TNavalUnit(Item[F1stMovSUIndx4]);

if NoSB(F1stMovSUni4) then
begin
FoundMovSUni4 := F1stMovSUni4;
Break;
end;

Inc(F1stMovSUIndx4);
end;

if FoundMovSUni4 <> nil then
Result := mvNoShoreBombardment
else
begin
F1stMovSUIndx4 := 0;
FoundMovSUni4 := nil;

while F1stMovSUIndx4 < Count do
begin
F1stMovSUni4 := TNavalUnit(Item[F1stMovSUIndx4]);

if NoSBFactors(F1stMovSUni4) then
begin
FoundMovSUni4 := F1stMovSUni4;
Break;
end;

Inc(F1stMovSUIndx4);
end;

if FoundMovSUni4 <> nil then
Result := mvNoShoreBombardmentFactors;
end;
end;
// ****************************************************************************
// Check attacking HQ support.
// ****************************************************************************
pHQSupportA:
begin
TMapArea.ConnectingHexsideRange(PickUpPoint.Hex, MULF.Hex, HS);

if (not LandCombatHexes.Search(MULF.Hex, Index, CR)) or
(HS <> FirstMU.AttackingHexside) then
Result := mvHQSupportA
else if CR.HQA <> nil then
Result := mvHasHQSupportA;
end;
// ****************************************************************************
// Check defending HQ support.
// ****************************************************************************
pHQSupportD: // CanMoveTo.
begin
HQSameHex := ExactSameLocation(PickUpPoint, MULF);
HQAdjacent := THexArea.AdjacentHexes(PickUpPoint.Column,
PickUpPoint.Row, MULF.Column, MULF.Row);

if (not LandCombatHexes.Search(SmallPoint(MULF.Column, MULF.Row),
Index, CR)) or ((not HQSameHex) and (not HQAdjacent)) or
(LandCombatHexes.Search(SmallPoint(PickUpPoint.Column,
PickUpPoint.Row), Index, CR2) and HQAdjacent) then
Result := mvHQSupportD
else if (not HQSameHex) and
(not FirstMU.CooperatesWithLocation(MULF.Hex)) then
Result := mvHQSupportDNoCoop
else if (CR <> nil) and (CR.HQD <> nil) then
Result := mvHasHQSupportD;
end;

pGroundSupport:
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit;
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
UFUnit := FirstMU;

case Game.AirSubPhase of
aspCAP:
begin
Good := LandCombatHexes.Search(MULF.Hex, Index, CR) and
(not CR.CombatHexUnits.SurprisedStack(MapHex,
Game.NonPhasingSide))
and
FriendlyHex(MULF.Column, MULF.Row);

if Good then
begin
// ****************************************************************************
// If the hex is empty, then all units in Self need to cooperate with the
// notional unit (i.e., whoever controls the hex). Otherwise, Self has to
// cooperate with all the friendly units in the hex.
// ****************************************************************************
if MapHex.Empty then
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if DoesntCooperatesWithHex(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

Good := FoundMovSUni2 = nil;
end
else
// ****************************************************************************
// If the hex contains units, Self has to cooperate with all the friendly units
// in the hex.
// ****************************************************************************
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < MapHex.Count do
begin
F1stMovSUni2 := TUnit(MapHex.Item[F1stMovSUIndx2]);

if not DoesCooperate(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

Good := FoundMovSUni2 = nil;
end;
end;
end; // End of AspCAP.

aspFlyA:
begin
UFSide := Game.NonPhasingSide;

if NoCooperationWithTarget then Exit; // CanMoveTo has been set.

Good := LandCombatHexes.Search(MULF.Hex, Index, CR);

if Good then
begin
if not HasAir then
begin
if HDistance > 1 then Result := mvBombardAdjacent
else if Map.HexWeather[MULF.Column, MULF.Row] in
NoAirFactorsWeather then
Result := mvBombardWeather;
end;
end;
end;

aspFlyD:
begin
UFSide := Game.NonPhasingSide;

if NoCooperationWithTarget then Exit; // CanMoveTo has been set.

Good := LandCombatHexes.Search(MULF.Hex, Index, CR);

if Good then
begin
if CR.CombatHexUnits.SurprisedStack(MapHex,
Game.NonPhasingSide) then
Result := mvAirSurprisedGroundSupport
else if not HasAir then
begin
if HDistance > 1 then Result := mvBombardAdjacent
else if Map.HexWeather[MULF.Column, MULF.Row] in
NoAirFactorsWeather then
Result := mvBombardWeather;
end;
end;
end; // End of AspFlyD.

AspInterceptA:
begin
Good := LandCombatHexes.Search(MULF.Hex, Index, CR);

if Good then
begin
if CantInterceptA then Exit;
end;
end;

AspInterceptD:
begin
Good := LandCombatHexes.Search(MULF.Hex, Index, CR);

if Good then
begin
if CantInterceptD then Exit;
end;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of Case Game.AirSubPhase

if not Good then Result := mvNoTarget;
end; // End of pGroundSupport.

pLandCombatResolution:
begin
case Game.Phase_LandCombatResolution.CurrentSubPhase of
// ****************************************************************************
// The code should never get here for LCRspHexControl since that is processed
// using a digression.
// ****************************************************************************
LCRspLandCombatSelection, LCRspChooseCombatType,
LCRspLandCombatResolution,
LCRspAssignLosses, LCRspHexControl: ;

LCRspRetreats:
begin
if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement then
Exit;
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin
if CantTravel then Result := mvMinorLimit // LCRspRetreats.
else Result := mvForeignCommitment;

Exit;
end;

if not RetreatHexes.Search(MULF.Column, MULF.Row) then
Result := mvNoRetreat
else
Result := CanStack(MapHex); // LCRspRetreats.

if (Result = mvOK) and FTCFails then Exit;
end;

LCRspAdvanceAfterCombat:
begin
if MULF.AtSea then Result := mvNoLandMove
else if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement then
Exit
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
else if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin
if CantTravel then Result := mvMinorLimit // LCRspAdvanceAfterCombat.
else Result := mvForeignCommitment;

Exit;
end
else
begin
if not CanMove(MULF.Column, MULF.Row, Disrupt) then
begin // Move fails. Determine why for error message.
UFSide := Game.PhasingSide;

if (Game.CombatResult.LRetreat <> lcrBreakthrough) and
(HDistance > 1) then
Result := mvNoBreakthrough
else if EnemyStack(MapHex) or
(EnemyHex(MULF.Column, MULF.Row) and
MapHex.HasUnit(UFilterNotSide)) then
Result := mvNoOverrun
else if MapHex.HasUnit(UFilterNotSide) and
(not EnemyHex(MULF.Column, MULF.Row)) then
Result := mvNeutralNotAtWar
else
begin
Result := CanStack(MapHex); // Advance after combat.

if Result = mvOK then
Result := mvMP; // Advance after combat.
end;
end;

if Result = mvOK then
begin // Determine LHR. Check for stacking limits.
LandHexList.Search(MULF.RefCol, MULF.RefRow, Index, LHR);
Result := CanStack(MapHex, False, nil, False, False, Side);

if (Result = mvOK) and Disrupt then Result := mvDisruptedExt;
end;
end;
end; // End of LCRspAdvanceAfterCombat.
end; // End of case Phase_LandCombatResolution.CurrentSubPhase.
end; // End of pLandCombatResolution.
// ****************************************************************************
// Check air rebase movement.
// ****************************************************************************
pAirRebase:
begin // Both FTCFails and RestrictedReinforcement set CanMoveTo.
if FTCFails or RestrictedReinforcement then Exit;

C := TMajorCountry(Countries[FirstMU.ControllingMajorCountry]);
ComputeUnits; // Count the # of limited activities needed to move stack.
// ****************************************************************************
// First check for rebasing from a naval transport to a land hex.
// ****************************************************************************
if FirstMU.WasAboardTransport and
(not (FirstMU.WasAboardWhom.UnitType in CarrierSet)) then
begin
if not AirHexList.Search(MULF.Column, MULF.Row, Index, AHR) then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
' Destination hex ' + HexName(MULF.Hex) +
' was not in AirHexList, whose count = ' +
IntToStr(AirHexList.Count));
*)
Result := mvOutOfRange; // Air rebase, unload from transport.
end
else
begin
Result := CanStack(MapHex); // Air rebase, unload from transport.

if (Result = mvOK) and
(not FirstMU.CanUnloadIntoHex(MULF.Hex)) then
Result := mvNoUnload;
end;
end
else
// ****************************************************************************
// Rebasing land based air from one land hex to another, or carrier air units.
// ****************************************************************************
begin
if MULF.AtSea then
begin
if FirstMU.UnitType <> utCarrierAir then
Result := mvLandAirInSeaArea
else if not AirHexList.Search(RefC, RefR, Index, AHR) then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
UFUnit.ViewName +
' can''t rebase to ' +
HexName(SmallPoint(RefC, RefR)) +
' because it is not in AirHexList.');
*)
Result := mvNoCarrier;
end
end
// ****************************************************************************
// Check for sufficient air missions or Rebase For Free.
// ****************************************************************************
else if (C.CurrLimits.AirMissions = 0) and
((not TAirUnit(FirstMU).CanAirRebaseForFree) or
// ****************************************************************************
// Rebasing for free requires not changing the unit's hex location.
// ****************************************************************************
(not SameHex)) then
Result := mvOnlyInSameHex
else
begin // The unit is moving to a land hex.
// ****************************************************************************
// RebaseRange sets CheckExtended and DoubleRange. CanMoveTo.
// ****************************************************************************
RebaseRangeMS := TAirUnit(FirstMU).RebaseRange(CheckExtended,
DoubleRange);
(*
if (FirstMU.Country = Finland.ID) and (HexHomeC = Sweden) then
begin
DistToHex := Map.AirDistance(pAirRebase, FirstMU, PickUpPoint,
MULF.Hex,
UnitHomeCountryCommonwealth(FirstMU),
RebaseRangeMS);

ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
' DistToHex = ' + IntToStr(DistToHex));
end;
*)
// ****************************************************************************
// MC is the governed area that geographically owns the destination hex, and
// HexC is the major power that controls the destination hex.
// We may want to know the minor country that controls the hex (HexMinC).
// ****************************************************************************
if EnemyStack(MapHex) then Result := mvEnemyUnit
// ****************************************************************************
// When OptRules.Internment is active, air units belonging to minor countries
// can fly into neutral minor countries to be interned. The following
// conditionals permit these moves.
// ****************************************************************************
else if OptRules.Internment and
(UnitHomeCountryCommonwealth(FirstMU).ClassType =
TMinorCountry) and
(HexHomeC.ClassType = TMinorCountry) and
(not HexHomeC.Conquered) and
HexHomeC.Neutral then
begin
if THexArea.HexDistance(PickUpPoint.Hex, MULF.Hex, MapColumns,
True) > RebaseRangeMS then
CanMoveTo := mvOutOfRange // Air rebase for internment.
else
Result := mvOK; // Internment possible.
end
else if not AirHexList.Search(MULF.RefCol, MULF.RefRow, Index,
AHR) then
begin
if not MapHex.Cooperates(Self) then Result := mvStackingNoCoop
else Result := mvOutOfRange; // Air rebase to & from a land hex.
end
else if (HexC = nil) or (HexC.Side <> C.Side) then
Result := mvHexControl;
end; // End of unit rebasing to a land hex.

if Result = mvOK then
begin
if FirstMU.UnitType = utCarrierAir then
begin
UFUnit := FirstMU;
UFPhase := pAirRebase;
UFSubPhase := AspNone;
// ****************************************************************************
// Carrier air units.
// ****************************************************************************
if MULF.AtSea then
begin
if SameHex then
begin
UFSection := MULF.Section;
// ****************************************************************************
// See if there is a carrier that the unit can load onto in the MULF Section -
// other than its current parent carrier.
// ****************************************************************************
if not MapHex.HasUnit(UFilterCarrierCanLoadPlaneInSectionExcept)
then
Result := mvNoCarrier;
end
else
begin // Destination at sea, different hex.
// ****************************************************************************
// RebaseRange sets CheckExtended and DoubleRange. CanMoveTo.
// ****************************************************************************
RebaseRangeMS := TAirUnit(FirstMU).RebaseRange(CheckExtended,
DoubleRange);
UFRange := RebaseRangeMS -
Map.AirDistance(Game.Phase, FirstMU,
PickUpPoint, MULF.Hex,
UnitHomeCountryCommonwealth(FirstMU),
RebaseRangeMS, False, True);
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
UFUnit.ViewName +
' has RebaseRange = ' + IntToStr(RebaseRangeMS) +
', has UFRange = ' + IntToStr(UFRange) +
', and is trying to rebase into ' + HexName(MULF.Hex));
*)
// ****************************************************************************
// See if there is a carrier that the unit can load onto within range - other
// than its current parent carrier.
// ****************************************************************************
if not SAStack.HasUnit(UFilterCarrierCanLoadPlaneInRangeExcept)
// if not MapHex.HasUnit(UFilterCarrierCanLoadPlaneInRangeExcept)
then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
UFUnit.ViewName +
' was unable to rebase into ' + HexName(MULF.Hex));
*)
Result := mvNoCarrier;
end;
end;
end // End of destination being AtSea.
// ****************************************************************************
// Carrier air unit whose destination is not at sea.
// ****************************************************************************
else if not MapHex.HasUnit(UFilterCanLoadOntoExcept) then
Result := CanStack(MapHex); // Carrier air unit.
end
else Result := CanStack(MapHex); // Air rebase.
end;
end;
end; // End of pAirRebase.

pAirReorganization:
begin
ComputeUnits; // Count the # of activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit; // Checks within range.
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
AspCAP:
begin
UFSide := Game.PhasingSide;
Good := MapHex.HasUnit(UFilterEnemyDisruptedNonHQUnit);
end;

AspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

if HasUnit(UFilterFlyingBoat) then
Res := CanStack(MapHex)// Air supply.
else
Res := mvOK;

if (Res = mvOK) and Good then
Good :=
MapHex.HasUnit(UFilterFriendlyCooperatingDisruptedNonHQUnit)
else
Result := Res;
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of Case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pAirReorganization.

pPartisan: CheckUsingSetupTray;

pReturnToBaseA, pReturnToBaseD: // CanMoveTo.
begin
if HasAirAndNaval then
begin
Result := mvAbortAirNaval; // Cannot move air & naval together.
Exit;
end
else if EnemyStackOrHex(MapHex) then Result := mvHexControl
else if FTCFails or
((FirstMU is TNavalUnit) and
(InvalidNavalGroup or
InvalidNavalMove)) or
// Trying to move to an all-sea hex.
RestrictedReinforcement then
Exit
else if InvalidDestination(False) then Exit;
end;

pVichy:
begin
case Game.VichySubPhase of
vspControl: ;

vspMoveNonFrenchLandAir:
begin
if MULF.OnLand and EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl;

// ShowMessageOK('[TMovingStack.CanMoveTo]: vspMoveNonFrenchLandAir ');

end
else if RestrictedReinforcement then Exit;
end;

vspMoveNonFrenchNaval:
begin
if MULF.OnLand and EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl;

// ShowMessageOK('[TMovingStack.CanMoveTo]: vspMoveNonFrenchNaval ');

end
else if RestrictedReinforcement then Exit;
end;

vspMoveFrenchAtSea:
begin
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if (not MULF.OnLand) or
((HexC <> France) and
(HexC <> VichyFrance)) then
Result := mvFranceOnly
// ****************************************************************************
// When returning French units at sea to base during Vichy declaration, only
// hexes in the NearestHexes list are legal. This might not be called.
// ****************************************************************************
else if NearHexes.Empty then
Result := mvNoRelocateHex
else if not NearHexes.Search(MULF.Column, MULF.Row) then
Result := mvOutOfRange; // French returning from sea.
end;

vspMoveFrenchLandAirAxis:
begin
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if MULF.OnLand and (HexC <> France) and (HexC <> VichyFrance) then
Result := mvFranceOnly;
end;

vspMoveFrenchNavalAxis:
begin
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if MULF.OnLand and (HexC <> France) and (HexC <> VichyFrance) then
Result := mvFranceOnly;
end;

vspDestroyFrench: ;

vspMoveFrenchLandAirAllied:
begin
if RestrictedReinforcement then Exit;
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if MULF.OnLand and (HexC <> France) and (HexC <> VichyFrance) then
Result := mvFranceOnly;
end;

vspMoveFrenchNavalAllied:
begin
if RestrictedReinforcement then Exit;
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if MULF.OnLand and (HexC <> France) and (HexC <> VichyFrance) then
Result := mvFranceOnly;
end;

vspProduction: ;

vspSetup: CheckUsingSetupTray;

vspMoveFrenchVichy: ;

vspUnitControl: ;

vspConquerFrance: ;
end; // End of case Game.VichySubPhase.
end;
end; // End of case Game.Phase.

// ShowMessageOK('[TMovingStack.CanMoveTo] Z.');

end;
// ****************************************************************************
// Finally, check if the move violates a Neutrality Pact. This takes
// restriction applies across all unit types and all phases of the game.
// ****************************************************************************
if (Result in [mvOK, mvDisruptedExt]) and HexViolatesPact(MULF.Hex) then
Result := mvPact;
end; // End of CanMoveTo.


< Message edited by Shannon V. OKeets -- 6/12/2013 8:50:52 PM >


_____________________________

Steve

Perfection is an elusive goal.

(in reply to Extraneous)
Post #: 61
RE: I believe this game will never happen - 6/12/2013 8:13:06 PM   
Greyshaft


Posts: 2252
Joined: 10/27/2003
From: Sydney, Australia
Status: offline

quote:

ORIGINAL: bo
Hey Greyshaft I think Extraneous was calling you an aborigine
Bo


While I may (or may not) agree with you Bo, we need to consider whether questions of race are appropriate in this Forum... Extraneous can call me a dork, a dumbo, an a$$hole, an ignoramous or label me with any of thousands of other vague descriptions without fear of contradiction, but tagging me as a specific racial group and implying that that race has lesser qualities than another race constitutes racial vilification in Australia and is against the law.

Perhaps we can avoid the whole nasty legal mess by just agreeing that I'm a Dumbo and moving on ?

_____________________________

/Greyshaft

(in reply to bo)
Post #: 62
RE: I believe this game will never happen - 6/12/2013 8:37:08 PM   
warspite1


Posts: 41353
Joined: 2/2/2008
From: England
Status: offline

quote:

ORIGINAL: Shannon V. OKeets


quote:

ORIGINAL: Extraneous

quote:

ORIGINAL: Shannon V. OKeets

My 10 years of playing WIF over the board yielded "very little knowledge"????


And here I thought when we started you were new at WiF.


quote:

ORIGINAL: Centuur

I think that a sane programmer who didn't play WiF over the board wouldn't start coding it... He would read the rulebook and throw the whole thing directly into a wastebucket. Far to difficult... That's why I love the fact that there is a madman here who played the game and is a skilled games programmer too...


Evidently you wouldn't pass the aptitude test for programming (yes there was/is one).

I find it laughable the way you all assume programming is such a hard thing to do.


Here is how it works in the real world.

A Systems analyst is given the project and meets with the user to define the specifications of the project

The Systems analyst then assigns Programmers from their group deadlines to write programs (executables, modules, or etc.) for the project.

The Programmers are to code and desk check their programs as completely as possible before submitting their programs to the test group.

The test group submits reports on errors found in the programs to the Systems analyst.

The Systems analyst returns the error report to the correct programmer for corrections.

The Systems analyst is responsible for seeing that all programmers provide documentation of their work, that the programmers are notified of changes from the user, and for the final presentation of the finished product.

Simple huh.

(Substitute: Developer for Systems analyst, game for project, rules for user, beta testers for test group and you have an Idea how a system design works.)

You keep assuming you know more about a topic because you've read something about them. People who work in the field have several orders of magnitude more knowledge than someone who has merely read up on a subject.

Here is some "simple programming" for you to critique. This is an excerpt of ~4000 lines of code from a module of 11,000 lines. There are ~250 modules in MWIF, totaling over 400,000 lines of code.

The following code (which references hundreds of code segments in other modules) is to determine if a stack of units that the players has picked up can move to the hex over which the players has moved the cursor. This executes in real time as the player moves the mouse over the map. For each hex it the cursor passes over, a message is shown on the Main form telling the player whether the move is legal - and if not, why not. The cursor itself is also updated to either a target icon (ok move) or an X (move illegal).

---

// ****************************************************************************
function TMovingStack.CanMoveTo(const MULF: TUnitLocationFull;
var Disrupt: Boolean;
const CheckIfValid: Boolean = True;
const CheckShift: Boolean = True): TMoveResult;
var
U: TUnit;
FirstMU: TUnit; // First Moving Unit in Self.
C: TMajorCountry;
HexMP: TMajorCountry;
MPow: TMajorCountry;
Index: Longint;
RR: TRailHexData;
Old: TUnitLocationFull;
HS: THexsideRange;
MapHex: TMapStack;
SAStack: TUnitStack;
RefC: Integer; // Reference hex for sea area.
RefR: Integer;
Good: Boolean;
HasAir: Boolean;
Res: TMoveResult;
AHR: TAirHexRecord;
LHR: TLandHexRecord;
HR: TNavalHexRecord;
SectionSet: set of TSectionRange;
HQAdjacent: Boolean;
HQSameHex: Boolean;
MC: TGovernedArea;
HexHomeC: TMinorCountry;
MajC: TMajorCountry;
HexC: TMajorCountry;
HexMinC: TMinorCountry;
AirMaxRange: Integer;
ADistance: Integer;
HDistance: Integer;
CR: TLandCombatHex;
CR2: TLandCombatHex;
SameHex: Boolean;
MoveToSameHexNotOk: Boolean;
NavalUnitCounts: array [TMajorCountries] of Word;
Bombers: array [TMajorCountries] of Word;
LandUnits: array [TMajorCountries] of Word;
AirUnits: array [TMajorCountries] of Word;
MPI: TMajorCountries;
CCCount: Integer;
CCIndex: Integer; // Index for looking for Communist Chinese units.
CCUnit: TUnit;
CCFound: Boolean;
Coop: Boolean;
RebaseRangeMS: Integer;
// DistToHex: Integer;
CheckExtended: Boolean;
DoubleRange: Integer;
Shift: TShiftState;
MaxRange: Integer;
EastPol: Boolean;
BalticStat: Boolean;
F1stMovSUIndx2: Integer;
F1stMovSUni2: TUnit;
FoundMovSUni2: TUnit;
F1stMovSUIndx4: Integer;
F1stMovSUni4: TNavalUnit;
FoundMovSUni4: TNavalUnit;
CantTravel: Boolean;
Cargo: TUnit;
First: TUnit;
Second: TUnit;

procedure CheckUsingSetupTray;
begin
// ****************************************************************************
// Check for placing units on the map from the setup tray.
// ****************************************************************************
MapHex := MapStacks[MULF.Column, MULF.Row]; // Map stack of destination.
Result := CanSetup(MULF.Column, MULF.Row); // CanMoveTo.

if Result = mvOK then Result := CanStack(MapHex); // Setup stacking limits.

if (Result = mvStackingAir) and
(not MULF.AtSea) and
(UnitCount(UFilterCarrierAirUnit) = 1) then
begin
UFUnit := FindUnit(UFilterCarrierAirUnit);
UFPhase := Game.Phase;
UFSubPhase := aspNone;

if MapHex.HasUnit(UFilterCarrierCanLoadPlane) then Result := mvOK;
end;
end; // End of CheckUsingSetupTray.

function MovingNeutral: Boolean;
begin
// ****************************************************************************
// Check for neutral country trying to move.
// ****************************************************************************
Result := False;
F1stMovSUIndx2 := 0;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if F1stMovSUni2.NeutralProhibitedHex(MULF.Column, MULF.Row) then
begin
CanMoveTo := mvNeutralMove;
Result := True;
Exit;
end;

Inc(F1stMovSUIndx2);
end;
end;

function FTCFails: Boolean;
// ****************************************************************************
// Under very special circumstances, check for foreign troop commitment.
// ****************************************************************************
function NotEnoughMPOrRange: Boolean;
var
Index: Integer;
HRMP: TnavalHexRecord;
begin // Test if range and movement points permit a naval move.
Result :=
(not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index, HRMP)) or
(MaxNavalRange - HRMP.AvoidRange <= 0) or
(MaxNavalMovement - HRMP.AvoidMP <= 0);
end;

begin // FTCFails.
Result := False;

if (HexC <> nil) and // Hex must have an owner.
(FirstMU.Side = HexC.Side) and // Moving unit & hex on same side.
(HexMP <> nil) and
(HexMP.ID = HexC.ID) and
((not CheckShift) or
(not (ssCtrl in Shift)) or
(Game.Phase <> pNavalMovement) or
LoadedInPort or
NotEnoughMPOrRange) and // Use NavalHexList to check MPs and range.
(not CanMoveToCountry(Map.HexFTCCountry[MULF.Column, MULF.Row])) then
begin // 'The foreign troop commitment limit for %s will not be satisfied.'
(*
ShowMessageOK('[TMovingStack.CanMoveTo] FTCFails' +
'. HexMP = ' + HexMP.Name +
'. FirstMU''s country = ' +
Countries[FirstMU.Country].Name );
*)
CanMoveTo := mvForeignCommitment;
Result := True;
end;
end; // End of FTCFails.

function InvalidNavalGroup: Boolean;
begin
Result := False;
SectionSet := [];

if HasSurfaceAndSubs then
begin
CanMoveTo := mvSurfaceSubs; // Cannot move surface naval & subs together.
Result := True;
Exit;
end
else
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if (SectionSet <> []) and (not(F1stMovSUni2.Section in SectionSet)) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end
else
Include(SectionSet, F1stMovSUni2.Section);

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 <> nil then
begin // Units can't start in different sections.
CanMoveTo := mvNotAllSameSection;
Result := True;
Exit;
end;
end;
end; // End of InvalidNavalGroup.

function IllegalPartisanMove: Boolean;
begin
Result := False;
F1stMovSUIndx2 := 0;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if (F1stMovSUni2.UnitType = utPartisan) and
(MULF.AtSea or (Map.HexHomeCountry[MULF.Column,
MULF.Row] <> UnitHomeCountry(F1stMovSUni2))) then
begin
CanMoveTo := mvPartisan;
Result := True; // True means the the partisan was moved illegally.
Exit;
end;

Inc(F1stMovSUIndx2);
end;
end; // End of IllegalPartisanMove.

function IllegalWarlordMove: Boolean;

function CheckWarlord(var U: TUnit): Boolean;
var
Hx: TSmallPoint;
begin // True means the the warlord was moved illegally.
Result := (U.UnitType = utWarlord);

if Result then
begin
Hx := SmallPoint(TLandUnit(U).CityColumn, TLandUnit(U).CityRow);

Result := MULF.AtSea or (TGameMapArea.HexDistance(MULF, Hx) > 6);
end;
end;

begin // IllegalWarlordMove.
Result := False;
F1stMovSUIndx2 := 0;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if CheckWarlord(F1stMovSUni2) then
begin
CanMoveTo := mvWarlordRange; // Moving a warlord unit illegally.
Result := True;
Exit;
end;

Inc(F1stMovSUIndx2);
end;
end; // End of IllegalWarlordMove.

procedure ComputeUnits;
var
MStckIndx: Integer;
MStckUni: TUnit;
// ****************************************************************************
// Count the number of limited moves needed to move the stack.
// ****************************************************************************
var
MCCounter: TMajorCountries;
ConvoyPts: array [TMajorCountries] of Word; // Convoys are worth 1/2.

procedure CountUnit(var U: TUnit);
var
MCi: TMajorCountries;
begin
MCi := UnitControllingMajorCountry(U).Value;

if UFilterStackingNonConvoyNavalUnit(U) then
Inc(NavalUnitCounts[MCi])
else if UFilterConvoyUnit(U) then
Inc(ConvoyPts[MCi], TNavalUnit(U).Convoy)
else if UFilterAirUnit(U) then
begin
Inc(AirUnits[MCi]);

if UFilterBomber(U) then
Inc(Bombers[MCi]);
end
else if UFilterLandUnit(U) and (not U.LandMovesForFree) then
Inc(LandUnits[MCi]);
end;

begin // ComputeUnits.
FillChar(NavalUnitCounts, SizeOf(NavalUnitCounts), 0); // Naval unit moves.
FillChar(ConvoyPts, SizeOf(ConvoyPts), 0); // Convoys = 1/2.
FillChar(Bombers, SizeOf(Bombers), 0); // Bombing missions.
FillChar(LandUnits, SizeOf(LandUnits), 0); // Land unit moves.
FillChar(AirUnits, SizeOf(LandUnits), 0); // Air unit moves.
MStckIndx := 0;

while MStckIndx < Count do
begin
MStckUni := TUnit(Item[MStckIndx]);
CountUnit(MStckUni);
Inc(MStckIndx);
end;
// ****************************************************************************
// For every 2 convoys add 1 naval move.
// ****************************************************************************
for MCCounter := Low(TMajorCountries) to High(TMajorCountries) do
Inc(NavalUnitCounts[MCCounter], Succ(ConvoyPts[MCCounter]) div 2);
end; // End of ComputeUnits.

function RestrictedReinforcement: Boolean;
// ****************************************************************************
// Check if the player is trying to move units to reinforce an area in the
// Pacific in violation of the US Entry options/restrictions.
// ****************************************************************************
function CheckReinforcing(var U: TUnit): Boolean;
var
Loc: TSetupLocation;
begin
Result := True; // Default is violation occurs.
// ****************************************************************************
// US Entry option #26, US relocates fleet to Pearl Harbor.
// Only US naval transports and convoys can base at Honolulu or Pago Pago unless
// option #26 has been chosen.
// ****************************************************************************
if (EqualSmallPt(MULF.Hex, Honolulu) or
EqualSmallPt(MULF.Hex, PagoPago)) and
(not USEntry.OptionChosen(useRelocate)) and
UFilterUSNotPearlHarbor(U) then
begin
CanMoveTo := mvUSPearlHarbor; // Assign result for function CanMoveTo.
Exit;
end;
// ****************************************************************************
// Allied land and aircraft units are prohibited from entering certain areas of
// the map until US entry options have been taken, or the Axis has moved there.
// ****************************************************************************
if UFilterAlliedAirNotOnCarrierOrLandUnit(U) then
begin
// ****************************************************************************
// US Entry option #43, CW reinforces the NEI.
// Only NEI land and air units can enter NEI until (1) the Comonwealth and Japan
// are at war, or (2) option #43 has been selected, or (3) an axis land unit has
// entered NEI. All 3 of these are kept track of with CWCanReinforceNEI.
// ****************************************************************************
if (MC = NEI) and // MC is the country of the hex under the cursor.
(U.SourceCountry <> NEI.ID) and (not CWCanReinforceNEI) then
begin
CanMoveTo := mvCWNEI; // Assign result for function CanMoveTo.
Exit;
end;
// ****************************************************************************
// US Entry option #36, CW reinforces the Pacific.
// Allied land and air units can not enter Hong Kong or any Commonwealth
// controlled territory in the Pacific until (1) The Comonwealth and Japan are
// at war, (2) option #36 has been selected, or (3) an Axis land unit has
// entered Hong Kong or a Commonwealth controlled territory in the Pacific. All
// 3 of these are kept track of with CWCanReinforcePacific.
// ****************************************************************************
if ((MC = HongKong) or
((MC.ControllingMajorPower = Commonwealth) and
(MC.ClassType = TGovernedArea) and
MC.Pacific)) and
(not CWCanReinforcePacific) then
begin
CanMoveTo := mvCWPacific; // Assign result for function CanMoveTo.
Exit;
end;
// ****************************************************************************
// US Entry option #40, USA reinforces Guam.
// USA land and air units can not enter Guam until (1) option #40 has been
// selected or (2) an Axis land unit has entered Guam or the Marshalls. Both of
// these are kept track of with USCanReinforceGuam.
// ****************************************************************************
if EqualSmallPt(MULF.Hex, Guam) and (not USCanReinforceGuam) then
begin
CanMoveTo := mvUSGuam; // Assign result for function CanMoveTo.
Exit;
end;
// ****************************************************************************
// US Entry option #41, US reinforces the Philippines.
// USA land and air units can not enter the Philippines until (1) option #40 has
// been selected or (2) an Axis land unit has entered the Philippines. Both of
// these are kept track of with USCanReinforcePhilippines.
// In some scenarios the US starts with units in the Philippines. An exception
// is made to permit those units to relocate within the Philippines.
// Territorial units are not subject to this rule.
// ****************************************************************************
if (MC = Philippines) and
(U.SourceCountry <> Philippines.ID) and
(not USCanReinforcePhilippines) and
((not PickUpPoint.OnMap) or
(Map.HexCountry[PickUpPoint.Column, PickUpPoint.Row] <>
Philippines)) then
begin
// ****************************************************************************
// Unit's SetupGroupIndex - 1 is the index into SULocations.
// ****************************************************************************
if (Game.Phase = pSetup) and EqualSmallPt(MULF.Hex, Manila) then
begin
Loc := SULocations[U.SetupGroupIndex - 1];

if String(Loc.CityName) <> rsManila then
begin
CanMoveTo := mvUSPhilippines; // Result for function CanMoveTo.
Exit;
end;
end
else
begin
CanMoveTo := mvUSPhilippines; // Result for function CanMoveTo.
Exit;
end;
end;
end;

Result := False; // No violation occurred.
end;

begin // RestrictedReinforcement.
Result := False;
// ****************************************************************************
// Restrictions on setting up do not apply to later scenarios.
// ****************************************************************************
if CurrScenario in [scGuadalCanal, scBruteForce, scDarkness,
scDeclineAndFall] then
Exit;

if (MC <> nil) and (not HasAllUnit(UFilterPartisan)) then
begin
F1stMovSUIndx2 := 0;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if CheckReinforcing(F1stMovSUni2) then
begin
Result := True; // Move will violate restricted reinforcement.
Exit;
end;

Inc(F1stMovSUIndx2);
end;
end;
end; // End of RestrictedReinforcement.

function InsufficientAirMissions: Boolean;
var
MPIndex: TMajorCountries;
begin
Result := False;
// ****************************************************************************
// Check for exceeding air mission limits.
// ****************************************************************************
if HasAir then
begin
// ****************************************************************************
// Compare the number of bombers in the moving stack to the air mission limits
// for the owning major power.
// ****************************************************************************
for MPIndex := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPIndex];

if MPow.LegalCountry and
(MPow.CurrLimits.AirMissions <> aUnlimited) and
(Bombers[MPIndex] > MPow.CurrLimits.AirMissions) then
begin
CanMoveTo := mvAirMissions;
Result := True;
Exit;
end;
end;
end;
end; // End of InsufficientAirMissions.

function NoCooperationWithTarget: Boolean;
// ****************************************************************************
// This routine returns True if there is no cooperation or if the target is out
// of range. Otherwise it sets Good depending on the target hex's terrain.
// ****************************************************************************
function CheckForNoBombers: Boolean;
var
NoNeedToCheck: Boolean;
// ****************************************************************************
// This routine returns True if there no bombers in the target hex and a fighter
// is attempting to fly to the hex.
// ****************************************************************************
begin
// ****************************************************************************
// There is no need to check for bombers during:
// AspCAP,
// during any subphase except AspFlyA of non-GroundSupport air missions,
// during any subphase except AspFlyA and AspFlyD of Ground Support missions.
// ****************************************************************************
NoNeedToCheck := (Game.AirSubPhase = AspCAP) or
((Game.Phase <> pGroundSupport) and
(Game.AirSubPhase <> AspFlyA)) or
((Game.Phase = pGroundSupport) and
(not (Game.AirSubPhase in [AspFlyA, AspFlyD])));

if NoNeedToCheck then
begin
Result := False;
Exit;
end;
// ****************************************************************************
// Check for fighter flying day missions.
// ****************************************************************************
Result := HasUnit(UFilterFighterDayMission) and
(not HasUnit(UFilterBomberDayMission)) and // No bomber in stack.
(((Game.AirSubPhase = AspFlyA) and // No bomber in hex.
(not MapHex.HasUnit(UFilterBomberFlyingDayMission))) or
((Game.AirSubPhase = AspFlyD) and
(not OtherStackFilter(MapHex,
UFilterFriendlyBomberFlyingDayMission))
and
((not OtherStackFilter(MapHex,
UFilterEnemyFlyingDayMission)) or
(Self.AirDistanceFromTo(PickUpPoint, MULF.Hex, MaxRange) >
MaxRange))));

if Result then Exit;
// ****************************************************************************
// Check for bombers flying night missions.
// ****************************************************************************
Result := HasUnit(UFilterFighterNightMission) and
(not HasUnit(UFilterBomberNightMission)) and // No bomber in stack.
(((Game.AirSubPhase = AspFlyA) and // No bomber in hex.
(not MapHex.HasUnit(UFilterBomberFlyingNightMission))) or
((Game.AirSubPhase = AspFlyD) and
(not OtherStackFilter(MapHex,
UFilterFriendlyBomberFlyingNightMission))
and
((not OtherStackFilter(MapHex,
UFilterEnemyFlyingNightMission)) or
(Self.AirDistanceFromTo(PickUpPoint, MULF.Hex, MaxRange) >
Values.ARngMax))));
end;

begin
// ****************************************************************************
// NoCooperationWithTarget.
// Set cooperation with target units during ground strikes and ground support.
// Check artillery too if ground strike or ground support phase.
// ****************************************************************************
if HasAir or (Game.Phase in [pGroundSupport, pGroundStrike]) then
begin
if Game.Phase in [pGroundSupport, pGroundStrike] then
begin
if Side = Game.PhasingSide then // Non-phasing side is ok.
begin
LandCombatHexes.Search(MULF.Hex, Index, CR); // Land combat hex.

if CR = nil then Coop := CooperatesFlying(MapHex)
else Coop := CooperatesNotFlying(CR.CombatHexUnits) and
CooperatesFlying(MapHex);
end // Non-phasing side in ground support and ground strike.
else Coop := Cooperates(MapHex);
end
else Coop := CooperatesFlying(MapHex);
end
else Coop := True;
// ****************************************************************************
// Set MaxRange for ground support to ???
// ****************************************************************************
if Game.Phase = pGroundSupport then MaxRange := (Values.ARngMin + 1) div 2
else MaxRange := 0;
// ****************************************************************************
// Check that bombers (and artillery) correctly cooperate and are within range.
// ****************************************************************************
Result := False;

if (not Coop) or (not Self.Cooperates(Self)) then
begin
CanMoveTo := mvStackingNoCoop; // NoCooperationWithTarget.
Result := True;
end
else if CheckForNoBombers then
begin // No bombers when one must be present.
CanMoveTo := mvAirNoBombers;
Result := True;
end
else
begin
// ****************************************************************************
// Determine terrain conditions in target hex.
// ****************************************************************************
case Map.WeatherTerrain[MULF.Column, MULF.Row] of
teSea: Good := False;

teLake: Good := HasAir;

else Good := True;
end;
end; // End of non-cooperation.
end; // End of NoCooperationWithTarget.

function UnableToFlyToHex: Boolean;
begin // Called for each of the 8 air mission phases.
Result := False;

if HasAir then
begin
if (ADistance > AirMaxRange) and
// ****************************************************************************
// More severe restrictions than simply being within range apply during port
// attacks by air units that started at sea. They must be in a sea area that is
// adjacent to the port.
// ****************************************************************************
((Game.Phase <> pPortAttack) or
(not StartedAtSea) or
(ADistance > 1) or
(Map.Port[MULF.Column, MULF.Row] = ptNone)) then
begin
CanMoveTo := mvOutOfRange; // 8 air mission phases.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: UnableToFlyToHex ' +
'ADistance = ' + IntToStr(ADistance) +
'. AirMaxRange = ' + IntToStr(AirMaxRange));
*)
Result := True;
end
else if not (Game.AirSubPhase in [aspReturnA, aspReturnD]) then
begin
// ****************************************************************************
// Check for permission to fly given bad weather in the destination hex.
// ****************************************************************************
if Map.HexWeather[MULF.Column, MULF.Row] in NoAirFactorsWeather then
begin
CanMoveTo := mvAirWeather;
Result := True;
end
// ****************************************************************************
// Record aircraft that are flying at extended range.
// ****************************************************************************
else if ((Game.Phase <> pPortAttack) or
(not StartedAtSea) or
(ADistance > 1)) and
((ADistance > AirNormalRange) or
HasUnit(UFilterForceExtendedUnit)) then
begin
CanMoveTo := mvDisruptedExt;
end;
end;
end; // End of HasAir.
end; // End of UnableToFlyToHex.

function IsInTargetRange(var TargetRangeUnit: TUnit): Boolean;
begin // TargetRangeUnit is a unit in the moving stack.
Result := UnitInTargetRange(TargetRangeUnit, Game.AirSubPhase, MULF.Hex);
end;

function CantInterceptA: Boolean;
begin
Result := False;
Good := OtherStackFilter(MapHex, UFilterSelectedEnemyAirUnitMissionTime);
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: AspInterceptA ' +
'. Good = ' + BoolToStr(Good));
*)
if Good then
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if IsInTargetRange(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 = nil then
begin
CanMoveTo := mvNoTarget;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: AspInterceptA ' +
'. Failed target in range.');
*)
Exit;
end;
end;

if not Cooperates(MapHex) then // CantInterceptA.
begin
CanMoveTo := mvStackingNoCoop;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: AspInterceptA ' +
'. Failed Cooperates.');
*)
end;
end; // End of CantInterceptA.

function CantInterceptD: Boolean;
begin
Result := False;
Good := OtherStackFilter(MapHex, UFilterSelectedEnemyAirUnitMissionTime);

if Good then
begin
if (Game.Phase = pStrategicBombardment) and
MapHex.UnitsSurpriseHex then // Air interception.
begin
CanMoveTo := mvAirSurprisedHex;
Result := True;
Exit;
end
else if MapHex.SurprisedStack(Self, Game.NonPhasingSide, UFilterFlying,
UFilterAirUnit) or
((Game.Phase in [pPortAttack, pCarpetBombing, pGroundStrike,
pGroundSupport]) and
MapHex.SurprisedStack(MapHex, Game.NonPhasingSide,
UFilterFlying)) then
begin
CanMoveTo := mvAirSurprisedIntercept;
Result := True;
Exit;
end
else
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if IsInTargetRange(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 = nil then
begin
CanMoveTo := mvNoTarget;
Result := True;
Exit;
end;
end;

if not Cooperates(MapHex) then // CantInterceptD.
begin
CanMoveTo := mvStackingNoCoop;
Result := True;
end;
end;
end; // End of CantInterceptD.

function CantReturnAD: Boolean;
var
MovRes: TMoveResult;
begin // Air units only.
Result := False;
// ****************************************************************************
// When OptRules.Internment is active, air units belonging to minor countries
// can fly into neutral minor countries to be interned. This can happen at any
// time that the air unit can fly (e.g., return to base, forced rebase, etc.).
// The following conditionals permit these moves.
// ****************************************************************************
Good := OptRules.Internment and
(FirstMU is TAirUnit) and
(UnitHomeCountryCommonwealth(FirstMU).ClassType = TMinorCountry) and
MULF.OnLand and
(Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.ClassType =
TMinorCountry) and
(not Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.Conquered)
and
Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.Neutral;

if not Good then
begin
Good := FriendlyHex(MULF.Column, MULF.Row);

if not Good then
begin
CanMoveTo := mvNotAFriendlyHex;
Result := True;
end
else
begin
if EnemyStack(MapHex) then
begin
CanMoveTo := mvEnemyUnit;
Result := True;
end
else
begin
MovRes := CanStack(MapHex, False, nil, False, True); // Air units only.
CanMoveTo := MovRes;
Result := MovRes <> mvOK;
end;
end;
end;
end; // End of CantReturnAD.

function InvalidNavalMove: Boolean;
var
MovRes: TMoveResult;
begin
Result := False;
// ****************************************************************************
// Test stacking limits for moving naval units.
// ****************************************************************************
// if Game.DigressionInProgress or
// (Game.Phase in [pReturnToBaseA, pReturnToBaseD]) then
// begin
MovRes := CanStack(MapHex);

if MovRes <> mvOK then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = MovRes.');
*)
if MULF.OnLand and (Map.Port[MULF.Column, MULF.Row] = ptNone) then
begin
CanMoveTo := mvNoPort;
Result := True;
Exit;
end
else
begin
if MULF.OnLand and
(Map.Port[MULF.Column, MULF.Row] <> ptNone) and
(MovRes in [mvStackingLand, mvStackingAir, mvStackingFlyingBoat,
mvStackingNaval]) then
begin // Nothing needs to be done here?

end
else
begin
CanMoveTo := MovRes;
Result := True;
Exit;
end;
end;
end;
// ****************************************************************************
// Test moving naval units during Vichy formation.
// In the Vichy subphases vspMoveFrenchAtSea, vspMoveFrenchNavalAxis, and
// vspMoveFrenchNavalAllied NearHexes stores the legal hex destinations.
// ****************************************************************************
if (Game.Phase = pVichy) and
(Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied]) then
begin
if NearHexes.Empty then
begin
CanMoveTo := mvNoAbortPort;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove NearHexes ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNoAbortPort.');
*)
end
else if not NearHexes.Search(MULF.Column, MULF.Row) then
begin
CanMoveTo := mvNotClosest;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNotClosest.');
*)
end;
end
// ****************************************************************************
// Test whether the hex is a valid destination or waypoint. This sets HR.
// ****************************************************************************
else if not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index, HR) then
begin
if MULF.AtSea and
(CurrScenario <> scGuadalCanal) and
(not SeaAreas[MULF.SeaAreaID].LegalSeaArea) then
begin // Barbarossa and half map scenarios only.
CanMoveTo := mvIllegalSeaArea;
Result := True;
end
else if StartedAtSea and
MULF.AtSea and
((Old.SeaAreaID <> MULF.SeaAreaID) or
// ****************************************************************************
// A stack can't move into the sea area where it started if interception is
// possible. So, if you leave a sea area (S) and then return to S, and enemy
// units can intercept the moving stack in S, then S is not a valid destination.
// ****************************************************************************
(HR.DirectMP > 0)) then
begin
CanMoveTo := mvNoSeaArea;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNoSeaArea.');
*)
end
else if Game.DigressionInProgress and
(Game.CurrentDigression = digOverrun) then
begin
CanMoveTo := mvMoveToPortWithinRange;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvMoveToPortWithinRange.');
*)
end
else if Game.Phase = pNavalMovement then
begin
CanMoveTo := mvMP;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvMP' +
'. NavalHexList count = ' + IntToStr(NavalHexList.Count));
*)
end
else if NavalHexList.Empty then
begin
CanMoveTo := mvNoAbortPort;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove NavalHexList ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNoAbortPort.');
*)
end
else
begin
CanMoveTo := mvMoveToPort;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvMoveToPort.');
*)
end;
end
else
// ****************************************************************************
// Even though the sea area in is NavalHexList, you may only be allowed to move
// there if using control-left-click. It cannot be a final stopping place.
// ****************************************************************************
begin
if MULF.AtSea and
(Shift * [ssCtrl] = []) and // Not Ctrl-Left-Shift.
((Game.DigressionInProgress and
(not HR.EnemyZOC)) or // Must end in a port.
// ****************************************************************************
// A stack can only end its move in the sea area where it started if it hasn't
// moved.
// ****************************************************************************
(StartedAtSea and
((Old.SeaAreaID <> MULF.SeaAreaID) or
((Old.SeaAreaID = MULF.SeaAreaID) and
(MPUsedSoFar > 0))))) then
begin
CanMoveTo := mvPassThruSeaArea;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvPassThruSeaArea.' +
'. Old sea area = ' + SeaAreas[Old.SeaAreaID].Name +
'. New sea area = ' + SeaAreas[MULF.SeaAreaID].Name +
'. DirectMP = ' + IntToStr(HR.DirectMP));
*)
end;
end;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. About to call CheckIfValid.');
*)
// ****************************************************************************
// Not Result means the move is ok to make.
// ****************************************************************************
if (not Result) and
CheckIfValid and
(not HR.ValidMove) and
(not (Game.VichySubPhase in [vspMoveFrenchAtSea, vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied])) then
begin
CanMoveTo := mvMoveThroughEnemySeaArea;
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalMove ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvMoveThroughEnemySeaArea.');
*)
end;
// end;
end; // End of InvalidNavalMove.

function InvalidNavalAirNavalMission: Boolean;
begin
Result := False;

if HasUnit(UFilterNightMission) then
begin
CanMoveTo := mvNightNavalAir; // Naval Air night missions not permitted.
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalAirNavalMission ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvNightNavalAir.');
*)
end
else
begin
if (Map.HexWeather[MULF.Column, MULF.Row] in NoAirFactorsWeather) then
begin
CanMoveTo := mvAirWeather; // Flights not permitted into bad weather.
Result := True;
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidNavalAirNavalMission ' +
HexName(SmallPoint(MapHex.Column, MapHex.Row)) +
'. CanMoveTo = mvAirWeather.');
*)
end;
end;
end;

function InvalidNavalAirSupport: Boolean;
begin
Result := False;
// ****************************************************************************
// Check for trying to move the stack to a hex not in the sea area where the
// current naval combat is occurring.
// ****************************************************************************
if (not MULF.AtSea) or
(MULF.SeaAreaID <> Game.CurrNavalCombat.NCHSeaArea.ID) then
begin
CanMoveTo := mvCombatSeaArea;
Result := True;
end;
end;
(*
if ((Game.Phase in [pReturnToBaseA, pReturnToBaseD]) or
Game.NavalCombatAbortDigress) or
(P in [pNavalAir, pNavalCombatA, pNavalCombatD]) then
end;
*)
function InvalidDestination(const CanUseDoubleRange: Boolean = True): Boolean;
var // Only air units. Not used for the 8 air missions or air rebases.
MovRes: TMoveResult;
MaximumRange: Integer;
begin
Result := False;

if not (FirstMU is TAirUnit) then Exit;

if MULF.AtSea then
begin // Moving to a sea area.
UFUnit := FirstMU;

if StartedAtSea then
begin
if (Game.Phase in ReturnToBasePhases) or
Game.NavalCombatAbortDigress or
(MULF.SeaAreaID <> PickUpPoint.SeaAreaID) then
begin
CanMoveTo := mvNavalAirOtherSeaArea;
Result := True; // Cannot fly Naval Air into a different sea area.
end
else
begin
// ****************************************************************************
// rsNavalAirSection0 = 'You can only fly to the same sea area if you can ' +
// 'move to a lower section'. This is not possible from section zero.
// ****************************************************************************
if FirstMU.Section = 0 then
begin
CanMoveTo := mvNavalAirSection0;
Result := True;
end;
end;
end;
end
else
begin // Moving to a land hex.
C := TMajorCountry(Countries[FirstMU.ControllingMajorCountry]);

if ((Game.Phase <> pVichy) or
(not (Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied]))) and
((HexC <> nil) and
(HexC.Side = OtherSide(C.Side))) then
begin
CanMoveTo := mvHexControl;

// ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidDestination ');

Result := True;
end
else if EnemyStack(MapHex) then
begin
CanMoveTo := mvEnemyUnit;
Result := True;
end;
end; // End of moving to a land hex.

if not Result then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: Range check.');

// ****************************************************************************
// If the air unit is at sea flying at extended range, then it can use extended
// range to return to base.
// ****************************************************************************
if CanUseDoubleRange or (TAirUnit(FirstMU).FlyingExtended) then
MaximumRange := AirMaxRange * 2
else
MaximumRange := AirMaxRange;

if Map.AirDistance(Game.Phase, FirstMU, PickUpPoint, MULF.Hex,
UnitHomeCountryCommonwealth(FirstMU),
MaximumRange) +
(Ord(Game.SectionRangePhase or
((Game.DigressionInProgress) and
(Game.CurrentDigression = digReturnToBase))) *
SeaAreaRange[FirstMU.Section]) >
MaximumRange then
begin
CanMoveTo := mvOutOfRange; // Not used for the air missions or rebases.

// ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidDestination ' +
// 'MaximumRange = ' + IntToStr(MaximumRange));

Result := True;
end;
end;

if not Result then
begin
MovRes := CanStack(MapHex);

if MovRes <> mvOK then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: InvalidDestination ' +
// 'Can not stack in hex.');

CanMoveTo := MovRes;
Result := True;
end;
end;
end;

function NotLoaded(var U: TUnit): Boolean;
var
AU: TAirUnit;
begin
AU := TAirUnit(U);
Result := (U is TAirUnit) and AU.Bomber and (AU.TransportingTotal = 0);
end;

function NotSupplyLoaded(var U: TUnit): Boolean;
var
AU: TAirUnit;
begin
Result := False;
AU := TAirUnit(U);

if (U is TAirUnit) and
AU.Bomber and
(AU.AirTransport = atrNormal) and
(AU.TransportingTotal = 1) and
(AU.TransLink[1].UnitType in LargeAirTransportSet) then
begin // LargeAirTransportSet = [utArmoredParatroop, utSupply].
Cargo := AU.TransLink[1]; // AU's cargo.

// ShowMessageOK('[TMovingStack.CanMoveTo] NotSupplyLoaded with Cargo = ' +
// Cargo.ViewName);

First := Cargo.TransportedByWhom; // First transport carrying Cargo.
Second := Cargo.TransLink[2]; // Cargo stores 2nd transporting unit.
Result := (First = nil) or
(Second = nil) or
(IndexOf(Second) = tbNone) or
(IndexOf(First) = tbNone);
end;
end;

function IsAirLandingUnit(var U: TUnit): Boolean;
begin
Result := (U.UnitType = utAirLanding) and U.AboardTransport;
end;

function IsParatroopUnit(var PU: TUnit): Boolean;
begin
Result := (PU.UnitType = utParatroop)
and PU.AboardTransport and PU.Cooperates(U);
end;

function NoAttack(var U: TUnit): Boolean;
var
CR3: TLandCombatHex;
UIndx: Integer;
UInStack: TUnit;
MPCont: TMajorCountry;
begin
if U.Country = CommunistChina.ID then
begin
if CCLimitsCurr.LandAttacks = aUnlimited then
begin
Result := False; // Unlimited attacks permitted.
Exit;
end;

if LandCombatHexes.Search(MULF.Hex, Index, CR3) then
begin
for UIndx := 0 to CR3.CombatHexUnits.Count - 1 do
begin
UInStack := CR3.CombatHexUnits[UIndx];

if UInStack.Country = CommunistChina.ID then
begin
Result := False; // Another CC unit added to existing attack.
Exit;
end;
end;

Result := CCLimitsCurr.LandAttacks = 0; // New attack needed.
end
else
Result := CCLimitsCurr.LandAttacks = 0; // New attack needed.
end
else
begin // Not a Communist Chinese unit.
MPCont := UnitControllingMajorCountry(U);

if MPCont.CurrLimits.LandAttacks = aUnlimited then
begin
Result := False; // Unlimited attacks permitted.
Exit;
end;

if LandCombatHexes.Search(MULF.Hex, Index, CR3) and
(MPCont.Value in CR3.AttLandMPs) then
Result := False// Another MPCont unit added to existing attack.
else
Result := MPCont.CurrLimits.LandAttacks = 0; // New attack needed.
end;
end;

function NoSB(var U: TNavalUnit): Boolean;
begin // SB = Shore Bombardment.
Result := not U.CanShoreBombardHex(MULF.Column, MULF.Row,
Game.Phase = pShoreBombardmentA);
end;

function NoSBFactors(var U: TNavalUnit): Boolean;
begin // SB = Shore Bombardment.
Result := U.BombardmentHex[MULF.Column, MULF.Row] = 0;
end;

function AnyWillBeDisrupted: Boolean;
var
F1stMovSUIndx: Integer;
F1stMovSUni: TLandUnit;
FoundMovSUni: TLandUnit;
begin
F1stMovSUIndx := 0;
FoundMovSUni := nil;

while F1stMovSUIndx < Count do
begin
F1stMovSUni := TLandUnit(Item[F1stMovSUIndx]);

if F1stMovSUni.TerrainMP[MULF.Column, MULF.Row] >
F1stMovSUni.CurrMove then
begin
FoundMovSUni := F1stMovSUni;
Break;
end;

Inc(F1stMovSUIndx);
end;

Result := FoundMovSUni <> nil;
end;

function DoesntCooperatesWithHex(const SelfU: TUnit): Boolean;
begin
(*
if HexMinC = nil then
MainForm.DebugPanel.Caption :=
'[TMovingStack.CanMoveTo]: DoesntCooperatesWithHex ' +
HexName(MULF.Hex) + '. HexMinC is nil.'
else
MainForm.DebugPanel.Caption :=
'[TMovingStack.CanMoveTo]: DoesntCooperatesWithHex ' +
HexName(MULF.Hex) + '. ' + HexMinC.Name;
*)
Result := (HexMinC <> nil) and (not HexMinC.CooperatesWith(SelfU.Country));
end;

function DoesCooperate(var U: TUnit): Boolean;
var // This routine is only called when flying CAP.
F1stMovSUIndx: Integer;
F1stMovSUni: TUnit;
FoundMovSUni: TUnit;
// ****************************************************************************
// Returns True if U cooperates with any units in Self.
// ****************************************************************************
function CooperatesWithUnit(var SelfU: TUnit): Boolean;
var
MinC2: TMinorCountry;
begin
MinC2 := Countries[SelfU.Country].HomeCountryCommonwealth;
Result := MinC2.CooperatesWith(U.Country);
end;

begin // DoesCooperate.
Result := Game.NonPhasingSide = U.Side; // Only check units on non-phasing side.

if Result then
begin
F1stMovSUIndx := 0;
FoundMovSUni := nil;

while F1stMovSUIndx < Count do
begin
F1stMovSUni := TUnit(Item[F1stMovSUIndx]);

if CooperatesWithUnit(F1stMovSUni) then
begin
FoundMovSUni := F1stMovSUni;
Break;
end;

Inc(F1stMovSUIndx);
end;

Result := FoundMovSUni <> nil;
end;
end;

begin
// ****************************************************************************
// TMovingStack.CanMoveTo.
// ****************************************************************************
Disrupt := False; // Initialize var parameter.
// ****************************************************************************
// No units may enter the Qattara Depression.
// ****************************************************************************
if Map.Terrain[MULF.Column, MULF.Row] = teQattaraDepression then
begin
Result := mvQattara;
Exit;
end;
// ****************************************************************************
// Switch the meaning of Left-Control-Click and Left-Click.
// ****************************************************************************
if CheckShift then
begin
Shift := CurrentShiftState;

if MoveCtrlKey then
begin
if Shift * [ssLeft, ssCtrl] = [ssLeft, ssCtrl] then Exclude(Shift, ssLeft)
else if ssLeft in Shift then Include(Shift, ssCtrl);
end;
end;
// ****************************************************************************
// Perform distance calculations which may be needed later in several places.
// HDistance is the Hex distance from PickUpPoint to MULF.
// ADistance is the Air distance from PickUpPoint to MULF (needs AirMaxRange).
// First check if the PickupPoint is on the map.
// ****************************************************************************
if PickUpPoint.OnMap then
begin
if (Game.Phase = pAirRebase) or
(Game.DigressionInProgress and
(Game.CurrentDigression = digOverrun)) then
AirMaxRange := TAirUnit(FirstMovingUnit).RebaseRange(CheckExtended,
DoubleRange)
else
AirMaxRange := AirRangeOfStack; // Minimum range of all units in stack.

// ShowMessageOK('[TMovingStack.CanMoveTo]: A ' +
// 'AirMaxRange = ' + IntToStr(AirMaxRange));

ADistance := AirDistanceFromTo(PickUpPoint, MULF.Hex, AirMaxRange);
HDistance := TGameMapArea.HexDistance(PickUpPoint, MULF.Hex);
end
else
begin // The next 3 lines of code are for the compiler.
AirMaxRange := 255;
ADistance := 0;
HDistance := 0;
end;
// ****************************************************************************
// Begin validation of move.
// ****************************************************************************
MapHex := MapStacks[MULF.Column, MULF.Row]; // Map stack at destination.
FirstMU := FirstMovingUnit;

if MULF.AtSea then
begin
SAStack := SeaAreas[MULF.SeaAreaID].SeaStack;

if FirstMU.Side = sdAxis then
begin
RefC := SeaAreas[MULF.SeaAreaID].AxisBoxZero.X;
RefR := SeaAreas[MULF.SeaAreaID].AxisBoxZero.Y;
end
else
begin
RefC := SeaAreas[MULF.SeaAreaID].AlliedBoxZero.X;
RefR := SeaAreas[MULF.SeaAreaID].AlliedBoxZero.Y;
end;
end
else
begin
SAStack := nil;
RefC := 0; // Not used.
RefR := 0;
end;

Old := PickUpPoint;
SameHex := ExactSameLocation(PickUpPoint, MULF);
Result := mvOK; // Default is that it's an ok move.
// ****************************************************************************
// Check for trying to move to the starting location for the moving stack, which
// is ok most of the time, but may be illegal in cases listed below.
// ****************************************************************************
MoveToSameHexNotOk := (Game.DigressionInProgress and
// ****************************************************************************
// May not relocate or abort to the same hex.
// ****************************************************************************
(Game.CurrentDigression = digRelocate)) or
Game.NavalCombatAbortDigress or
// ****************************************************************************
// May not fly some air phases/subphases to same hex.
// ****************************************************************************
((Game.Phase in [pPortAttack, pStrategicBombardment,
pCarpetBombing, pGroundStrike,
pParadrop]) and
(Game.AirSubPhase in [AspFlyA, AspInterceptA,
AspAntiAirA, AspReturnA])) or
// ****************************************************************************
// Air units can never fly air missions to all sea hexes.
// ****************************************************************************
((Game.Phase in AirPhases) and
MULF.AtSea);
// ****************************************************************************
// If trying to move to the same hex and that is ok, then we are done.
// ****************************************************************************
if SameHex and (not MoveToSameHexNotOk) then Exit; // Note negative.
// ****************************************************************************
// MC is the governed area that geographically owns the destination hex.
// HexHomeC converts subcountries (e.g., Transylvania) to its parent country.
// HexC is the major power that controls the destination hex.
// We may want to know the minor country that controls the hex (HexMinC).
// ****************************************************************************
MC := Map.HexCountry[MULF.Column, MULF.Row];
HexHomeC := Map.HexHomeCountry[MULF.Column, MULF.Row];
HexC := Map.HexControlMajorCountry[MULF.Column, MULF.Row];
HexMinC := Map.HexControlHex[MULF.Hex];
// ****************************************************************************
// HexMP is the major power that controls the country (governed area) that
// geographically owns the destination hex. HexMP does not necessarily = HexC.
// ****************************************************************************
if MC = nil then HexMP := nil
else HexMP := MC.ControllingMajorPower;
// ****************************************************************************
// Check for legal country (in the game).
// ****************************************************************************
if (MC <> nil) and (not (MC.ID in LegalCountries)) then
begin
Result := mvIllegalCountry;
Exit;
end;
// ****************************************************************************
// Check for neutral country trying to move. If MovingNeutral returns True,
// then the Result = mvNeutralMove.
// ****************************************************************************
if (MC <> nil) and (not Game.InSettingUpPhase) and MovingNeutral then Exit;

// ShowMessageOK('[TMovingStack.CanMoveTo]: mvNeutral check point A.');

// ****************************************************************************
// Check for moving into a neutral country.
// ****************************************************************************
if (MC <> nil) and
(not Game.InSettingUpPhase) and
(not MULF.AtSea) and
NeutralHex(MULF.Hex) and
((Map.HexControlMajorCountry[MULF.Column, MULF.Row] = nil) or
(Map.HexControlMajorCountry[MULF.Column, MULF.Row].ID <>
Self.StackControllingMP(False, True))) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: mvNeutral check point B.');

EastPol := MC.ID = EasternPoland.ID;
BalticStat := ((MC.ID = Estonia.ID) and
(Estonia.NeverInWar)) or
((MC.ID = Latvia.ID) and
(Latvia.NeverInWar)) or
((MC.ID = Lithuania.ID) and
(Lithuania.NeverInWar));
// ****************************************************************************
// Move is ok if the USSR is occupying Eastern Poland or the Baltic States.
// ****************************************************************************
if (not ((FirstMU.Country in [USSR.ID, Siberia.ID]) and
EastPol and
(not EasternPolandOccupied) and
(not Poland.Conquered))) and
(not ((FirstMU.Country in [USSR.ID, Siberia.ID]) and
EasternPolandOccupied and
BalticStat and
(not BalticStatesOccupied))) and
// ****************************************************************************
// When OptRules.Internment is active, air units belonging to minor countries
// can fly into neutral minor countries to be interned. This can happen at any
// time that the air unit can fly (e.g., return to base, forced rebase, etc.).
// The following conditionals permit these moves.
// ****************************************************************************
(not (OptRules.Internment and
(FirstMU is TAirUnit) and
(UnitHomeCountryCommonwealth(FirstMU).ClassType = TMinorCountry) and
(MC.HomeCountry.ClassType = TMinorCountry) and
MULF.OnLand and
(Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.ClassType =
TMinorCountry) and
(not Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.Conquered)
and
Map.HexHomeCountry[MULF.Column, MULF.Row].HomeCountry.Neutral)) and
// ****************************************************************************
// Move is ok to enter a neutral (e.g., Vichy France) when returning French air
// and naval units to base, or rebasing French naval units outside of French
// possessions, or moving French units back into French territories.
// ****************************************************************************
(not ((Game.Phase = pVichy) and
(Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchLandAirAxis,
vspMoveFrenchLandAirAllied,
vspMoveFrenchNavalAllied]))) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: mvNeutral check point C.');

Result := mvNeutral;
Exit;
end;
end; // End of checking for neutral country.
// ****************************************************************************
// RAC 17.4: Vichy units may only enter a hex outside Vichy France is it is
// controlled by an enemy major power.
//
// Check for moving Vichy units into hexes controlled by neither Vichy nor a
// major power at war with Vichy.
// ****************************************************************************
if (MC <> nil) and
(not MULF.AtSea) and
(FirstMU.Country = VichyFrance.ID) and
(HexC <> VichyFrance) and
(HexC <> nil) and
(HexC.Relations[VichyFrance.ID] <> crWar) then
begin
Result := mvVichyOutsideVichy;
Exit;
end;
// ++++++++++++++++++++++++++
// Process digressions first.
// ++++++++++++++++++++++++++
// ****************************************************************************
if Game.DigressionInProgress then
begin
case Game.CurrentDigression of
// ****************************************************************************
// Moving units on the map does not occur.
// ****************************************************************************
digNavalInterception, digFixOverstacking, digCollapseVichy: ;
// ****************************************************************************
// Check for relocating units to the nearest legal hex.
// ****************************************************************************
digRelocate:
begin
if NearHexes.Empty then
Result := mvNoRelocateHex
else if not NearHexes.Search(MULF.Column, MULF.Row) then
Result := mvNotClosest
else if (Game.Phase = pVichy) and
(Game.VichySubPhase in [vspMoveFrenchLandAirAxis,
vspMoveFrenchLandAirAllied]) then
Exit
else if FTCFails or RestrictedReinforcement then
Exit
else if MULF.OnLand and EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl; // digRelocate.

// ShowMessageOK('[TMovingStack.CanMoveTo]: digRelocate.');

end;
end;
// ****************************************************************************
// Check for rebasing units due to overrun or return to base digression.
// ****************************************************************************
digOverrun, digReturnToBase:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: digOverrun, digReturnToBase.');

if FTCFails or RestrictedReinforcement then Exit;
// ****************************************************************************
// Check naval group for illegal combintations.
// ****************************************************************************
if (FirstMU is TNavalUnit) and
(InvalidNavalGroup or
InvalidNavalMove) then
Exit;
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] digOverrun, digReturnToBase ' +
// 'FTC failure.');

if CantTravel then Result := mvMinorLimit // digOverrun, digReturnToBase.
else Result := mvForeignCommitment;

Exit;
end;

if ((Game.Phase <> pVichy) or
(not (Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied]))) and
InvalidDestination(Game.CurrentDigression = digOverrun) then
Exit;

if MULF.AtSea then
begin // Moving to a sea area.
UFUnit := FirstMU;

if FirstMU.UnitType = utCarrierAir then
begin
if not MapHex.HasUnit(UFilterCarrierCanLoadPlane) then
Result := mvNoCarrier; // No carrier available in sea area.
end
else if FirstMU is TAirUnit then
Result := mvLandAirInSeaArea // Only carrier air units RTB at sea.
else if (FirstMU is TNavalUnit) and
(not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index,
HR)) then
begin
if FirstMU.UnitType <> utCarrierAir then
Result := mvLandAirInSeaArea
// Only carrier air units RTB at sea.
else if not MapHex.HasUnit(UFilterCarrierCanLoadPlane) then
Result := mvNoCarrier; // No carrier available in sea area.
end;
end
else
// ****************************************************************************
// One possibility is that naval units have a viable return to base hex but in
// order to reach it, they have to pass through a sea area where they can be
// intercepted by enemy units. In that case, they are allowed to enter the sea
// area.
// ****************************************************************************
begin // Moving to a land hex.
if (Game.Phase = pVichy) and
(Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied]) then
begin // Returning French units to base during Vichy declaration.
if NearHexes.Empty then
begin
if Game.VichySubPhase = vspMoveFrenchAtSea then
Result := mvNoRelocateHex
else
Result := mvNoAbortPort;
end
else if not NearHexes.Search(MULF.Column, MULF.Row) then
Result := mvOutOfRange // French returning from sea.
else
begin
(*
if Game.VichySubPhase = vspMoveFrenchAtSea then
MainForm.DebugPanel.Caption :=
'[TMovingStack.CanMoveTo]: Ok to move to ' +
HexName(MULF.Hex);
*)
end;
end
else if EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl; // digOverrun, digReturnToBase.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: digOverrun, ' +
' digReturnToBase EnemyStackOrHex');
*)
end
else
begin
C := TMajorCountry(Countries[FirstMU.ControllingMajorCountry]);

if (HexC = nil) or (HexC.Side <> C.Side) then
begin
Result := mvHexControl; // digOverrun, digReturnToBase.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: digOverrun, ' +
' digReturnToBase Enemy controlled hex.');
*)
end
else if EnemyStack(MapHex) then
Result := mvEnemyUnit; // An enemy unit is in the hex.
end;
end;

if Result = mvOK then
begin // Check if the destination is in the predetermined list.
if (Game.Phase <> pVichy) or
(not (Game.VichySubPhase in [vspMoveFrenchAtSea,
vspMoveFrenchNavalAxis,
vspMoveFrenchNavalAllied])) then
begin
if (Game.CurrentDigression = digOverrun) or
(FirstMU is TNavalUnit) then
begin
if (FirstMU is TNavalUnit) and
(not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index,
HR)) then
Result := mvOutOfRange // Overrun naval units.
else if (FirstMU is TAirUnit) and
(not AirHexList.Search(MULF.RefCol, MULF.RefRow, Index,
AHR)) then
begin
if ADistance > AirMaxRange then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: Air unit, ' +
FirstMU.ViewName +
', in digOverrun. ADistance = ' +
IntToStr(ADistance) +
' is greater than AirMaxRange = ' +
IntToStr(AirMaxRange));
*)
Result := mvOutOfRange; // Air unit; digOverrun.
end
else
begin
Good := FriendlyHex(MULF.Column, MULF.Row);

if Good then
begin
if EnemyStack(MapHex) then Result := mvEnemyUnit
else Result := CanStack(MapHex, False, nil, False, True);
end;
end;
end;
end
else
begin // Air unit returning to base due to abort result/choice.
if ADistance > AirMaxRange then
Result := mvOutOfRange // // Air unit; digReturnToBase.
else
begin
Good := FriendlyHex(MULF.Column, MULF.Row);

if Good then
begin
if EnemyStack(MapHex) then Result := mvEnemyUnit
else Result := CanStack(MapHex, False, nil, False, True);
end;
end;
end;
end;
end;
// ****************************************************************************
// Check if move is within legal stacking limits.
// ****************************************************************************
// if Result = mvOK then Result := CanStack(MapHex);
end; // End of digOverrun, digReturnToBase.

digNavalCombatAbort:
begin
if HasAirAndNaval then
Result := mvAbortAirNaval// Cannot move air & naval together.
else if MULF.OnLand and EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl; // digNavalCombatAbort.

// ShowMessageOK('[TMovingStack.CanMoveTo]: digNavalCombatAbort ');

end
else if FTCFails or RestrictedReinforcement then
Exit
// ****************************************************************************
// Check naval group for illegal combintations.
// ****************************************************************************
else if (FirstMU is TNavalUnit) and
(InvalidNavalGroup or
InvalidNavalMove) then
Exit// Trying to move to an all-sea hex.
else if InvalidDestination then Exit;

if MULF.AtSea then
begin // Moving to a sea area.
UFUnit := FirstMU;
// ****************************************************************************
// One possibility is that naval units do have a viable return to base hex but
// in order to reach it, they have to pass through a sea area where they can be
// intercepted by enemy units. In that case, they are allowed to enter the sea
// area.
// ****************************************************************************
if (not (FirstMU is TNavalUnit)) or
(not NavalHexList.Search(MULF.RefCol, MULF.RefRow, Index, HR)) then
begin
if FirstMU.UnitType <> utCarrierAir then
Result := mvLandAirInSeaArea
// Only carrier air units RTB at sea.
else if not MapHex.HasUnit(UFilterCarrierCanLoadPlane) then
Result := mvNoCarrier; // No carrier available in sea area.
end;
end
else
begin // Moving to a land hex.
if EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl; // digNavalCombatAbort.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: digNavalCombatAbort ' +
' EnemyStackOrHex');
*)
end
else
begin
C := TMajorCountry(Countries[FirstMU.ControllingMajorCountry]);

if (HexC = nil) or (HexC.Side <> C.Side) then
begin
Result := mvHexControl; // digNavalCombatAbort.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: digNavalCombatAbort ' +
' Enemy controlled hex.');
*)
end
else if EnemyStack(MapHex) then
Result := mvEnemyUnit; // An enemy unit is in the hex.
end;
end;
end; // End of digNavalCombatAbort.
end; // End of case Game.CurrenntDigression.

Exit; // Exit after every digression.
end
else
// ****************************************************************************
// +++++++++++++++++++++++++++++
// Process by phase of the game.
// +++++++++++++++++++++++++++++
// ****************************************************************************
begin
case Game.Phase of
// ****************************************************************************
// In many phases, units can not be 'moved'. Those are listed first since they
// should never be encountered by this routine.
// ****************************************************************************
pLending, pInitiative, pWeather, pChooseAction, pIgnoreNotional,
pEmergencyHQSupply, pHQReorganization, pTRSSupply, pEndOfAction,
pEntry, pUSEntry, pProdPlanningPrelim, pStayAtSeaA, pStayAtSeaD,
pUseOil, pFinalReorganization, pBreakDown, pProdPlanningFinal,
pSearchAndSeizure, pScrapDestroyed, pNavalRepair, pProduction,
pReform, pIntelligence, pUkraine, pConquest, pMutualPeace,
pLiberation, pSurrender, pMinorSupport, pFactoryDestruction,
pVictory, pGameEnd, pQuit, pNone:
Exit;

pSetup:
begin
if RestrictedReinforcement then Exit;

if MULF.OnLand and EnemyStackOrHex(MapHex) and
(not SettingUpPartisans) then
Result := mvHexControl
else
CheckUsingSetupTray;
end;

pReinforcement:
begin
if Game.Phase_Reinforce.CurrentSubPhase[Game.LocalDeciderMP] =
RspPlaceUnits then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pReinforcement ' +
// 'Result at A = ' + IntToStr(Ord(Result)));

if MULF.OnLand and EnemyStackOrHex(MapHex) then
Result := mvHexControl
else if RestrictedReinforcement then Exit;
// ****************************************************************************
// Check for placing reinforcement units on the map from the setup tray.
// ****************************************************************************
MapHex := MapStacks[MULF.Column, MULF.Row]; // Destination MapStack.
Result := CanSetup(MULF.Column, MULF.Row); // CanMoveTo.
(*
if not (Result in [mvOK, mvWarlordHex]) then
ShowMessageOK('[TMovingStack.CanMoveTo]: pReinforcement ' +
'Result at B = ' + IntToStr(Ord(Result)));
*)
if Result = mvOK then
Result := CanStack(MapHex); // MapStack stacking limits for setup phases.
(*
if not (Result in [mvOK, mvWarlordHex]) then
ShowMessageOK('[TMovingStack.CanMoveTo]: pReinforcement ' +
'Result at C = ' + IntToStr(Ord(Result)));
*)
if (Result = mvStackingAir) and
(not MULF.AtSea) and
(UnitCount(UFilterCarrierAirUnit) = 1) then
begin
UFUnit := FindUnit(UFilterCarrierAirUnit);
UFPhase := Game.Phase;
UFSubPhase := aspNone;

if MapHex.HasUnit(UFilterCarrierCanLoadPlane) then
Result := mvOK;
end;
end;
end; // End of pReinforcement.

pDeclareWar:
begin
CheckUsingSetupTray;
end;

pPortAttack:
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if RestrictedReinforcement or UnableToFlyToHex then Exit;
// ****************************************************************************
// Check for attempting to port attack at night - which is forbidden.
// ****************************************************************************
if HasUnit(UFilterNightMission) then
begin
Result := mvNightPortAttack; // No night missions for port attacks.
Exit;
end;
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
AspCAP:
begin
UFSide := Game.PhasingSide;
Good := MapHex.HasUnit(UFilterPortAttackTargetCooperates);
end;

AspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

if Good then Good := MapHex.HasUnit(UFilterPortAttackTargetEnemy);
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end;

if not Good then Result := mvNoTarget;
end; // End of pPortAttack.

pNavalAir: // CanMoveTo.
begin
ComputeUnits; // Count the # of limited activities needed to move stack.

if RestrictedReinforcement or InvalidNavalAirNavalMission then Exit;

if (MULF.OnLand and
PickUpPoint.OnLand) or
(MULF.AtSea and
PickUpPoint.AtSea and
(MULF.SeaAreaID <> PickUpPoint.SeaAreaID)) then
begin
Result := mvNavalAirNotSeaArea;
Exit;
end;

if InvalidDestination(False) then Exit;
// ****************************************************************************
// Check for available air missions for all air units in the moving stack. Even
// fighters count during the Naval Air phase.
// ****************************************************************************
for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.AirMissions <> aUnlimited) and
(AirUnits[MPI] > MPow.CurrLimits.AirMissions) then
begin
Result := mvAirMissions;
Break;
end;
end;
end; // End of pNavalAir.

pNavalMovement: // CanMoveTo.
begin
if FTCFails or
InvalidNavalGroup or
RestrictedReinforcement or
InvalidNavalMove then // Trying to move to an all-sea hex.
Exit;

// ShowMessageOK('[TMovingStack.CanMoveTo] pNavalMovement A.');

ComputeUnits; // Count the # of limited activities needed to move stack.

// ShowMessageOK('[TMovingStack.CanMoveTo] pNavalMovement B.');

if MULF.OnLand and EnemyStackOrHex(MapHex) then Result := mvHexControl
// ****************************************************************************
// Moving into a sea area in order to fight through, does not count as a naval
// move.
// ****************************************************************************
else if (not SameHex) and (not Game.NavalInterceptionDigression) then
begin // Check for exceeding naval move limits.
for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];
MajC := UnitControllingMajorCountry(FirstMU);

if MajC = VichyFrance then MPow := Game.VichyFranceController
else MPow := MajC;
// ****************************************************************************
// This routine is for neutral major powers only.
// ****************************************************************************
if MPow.LegalCountry and
(MPow.CurrLimits.NavalMoves <> aUnlimited) and // CanMoveTo.
MajC.NeutralNavalMoves and // 1 move/unit.
(NavalUnitCounts[MPI] > MPow.CurrLimits.NavalMoves) then
begin
Result := mvNavalMoves; // Insufficient naval moves for neutral.
Break;
end;
end;
end;

// ShowMessageOK('[TMovingStack.CanMoveTo] pNavalMovement C.');

end;

pNavalCombatA, pNavalCombatD: // CanMoveTo.
begin
if Game.NCSubPhase in [NCspNavalAirSupportA, NCspNavalAirSupportD] then
begin
if InvalidNavalAirSupport or InvalidDestination(False) then Exit;
end;
end;

pStrategicBombardment: // CanMoveTo.
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

// ShowMessageOK('[TMovingStack.CanMoveTo]: pStrategicBombardment A.');

if UnableToFlyToHex then Exit;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pStrategicBombardment B.');

// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;
// ****************************************************************************
// Set UFSide to the enemy side except during a CAP subphase.
// ****************************************************************************
case Game.AirSubPhase of
aspCAP:
begin
UFSide := Game.PhasingSide;
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if DoesntCooperatesWithHex(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if Good then
Good := (FoundMovSUni2 = nil) and
((Map.FactoryList.FactoryTargetCount[MULF.Column,
MULF.Row] > 0) or
(Map.OilTargetCount[MULF.Column, MULF.Row] > 0) or
(Map.SavedBuildTargetCount[MULF.Column, MULF.Row] > 0) or
(Map.SavedOilTargetCount[MULF.Column, MULF.Row] > 0) or
MapHex.HasUnit(UFilterSynthOilUnitNotLost));
end;

aspFlyA:
begin
UFSide := Game.NonPhasingSide;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pStrategicBombardment ' +
// 'AspFlyA C.');
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pStrategicBombardment ' +
// 'AspFlyA D.');

if Good then
Good := EnemyHex(MULF.Column, MULF.Row) and
((Map.FactoryList.FactoryTargetCount[MULF.Column,
MULF.Row] > 0) or
(Map.OilTargetCount[MULF.Column, MULF.Row] > 0) or
(Map.SavedBuildTargetCount[MULF.Column, MULF.Row] > 0) or
(Map.SavedOilTargetCount[MULF.Column, MULF.Row] > 0) or
MapHex.HasUnit(UFilterSynthOilUnitNotLost));
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

aspReturnA, aspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pStrategicBombardment.

pCarpetBombing:
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit;
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
AspCAP:
begin
UFSide := Game.PhasingSide;
Good := MapHex.HasUnit(UFilterCarpetBombingTargetCooperates);
end;

AspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;
// ****************************************************************************
// It is possible to carpetbomb a unit on the other side even if you are not at
// war with its controlling major power, if it is in a hex controlled by a
// country with which you are at war.
// ****************************************************************************
UFSide := Game.NonPhasingSide; // Has to be reset.

if Good then
Good := (EnemyHex(MULF.Column, MULF.Row) and
MapHex.HasUnit(UFilterCarpetBombingTargetSide)) or
MapHex.HasUnit(UFilterCarpetBombingTargetEnemy);
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pCarpetBombing.

pGroundStrike:
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit; // Only air units are checked.
// ****************************************************************************
// Set Good which indicates whether the unit can ground strike depending on the
// target units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
aspCAP:
begin
UFSide := Game.PhasingSide;
Good := LandCombatHexes.Search(MULF.Hex, Index, CR) and
FriendlyStack(MapHex) and
MapHex.HasUnit(UFilterGroundStrikeTargetCooperates);
// ****************************************************************************
// Check to see if UTarget is surprised. If it is, it cannot fly CAP.
// ****************************************************************************
// (not UTarget.SurprisedBy(UAttacker)) then
end;

aspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;
// ****************************************************************************
// It is possible to ground strike a unit on the other side even if you are not
// at war with its controlling major power, if it is in a hex controlled by a
// country with which you are at war.
// ****************************************************************************
UFSide := Game.NonPhasingSide; // Has to be reset.

if Good then
Good := (EnemyHex(MULF.Column, MULF.Row) and
MapHex.HasUnit(UFilterGroundStrikeTargetSide)) or
MapHex.HasUnit(UFilterGroundStrikeTargetEnemy);
(*
if EnemyHex(MULF.Column, MULF.Row) and
(not MapHex.HasUnit(UFilterGroundStrikeTargetSide)) then
begin
ShowMessageOK('[TMovingStack.CanMoveTo]: pGroundStrike ' +
'AspFlyA UFilterGroundStrikeTargetSide ' +
' failed.');
end
else if not Good then
ShowMessageOK('[TMovingStack.CanMoveTo]: pGroundStrike ' +
'AspFlyA UFilterGroundStrikeTargetEnemy ' +
' failed.');
*)
// ****************************************************************************
// This final check is for artillery units that are bombarding.
// ****************************************************************************
if Good and (not HasAir) then
begin
UFSide := Game.NonPhasingSide; // Has to be reset.
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pGroundStrike ' +
'AspFlyA HDistance = ' + IntToStr(HDistance));
*)
if (HDistance > 1) or
(EnemyHex(MULF.Column, MULF.Row) and
(not MapHex.HasUnit(UFilterGroundStrikeTargetSide))) or
((not EnemyHex(MULF.Column, MULF.Row)) and
(not MapHex.HasUnit(UFilterGroundStrikeTargetEnemy))) then
begin
Result := mvBombardAdjacent;
end
else if Map.HexWeather[MULF.Column, MULF.Row] in
NoAirFactorsWeather then
Result := mvBombardWeather
else if Map.HexsideTerrain[PickUpPoint.Column, PickUpPoint.Row,
THexArea.ConnectingHexsideRange(PickUpPoint.Hex,
MULF.Hex), hsAlpine] then
Result := mvBombardAlpine;
end;
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pGroundStrike.
// ****************************************************************************
// Check rail movement.
// ****************************************************************************
pRailMovement: // TMovingStack.CanMoveTo.
begin
if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement then
Exit;
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] pRailMovement ' +
// 'FTC failure.');

if CantTravel then Result := mvMinorLimit // pRailMovement.
else Result := mvForeignCommitment;

Exit;
end;

ComputeUnits; // Count the # of limited activities needed to move stack.
RR := Map.RailHexes.Search(MULF.Column, MULF.Row);

if EnemyStackOrHex(MapHex) then Result := mvHexControl
else if (RR = nil) or (not RR.RInclude) then Result := mvNoRailMove
else
begin
if (FirstMU.UnitType = utFactory) and
((Map.City[MULF.Column, MULF.Row] = cyNone) or
(Map.HexHomeCountryCommonwealth[MULF.Column, MULF.Row] <>
UnitControllingMajorCountry(FirstMU))) then
Result := mvNoHomeCity
// ****************************************************************************
// There is a limit of 2 non-red factories and 3 total factories in a hex.
// ****************************************************************************
else if (FirstMU.UnitType = utFactory) and
Map.NoRoomForFactory(MULF.Column, MULF.Row) then
Result := mvCityCapacityFactory
// ****************************************************************************
// HQ units and Railway guns can move to any rail hex. The hex does not have to
// be a station.
// ****************************************************************************
else if (not (FirstMU.UnitType in HeadquartersSet + [utRailwayGun]))
and
(not Map.IsStationHex(MULF.Column, MULF.Row)) then
Result := mvNoStation
else
begin
if (FirstMU.RailMoveCost(RR.RHexCount) >
UnitControllingMajorCountry(FirstMU).CurrLimits.RailMoves) or
((FirstMU.Country = CommunistChina.ID) and
(FirstMU.RailMoveCost(RR.RHexCount) >
CCLimitsCurr.RailMoves)) then
Result := mvRailMoves
else
Result := CanStack(MapHex); // Rail movement.
end;
end;
end; // End of pRailMovement.
// ****************************************************************************
// Check land movement (including advance after combat).
// ****************************************************************************
pLandMovement:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] pLandMovement A.');

if MULF.AtSea then Result := mvNoLandMove
else if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement then
Exit
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
else if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] pLandMovement ' +
// 'FTC failure after call to CanMoveMinor.');

if CantTravel then Result := mvMinorLimit // pLandMovement.
else Result := mvForeignCommitment;

Exit;
end
else
begin
ComputeUnits; // Count the # of activities needed to move the stack.

if not CanMove(MULF.Column, MULF.Row, Disrupt) then
begin // Move fails. Determine why for error message.
UFSide := Game.PhasingSide;

if EnemyStack(MapHex) or
(EnemyHex(MULF.Column, MULF.Row) and
MapHex.HasUnit(UFilterNotSide)) then
begin
if ((HDistance = 1) and
(FirstMU.HexsideMP[PickUpPoint.Hex, MULF.Hex] <>
ProhibitedTerrain)) then
Result := mvNoOverrun
else
Result := mvOverrunAdjacent;
end
else if InEnemyZOC and (not FirstMove) then
Result := mvEnemyZOC
else if MapHex.HasUnit(UFilterNotSide) and
(not EnemyHex(MULF.Column, MULF.Row)) then
Result := mvNeutralNotAtWar
else if MajPower(FirstMU).HexViolatesPact(MULF.Hex) then
Result := mvPact
else
begin
Result := CanStack(MapHex); // Land movement.

if Result = mvOK then Result := mvMP; // Land movement.
end;
end
else
begin // Legal move, check against action limits.
for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves)
and UnitsNotMoved then
begin
Result := mvLandMoves;
Break;
end;
end;
// ****************************************************************************
// Perform another check of all the units in Self to see how many Communist
// Chinese units are in the stack.
// ****************************************************************************
CCCount := 0;

for CCIndex := 0 to Self.Count - 1 do
begin
CCUnit := Self[CCIndex];

if CCUnit.Country = CommunistChina.ID then
Inc(CCCount);
end;
// ****************************************************************************
// If Self has a CC unit, then check available CCLimitsCurr.LandMoves.
// ****************************************************************************
if (CCCount > 0) and (CCLimitsCurr.LandMoves <> aUnlimited) and
(CCCount > CCLimitsCurr.LandMoves) then
Result := mvLandMoves;
end;

if Result = mvOK then
begin // Determine HR. Check for stacking limits.
LandHexList.Search(MULF.RefCol, MULF.RefRow, Index, LHR);
Result := CanStack(MapHex, False, nil, False, False, Side);

if (Result = mvOK) and Disrupt then
Result := mvDisruptedExt;
end;
end;
end; // End of pLandMovement.

pAirTransport:
begin
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement or
UnableToFlyToHex then
Exit;
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo] pAirTransport ' +
// 'FTC failure.');

if CantTravel then Result := mvMinorLimit // pAirTransport.
else Result := mvForeignCommitment;

Exit;
end;

ComputeUnits; // Count the # of limited activities needed to move stack.
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
aspCAP:
begin
UFSide := Game.PhasingSide;
Good := EnemyHex(MULF.Column, MULF.Row);
end;

aspFlyA:
begin
// ****************************************************************************
// First check for a transport in the moving stack that is carrying half of a
// unit in the LargeAirTransportSet, while a second transport, which is not in
// the moving stack is carrying the other half. If this condition is detected,
// then automatically add the second transport to the moving stack.
// ****************************************************************************
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);
// ****************************************************************************
// Check if Cargo is being carried by another ATR (Second, which is not in the
// moving stack).
// ****************************************************************************
if NotSupplyLoaded(F1stMovSUni2) then
begin
if Second <> nil then
begin
PickingUpMultipleUnits := False;
AddToMovingStack(Second);
end;

if First <> nil then
begin
PickingUpMultipleUnits := False;
AddToMovingStack(First);
end;
end;

Inc(F1stMovSUIndx2);
end; // End of while.

UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves) then
begin // Insufficient land moves available.
Result := mvLandMoves;
Break;
end;
end;

if Result = mvOK then
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NotSupplyLoaded(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end; // End of while.

if FoundMovSUni2 <> nil then Result := mvNotSupplyLoaded
else
begin
Res := CanStack(MapHex); // Air transport.

if Res = mvOK then
begin
if Good then Good := FriendlyHex(MULF.Column, MULF.Row);
// ****************************************************************************
// It is a friendly hex. Check if this is an attempt to fly to a hex that has a
// unit which can be loaded onto an air transport. For example, the ATR can not
// fly to an empty hex unless it is already carrying a unit it loaded before it
// took to the air.
// ****************************************************************************
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NotLoaded(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if Good and
(not AirTransportReturn) and
(FoundMovSUni2 <> nil) then
begin
UFPhase := Game.Phase;
UFSubPhase := Game.AirSubPhase;
Good := OtherStackFilter(MapHex, UFilterLoadable);
end;
end // End of Res = mvOK.
else Result := Res;
end; // End of FoundMovSUni2 = nil.
end; // End of Result = mvOK.
end; // End of AspFlyA.

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
// ****************************************************************************
// First check for a transport in the moving stack that is carrying half of a
// unit in the LargeAirTransportSet, while a second transport, which is not in
// the moving stack is carrying the other half. If this condition is detected,
// then automatically add the second transport to the moving stack.
// ****************************************************************************
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);
// ****************************************************************************
// Check if Cargo is being carried by another ATR (Second, which is not in the
// moving stack).
// ****************************************************************************
if NotSupplyLoaded(F1stMovSUni2) then
begin
if Second <> nil then
begin
PickingUpMultipleUnits := False;
AddToMovingStack(Second);
end;

if First <> nil then
begin
PickingUpMultipleUnits := False;
AddToMovingStack(First);
end;
end;

Inc(F1stMovSUIndx2);
end; // End of while.

CantReturnAD;
Exit;
end;
end; // End of Case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pAirTransport.
// ****************************************************************************
// Check unloading land units from a sea area into a friendly land hex.
// ****************************************************************************
pUnloadLandUnits:
begin
if FTCFails or RestrictedReinforcement then Exit;

ComputeUnits; // Count the # of limited activities needed to move stack.

if MULF.OnLand and EnemyStackOrHex(MapHex) then Result := mvHexControl
else Result := CanStack(MapHex); // Unloading land units.

if Result = mvOK then
begin
if not FirstMU.CanUnloadIntoHex(MULF.Hex) then Result := mvNoDebark
else
begin
for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves) then
begin
Result := mvLandMoves;
Break;
end;
end;

if (Result = mvOK) and AnyWillBeDisrupted then
Result := mvDisruptedExt;
end;
end;
end;
// ****************************************************************************
// Check invasion.
// ****************************************************************************
pInvasion:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion A.');

ComputeUnits; // Count the # of limited activities needed to move stack.
Result := CanStack(MapHex, True); // Invasion.

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion B.');

if Result = mvOK then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion C.');

if not FirstMU.CanInvadeIntoHex(MULF.Hex) then Result := mvNoInvasion
else
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion D.');

for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if MPow.LegalCountry and
(MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves) then
begin
Result := mvLandMoves;
Break;
end;
end;
end;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion E.');

if Result = mvOK then
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion F.');

F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NoAttack(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 <> nil then Result := mvLandAttacks;
end;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion G.');

if (Result = mvOK) and AnyWillBeDisrupted then
Result := mvDisruptedExt;
end;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pInvasion H.');

end;

pParadrop:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pParadrop A.');

ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit;
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

// ShowMessageOK('[TMovingStack.CanMoveTo]: pParadrop B.');

case Game.AirSubPhase of
aspCAP:
begin
UFSide := Game.PhasingSide;
LandCombatHexes.Search(MULF.Hex, Index, CR);
Good := ((CR = nil) or
(not CR.CombatHexUnits.SurprisedStack(MapHex,
Game.NonPhasingSide)))
and
FriendlyHex(MULF.Column, MULF.Row);

if Good then
begin
if MapHex.Empty then
begin
// ****************************************************************************
// If the hex is empty, then all units in Self need to cooperate with the
// notional unit (i.e., whoever controls the hex).
// ****************************************************************************
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if DoesntCooperatesWithHex(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

Good := FoundMovSUni2 = nil;
end
else
// ****************************************************************************
// If the hex contains units, Self has to cooperate with all the friendly units
// in the hex.
// ****************************************************************************
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < MapHex.Count do
begin
F1stMovSUni2 := TUnit(MapHex.Item[F1stMovSUIndx2]);

if not DoesCooperate(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

Good := FoundMovSUni2 = nil;
end;
end; // End of Good so far.
end; // End of AspCAP.

aspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

if Map.WeatherTerrain[MULF.Column, MULF.Row] in [teSea,
teLake] then
Result := mvNoTarget
else
Result := CanStack(MapHex, True); // Paradrop.

if Result = mvOK then
begin
CR := LandCombatHexes.FindCombat(MULF.Hex);

for MPI := Low(TMajorCountries) to High(TMajorCountries) do
begin
MPow := MajorPowers[MPI];

if not MPow.LegalCountry then Continue;

UFCountry := MPow.ID;

if (MPow.CurrLimits.LandMoves <> aUnlimited) and
(LandUnits[MPI] > MPow.CurrLimits.LandMoves) then
Result := mvLandMoves
else if (LandUnits[MPI] > 0) and
(MPow.CurrLimits.LandAttacks = 0) and
((CR = nil) or
(not (CR.CombatHexUnits.HasUnit
(UFilterControllingMajorCountry)))) then
Result := mvLandAttacks;

if Result <> mvOK then Break;
end; // End of for each major power.
// ****************************************************************************
// Perform another check of all the units in Self to see if a Communist Chinese
// unit is part of the attack. If so, then see if a Communist Chinese unit is
// already in CR.CombatHexUnits.
// ****************************************************************************
CCCount := 0;

for CCIndex := 0 to Self.Count - 1 do
begin
CCUnit := Self[CCIndex];
// CC unit in Self.
if CCUnit.Country = CommunistChina.ID then Inc(CCCount);
end;
// ****************************************************************************
// If Self has a CC unit, then a check has to be made for both
// CCLimitsCurr.LandMoves and CCLimitsCurr.LandAttacks.
// ****************************************************************************
if CCCount > 0 then
begin
if (CCLimitsCurr.LandMoves <> aUnlimited) and
(CCCount > CCLimitsCurr.LandMoves) then
Result := mvLandMoves
else
begin // Enough land moves available.
if CCLimitsCurr.LandAttacks = 0 then
begin // Check existing attack.
if (CR = nil) then Result := mvLandAttacks
else
begin
CCFound := False;

for CCIndex := 0 to CR.CombatHexUnits.Count - 1 do
begin
CCUnit := CR.CombatHexUnits[CCIndex];

if CCUnit.Country = CommunistChina.ID then
begin
CCFound := True;
Break; // CC unit already in the attack.
end;
end;

if not CCFound then Result := mvLandAttacks;
end;
end; // End of CCLimitsCurr.LandAttacks = 0.
end; // End of enough land moves available.
end; // End of CCCount > 0.

if Result = mvOK then
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NotLoaded(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 <> nil then Result := mvNotLoaded
else
begin
F1stMovSUIndx2 := 0;
U := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if IsAirLandingUnit(F1stMovSUni2) then
begin
U := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;
// ****************************************************************************
// If there is no air landing unit in the stack, just check for an enemy hex.
// ****************************************************************************
if U = nil then Good := EnemyHex(MULF.Column, MULF.Row)
else
// ****************************************************************************
// If an air landing unit has been found (U <> nil), then check for an
// accompanying paratroop unit in the moving stack or in the hex.
// ****************************************************************************
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;
// ****************************************************************************
// Moving stack check for accompanying paratroop unit.
// ****************************************************************************
while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if IsParatroopUnit(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;
// ****************************************************************************
// If there is paradrop unit in the stack, check for an enemy hex.
// ****************************************************************************
if FoundMovSUni2 <> nil then
Good := EnemyHex(MULF.Column, MULF.Row)
else
// ****************************************************************************
// Check for an accompanying paratroop unit in the hex.
// ****************************************************************************
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < MapHex.Count do
begin
F1stMovSUni2 := TUnit(MapHex.Item[F1stMovSUIndx2]);

if IsParatroopUnit(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 = nil then
Result := mvNoExistingPara
// ****************************************************************************
// Friendly paratroop unit found in hex.
// ****************************************************************************
else Good := EnemyHex(MULF.Column, MULF.Row);
end;
end;
end;
end;
end;
end; // End AspFlyA.

AspInterceptA:
begin

// ShowMessageOK('[TMovingStack.CanMoveTo]: pParadrop AspInterceptA.');

if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of Case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pParadrop.
// ****************************************************************************
// Check land combat declaration.
// ****************************************************************************
pLandCombatDeclaration: // CanMoveTo.
begin
ComputeUnits; // Count the # of limited activities needed to move stack.

if not CanMove(MULF.Column, MULF.Row, Disrupt) then
Result := mvAttack // No.
else
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if NoAttack(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

if FoundMovSUni2 <> nil then
Result := mvLandAttacks // No.
else if LandCombatHexes.Search(MULF.Hex, Index, CR) and
((not CooperatesNotFlying(Self)) or
(not CooperatesNotFlying(CR.CombatHexUnits))) then
Result := mvAttackNoCoop; // No.
end;
end;
// ****************************************************************************
// Check shore bombardment.
// ****************************************************************************
pShoreBombardmentA, pShoreBombardmentD:
begin
F1stMovSUIndx4 := 0;
FoundMovSUni4 := nil;

while F1stMovSUIndx4 < Count do
begin
F1stMovSUni4 := TNavalUnit(Item[F1stMovSUIndx4]);

if NoSB(F1stMovSUni4) then
begin
FoundMovSUni4 := F1stMovSUni4;
Break;
end;

Inc(F1stMovSUIndx4);
end;

if FoundMovSUni4 <> nil then
Result := mvNoShoreBombardment
else
begin
F1stMovSUIndx4 := 0;
FoundMovSUni4 := nil;

while F1stMovSUIndx4 < Count do
begin
F1stMovSUni4 := TNavalUnit(Item[F1stMovSUIndx4]);

if NoSBFactors(F1stMovSUni4) then
begin
FoundMovSUni4 := F1stMovSUni4;
Break;
end;

Inc(F1stMovSUIndx4);
end;

if FoundMovSUni4 <> nil then
Result := mvNoShoreBombardmentFactors;
end;
end;
// ****************************************************************************
// Check attacking HQ support.
// ****************************************************************************
pHQSupportA:
begin
TMapArea.ConnectingHexsideRange(PickUpPoint.Hex, MULF.Hex, HS);

if (not LandCombatHexes.Search(MULF.Hex, Index, CR)) or
(HS <> FirstMU.AttackingHexside) then
Result := mvHQSupportA
else if CR.HQA <> nil then
Result := mvHasHQSupportA;
end;
// ****************************************************************************
// Check defending HQ support.
// ****************************************************************************
pHQSupportD: // CanMoveTo.
begin
HQSameHex := ExactSameLocation(PickUpPoint, MULF);
HQAdjacent := THexArea.AdjacentHexes(PickUpPoint.Column,
PickUpPoint.Row, MULF.Column, MULF.Row);

if (not LandCombatHexes.Search(SmallPoint(MULF.Column, MULF.Row),
Index, CR)) or ((not HQSameHex) and (not HQAdjacent)) or
(LandCombatHexes.Search(SmallPoint(PickUpPoint.Column,
PickUpPoint.Row), Index, CR2) and HQAdjacent) then
Result := mvHQSupportD
else if (not HQSameHex) and
(not FirstMU.CooperatesWithLocation(MULF.Hex)) then
Result := mvHQSupportDNoCoop
else if (CR <> nil) and (CR.HQD <> nil) then
Result := mvHasHQSupportD;
end;

pGroundSupport:
begin
ComputeUnits; // Count the # of limited activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit;
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
UFUnit := FirstMU;

case Game.AirSubPhase of
aspCAP:
begin
Good := LandCombatHexes.Search(MULF.Hex, Index, CR) and
(not CR.CombatHexUnits.SurprisedStack(MapHex,
Game.NonPhasingSide))
and
FriendlyHex(MULF.Column, MULF.Row);

if Good then
begin
// ****************************************************************************
// If the hex is empty, then all units in Self need to cooperate with the
// notional unit (i.e., whoever controls the hex). Otherwise, Self has to
// cooperate with all the friendly units in the hex.
// ****************************************************************************
if MapHex.Empty then
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < Count do
begin
F1stMovSUni2 := TUnit(Item[F1stMovSUIndx2]);

if DoesntCooperatesWithHex(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

Good := FoundMovSUni2 = nil;
end
else
// ****************************************************************************
// If the hex contains units, Self has to cooperate with all the friendly units
// in the hex.
// ****************************************************************************
begin
F1stMovSUIndx2 := 0;
FoundMovSUni2 := nil;

while F1stMovSUIndx2 < MapHex.Count do
begin
F1stMovSUni2 := TUnit(MapHex.Item[F1stMovSUIndx2]);

if not DoesCooperate(F1stMovSUni2) then
begin
FoundMovSUni2 := F1stMovSUni2;
Break;
end;

Inc(F1stMovSUIndx2);
end;

Good := FoundMovSUni2 = nil;
end;
end;
end; // End of AspCAP.

aspFlyA:
begin
UFSide := Game.NonPhasingSide;

if NoCooperationWithTarget then Exit; // CanMoveTo has been set.

Good := LandCombatHexes.Search(MULF.Hex, Index, CR);

if Good then
begin
if not HasAir then
begin
if HDistance > 1 then Result := mvBombardAdjacent
else if Map.HexWeather[MULF.Column, MULF.Row] in
NoAirFactorsWeather then
Result := mvBombardWeather;
end;
end;
end;

aspFlyD:
begin
UFSide := Game.NonPhasingSide;

if NoCooperationWithTarget then Exit; // CanMoveTo has been set.

Good := LandCombatHexes.Search(MULF.Hex, Index, CR);

if Good then
begin
if CR.CombatHexUnits.SurprisedStack(MapHex,
Game.NonPhasingSide) then
Result := mvAirSurprisedGroundSupport
else if not HasAir then
begin
if HDistance > 1 then Result := mvBombardAdjacent
else if Map.HexWeather[MULF.Column, MULF.Row] in
NoAirFactorsWeather then
Result := mvBombardWeather;
end;
end;
end; // End of AspFlyD.

AspInterceptA:
begin
Good := LandCombatHexes.Search(MULF.Hex, Index, CR);

if Good then
begin
if CantInterceptA then Exit;
end;
end;

AspInterceptD:
begin
Good := LandCombatHexes.Search(MULF.Hex, Index, CR);

if Good then
begin
if CantInterceptD then Exit;
end;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of Case Game.AirSubPhase

if not Good then Result := mvNoTarget;
end; // End of pGroundSupport.

pLandCombatResolution:
begin
case Game.Phase_LandCombatResolution.CurrentSubPhase of
// ****************************************************************************
// The code should never get here for LCRspHexControl since that is processed
// using a digression.
// ****************************************************************************
LCRspLandCombatSelection, LCRspChooseCombatType,
LCRspLandCombatResolution,
LCRspAssignLosses, LCRspHexControl: ;

LCRspRetreats:
begin
if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement then
Exit;
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin
if CantTravel then Result := mvMinorLimit // LCRspRetreats.
else Result := mvForeignCommitment;

Exit;
end;

if not RetreatHexes.Search(MULF.Column, MULF.Row) then
Result := mvNoRetreat
else
Result := CanStack(MapHex); // LCRspRetreats.

if (Result = mvOK) and FTCFails then Exit;
end;

LCRspAdvanceAfterCombat:
begin
if MULF.AtSea then Result := mvNoLandMove
else if FTCFails or
IllegalPartisanMove or
IllegalWarlordMove or
RestrictedReinforcement then
Exit
// ****************************************************************************
// Moving a minor unit to sea or outside its home country may not be permitted.
// ****************************************************************************
else if not CanMoveMinor(MULF.Column, MULF.Row, CantTravel) then
begin
if CantTravel then Result := mvMinorLimit // LCRspAdvanceAfterCombat.
else Result := mvForeignCommitment;

Exit;
end
else
begin
if not CanMove(MULF.Column, MULF.Row, Disrupt) then
begin // Move fails. Determine why for error message.
UFSide := Game.PhasingSide;

if (Game.CombatResult.LRetreat <> lcrBreakthrough) and
(HDistance > 1) then
Result := mvNoBreakthrough
else if EnemyStack(MapHex) or
(EnemyHex(MULF.Column, MULF.Row) and
MapHex.HasUnit(UFilterNotSide)) then
Result := mvNoOverrun
else if MapHex.HasUnit(UFilterNotSide) and
(not EnemyHex(MULF.Column, MULF.Row)) then
Result := mvNeutralNotAtWar
else
begin
Result := CanStack(MapHex); // Advance after combat.

if Result = mvOK then
Result := mvMP; // Advance after combat.
end;
end;

if Result = mvOK then
begin // Determine LHR. Check for stacking limits.
LandHexList.Search(MULF.RefCol, MULF.RefRow, Index, LHR);
Result := CanStack(MapHex, False, nil, False, False, Side);

if (Result = mvOK) and Disrupt then Result := mvDisruptedExt;
end;
end;
end; // End of LCRspAdvanceAfterCombat.
end; // End of case Phase_LandCombatResolution.CurrentSubPhase.
end; // End of pLandCombatResolution.
// ****************************************************************************
// Check air rebase movement.
// ****************************************************************************
pAirRebase:
begin // Both FTCFails and RestrictedReinforcement set CanMoveTo.
if FTCFails or RestrictedReinforcement then Exit;

C := TMajorCountry(Countries[FirstMU.ControllingMajorCountry]);
ComputeUnits; // Count the # of limited activities needed to move stack.
// ****************************************************************************
// First check for rebasing from a naval transport to a land hex.
// ****************************************************************************
if FirstMU.WasAboardTransport and
(not (FirstMU.WasAboardWhom.UnitType in CarrierSet)) then
begin
if not AirHexList.Search(MULF.Column, MULF.Row, Index, AHR) then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
' Destination hex ' + HexName(MULF.Hex) +
' was not in AirHexList, whose count = ' +
IntToStr(AirHexList.Count));
*)
Result := mvOutOfRange; // Air rebase, unload from transport.
end
else
begin
Result := CanStack(MapHex); // Air rebase, unload from transport.

if (Result = mvOK) and
(not FirstMU.CanUnloadIntoHex(MULF.Hex)) then
Result := mvNoUnload;
end;
end
else
// ****************************************************************************
// Rebasing land based air from one land hex to another, or carrier air units.
// ****************************************************************************
begin
if MULF.AtSea then
begin
if FirstMU.UnitType <> utCarrierAir then
Result := mvLandAirInSeaArea
else if not AirHexList.Search(RefC, RefR, Index, AHR) then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
UFUnit.ViewName +
' can''t rebase to ' +
HexName(SmallPoint(RefC, RefR)) +
' because it is not in AirHexList.');
*)
Result := mvNoCarrier;
end
end
// ****************************************************************************
// Check for sufficient air missions or Rebase For Free.
// ****************************************************************************
else if (C.CurrLimits.AirMissions = 0) and
((not TAirUnit(FirstMU).CanAirRebaseForFree) or
// ****************************************************************************
// Rebasing for free requires not changing the unit's hex location.
// ****************************************************************************
(not SameHex)) then
Result := mvOnlyInSameHex
else
begin // The unit is moving to a land hex.
// ****************************************************************************
// RebaseRange sets CheckExtended and DoubleRange. CanMoveTo.
// ****************************************************************************
RebaseRangeMS := TAirUnit(FirstMU).RebaseRange(CheckExtended,
DoubleRange);
(*
if (FirstMU.Country = Finland.ID) and (HexHomeC = Sweden) then
begin
DistToHex := Map.AirDistance(pAirRebase, FirstMU, PickUpPoint,
MULF.Hex,
UnitHomeCountryCommonwealth(FirstMU),
RebaseRangeMS);

ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
' DistToHex = ' + IntToStr(DistToHex));
end;
*)
// ****************************************************************************
// MC is the governed area that geographically owns the destination hex, and
// HexC is the major power that controls the destination hex.
// We may want to know the minor country that controls the hex (HexMinC).
// ****************************************************************************
if EnemyStack(MapHex) then Result := mvEnemyUnit
// ****************************************************************************
// When OptRules.Internment is active, air units belonging to minor countries
// can fly into neutral minor countries to be interned. The following
// conditionals permit these moves.
// ****************************************************************************
else if OptRules.Internment and
(UnitHomeCountryCommonwealth(FirstMU).ClassType =
TMinorCountry) and
(HexHomeC.ClassType = TMinorCountry) and
(not HexHomeC.Conquered) and
HexHomeC.Neutral then
begin
if THexArea.HexDistance(PickUpPoint.Hex, MULF.Hex, MapColumns,
True) > RebaseRangeMS then
CanMoveTo := mvOutOfRange // Air rebase for internment.
else
Result := mvOK; // Internment possible.
end
else if not AirHexList.Search(MULF.RefCol, MULF.RefRow, Index,
AHR) then
begin
if not MapHex.Cooperates(Self) then Result := mvStackingNoCoop
else Result := mvOutOfRange; // Air rebase to & from a land hex.
end
else if (HexC = nil) or (HexC.Side <> C.Side) then
Result := mvHexControl;
end; // End of unit rebasing to a land hex.

if Result = mvOK then
begin
if FirstMU.UnitType = utCarrierAir then
begin
UFUnit := FirstMU;
UFPhase := pAirRebase;
UFSubPhase := AspNone;
// ****************************************************************************
// Carrier air units.
// ****************************************************************************
if MULF.AtSea then
begin
if SameHex then
begin
UFSection := MULF.Section;
// ****************************************************************************
// See if there is a carrier that the unit can load onto in the MULF Section -
// other than its current parent carrier.
// ****************************************************************************
if not MapHex.HasUnit(UFilterCarrierCanLoadPlaneInSectionExcept)
then
Result := mvNoCarrier;
end
else
begin // Destination at sea, different hex.
// ****************************************************************************
// RebaseRange sets CheckExtended and DoubleRange. CanMoveTo.
// ****************************************************************************
RebaseRangeMS := TAirUnit(FirstMU).RebaseRange(CheckExtended,
DoubleRange);
UFRange := RebaseRangeMS -
Map.AirDistance(Game.Phase, FirstMU,
PickUpPoint, MULF.Hex,
UnitHomeCountryCommonwealth(FirstMU),
RebaseRangeMS, False, True);
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
UFUnit.ViewName +
' has RebaseRange = ' + IntToStr(RebaseRangeMS) +
', has UFRange = ' + IntToStr(UFRange) +
', and is trying to rebase into ' + HexName(MULF.Hex));
*)
// ****************************************************************************
// See if there is a carrier that the unit can load onto within range - other
// than its current parent carrier.
// ****************************************************************************
if not SAStack.HasUnit(UFilterCarrierCanLoadPlaneInRangeExcept)
// if not MapHex.HasUnit(UFilterCarrierCanLoadPlaneInRangeExcept)
then
begin
(*
ShowMessageOK('[TMovingStack.CanMoveTo]: pAirRebase ' +
UFUnit.ViewName +
' was unable to rebase into ' + HexName(MULF.Hex));
*)
Result := mvNoCarrier;
end;
end;
end // End of destination being AtSea.
// ****************************************************************************
// Carrier air unit whose destination is not at sea.
// ****************************************************************************
else if not MapHex.HasUnit(UFilterCanLoadOntoExcept) then
Result := CanStack(MapHex); // Carrier air unit.
end
else Result := CanStack(MapHex); // Air rebase.
end;
end;
end; // End of pAirRebase.

pAirReorganization:
begin
ComputeUnits; // Count the # of activities needed to move stack.
HasAir := HasUnit(UFilterAirUnit); // Air unit, not artillery unit.

if UnableToFlyToHex then Exit; // Checks within range.
// ****************************************************************************
// Set Good which indicates whether the unit can fly depending on the target
// units in the hex.
// ****************************************************************************
Good := True;
UFUnit := FirstMU;

case Game.AirSubPhase of
AspCAP:
begin
UFSide := Game.PhasingSide;
Good := MapHex.HasUnit(UFilterEnemyDisruptedNonHQUnit);
end;

AspFlyA:
begin
UFSide := Game.NonPhasingSide;
// CanMoveTo has been set.
if InsufficientAirMissions or NoCooperationWithTarget then Exit;

if HasUnit(UFilterFlyingBoat) then
Res := CanStack(MapHex)// Air supply.
else
Res := mvOK;

if (Res = mvOK) and Good then
Good :=
MapHex.HasUnit(UFilterFriendlyCooperatingDisruptedNonHQUnit)
else
Result := Res;
end;

AspInterceptA:
begin
if CantInterceptA then Exit;
end;

AspInterceptD:
begin
if CantInterceptD then Exit;
end;

AspReturnA, AspReturnD:
begin
CantReturnAD;
Exit;
end;
end; // End of Case Game.AirSubPhase.

if not Good then Result := mvNoTarget;
end; // End of pAirReorganization.

pPartisan: CheckUsingSetupTray;

pReturnToBaseA, pReturnToBaseD: // CanMoveTo.
begin
if HasAirAndNaval then
begin
Result := mvAbortAirNaval; // Cannot move air & naval together.
Exit;
end
else if EnemyStackOrHex(MapHex) then Result := mvHexControl
else if FTCFails or
((FirstMU is TNavalUnit) and
(InvalidNavalGroup or
InvalidNavalMove)) or
// Trying to move to an all-sea hex.
RestrictedReinforcement then
Exit
else if InvalidDestination(False) then Exit;
end;

pVichy:
begin
case Game.VichySubPhase of
vspControl: ;

vspMoveNonFrenchLandAir:
begin
if MULF.OnLand and EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl;

// ShowMessageOK('[TMovingStack.CanMoveTo]: vspMoveNonFrenchLandAir ');

end
else if RestrictedReinforcement then Exit;
end;

vspMoveNonFrenchNaval:
begin
if MULF.OnLand and EnemyStackOrHex(MapHex) then
begin
Result := mvHexControl;

// ShowMessageOK('[TMovingStack.CanMoveTo]: vspMoveNonFrenchNaval ');

end
else if RestrictedReinforcement then Exit;
end;

vspMoveFrenchAtSea:
begin
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if (not MULF.OnLand) or
((HexC <> France) and
(HexC <> VichyFrance)) then
Result := mvFranceOnly
// ****************************************************************************
// When returning French units at sea to base during Vichy declaration, only
// hexes in the NearestHexes list are legal. This might not be called.
// ****************************************************************************
else if NearHexes.Empty then
Result := mvNoRelocateHex
else if not NearHexes.Search(MULF.Column, MULF.Row) then
Result := mvOutOfRange; // French returning from sea.
end;

vspMoveFrenchLandAirAxis:
begin
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if MULF.OnLand and (HexC <> France) and (HexC <> VichyFrance) then
Result := mvFranceOnly;
end;

vspMoveFrenchNavalAxis:
begin
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if MULF.OnLand and (HexC <> France) and (HexC <> VichyFrance) then
Result := mvFranceOnly;
end;

vspDestroyFrench: ;

vspMoveFrenchLandAirAllied:
begin
if RestrictedReinforcement then Exit;
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if MULF.OnLand and (HexC <> France) and (HexC <> VichyFrance) then
Result := mvFranceOnly;
end;

vspMoveFrenchNavalAllied:
begin
if RestrictedReinforcement then Exit;
// ****************************************************************************
// There is an additional restriction during some Vichy subphases: the units
// must be moved to France or Vichy France.
// ****************************************************************************
if MULF.OnLand and (HexC <> France) and (HexC <> VichyFrance) then
Result := mvFranceOnly;
end;

vspProduction: ;

vspSetup: CheckUsingSetupTray;

vspMoveFrenchVichy: ;

vspUnitControl: ;

vspConquerFrance: ;
end; // End of case Game.VichySubPhase.
end;
end; // End of case Game.Phase.

// ShowMessageOK('[TMovingStack.CanMoveTo] Z.');

end;
// ****************************************************************************
// Finally, check if the move violates a Neutrality Pact. This takes
// restriction applies across all unit types and all phases of the game.
// ****************************************************************************
if (Result in [mvOK, mvDisruptedExt]) and HexViolatesPact(MULF.Hex) then
Result := mvPact;
end; // End of CanMoveTo.

warspite1

Looks bloody complicated to me


_____________________________

England expects that every man will do his duty. Horatio Nelson October 1805



(in reply to Shannon V. OKeets)
Post #: 63
RE: I believe this game will never happen - 6/12/2013 10:22:58 PM   
bo

 

Posts: 4176
Joined: 5/1/2009
Status: offline
quote:

ORIGINAL: Greyshaft


quote:

ORIGINAL: bo
Hey Greyshaft I think Extraneous was calling you an aborigine
Bo


While I may (or may not) agree with you Bo, we need to consider whether questions of race are appropriate in this Forum... Extraneous can call me a dork, a dumbo, an a$$hole, an ignoramous or label me with any of thousands of other vague descriptions without fear of contradiction, but tagging me as a specific racial group and implying that that race has lesser qualities than another race constitutes racial vilification in Australia and is against the law.

Perhaps we can avoid the whole nasty legal mess by just agreeing that I'm a Dumbo and moving on ?


Legal mess, racial vilification I am slightly confused Greyshaft are you referring to what I said or what Extraneous said.


Thank you.

Bo

< Message edited by bo -- 6/13/2013 2:43:15 AM >

(in reply to Greyshaft)
Post #: 64
RE: I believe this game will never happen - 6/13/2013 12:20:33 AM   
CrusssDaddy

 

Posts: 330
Joined: 8/6/2004
Status: offline
Where's the code that makes rain look like a plague of locusts? If you post it, perhaps some kind fellow could amend it to look not-retarded.

(in reply to bo)
Post #: 65
RE: I believe this game will never happen - 6/13/2013 12:27:24 AM   
Shannon V. OKeets

 

Posts: 22095
Joined: 5/19/2005
From: Honolulu, Hawaii
Status: offline

quote:

ORIGINAL: CrusssDaddy

Where's the code that makes rain look like a plague of locusts? If you post it, perhaps some kind fellow could amend it to look not-retarded.


It's a graphics overlay. You can change the graphics data file if you like - owners of the game will be able to do that.

_____________________________

Steve

Perfection is an elusive goal.

(in reply to CrusssDaddy)
Post #: 66
RE: I believe this game will never happen - 6/13/2013 12:52:06 AM   
CrusssDaddy

 

Posts: 330
Joined: 8/6/2004
Status: offline

quote:

ORIGINAL: Shannon V. OKeets


quote:

ORIGINAL: CrusssDaddy

Where's the code that makes rain look like a plague of locusts? If you post it, perhaps some kind fellow could amend it to look not-retarded.


It's a graphics overlay. You can change the graphics data file if you like - owners of the game will be able to do that.


I feel kinda like Michael Bluth looking curiously into Gob's bag in the fridge that is labeled DEAD PIGEON DO NOT EAT:

"I don't know what else I expected."

(in reply to Shannon V. OKeets)
Post #: 67
RE: I believe this game will never happen - 6/13/2013 1:35:03 AM   
Extraneous

 

Posts: 1810
Joined: 6/14/2008
Status: offline
quote:

ORIGINAL: Shannon V. OKeets

You keep assuming you know more about a topic because you've read something about it. People who work in the field have several orders of magnitude more knowledge than someone who has merely read up on a subject.

Here is some "simple programming" for you to critique. This is an excerpt of ~4000 lines of code from a module of 11,000 lines. There are ~250 modules in MWIF, totaling over 400,000 lines of code.

The following code (which references hundreds of code segments in other modules) is to determine if a stack of units that the player has picked up can move to the hex over which the player has moved the cursor. This executes in real time as the player moves the mouse over the map. For each hex the cursor passes over, a message is shown on the Main form telling the player whether the move is legal - and if not, why not. The cursor itself is also updated to either a target icon (ok move) or an X (move illegal).

By the way, the above paragraph IS the program specification for this function. It might also include a reference to the Rules as Written document for determining whether a stack of units can move to a hex. And RAW is perfectly clear in all particulars.



I DID NOT READ IT ANYWHERE.

Prior to moving into programming I was a Computer Operator for American Airlines.

I became a Documentation Analyst for a small company when American Airlines instituted a no nepotism policy (my father also worked there).

At this small company I worked my way up to programming where I was offered a job with Informatics (which is now Computer Associates International).

Informatics address was 555 Madison Ave. New York, New York (the IBM offices were 2 floors above ours).

As a computer consultant I worked for Informatics assigned to the Sate of New York Welfare Managment System.

There is more to my resume but this should satisfy a reasonable person.


Steve your experence in computer consulting is what? How large a company was it?

Wasn't CWiF originaly written in C or C++? How many times have you changed/upgraded the language since you took over the project?

Only 4,000 lines of code? I wrote a program in COBOL that was over 3,000 lines of code in the 70's.


I have just given you an example of the system standards I worked under for over 20 years SIMPLIFIED for the non-computer professional.

Your example of code doesn't matter since code jockeys are a dime a dozen. I am talking about system design not code.


quote:

ORIGINAL: bo

Hey Greyshaft I think Extraneous was calling you an aborigine
Bo


Mr. William Bowen (from your Matrix profile):
For your enlightenment Australia is a continent. Saying that "a continent is surrounded by heathens" precludes the population of said continent from being heathens. This would include the aboriginal tribes of Australia.

To put it in easier terms just for you:

I insulted everyone in Asia except all the people in Australia and gave an example.



_____________________________

University of Science Music and Culture (USMC) class of 71 and 72 ~ Extraneous (AKA Mziln)

(in reply to Centuur)
Post #: 68
RE: I believe this game will never happen - 6/13/2013 1:40:52 AM   
CrusssDaddy

 

Posts: 330
Joined: 8/6/2004
Status: offline
Extraneous, yours is not a formidable intellect but you are a prolific poster, so you have that going for you.

(in reply to Extraneous)
Post #: 69
RE: I believe this game will never happen - 6/13/2013 1:49:11 AM   
Extraneous

 

Posts: 1810
Joined: 6/14/2008
Status: offline

quote:

ORIGINAL: CrusssDaddy

Extraneous, yours is not a formidable intellect but you are a prolific poster, so you have that going for you.



Your just jealous because they hate me more than you.

_____________________________

University of Science Music and Culture (USMC) class of 71 and 72 ~ Extraneous (AKA Mziln)

(in reply to CrusssDaddy)
Post #: 70
RE: I believe this game will never happen - 6/13/2013 2:14:14 AM   
CrusssDaddy

 

Posts: 330
Joined: 8/6/2004
Status: offline
quote:

ORIGINAL: Extraneous


quote:

ORIGINAL: CrusssDaddy

Extraneous, yours is not a formidable intellect but you are a prolific poster, so you have that going for you.



Your just jealous because they hate me more than you.


*You're*

And you're right!

(in reply to Extraneous)
Post #: 71
RE: I believe this game will never happen - 6/13/2013 2:36:17 AM   
bo

 

Posts: 4176
Joined: 5/1/2009
Status: offline

quote:

ORIGINAL: Extraneous


quote:

ORIGINAL: CrusssDaddy

Extraneous, yours is not a formidable intellect but you are a prolific poster, so you have that going for you.



Your just jealous because they hate me more than you.



How did you know I need easier terms you been talking to my wife?

Australia is a continent [BS] I went to Catholic grade school and the nuns told me it was an island and they were never wrong, because if we told the nun she was wrong they beat our hands with a ruler, I still can't spell Mississipi right and that means ten cracks on the hand. Ouch!

You just cannot help yourself can you, you been talking down to everyone here but crussdaddy and I can understand that because you cannot insult him now you are talking down to Steve and that is not allowed here

I guess you ignored my post about becoming a beta tester now I understand why, it is beneath you to do that menial old nasty testing of MWIF so you are just going to sit on the posts and tell everyone about your wonderful resume which you have not finished telling us about because what you told us should satisfy a reasonable person. Well guess what I am not a reasonable person and I am a doubting Thomas so that means I want to see from proof of your greatness ooops sorry your Majesty.

Where did you get my full name from, oh I know you got it from Edward Snowden in Hong Kong.

Bo


(in reply to Extraneous)
Post #: 72
RE: I believe this game will never happen - 6/13/2013 2:41:12 AM   
bo

 

Posts: 4176
Joined: 5/1/2009
Status: offline

quote:

ORIGINAL: CrusssDaddy

quote:

ORIGINAL: Extraneous


quote:

ORIGINAL: CrusssDaddy

Extraneous, yours is not a formidable intellect but you are a prolific poster, so you have that going for you.



Your just jealous because they hate me more than you.


*You're*

And you're right!


I don't hate you cruss you know that, I understand you perfectly Actually that scares me a little to say I understand you. You will be the first person I play in net-play shortly if you would like that

Bo

(in reply to CrusssDaddy)
Post #: 73
RE: I believe this game will never happen - 6/13/2013 3:39:06 AM   
Shannon V. OKeets

 

Posts: 22095
Joined: 5/19/2005
From: Honolulu, Hawaii
Status: offline

quote:

ORIGINAL: CrusssDaddy


quote:

ORIGINAL: Shannon V. OKeets


quote:

ORIGINAL: CrusssDaddy

Where's the code that makes rain look like a plague of locusts? If you post it, perhaps some kind fellow could amend it to look not-retarded.


It's a graphics overlay. You can change the graphics data file if you like - owners of the game will be able to do that.


I feel kinda like Michael Bluth looking curiously into Gob's bag in the fridge that is labeled DEAD PIGEON DO NOT EAT:

"I don't know what else I expected."


Okay. How about this: "The graphics for the weather images are pictures. You can change the picture."

_____________________________

Steve

Perfection is an elusive goal.

(in reply to CrusssDaddy)
Post #: 74
RE: I believe this game will never happen - 6/13/2013 3:49:02 AM   
paulderynck


Posts: 8201
Joined: 3/24/2007
From: Canada
Status: offline

quote:

ORIGINAL: Extraneous

Prior to moving into programming I was a Computer Operator for American Airlines.

Ah yes, computer operators were the guys who slept through night shift when they got tired of watching the LEDs blink.

quote:

ORIGINAL: Extraneous
I became a Documentation Analyst for a small company when American Airlines instituted a no nepotism policy (my father also worked there).


IIRC Documentation Analysts were the guys who made sure every second ply on the toilet paper had the manufacturer's trade mark on it.

quote:

ORIGINAL: Extraneous
At this small company I worked my way up to programming where I was offered a job with Informatics (which is now Computer Associates International).

Informatics address was 555 Madison Ave. New York, New York (the IBM offices were 2 floors above ours).


What a coincidence! 555 is the starting phone number for all the numbers in all the movies and TV shows! You must know some really famous people.

quote:

ORIGINAL: Extraneous
As a computer consultant I worked for Informatics assigned to the Sate of New York Welfare Managment System.

Clearly Informatics is a specialty that doesn't require the ability to spell.

quote:

ORIGINAL: Extraneous
There is more to my resume but this should satisfy a reasonable person.


We were totally satisfied before you posted your resume. The big question is: How would you know anything about reason?


_____________________________

Paul

(in reply to Extraneous)
Post #: 75
RE: I believe this game will never happen - 6/13/2013 4:06:39 AM   
Shannon V. OKeets

 

Posts: 22095
Joined: 5/19/2005
From: Honolulu, Hawaii
Status: offline

quote:

ORIGINAL: Extraneous

quote:

ORIGINAL: Shannon V. OKeets

You keep assuming you know more about a topic because you've read something about it. People who work in the field have several orders of magnitude more knowledge than someone who has merely read up on a subject.

Here is some "simple programming" for you to critique. This is an excerpt of ~4000 lines of code from a module of 11,000 lines. There are ~250 modules in MWIF, totaling over 400,000 lines of code.

The following code (which references hundreds of code segments in other modules) is to determine if a stack of units that the player has picked up can move to the hex over which the player has moved the cursor. This executes in real time as the player moves the mouse over the map. For each hex the cursor passes over, a message is shown on the Main form telling the player whether the move is legal - and if not, why not. The cursor itself is also updated to either a target icon (ok move) or an X (move illegal).

By the way, the above paragraph IS the program specification for this function. It might also include a reference to the Rules as Written document for determining whether a stack of units can move to a hex. And RAW is perfectly clear in all particulars.



I DID NOT READ IT ANYWHERE.

Prior to moving into programming I was a Computer Operator for American Airlines.

I became a Documentation Analyst for a small company when American Airlines instituted a no nepotism policy (my father also worked there).

At this small company I worked my way up to programming where I was offered a job with Informatics (which is now Computer Associates International).

Informatics address was 555 Madison Ave. New York, New York (the IBM offices were 2 floors above ours).

As a computer consultant I worked for Informatics assigned to the Sate of New York Welfare Managment System.

There is more to my resume but this should satisfy a reasonable person.


Steve your experence in computer consulting is what? How large a company was it?

Wasn't CWiF originaly written in C or C++? How many times have you changed/upgraded the language since you took over the project?

Only 4,000 lines of code? I wrote a program in COBOL that was over 3,000 lines of code in the 70's.


I have just given you an example of the system standards I worked under for over 20 years SIMPLIFIED for the non-computer professional.

Your example of code doesn't matter since code jockeys are a dime a dozen. I am talking about system design not code.


quote:

ORIGINAL: bo

Hey Greyshaft I think Extraneous was calling you an aborigine
Bo


Mr. William Bowen (from your Matrix profile):
For your enlightenment Australia is a continent. Saying that "a continent is surrounded by heathens" precludes the population of said continent from being heathens. This would include the aboriginal tribes of Australia.

To put it in easier terms just for you:

I insulted everyone in Asia except all the people in Australia and gave an example.



I've worked for many computer companies; they varied in size from a half dozen programmers up to thousands of programmers. Code jockeys?

CWIF was in Delphi (an object oriented Pascal) as is MWIF.

The sample I posted was 4000 lines. MWIF is 400,000+ lines of code.

I read/recorded COBOL texts for Recording for the Blind when I lived in Philadelphia. While it is not one of the six programming languages in which I have written over 100,000 lines of code, I did acquire a familiarity with its programming style: compared to the other languages which I have used, COBOL requires an enormous number of lines of code to perform the simplest of programming tasks. New programs are not written in COBOL, although there are still many people performing maintenance on COBOL programs - most of which were written in the 1970's for IBM mainframes. Similarly, many people are maintaining programs written in IBM Assembler for those same computers.

By systems design, you mean what? Database? User interface? Processing input files into output files? Diagrams of system components with logic flow? MWIF has all of that, although I chose to use simple comma-separated-values files instead of a formal database language. I've written code for a dozen or so database languages and they weren't really an appropriate solution for a game's data storage. The hundreds of forms in MWIF are for a more complicated program design than any user interface I've see for a commercial product. I've also created dozens of logic flow diagrams for MWIF. To do that I work with a white board, flip chart paper (it's large enough to hold large diagrams), double size paper, and ultimately CorelDraw for final versions.

Design without implementation has marginal value. I learned that from my father, a civil engineer who had to make plant layout drawings done by architects a reality for a large chemical company. I saw it again at Boeing when product designs had to be manufactured. In my opinion, integration of design with implementation is the only way to make a successful product. Having one person (or group) create a product design and then pass it along to another person/group to transform the design into a product either results in numerous exchanges between the two groups to reach consensus or the last person/group in the process just does what they think is best - regardless of what the design originally said should be done.

As a recent case in point, we are having the architect who helped redesign our kitchen/bath also act as the project manager for the work. She knew that going in, so her design decisions were made with a full understanding of what would actually have to be done when the walls and floors are removed and new everything installed.

Integration is difficult for large projects, but quite doable when the people involved commit to working closely together to achieve a common goal. The disasters occur when one group assumes their responsibility stops at a fixed point in the development process - leaving the next group to figure out how to resolve any problems that crop up later.



_____________________________

Steve

Perfection is an elusive goal.

(in reply to Extraneous)
Post #: 76
RE: I believe this game will never happen - 6/13/2013 5:02:08 AM   
Greyshaft


Posts: 2252
Joined: 10/27/2003
From: Sydney, Australia
Status: offline

quote:

ORIGINAL: bo

quote:

ORIGINAL: Greyshaft


quote:

ORIGINAL: bo
Hey Greyshaft I think Extraneous was calling you an aborigine
Bo


While I may (or may not) agree with you Bo, we need to consider whether questions of race are appropriate in this Forum... Extraneous can call me a dork, a dumbo, an a$$hole, an ignoramous or label me with any of thousands of other vague descriptions without fear of contradiction, but tagging me as a specific racial group and implying that that race has lesser qualities than another race constitutes racial vilification in Australia and is against the law.

Perhaps we can avoid the whole nasty legal mess by just agreeing that I'm a Dumbo and moving on ?


Legal mess, racial vilification I am slightly confused Greyshaft are you referring to what I said or what Extraneous said.

Thank you.

Bo


Bo,
Extraneous was being a dork but he didn't mention a racial group.
On the other hand you used the word 'aborigine' which does refer to a racial group in Australia. I'm sure no offence was intended to anyone but I think this conversation is teetering out of control and giving Extraneous more attention than his post deserves. I just want to ensure we all stay on the right side of the Matrix posting guidelines.


_____________________________

/Greyshaft

(in reply to bo)
Post #: 77
RE: I believe this game will never happen - 6/13/2013 5:49:15 AM   
warspite1


Posts: 41353
Joined: 2/2/2008
From: England
Status: offline

quote:

ORIGINAL: Shannon V. OKeets


quote:

ORIGINAL: CrusssDaddy


quote:

ORIGINAL: Shannon V. OKeets


quote:

ORIGINAL: CrusssDaddy

Where's the code that makes rain look like a plague of locusts? If you post it, perhaps some kind fellow could amend it to look not-retarded.


It's a graphics overlay. You can change the graphics data file if you like - owners of the game will be able to do that.


I feel kinda like Michael Bluth looking curiously into Gob's bag in the fridge that is labeled DEAD PIGEON DO NOT EAT:

"I don't know what else I expected."


Okay. How about this: "The graphics for the weather images are pictures. You can change the picture."
warspite1




_____________________________

England expects that every man will do his duty. Horatio Nelson October 1805



(in reply to Shannon V. OKeets)
Post #: 78
RE: I believe this game will never happen - 6/13/2013 5:56:17 AM   
warspite1


Posts: 41353
Joined: 2/2/2008
From: England
Status: offline
quote:

ORIGINAL: Extraneous


quote:

ORIGINAL: CrusssDaddy

Extraneous, yours is not a formidable intellect but you are a prolific poster, so you have that going for you.



Your just jealous because they hate me more than you.
warspite1

No one hates you Extraneous - are you a Millwall fan by the way? - You have been a useful contributor to the project. Its just your posting manner grates from time to time

For that matter, I suspect no one hates CrusssDaddy. He's just a bit like bleach on the skin or a whinny little child - an irritant that you could do without .


_____________________________

England expects that every man will do his duty. Horatio Nelson October 1805



(in reply to Extraneous)
Post #: 79
RE: I believe this game will never happen - 6/13/2013 4:05:46 PM   
bo

 

Posts: 4176
Joined: 5/1/2009
Status: offline

quote:

ORIGINAL: Greyshaft


quote:

ORIGINAL: bo

quote:

ORIGINAL: Greyshaft


quote:

ORIGINAL: bo
Hey Greyshaft I think Extraneous was calling you an aborigine
Bo


While I may (or may not) agree with you Bo, we need to consider whether questions of race are appropriate in this Forum... Extraneous can call me a dork, a dumbo, an a$$hole, an ignoramous or label me with any of thousands of other vague descriptions without fear of contradiction, but tagging me as a specific racial group and implying that that race has lesser qualities than another race constitutes racial vilification in Australia and is against the law.

Perhaps we can avoid the whole nasty legal mess by just agreeing that I'm a Dumbo and moving on ?


Legal mess, racial vilification I am slightly confused Greyshaft are you referring to what I said or what Extraneous said.

Thank you.

Bo


Bo,
Extraneous was being a dork but he didn't mention a racial group.
On the other hand you used the word 'aborigine' which does refer to a racial group in Australia. I'm sure no offence was intended to anyone but I think this conversation is teetering out of control and giving Extraneous more attention than his post deserves. I just want to ensure we all stay on the right side of the Matrix posting guidelines.


quote:


Thank you.

Bo




Greyshaft I apologize to you if you thought I made a racial statement, my comment was not racial as I would never do that on the posts or anywhere else. That is why I used the laughing face. I thought he was insulting you and Australia that's all. I misunderstood his comment. But one thing I did not misunderstand is his arrogance of talking down to all the posters here including Steve.

Bo

(in reply to Greyshaft)
Post #: 80
RE: I believe this game will never happen - 6/13/2013 10:10:12 PM   
Greyshaft


Posts: 2252
Joined: 10/27/2003
From: Sydney, Australia
Status: offline
Bo,
I didn't feel insulted by you or the Ex at all. I was just pointing out that using names of racial groups during a slanging match (no matter how light-hearted) brings us into dangerous territory. Lets stick to dork and dumbo etc

_____________________________

/Greyshaft

(in reply to bo)
Post #: 81
RE: I believe this game will never happen - 6/13/2013 10:13:21 PM   
Extraneous

 

Posts: 1810
Joined: 6/14/2008
Status: offline
quote:

ORIGINAL: warspite1

No one hates you Extraneous - are you a Millwall fan by the way? - You have been a useful contributor to the project. Its just your posting manner grates from time to time

For that matter, I suspect no one hates CrusssDaddy. He's just a bit like bleach on the skin or a whinny little child - an irritant that you could do without .



I like Schalke 04 for football and Australia for rugby.

But for real excitement give me Irish hurling (this is the Irish national sport and has nothing to do with drinking).

American sports are over rated (millionaires being paid to play kid games).


quote:

ORIGINAL: paulderynck

1) Ah yes, computer operators were the guys who slept through night shift when they got tired of watching the LEDs blink.

2) IIRC Documentation Analysts were the guys who made sure every second ply on the toilet paper had the manufacturer's trade mark on it.

3) What a coincidence! 555 is the starting phone number for all the numbers in all the movies and TV shows! You must know some really famous people.

4) Clearly Informatics is a specialty that doesn't require the ability to spell.

5) We were totally satisfied before you posted your resume. The big question is: How would you know anything about reason?




Mr. Paul Derynck

1) Do you know what a mainframe computer is? How about an IBM-360/50 or IBM-370/168? Have you ever heard of UNIVAC (the company or the machine)?

2) Do you know what a flowchart is? How about a system flowchart? You obviously don't know what a Documentation Analyst does.

3) Yes I have met several have you?

4) Since it passes Microsoft Word spell check enlighten us how you think "Informatics" should be spelled?

5) Oh that's not the whole resume.


Have you ever had a job or are you a professional student?


quote:

ORIGINAL: bo

How did you know I need easier terms you been talking to my wife?

Australia is a continent [BS] I went to Catholic grade school and the nuns told me it was an island and they were never wrong, because if we told the nun she was wrong they beat our hands with a ruler, I still can't spell Mississipi right and that means ten cracks on the hand. Ouch!

You just cannot help yourself can you, you been talking down to everyone here but crussdaddy and I can understand that because you cannot insult him now you are talking down to Steve and that is not allowed here

I guess you ignored my post about becoming a beta tester now I understand why, it is beneath you to do that menial old nasty testing of MWIF so you are just going to sit on the posts and tell everyone about your wonderful resume which you have not finished telling us about because what you told us should satisfy a reasonable person. Well guess what I am not a reasonable person and I am a doubting Thomas so that means I want to see from proof of your greatness ooops sorry your Majesty.

Where did you get my full name from, oh I know you got it from Edward Snowden in Hong Kong.

Bo



Mr. William Bowen (from your Matrix profile): Look it up Australia is considered a continent.

How is your wife Bill? Did you finally talk to her?

I don't talk down to crussdaddy because it would do no good. Talking down to you on the other hand is required so you can understand.

If you are part of the Beta test team you should know why I quit or you can ask. If you're not part of the Beta test team tough.


quote:

ORIGINAL: Shannon V. OKeets

I've worked for many computer companies; they varied in size from a half dozen programmers up to thousands of programmers. Code jockeys?

CWIF was in Delphi (an object oriented Pascal) as is MWIF.

The sample I posted was 4000 lines. MWIF is 400,000+ lines of code.

I read/recorded COBOL texts for Recording for the Blind when I lived in Philadelphia. While it is not one of the six programming languages in which I have written over 100,000 lines of code, I did acquire a familiarity with its programming style: compared to the other languages which I have used, COBOL requires an enormous number of lines of code to perform the simplest of programming tasks. New programs are not written in COBOL, although there are still many people performing maintenance on COBOL programs - most of which were written in the 1970's for IBM mainframes. Similarly, many people are maintaining programs written in IBM Assembler for those same computers.

By systems design, you mean what? Database? User interface? Processing input files into output files? Diagrams of system components with logic flow? MWIF has all of that, although I chose to use simple comma-separated-values files instead of a formal database language. I've written code for a dozen or so database languages and they weren't really an appropriate solution for a game's data storage. The hundreds of forms in MWIF are for a more complicated program design than any user interface I've see for a commercial product. I've also created dozens of logic flow diagrams for MWIF. To do that I work with a white board, flip chart paper (it's large enough to hold large diagrams), double size paper, and ultimately CorelDraw for final versions.

Design without implementation has marginal value. I learned that from my father, a civil engineer who had to make plant layout drawings done by architects a reality for a large chemical company. I saw it again at Boeing when product designs had to be manufactured. In my opinion, integration of design with implementation is the only way to make a successful product. Having one person (or group) create a product design and then pass it along to another person/group to transform the design into a product either results in numerous exchanges between the two groups to reach consensus or the last person/group in the process just does what they think is best - regardless of what the design originally said should be done.

As a recent case in point, we are having the architect who helped redesign our kitchen/bath also act as the project manager for the work. She knew that going in, so her design decisions were made with a full understanding of what would actually have to be done when the walls and floors are removed and new everything installed.

Integration is difficult for large projects, but quite doable when the people involved commit to working closely together to achieve a common goal. The disasters occur when one group assumes their responsibility stops at a fixed point in the development process - leaving the next group to figure out how to resolve any problems that crop up later.



You only know 6 computer languages?

I know 2 scientific computer languages, 3 business computer languages, 3 job control computer languages, and 4 forth generation computer languages.

System design is the process of defining the architecture, components, modules, interfaces, and data for a system to satisfy specified requirements.

Implementation without design is chaos.



_____________________________

University of Science Music and Culture (USMC) class of 71 and 72 ~ Extraneous (AKA Mziln)

(in reply to bo)
Post #: 82
RE: I believe this game will never happen - 6/13/2013 10:50:53 PM   
bo

 

Posts: 4176
Joined: 5/1/2009
Status: offline
I would really like to know why you quit the beta team Extraneous, I mean really pretty please. And please talk down to me so I truly understand why you quit because it is very important to all of us or at least me. And tough, I am a beta tester but you knew that.

I just went to Google earth and checked again and it looks like to me that Australia is surrounded by water so IMHO it is downgraded from a continent to an island status. Big island to be sure. I notice the Snowden comment went right over your head. If you want me to explain it to you I will gladly do so but then I would have to talk down to you so you would understand.

Your comment to Steve was uncalled for please leave him out of this please.

This is my last post to you as Mr. nice guy, from now on it is Extraneous hunting season

Bo

(in reply to Shannon V. OKeets)
Post #: 83
RE: I believe this game will never happen - 6/14/2013 2:17:51 AM   
Greyshaft


Posts: 2252
Joined: 10/27/2003
From: Sydney, Australia
Status: offline
Geographically Australia is a continent. Since it is completely surrounded by water is it also technically an island.
Its another of the useless facts that I learned when I was in school (in Australia)
I don't think it matters to MWiF.

_____________________________

/Greyshaft

(in reply to bo)
Post #: 84
RE: I believe this game will never happen - 6/14/2013 5:13:45 AM   
CrusssDaddy

 

Posts: 330
Joined: 8/6/2004
Status: offline
Ugh, and I thought the "When?" thread was tedious. CAN WE GET SOME MORE CODE DUMPS, I LIKE SCROLLING!!!

(in reply to Greyshaft)
Post #: 85
RE: I believe this game will never happen - 6/14/2013 8:11:50 AM   
Centuur


Posts: 8802
Joined: 6/3/2011
From: Hoorn (NED).
Status: offline

quote:

ORIGINAL: bo

I would really like to know why you quit the beta team Extraneous, I mean really pretty please. And please talk down to me so I truly understand why you quit because it is very important to all of us or at least me. And tough, I am a beta tester but you knew that.

I just went to Google earth and checked again and it looks like to me that Australia is surrounded by water so IMHO it is downgraded from a continent to an island status. Big island to be sure. I notice the Snowden comment went right over your head. If you want me to explain it to you I will gladly do so but then I would have to talk down to you so you would understand.

Your comment to Steve was uncalled for please leave him out of this please.

This is my last post to you as Mr. nice guy, from now on it is Extraneous hunting season

Bo

I agree that Mr. Extranous is now a hunted man. I hate quitters, especially if there isn't a reason to quit. Sure, there are times when a software tester wants to grill the programmer on the barbecue. Sure, there are times when you don't want to do anything about testing, since it doesn't seem things are progressing. But that's all part of the show. So put the thing aside for a couple of weeks and return to testing later on, when things are getting interesting again. But to totally quit? Never! I want this game to go on the market.
Of course I can understand that especially the testers of the first hour are disappointed, since the whole thing is really very, very slowly progressing. That those guys tend to get a little tired running things is understandable. That they decide to postpone testing for all kind of reasons is expected. But to totally quit? That's pretty drastic.
What I would like to see is some of the old guard returning to beta testing (if they can). I think that would help a lot...


_____________________________

Peter

(in reply to bo)
Post #: 86
RE: I believe this game will never happen - 6/14/2013 9:36:55 AM   
Extraneous

 

Posts: 1810
Joined: 6/14/2008
Status: offline
quote:

ORIGINAL: bo

I would really like to know why you quit the beta team Extraneous, I mean really pretty please. And please talk down to me so I truly understand why you quit because it is very important to all of us or at least me. And tough, I am a beta tester but you knew that.

I just went to Google earth and checked again and it looks like to me that Australia is surrounded by water so IMHO it is downgraded from a continent to an island status. Big island to be sure. I notice the Snowden comment went right over your head. If you want me to explain it to you I will gladly do so but then I would have to talk down to you so you would understand.

Your comment to Steve was uncalled for please leave him out of this please.

This is my last post to you as Mr. nice guy, from now on it is Extraneous hunting season

Bo


Then as a beta tester ask the other beta testers or Steve.

As a beta tester you know that unless Steve releases me from the NDA or the proper time after the game is released has elapsed I cannot respond to why I quit.

Steve decided to bring it up when he said I looked up system design.

I don't know about you but telling me I don't know anything about a career I worked at for most of my life is HIGHLY insulting.

You expect me to ignore an insult to my life? It ain't going to happen.

Strange the Australian government seams to think Australia is a continent.

ROFLMAO I'm so afraid! Like it wasn't already Extraneous hunting season


quote:

ORIGINAL: Centuur

I agree that Mr. Extranous is now a hunted man. I hate quitters, especially if there isn't a reason to quit. Sure, there are times when a software tester wants to grill the programmer on the barbecue. Sure, there are times when you don't want to do anything about testing, since it doesn't seem things are progressing. But that's all part of the show. So put the thing aside for a couple of weeks and return to testing later on, when things are getting interesting again. But to totally quit? Never! I want this game to go on the market.

Of course I can understand that especially the testers of the first hour are disappointed, since the whole thing is really very, very slowly progressing. That those guys tend to get a little tired running things is understandable. That they decide to postpone testing for all kind of reasons is expected. But to totally quit? That's pretty drastic.
What I would like to see is some of the old guard returning to beta testing (if they can). I think that would help a lot...



If your implying I had no reason then I suggest you think again.

If you think I'm using the NDA as a shield I suggest you think again.

If you think it was the length of time the beta was taking you are wrong.




< Message edited by Extraneous -- 6/14/2013 9:46:40 AM >


_____________________________

University of Science Music and Culture (USMC) class of 71 and 72 ~ Extraneous (AKA Mziln)

(in reply to Centuur)
Post #: 87
RE: I believe this game will never happen - 6/14/2013 12:46:02 PM   
Centuur


Posts: 8802
Joined: 6/3/2011
From: Hoorn (NED).
Status: offline

quote:

ORIGINAL: Extraneous

quote:

ORIGINAL: bo

I would really like to know why you quit the beta team Extraneous, I mean really pretty please. And please talk down to me so I truly understand why you quit because it is very important to all of us or at least me. And tough, I am a beta tester but you knew that.

I just went to Google earth and checked again and it looks like to me that Australia is surrounded by water so IMHO it is downgraded from a continent to an island status. Big island to be sure. I notice the Snowden comment went right over your head. If you want me to explain it to you I will gladly do so but then I would have to talk down to you so you would understand.

Your comment to Steve was uncalled for please leave him out of this please.

This is my last post to you as Mr. nice guy, from now on it is Extraneous hunting season

Bo


Then as a beta tester ask the other beta testers or Steve.

As a beta tester you know that unless Steve releases me from the NDA or the proper time after the game is released has elapsed I cannot respond to why I quit.

Steve decided to bring it up when he said I looked up system design.

I don't know about you but telling me I don't know anything about a career I worked at for most of my life is HIGHLY insulting.

You expect me to ignore an insult to my life? It ain't going to happen.

Strange the Australian government seams to think Australia is a continent.

ROFLMAO I'm so afraid! Like it wasn't already Extraneous hunting season


quote:

ORIGINAL: Centuur

I agree that Mr. Extranous is now a hunted man. I hate quitters, especially if there isn't a reason to quit. Sure, there are times when a software tester wants to grill the programmer on the barbecue. Sure, there are times when you don't want to do anything about testing, since it doesn't seem things are progressing. But that's all part of the show. So put the thing aside for a couple of weeks and return to testing later on, when things are getting interesting again. But to totally quit? Never! I want this game to go on the market.

Of course I can understand that especially the testers of the first hour are disappointed, since the whole thing is really very, very slowly progressing. That those guys tend to get a little tired running things is understandable. That they decide to postpone testing for all kind of reasons is expected. But to totally quit? That's pretty drastic.
What I would like to see is some of the old guard returning to beta testing (if they can). I think that would help a lot...



If your implying I had no reason then I suggest you think again.

If you think I'm using the NDA as a shield I suggest you think again.

If you think it was the length of time the beta was taking you are wrong.





First: I'm not saying that you didn't have a reason to quit. Reading is difficult, isn't it. In my opinion, people who quit usually do these kind of things out of the wrong reasons. Not being able to accept certain points of view from people in charge is one of them. After having to deal with you on this forum, I think you are in that category (if not, why are you always saying: "I'm right and you are wrong" in your posts).

Second: I didn't think you are using the NDA as a shield. If things have occured which you can't speak about here, than that's to bad for us. If you can't seem to give the reason due to the contract, than that is a valid way of excusing yourself and we have to abide by that decision and don't press on the attack. However: this also means that you should be a little more cautious in how you operate on this forum. You know what happens behind the public screens, so you should know better...

Third: the second paragraph (is this good English) was not intended to you personally, but in general to the Beta testers who have slowly decided to leave things as they were at that time and who didn't simply quit, but just vanished out of view. It is difficult to keep volunteers working for you if there are continuous delays and it doesn't seem things are drawing to a close soon, especially since it is work done "at distance". I haven't even got a clue how Steve looks like, or Bo, or Warspite, or Red Prince or all other people behind this. That is a disadvantage. I would like to get a beer (Budweiser is absolutely out of the question) somewhere in a pub in the world with all of them (keep on dreaming) to make sure everyone is again on the same track if I were in Steve's place. However, that isn't going to happen. I'm convinced there are a lot of the old beta testers around who have put this thing behind them, thinking: "This is never going to happen". They are wrong, but I can't blame them. A decade of development is a very, very long time.

_____________________________

Peter

(in reply to Extraneous)
Post #: 88
RE: I believe this game will never happen - 6/14/2013 4:44:37 PM   
brian brian

 

Posts: 3191
Joined: 11/16/2005
Status: offline
my head hurts

(in reply to Centuur)
Post #: 89
RE: I believe this game will never happen - 6/14/2013 4:45:18 PM   
bo

 

Posts: 4176
Joined: 5/1/2009
Status: offline
I rarely ever disagree with the gentleman from Hoorn but there are two things he has said that I have to disagree with him, one is the Budweiser question that we will probably never resolve and two that Extraneous may not be hiding behind his NDA. He is hiding behind it like all cowards hide behind something, like behind the fifth amendment with Matrix it is the NDA.

Fess up, what is Matrix going to do beat you with a wet noodle? Lock you in a room with crussdaddy for a week, hmmmm, whew that would be punishment above and beyond cruelty

Then again with all your brilliant knowledge of computer programing, just maybe this was beneath your gigantic ego to solve the problem of why a unit was getting a madexcept for doing this or doing that.

Just getting warmed up to the task at hand Extraneous You end the insults here and I will.

Bo

(in reply to Shannon V. OKeets)
Post #: 90
Page:   <<   < prev  1 2 [3] 4   next >   >>
All Forums >> [New Releases from Matrix Games] >> World in Flames >> RE: I believe this game will never happen Page: <<   < prev  1 2 [3] 4   next >   >>
Jump to:





New Messages No New Messages
Hot Topic w/ New Messages Hot Topic w/o New Messages
Locked w/ New Messages Locked w/o New Messages
 Post New Thread
 Reply to Message
 Post New Poll
 Submit Vote
 Delete My Own Post
 Delete My Own Thread
 Rate Posts


Forum Software © ASPPlayground.NET Advanced Edition 2.4.5 ANSI

0.813