anchor.diff:    Classes, KromUtils, Math, SysUtils,
     KM_Units, KM_UnitGroups,
     KM_CommonClasses, KM_CommonTypes, KM_Defaults, KM_Points,
  -  KM_Houses, KM_ResHouses, KM_NavMeshPathFinding;
  +  KM_Houses, KM_ResHouses, KM_NavMeshPathFinding,
  +  KM_Eye, KM_NavMeshInfluences;
   
   type
  -  TAISquad = class // Squad management (one group) -> move group / attack something with group
  +  TKMSquadArray = array[TGroupType] of TKMList;
  +
  +  TAISquad = class // Squad management (one group)
     private
  -    fGroup: TKMUnitGroup; //Commander of group currently occupying position
  +    fGroup: TKMUnitGroup;
  +    fIsReady: Boolean;
       fFinalPosition: TKMPointDir;
  +    fTargetHouse: TKMHouse;
       fTargetUnit: TKMUnit;
  -    fTargetHouse: TKMHouse;
       fTimeLimit: Cardinal;
  -    fPolygonPath: TKMWordArray;
  -    fPointPath: TKMPointArray;
  +
  +    fDEBUGPointPath: TKMPointArray;
   
       function GetGroupPosition(): TKMPoint; inline;
  +    function PlanPath(var aActualPosition, aTargetPosition: TKMPoint): Boolean;
  +
  +    procedure SetTargetHouse(aHouse: TKMHouse);
  +    procedure SetTargetUnit(aUnit: TKMUnit);
     public
       constructor Create(aGroup: TKMUnitGroup);
  +    constructor Load(LoadStream: TKMemoryStream);
       destructor Destroy; override;
       procedure Save(SaveStream: TKMemoryStream);
  -    procedure Load(LoadStream: TKMemoryStream);
  -
  -    //property State: TAISquadState read fSquadState;
  -    //property Order: TAISquadOrder read fSquadOrder write fSquadOrder;
  -    property TargetHouse: TKMHouse read fTargetHouse write fTargetHouse;
  -    property TargetUnit: TKMUnit read fTargetUnit write fTargetUnit;
  +    procedure SyncLoad();
  +
  +    property Group: TKMUnitGroup read fGroup;
  +    property IsReady: Boolean read fIsReady;
  +    property FinalPosition: TKMPointDir read fFinalPosition write fFinalPosition;
       property Position: TKMPoint read GetGroupPosition;
  -    property Group: TKMUnitGroup read fGroup;
  +    property TargetHouse: TKMHouse read fTargetHouse write SetTargetHouse;
  +    property TargetUnit: TKMUnit read fTargetUnit write SetTargetUnit;
  +    property PointPath: TKMPointArray read fDEBUGPointPath write fDEBUGPointPath;
  +
  +
   
       procedure UpdateState(aTick: Cardinal);
     end;
  
positive.code: procedure TKMArmyAttack.OwnerUpdate(aPlayer: TKMHandIndex);
  begin
    fOwner := aPlayer;
  end;
  
  
  function TKMArmyAttack.SelectTarget(aCompany: TAICompany; aPoint: TKMPoint): Boolean;
  var
    I: Integer;
    TargetHouse: TKMHouse;
    TargetUnit: TKMUnit;
  begin
    Result := False;
    // Compute common stuf first
    TargetHouse := gHands.GetClosestHouse(aCompany.Position, fOwner, at_Enemy, false);
    if (TargetHouse = nil) then
    begin
      TargetUnit := gHands.GetClosestUnit(aCompany.Position, fOwner, at_Enemy);
      if (TargetUnit = nil) then
        Exit;
    end;
  
    Result := True;
  end;
  
  
  procedure TKMArmyAttack.OrderToAttack();
  var
    I, idx: Integer;
    Target: TKMPoint;
    Company: TAICompany;
  begin
    Company := nil;
    fCompaniesCnt := fCompaniesCnt + 1;
    idx := fCompaniesCnt - 1;
    fCompanies.Add( TKMArmyAttack.Create(fOwner) );
    for I := 0 to gHands[fOwner].UnitGroups.Count - 1 do   // Edit (not all groups into 1 company)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    begin
      Company := fCompanies.Items[idx];
      Company.AddSquad( gHands[fOwner].UnitGroups[I] );
    end;
  
    if SelectTarget(Company,Target) AND (Company <> nil) then
      Company.LaunchAttack(Target);
  end;
  
  
  
  procedure TKMArmyAttack.LogStatus(var aBalanceText: UnicodeString);
  begin
    aBalanceText := '';
  end;
  
  
  
negative.code:   TAICompany = class
    private
      fOwner: TKMHandIndex;
      fPosition: TKMPoint;
      fTargetHouse: TKMHouse;
      fTargetUnit: TKMUnit;
      fSquads: TKMSquadArray;
  
      fDEBUGPointPath: TKMPointArray;
  
      function GetPosition(): TKMPoint;
      function GetTargetPosition(): TKMPoint;
      function GetPointerPosition(aHouse: TKMHouse; aUnit: TKMUnit): TKMPoint;
      procedure OrderToAttack(aActualPosition: TKMPoint; UGA: TKMUnitGroupArray; HA: TKMHouseArray; aTargetHouse: Boolean);
      procedure OrderMove(aActualPosition: TKMPoint);
    public
      constructor Create(aPlayer: TKMHandIndex);
      constructor Load(LoadStream: TKMemoryStream);
      destructor Destroy(); override;
      procedure Save(SaveStream: TKMemoryStream);
      procedure SyncLoad();
  
      property Position: TKMPoint read fPosition;
      property TargetPosition: TKMPoint read GetTargetPosition;
      property Squads: TKMSquadArray read fSquads;
      property PointPath: TKMPointArray read fDEBUGPointPath write fDEBUGPointPath;
  
      procedure InitCompany();
  
      procedure UpdateState(aTick: Cardinal);
      procedure OwnerUpdate(aPlayer: TKMHandIndex);
      procedure AddSquad(aGroup: TKMUnitGroup);
      procedure DeleteSquad(aGT: TGroupType; aIdx: Integer);
      function SquadCnt(aTypes: TGroupTypeSet = [Low(TGroupType)..High(TGroupType)]): Word;
      function IsGroupInCompany(aGroup: TKMUnitGroup): Boolean;
      function SetTarget(aHouse: TKMHouse; aUnit: TKMUnit = nil): Boolean;
      function ActualizeTarget(aInitPosition: TKMPoint; var aTargetHouse: TKMHouse; var aTargetUnit: TKMUnit; aAimCivilians: Boolean = True): Boolean;
    end;
  
    TKMArmyAttack = class
    private
      fOwner: TKMHandIndex;
      fCompanies: TKMList;
  
      //function SelectClosestTarget(aInitPoint: TKMPoint; var aTargetHouse: TKMHouse; var aTargetUnit: TKMUnit; var aTargetGroup: TKMUnitGroup): Boolean;
      function GetCount(): Integer;
      function GetCompany(aIdx: Integer): TAICompany;
    public
      constructor Create(aPlayer: TKMHandIndex);
      destructor Destroy(); override;
      procedure Save(SaveStream: TKMemoryStream);
      procedure Load(LoadStream: TKMemoryStream);
      procedure SyncLoad();
  
      property Count: Integer read GetCount;
      property Company[aIdx: Integer]: TAICompany read GetCompany; default;
  
      procedure AfterMissionInit();
      procedure UpdateState(aTick: Cardinal);
      procedure OwnerUpdate(aPlayer: TKMHandIndex);
      function FindBestTarget(var TargetOwner: TKMHandIndex; var aTargetPoint: TKMPoint; aForceToAttack: Boolean = False): Boolean;
      procedure OrderToAttack(aTargetPoint: TKMPoint; aGroups: TKMUnitGroupArray);
      function IsGroupInAction(aGroup: TKMUnitGroup): Boolean;
  
      procedure LogStatus(var aBalanceText: UnicodeString);
      procedure Paint();
    end;
  
  const
    COMPANY_SCAN_RAD = 20;
    SQR_COMPANY_SCAN_RAD = COMPANY_SCAN_RAD * COMPANY_SCAN_RAD;
    COMPANY_ATTACK_RAD = 15;
    SQR_COMPANY_ATTACK_RAD = COMPANY_ATTACK_RAD * COMPANY_ATTACK_RAD;
    TARGET_HOUSES: THouseTypeSet = [ht_WatchTower, ht_Barracks, ht_Store];
  
  implementation
  uses
    KM_Game, KM_Hand, KM_HandsCollection, KM_Terrain, KM_AIFields,
    KM_NavMesh, KM_CommonUtils, KM_AISetup, KM_AI, KM_RenderAux;
  
  
  
  
  { TAISquad }
  