Ignore:
Timestamp:
Jan 8, 2017, 11:42:00 PM (7 years ago)
Author:
chronos
Message:
  • Fixed: Source formatting of some files due missing semicolon before until keyword.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/LocalPlayer/IsoEngine.pas

    r28 r33  
    360360        if Border then
    361361          inc(TSpriteSize[i].Left);
    362       until not Border or
    363         (TSpriteSize[i].Left = xxt * 2 - 1);
     362      until not Border or (TSpriteSize[i].Left = xxt * 2 - 1);
    364363      TSpriteSize[i].Top := 0;
    365364      repeat
     
    371370        if Border then
    372371          inc(TSpriteSize[i].Top);
    373       until not Border or
    374         (TSpriteSize[i].Top = yyt * 3 - 1);
     372      until not Border or (TSpriteSize[i].Top = yyt * 3 - 1);
    375373      TSpriteSize[i].Right := xxt * 2;
    376374      repeat
     
    382380        if Border then
    383381          dec(TSpriteSize[i].Right);
    384       until not Border or
    385         (TSpriteSize[i].Right = TSpriteSize[i].Left);
     382      until not Border or (TSpriteSize[i].Right = TSpriteSize[i].Left);
    386383      TSpriteSize[i].Bottom := yyt * 3;
    387384      repeat
    388385        Border := true;
    389386        for x := 0 to xxt * 2 - 1 do
    390           if MaskLine[TSpriteSize[i].Bottom - 1]^
    391             [1 + xSrc * (xxt * 2 + 1) + x, 0] = 0 then
    392               Border := false;
     387          if MaskLine[TSpriteSize[i].Bottom - 1]^[1 + xSrc * (xxt * 2 + 1) + x,
     388            0] = 0 then
     389            Border := false;
    393390        if Border then
    394391          dec(TSpriteSize[i].Bottom);
    395       until not Border or
    396         (TSpriteSize[i].Bottom = TSpriteSize[i].Top);
     392      until not Border or (TSpriteSize[i].Bottom = TSpriteSize[i].Top);
    397393    end
    398394  end;
     
    409405end;
    410406
    411         procedure Done;
     407procedure Done;
     408begin
     409  NoMap.Free;
     410  NoMap := nil;
     411  LandPatch.Free;
     412  LandPatch := nil;
     413  OceanPatch.Free;
     414  OceanPatch := nil;
     415  Borders.Free;
     416  Borders := nil;
     417end;
     418
     419procedure Reset;
     420begin
     421  BordersOK := 0;
     422end;
     423
     424constructor TIsoMap.Create;
     425begin
     426  inherited;
     427  FLeft := 0;
     428  FTop := 0;
     429  FRight := 0;
     430  FBottom := 0;
     431  AttLoc := -1;
     432  DefLoc := -1;
     433  FAdviceLoc := -1;
     434end;
     435
     436procedure TIsoMap.SetOutput(Output: TBitmap);
     437begin
     438  FOutput := Output;
     439  FLeft := 0;
     440  FTop := 0;
     441  FRight := FOutput.Width;
     442  FBottom := FOutput.Height;
     443end;
     444
     445procedure TIsoMap.SetPaintBounds(Left, Top, Right, Bottom: integer);
     446begin
     447  FLeft := Left;
     448  FTop := Top;
     449  FRight := Right;
     450  FBottom := Bottom;
     451end;
     452
     453procedure TIsoMap.FillRect(x, y, Width, Height, Color: integer);
     454begin
     455  if x < FLeft then
     456  begin
     457    Width := Width - (FLeft - x);
     458    x := FLeft
     459  end;
     460  if y < FTop then
     461  begin
     462    Height := Height - (FTop - y);
     463    y := FTop
     464  end;
     465  if x + Width >= FRight then
     466    Width := FRight - x;
     467  if y + Height >= FBottom then
     468    Height := FBottom - y;
     469  if (Width <= 0) or (Height <= 0) then
     470    exit;
     471
     472  with FOutput.Canvas do
     473  begin
     474    Brush.Color := Color;
     475    FillRect(Rect(x, y, x + Width, y + Height));
     476    Brush.Style := bsClear;
     477  end
     478end;
     479
     480procedure TIsoMap.Textout(x, y, Color: integer; const s: string);
     481begin
     482  FOutput.Canvas.Font.Color := Color;
     483  FOutput.Canvas.TextRect(Rect(FLeft, FTop, FRight, FBottom), x, y, s)
     484end;
     485
     486procedure TIsoMap.BitBlt(Src: TBitmap; x, y, Width, Height, xSrc, ySrc,
     487  Rop: integer);
     488begin
     489  if x < FLeft then
     490  begin
     491    Width := Width - (FLeft - x);
     492    xSrc := xSrc + (FLeft - x);
     493    x := FLeft
     494  end;
     495  if y < FTop then
     496  begin
     497    Height := Height - (FTop - y);
     498    ySrc := ySrc + (FTop - y);
     499    y := FTop
     500  end;
     501  if x + Width >= FRight then
     502    Width := FRight - x;
     503  if y + Height >= FBottom then
     504    Height := FBottom - y;
     505  if (Width <= 0) or (Height <= 0) then
     506    exit;
     507
     508  LCLIntf.BitBlt(FOutput.Canvas.Handle, x, y, Width, Height, Src.Canvas.Handle,
     509    xSrc, ySrc, Rop);
     510end;
     511
     512procedure TIsoMap.Sprite(HGr, xDst, yDst, Width, Height, xGr, yGr: integer);
     513begin
     514  BitBlt(GrExt[HGr].Mask, xDst, yDst, Width, Height, xGr, yGr, SRCAND);
     515  BitBlt(GrExt[HGr].Data, xDst, yDst, Width, Height, xGr, yGr, SRCPAINT);
     516end;
     517
     518procedure TIsoMap.TSprite(xDst, yDst, grix: integer;
     519  PureBlack: boolean = false);
     520var
     521  Width, Height, xSrc, ySrc: integer;
     522begin
     523  Width := TSpriteSize[grix].Right - TSpriteSize[grix].Left;
     524  Height := TSpriteSize[grix].Bottom - TSpriteSize[grix].Top;
     525  xSrc := 1 + grix mod 9 * (xxt * 2 + 1) + TSpriteSize[grix].Left;
     526  ySrc := 1 + grix div 9 * (yyt * 3 + 1) + TSpriteSize[grix].Top;
     527  xDst := xDst + TSpriteSize[grix].Left;
     528  yDst := yDst - yyt + TSpriteSize[grix].Top;
     529  if xDst < FLeft then
     530  begin
     531    Width := Width - (FLeft - xDst);
     532    xSrc := xSrc + (FLeft - xDst);
     533    xDst := FLeft
     534  end;
     535  if yDst < FTop then
     536  begin
     537    Height := Height - (FTop - yDst);
     538    ySrc := ySrc + (FTop - yDst);
     539    yDst := FTop
     540  end;
     541  if xDst + Width >= FRight then
     542    Width := FRight - xDst;
     543  if yDst + Height >= FBottom then
     544    Height := FBottom - yDst;
     545  if (Width <= 0) or (Height <= 0) then
     546    exit;
     547
     548  LCLIntf.BitBlt(OutDC, xDst, yDst, Width, Height, MaskDC, xSrc, ySrc, SRCAND);
     549  if not PureBlack then
     550    LCLIntf.BitBlt(OutDC, xDst, yDst, Width, Height, DataDC, xSrc, ySrc,
     551      SRCPAINT);
     552end;
     553
     554procedure TIsoMap.PaintUnit(x, y: integer; const UnitInfo: TUnitInfo;
     555  Status: integer);
     556var
     557  xsh, ysh, xGr, yGr, j, mixShow: integer;
     558begin
     559  with UnitInfo do
     560    if (Owner = me) or (emix <> $FFFF) then
     561    begin
     562      if Job = jCity then
     563        mixShow := -1 // building site
     564      else
     565        mixShow := mix;
     566      if (Tribe[Owner].ModelPicture[mixShow].HGr = 0) and
     567        (@OnInitEnemyModel <> nil) then
     568        if not OnInitEnemyModel(emix) then
     569          exit;
     570      xsh := Tribe[Owner].ModelPicture[mixShow].xShield;
     571      ysh := Tribe[Owner].ModelPicture[mixShow].yShield;
     572{$IFNDEF SCR} if Status and usStay <> 0 then
     573        j := 19
     574      else if Status and usRecover <> 0 then
     575        j := 16
     576      else if Status and (usGoto or usEnhance) = usGoto or usEnhance then
     577        j := 18
     578      else if Status and usEnhance <> 0 then
     579        j := 17
     580      else if Status and usGoto <> 0 then
     581        j := 20
     582      else {$ENDIF} if Job = jCity then
     583          j := jNone
     584        else
     585          j := Job;
     586      if Flags and unMulti <> 0 then
     587        Sprite(Tribe[Owner].symHGr, x + xsh - 1 + 4, y + ysh - 2, 14, 12,
     588          33 + Tribe[Owner].sympix mod 10 * 65,
     589          1 + Tribe[Owner].sympix div 10 * 49);
     590      Sprite(Tribe[Owner].symHGr, x + xsh - 1, y + ysh - 2, 14, 12,
     591        18 + Tribe[Owner].sympix mod 10 * 65,
     592        1 + Tribe[Owner].sympix div 10 * 49);
     593      FillRect(x + xsh, y + ysh + 5, 1 + Health * 11 div 100, 3,
     594        ColorOfHealth(Health));
     595      if j > 0 then
     596      begin
     597        xGr := 121 + j mod 7 * 9;
     598        yGr := 1 + j div 7 * 9;
     599        BitBlt(GrExt[HGrSystem].Mask, x + xsh + 3, y + ysh + 9, 8, 8, xGr,
     600          yGr, SRCAND);
     601        Sprite(HGrSystem, x + xsh + 2, y + ysh + 8, 8, 8, xGr, yGr);
     602      end;
     603      with Tribe[Owner].ModelPicture[mixShow] do
     604        Sprite(HGr, x, y, 64, 48, pix mod 10 * 65 + 1, pix div 10 * 49 + 1);
     605      if Flags and unFortified <> 0 then
     606      begin
     607        { OutDC:=FOutput.Canvas.Handle;
     608          DataDC:=GrExt[HGrTerrain].Data.Canvas.Handle;
     609          MaskDC:=GrExt[HGrTerrain].Mask.Canvas.Handle;
     610          TSprite(x,y+16,12*9+7); }
     611        Sprite(HGrStdUnits, x, y, xxu * 2, yyu * 2, 1 + 6 * (xxu * 2 + 1), 1);
     612      end
     613    end
     614end; { PaintUnit }
     615
     616procedure TIsoMap.PaintCity(x, y: integer; const CityInfo: TCityInfo;
     617  accessory: boolean);
     618var
     619  age, cHGr, cpix, xGr, xShield, yShield, LabelTextColor, LabelLength: integer;
     620  cpic: TCityPicture;
     621  s: string;
     622begin
     623  age := GetAge(CityInfo.Owner);
     624  if CityInfo.size < 5 then
     625    xGr := 0
     626  else if CityInfo.size < 9 then
     627    xGr := 1
     628  else if CityInfo.size < 13 then
     629    xGr := 2
     630  else
     631    xGr := 3;
     632  Tribe[CityInfo.Owner].InitAge(age);
     633  if age < 2 then
     634  begin
     635    cHGr := Tribe[CityInfo.Owner].cHGr;
     636    cpix := Tribe[CityInfo.Owner].cpix;
     637    if (ciWalled and CityInfo.Flags = 0) or
     638      (GrExt[cHGr].Data.Canvas.Pixels[(xGr + 4) * 65, cpix * 49 + 48] = $00FFFF)
     639    then
     640      Sprite(cHGr, x - xxc, y - 2 * yyc, xxc * 2, yyc * 3,
     641        xGr * (xxc * 2 + 1) + 1, 1 + cpix * (yyc * 3 + 1));
     642    if ciWalled and CityInfo.Flags <> 0 then
     643      Sprite(cHGr, x - xxc, y - 2 * yyc, xxc * 2, yyc * 3,
     644        (xGr + 4) * (xxc * 2 + 1) + 1, 1 + cpix * (yyc * 3 + 1));
     645  end
     646  else
     647  begin
     648    if ciWalled and CityInfo.Flags <> 0 then
     649      Sprite(HGrCities, x - xxt, y - 2 * yyt, 2 * xxt, 3 * yyt,
     650        (xGr + 4) * (2 * xxt + 1) + 1, 1 + (age - 2) * (3 * yyt + 1))
     651    else
     652      Sprite(HGrCities, x - xxt, y - 2 * yyt, 2 * xxt, 3 * yyt,
     653        xGr * (2 * xxt + 1) + 1, 1 + (age - 2) * (3 * yyt + 1));
     654  end;
     655
     656  if not accessory then
     657    exit;
     658
     659  { if ciCapital and CityInfo.Flags<>0 then
     660    Sprite(Tribe[CityInfo.Owner].symHGr,x+cpic.xf,y-13+cpic.yf,13,14,
     661    1+Tribe[CityInfo.Owner].sympix mod 10 *65,
     662    1+Tribe[CityInfo.Owner].sympix div 10 *49); {capital -- paint flag }
     663
     664  if MyMap[CityInfo.Loc] and fObserved <> 0 then
     665  begin
     666    if age < 2 then
     667    begin
     668      cpic := Tribe[CityInfo.Owner].CityPicture[xGr];
     669      xShield := x - xxc + cpic.xShield;
     670      yShield := y - 2 * yyc + cpic.yShield;
     671    end
     672    else
     673    begin
     674      cpic := CitiesPictures[age, xGr];
     675      xShield := x - xxt + cpic.xShield;
     676      yShield := y - 2 * yyt + cpic.yShield;
     677    end;
     678    s := IntToStr(CityInfo.size);
     679    LabelLength := FOutput.Canvas.TextWidth(s);
     680    FillRect(xShield, yShield, LabelLength + 4, 16, $000000);
     681    if MyMap[CityInfo.Loc] and (fUnit or fObserved) = fObserved then
     682      // empty city
     683      LabelTextColor := Tribe[CityInfo.Owner].Color
     684    else
     685    begin
     686      FillRect(xShield + 1, yShield + 1, LabelLength + 2, 14,
     687        Tribe[CityInfo.Owner].Color);
     688      LabelTextColor := $000000;
     689    end;
     690    Textout(xShield + 2, yShield - 1, LabelTextColor, s);
     691  end
     692end; { PaintCity }
     693
     694function PoleTile(Loc: integer): integer;
     695begin { virtual pole tile }
     696  result := fUNKNOWN;
     697  if Loc < -2 * G.lx then
     698  else if Loc < -G.lx then
     699  begin
     700    if (MyMap[dLoc(Loc, 0, 2)] and fTerrain <> fUNKNOWN) and
     701      (MyMap[dLoc(Loc, -2, 2)] and fTerrain <> fUNKNOWN) and
     702      (MyMap[dLoc(Loc, 2, 2)] and fTerrain <> fUNKNOWN) then
     703      result := fArctic;
     704    if (MyMap[dLoc(Loc, 0, 2)] and fObserved <> 0) and
     705      (MyMap[dLoc(Loc, -2, 2)] and fObserved <> 0) and
     706      (MyMap[dLoc(Loc, 2, 2)] and fObserved <> 0) then
     707      result := result or fObserved
     708  end
     709  else if Loc < 0 then
     710  begin
     711    if (MyMap[dLoc(Loc, -1, 1)] and fTerrain <> fUNKNOWN) and
     712      (MyMap[dLoc(Loc, 1, 1)] and fTerrain <> fUNKNOWN) then
     713      result := fArctic;
     714    if (MyMap[dLoc(Loc, -1, 1)] and fObserved <> 0) and
     715      (MyMap[dLoc(Loc, 1, 1)] and fObserved <> 0) then
     716      result := result or fObserved
     717  end
     718  else if Loc < G.lx * (G.ly + 1) then
     719  begin
     720    if (MyMap[dLoc(Loc, -1, -1)] and fTerrain <> fUNKNOWN) and
     721      (MyMap[dLoc(Loc, 1, -1)] and fTerrain <> fUNKNOWN) then
     722      result := fArctic;
     723    if (MyMap[dLoc(Loc, -1, -1)] and fObserved <> 0) and
     724      (MyMap[dLoc(Loc, 1, -1)] and fObserved <> 0) then
     725      result := result or fObserved
     726  end
     727  else if Loc < G.lx * (G.ly + 2) then
     728  begin
     729    if (MyMap[dLoc(Loc, 0, -2)] and fTerrain <> fUNKNOWN) and
     730      (MyMap[dLoc(Loc, -2, -2)] and fTerrain <> fUNKNOWN) and
     731      (MyMap[dLoc(Loc, 2, -2)] and fTerrain <> fUNKNOWN) then
     732      result := fArctic;
     733    if (MyMap[dLoc(Loc, 0, -2)] and fObserved <> 0) and
     734      (MyMap[dLoc(Loc, -2, -2)] and fObserved <> 0) and
     735      (MyMap[dLoc(Loc, 2, -2)] and fObserved <> 0) then
     736      result := result or fObserved
     737  end
     738end;
     739
     740const
     741  Dirx: array [0 .. 7] of integer = (1, 2, 1, 0, -1, -2, -1, 0);
     742  Diry: array [0 .. 7] of integer = (-1, 0, 1, 2, 1, 0, -1, -2);
     743
     744function TIsoMap.Connection4(Loc, Mask, Value: integer): integer;
     745begin
     746  result := 0;
     747  if dLoc(Loc, 1, -1) >= 0 then
     748  begin
     749    if MyMap[dLoc(Loc, 1, -1)] and Mask = Cardinal(Value) then
     750      inc(result, 1);
     751    if MyMap[dLoc(Loc, -1, -1)] and Mask = Cardinal(Value) then
     752      inc(result, 8);
     753  end;
     754  if dLoc(Loc, 1, 1) < G.lx * G.ly then
     755  begin
     756    if MyMap[dLoc(Loc, 1, 1)] and Mask = Cardinal(Value) then
     757      inc(result, 2);
     758    if MyMap[dLoc(Loc, -1, 1)] and Mask = Cardinal(Value) then
     759      inc(result, 4);
     760  end
     761end;
     762
     763function TIsoMap.Connection8(Loc, Mask: integer): integer;
     764var
     765  Dir, ConnLoc: integer;
     766begin
     767  result := 0;
     768  for Dir := 0 to 7 do
     769  begin
     770    ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]);
     771    if (ConnLoc >= 0) and (ConnLoc < G.lx * G.ly) and
     772      (MyMap[ConnLoc] and Mask <> 0) then
     773      inc(result, 1 shl Dir);
     774  end
     775end;
     776
     777function TIsoMap.OceanConnection(Loc: integer): integer;
     778var
     779  Dir, ConnLoc: integer;
     780begin
     781  result := 0;
     782  for Dir := 0 to 7 do
     783  begin
     784    ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]);
     785    if (ConnLoc < 0) or (ConnLoc >= G.lx * G.ly) or
     786      ((MyMap[ConnLoc] - 2) and fTerrain < 13) then
     787      inc(result, 1 shl Dir);
     788  end
     789end;
     790
     791procedure TIsoMap.PaintShore(x, y, Loc: integer);
     792var
     793  Conn, Tile: integer;
     794begin
     795  if (y <= FTop - yyt * 2) or (y > FBottom) or (x <= FLeft - xxt * 2) or
     796    (x > FRight) then
     797    exit;
     798  if (Loc < 0) or (Loc >= G.lx * G.ly) then
     799    exit;
     800  Tile := MyMap[Loc];
     801  if Tile and fTerrain >= fGrass then
     802    exit;
     803  Conn := OceanConnection(Loc);
     804  if Conn = 0 then
     805    exit;
     806
     807  BitBlt(GrExt[HGrTerrain].Data, x + xxt div 2, y, xxt, yyt,
     808    1 + (Conn shr 6 + Conn and 1 shl 2) * (xxt * 2 + 1),
     809    1 + yyt + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT);
     810  BitBlt(GrExt[HGrTerrain].Data, x + xxt, y + yyt div 2, xxt, yyt,
     811    1 + (Conn and 7) * (xxt * 2 + 1) + xxt,
     812    1 + yyt * 2 + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT);
     813  BitBlt(GrExt[HGrTerrain].Data, x + xxt div 2, y + yyt, xxt, yyt,
     814    1 + (Conn shr 2 and 7) * (xxt * 2 + 1) + xxt,
     815    1 + yyt + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT);
     816  BitBlt(GrExt[HGrTerrain].Data, x, y + yyt div 2, xxt, yyt,
     817    1 + (Conn shr 4 and 7) * (xxt * 2 + 1),
     818    1 + yyt * 2 + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT);
     819  Conn := Connection4(Loc, fTerrain, fUNKNOWN); { dither to black }
     820  if Conn and 1 <> 0 then
     821    BitBlt(GrExt[HGrTerrain].Mask, x + xxt, y, xxt, yyt, 1 + 7 * (xxt * 2 + 1) +
     822      xxt, 1 + yyt + 15 * (yyt * 3 + 1), SRCAND);
     823  if Conn and 2 <> 0 then
     824    BitBlt(GrExt[HGrTerrain].Mask, x + xxt, y + yyt, xxt, yyt,
     825      1 + 7 * (xxt * 2 + 1) + xxt, 1 + yyt * 2 + 15 * (yyt * 3 + 1), SRCAND);
     826  if Conn and 4 <> 0 then
     827    BitBlt(GrExt[HGrTerrain].Mask, x, y + yyt, xxt, yyt, 1 + 7 * (xxt * 2 + 1),
     828      1 + yyt * 2 + 15 * (yyt * 3 + 1), SRCAND);
     829  if Conn and 8 <> 0 then
     830    BitBlt(GrExt[HGrTerrain].Mask, x, y, xxt, yyt, 1 + 7 * (xxt * 2 + 1),
     831      1 + yyt + 15 * (yyt * 3 + 1), SRCAND);
     832end;
     833
     834procedure TIsoMap.PaintTileExtraTerrain(x, y, Loc: integer);
     835var
     836  Dir, Conn, RRConn, yGr, Tile, yLoc: integer;
     837begin
     838  if (Loc < 0) or (Loc >= G.lx * G.ly) or (y <= -yyt * 2) or
     839    (y > FOutput.Height) or (x <= -xxt * 2) or (x > FOutput.Width) then
     840    exit;
     841  Tile := MyMap[Loc];
     842  if Tile and fTerrain = fForest then
     843  begin
     844    yLoc := Loc div G.lx;
     845    if IsJungle(yLoc) then
     846      yGr := 18
     847    else
     848      yGr := 3;
     849    Conn := Connection4(Loc, fTerrain, Tile and fTerrain);
     850    if (yLoc = (G.ly - 2) div 4) or (G.ly - 1 - yLoc = (G.ly + 2) div 4) then
     851      Conn := Conn and not 6 // no connection to south
     852    else if (yLoc = (G.ly + 2) div 4) or (G.ly - 1 - yLoc = (G.ly - 2) div 4)
     853    then
     854      Conn := Conn and not 9; // no connection to north
     855    TSprite(x, y, Conn mod 8 + (yGr + Conn div 8) * 9);
     856  end
     857  else if Tile and fTerrain in [fHills, fMountains, fForest] then
     858  begin
     859    yGr := 3 + 2 * (Tile and fTerrain - fForest);
     860    Conn := Connection4(Loc, fTerrain, Tile and fTerrain);
     861    TSprite(x, y, Conn mod 8 + (yGr + Conn div 8) * 9);
     862  end
     863  else if Tile and fDeadLands <> 0 then
     864    TSprite(x, y, 2 * 9 + 6);
     865
     866  if ShowObjects then
     867  begin
     868    if Tile and fTerImp = tiFarm then
     869      TSprite(x, y, 109) { farmland }
     870    else if Tile and fTerImp = tiIrrigation then
     871      TSprite(x, y, 108); // irrigation
     872  end;
     873  if Tile and fRiver <> 0 then
     874  begin
     875    Conn := Connection4(Loc, fRiver, fRiver) or
     876      Connection4(Loc, fTerrain, fShore) or Connection4(Loc, fTerrain,
     877      fUNKNOWN);
     878    TSprite(x, y, Conn mod 8 + (13 + Conn div 8) * 9);
     879  end;
     880
     881  if Tile and fTerrain < fGrass then
     882  begin
     883    Conn := Connection4(Loc, fRiver, fRiver);
     884    for Dir := 0 to 3 do
     885      if Conn and (1 shl Dir) <> 0 then { river mouths }
     886        TSprite(x, y, 15 * 9 + Dir);
     887    if ShowObjects then
     888    begin
     889      Conn := Connection8(Loc, fCanal);
     890      for Dir := 0 to 7 do
     891        if Conn and (1 shl Dir) <> 0 then { canal mouths }
     892          TSprite(x, y, 20 * 9 + 1 + Dir);
     893    end
     894  end;
     895
     896  if ShowObjects then
     897  begin
     898    if (Tile and fCanal <> 0) or (Tile and fCity <> 0) then
     899    begin // paint canal connections
     900      Conn := Connection8(Loc, fCanal or fCity);
     901      if Tile and fCanal <> 0 then
     902        Conn := Conn or ($FF - OceanConnection(Loc));
     903      if Conn = 0 then
     904      begin
     905        if Tile and fCanal <> 0 then
     906          TSprite(x, y, 99)
     907      end
     908      else
     909        for Dir := 0 to 7 do
     910          if (1 shl Dir) and Conn <> 0 then
     911            TSprite(x, y, 100 + Dir);
     912    end;
     913    if Tile and (fRR or fCity) <> 0 then
     914      RRConn := Connection8(Loc, fRR or fCity)
     915    else
     916      RRConn := 0;
     917    if Tile and (fRoad or fRR or fCity) <> 0 then
     918    begin // paint road connections
     919      Conn := Connection8(Loc, fRoad or fRR or fCity) and not RRConn;
     920      if (Conn = 0) and (Tile and (fRR or fCity) = 0) then
     921        TSprite(x, y, 81)
     922      else if Conn > 0 then
     923        for Dir := 0 to 7 do
     924          if (1 shl Dir) and Conn <> 0 then
     925            TSprite(x, y, 82 + Dir);
     926    end;
     927    // paint railroad connections
     928    if (Tile and fRR <> 0) and (RRConn = 0) then
     929      TSprite(x, y, 90)
     930    else if RRConn > 0 then
     931      for Dir := 0 to 7 do
     932        if (1 shl Dir) and RRConn <> 0 then
     933          TSprite(x, y, 91 + Dir);
     934  end;
     935end;
     936
     937// (x,y) is top left pixel of (2*xxt,3*yyt) rectangle
     938procedure TIsoMap.PaintTileObjects(x, y, Loc, CityLoc, CityOwner: integer;
     939  UseBlink: boolean);
     940type
     941  TLine = array [0 .. 9 * 65, 0 .. 2] of Byte;
     942var
     943  p1, p2, uix, cix, dy, Loc1, Tile, Multi, Destination: integer;
     944  CityInfo: TCityInfo;
     945  UnitInfo: TUnitInfo;
     946  fog: boolean;
     947
     948  procedure NameCity;
     949  var
     950    cix, xs, w: integer;
     951    BehindCityInfo: TCityInfo;
     952    s: string;
     953    IsCapital: boolean;
     954  begin
     955    BehindCityInfo.Loc := Loc - 2 * G.lx;
     956    if ShowCityNames and (Options and (1 shl moEditMode) = 0) and
     957      (BehindCityInfo.Loc >= 0) and (BehindCityInfo.Loc < G.lx * G.ly) and
     958      (MyMap[BehindCityInfo.Loc] and fCity <> 0) then
     959    begin
     960      GetCityInfo(BehindCityInfo.Loc, cix, BehindCityInfo);
     961      IsCapital := BehindCityInfo.Flags and ciCapital <> 0;
     962      { if Showuix and (cix>=0) then s:=IntToStr(cix)
     963        else } s := CityName(BehindCityInfo.ID);
     964      w := FOutput.Canvas.TextWidth(s);
     965      xs := x + xxt - (w + 1) div 2;
     966      if IsCapital then
     967        FOutput.Canvas.Font.Style := FOutput.Canvas.Font.Style + [fsUnderline];
     968      Textout(xs + 1, y - 9, $000000, s);
     969      Textout(xs, y - 10, $FFFFFF, s);
     970      if IsCapital then
     971        FOutput.Canvas.Font.Style := FOutput.Canvas.Font.Style - [fsUnderline];
     972    end;
     973  end;
     974
     975  procedure ShowSpacePort;
     976  begin
     977    if ShowObjects and (Options and (1 shl moEditMode) = 0) and
     978      (Tile and fCity <> 0) and (CityInfo.Flags and ciSpacePort <> 0) then
     979      TSprite(x + xxt, y - 6, 12 * 9 + 5);
     980  end;
     981
     982  procedure PaintBorder;
     983  var
     984    dx, dy: integer;
     985    Line: ^TLine;
     986  begin
     987    if ShowBorder and (Loc >= 0) and (Loc < G.lx * G.ly) and
     988      (Tile and fTerrain <> fUNKNOWN) then
     989    begin
     990      p1 := MyRO.Territory[Loc];
     991      if (p1 >= 0) and (ShowMyBorder or (p1 <> me)) then
     992      begin
     993        if BordersOK and (1 shl p1) = 0 then
    412994        begin
    413           NoMap.Free;
    414           NoMap := nil;
    415           LandPatch.Free;
    416           LandPatch := nil;
    417           OceanPatch.Free;
    418           OceanPatch := nil;
    419           Borders.Free;
    420           Borders := nil;
     995          LCLIntf.BitBlt(Borders.Canvas.Handle, 0, p1 * (yyt * 2), xxt * 2,
     996            yyt * 2, GrExt[HGrTerrain].Data.Canvas.Handle,
     997            1 + 8 * (xxt * 2 + 1), 1 + yyt + 16 * (yyt * 3 + 1), SRCCOPY);
     998          Borders.BeginUpdate;
     999          for dy := 0 to yyt * 2 - 1 do
     1000          begin
     1001            Line := Borders.ScanLine[p1 * (yyt * 2) + dy];
     1002            for dx := 0 to xxt * 2 - 1 do
     1003              if Line[dx, 0] = 99 then
     1004              begin
     1005                Line[dx, 0] := Tribe[p1].Color shr 16 and $FF;
     1006                Line[dx, 1] := Tribe[p1].Color shr 8 and $FF;
     1007                Line[dx, 2] := Tribe[p1].Color and $FF;
     1008              end
     1009          end;
     1010          Borders.EndUpdate;
     1011          BordersOK := BordersOK or 1 shl p1;
    4211012        end;
    422 
    423         procedure Reset;
     1013        for dy := 0 to 1 do
     1014          for dx := 0 to 1 do
     1015          begin
     1016            Loc1 := dLoc(Loc, dx * 2 - 1, dy * 2 - 1);
     1017            begin
     1018              if (Loc1 < 0) or (Loc1 >= G.lx * G.ly) then
     1019                p2 := -1
     1020              else if MyMap[Loc1] and fTerrain = fUNKNOWN then
     1021                p2 := p1
     1022              else
     1023                p2 := MyRO.Territory[Loc1];
     1024              if p2 <> p1 then
     1025              begin
     1026                BitBlt(GrExt[HGrTerrain].Mask, x + dx * xxt, y + dy * yyt, xxt,
     1027                  yyt, 1 + 8 * (xxt * 2 + 1) + dx * xxt,
     1028                  1 + yyt + 16 * (yyt * 3 + 1) + dy * yyt, SRCAND);
     1029                BitBlt(Borders, x + dx * xxt, y + dy * yyt, xxt, yyt, dx * xxt,
     1030                  p1 * (yyt * 2) + dy * yyt, SRCPAINT);
     1031              end
     1032            end;
     1033          end
     1034      end
     1035    end;
     1036  end;
     1037
     1038begin
     1039  if (Loc < 0) or (Loc >= G.lx * G.ly) then
     1040    Tile := PoleTile(Loc)
     1041  else
     1042    Tile := MyMap[Loc];
     1043  if ShowObjects and (Options and (1 shl moEditMode) = 0) and
     1044    (Tile and fCity <> 0) then
     1045    GetCityInfo(Loc, cix, CityInfo);
     1046  if (y <= FTop - yyt * 2) or (y > FBottom) or (x <= FLeft - xxt * 2) or
     1047    (x > FRight) then
     1048  begin
     1049    NameCity;
     1050    ShowSpacePort;
     1051    exit;
     1052  end;
     1053  if Tile and fTerrain = fUNKNOWN then
     1054  begin
     1055    NameCity;
     1056    ShowSpacePort;
     1057    exit
     1058  end; { square not discovered }
     1059
     1060  if not(FoW and (Tile and fObserved = 0)) then
     1061    PaintBorder;
     1062
     1063  if (Loc >= 0) and (Loc < G.lx * G.ly) and (Loc = FAdviceLoc) then
     1064    TSprite(x, y, 7 + 9 * 2);
     1065
     1066  if (Loc >= 0) and (Loc < G.lx * G.ly) and (Tile and fSpecial <> 0)
     1067  then { special ressources }
     1068  begin
     1069    dy := Loc div G.lx;
     1070    if Tile and fTerrain < fForest then
     1071      TSprite(x, y, Tile and fTerrain + (Tile and fSpecial shr 5) * 9)
     1072    else if (Tile and fTerrain = fForest) and IsJungle(dy) then
     1073      TSprite(x, y, 8 + 17 * 9 + (Tile and fSpecial shr 5) * 9)
     1074    else
     1075      TSprite(x, y, 8 + 2 * 9 + ((Tile and fTerrain - fForest) * 2 + Tile and
     1076        fSpecial shr 5) * 9);
     1077  end;
     1078
     1079  if ShowObjects then
     1080  begin
     1081    if Tile and fTerImp = tiMine then
     1082      TSprite(x, y, 2 + 9 * 12);
     1083    if Tile and fTerImp = tiBase then
     1084      TSprite(x, y, 4 + 9 * 12);
     1085    if Tile and fPoll <> 0 then
     1086      TSprite(x, y, 6 + 9 * 12);
     1087    if Tile and fTerImp = tiFort then
     1088    begin
     1089      TSprite(x, y, 7 + 9 * 12);
     1090      if Tile and fObserved = 0 then
     1091        TSprite(x, y, 3 + 9 * 12);
     1092    end;
     1093  end;
     1094  if Tile and fDeadLands <> 0 then
     1095    TSprite(x, y, (12 + Tile shr 25 and 3) * 9 + 8);
     1096
     1097  if Options and (1 shl moEditMode) <> 0 then
     1098    fog := (Loc < 0) or (Loc >= G.lx * G.ly)
     1099    // else if CityLoc>=0 then
     1100    // fog:= (Loc<0) or (Loc>=G.lx*G.ly) or (Distance(Loc,CityLoc)>5)
     1101  else if ShowGrWall then
     1102    fog := Tile and fGrWall = 0
     1103  else
     1104    fog := FoW and (Tile and fObserved = 0);
     1105  if fog and ShowObjects then
     1106    if Loc < -G.lx then
     1107      Sprite(HGrTerrain, x, y + yyt, xxt * 2, yyt, 1 + 6 * (xxt * 2 + 1),
     1108        1 + yyt * 2 + 15 * (yyt * 3 + 1))
     1109    else if Loc >= G.lx * (G.ly + 1) then
     1110      Sprite(HGrTerrain, x, y, xxt * 2, yyt, 1 + 6 * (xxt * 2 + 1),
     1111        1 + yyt + 15 * (yyt * 3 + 1))
     1112    else
     1113      TSprite(x, y, 6 + 9 * 15, xxt <> 33);
     1114
     1115  if FoW and (Tile and fObserved = 0) then
     1116    PaintBorder;
     1117
     1118{$IFNDEF SCR}
     1119  // paint goto destination mark
     1120  if DestinationMarkON and (CityOwner < 0) and (UnFocus >= 0) and
     1121    (MyUn[UnFocus].Status and usGoto <> 0) then
     1122  begin
     1123    Destination := MyUn[UnFocus].Status shr 16;
     1124    if (Destination = Loc) and (Destination <> MyUn[UnFocus].Loc) then
     1125      if not UseBlink or BlinkOn then
     1126        TSprite(x, y, 8 + 9 * 1)
     1127      else
     1128        TSprite(x, y, 8 + 9 * 2)
     1129  end;
     1130{$ENDIF}
     1131  if Options and (1 shl moEditMode) <> 0 then
     1132  begin
     1133    if Tile and fPrefStartPos <> 0 then
     1134      TSprite(x, y, 0 + 9 * 1)
     1135    else if Tile and fStartPos <> 0 then
     1136      TSprite(x, y, 0 + 9 * 2);
     1137  end
     1138  else if ShowObjects then
     1139  begin
     1140    { if (CityLoc<0) and (UnFocus>=0) and (Loc=MyUn[UnFocus].Loc) then
     1141      if BlinkOn then TSprite(x,y,8+9*0)
     1142      else TSprite(x,y,8+9*1); }
     1143
     1144    NameCity;
     1145    ShowSpacePort;
     1146    if Tile and fCity <> 0 then
     1147      PaintCity(x + xxt, y + yyt, CityInfo, CityOwner < 0);
     1148
     1149    if (Tile and fUnit <> 0) and (Loc <> AttLoc) and
     1150      ((Loc <> DefLoc) or (DefHealth <> 0))
     1151{$IFNDEF SCR} and ((CityOwner >= 0) or (UnFocus < 0) or not UseBlink or
     1152      BlinkOn or (Loc <> MyUn[UnFocus].Loc)){$ENDIF}
     1153      and ((Tile and fCity <> fCity) or (Loc = DefLoc)
     1154{$IFNDEF SCR} or (not UseBlink or BlinkOn) and (UnFocus >= 0) and
     1155      (Loc = MyUn[UnFocus].Loc){$ENDIF}) then
     1156    begin { unit }
     1157      GetUnitInfo(Loc, uix, UnitInfo);
     1158      if (Loc = DefLoc) and (DefHealth >= 0) then
     1159        UnitInfo.Health := DefHealth;
     1160      if (UnitInfo.Owner <> CityOwner) and
     1161        not((CityOwner = me) and (MyRO.Treaty[UnitInfo.Owner] = trAlliance))
     1162      then
     1163{$IFNDEF SCR} if (UnFocus >= 0) and (Loc = MyUn[UnFocus].Loc) then { active unit }
    4241164        begin
    425           BordersOK := 0;
     1165          Multi := UnitInfo.Flags and unMulti;
     1166          MakeUnitInfo(me, MyUn[UnFocus], UnitInfo);
     1167          UnitInfo.Flags := UnitInfo.Flags or Multi;
     1168          PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo,
     1169            MyUn[UnFocus].Status);
     1170        end
     1171        else if UnitInfo.Owner = me then
     1172        begin
     1173          if ClientMode = cMovieTurn then
     1174            PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 0)
     1175            // status is not set with precise timing during loading
     1176          else
     1177            PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo,
     1178              MyUn[uix].Status);
     1179          // if Showuix then Textout(x+16,y+5,$80FF00,IntToStr(uix));
     1180        end
     1181        else {$ENDIF} PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 0);
     1182    end
     1183    else if Tile and fHiddenUnit <> 0 then
     1184      Sprite(HGrStdUnits, x + (xxt - xxu), y + (yyt - yyu_anchor), xxu * 2,
     1185        yyu * 2, 1 + 5 * (xxu * 2 + 1), 1)
     1186    else if Tile and fStealthUnit <> 0 then
     1187      Sprite(HGrStdUnits, x + (xxt - xxu), y + (yyt - yyu_anchor), xxu * 2,
     1188        yyu * 2, 1 + 5 * (xxu * 2 + 1), 1 + 1 * (yyu * 2 + 1))
     1189  end;
     1190
     1191  if ShowObjects and (Tile and fTerImp = tiFort) and (Tile and fObserved <> 0)
     1192  then
     1193    TSprite(x, y, 3 + 9 * 12);
     1194
     1195  if (Loc >= 0) and (Loc < G.lx * G.ly) then
     1196    if ShowLoc then
     1197      Textout(x + xxt - 16, y + yyt - 9, $FFFF00, IntToStr(Loc))
     1198    else if ShowDebug and (DebugMap <> nil) and (Loc >= 0) and
     1199      (Loc < G.lx * G.ly) and (DebugMap[Loc] <> 0) then
     1200      Textout(x + xxt - 16, y + yyt - 9, $00E0FF,
     1201        IntToStr(integer(DebugMap[Loc])))
     1202end; { PaintTileObjects }
     1203
     1204procedure TIsoMap.PaintGrid(x, y, nx, ny: integer);
     1205
     1206  procedure ClippedLine(dx0, dy0: integer; mirror: boolean);
     1207  var
     1208    x0, x1, dxmin, dymin, dxmax, dymax, n: integer;
     1209  begin
     1210    with FOutput.Canvas do
     1211    begin
     1212      dxmin := (FLeft - x) div xxt;
     1213      dymin := (RealTop - y) div yyt;
     1214      dxmax := (FRight - x - 1) div xxt + 1;
     1215      dymax := (RealBottom - y - 1) div yyt + 1;
     1216      n := dymax - dy0;
     1217      if mirror then
     1218      begin
     1219        if dx0 - dxmin < n then
     1220          n := dx0 - dxmin;
     1221        if dx0 > dxmax then
     1222        begin
     1223          n := n - (dx0 - dxmax);
     1224          dy0 := dy0 + (dx0 - dxmax);
     1225          dx0 := dxmax
    4261226        end;
    427 
    428         constructor TIsoMap.Create;
     1227        if dy0 < dymin then
    4291228        begin
    430           inherited;
    431           FLeft := 0;
    432           FTop := 0;
    433           FRight := 0;
    434           FBottom := 0;
    435           AttLoc := -1;
    436           DefLoc := -1;
    437           FAdviceLoc := -1;
     1229          n := n - (dymin - dy0);
     1230          dx0 := dx0 - (dymin - dy0);
     1231          dy0 := dymin
    4381232        end;
    439 
    440         procedure TIsoMap.SetOutput(Output: TBitmap);
     1233      end
     1234      else
     1235      begin
     1236        if dxmax - dx0 < n then
     1237          n := dxmax - dx0;
     1238        if dx0 < dxmin then
    4411239        begin
    442           FOutput := Output;
    443           FLeft := 0;
    444           FTop := 0;
    445           FRight := FOutput.Width;
    446           FBottom := FOutput.Height;
     1240          n := n - (dxmin - dx0);
     1241          dy0 := dy0 + (dxmin - dx0);
     1242          dx0 := dxmin
    4471243        end;
    448 
    449         procedure TIsoMap.SetPaintBounds(Left, Top, Right, Bottom: integer);
     1244        if dy0 < dymin then
    4501245        begin
    451           FLeft := Left;
    452           FTop := Top;
    453           FRight := Right;
    454           FBottom := Bottom;
     1246          n := n - (dymin - dy0);
     1247          dx0 := dx0 + (dymin - dy0);
     1248          dy0 := dymin
    4551249        end;
    456 
    457         procedure TIsoMap.FillRect(x, y, Width, Height, Color: integer);
    458         begin
    459           if x < FLeft then
     1250      end;
     1251      if n <= 0 then
     1252        exit;
     1253      if mirror then
     1254      begin
     1255        x0 := x + dx0 * xxt - 1;
     1256        x1 := x + (dx0 - n) * xxt - 1;
     1257      end
     1258      else
     1259      begin
     1260        x0 := x + dx0 * xxt;
     1261        x1 := x + (dx0 + n) * xxt;
     1262      end;
     1263      moveto(x0, y + dy0 * yyt);
     1264      lineto(x1, y + (dy0 + n) * yyt);
     1265    end
     1266  end;
     1267
     1268var
     1269  i: integer;
     1270begin
     1271  FOutput.Canvas.pen.Color := $000000; // $FF shl (8*random(3));
     1272  for i := 0 to nx div 2 do
     1273    ClippedLine(i * 2, 0, false);
     1274  for i := 1 to (nx + 1) div 2 do
     1275    ClippedLine(i * 2, 0, true);
     1276  for i := 0 to ny div 2 do
     1277  begin
     1278    ClippedLine(0, 2 * i + 2, false);
     1279    ClippedLine(nx + 1, 2 * i + 1 + nx and 1, true);
     1280  end;
     1281end;
     1282
     1283procedure TIsoMap.Paint(x, y, Loc, nx, ny, CityLoc, CityOwner: integer;
     1284  UseBlink: boolean; CityAllowClick: boolean);
     1285
     1286  function IsShoreTile(Loc: integer): boolean;
     1287  const
     1288    Dirx: array [0 .. 7] of integer = (1, 2, 1, 0, -1, -2, -1, 0);
     1289    Diry: array [0 .. 7] of integer = (-1, 0, 1, 2, 1, 0, -1, -2);
     1290  var
     1291    Dir, ConnLoc: integer;
     1292  begin
     1293    result := false;
     1294    for Dir := 0 to 7 do
     1295    begin
     1296      ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]);
     1297      if (ConnLoc < 0) or (ConnLoc >= G.lx * G.ly) or
     1298        ((MyMap[ConnLoc] - 2) and fTerrain < 13) then
     1299        result := true
     1300    end
     1301  end;
     1302
     1303  procedure ShadeOutside(x0, y0, x1, y1, xm, ym: integer);
     1304  const
     1305    rShade = 3.75;
     1306
     1307    procedure MakeDark(Line: pointer; length: integer);
     1308    type
     1309      TCardArray = array [0 .. 9999] of Cardinal;
     1310      PCardArray = ^TCardArray;
     1311      TByteArray = array [0 .. 9999] of Byte;
     1312      PByteArray = ^TByteArray;
     1313    var
     1314      i, rest: integer;
     1315    begin
     1316      for i := length * 3 div 4 - 1 downto 0 do
     1317        PCardArray(Line)[i] := PCardArray(Line)[i] shr 1 and $7F7F7F7F;
     1318      rest := (length * 3 div 4) * 4;
     1319      for i := length * 3 mod 4 - 1 downto 0 do
     1320        PByteArray(Line)[rest + i] := PByteArray(Line)[rest + i] shr 1 and $7F;
     1321    end;
     1322
     1323  type
     1324    TLine = array [0 .. 99999, 0 .. 2] of Byte;
     1325  var
     1326    y, wBright: integer;
     1327    y_n, w_n: single;
     1328    Line: ^TLine;
     1329  begin
     1330    FOutput.BeginUpdate;
     1331    for y := y0 to y1 - 1 do
     1332    begin
     1333      Line := FOutput.ScanLine[y];
     1334      y_n := (y - ym) / yyt;
     1335      if abs(y_n) < rShade then
     1336      begin
     1337        w_n := sqrt(sqr(rShade) - sqr(y_n));
     1338        wBright := trunc(w_n * xxt + 0.5);
     1339        MakeDark(@Line[x0], xm - x0 - wBright);
     1340        MakeDark(@Line[xm + wBright], x1 - xm - wBright);
     1341      end
     1342      else
     1343        MakeDark(@Line[x0], x1 - x0);
     1344    end;
     1345    FOutput.EndUpdate;
     1346  end;
     1347
     1348  procedure CityGrid(xm, ym: integer);
     1349  var
     1350    i: integer;
     1351  begin
     1352    with FOutput.Canvas do
     1353    begin
     1354      if CityAllowClick then
     1355        pen.Color := $FFFFFF
     1356      else
     1357        pen.Color := $000000;
     1358      pen.Width := 1;
     1359      for i := 0 to 3 do
     1360      begin
     1361        moveto(xm - xxt * (4 - i), ym + yyt * (1 + i));
     1362        lineto(xm + xxt * (1 + i), ym - yyt * (4 - i));
     1363        moveto(xm - xxt * (4 - i), ym - yyt * (1 + i));
     1364        lineto(xm + xxt * (1 + i), ym + yyt * (4 - i));
     1365      end;
     1366      moveto(xm - xxt * 4, ym + yyt * 1);
     1367      lineto(xm - xxt * 1, ym + yyt * 4);
     1368      moveto(xm + xxt * 1, ym + yyt * 4);
     1369      lineto(xm + xxt * 4, ym + yyt * 1);
     1370      moveto(xm - xxt * 4, ym - yyt * 1);
     1371      lineto(xm - xxt * 1, ym - yyt * 4);
     1372      moveto(xm + xxt * 1, ym - yyt * 4);
     1373      lineto(xm + xxt * 4, ym - yyt * 1);
     1374      pen.Width := 1;
     1375    end
     1376  end;
     1377
     1378var
     1379  dx, dy, xm, ym, ALoc, BLoc, ATer, BTer, Aix, bix: integer;
     1380begin
     1381  FoW := true;
     1382  ShowLoc := Options and (1 shl moLocCodes) <> 0;
     1383  ShowDebug := pDebugMap >= 0;
     1384  ShowObjects := (CityOwner >= 0) or (Options and (1 shl moBareTerrain) = 0);
     1385  ShowCityNames := ShowObjects and (CityOwner < 0) and
     1386    (Options and (1 shl moCityNames) <> 0);
     1387  ShowBorder := true;
     1388  ShowMyBorder := CityOwner < 0;
     1389  ShowGrWall := (CityOwner < 0) and (Options and (1 shl moGreatWall) <> 0);
     1390  if ShowDebug then
     1391    Server(sGetDebugMap, me, pDebugMap, DebugMap)
     1392  else
     1393    DebugMap := nil;
     1394  with FOutput.Canvas do
     1395  begin
     1396    RealTop := y - ((Loc + 12345 * G.lx) div G.lx - 12345) * yyt;
     1397    RealBottom := y + (G.ly - ((Loc + 12345 * G.lx) div G.lx - 12345) +
     1398      3) * yyt;
     1399    Brush.Color := EmptySpaceColor;
     1400    if RealTop > FTop then
     1401      FillRect(Rect(FLeft, FTop, FRight, RealTop))
     1402    else
     1403      RealTop := FTop;
     1404    if RealBottom < FBottom then
     1405      FillRect(Rect(FLeft, RealBottom, FRight, FBottom))
     1406    else
     1407      RealBottom := FBottom;
     1408    Brush.Color := $000000;
     1409    FillRect(Rect(FLeft, RealTop, FRight, RealBottom));
     1410    Brush.Style := bsClear;
     1411  end;
     1412
     1413  for dy := 0 to ny + 1 do
     1414    if (Loc + dy * G.lx >= 0) and (Loc + (dy - 3) * G.lx < G.lx * G.ly) then
     1415      for dx := 0 to nx do
     1416      begin
     1417        ALoc := dLoc(Loc, dx - (dy + dx) and 1, dy - 2);
     1418        BLoc := dLoc(Loc, dx - (dy + dx + 1) and 1, dy - 1);
     1419        if (ALoc < 0) or (ALoc >= G.lx * G.ly) then
     1420          ATer := PoleTile(ALoc) and fTerrain
     1421        else
     1422          ATer := MyMap[ALoc] and fTerrain;
     1423        if (BLoc < 0) or (BLoc >= G.lx * G.ly) then
     1424          BTer := PoleTile(BLoc) and fTerrain
     1425        else
     1426          BTer := MyMap[BLoc] and fTerrain;
     1427
     1428        if (ATer <> fUNKNOWN) or (BTer <> fUNKNOWN) then
     1429          if ((ATer < fGrass) or (ATer = fUNKNOWN)) and
     1430            ((BTer < fGrass) or (BTer = fUNKNOWN)) then
    4601431          begin
    461             Width := Width - (FLeft - x);
    462             x := FLeft
    463           end;
    464           if y < FTop then
    465           begin
    466             Height := Height - (FTop - y);
    467             y := FTop
    468           end;
    469           if x + Width >= FRight then
    470             Width := FRight - x;
    471           if y + Height >= FBottom then
    472             Height := FBottom - y;
    473           if (Width <= 0) or (Height <= 0) then
    474             exit;
    475 
    476           with FOutput.Canvas do
    477           begin
    478             Brush.Color := Color;
    479             FillRect(Rect(x, y, x + Width, y + Height));
    480             Brush.Style := bsClear;
    481           end
    482         end;
    483 
    484         procedure TIsoMap.Textout(x, y, Color: integer; const s: string);
    485         begin
    486           FOutput.Canvas.Font.Color := Color;
    487           FOutput.Canvas.TextRect(Rect(FLeft, FTop, FRight, FBottom), x, y, s)
    488         end;
    489 
    490         procedure TIsoMap.BitBlt(Src: TBitmap; x, y, Width, Height, xSrc, ySrc,
    491           Rop: integer);
    492         begin
    493           if x < FLeft then
    494           begin
    495             Width := Width - (FLeft - x);
    496             xSrc := xSrc + (FLeft - x);
    497             x := FLeft
    498           end;
    499           if y < FTop then
    500           begin
    501             Height := Height - (FTop - y);
    502             ySrc := ySrc + (FTop - y);
    503             y := FTop
    504           end;
    505           if x + Width >= FRight then
    506             Width := FRight - x;
    507           if y + Height >= FBottom then
    508             Height := FBottom - y;
    509           if (Width <= 0) or (Height <= 0) then
    510             exit;
    511 
    512           LCLIntf.BitBlt(FOutput.Canvas.Handle, x, y, Width, Height,
    513             Src.Canvas.Handle, xSrc, ySrc, Rop);
    514         end;
    515 
    516         procedure TIsoMap.Sprite(HGr, xDst, yDst, Width, Height, xGr,
    517           yGr: integer);
    518         begin
    519           BitBlt(GrExt[HGr].Mask, xDst, yDst, Width, Height, xGr, yGr, SRCAND);
    520           BitBlt(GrExt[HGr].Data, xDst, yDst, Width, Height, xGr, yGr,
    521             SRCPAINT);
    522         end;
    523 
    524         procedure TIsoMap.TSprite(xDst, yDst, grix: integer;
    525           PureBlack: boolean = false);
    526         var
    527           Width, Height, xSrc, ySrc: integer;
    528         begin
    529           Width := TSpriteSize[grix].Right - TSpriteSize[grix].Left;
    530           Height := TSpriteSize[grix].Bottom - TSpriteSize[grix].Top;
    531           xSrc := 1 + grix mod 9 * (xxt * 2 + 1) + TSpriteSize[grix].Left;
    532           ySrc := 1 + grix div 9 * (yyt * 3 + 1) + TSpriteSize[grix].Top;
    533           xDst := xDst + TSpriteSize[grix].Left;
    534           yDst := yDst - yyt + TSpriteSize[grix].Top;
    535           if xDst < FLeft then
    536           begin
    537             Width := Width - (FLeft - xDst);
    538             xSrc := xSrc + (FLeft - xDst);
    539             xDst := FLeft
    540           end;
    541           if yDst < FTop then
    542           begin
    543             Height := Height - (FTop - yDst);
    544             ySrc := ySrc + (FTop - yDst);
    545             yDst := FTop
    546           end;
    547           if xDst + Width >= FRight then
    548             Width := FRight - xDst;
    549           if yDst + Height >= FBottom then
    550             Height := FBottom - yDst;
    551           if (Width <= 0) or (Height <= 0) then
    552             exit;
    553 
    554           LCLIntf.BitBlt(OutDC, xDst, yDst, Width, Height, MaskDC, xSrc,
    555             ySrc, SRCAND);
    556           if not PureBlack then
    557             LCLIntf.BitBlt(OutDC, xDst, yDst, Width, Height, DataDC, xSrc, ySrc,
    558               SRCPAINT);
    559         end;
    560 
    561         procedure TIsoMap.PaintUnit(x, y: integer; const UnitInfo: TUnitInfo;
    562           Status: integer);
    563         var
    564           xsh, ysh, xGr, yGr, j, mixShow: integer;
    565         begin
    566           with UnitInfo do
    567             if (Owner = me) or (emix <> $FFFF) then
     1432            if ATer = fUNKNOWN then
     1433              Aix := 0
     1434            else if IsShoreTile(ALoc) then
     1435              if ATer = fOcean then
     1436                Aix := -1
     1437              else
     1438                Aix := 1
     1439            else
     1440              Aix := ATer + 2;
     1441            if BTer = fUNKNOWN then
     1442              bix := 0
     1443            else if IsShoreTile(BLoc) then
     1444              if BTer = fOcean then
     1445                bix := -1
     1446              else
     1447                bix := 1
     1448            else
     1449              bix := BTer + 2;
     1450            if (Aix > 1) or (bix > 1) then
    5681451            begin
    569               if Job = jCity then
    570                 mixShow := -1 // building site
    571               else
    572                 mixShow := mix;
    573               if (Tribe[Owner].ModelPicture[mixShow].HGr = 0) and
    574                 (@OnInitEnemyModel <> nil) then
    575                 if not OnInitEnemyModel(emix) then
    576                   exit;
    577               xsh := Tribe[Owner].ModelPicture[mixShow].xShield;
    578               ysh := Tribe[Owner].ModelPicture[mixShow].yShield;
    579 {$IFNDEF SCR} if Status and usStay <> 0 then
    580                 j := 19
    581               else if Status and usRecover <> 0 then
    582                 j := 16
    583               else if Status and (usGoto or usEnhance) = usGoto or usEnhance
    584               then
    585                 j := 18
    586               else if Status and usEnhance <> 0 then
    587                 j := 17
    588               else if Status and usGoto <> 0 then
    589                 j := 20
    590               else {$ENDIF} if Job = jCity then
    591                   j := jNone
     1452              if Aix = -1 then
     1453                if bix = fOcean + 2 then
     1454                begin
     1455                  Aix := 0;
     1456                  bix := 0
     1457                end
    5921458                else
    593                   j := Job;
    594               if Flags and unMulti <> 0 then
    595                 Sprite(Tribe[Owner].symHGr, x + xsh - 1 + 4, y + ysh - 2, 14,
    596                   12, 33 + Tribe[Owner].sympix mod 10 * 65,
    597                   1 + Tribe[Owner].sympix div 10 * 49);
    598               Sprite(Tribe[Owner].symHGr, x + xsh - 1, y + ysh - 2, 14, 12,
    599                 18 + Tribe[Owner].sympix mod 10 * 65,
    600                 1 + Tribe[Owner].sympix div 10 * 49);
    601               FillRect(x + xsh, y + ysh + 5, 1 + Health * 11 div 100, 3,
    602                 ColorOfHealth(Health));
    603               if j > 0 then
    604               begin
    605                 xGr := 121 + j mod 7 * 9;
    606                 yGr := 1 + j div 7 * 9;
    607                 BitBlt(GrExt[HGrSystem].Mask, x + xsh + 3, y + ysh + 9, 8, 8,
    608                   xGr, yGr, SRCAND);
    609                 Sprite(HGrSystem, x + xsh + 2, y + ysh + 8, 8, 8, xGr, yGr);
    610               end;
    611               with Tribe[Owner].ModelPicture[mixShow] do
    612                 Sprite(HGr, x, y, 64, 48, pix mod 10 * 65 + 1,
    613                   pix div 10 * 49 + 1);
    614               if Flags and unFortified <> 0 then
    615               begin
    616                 { OutDC:=FOutput.Canvas.Handle;
    617                   DataDC:=GrExt[HGrTerrain].Data.Canvas.Handle;
    618                   MaskDC:=GrExt[HGrTerrain].Mask.Canvas.Handle;
    619                   TSprite(x,y+16,12*9+7); }
    620                 Sprite(HGrStdUnits, x, y, xxu * 2, yyu * 2,
    621                   1 + 6 * (xxu * 2 + 1), 1);
    622               end
     1459                begin
     1460                  Aix := 0;
     1461                  bix := 1
     1462                end
     1463              else if bix = -1 then
     1464                if Aix = fOcean + 2 then
     1465                begin
     1466                  Aix := 1;
     1467                  bix := 1
     1468                end
     1469                else
     1470                begin
     1471                  Aix := 1;
     1472                  bix := 0
     1473                end;
     1474              BitBlt(OceanPatch, x + dx * xxt, y + dy * yyt, xxt, yyt,
     1475                Aix * (xxt * 2) + (dx + dy + 1) and 1 * xxt, bix * yyt, SRCCOPY)
    6231476            end
    624         end; { PaintUnit }
    625 
    626         procedure TIsoMap.PaintCity(x, y: integer; const CityInfo: TCityInfo;
    627           accessory: boolean);
    628         var
    629           age, cHGr, cpix, xGr, xShield, yShield, LabelTextColor,
    630             LabelLength: integer;
    631           cpic: TCityPicture;
    632           s: string;
    633         begin
    634           age := GetAge(CityInfo.Owner);
    635           if CityInfo.size < 5 then
    636             xGr := 0
    637           else if CityInfo.size < 9 then
    638             xGr := 1
    639           else if CityInfo.size < 13 then
    640             xGr := 2
    641           else
    642             xGr := 3;
    643           Tribe[CityInfo.Owner].InitAge(age);
    644           if age < 2 then
    645           begin
    646             cHGr := Tribe[CityInfo.Owner].cHGr;
    647             cpix := Tribe[CityInfo.Owner].cpix;
    648             if (ciWalled and CityInfo.Flags = 0) or
    649               (GrExt[cHGr].Data.Canvas.Pixels[(xGr + 4) * 65, cpix * 49 + 48]
    650               = $00FFFF) then
    651               Sprite(cHGr, x - xxc, y - 2 * yyc, xxc * 2, yyc * 3,
    652                 xGr * (xxc * 2 + 1) + 1, 1 + cpix * (yyc * 3 + 1));
    653             if ciWalled and CityInfo.Flags <> 0 then
    654               Sprite(cHGr, x - xxc, y - 2 * yyc, xxc * 2, yyc * 3,
    655                 (xGr + 4) * (xxc * 2 + 1) + 1, 1 + cpix * (yyc * 3 + 1));
    6561477          end
    6571478          else
    6581479          begin
    659             if ciWalled and CityInfo.Flags <> 0 then
    660               Sprite(HGrCities, x - xxt, y - 2 * yyt, 2 * xxt, 3 * yyt,
    661                 (xGr + 4) * (2 * xxt + 1) + 1, 1 + (age - 2) * (3 * yyt + 1))
     1480            if ATer = fUNKNOWN then
     1481              Aix := 0
     1482            else if (ALoc >= 0) and (ALoc < G.lx * G.ly) and
     1483              (MyMap[ALoc] and fDeadLands <> 0) then
     1484              Aix := -2
     1485            else if ATer = fOcean then
     1486              Aix := -1
     1487            else if ATer = fShore then
     1488              Aix := 1
     1489            else if ATer >= fForest then
     1490              Aix := 8
    6621491            else
    663               Sprite(HGrCities, x - xxt, y - 2 * yyt, 2 * xxt, 3 * yyt,
    664                 xGr * (2 * xxt + 1) + 1, 1 + (age - 2) * (3 * yyt + 1));
    665           end;
    666 
    667           if not accessory then
    668             exit;
    669 
    670           { if ciCapital and CityInfo.Flags<>0 then
    671             Sprite(Tribe[CityInfo.Owner].symHGr,x+cpic.xf,y-13+cpic.yf,13,14,
    672             1+Tribe[CityInfo.Owner].sympix mod 10 *65,
    673             1+Tribe[CityInfo.Owner].sympix div 10 *49); {capital -- paint flag }
    674 
    675           if MyMap[CityInfo.Loc] and fObserved <> 0 then
    676           begin
    677             if age < 2 then
     1492              Aix := ATer;
     1493            if BTer = fUNKNOWN then
     1494              bix := 0
     1495            else if (BLoc >= 0) and (BLoc < G.lx * G.ly) and
     1496              (MyMap[BLoc] and fDeadLands <> 0) then
     1497              bix := -2
     1498            else if BTer = fOcean then
     1499              bix := -1
     1500            else if BTer = fShore then
     1501              bix := 1
     1502            else if BTer >= fForest then
     1503              bix := 8
     1504            else
     1505              bix := BTer;
     1506            if (Aix = -2) and (bix = -2) then
    6781507            begin
    679               cpic := Tribe[CityInfo.Owner].CityPicture[xGr];
    680               xShield := x - xxc + cpic.xShield;
    681               yShield := y - 2 * yyc + cpic.yShield;
     1508              Aix := fDesert;
     1509              bix := fDesert
    6821510            end
     1511            else if Aix = -2 then
     1512              if bix < 2 then
     1513                Aix := 8
     1514              else
     1515                Aix := bix
     1516            else if bix = -2 then
     1517              if Aix < 2 then
     1518                bix := 8
     1519              else
     1520                bix := Aix;
     1521            if Aix = -1 then
     1522              BitBlt(GrExt[HGrTerrain].Data, x + dx * xxt, y + dy * yyt, xxt,
     1523                yyt, 1 + 6 * (xxt * 2 + 1) + (dx + dy + 1) and 1 * xxt, 1 + yyt,
     1524                SRCCOPY) // arctic <-> ocean
     1525            else if bix = -1 then
     1526              BitBlt(GrExt[HGrTerrain].Data, x + dx * xxt, y + dy * yyt, xxt,
     1527                yyt, 1 + 6 * (xxt * 2 + 1) + xxt - (dx + dy + 1) and 1 * xxt,
     1528                1 + yyt * 2, SRCCOPY) // arctic <-> ocean
    6831529            else
    684             begin
    685               cpic := CitiesPictures[age, xGr];
    686               xShield := x - xxt + cpic.xShield;
    687               yShield := y - 2 * yyt + cpic.yShield;
    688             end;
    689             s := IntToStr(CityInfo.size);
    690             LabelLength := FOutput.Canvas.TextWidth(s);
    691             FillRect(xShield, yShield, LabelLength + 4, 16, $000000);
    692             if MyMap[CityInfo.Loc] and (fUnit or fObserved) = fObserved then
    693               // empty city
    694               LabelTextColor := Tribe[CityInfo.Owner].Color
    695             else
    696             begin
    697               FillRect(xShield + 1, yShield + 1, LabelLength + 2, 14,
    698                 Tribe[CityInfo.Owner].Color);
    699               LabelTextColor := $000000;
    700             end;
    701             Textout(xShield + 2, yShield - 1, LabelTextColor, s);
     1530              BitBlt(LandPatch, x + dx * xxt, y + dy * yyt, xxt, yyt,
     1531                Aix * (xxt * 2) + (dx + dy + 1) and 1 * xxt, bix * yyt, SRCCOPY)
    7021532          end
    703         end; { PaintCity }
    704 
    705         function PoleTile(Loc: integer): integer;
    706         begin { virtual pole tile }
    707           result := fUNKNOWN;
    708           if Loc < -2 * G.lx then
    709           else if Loc < -G.lx then
    710           begin
    711             if (MyMap[dLoc(Loc, 0, 2)] and fTerrain <> fUNKNOWN) and
    712               (MyMap[dLoc(Loc, -2, 2)] and fTerrain <> fUNKNOWN) and
    713               (MyMap[dLoc(Loc, 2, 2)] and fTerrain <> fUNKNOWN) then
    714               result := fArctic;
    715             if (MyMap[dLoc(Loc, 0, 2)] and fObserved <> 0) and
    716               (MyMap[dLoc(Loc, -2, 2)] and fObserved <> 0) and
    717               (MyMap[dLoc(Loc, 2, 2)] and fObserved <> 0) then
    718               result := result or fObserved
    719           end
    720           else if Loc < 0 then
    721           begin
    722             if (MyMap[dLoc(Loc, -1, 1)] and fTerrain <> fUNKNOWN) and
    723               (MyMap[dLoc(Loc, 1, 1)] and fTerrain <> fUNKNOWN) then
    724               result := fArctic;
    725             if (MyMap[dLoc(Loc, -1, 1)] and fObserved <> 0) and
    726               (MyMap[dLoc(Loc, 1, 1)] and fObserved <> 0) then
    727               result := result or fObserved
    728           end
    729           else if Loc < G.lx * (G.ly + 1) then
    730           begin
    731             if (MyMap[dLoc(Loc, -1, -1)] and fTerrain <> fUNKNOWN) and
    732               (MyMap[dLoc(Loc, 1, -1)] and fTerrain <> fUNKNOWN) then
    733               result := fArctic;
    734             if (MyMap[dLoc(Loc, -1, -1)] and fObserved <> 0) and
    735               (MyMap[dLoc(Loc, 1, -1)] and fObserved <> 0) then
    736               result := result or fObserved
    737           end
    738           else if Loc < G.lx * (G.ly + 2) then
    739           begin
    740             if (MyMap[dLoc(Loc, 0, -2)] and fTerrain <> fUNKNOWN) and
    741               (MyMap[dLoc(Loc, -2, -2)] and fTerrain <> fUNKNOWN) and
    742               (MyMap[dLoc(Loc, 2, -2)] and fTerrain <> fUNKNOWN) then
    743               result := fArctic;
    744             if (MyMap[dLoc(Loc, 0, -2)] and fObserved <> 0) and
    745               (MyMap[dLoc(Loc, -2, -2)] and fObserved <> 0) and
    746               (MyMap[dLoc(Loc, 2, -2)] and fObserved <> 0) then
    747               result := result or fObserved
    748           end
     1533      end;
     1534
     1535  OutDC := FOutput.Canvas.Handle;
     1536  DataDC := GrExt[HGrTerrain].Data.Canvas.Handle;
     1537  MaskDC := GrExt[HGrTerrain].Mask.Canvas.Handle;
     1538  for dy := -2 to ny + 1 do
     1539    for dx := -1 to nx do
     1540      if (dx + dy) and 1 = 0 then
     1541        PaintShore(x + xxt * dx, y + yyt + yyt * dy, dLoc(Loc, dx, dy));
     1542  for dy := -2 to ny + 1 do
     1543    for dx := -1 to nx do
     1544      if (dx + dy) and 1 = 0 then
     1545        PaintTileExtraTerrain(x + xxt * dx, y + yyt + yyt * dy,
     1546          dLoc(Loc, dx, dy));
     1547  if CityOwner >= 0 then
     1548  begin
     1549    for dy := -2 to ny + 1 do
     1550      for dx := -2 to nx + 1 do
     1551        if (dx + dy) and 1 = 0 then
     1552        begin
     1553          ALoc := dLoc(Loc, dx, dy);
     1554          if Distance(ALoc, CityLoc) > 5 then
     1555            PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, ALoc, CityLoc,
     1556              CityOwner, UseBlink);
    7491557        end;
    750 
    751         const
    752           Dirx: array [0 .. 7] of integer = (1, 2, 1, 0, -1, -2, -1, 0);
    753           Diry: array [0 .. 7] of integer = (-1, 0, 1, 2, 1, 0, -1, -2);
    754 
    755         function TIsoMap.Connection4(Loc, Mask, Value: integer): integer;
     1558    dx := ((CityLoc mod G.lx * 2 + CityLoc div G.lx and 1) -
     1559      ((Loc + 666 * G.lx) mod G.lx * 2 + (Loc + 666 * G.lx) div G.lx and 1) + 3
     1560      * G.lx) mod (2 * G.lx) - G.lx;
     1561    dy := CityLoc div G.lx - (Loc + 666 * G.lx) div G.lx + 666;
     1562    xm := x + (dx + 1) * xxt;
     1563    ym := y + (dy + 1) * yyt + yyt;
     1564    ShadeOutside(FLeft, FTop, FRight, FBottom, xm, ym);
     1565    CityGrid(xm, ym);
     1566    for dy := -2 to ny + 1 do
     1567      for dx := -2 to nx + 1 do
     1568        if (dx + dy) and 1 = 0 then
    7561569        begin
    757           result := 0;
    758           if dLoc(Loc, 1, -1) >= 0 then
    759           begin
    760             if MyMap[dLoc(Loc, 1, -1)] and Mask = Cardinal(Value) then
    761               inc(result, 1);
    762             if MyMap[dLoc(Loc, -1, -1)] and Mask = Cardinal(Value) then
    763               inc(result, 8);
    764           end;
    765           if dLoc(Loc, 1, 1) < G.lx * G.ly then
    766           begin
    767             if MyMap[dLoc(Loc, 1, 1)] and Mask = Cardinal(Value) then
    768               inc(result, 2);
    769             if MyMap[dLoc(Loc, -1, 1)] and Mask = Cardinal(Value) then
    770               inc(result, 4);
    771           end
     1570          ALoc := dLoc(Loc, dx, dy);
     1571          if Distance(ALoc, CityLoc) <= 5 then
     1572            PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, ALoc, CityLoc,
     1573              CityOwner, UseBlink);
    7721574        end;
    773 
    774         function TIsoMap.Connection8(Loc, Mask: integer): integer;
    775         var
    776           Dir, ConnLoc: integer;
    777         begin
    778           result := 0;
    779           for Dir := 0 to 7 do
    780           begin
    781             ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]);
    782             if (ConnLoc >= 0) and (ConnLoc < G.lx * G.ly) and
    783               (MyMap[ConnLoc] and Mask <> 0) then
    784               inc(result, 1 shl Dir);
    785           end
    786         end;
    787 
    788         function TIsoMap.OceanConnection(Loc: integer): integer;
    789         var
    790           Dir, ConnLoc: integer;
    791         begin
    792           result := 0;
    793           for Dir := 0 to 7 do
    794           begin
    795             ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]);
    796             if (ConnLoc < 0) or (ConnLoc >= G.lx * G.ly) or
    797               ((MyMap[ConnLoc] - 2) and fTerrain < 13) then
    798               inc(result, 1 shl Dir);
    799           end
    800         end;
    801 
    802         procedure TIsoMap.PaintShore(x, y, Loc: integer);
    803         var
    804           Conn, Tile: integer;
    805         begin
    806           if (y <= FTop - yyt * 2) or (y > FBottom) or (x <= FLeft - xxt * 2) or
    807             (x > FRight) then
    808             exit;
    809           if (Loc < 0) or (Loc >= G.lx * G.ly) then
    810             exit;
    811           Tile := MyMap[Loc];
    812           if Tile and fTerrain >= fGrass then
    813             exit;
    814           Conn := OceanConnection(Loc);
    815           if Conn = 0 then
    816             exit;
    817 
    818           BitBlt(GrExt[HGrTerrain].Data, x + xxt div 2, y, xxt, yyt,
    819             1 + (Conn shr 6 + Conn and 1 shl 2) * (xxt * 2 + 1),
    820             1 + yyt + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT);
    821           BitBlt(GrExt[HGrTerrain].Data, x + xxt, y + yyt div 2, xxt, yyt,
    822             1 + (Conn and 7) * (xxt * 2 + 1) + xxt,
    823             1 + yyt * 2 + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT);
    824           BitBlt(GrExt[HGrTerrain].Data, x + xxt div 2, y + yyt, xxt, yyt,
    825             1 + (Conn shr 2 and 7) * (xxt * 2 + 1) + xxt,
    826             1 + yyt + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT);
    827           BitBlt(GrExt[HGrTerrain].Data, x, y + yyt div 2, xxt, yyt,
    828             1 + (Conn shr 4 and 7) * (xxt * 2 + 1),
    829             1 + yyt * 2 + (16 + Tile and fTerrain) * (yyt * 3 + 1), SRCPAINT);
    830           Conn := Connection4(Loc, fTerrain, fUNKNOWN); { dither to black }
    831           if Conn and 1 <> 0 then
    832             BitBlt(GrExt[HGrTerrain].Mask, x + xxt, y, xxt, yyt,
    833               1 + 7 * (xxt * 2 + 1) + xxt,
    834               1 + yyt + 15 * (yyt * 3 + 1), SRCAND);
    835           if Conn and 2 <> 0 then
    836             BitBlt(GrExt[HGrTerrain].Mask, x + xxt, y + yyt, xxt, yyt,
    837               1 + 7 * (xxt * 2 + 1) + xxt, 1 + yyt * 2 + 15 *
    838               (yyt * 3 + 1), SRCAND);
    839           if Conn and 4 <> 0 then
    840             BitBlt(GrExt[HGrTerrain].Mask, x, y + yyt, xxt, yyt,
    841               1 + 7 * (xxt * 2 + 1), 1 + yyt * 2 + 15 * (yyt * 3 + 1), SRCAND);
    842           if Conn and 8 <> 0 then
    843             BitBlt(GrExt[HGrTerrain].Mask, x, y, xxt, yyt,
    844               1 + 7 * (xxt * 2 + 1), 1 + yyt + 15 * (yyt * 3 + 1), SRCAND);
    845         end;
    846 
    847         procedure TIsoMap.PaintTileExtraTerrain(x, y, Loc: integer);
    848         var
    849           Dir, Conn, RRConn, yGr, Tile, yLoc: integer;
    850         begin
    851           if (Loc < 0) or (Loc >= G.lx * G.ly) or (y <= -yyt * 2) or
    852             (y > FOutput.Height) or (x <= -xxt * 2) or (x > FOutput.Width) then
    853             exit;
    854           Tile := MyMap[Loc];
    855           if Tile and fTerrain = fForest then
    856           begin
    857             yLoc := Loc div G.lx;
    858             if IsJungle(yLoc) then
    859               yGr := 18
    860             else
    861               yGr := 3;
    862             Conn := Connection4(Loc, fTerrain, Tile and fTerrain);
    863             if (yLoc = (G.ly - 2) div 4) or (G.ly - 1 - yLoc = (G.ly + 2) div 4)
    864             then
    865               Conn := Conn and not 6 // no connection to south
    866             else if (yLoc = (G.ly + 2) div 4) or
    867               (G.ly - 1 - yLoc = (G.ly - 2) div 4) then
    868               Conn := Conn and not 9; // no connection to north
    869             TSprite(x, y, Conn mod 8 + (yGr + Conn div 8) * 9);
    870           end
    871           else if Tile and fTerrain in [fHills, fMountains, fForest] then
    872           begin
    873             yGr := 3 + 2 * (Tile and fTerrain - fForest);
    874             Conn := Connection4(Loc, fTerrain, Tile and fTerrain);
    875             TSprite(x, y, Conn mod 8 + (yGr + Conn div 8) * 9);
    876           end
    877           else if Tile and fDeadLands <> 0 then
    878             TSprite(x, y, 2 * 9 + 6);
    879 
    880           if ShowObjects then
    881           begin
    882             if Tile and fTerImp = tiFarm then
    883               TSprite(x, y, 109) { farmland }
    884             else if Tile and fTerImp = tiIrrigation then
    885               TSprite(x, y, 108); // irrigation
    886           end;
    887           if Tile and fRiver <> 0 then
    888           begin
    889             Conn := Connection4(Loc, fRiver, fRiver) or
    890               Connection4(Loc, fTerrain, fShore) or
    891               Connection4(Loc, fTerrain, fUNKNOWN);
    892             TSprite(x, y, Conn mod 8 + (13 + Conn div 8) * 9);
    893           end;
    894 
    895           if Tile and fTerrain < fGrass then
    896           begin
    897             Conn := Connection4(Loc, fRiver, fRiver);
    898             for Dir := 0 to 3 do
    899               if Conn and (1 shl Dir) <> 0 then { river mouths }
    900                 TSprite(x, y, 15 * 9 + Dir);
    901             if ShowObjects then
    902             begin
    903               Conn := Connection8(Loc, fCanal);
    904               for Dir := 0 to 7 do
    905                 if Conn and (1 shl Dir) <> 0 then { canal mouths }
    906                   TSprite(x, y, 20 * 9 + 1 + Dir);
    907             end
    908           end;
    909 
    910           if ShowObjects then
    911           begin
    912             if (Tile and fCanal <> 0) or (Tile and fCity <> 0) then
    913             begin // paint canal connections
    914               Conn := Connection8(Loc, fCanal or fCity);
    915               if Tile and fCanal <> 0 then
    916                 Conn := Conn or ($FF - OceanConnection(Loc));
    917               if Conn = 0 then
    918               begin
    919                 if Tile and fCanal <> 0 then
    920                   TSprite(x, y, 99)
    921               end
    922               else
    923                 for Dir := 0 to 7 do
    924                   if (1 shl Dir) and Conn <> 0 then
    925                     TSprite(x, y, 100 + Dir);
    926             end;
    927             if Tile and (fRR or fCity) <> 0 then
    928               RRConn := Connection8(Loc, fRR or fCity)
    929             else
    930               RRConn := 0;
    931             if Tile and (fRoad or fRR or fCity) <> 0 then
    932             begin // paint road connections
    933               Conn := Connection8(Loc, fRoad or fRR or fCity) and not RRConn;
    934               if (Conn = 0) and (Tile and (fRR or fCity) = 0) then
    935                 TSprite(x, y, 81)
    936               else if Conn > 0 then
    937                 for Dir := 0 to 7 do
    938                   if (1 shl Dir) and Conn <> 0 then
    939                     TSprite(x, y, 82 + Dir);
    940             end;
    941             // paint railroad connections
    942             if (Tile and fRR <> 0) and (RRConn = 0) then
    943               TSprite(x, y, 90)
    944             else if RRConn > 0 then
    945               for Dir := 0 to 7 do
    946                 if (1 shl Dir) and RRConn <> 0 then
    947                   TSprite(x, y, 91 + Dir);
    948           end;
    949         end;
    950 
    951         // (x,y) is top left pixel of (2*xxt,3*yyt) rectangle
    952         procedure TIsoMap.PaintTileObjects(x, y, Loc, CityLoc,
    953           CityOwner: integer; UseBlink: boolean);
    954         type
    955           TLine = array [0 .. 9 * 65, 0 .. 2] of Byte;
    956         var
    957           p1, p2, uix, cix, dy, Loc1, Tile, Multi, Destination: integer;
    958           CityInfo: TCityInfo;
    959           UnitInfo: TUnitInfo;
    960           fog: boolean;
    961 
    962           procedure NameCity;
    963           var
    964             cix, xs, w: integer;
    965             BehindCityInfo: TCityInfo;
    966             s: string;
    967             IsCapital: boolean;
    968           begin
    969             BehindCityInfo.Loc := Loc - 2 * G.lx;
    970             if ShowCityNames and (Options and (1 shl moEditMode) = 0) and
    971               (BehindCityInfo.Loc >= 0) and (BehindCityInfo.Loc < G.lx * G.ly)
    972               and (MyMap[BehindCityInfo.Loc] and fCity <> 0) then
    973             begin
    974               GetCityInfo(BehindCityInfo.Loc, cix, BehindCityInfo);
    975               IsCapital := BehindCityInfo.Flags and ciCapital <> 0;
    976               { if Showuix and (cix>=0) then s:=IntToStr(cix)
    977                 else } s := CityName(BehindCityInfo.ID);
    978               w := FOutput.Canvas.TextWidth(s);
    979               xs := x + xxt - (w + 1) div 2;
    980               if IsCapital then
    981                 FOutput.Canvas.Font.Style := FOutput.Canvas.Font.Style +
    982                   [fsUnderline];
    983               Textout(xs + 1, y - 9, $000000, s);
    984               Textout(xs, y - 10, $FFFFFF, s);
    985               if IsCapital then
    986                 FOutput.Canvas.Font.Style := FOutput.Canvas.Font.Style -
    987                   [fsUnderline];
    988             end;
    989           end;
    990 
    991           procedure ShowSpacePort;
    992           begin
    993             if ShowObjects and (Options and (1 shl moEditMode) = 0) and
    994               (Tile and fCity <> 0) and (CityInfo.Flags and ciSpacePort <> 0)
    995             then
    996               TSprite(x + xxt, y - 6, 12 * 9 + 5);
    997           end;
    998 
    999           procedure PaintBorder;
    1000           var
    1001             dx, dy: integer;
    1002             Line: ^TLine;
    1003           begin
    1004             if ShowBorder and (Loc >= 0) and (Loc < G.lx * G.ly) and
    1005               (Tile and fTerrain <> fUNKNOWN) then
    1006             begin
    1007               p1 := MyRO.Territory[Loc];
    1008               if (p1 >= 0) and (ShowMyBorder or (p1 <> me)) then
    1009               begin
    1010                 if BordersOK and (1 shl p1) = 0 then
    1011                 begin
    1012                   LCLIntf.BitBlt(Borders.Canvas.Handle, 0, p1 * (yyt * 2),
    1013                     xxt * 2, yyt * 2, GrExt[HGrTerrain].Data.Canvas.Handle,
    1014                     1 + 8 * (xxt * 2 + 1),
    1015                     1 + yyt + 16 * (yyt * 3 + 1), SRCCOPY);
    1016                   Borders.BeginUpdate;
    1017                   for dy := 0 to yyt * 2 - 1 do
    1018                   begin
    1019                     Line := Borders.ScanLine[p1 * (yyt * 2) + dy];
    1020                     for dx := 0 to xxt * 2 - 1 do
    1021                       if Line[dx, 0] = 99 then
    1022                       begin
    1023                         Line[dx, 0] := Tribe[p1].Color shr 16 and $FF;
    1024                         Line[dx, 1] := Tribe[p1].Color shr 8 and $FF;
    1025                         Line[dx, 2] := Tribe[p1].Color and $FF;
    1026                       end
    1027                   end;
    1028                   Borders.EndUpdate;
    1029                   BordersOK := BordersOK or 1 shl p1;
    1030                 end;
    1031                 for dy := 0 to 1 do
    1032                   for dx := 0 to 1 do
    1033                   begin
    1034                     Loc1 := dLoc(Loc, dx * 2 - 1, dy * 2 - 1);
    1035                     begin
    1036                       if (Loc1 < 0) or (Loc1 >= G.lx * G.ly) then
    1037                         p2 := -1
    1038                       else if MyMap[Loc1] and fTerrain = fUNKNOWN then
    1039                         p2 := p1
    1040                       else
    1041                         p2 := MyRO.Territory[Loc1];
    1042                       if p2 <> p1 then
    1043                       begin
    1044                         BitBlt(GrExt[HGrTerrain].Mask, x + dx * xxt,
    1045                           y + dy * yyt, xxt, yyt, 1 + 8 * (xxt * 2 + 1) + dx *
    1046                           xxt, 1 + yyt + 16 * (yyt * 3 + 1) + dy * yyt, SRCAND);
    1047                         BitBlt(Borders, x + dx * xxt, y + dy * yyt, xxt, yyt,
    1048                           dx * xxt, p1 * (yyt * 2) + dy * yyt, SRCPAINT);
    1049                       end
    1050                     end;
    1051                   end
    1052               end
    1053             end;
    1054           end;
    1055 
    1056         begin
    1057           if (Loc < 0) or (Loc >= G.lx * G.ly) then
    1058             Tile := PoleTile(Loc)
    1059           else
    1060             Tile := MyMap[Loc];
    1061           if ShowObjects and (Options and (1 shl moEditMode) = 0) and
    1062             (Tile and fCity <> 0) then
    1063             GetCityInfo(Loc, cix, CityInfo);
    1064           if (y <= FTop - yyt * 2) or (y > FBottom) or (x <= FLeft - xxt * 2) or
    1065             (x > FRight) then
    1066           begin
    1067             NameCity;
    1068             ShowSpacePort;
    1069             exit;
    1070           end;
    1071           if Tile and fTerrain = fUNKNOWN then
    1072           begin
    1073             NameCity;
    1074             ShowSpacePort;
    1075             exit
    1076           end; { square not discovered }
    1077 
    1078           if not(FoW and (Tile and fObserved = 0)) then
    1079             PaintBorder;
    1080 
    1081           if (Loc >= 0) and (Loc < G.lx * G.ly) and (Loc = FAdviceLoc) then
    1082             TSprite(x, y, 7 + 9 * 2);
    1083 
    1084           if (Loc >= 0) and (Loc < G.lx * G.ly) and (Tile and fSpecial <> 0)
    1085           then { special ressources }
    1086           begin
    1087             dy := Loc div G.lx;
    1088             if Tile and fTerrain < fForest then
    1089               TSprite(x, y, Tile and fTerrain + (Tile and fSpecial shr 5) * 9)
    1090             else if (Tile and fTerrain = fForest) and IsJungle(dy) then
    1091               TSprite(x, y, 8 + 17 * 9 + (Tile and fSpecial shr 5) * 9)
    1092             else
    1093               TSprite(x, y, 8 + 2 * 9 + ((Tile and fTerrain - fForest) * 2 +
    1094                 Tile and fSpecial shr 5) * 9);
    1095           end;
    1096 
    1097           if ShowObjects then
    1098           begin
    1099             if Tile and fTerImp = tiMine then
    1100               TSprite(x, y, 2 + 9 * 12);
    1101             if Tile and fTerImp = tiBase then
    1102               TSprite(x, y, 4 + 9 * 12);
    1103             if Tile and fPoll <> 0 then
    1104               TSprite(x, y, 6 + 9 * 12);
    1105             if Tile and fTerImp = tiFort then
    1106             begin
    1107               TSprite(x, y, 7 + 9 * 12);
    1108               if Tile and fObserved = 0 then
    1109                 TSprite(x, y, 3 + 9 * 12);
    1110             end;
    1111           end;
    1112           if Tile and fDeadLands <> 0 then
    1113             TSprite(x, y, (12 + Tile shr 25 and 3) * 9 + 8);
    1114 
    1115           if Options and (1 shl moEditMode) <> 0 then
    1116             fog := (Loc < 0) or (Loc >= G.lx * G.ly)
    1117             // else if CityLoc>=0 then
    1118             // fog:= (Loc<0) or (Loc>=G.lx*G.ly) or (Distance(Loc,CityLoc)>5)
    1119           else if ShowGrWall then
    1120             fog := Tile and fGrWall = 0
    1121           else
    1122             fog := FoW and (Tile and fObserved = 0);
    1123           if fog and ShowObjects then
    1124             if Loc < -G.lx then
    1125               Sprite(HGrTerrain, x, y + yyt, xxt * 2, yyt,
    1126                 1 + 6 * (xxt * 2 + 1), 1 + yyt * 2 + 15 * (yyt * 3 + 1))
    1127             else if Loc >= G.lx * (G.ly + 1) then
    1128               Sprite(HGrTerrain, x, y, xxt * 2, yyt, 1 + 6 * (xxt * 2 + 1),
    1129                 1 + yyt + 15 * (yyt * 3 + 1))
    1130             else
    1131               TSprite(x, y, 6 + 9 * 15, xxt <> 33);
    1132 
    1133           if FoW and (Tile and fObserved = 0) then
    1134             PaintBorder;
    1135 
    1136 {$IFNDEF SCR}
    1137           // paint goto destination mark
    1138           if DestinationMarkON and (CityOwner < 0) and (UnFocus >= 0) and
    1139             (MyUn[UnFocus].Status and usGoto <> 0) then
    1140           begin
    1141             Destination := MyUn[UnFocus].Status shr 16;
    1142             if (Destination = Loc) and (Destination <> MyUn[UnFocus].Loc) then
    1143               if not UseBlink or BlinkOn then
    1144                 TSprite(x, y, 8 + 9 * 1)
    1145               else
    1146                 TSprite(x, y, 8 + 9 * 2)
    1147           end;
    1148 {$ENDIF}
    1149           if Options and (1 shl moEditMode) <> 0 then
    1150           begin
    1151             if Tile and fPrefStartPos <> 0 then
    1152               TSprite(x, y, 0 + 9 * 1)
    1153             else if Tile and fStartPos <> 0 then
    1154               TSprite(x, y, 0 + 9 * 2);
    1155           end
    1156           else if ShowObjects then
    1157           begin
    1158             { if (CityLoc<0) and (UnFocus>=0) and (Loc=MyUn[UnFocus].Loc) then
    1159               if BlinkOn then TSprite(x,y,8+9*0)
    1160               else TSprite(x,y,8+9*1); }
    1161 
    1162             NameCity;
    1163             ShowSpacePort;
    1164             if Tile and fCity <> 0 then
    1165               PaintCity(x + xxt, y + yyt, CityInfo, CityOwner < 0);
    1166 
    1167             if (Tile and fUnit <> 0) and (Loc <> AttLoc) and
    1168               ((Loc <> DefLoc) or (DefHealth <> 0))
    1169 {$IFNDEF SCR} and ((CityOwner >= 0) or (UnFocus < 0) or not UseBlink or
    1170               BlinkOn or (Loc <> MyUn[UnFocus].Loc)){$ENDIF}
    1171               and ((Tile and fCity <> fCity) or (Loc = DefLoc)
    1172 {$IFNDEF SCR} or (not UseBlink or BlinkOn) and (UnFocus >= 0) and
    1173               (Loc = MyUn[UnFocus].Loc){$ENDIF}) then
    1174             begin { unit }
    1175               GetUnitInfo(Loc, uix, UnitInfo);
    1176               if (Loc = DefLoc) and (DefHealth >= 0) then
    1177                 UnitInfo.Health := DefHealth;
    1178               if (UnitInfo.Owner <> CityOwner) and
    1179                 not((CityOwner = me) and
    1180                 (MyRO.Treaty[UnitInfo.Owner] = trAlliance)) then
    1181 {$IFNDEF SCR} if (UnFocus >= 0) and (Loc = MyUn[UnFocus].Loc) then { active unit }
    1182                 begin
    1183                   Multi := UnitInfo.Flags and unMulti;
    1184                   MakeUnitInfo(me, MyUn[UnFocus], UnitInfo);
    1185                   UnitInfo.Flags := UnitInfo.Flags or Multi;
    1186                   PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo,
    1187                     MyUn[UnFocus].Status);
    1188                 end
    1189                 else if UnitInfo.Owner = me then
    1190                 begin
    1191                   if ClientMode = cMovieTurn then
    1192                     PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor),
    1193                       UnitInfo, 0)
    1194                     // status is not set with precise timing during loading
    1195                   else
    1196                     PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo,
    1197                       MyUn[uix].Status);
    1198                   // if Showuix then Textout(x+16,y+5,$80FF00,IntToStr(uix));
    1199                 end
    1200                 else {$ENDIF} PaintUnit(x + (xxt - xxu), y + (yyt - yyu_anchor), UnitInfo, 0);
    1201             end
    1202             else if Tile and fHiddenUnit <> 0 then
    1203               Sprite(HGrStdUnits, x + (xxt - xxu), y + (yyt - yyu_anchor),
    1204                 xxu * 2, yyu * 2, 1 + 5 * (xxu * 2 + 1), 1)
    1205             else if Tile and fStealthUnit <> 0 then
    1206               Sprite(HGrStdUnits, x + (xxt - xxu), y + (yyt - yyu_anchor),
    1207                 xxu * 2, yyu * 2, 1 + 5 * (xxu * 2 + 1), 1 + 1 * (yyu * 2 + 1))
    1208           end;
    1209 
    1210           if ShowObjects and (Tile and fTerImp = tiFort) and
    1211             (Tile and fObserved <> 0) then
    1212             TSprite(x, y, 3 + 9 * 12);
    1213 
    1214           if (Loc >= 0) and (Loc < G.lx * G.ly) then
    1215             if ShowLoc then
    1216               Textout(x + xxt - 16, y + yyt - 9, $FFFF00, IntToStr(Loc))
    1217             else if ShowDebug and (DebugMap <> nil) and (Loc >= 0) and
    1218               (Loc < G.lx * G.ly) and (DebugMap[Loc] <> 0) then
    1219               Textout(x + xxt - 16, y + yyt - 9, $00E0FF,
    1220                 IntToStr(integer(DebugMap[Loc])))
    1221         end; { PaintTileObjects }
    1222 
    1223         procedure TIsoMap.PaintGrid(x, y, nx, ny: integer);
    1224 
    1225           procedure ClippedLine(dx0, dy0: integer; mirror: boolean);
    1226           var
    1227             x0, x1, dxmin, dymin, dxmax, dymax, n: integer;
    1228           begin
    1229             with FOutput.Canvas do
    1230             begin
    1231               dxmin := (FLeft - x) div xxt;
    1232               dymin := (RealTop - y) div yyt;
    1233               dxmax := (FRight - x - 1) div xxt + 1;
    1234               dymax := (RealBottom - y - 1) div yyt + 1;
    1235               n := dymax - dy0;
    1236               if mirror then
    1237               begin
    1238                 if dx0 - dxmin < n then
    1239                   n := dx0 - dxmin;
    1240                 if dx0 > dxmax then
    1241                 begin
    1242                   n := n - (dx0 - dxmax);
    1243                   dy0 := dy0 + (dx0 - dxmax);
    1244                   dx0 := dxmax
    1245                 end;
    1246                 if dy0 < dymin then
    1247                 begin
    1248                   n := n - (dymin - dy0);
    1249                   dx0 := dx0 - (dymin - dy0);
    1250                   dy0 := dymin
    1251                 end;
    1252               end
    1253               else
    1254               begin
    1255                 if dxmax - dx0 < n then
    1256                   n := dxmax - dx0;
    1257                 if dx0 < dxmin then
    1258                 begin
    1259                   n := n - (dxmin - dx0);
    1260                   dy0 := dy0 + (dxmin - dx0);
    1261                   dx0 := dxmin
    1262                 end;
    1263                 if dy0 < dymin then
    1264                 begin
    1265                   n := n - (dymin - dy0);
    1266                   dx0 := dx0 + (dymin - dy0);
    1267                   dy0 := dymin
    1268                 end;
    1269               end;
    1270               if n <= 0 then
    1271                 exit;
    1272               if mirror then
    1273               begin
    1274                 x0 := x + dx0 * xxt - 1;
    1275                 x1 := x + (dx0 - n) * xxt - 1;
    1276               end
    1277               else
    1278               begin
    1279                 x0 := x + dx0 * xxt;
    1280                 x1 := x + (dx0 + n) * xxt;
    1281               end;
    1282               moveto(x0, y + dy0 * yyt);
    1283               lineto(x1, y + (dy0 + n) * yyt);
    1284             end
    1285           end;
    1286 
    1287         var
    1288           i: integer;
    1289         begin
    1290           FOutput.Canvas.pen.Color := $000000; // $FF shl (8*random(3));
    1291           for i := 0 to nx div 2 do
    1292             ClippedLine(i * 2, 0, false);
    1293           for i := 1 to (nx + 1) div 2 do
    1294             ClippedLine(i * 2, 0, true);
    1295           for i := 0 to ny div 2 do
    1296           begin
    1297             ClippedLine(0, 2 * i + 2, false);
    1298             ClippedLine(nx + 1, 2 * i + 1 + nx and 1, true);
    1299           end;
    1300         end;
    1301 
    1302         procedure TIsoMap.Paint(x, y, Loc, nx, ny, CityLoc, CityOwner: integer;
    1303           UseBlink: boolean; CityAllowClick: boolean);
    1304 
    1305           function IsShoreTile(Loc: integer): boolean;
    1306           const
    1307             Dirx: array [0 .. 7] of integer = (1, 2, 1, 0, -1, -2, -1, 0);
    1308             Diry: array [0 .. 7] of integer = (-1, 0, 1, 2, 1, 0, -1, -2);
    1309           var
    1310             Dir, ConnLoc: integer;
    1311           begin
    1312             result := false;
    1313             for Dir := 0 to 7 do
    1314             begin
    1315               ConnLoc := dLoc(Loc, Dirx[Dir], Diry[Dir]);
    1316               if (ConnLoc < 0) or (ConnLoc >= G.lx * G.ly) or
    1317                 ((MyMap[ConnLoc] - 2) and fTerrain < 13) then
    1318                 result := true
    1319             end
    1320           end;
    1321 
    1322           procedure ShadeOutside(x0, y0, x1, y1, xm, ym: integer);
    1323           const
    1324             rShade = 3.75;
    1325 
    1326             procedure MakeDark(Line: pointer; length: integer);
    1327             type
    1328               TCardArray = array [0 .. 9999] of Cardinal;
    1329               PCardArray = ^TCardArray;
    1330               TByteArray = array [0 .. 9999] of Byte;
    1331               PByteArray = ^TByteArray;
    1332             var
    1333               i, rest: integer;
    1334             begin
    1335               for i := length * 3 div 4 - 1 downto 0 do
    1336                 PCardArray(Line)[i] := PCardArray(Line)[i] shr 1 and $7F7F7F7F;
    1337               rest := (length * 3 div 4) * 4;
    1338               for i := length * 3 mod 4 - 1 downto 0 do
    1339                 PByteArray(Line)[rest + i] := PByteArray(Line)
    1340                   [rest + i] shr 1 and $7F;
    1341             end;
    1342 
    1343           type
    1344             TLine = array [0 .. 99999, 0 .. 2] of Byte;
    1345           var
    1346             y, wBright: integer;
    1347             y_n, w_n: single;
    1348             Line: ^TLine;
    1349           begin
    1350             FOutput.BeginUpdate;
    1351             for y := y0 to y1 - 1 do
    1352             begin
    1353               Line := FOutput.ScanLine[y];
    1354               y_n := (y - ym) / yyt;
    1355               if abs(y_n) < rShade then
    1356               begin
    1357                 w_n := sqrt(sqr(rShade) - sqr(y_n));
    1358                 wBright := trunc(w_n * xxt + 0.5);
    1359                 MakeDark(@Line[x0], xm - x0 - wBright);
    1360                 MakeDark(@Line[xm + wBright], x1 - xm - wBright);
    1361               end
    1362               else
    1363                 MakeDark(@Line[x0], x1 - x0);
    1364             end;
    1365             FOutput.EndUpdate;
    1366           end;
    1367 
    1368           procedure CityGrid(xm, ym: integer);
    1369           var
    1370             i: integer;
    1371           begin
    1372             with FOutput.Canvas do
    1373             begin
    1374               if CityAllowClick then
    1375                 pen.Color := $FFFFFF
    1376               else
    1377                 pen.Color := $000000;
    1378               pen.Width := 1;
    1379               for i := 0 to 3 do
    1380               begin
    1381                 moveto(xm - xxt * (4 - i), ym + yyt * (1 + i));
    1382                 lineto(xm + xxt * (1 + i), ym - yyt * (4 - i));
    1383                 moveto(xm - xxt * (4 - i), ym - yyt * (1 + i));
    1384                 lineto(xm + xxt * (1 + i), ym + yyt * (4 - i));
    1385               end;
    1386               moveto(xm - xxt * 4, ym + yyt * 1);
    1387               lineto(xm - xxt * 1, ym + yyt * 4);
    1388               moveto(xm + xxt * 1, ym + yyt * 4);
    1389               lineto(xm + xxt * 4, ym + yyt * 1);
    1390               moveto(xm - xxt * 4, ym - yyt * 1);
    1391               lineto(xm - xxt * 1, ym - yyt * 4);
    1392               moveto(xm + xxt * 1, ym - yyt * 4);
    1393               lineto(xm + xxt * 4, ym - yyt * 1);
    1394               pen.Width := 1;
    1395             end
    1396           end;
    1397 
    1398         var
    1399           dx, dy, xm, ym, ALoc, BLoc, ATer, BTer, Aix, bix: integer;
    1400         begin
    1401           FoW := true;
    1402           ShowLoc := Options and (1 shl moLocCodes) <> 0;
    1403           ShowDebug := pDebugMap >= 0;
    1404           ShowObjects := (CityOwner >= 0) or
    1405             (Options and (1 shl moBareTerrain) = 0);
    1406           ShowCityNames := ShowObjects and (CityOwner < 0) and
    1407             (Options and (1 shl moCityNames) <> 0);
    1408           ShowBorder := true;
    1409           ShowMyBorder := CityOwner < 0;
    1410           ShowGrWall := (CityOwner < 0) and
    1411             (Options and (1 shl moGreatWall) <> 0);
    1412           if ShowDebug then
    1413             Server(sGetDebugMap, me, pDebugMap, DebugMap)
    1414           else
    1415             DebugMap := nil;
    1416           with FOutput.Canvas do
    1417           begin
    1418             RealTop := y - ((Loc + 12345 * G.lx) div G.lx - 12345) * yyt;
    1419             RealBottom := y +
    1420               (G.ly - ((Loc + 12345 * G.lx) div G.lx - 12345) + 3) * yyt;
    1421             Brush.Color := EmptySpaceColor;
    1422             if RealTop > FTop then
    1423               FillRect(Rect(FLeft, FTop, FRight, RealTop))
    1424             else
    1425               RealTop := FTop;
    1426             if RealBottom < FBottom then
    1427               FillRect(Rect(FLeft, RealBottom, FRight, FBottom))
    1428             else
    1429               RealBottom := FBottom;
    1430             Brush.Color := $000000;
    1431             FillRect(Rect(FLeft, RealTop, FRight, RealBottom));
    1432             Brush.Style := bsClear;
    1433           end;
    1434 
    1435           for dy := 0 to ny + 1 do
    1436             if (Loc + dy * G.lx >= 0) and (Loc + (dy - 3) * G.lx < G.lx * G.ly)
    1437             then
    1438               for dx := 0 to nx do
    1439               begin
    1440                 ALoc := dLoc(Loc, dx - (dy + dx) and 1, dy - 2);
    1441                 BLoc := dLoc(Loc, dx - (dy + dx + 1) and 1, dy - 1);
    1442                 if (ALoc < 0) or (ALoc >= G.lx * G.ly) then
    1443                   ATer := PoleTile(ALoc) and fTerrain
    1444                 else
    1445                   ATer := MyMap[ALoc] and fTerrain;
    1446                 if (BLoc < 0) or (BLoc >= G.lx * G.ly) then
    1447                   BTer := PoleTile(BLoc) and fTerrain
    1448                 else
    1449                   BTer := MyMap[BLoc] and fTerrain;
    1450 
    1451                 if (ATer <> fUNKNOWN) or (BTer <> fUNKNOWN) then
    1452                   if ((ATer < fGrass) or (ATer = fUNKNOWN)) and
    1453                     ((BTer < fGrass) or (BTer = fUNKNOWN)) then
    1454                   begin
    1455                     if ATer = fUNKNOWN then
    1456                       Aix := 0
    1457                     else if IsShoreTile(ALoc) then
    1458                       if ATer = fOcean then
    1459                         Aix := -1
    1460                       else
    1461                         Aix := 1
    1462                     else
    1463                       Aix := ATer + 2;
    1464                     if BTer = fUNKNOWN then
    1465                       bix := 0
    1466                     else if IsShoreTile(BLoc) then
    1467                       if BTer = fOcean then
    1468                         bix := -1
    1469                       else
    1470                         bix := 1
    1471                     else
    1472                       bix := BTer + 2;
    1473                     if (Aix > 1) or (bix > 1) then
    1474                     begin
    1475                       if Aix = -1 then
    1476                         if bix = fOcean + 2 then
    1477                         begin
    1478                           Aix := 0;
    1479                           bix := 0
    1480                         end
    1481                         else
    1482                         begin
    1483                           Aix := 0;
    1484                           bix := 1
    1485                         end
    1486                       else if bix = -1 then
    1487                         if Aix = fOcean + 2 then
    1488                         begin
    1489                           Aix := 1;
    1490                           bix := 1
    1491                         end
    1492                         else
    1493                         begin
    1494                           Aix := 1;
    1495                           bix := 0
    1496                         end;
    1497                       BitBlt(OceanPatch, x + dx * xxt, y + dy * yyt, xxt, yyt,
    1498                         Aix * (xxt * 2) + (dx + dy + 1) and 1 * xxt,
    1499                         bix * yyt, SRCCOPY)
    1500                     end
    1501                   end
    1502                   else
    1503                   begin
    1504                     if ATer = fUNKNOWN then
    1505                       Aix := 0
    1506                     else if (ALoc >= 0) and (ALoc < G.lx * G.ly) and
    1507                       (MyMap[ALoc] and fDeadLands <> 0) then
    1508                       Aix := -2
    1509                     else if ATer = fOcean then
    1510                       Aix := -1
    1511                     else if ATer = fShore then
    1512                       Aix := 1
    1513                     else if ATer >= fForest then
    1514                       Aix := 8
    1515                     else
    1516                       Aix := ATer;
    1517                     if BTer = fUNKNOWN then
    1518                       bix := 0
    1519                     else if (BLoc >= 0) and (BLoc < G.lx * G.ly) and
    1520                       (MyMap[BLoc] and fDeadLands <> 0) then
    1521                       bix := -2
    1522                     else if BTer = fOcean then
    1523                       bix := -1
    1524                     else if BTer = fShore then
    1525                       bix := 1
    1526                     else if BTer >= fForest then
    1527                       bix := 8
    1528                     else
    1529                       bix := BTer;
    1530                     if (Aix = -2) and (bix = -2) then
    1531                     begin
    1532                       Aix := fDesert;
    1533                       bix := fDesert
    1534                     end
    1535                     else if Aix = -2 then
    1536                       if bix < 2 then
    1537                         Aix := 8
    1538                       else
    1539                         Aix := bix
    1540                     else if bix = -2 then
    1541                       if Aix < 2 then
    1542                         bix := 8
    1543                       else
    1544                         bix := Aix;
    1545                     if Aix = -1 then
    1546                       BitBlt(GrExt[HGrTerrain].Data, x + dx * xxt, y + dy * yyt,
    1547                         xxt, yyt, 1 + 6 * (xxt * 2 + 1) + (dx + dy + 1) and
    1548                         1 * xxt, 1 + yyt, SRCCOPY) // arctic <-> ocean
    1549                     else if bix = -1 then
    1550                       BitBlt(GrExt[HGrTerrain].Data, x + dx * xxt, y + dy * yyt,
    1551                         xxt, yyt, 1 + 6 * (xxt * 2 + 1) + xxt - (dx + dy + 1)
    1552                         and 1 * xxt, 1 + yyt * 2, SRCCOPY) // arctic <-> ocean
    1553                     else
    1554                       BitBlt(LandPatch, x + dx * xxt, y + dy * yyt, xxt, yyt,
    1555                         Aix * (xxt * 2) + (dx + dy + 1) and 1 * xxt,
    1556                         bix * yyt, SRCCOPY)
    1557                   end
    1558               end;
    1559 
    1560           OutDC := FOutput.Canvas.Handle;
    1561           DataDC := GrExt[HGrTerrain].Data.Canvas.Handle;
    1562           MaskDC := GrExt[HGrTerrain].Mask.Canvas.Handle;
    1563           for dy := -2 to ny + 1 do
    1564             for dx := -1 to nx do
    1565               if (dx + dy) and 1 = 0 then
    1566                 PaintShore(x + xxt * dx, y + yyt + yyt * dy, dLoc(Loc, dx, dy));
    1567           for dy := -2 to ny + 1 do
    1568             for dx := -1 to nx do
    1569               if (dx + dy) and 1 = 0 then
    1570                 PaintTileExtraTerrain(x + xxt * dx, y + yyt + yyt * dy,
    1571                   dLoc(Loc, dx, dy));
    1572           if CityOwner >= 0 then
    1573           begin
    1574             for dy := -2 to ny + 1 do
    1575               for dx := -2 to nx + 1 do
    1576                 if (dx + dy) and 1 = 0 then
    1577                 begin
    1578                   ALoc := dLoc(Loc, dx, dy);
    1579                   if Distance(ALoc, CityLoc) > 5 then
    1580                     PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, ALoc,
    1581                       CityLoc, CityOwner, UseBlink);
    1582                 end;
    1583             dx := ((CityLoc mod G.lx * 2 + CityLoc div G.lx and 1) -
    1584               ((Loc + 666 * G.lx) mod G.lx * 2 + (Loc + 666 * G.lx) div G.lx and
    1585               1) + 3 * G.lx) mod (2 * G.lx) - G.lx;
    1586             dy := CityLoc div G.lx - (Loc + 666 * G.lx) div G.lx + 666;
    1587             xm := x + (dx + 1) * xxt;
    1588             ym := y + (dy + 1) * yyt + yyt;
    1589             ShadeOutside(FLeft, FTop, FRight, FBottom, xm, ym);
    1590             CityGrid(xm, ym);
    1591             for dy := -2 to ny + 1 do
    1592               for dx := -2 to nx + 1 do
    1593                 if (dx + dy) and 1 = 0 then
    1594                 begin
    1595                   ALoc := dLoc(Loc, dx, dy);
    1596                   if Distance(ALoc, CityLoc) <= 5 then
    1597                     PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, ALoc,
    1598                       CityLoc, CityOwner, UseBlink);
    1599                 end;
    1600           end
    1601           else
    1602           begin
    1603             if ShowLoc or (Options and (1 shl moEditMode) <> 0) or
    1604               (Options and (1 shl moGrid) <> 0) then
    1605               PaintGrid(x, y, nx, ny);
    1606             for dy := -2 to ny + 1 do
    1607               for dx := -2 to nx + 1 do
    1608                 if (dx + dy) and 1 = 0 then
    1609                   PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy,
    1610                     dLoc(Loc, dx, dy), CityLoc, CityOwner, UseBlink);
    1611           end;
    1612 
    1613           // frame(FOutput.Canvas,x+1,y+1,x+nx*33+33-2,y+ny*16+32-2,$FFFF,$FFFF);
    1614         end; { Paint }
    1615 
    1616         procedure TIsoMap.AttackBegin(const ShowMove: TShowMove);
    1617         begin
    1618           AttLoc := ShowMove.FromLoc;
    1619           DefLoc := dLoc(AttLoc, ShowMove.dx, ShowMove.dy);
    1620           DefHealth := -1;
    1621         end;
    1622 
    1623         procedure TIsoMap.AttackEffect(const ShowMove: TShowMove);
    1624         begin
    1625           DefHealth := ShowMove.EndHealthDef;
    1626         end;
    1627 
    1628         procedure TIsoMap.AttackEnd;
    1629         begin
    1630           AttLoc := -1;
    1631           DefLoc := -1;
    1632         end;
     1575  end
     1576  else
     1577  begin
     1578    if ShowLoc or (Options and (1 shl moEditMode) <> 0) or
     1579      (Options and (1 shl moGrid) <> 0) then
     1580      PaintGrid(x, y, nx, ny);
     1581    for dy := -2 to ny + 1 do
     1582      for dx := -2 to nx + 1 do
     1583        if (dx + dy) and 1 = 0 then
     1584          PaintTileObjects(x + xxt * dx, y + yyt + yyt * dy, dLoc(Loc, dx, dy),
     1585            CityLoc, CityOwner, UseBlink);
     1586  end;
     1587
     1588  // frame(FOutput.Canvas,x+1,y+1,x+nx*33+33-2,y+ny*16+32-2,$FFFF,$FFFF);
     1589end; { Paint }
     1590
     1591procedure TIsoMap.AttackBegin(const ShowMove: TShowMove);
     1592begin
     1593  AttLoc := ShowMove.FromLoc;
     1594  DefLoc := dLoc(AttLoc, ShowMove.dx, ShowMove.dy);
     1595  DefHealth := -1;
     1596end;
     1597
     1598procedure TIsoMap.AttackEffect(const ShowMove: TShowMove);
     1599begin
     1600  DefHealth := ShowMove.EndHealthDef;
     1601end;
     1602
     1603procedure TIsoMap.AttackEnd;
     1604begin
     1605  AttLoc := -1;
     1606  DefLoc := -1;
     1607end;
    16331608
    16341609initialization
Note: See TracChangeset for help on using the changeset viewer.