anchor.diff:  //Render debug symbols
   procedure TKMInfluences.Paint(aRect: TKMRect);
   var
  -  I, K, J: Integer;
  +  PL, WatchedPL: TKMHandIndex;
  +  I, Cnt: Word;
  +  X,Y: Integer;
  +  PolyArr: TPolygonArray;
  +  NodeArr: TNodeArray;
     Col: Cardinal;
   begin
  -  if not AI_GEN_INFLUENCE_MAPS then Exit;
  -
  -  if OVERLAY_INFLUENCE then
  -    for I := aRect.Top to aRect.Bottom do
  -    for K := aRect.Left to aRect.Right do
  +  if not AI_GEN_NAVMESH OR not AI_GEN_INFLUENCE_MAPS then
  +    Exit;
  +
  +  if OVERLAY_AVOID then
  +    for Y := aRect.Top to aRect.Bottom do
  +    for X := aRect.Left to aRect.Right do
       begin
  -      Col := $80000000;
  -      J := GetBestOwner(K,I);
  -      if J <> PLAYER_NONE then
  -        Col := (gHands[J].FlagColor and $FFFFFF) or (Influence[J,I,K] shl 24);
  -      gRenderAux.Quad(K, I, Col);
  +      Col := AvoidBuilding[Y,X] * 65793 OR $80000000;
  +      gRenderAux.Quad(X, Y, Col);
       end;
   
  -  if OVERLAY_OWNERSHIP then
  -    for I := aRect.Top to aRect.Bottom do
  -    for K := aRect.Left to aRect.Right do
  +  if OVERLAY_INFLUENCE OR OVERLAY_OWNERSHIP then
  +  begin
  +    PolyArr := fNavMesh.Polygons;
  +    NodeArr := fNavMesh.Nodes;
  +    for I := 0 to fPolygons - 1 do
       begin
  -      Col := $80000000;
  -      J := GetBestOwner(K,I);
  -      if J <> PLAYER_NONE then
  -        Col := (gHands[J].FlagColor and $FFFFFF)
  -                or (Ownership[J,I,K] shl 24)
  -                or ((Byte(InRange(Ownership[J,I,K], OWN_THRESHOLD, OWN_MARGIN)) * 255) shl 24);
  -      gRenderAux.Quad(K, I, Col);
  +      PL := GetBestOwner(I);
  +      if (PL = PLAYER_NONE) then
  +        continue
  +      else
  +        Col := (gHands[PL].FlagColor AND $FFFFFF) OR (OwnPoly[PL,I] shl 24);
  +
  +      //NavMesh polys coverage
  +      gRenderAux.TriangleOnTerrain(
  +        NodeArr[PolyArr[I].Indices[0]].Loc.X,
  +        NodeArr[PolyArr[I].Indices[0]].Loc.Y,
  +        NodeArr[PolyArr[I].Indices[1]].Loc.X,
  +        NodeArr[PolyArr[I].Indices[1]].Loc.Y,
  +        NodeArr[PolyArr[I].Indices[2]].Loc.X,
  +        NodeArr[PolyArr[I].Indices[2]].Loc.Y, Col);
       end;
  -
  -  if OVERLAY_AVOID then
  -    for I := aRect.Top to aRect.Bottom do
  -    for K := aRect.Left to aRect.Right do
  +  end;
  +
  +  if OVERLAY_AI_COMBAT then
  +  begin
  +    WatchedPL := gMySpectator.HandIndex;
  +    if (WatchedPL = PLAYER_NONE) then
  +      Exit;
  +
  +    PolyArr := fNavMesh.Polygons;
  +    NodeArr := fNavMesh.Nodes;
  +
  +    for PL := 0 to gHands.Count - 1 do
       begin
  -      Col := AvoidBuilding[I,K] * 65793 or $80000000;
  -      gRenderAux.Quad(K, I, Col);
  +      if (WatchedPL = PL) then
  +        Col := $0000FF00 // Green
  +      else if (gHands[WatchedPL].Alliances[PL] = at_Ally) then
  +        Col := $00FF0000 // Blue
  +      else
  +        Col := $000000FF; // Red
  +
  +      for I := 0 to fPolygons - 1 do
  +      begin
  +        Cnt := PresenceAllGroups[PL,I];
  +        if (Cnt > 0) then
  +        begin
  +          Cnt := Min(Cnt,$5F);
  +          //NavMesh polys coverage
  +          gRenderAux.TriangleOnTerrain(
  +            NodeArr[PolyArr[I].Indices[0]].Loc.X,
  +            NodeArr[PolyArr[I].Indices[0]].Loc.Y,
  +            NodeArr[PolyArr[I].Indices[1]].Loc.X,
  +            NodeArr[PolyArr[I].Indices[1]].Loc.Y,
  +            NodeArr[PolyArr[I].Indices[2]].Loc.X,
  +            NodeArr[PolyArr[I].Indices[2]].Loc.Y, (Col OR (Cnt shl 24)) ); // (Col OR $50000000)
  +        end;
  +      end;
       end;
  -end;
  -
  +    //for I := 0 to fPolygons - 1 do
  +    //begin
  +    //  BestCnt := 0;
  +    //  for PL := 0 to gHands.Count - 1 do
  +    //  begin
  +    //    Cnt := PresenceAllGroups[PL,I];
  +    //    if (Cnt > BestCnt) then
  +    //    begin
  +    //      BestCnt := Cnt;
  +    //      if (WatchedPL = PL) then
  +    //        Col := $0000FF00 // Green
  +    //      else if (gHands[WatchedPL].Alliances[PL] = at_Ally) then
  +    //        Col := $00FF0000 // Blue
  +    //      else
  +    //        Col := $000000FF; // Red
  +    //    end;
  +    //  end;
  +    //  if (BestCnt > 0) then
  +    //  begin
  +    //    BestCnt := Min(BestCnt,$9F);
  +    //    //NavMesh polys coverage
  +    //    gRenderAux.TriangleOnTerrain(
  +    //      NodeArr[PolyArr[I].Indices[0]].Loc.X,
  +    //      NodeArr[PolyArr[I].Indices[0]].Loc.Y,
  +    //      NodeArr[PolyArr[I].Indices[1]].Loc.X,
  +    //      NodeArr[PolyArr[I].Indices[1]].Loc.Y,
  +    //      NodeArr[PolyArr[I].Indices[2]].Loc.X,
  +    //      NodeArr[PolyArr[I].Indices[2]].Loc.Y, (Col OR (BestCnt shl 24)) );
  +    //  end;
  +    //end;
  +  end;
  +end;
   
   end.
  
positive.code: {$I KaM_Remake.inc}
  interface
  uses
    KM_CommonClasses, KM_Defaults, KM_Points;
  
  
  type
    //Collection of influence maps
    TKMInfluences = class
    private
      fMapX: Word;
      fMapY: Word;
      fUpdatePlayerId: TKMHandIndex; //Player we will be updating next
      //This is cache for CanOwn in gTerrain.Land
      Ownable: array of array of Boolean;
  
      //Stored in 1D arrays for optimisation, accessed through property
      fInfluence: array of Byte; //Each players area of influence
      fOwnership: array of Byte;
  
      function GetInfluence(aPlayer: Byte; Y,X: Word): Byte; inline;
      procedure SetInfluence(aPlayer: Byte; Y,X: Word; aInfluence: Byte); inline;
      function GetOwnership(aPlayer: Byte; Y,X: Word): Byte; inline;
      procedure SetOwnership(aPlayer: Byte; Y,X: Word; aOwnership: Byte); inline;
  
      property Influence[aPlayer: Byte; Y,X: Word]: Byte read GetInfluence write SetInfluence;
  
      procedure InitInfluenceAvoid;
      procedure InitInfluenceOwnable;
      procedure UpdateDirectInfluence(aIndex: TKMHandIndex);
      procedure UpdateOwnershipInfluence(aIndex: TKMHandIndex);
    public
      //Common map of areas where building is undesired (around Store, Mines, Woodcutters)
      AvoidBuilding: array of array of Byte;
  
      //Tiles best owner and his influence
      property Ownership[aPlayer:Byte; Y,X: Word]: Byte read GetOwnership write SetOwnership;
      //Tension: array of array of array of SmallInt;
  
      procedure AddAvoidBuilding(X,Y: Word; aRad: Single; aValue: Byte = 255);
      procedure RemAvoidBuilding(aArea: TKMRect);
      function GetBestOwner(X, Y: Word): TKMHandIndex;
      function GetBestAllianceOwnership(aIndex: TKMHandIndex; X,Y: Word; aAllianceType: TAllianceType): Byte;
      function OtherOwnerships(aPlayer: Byte; X, Y: Word): Word;
      procedure Init;
      procedure ExportInfluenceMaps;
  
      procedure Save(SaveStream: TKMemoryStream);
      procedure Load(LoadStream: TKMemoryStream);
      procedure UpdateState(aTick: Cardinal);
      procedure Paint(aRect: TKMRect);
    end;
  
negative.code:   Classes, Graphics, SysUtils, Math,
    KM_RenderAux,
    KM_Terrain, KM_Houses, KM_HouseCollection,
    KM_Hand, KM_HandsCollection, KM_ResHouses,
    KM_AIFields;
  
  
  const
    GROUPS = 4;
    INIT_HOUSE_INFLUENCE = 255;
    MAX_INFLUENCE_DISTANCE = 150;
  
  
  { TKMInfluenceMaps }
  constructor TKMInfluences.Create(aNavMesh: TKMNavMesh);
  begin
    inherited Create();
  
    fNavMesh := aNavMesh;
    fUpdateCityIdx := 0;
    fUpdateArmyIdx := 0;
    fFloodFill := TKMInfluenceFloodFill.Create(False); // Check if True is better
    fInfluenceSearch := TNavMeshInfluenceSearch.Create(False);
  end;
  
  
  destructor TKMInfluences.Destroy();
  begin
    fFloodFill.Free;
    fInfluenceSearch.Free;
    inherited;
  end;
  
  
  procedure TKMInfluences.Save(SaveStream: TKMemoryStream);
  var
    PCount: Word;
    Y, Len: Integer;
  begin
    PCount := gHands.Count;
  
    SaveStream.WriteA('Influences');
    SaveStream.Write(PCount);
    SaveStream.Write(fMapX);
    SaveStream.Write(fMapY);
    SaveStream.Write(fPolygons);
    SaveStream.Write(fUpdateCityIdx);
    SaveStream.Write(fUpdateArmyIdx);
  
    SaveStream.WriteA('AvoidBuilding');
    for Y := 0 to fMapY - 1 do
      SaveStream.Write(AvoidBuilding[Y,0], fMapX * SizeOf(AvoidBuilding[0,0]));
  
    SaveStream.WriteA('Ownership');
    Len := Length(fOwnership);
    SaveStream.Write(Len);
    SaveStream.Write(fOwnership[0], SizeOf(fOwnership[0]) * Len);
  
    SaveStream.WriteA('ArmyPresence');
    Len := Length(fPresence);
    SaveStream.Write(Len);
    SaveStream.Write(fPresence[0], SizeOf(fPresence[0]) * Len);
  end;
  
  
  procedure TKMInfluences.Load(LoadStream: TKMemoryStream);
  var
    PCount: Word;
    Y, Len: Integer;
  begin
    LoadStream.ReadAssert('Influences');
    LoadStream.Read(PCount);
    LoadStream.Read(fMapX);
    LoadStream.Read(fMapY);
    LoadStream.Read(fPolygons);
    LoadStream.Read(fUpdateCityIdx);
    LoadStream.Read(fUpdateArmyIdx);
  
    LoadStream.ReadAssert('AvoidBuilding');
    SetLength(AvoidBuilding, fMapY, fMapX);
    for Y := 0 to fMapY - 1 do
      LoadStream.Read(AvoidBuilding[Y,0], fMapX * SizeOf(AvoidBuilding[0,0]));
  
    LoadStream.ReadAssert('Ownership');
    LoadStream.Read(Len);
    SetLength(fOwnership, Len);
    LoadStream.Read(fOwnership[0], SizeOf(fOwnership[0]) * Len);
  
    LoadStream.ReadAssert('ArmyPresence');
    LoadStream.Read(Len);
    SetLength(fPresence, Len);
    LoadStream.Read(fPresence[0], SizeOf(fPresence[0]) * Len);
  end;
  
  
  
  
  //Make the area around to be avoided by common houses
  procedure TKMInfluences.AddAvoidBuilding(aX,aY: Word; aRad: Single; aValue: Byte = 255);
  var
    X,Y: Integer;
  begin
    for Y := Max(aY - Ceil(aRad), 1) to Min(aY + Ceil(aRad), fMapY - 1) do
    for X := Max(aX - Ceil(aRad), 1) to Min(aX + Ceil(aRad), fMapX - 1) do
      if Sqr(aX-X) + Sqr(aY-Y) <= Sqr(aRad) then
        AvoidBuilding[Y,X] := Min(AvoidBuilding[Y,X] + aValue, 255);
  end;
  
  
  procedure TKMInfluences.RemAvoidBuilding(aArea: TKMRect);
  var
    X,Y: Integer;
  begin
    for Y := Max(aArea.Top , 1) to Min(aArea.Bottom, fMapY - 1) do
    for X := Max(aArea.Left, 1) to Min(aArea.Right , fMapX - 1) do
      AvoidBuilding[Y,X] := 0;
  end;
  
  
  //AI should avoid certain areas, keeping them for special houses
  procedure TKMInfluences.InitAvoidBuilding();
    procedure CheckAndMarkMine(aX,aY: Integer; aHT: THouseType);
    var
      X,Y,X2,Y2: Integer;
  