Changeset 42


Ignore:
Timestamp:
Jan 9, 2017, 9:54:57 PM (7 years ago)
Author:
chronos
Message:
  • Fixed: Correctly formatted IsoEngine source.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/delphi/LocalPlayer/IsoEngine.pas

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