Changeset 223


Ignore:
Timestamp:
Jul 14, 2018, 7:21:43 PM (6 years ago)
Author:
chronos
Message:
  • Modified: CellMoves moved from terrain map to player map. Every player should have own moves to avoid affecting moves of different player.
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Forms/UFormClient.lfm

    r221 r223  
    77  ClientHeight = 621
    88  ClientWidth = 775
    9   DesignTimePPI = 120
     9  DesignTimePPI = 144
    1010  OnClose = FormClose
    1111  OnCreate = FormCreate
     
    1313  OnKeyUp = FormKeyUp
    1414  OnShow = FormShow
    15   LCLVersion = '1.8.2.0'
     15  LCLVersion = '1.8.4.0'
    1616  WindowState = wsMaximized
    1717  object StatusBar1: TStatusBar
    1818    Left = 0
    19     Height = 28
    20     Top = 593
     19    Height = 30
     20    Top = 591
    2121    Width = 775
    2222    Panels = <   
     
    3434  object ToolBar1: TToolBar
    3535    Left = 0
    36     Height = 593
     36    Height = 591
    3737    Top = 0
    3838    Width = 32
     
    8080  object PaintBox1: TPaintBox
    8181    Left = 32
    82     Height = 593
     82    Height = 591
    8383    Top = 0
    8484    Width = 743
  • trunk/Forms/UFormClient.pas

    r222 r223  
    8585    procedure DoNextPlayer(Sender: TObject);
    8686    procedure DoTurnStart(Sender: TObject);
    87     procedure DoMove(CellFrom, CellTo: TCell; var CountOnce,
     87    procedure DoMove(CellFrom, CellTo: TPlayerCell; var CountOnce,
    8888      CountRepeat: Integer; Update: Boolean; var Confirm: Boolean);
    8989    procedure SetToolbarHints;
     
    129129end;
    130130
    131 procedure TFormClient.DoMove(CellFrom, CellTo: TCell; var CountOnce,
     131procedure TFormClient.DoMove(CellFrom, CellTo: TPlayerCell; var CountOnce,
    132132  CountRepeat: Integer; Update: Boolean; var Confirm: Boolean);
    133133var
     
    146146    FormMove.TrackBarRepeat.Max := FormMove.SpinEditRepeat.MaxValue;
    147147    FormMove.TrackBarRepeat.Position := FormMove.SpinEditRepeat.Value;
    148     FormMove.DefendCount := CellTo.Power;
     148    FormMove.DefendCount := CellTo.MapCell.Power;
    149149    // Attack count from other surrounding cells without current move if already exists
    150150    FormMove.AttackCount := 0;
     
    152152    if TUnitMove(CellTo.MovesTo[I]).CellFrom <> CellFrom then
    153153      FormMove.AttackCount := FormMove.AttackCount + TUnitMove(CellTo.MovesTo[I]).CountOnce;
    154     FormMove.ShowWinProbability := CellTo.Player <> CellFrom.Player;
     154    FormMove.ShowWinProbability := CellTo.MapCell.Player <> CellFrom.MapCell.Player;
    155155
    156156    if FormMove.ShowModal = mrOk then begin
     
    456456  Y: Integer);
    457457var
    458   Cell: TCell;
    459   OldCell: TCell;
     458  Cell: TPlayerCell;
     459  OldCell: TPlayerCell;
    460460  CellPos: TPoint;
    461461begin
     
    473473    OldCell := Client.View.FocusedCell;
    474474    with Core.Game do
    475       Cell := Map.PosToCell(Client.View.CanvasToCellPos(TPoint.Create(X, Y)), Client.View);
     475      if Assigned(Client.ControlPlayer) then
     476        Cell := Client.ControlPlayer.PlayerMap.PosToCell(Client.View.CanvasToCellPos(TPoint.Create(X, Y)), Client.View);
     477        //else Cell := Client.Game.Map.PosToCell(Client.View.CanvasToCellPos(TPoint.Create(X, Y)), Client.View);
    476478    if Assigned(Cell) then begin
    477479      Client.View.FocusedCell := Cell;
    478       StatusBar1.Panels[0].Text := '[' + IntToStr(Cell.PosPx.X) + ', ' + IntToStr(Cell.PosPx.Y) +
    479         '] (' + IntToStr(Cell.MovesFrom.Count) + ', ' + IntToStr(Cell.MovesTo.Count) + ') ' + IntToStr(Cell.Id);
     480      StatusBar1.Panels[0].Text := '[' + IntToStr(Cell.MapCell.PosPx.X) + ', ' + IntToStr(Cell.MapCell.PosPx.Y) +
     481        '] (' + IntToStr(Cell.MovesFrom.Count) + ', ' + IntToStr(Cell.MovesTo.Count) + ') ' + IntToStr(Cell.MapCell.Id);
    480482    end else begin
    481483      Client.View.FocusedCell := nil;
  • trunk/UClientAI.pas

    r222 r223  
    2323    procedure Process;
    2424    procedure FallBack;
    25     function AttackersCount(Cell: TCell): Integer;
     25    function AttackersCount(Cell: TPlayerCell): Integer;
    2626  end;
    2727
     
    3939procedure TComputer.AttackNeutral;
    4040var
    41   AllCells: TCells;
     41  AllCells: TPlayerCells;
    4242  TotalPower: Integer;
    4343  AttackPower: Integer;
    4444  TotalAttackPower: Integer;
    4545  CanAttack: Integer;
    46   TargetCells: TCells;
    47   Cell: TCell;
    48   NeighborCell: TCell;
     46  TargetCells: TPlayerCells;
     47  Cell: TPlayerCell;
     48  NeighborCell: TPlayerCell;
    4949const
    5050  AttackDiff = 1;
    5151begin
    52   AllCells := Game.Map.Cells;
    53   TargetCells := TCells.Create;
     52  AllCells := ControlPlayer.PlayerMap.Cells;
     53  TargetCells := TPlayerCells.Create;
    5454  TargetCells.FreeObjects := False;
    5555
     
    5757  for Cell in AllCells do
    5858  with Cell do begin
    59     if (Terrain <> ttVoid) and (Player = nil) then begin
     59    if (MapCell.Terrain <> ttVoid) and (MapCell.Player = nil) then begin
    6060      CanAttack := 0;
    6161      for NeighborCell in Neighbors do
    62       if NeighborCell.Player = ControlPlayer then begin
     62      if NeighborCell.MapCell.Player = ControlPlayer then begin
    6363        Inc(CanAttack);
    6464      end;
     
    7777      TotalPower := 0;
    7878      for NeighborCell in Neighbors do
    79       if NeighborCell.Player = ControlPlayer then
     79      if NeighborCell.MapCell.Player = ControlPlayer then
    8080        TotalPower := TotalPower + NeighborCell.GetAvialPower;
    8181
    8282      // Attack if target is weaker
    83       if TotalPower >= (Power + AttackDiff) then begin
     83      if TotalPower >= (MapCell.Power + AttackDiff) then begin
    8484        TotalAttackPower := 0;
    8585        for NeighborCell in Neighbors do
    86         if NeighborCell.Player = ControlPlayer then begin
     86        if NeighborCell.MapCell.Player = ControlPlayer then begin
    8787          // Use only necessary power
    88           AttackPower := Power - TotalAttackPower + AttackDiff;
     88          AttackPower := MapCell.Power - TotalAttackPower + AttackDiff;
    8989          if NeighborCell.GetAvialPower < AttackPower then
    9090            AttackPower := NeighborCell.GetAvialPower;
     
    100100procedure TComputer.AttackPlayers;
    101101var
    102   AllCells: TCells;
     102  AllCells: TPlayerCells;
    103103  TotalPower: Integer;
    104104  AttackPower: Integer;
    105105  TotalAttackPower: Integer;
    106106  CanAttack: Integer;
    107   TargetCells: TCells;
    108   TargetCell: TCell;
    109   NeighborCell: TCell;
     107  TargetCells: TPlayerCells;
     108  TargetCell: TPlayerCell;
     109  NeighborCell: TPlayerCell;
    110110begin
    111111if ControlPlayer.Defensive then Exit;
    112112
    113   AllCells := Game.Map.Cells;
    114   TargetCells := TCells.Create;
     113  AllCells := ControlPlayer.PlayerMap.Cells;
     114  TargetCells := TPlayerCells.Create;
    115115  TargetCells.FreeObjects := False;
    116116
    117117  // Get list of all attack target cells
    118118  for TargetCell in AllCells do begin
    119     if (TargetCell.Terrain <> ttVoid) and (TargetCell.Player <> ControlPlayer) and
    120       (TargetCell.Player <> nil) then begin
     119    if (TargetCell.MapCell.Terrain <> ttVoid) and (TargetCell.MapCell.Player <> ControlPlayer) and
     120      (TargetCell.MapCell.Player <> nil) then begin
    121121      CanAttack := 0;
    122122      for NeighborCell in TargetCell.Neighbors do
    123       if NeighborCell.Player = ControlPlayer then begin
     123      if NeighborCell.MapCell.Player = ControlPlayer then begin
    124124        Inc(CanAttack);
    125125      end;
     
    137137      TotalPower := 0;
    138138      for NeighborCell in TargetCell.Neighbors do
    139       if NeighborCell.Player = ControlPlayer then begin
     139      if NeighborCell.MapCell.Player = ControlPlayer then begin
    140140        TotalPower := TotalPower + NeighborCell.GetAvialPower;
    141141      end;
    142142      // Attack if target is weaker
    143       if Game.AttackProbability(TotalPower, TargetCell.Power) >=
     143      if Game.AttackProbability(TotalPower, TargetCell.MapCell.Power) >=
    144144        ComputerAggroProbability[ControlPlayer.Agressivity] then begin
    145145        // Try to limit total attacking power to necessary minimum
    146         while Game.AttackProbability(TotalPower - 1, TargetCell.Power) >=
     146        while Game.AttackProbability(TotalPower - 1, TargetCell.MapCell.Power) >=
    147147          ComputerAggroProbability[ControlPlayer.Agressivity] do
    148148          Dec(TotalPower);
     
    151151        TotalAttackPower := 0;
    152152        for NeighborCell in TargetCell.Neighbors do
    153         if NeighborCell.Player = ControlPlayer then begin
     153        if NeighborCell.MapCell.Player = ControlPlayer then begin
    154154          // Use only necessary power
    155155          AttackPower := TotalPower - TotalAttackPower;
     
    168168procedure TComputer.InnerMoves;
    169169var
    170   AllCells: TCells;
     170  AllCells: TPlayerCells;
    171171  I, J: Integer;
    172172  C: Integer;
    173173  CanAttack: Integer;
    174   TargetCells: TCells;
    175   NewTargetCells: TCells;
    176   Cells2: TCells;
     174  TargetCells: TPlayerCells;
     175  NewTargetCells: TPlayerCells;
     176  Cells2: TPlayerCells;
    177177  MovedPower: Integer;
    178178begin
    179179  // We need to move available power to borders to be available for attacks
    180180  // or defense
    181   AllCells := Game.Map.Cells;
    182   TargetCells := TCells.Create;
     181  AllCells := ControlPlayer.PlayerMap.Cells;
     182  TargetCells := TPlayerCells.Create;
    183183  TargetCells.FreeObjects := False;
    184   NewTargetCells := TCells.Create;
     184  NewTargetCells := TPlayerCells.Create;
    185185  NewTargetCells.FreeObjects := False;
    186186
     
    188188  for C := 0 to AllCells.Count - 1 do
    189189  with AllCells[C] do begin
    190     if (Player <> ControlPlayer) and (Player <> nil) and (Terrain <> ttVoid) then begin
     190    if (MapCell.Player <> ControlPlayer) and (MapCell.Player <> nil) and (MapCell.Terrain <> ttVoid) then begin
    191191      CanAttack := 0;
    192192      for I := 0 to Neighbors.Count - 1 do
    193       if ((Neighbors[I].Player = ControlPlayer) or
    194       (Neighbors[I].Player = nil)) and (Neighbors[I].Terrain <> ttVoid) then begin
     193      if ((Neighbors[I].MapCell.Player = ControlPlayer) or
     194      (Neighbors[I].MapCell.Player = nil)) and (Neighbors[I].MapCell.Terrain <> ttVoid) then begin
    195195        Inc(CanAttack);
    196196      end;
     
    210210    // Set mark for selected border cells
    211211    for C := 0 to TargetCells.Count - 1 do
    212       TargetCells[C].Mark := True;
     212      TargetCells[C].MapCell.Mark := True;
    213213
    214214    // Move all power from unmarked cells and mark them
     
    217217    with TargetCells[C] do begin
    218218      for I := 0 to Neighbors.Count - 1 do begin
    219         if (Neighbors[I].Terrain <> ttVoid) and (not Neighbors[I].Mark) then begin
    220           if (TargetCells[C].Player = ControlPlayer) and
    221           (Neighbors[I].Player = ControlPlayer) then begin
     219        if (Neighbors[I].MapCell.Terrain <> ttVoid) and (not Neighbors[I].MapCell.Mark) then begin
     220          if (TargetCells[C].MapCell.Player = ControlPlayer) and
     221          (Neighbors[I].MapCell.Player = ControlPlayer) then begin
    222222            // Do not take units from front line
    223223            Cells2 := Neighbors[I].Neighbors;
    224224            CanAttack := 0;
    225225            for J := 0 to Cells2.Count - 1 do
    226             if ((Cells2[J].Player <> ControlPlayer) or (Cells2[J].Player = nil))
    227             and (Cells2[J].Terrain <> ttVoid) then begin
     226            if ((Cells2[J].MapCell.Player <> ControlPlayer) or (Cells2[J].MapCell.Player = nil))
     227            and (Cells2[J].MapCell.Terrain <> ttVoid) then begin
    228228              Inc(CanAttack);
    229229            end;
     
    232232              if (TargetCells[C].GetAvialPower + TargetCells[C].GetAttackPower + MovedPower) > Game.Map.MaxPower then
    233233                MovedPower := Game.Map.MaxPower - TargetCells[C].GetAvialPower - TargetCells[C].GetAttackPower;
    234               Player.SetMove(Neighbors[I], TargetCells[C], MovedPower, False);
     234              MapCell.Player.SetMove(Neighbors[I], TargetCells[C], MovedPower, False);
    235235            end;
    236236          end;
    237           Neighbors[I].Mark := True;
     237          Neighbors[I].MapCell.Mark := True;
    238238          NewTargetCells.Add(Neighbors[I]);
    239239        end;
     
    244244    FreeAndNil(TargetCells);
    245245    TargetCells := NewTargetCells;
    246     NewTargetCells := TCells.Create;
     246    NewTargetCells := TPlayerCells.Create;
    247247    NewTargetCells.FreeObjects := False;
    248248  end;
     
    281281  C: Integer;
    282282  I: Integer;
    283   AllCells: TCells;
    284   BorderCells: TCells;
     283  AllCells: TPlayerCells;
     284  BorderCells: TPlayerCells;
    285285  EnemyPower: Integer;
    286286begin
    287   BorderCells := TCells.Create;
     287  BorderCells := TPlayerCells.Create;
    288288  BorderCells.FreeObjects := False;
    289   AllCells := Game.Map.Cells;
     289  AllCells := ControlPlayer.PlayerMap.Cells;
    290290
    291291  // Get list of border cells
    292292  for C := 0 to AllCells.Count - 1 do
    293293  with AllCells[C] do begin
    294     if (Terrain <> ttVoid) and (Player = ControlPlayer)  then begin
     294    if (MapCell.Terrain <> ttVoid) and (MapCell.Player = ControlPlayer)  then begin
    295295      if AttackersCount(AllCells[C]) > 0 then
    296296        BorderCells.Add(AllCells[C]);
     
    305305    EnemyPower := 0;
    306306    for I := 0 to Neighbors.Count - 1 do
    307     if (Neighbors[I].Player <> ControlPlayer) and (Neighbors[I].Player <> nil) then begin
    308       Inc(EnemyPower, Neighbors[I].Power);
     307    if (Neighbors[I].MapCell.Player <> ControlPlayer) and (Neighbors[I].MapCell.Player <> nil) then begin
     308      Inc(EnemyPower, Neighbors[I].MapCell.Power);
    309309    end;
    310310    if EnemyPower > (GetAvialPower + GetAttackPower) then begin
    311311      // Fallback
    312312      for I := MovesTo.Count - 1 downto 0 do
    313         Player.Moves.Remove(MovesTo[I]);
     313        MapCell.Player.Moves.Remove(MovesTo[I]);
    314314      for I := 0 to Neighbors.Count - 1 do
    315       if (Neighbors[I].Player = Player) and (AttackersCount(Neighbors[I]) = 0) then begin
    316         Player.SetMove(BorderCells[C], Neighbors[I], GetAvialPower, False);
     315      if (Neighbors[I].MapCell.Player = MapCell.Player) and (AttackersCount(Neighbors[I]) = 0) then begin
     316        MapCell.Player.SetMove(BorderCells[C], Neighbors[I], GetAvialPower, False);
    317317        Break;
    318318      end;
     
    323323end;
    324324
    325 function TComputer.AttackersCount(Cell: TCell): Integer;
     325function TComputer.AttackersCount(Cell: TPlayerCell): Integer;
    326326var
    327327  I: Integer;
     
    329329  Result := 0;
    330330  for I := 0 to Cell.Neighbors.Count - 1 do
    331   if (Cell.Neighbors[I].Player <> ControlPlayer) and
    332     (Cell.Neighbors[I].Player <> nil) then begin
     331  if (Cell.Neighbors[I].MapCell.Player <> ControlPlayer) and
     332    (Cell.Neighbors[I].MapCell.Player <> nil) then begin
    333333      Inc(Result);
    334334  end;
  • trunk/UGame.pas

    r222 r223  
    2828  TCellLinks = class;
    2929  TMapArea = class;
     30  TPlayerCells = class;
     31  TPlayerCell = class;
     32  TPlayerMap = class;
    3033
    3134  TTerrainType = (ttVoid, ttNormal, ttCity);
     
    5053    PlayerId: Integer;
    5154    Player: TPlayer;
    52     MovesFrom: TUnitMoves;
    53     MovesTo: TUnitMoves;
    5455    NeighborsId: array of Integer;
    5556    Neighbors: TCells;
     
    5758    Weight: Integer; // Temporary value
    5859    Angle: Double; // Temporary value
     60    PlayerCell: Pointer; // Temporary value
    5961    Links: TCellLinks;
    6062    Extra: TExtraType;
     
    6264    procedure ConnectTo(Cell: TCell);
    6365    procedure DisconnectFrom(Cell: TCell);
    64     procedure Check;
    6566    function NeighboringToVoid: Boolean;
    6667    procedure AreaExtend;
     
    7172    function IsVisible(View: TView): Boolean;
    7273    function GetColor: TColor;
    73     function GetAvialPower: Integer;
    74     function GetAttackPower: Integer;
    7574    function ToString: ansistring; override;
    7675    constructor Create;
     
    140139    Game: TGame;
    141140    SourceRect: TRect;
    142     FocusedCell: TCell;
    143     SelectedCell: TCell;
     141    FocusedCell: TPlayerCell;
     142    SelectedCell: TPlayerCell;
    144143    procedure Clear;
    145144    constructor Create;
     
    210209    Areas: TMapAreas;
    211210    Cyclic: Boolean;
     211    procedure Paint(Canvas: TCanvas; View: TView);
    212212    function IsOutsideShape(Coord: TPoint): Boolean; virtual;
    213213    function IsCellsNeighbor(Cell1, Cell2: TCell): Boolean; virtual;
     
    231231    constructor Create; virtual;
    232232    destructor Destroy; override;
    233     procedure Paint(Canvas: TCanvas; View: TView); virtual;
    234233    function CalculatePixelRect: TRect; virtual;
    235234    procedure ForEachCells(Method: TMethod); virtual;
     
    238237  end;
    239238
    240   TPlayerCells = class;
    241   TPlayerMap = class;
    242 
    243239  { TPlayerCell }
    244240
    245241  TPlayerCell = class
     242    MovesFrom: TUnitMoves;
     243    MovesTo: TUnitMoves;
    246244    Explored: Boolean;
    247245    InVisibleRange: Boolean;
    248246    MapCell: TCell;
    249247    List: TPlayerCells;
     248    Neighbors: TPlayerCells;
     249    procedure ConnectTo(Cell: TPlayerCell);
     250    procedure DisconnectFrom(Cell: TPlayerCell);
     251    function GetAvialPower: Integer;
     252    function GetAttackPower: Integer;
    250253    procedure LoadFromNode(Node: TDOMNode);
    251254    procedure SaveToNode(Node: TDOMNode);
     255    constructor Create;
     256    destructor Destroy; override;
    252257  end;
    253258
     
    256261  TPlayerCells = class(TFPGObjectList<TPlayerCell>)
    257262    Map: TPlayerMap;
     263    function FindByCellId(Id: Integer): TPlayerCell;
    258264    function SearchCell(Cell: TCell): TPlayerCell;
    259265    procedure LoadFromNode(Node: TDOMNode);
     
    266272    Cells: TPlayerCells;
    267273    Player: TPlayer;
     274    procedure PaintCell(Canvas: TCanvas; Pos: TPoint; Text: string; View: TView;
     275      Cell: TPlayerCell);
     276    function PosToCell(Pos: TPoint; View: TView): TPlayerCell; virtual;
     277    function CellToPos(Cell: TPlayerCell): TPoint; virtual;
    268278    procedure LoadFromNode(Node: TDOMNode);
    269279    procedure SaveToNode(Node: TDOMNode);
     
    298308  TUnitMove = class;
    299309
    300   TMoveEvent = procedure(CellFrom, CellTo: TCell; var CountOnce, CountRepeat: Integer;
     310  TMoveEvent = procedure(CellFrom, CellTo: TPlayerCell; var CountOnce, CountRepeat: Integer;
    301311    Update: Boolean; var Confirm: Boolean) of object;
    302312
     
    310320    procedure SetGame(AValue: TGame);
    311321    procedure Attack(var AttackPower, DefendPower: Integer);
    312     procedure ClearMovesFromCell(Cell: TCell);
     322    procedure ClearMovesFromCell(Cell: TPlayerCell);
    313323    procedure MoveAll;
    314324    procedure ReduceMovesPower;
     325    procedure RemoveInvalidMoves;
    315326    procedure CheckCounterMove(Move: TUnitMove);
    316327    procedure SetMode(AValue: TPlayerMode);
     
    333344    TurnStats: TGameTurnStats;
    334345    Moves: TUnitMoves;
    335     function SetMove(CellFrom, CellTo: TCell; Power: Integer; Confirmation: Boolean = True): TUnitMove;
     346    function SetMove(CellFrom, CellTo: TPlayerCell; Power: Integer; Confirmation: Boolean = True): TUnitMove;
    336347    procedure Reset;
    337348    procedure Surrender;
     
    379390  TUnitMove = class
    380391  private
    381     FCellFrom: TCell;
    382     FCellTo: TCell;
    383     procedure SetCellFrom(AValue: TCell);
    384     procedure SetCellTo(AValue: TCell);
     392    FCellFrom: TPlayerCell;
     393    FCellTo: TPlayerCell;
     394    procedure SetCellFrom(AValue: TPlayerCell);
     395    procedure SetCellTo(AValue: TPlayerCell);
    385396  public
    386397    List: TUnitMoves;
     
    391402    constructor Create;
    392403    destructor Destroy; override;
    393     property CellFrom: TCell read FCellFrom write SetCellFrom;
    394     property CellTo: TCell read FCellTo write SetCellTo;
     404    property CellFrom: TPlayerCell read FCellFrom write SetCellFrom;
     405    property CellTo: TPlayerCell read FCellTo write SetCellTo;
    395406  end;
    396407
     
    399410  TUnitMoves = class(TFPGObjectList<TUnitMove>)
    400411    Game: TGame;
    401     function SearchByFromTo(CellFrom, CellTo: TCell): TUnitMove;
     412    Player: TPlayer;
     413    function SearchByFromTo(CellFrom, CellTo: TPlayerCell): TUnitMove;
    402414    procedure LoadFromNode(Node: TDOMNode);
    403415    procedure SaveToNode(Node: TDOMNode);
     
    493505
    494506procedure InitStrings;
    495 function CellCompare(const Item1, Item2: TCell): Integer;
    496 function CellCompareDescending(const Item1, Item2: TCell): Integer;
     507function CellCompare(const Item1, Item2: TPlayerCell): Integer;
     508function CellCompareDescending(const Item1, Item2: TPlayerCell): Integer;
    497509
    498510resourcestring
     
    744756end;
    745757
     758procedure TPlayerCell.ConnectTo(Cell: TPlayerCell);
     759begin
     760  if (Cell.Neighbors.IndexOf(Self) = -1) and
     761  (Neighbors.IndexOf(Cell) = -1) then begin;
     762    Cell.Neighbors.Add(Self);
     763    Neighbors.Add(Cell);
     764  end;
     765end;
     766
     767procedure TPlayerCell.DisconnectFrom(Cell: TPlayerCell);
     768var
     769  I: Integer;
     770begin
     771  I := Cell.Neighbors.IndexOf(Self);
     772  if I >= 0 then Cell.Neighbors.Delete(I) else
     773    raise Exception.Create('Can''t disconnect neigboring cells.');
     774  I := Neighbors.IndexOf(Cell);
     775  if I >= 0 then Neighbors.Delete(I)
     776    else Exception.Create('Can''t disconnect neigboring cells.');
     777end;
     778
     779function TPlayerCell.GetAvialPower: Integer;
     780var
     781  UnitMove: TUnitMove;
     782begin
     783  Result := MapCell.Power;
     784  for UnitMove in MovesFrom do
     785    Result := Result - UnitMove.CountOnce;
     786end;
     787
     788function TPlayerCell.GetAttackPower: Integer;
     789var
     790  I: Integer;
     791begin
     792  Result := 0;
     793  for I := 0 to MovesTo.Count - 1 do
     794    Result := Result + TUnitMove(MovesTo[I]).CountOnce;
     795end;
     796
    746797procedure TPlayerCell.SaveToNode(Node: TDOMNode);
    747798begin
     
    750801end;
    751802
     803constructor TPlayerCell.Create;
     804begin
     805  MovesFrom := TUnitMoves.Create;
     806  MovesFrom.FreeObjects := False;
     807  MovesTo := TUnitMoves.Create;
     808  MovesTo.FreeObjects := False;
     809  Neighbors := TPlayerCells.Create;
     810  Neighbors.FreeObjects := False;
     811end;
     812
     813destructor TPlayerCell.Destroy;
     814var
     815  I: Integer;
     816begin
     817  for I := MovesFrom.Count - 1 downto 0 do
     818    TUnitMove(MovesFrom[I]).List.Remove(TUnitMove(MovesFrom[I]));
     819  FreeAndNil(MovesFrom);
     820  for I := MovesTo.Count - 1 downto 0 do
     821    TUnitMove(MovesTo[I]).List.Remove(TUnitMove(MovesTo[I]));
     822  FreeAndNil(MovesTo);
     823  for I := Neighbors.Count - 1 downto 0 do
     824    if Neighbors[I].Neighbors.Remove(Self) = -1 then
     825      raise Exception.Create(SCellRemoveNeighborError);
     826  FreeAndNil(Neighbors);
     827  inherited Destroy;
     828end;
     829
    752830{ TPlayerCells }
     831
     832function TPlayerCells.FindByCellId(Id: Integer): TPlayerCell;
     833var
     834  I: Integer;
     835begin
     836  I := 0;
     837  while (I < Count) and (Items[I].MapCell.Id <> Id) do Inc(I);
     838  if I < Count then Result := Items[I]
     839    else Result := nil;
     840end;
    753841
    754842function TPlayerCells.SearchCell(Cell: TCell): TPlayerCell;
     
    792880{ TPlayerMap }
    793881
     882procedure TPlayerMap.PaintCell(Canvas: TCanvas; Pos: TPoint; Text: string;
     883  View: TView; Cell: TPlayerCell);
     884var
     885  I: Integer;
     886  TextPos: TPoint;
     887  Points: array of Classes.TPoint;
     888  TextSize: TSize;
     889begin
     890  if Cell.MapCell.Extra = etObjectiveTarget then begin
     891    Text := Text + '!';
     892  end;
     893  with Canvas do begin
     894    if Assigned(View.FocusedCell) and (View.FocusedCell = Cell) then begin
     895      Pen.Color := clYellow;
     896      Pen.Style := psSolid;
     897      Pen.Width := 1;
     898    end else
     899    if Cell.MapCell.Terrain = ttCity then begin
     900      // Cannot set clear border as it will display shifted on gtk2
     901      //Pen.Style := psClear;
     902      Pen.Color := clBlack;
     903      Pen.Style := psSolid;
     904      Pen.Width := 3;
     905    end else begin
     906      // Cannot set clear border as it will display shifted on gtk2
     907      //Pen.Style := psClear;
     908      Pen.Color := Brush.Color;
     909      Pen.Style := psSolid;
     910      Pen.Width := 0;
     911    end;
     912    // Transform view
     913    SetLength(Points, Length(Cell.MapCell.Polygon.Points));
     914    for I := 0 to Length(Points) - 1 do
     915      Points[I] := PointToStdPoint(View.CellToCanvasPos(Cell.MapCell.Polygon.Points[I]));
     916    Brush.Style := bsSolid;
     917    //Polygon(Points, False, 0, Length(Points));
     918    TCanvasEx.PolygonEx(Canvas, Points, False);
     919    //MoveTo(Points[0].X, Points[0].Y);
     920    //LineTo(Points[1].X, Points[1].Y);
     921
     922    // Show cell text
     923    if (Cell.GetAvialPower <> 0) or (Cell.MapCell.Extra = etObjectiveTarget) then begin
     924      Pen.Style := psSolid;
     925      Font.Color := clWhite;
     926      Brush.Style := bsClear;
     927      Font.Size := Trunc(42 * View.Zoom);
     928      TextPos := View.CellToCanvasPos(Pos);
     929      TextSize := TextExtent(Text);
     930      TCanvasEx.TextOutEx(Canvas, Round(TextPos.X) - TextSize.cx div 2,
     931        Round(TextPos.Y) - TextSize.cy div 2, Text, False);
     932    end;
     933  end;
     934end;
     935
     936function TPlayerMap.PosToCell(Pos: TPoint; View: TView): TPlayerCell;
     937var
     938  I: Integer;
     939begin
     940  Result := nil;
     941  for I := 0 to Cells.Count - 1 do
     942  if Cells[I].MapCell.Terrain <> ttVoid then begin
     943    if Cells[I].MapCell.Polygon.IsPointInside(Pos) then begin
     944      Result := Cells[I];
     945      Exit;
     946    end;
     947  end;
     948end;
     949
     950function TPlayerMap.CellToPos(Cell: TPlayerCell): TPoint;
     951begin
     952  Result := Cell.MapCell.PosPx;
     953end;
     954
    794955procedure TPlayerMap.LoadFromNode(Node: TDOMNode);
    795956var
     
    817978var
    818979  I: Integer;
     980  J: Integer;
    819981  OldCount: Integer;
    820982begin
     983  for I := 0 to Cells.Count - 1 do
     984  with TPlayerCell(Cells[I]) do begin
     985    for J := Neighbors.Count - 1 downto 0 do
     986      DisconnectFrom(Neighbors[J]);
     987  end;
     988
    821989  // Update players cells count to map cells count to be 1:1
    822990  OldCount := Cells.Count;
     
    825993    Cells[I] := TPlayerCell.Create;
    826994
     995  for I := 0 to Player.Game.Map.Cells.Count - 1 do begin
     996    with Cells[I] do begin
     997      List := Cells;
     998      Explored := False;
     999      InVisibleRange := False;
     1000      MapCell := Player.Game.Map.Cells[I];
     1001      Player.Game.Map.Cells[I].PlayerCell := Cells[I];
     1002    end;
     1003  end;
     1004
    8271005  for I := 0 to Cells.Count - 1 do
    828   with Cells[I] do begin
    829     List := Cells;
    830     Explored := False;
    831     InVisibleRange := False;
    832     MapCell := Player.Game.Map.Cells[I];
     1006  with TPlayerCell(Cells[I]) do begin
     1007    for J := 0 to MapCell.Neighbors.Count - 1 do
     1008      ConnectTo(TCell(MapCell.Neighbors[J]).PlayerCell);
    8331009  end;
    8341010end;
     
    8961072      if (Cell.MapCell.Terrain <> ttVoid) and Cell.MapCell.IsVisible(View) then begin
    8971073        if Cell.MapCell.Player = Player then
    898           CellText := IntToStr(Cell.MapCell.GetAvialPower)
     1074          CellText := IntToStr(Cell.GetAvialPower)
    8991075          else CellText := IntToStr(Cell.MapCell.Power);
    900         if Assigned(SelectedCell) and (SelectedCell = Cell.MapCell) then
     1076        if Assigned(SelectedCell) and (SelectedCell = Cell) then
    9011077            Brush.Color := clGreen
    902           else if Assigned(SelectedCell) and Player.Game.Map.IsCellsNeighbor(SelectedCell, Cell.MapCell) then
     1078          else if Assigned(SelectedCell) and Player.Game.Map.IsCellsNeighbor(SelectedCell.MapCell, Cell.MapCell) then
    9031079            Brush.Color := clPurple
    9041080          else if Player.Game.FogOfWar then begin
     
    9151091            end;
    9161092          end else Brush.Color := Cell.MapCell.GetColor;
    917         Player.Game.Map.PaintCell(Canvas, Cell.MapCell.PosPx, CellText, View, Cell.MapCell);
     1093        Player.PlayerMap.PaintCell(Canvas, Cell.MapCell.PosPx, CellText, View, Cell);
    9181094      end else
    9191095      if Game.FogOfWar and (Cell.MapCell.Terrain = ttVoid) and (not Cell.Explored) then begin
    9201096        Brush.Color := clBlack;
    921         Player.Game.Map.PaintCell(Canvas, Cell.MapCell.PosPx, '', View, Cell.MapCell);
     1097        Player.PlayerMap.PaintCell(Canvas, Cell.MapCell.PosPx, '', View, Cell);
    9221098      end;
    9231099    end;
     
    9411117    Pen.Color := clCream;
    9421118    for Move in Player.Moves do begin
    943       PosFrom := Player.Game.Map.CellToPos(Move.CellFrom);
    944       PosTo := Player.Game.Map.CellToPos(Move.CellTo);
     1119      PosFrom := Player.Game.Map.CellToPos(Move.CellFrom.MapCell);
     1120      PosTo := Player.Game.Map.CellToPos(Move.CellTo.MapCell);
    9451121      // In Fog of war mode show only
    946       if Game.FogOfWar and not Cells.SearchCell(Move.CellFrom).InVisibleRange and
    947         not Cells.SearchCell(Move.CellTo).InVisibleRange then
     1122      if Game.FogOfWar and not Cells.SearchCell(Move.CellFrom.MapCell).InVisibleRange and
     1123        not Cells.SearchCell(Move.CellTo.MapCell).InVisibleRange then
    9481124        Continue;
    9491125      if Move.CountRepeat > 0 then Pen.Width := 2
     
    12311407{ TUnitMoves }
    12321408
    1233 function TUnitMoves.SearchByFromTo(CellFrom, CellTo: TCell): TUnitMove;
     1409function TUnitMoves.SearchByFromTo(CellFrom, CellTo: TPlayerCell): TUnitMove;
    12341410var
    12351411  UnitMove: TUnitMove;
     
    13081484
    13091485    Cell.Neighbors.Sort(CompareCellAngle);
     1486  end;
     1487end;
     1488
     1489procedure TMap.Paint(Canvas: TCanvas; View: TView);
     1490var
     1491  I: Integer;
     1492  Cell: TCell;
     1493  PosFrom, PosTo: TPoint;
     1494  Angle: Double;
     1495  ArrowCenter: TPoint;
     1496  Move: TUnitMove;
     1497  CellLink: TCellLink;
     1498begin
     1499  with Canvas, View do
     1500  try
     1501    Lock;
     1502
     1503    // Draw cell links
     1504    Pen.Color := clBlack;
     1505    Pen.Style := psSolid;
     1506    Pen.Width := 3;
     1507    for CellLink in CellLinks do
     1508    with CellLink do begin
     1509      if Length(Points) >= 2 then begin
     1510        MoveTo(PointToStdPoint(View.CellToCanvasPos(Points[0])));
     1511        for I := 1 to Length(Points) - 1 do
     1512          LineTo(PointToStdPoint(View.CellToCanvasPos(Points[I])));
     1513      end;
     1514    end;
     1515
     1516    // Draw cells
     1517    for Cell in Cells do begin
     1518      if (Cell.Terrain <> ttVoid) and Cell.IsVisible(View) then begin
     1519        if Assigned(SelectedCell) and (SelectedCell.MapCell = Cell) then
     1520          Brush.Color := clGreen
     1521          else if Assigned(SelectedCell) and IsCellsNeighbor(SelectedCell.MapCell, Cell) then
     1522            Brush.Color := clPurple
     1523          else Brush.Color := Cell.GetColor;
     1524        //Pen.Color := clBlack;
     1525        PaintCell(Canvas, Cell.PosPx, IntToStr(Cell.Power), View, Cell);
     1526      end;
     1527    end;
     1528  finally
     1529    Unlock;
    13101530  end;
    13111531end;
     
    15291749  end;
    15301750  with Canvas do begin
    1531     if Assigned(View.FocusedCell) and (View.FocusedCell = Cell) then begin
     1751    if Assigned(View.FocusedCell) and (View.FocusedCell.MapCell = Cell) then begin
    15321752      Pen.Color := clYellow;
    15331753      Pen.Style := psSolid;
     
    15581778
    15591779    // Show cell text
    1560     if (Cell.GetAvialPower <> 0) or (Cell.Extra = etObjectiveTarget) then begin
     1780    if (Cell.Power <> 0) or (Cell.Extra = etObjectiveTarget) then begin
    15611781      Pen.Style := psSolid;
    15621782      Font.Color := clWhite;
     
    17531973{ TUnitMove }
    17541974
    1755 procedure TUnitMove.SetCellFrom(AValue: TCell);
     1975procedure TUnitMove.SetCellFrom(AValue: TPlayerCell);
    17561976begin
    17571977  if FCellFrom = AValue then Exit;
     
    17651985end;
    17661986
    1767 procedure TUnitMove.SetCellTo(AValue: TCell);
     1987procedure TUnitMove.SetCellTo(AValue: TPlayerCell);
    17681988begin
    17691989  if FCellTo = AValue then Exit;
     
    17812001  CountOnce := ReadInteger(Node, 'CountOnce', 0);
    17822002  CountRepeat := ReadInteger(Node, 'CountRepeat', 0);
    1783   CellFrom := List.Game.Map.Cells.FindById(ReadInteger(Node, 'CellFrom', 0));
    1784   CellTo := List.Game.Map.Cells.FindById(ReadInteger(Node, 'CellTo', 0));
     2003  CellFrom := List.Player.PlayerMap.Cells.FindByCellId(ReadInteger(Node, 'CellFrom', 0));
     2004  CellTo := List.Player.PlayerMap.Cells.FindByCellId(ReadInteger(Node, 'CellTo', 0));
    17852005end;
    17862006
     
    17892009  WriteInteger(Node, 'CountOnce', CountOnce);
    17902010  WriteInteger(Node, 'CountRepeat', CountRepeat);
    1791   WriteInteger(Node, 'CellFrom', CellFrom.Id);
    1792   WriteInteger(Node, 'CellTo', CellTo.Id);
     2011  WriteInteger(Node, 'CellFrom', CellFrom.MapCell.Id);
     2012  WriteInteger(Node, 'CellTo', CellTo.MapCell.Id);
    17932013end;
    17942014
     
    18792099  if I >= 0 then Neighbors.Delete(I)
    18802100    else Exception.Create('Can''t disconnect neigboring cells.');
    1881 end;
    1882 
    1883 procedure TCell.Check;
    1884 var
    1885   AvailPower: Integer;
    1886 begin
    1887   AvailPower := GetAvialPower;
    1888   if AvailPower < 0 then
    1889     raise Exception.Create(Format(SUnitPowerMismatch, [Power, -(AvailPower - Power)]));
    18902101end;
    18912102
     
    20362247end;
    20372248
    2038 function TCell.GetAvialPower: Integer;
    2039 var
    2040   UnitMove: TUnitMove;
    2041 begin
    2042   Result := Power;
    2043   for UnitMove in MovesFrom do
    2044     Result := Result - UnitMove.CountOnce;
    2045 end;
    2046 
    2047 function TCell.GetAttackPower: Integer;
    2048 var
    2049   I: Integer;
    2050 begin
    2051   Result := 0;
    2052   for I := 0 to MovesTo.Count - 1 do
    2053     Result := Result + TUnitMove(MovesTo[I]).CountOnce;
    2054 end;
    2055 
    20562249function TCell.ToString: ansistring;
    20572250begin
     
    20652258  Neighbors := TCells.Create;
    20662259  Neighbors.FreeObjects := False;
    2067   MovesFrom := TUnitMoves.Create;
    2068   MovesFrom.FreeObjects := False;
    2069   MovesTo := TUnitMoves.Create;
    2070   MovesTo.FreeObjects := False;
    20712260  Links := TCellLinks.Create;
    20722261  Links.FreeObjects := False;
     
    20772266  I: Integer;
    20782267begin
    2079   for I := MovesFrom.Count - 1 downto 0 do
    2080     TUnitMove(MovesFrom[I]).List.Remove(TUnitMove(MovesFrom[I]));
    2081   FreeAndNil(MovesFrom);
    2082   for I := MovesTo.Count - 1 downto 0 do
    2083     TUnitMove(MovesTo[I]).List.Remove(TUnitMove(MovesTo[I]));
    2084   FreeAndNil(MovesTo);
    20852268  for I := Links.Count - 1 downto 0 do
    20862269    FMap.CellLinks.Remove(Links[I]);
     
    21692352    if Assigned(NewNode) then
    21702353      PlayerMap.LoadFromNode(NewNode);
     2354    PlayerMap.Update;
    21712355  end;
    21722356  with Node do begin
     
    22202404begin
    22212405  Moves := TUnitMoves.Create;
     2406  Moves.Player := Self;
    22222407  StartUnits := DefaultPlayerStartUnits;
    22232408  StartCell := nil;
     
    23252510end;
    23262511
    2327 function CellCompare(const Item1, Item2: TCell): Integer;
    2328 begin
    2329   if Item1.Power > Item2.Power then Result := 1
    2330   else if Item1.Power < Item2.Power then Result := -1
     2512function CellCompare(const Item1, Item2: TPlayerCell): Integer;
     2513begin
     2514  if Item1.MapCell.Power > Item2.MapCell.Power then Result := 1
     2515  else if Item1.MapCell.Power < Item2.MapCell.Power then Result := -1
    23312516  else Result := 0;
    23322517end;
    23332518
    2334 function CellCompareDescending(const Item1, Item2: TCell): Integer;
    2335 begin
    2336   if Item1.Power > Item2.Power then Result := -1
    2337   else if Item1.Power < Item2.Power then Result := 1
     2519function CellCompareDescending(const Item1, Item2: TPlayerCell): Integer;
     2520begin
     2521  if Item1.MapCell.Power > Item2.MapCell.Power then Result := -1
     2522  else if Item1.MapCell.Power < Item2.MapCell.Power then Result := 1
    23382523  else Result := 0;
    23392524end;
     
    23432528procedure TView.SelectCell(Pos: TPoint; Player: TPlayer; ShiftState: TShiftState);
    23442529var
    2345   NewSelectedCell: TCell;
     2530  NewSelectedCell: TPlayerCell;
    23462531  UnitMove: TUnitMove;
    23472532  I: Integer;
    23482533begin
    2349   NewSelectedCell := Game.Map.PosToCell(CanvasToCellPos(Pos), Self);
     2534  NewSelectedCell := Player.PlayerMap.PosToCell(CanvasToCellPos(Pos), Self);
    23502535  if Assigned(NewSelectedCell) then begin
    2351     if Assigned(SelectedCell) and Game.Map.IsCellsNeighbor(NewSelectedCell, SelectedCell) then begin
     2536    if Assigned(SelectedCell) and Game.Map.IsCellsNeighbor(NewSelectedCell.MapCell, SelectedCell.MapCell) then begin
    23522537      if ssShift in ShiftState then begin
    23532538        // Make maximum unit move without confirmation dialog
     
    23552540          Player.Moves.Remove(SelectedCell.MovesFrom[I]);
    23562541        end;
    2357         Game.CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.Power, False);
     2542        Game.CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.Power, False);
    23582543        SelectedCell := nil;
    23592544      end else
     
    23632548        for I := SelectedCell.MovesFrom.Count - 1 downto 0 do
    23642549          Player.Moves.Remove(SelectedCell.MovesFrom[I]);
    2365         UnitMove := Game.CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.Power, False);
     2550        UnitMove := Game.CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.Power, False);
    23662551        if Assigned(UnitMove) then
    23672552          UnitMove.CountRepeat := Player.Game.Map.MaxPower;
    2368         if NewSelectedCell.Player = Player then SelectedCell := NewSelectedCell
     2553        if NewSelectedCell.MapCell.Player = Player then SelectedCell := NewSelectedCell
    23692554          else SelectedCell := nil;
    23702555      end else begin
    2371         Game.CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.Power);
     2556        Game.CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.Power);
    23722557        SelectedCell := nil;
    23732558      end;
    23742559    end else
    2375     if (NewSelectedCell <> SelectedCell) and (NewSelectedCell.Player = Player) then
     2560    if (NewSelectedCell <> SelectedCell) and (NewSelectedCell.MapCell.Player = Player) then
    23762561      SelectedCell := NewSelectedCell
    23772562    else
    2378     if (NewSelectedCell = SelectedCell) and (NewSelectedCell.Player = Player) then
     2563    if (NewSelectedCell = SelectedCell) and (NewSelectedCell.MapCell.Player = Player) then
    23792564      SelectedCell := nil;
    23802565  end;
     
    24122597  with UnitMove do begin
    24132598  if CountOnce > 0 then begin
    2414     if CellFrom.Player = Self then begin
     2599    if CellFrom.MapCell.Player = Self then begin
    24152600      UnitCount := CountOnce;
    2416       if CountOnce > CellFrom.Power then
    2417         UnitCount := CellFrom.Power;
     2601      if CountOnce > CellFrom.MapCell.Power then
     2602        UnitCount := CellFrom.MapCell.Power;
    24182603      CountOnce := 0;
    2419       if CellTo.Player = Self then begin
     2604      if CellTo.MapCell.Player = Self then begin
    24202605        // Inner move
    2421         CellTo.Power := CellTo.Power + UnitCount;
     2606        CellTo.MapCell.Power := CellTo.MapCell.Power + UnitCount;
    24222607      end else begin
    24232608        AttackerPower := UnitCount;
    2424         DefenderPower := CellTo.Power;
     2609        DefenderPower := CellTo.MapCell.Power;
    24252610        Attack(AttackerPower, DefenderPower);
    24262611        if DefenderPower = 0 then begin
    24272612          // Attacker wins with possible loses
    24282613          ClearMovesFromCell(CellTo);
    2429           CellTo.Player := Self;
    2430           CellTo.Power := AttackerPower;
     2614          CellTo.MapCell.Player := Self;
     2615          CellTo.MapCell.Power := AttackerPower;
    24312616        end else
    24322617        if AttackerPower = 0 then begin
    24332618          // Defender wins with possible loses
    2434           CellTo.Power := DefenderPower;
     2619          CellTo.MapCell.Power := DefenderPower;
    24352620        end else
    24362621          raise Exception.Create(SUnfinishedBattle);
    24372622      end;
    2438       CellFrom.Power := CellFrom.Power - UnitCount;
     2623      CellFrom.MapCell.Power := CellFrom.MapCell.Power - UnitCount;
    24392624    end;
    24402625    end;
     
    24592644end;
    24602645
    2461 procedure TPlayer.ClearMovesFromCell(Cell: TCell);
    2462 var
    2463   I: Integer;
    2464 begin
    2465   if Assigned(Cell.Player) then
    2466   for I := Cell.Player.Moves.Count - 1 downto 0 do
    2467   if TUnitMove(Cell.Player.Moves[I]).CellFrom = Cell then
    2468     Cell.Player.Moves.Delete(I);
    2469 end;
    2470 
    2471 function TPlayer.SetMove(CellFrom, CellTo: TCell; Power: Integer; Confirmation: Boolean = True): TUnitMove;
     2646procedure TPlayer.RemoveInvalidMoves;
     2647var
     2648  I: Integer;
     2649begin
     2650  for I := Moves.Count - 1 downto 0 do
     2651    if Moves[I].CellFrom.MapCell.Player <> Self then
     2652      Moves.Delete(I);
     2653end;
     2654
     2655procedure TPlayer.ClearMovesFromCell(Cell: TPlayerCell);
     2656var
     2657  I: Integer;
     2658begin
     2659  for I := Cell.MovesFrom.Count - 1 downto 0 do
     2660    Cell.MovesFrom.Delete(I);
     2661end;
     2662
     2663function TPlayer.SetMove(CellFrom, CellTo: TPlayerCell; Power: Integer; Confirmation: Boolean = True): TUnitMove;
    24722664var
    24732665  NewMove: TUnitMove;
     
    24762668  Confirm: Boolean;
    24772669begin
    2478   if CellFrom.Player <> Self then
     2670  if CellFrom.MapCell.Player <> Self then
    24792671    raise Exception.Create('Can''t set move of other player.');
    24802672  Confirm := True;
     
    25182710      end;
    25192711    end;
    2520     CellFrom.Check;
    25212712    if Assigned(Game.FOnMoveUpdated) then Game.FOnMoveUpdated(Result);
    25222713  end;
     
    25292720  for Move in Moves do
    25302721  with Move do begin
    2531     if CellFrom.Player = Self then
     2722    if CellFrom.MapCell.Player = Self then
    25322723      if CountRepeat <= CellFrom.GetAvialPower then
    25332724        CountOnce := CountRepeat
     
    25432734  // Remove empty moves
    25442735  for I := Moves.Count - 1 downto 0 do
    2545   if (TUnitMove(Moves[I]).CellFrom.Player = Self) and
     2736  if (TUnitMove(Moves[I]).CellFrom.MapCell.Player = Self) and
    25462737    (TUnitMove(Moves[I]).CountOnce = 0) and (TUnitMove(Moves[I]).CountRepeat = 0) then
    25472738    Moves.Delete(I);
     
    27062897    Area := NewArea;
    27072898    AreaExtend;
    2708   end;
    2709 end;
    2710 
    2711 procedure TMap.Paint(Canvas: TCanvas; View: TView);
    2712 var
    2713   I: Integer;
    2714   Cell: TCell;
    2715   PosFrom, PosTo: TPoint;
    2716   Angle: Double;
    2717   ArrowCenter: TPoint;
    2718   Move: TUnitMove;
    2719   CellLink: TCellLink;
    2720 begin
    2721   with Canvas, View do
    2722   try
    2723     Lock;
    2724 
    2725     // Draw cell links
    2726     Pen.Color := clBlack;
    2727     Pen.Style := psSolid;
    2728     Pen.Width := 3;
    2729     for CellLink in CellLinks do
    2730     with CellLink do begin
    2731       if Length(Points) >= 2 then begin
    2732         MoveTo(PointToStdPoint(View.CellToCanvasPos(Points[0])));
    2733         for I := 1 to Length(Points) - 1 do
    2734           LineTo(PointToStdPoint(View.CellToCanvasPos(Points[I])));
    2735       end;
    2736     end;
    2737 
    2738     // Draw cells
    2739     for Cell in Cells do begin
    2740       if (Cell.Terrain <> ttVoid) and Cell.IsVisible(View) then begin
    2741         if Assigned(SelectedCell) and (SelectedCell = Cell) then
    2742             Brush.Color := clGreen
    2743           else if Assigned(SelectedCell) and IsCellsNeighbor(SelectedCell, Cell) then
    2744             Brush.Color := clPurple
    2745           else Brush.Color := Cell.GetColor;
    2746         //Pen.Color := clBlack;
    2747         PaintCell(Canvas, Cell.PosPx, IntToStr(Cell.GetAvialPower), View, Cell);
    2748       end;
    2749     end;
    2750 
    2751     // Draw arrows
    2752     Pen.Color := clCream;
    2753     for Move in Game.CurrentPlayer.Moves do begin
    2754       PosFrom := CellToPos(Move.CellFrom);
    2755       PosTo := CellToPos(Move.CellTo);
    2756       if Move.CountRepeat > 0 then Pen.Width := 2
    2757         else Pen.Width := 1;
    2758       Angle := ArcTan((PosTo.Y - PosFrom.Y) / (PosTo.X - PosFrom.X));
    2759       if Sign(PosTo.X - PosFrom.X) = -1 then Angle := Angle + Pi;
    2760       ArrowCenter := View.CellToCanvasPos(TPoint.Create(Trunc(PosFrom.X + (PosTo.X - PosFrom.X) / 2),
    2761         Trunc(PosFrom.Y + (PosTo.Y - PosFrom.Y) / 2)));
    2762       DrawArrow(Canvas, View, ArrowCenter,
    2763         Angle, IntToStr(Move.CountOnce));
    2764     end;
    2765   finally
    2766     Unlock;
    27672899  end;
    27682900end;
     
    32493381  CurrentPlayer.PlayerMap.CheckVisibility;
    32503382  CurrentPlayer.ReduceMovesPower;
     3383  CurrentPlayer.RemoveInvalidMoves;
    32513384  if Assigned(FOnChange) then
    32523385    FOnChange(Self);
  • trunk/UGameClient.pas

    r220 r223  
    3333    procedure SetForm(AValue: TForm);
    3434    procedure SetGame(AValue: TGame);
    35     procedure PlayerMove(CellFrom, CellTo: TCell; var CountOnce, CountRepeat: Integer;
     35    procedure PlayerMove(CellFrom, CellTo: TPlayerCell; var CountOnce, CountRepeat: Integer;
    3636      Update: Boolean; var Confirm: Boolean);
    3737    procedure SetOnMove(AValue: TMoveEvent);
     
    124124end;
    125125
    126 procedure TClient.PlayerMove(CellFrom, CellTo: TCell; var CountOnce,
     126procedure TClient.PlayerMove(CellFrom, CellTo: TPlayerCell; var CountOnce,
    127127  CountRepeat: Integer; Update: Boolean; var Confirm: Boolean);
    128128begin
Note: See TracChangeset for help on using the changeset viewer.