Changeset 265


Ignore:
Timestamp:
Jan 15, 2019, 1:03:40 AM (6 years ago)
Author:
chronos
Message:
  • Modified: Cell power is now internally represented as unit power (TUnit class).
  • Modified: Allow to have only one player in the game.
  • Added: New win objective None to just play freely without any win objective.
  • Added: New win objective to capture entire map.
  • Added: TGameSystem class to represent various game play systems of other existing games.
  • Fixed: Clear correctly defender player from unit moves if his cell is captured.
  • Fixed: Do not allow to remove too many players to have at least minimum players.
Location:
trunk
Files:
3 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Forms/UFormClient.lfm

    r249 r265  
    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 = 30
    20     Top = 591
     19    Height = 28
     20    Top = 593
    2121    Width = 775
    2222    Panels = <   
     
    3434  object ToolBar1: TToolBar
    3535    Left = 0
    36     Height = 591
     36    Height = 593
    3737    Top = 0
    3838    Width = 32
     
    8080  object PaintBox1: TPaintBox
    8181    Left = 32
    82     Height = 591
     82    Height = 593
    8383    Top = 0
    8484    Width = 743
  • trunk/Forms/UFormClient.pas

    r249 r265  
    152152    FormMove.TrackBarRepeat.Max := FormMove.SpinEditRepeat.MaxValue;
    153153    FormMove.TrackBarRepeat.Position := FormMove.SpinEditRepeat.Value;
    154     FormMove.DefendCount := CellTo.MapCell.Power;
     154    if Assigned(CellTo.MapCell.OneUnit) then
     155      FormMove.DefendCount := CellTo.MapCell.OneUnit.Power
     156      else FormMove.DefendCount := 0;
    155157    // Attack count from other surrounding cells without current move if already exists
    156158    FormMove.AttackCount := 0;
  • trunk/Forms/UFormNew.lfm

    r263 r265  
    1515  OnShow = FormShow
    1616  Position = poMainFormCenter
    17   LCLVersion = '1.8.2.0'
     17  LCLVersion = '1.8.4.0'
    1818  object PageControl1: TPageControl
    1919    Left = 4
     
    2121    Top = 4
    2222    Width = 749
    23     ActivePage = TabSheetMap
     23    ActivePage = TabSheetRules
    2424    Align = alClient
    2525    BorderSpacing.Around = 4
    26     TabIndex = 2
     26    TabIndex = 3
    2727    TabOrder = 0
    2828    object TabSheetMode: TTabSheet
    2929      Caption = 'Mode'
    30       ClientHeight = 651
    31       ClientWidth = 743
     30      ClientHeight = 655
     31      ClientWidth = 739
    3232      object Panel3: TPanel
    3333        Left = 0
     
    113113            item
    114114              Caption = 'Address'
    115               Width = 214
     115              Width = 219
    116116            end>
    117117          MultiSelect = True
     
    158158    object TabSheetPlayers: TTabSheet
    159159      Caption = 'Players'
    160       ClientHeight = 651
    161       ClientWidth = 743
     160      ClientHeight = 655
     161      ClientWidth = 739
    162162      object Panel2: TPanel
    163163        Left = 0
    164         Height = 651
     164        Height = 655
    165165        Top = 0
    166         Width = 743
     166        Width = 739
    167167        Align = alClient
    168168        BevelOuter = bvNone
    169         ClientHeight = 651
    170         ClientWidth = 743
     169        ClientHeight = 655
     170        ClientWidth = 739
    171171        TabOrder = 0
    172172        object ListViewPlayers: TListView
    173173          Left = 4
    174           Height = 601
     174          Height = 605
    175175          Top = 4
    176           Width = 735
     176          Width = 731
    177177          Align = alTop
    178178          Anchors = [akTop, akLeft, akRight, akBottom]
     
    212212          Left = 16
    213213          Height = 25
    214           Top = 613
     214          Top = 617
    215215          Width = 83
    216216          Action = APlayerAdd
     
    221221          Left = 120
    222222          Height = 25
    223           Top = 613
     223          Top = 617
    224224          Width = 83
    225225          Action = APlayerModify
     
    230230          Left = 224
    231231          Height = 25
    232           Top = 613
     232          Top = 617
    233233          Width = 83
    234234          Action = APlayerRemove
     
    240240    object TabSheetMap: TTabSheet
    241241      Caption = 'Map'
    242       ClientHeight = 651
    243       ClientWidth = 743
     242      ClientHeight = 655
     243      ClientWidth = 739
    244244      object Panel1: TPanel
    245245        Left = 0
    246         Height = 651
     246        Height = 655
    247247        Top = 0
    248         Width = 743
     248        Width = 739
    249249        Align = alClient
    250250        BevelOuter = bvNone
    251         ClientHeight = 651
    252         ClientWidth = 743
     251        ClientHeight = 655
     252        ClientWidth = 739
    253253        TabOrder = 0
    254254        object Label1: TLabel
     
    270270        object SpinEditMapSizeX: TSpinEdit
    271271          Left = 128
    272           Height = 36
     272          Height = 43
    273273          Top = 4
    274274          Width = 98
     
    280280        object SpinEditMapSizeY: TSpinEdit
    281281          Left = 128
    282           Height = 36
     282          Height = 43
    283283          Top = 55
    284284          Width = 98
     
    290290        object TrackBarSizeX: TTrackBar
    291291          Left = 240
    292           Height = 47
     292          Height = 58
    293293          Top = 8
    294           Width = 492
     294          Width = 488
    295295          Max = 100
    296296          Min = 2
     
    303303        object TrackBarSizeY: TTrackBar
    304304          Left = 240
    305           Height = 47
     305          Height = 58
    306306          Top = 49
    307           Width = 492
     307          Width = 488
    308308          Max = 100
    309309          Min = 2
     
    324324        object ComboBoxGridType: TComboBox
    325325          Left = 146
    326           Height = 36
     326          Height = 42
    327327          Top = 104
    328328          Width = 208
     
    340340        object ComboBoxMapShape: TComboBox
    341341          Left = 146
    342           Height = 36
     342          Height = 42
    343343          Top = 144
    344344          Width = 208
     
    365365          Height = 27
    366366          Top = 110
    367           Width = 255
     367          Width = 251
    368368          Anchors = [akTop, akLeft, akRight]
    369369          AutoSize = False
     
    373373        object SpinEditVoidPercent: TSpinEdit
    374374          Left = 216
    375           Height = 36
     375          Height = 43
    376376          Top = 224
    377377          Width = 106
     
    384384          Height = 30
    385385          Top = 232
    386           Width = 187
     386          Width = 189
    387387          Caption = 'Inaccessible places'
    388388          OnChange = CheckBoxVoidChange
     
    393393          Height = 30
    394394          Top = 272
    395           Width = 71
     395          Width = 73
    396396          Caption = 'Cities'
    397397          OnChange = CheckBoxCityChange
     
    400400        object SpinEditCityPercent: TSpinEdit
    401401          Left = 216
    402           Height = 36
     402          Height = 43
    403403          Top = 272
    404404          Width = 106
     
    425425        object SpinEditNeutralUnits: TSpinEdit
    426426          Left = 408
    427           Height = 36
     427          Height = 43
    428428          Top = 384
    429429          Width = 98
     
    442442        object EditImageFile: TEdit
    443443          Left = 144
    444           Height = 36
     444          Height = 43
    445445          Top = 184
    446           Width = 476
     446          Width = 472
    447447          Anchors = [akTop, akLeft, akRight]
    448448          TabOrder = 12
    449449        end
    450450        object ButtonImageBrowse: TButton
    451           Left = 628
     451          Left = 624
    452452          Height = 25
    453453          Top = 192
     
    470470          Height = 30
    471471          Top = 310
    472           Width = 210
     472          Width = 212
    473473          Caption = 'Bridges between cells'
    474474          TabOrder = 14
     
    476476        object SpinEditMaxPower: TSpinEdit
    477477          Left = 408
    478           Height = 36
     478          Height = 43
    479479          Top = 344
    480480          Width = 98
     
    497497          Height = 27
    498498          Top = 137
    499           Width = 255
     499          Width = 251
    500500          Anchors = [akTop, akLeft, akRight]
    501501          AutoSize = False
     
    507507    object TabSheetRules: TTabSheet
    508508      Caption = 'Rules'
    509       ClientHeight = 651
    510       ClientWidth = 743
     509      ClientHeight = 655
     510      ClientWidth = 739
    511511      object Panel4: TPanel
    512512        Left = 0
    513         Height = 651
     513        Height = 655
    514514        Top = 0
    515         Width = 743
     515        Width = 739
    516516        Align = alClient
    517517        BevelOuter = bvNone
    518         ClientHeight = 651
    519         ClientWidth = 743
     518        ClientHeight = 655
     519        ClientWidth = 739
    520520        TabOrder = 0
    521521        object RadioGroupGrowCells: TRadioGroup
     
    533533          ChildSizing.Layout = cclLeftToRightThenTopToBottom
    534534          ChildSizing.ControlsPerLine = 1
    535           ClientHeight = 77
    536           ClientWidth = 308
     535          ClientHeight = 78
     536          ClientWidth = 310
    537537          Items.Strings = (
    538538            'None'
     
    552552        object ComboBoxWinObjective: TComboBox
    553553          Left = 224
    554           Height = 36
     554          Height = 38
    555555          Top = 244
    556556          Width = 328
     
    580580          ChildSizing.Layout = cclLeftToRightThenTopToBottom
    581581          ChildSizing.ControlsPerLine = 1
    582           ClientHeight = 48
    583           ClientWidth = 301
     582          ClientHeight = 49
     583          ClientWidth = 303
    584584          Items.Strings = (
    585585            'By one'
     
    592592          Height = 30
    593593          Top = 24
    594           Width = 113
     594          Width = 115
    595595          Caption = 'Fog of war'
    596596          TabOrder = 3
     
    600600          Height = 78
    601601          Top = 290
    602           Width = 720
     602          Width = 716
    603603          ActivePage = TabSheetCaptureCities
    604604          Anchors = [akTop, akLeft, akRight]
     
    611611          end
    612612          object TabSheetCaptureCells: TTabSheet
    613             ClientHeight = 72
    614             ClientWidth = 714
     613            ClientHeight = 74
     614            ClientWidth = 706
    615615            object Label14: TLabel
    616616              Left = 8
     
    633633          end
    634634          object TabSheetStayAliveTurns: TTabSheet
    635             ClientHeight = 72
    636             ClientWidth = 714
     635            ClientHeight = 74
     636            ClientWidth = 706
    637637            object Label13: TLabel
    638638              Left = 8
     
    659659          Height = 30
    660660          Top = 62
    661           Width = 360
     661          Width = 362
    662662          Caption = 'Set cells without player units as neutral'
    663663          TabOrder = 5
  • trunk/Forms/UFormNew.pas

    r263 r265  
    163163  SGridTypeRandom = 'Random';
    164164  SGridTypeIsometric = 'Isometric';
     165  SWinObjectiveNone = 'None';
    165166  SWinObjectiveDefeatAllOponents = 'Defeat all oponents';
    166167  SWinObjectiveDefeatAllCities = 'Defeat all oponents cities';
    167168  SWinObjectiveCapturePosition = 'Capture all special cells';
    168169  SWinObjectiveStayAliveForTurns = 'Stay alive for number of turns';
     170  SWinObjectiveCaptureEntireMap = 'Capture entire map';
    169171  SGrowNone = 'None';
    170172  SGrowPlayerCities = 'Player cities';
     
    283285    LastIndex := ItemIndex;
    284286    Clear;
     287    Items.Add(SWinObjectiveNone);
    285288    Items.Add(SWinObjectiveDefeatAllOponents);
    286289    Items.Add(SWinObjectiveDefeatAllCities);
    287290    Items.Add(SWinObjectiveCapturePosition);
    288291    Items.Add(SWinObjectiveStayAliveForTurns);
     292    Items.Add(SWinObjectiveCaptureEntireMap);
    289293    ItemIndex := LastIndex;
    290294  end;
     
    327331procedure TFormNew.UpdateInterface;
    328332begin
    329   APlayerRemove.Enabled := Assigned(ListViewPlayers.Selected) and (Players.Count > 2);
     333  APlayerRemove.Enabled := Assigned(ListViewPlayers.Selected) and (Players.Count > MinPlayerCount);
    330334  APlayerAdd.Enabled := Players.Count < MaxPlayerCount;
    331335  APlayerModify.Enabled := Assigned(ListViewPlayers.Selected);
     
    427431  if ListViewPlayers.Items[I].Selected then begin
    428432    Players.Remove(ListViewPlayers.Items[I].Data);
     433    if Players.Count <= MinPlayerCount then Break;
    429434  end;
    430435  ReloadView;
     
    487492  if Players.Count <= (MaxPlayerCount - 1) then begin
    488493    NewPlayer := TPlayer.Create;
    489     NewPlayer.Id := Players.GetNewPlayerId;
     494    NewPlayer.Id := Players.GetNewId;
    490495    NewPlayer.Name := SPlayer + ' ' + IntToStr(NewPlayer.Id);
    491496    NewPlayer.Color := PlayerColors[Players.Count];
     
    539544    SpinEditTurns.Value := StayAliveForDefinedTurns;
    540545    SpinEditSpecialCells.Value := SpecialCaptureCellCount;
    541     CheckBoxEmptyCellsNeutral.Checked := EmptyCellsNeutral;
     546    CheckBoxEmptyCellsNeutral.Checked := GameSystem.EmptyCellsNeutral;
    542547  end;
    543548end;
     
    582587    StayAliveForDefinedTurns := SpinEditTurns.Value;
    583588    SpecialCaptureCellCount := SpinEditSpecialCells.Value;
    584     EmptyCellsNeutral := CheckBoxEmptyCellsNeutral.Checked;
     589    GameSystem.EmptyCellsNeutral := CheckBoxEmptyCellsNeutral.Checked;
    585590  end;
    586591end;
  • trunk/Languages/xtactics.cs.po

    r263 r265  
    99"MIME-Version: 1.0\n"
    1010"Content-Transfer-Encoding: 8bit\n"
    11 "X-Generator: Poedit 2.0.6\n"
     11"X-Generator: Poedit 2.1.1\n"
    1212"Language: cs\n"
    1313
     
    924924
    925925#: uformnew.sgrownone
     926msgctxt "uformnew.sgrownone"
    926927msgid "None"
    927928msgstr "Nikde"
     
    951952msgstr "Zakulacený"
    952953
     954#: uformnew.swinobjectivecaptureentiremap
     955msgid "Capture entire map"
     956msgstr "Obsadit celou mapu"
     957
    953958#: uformnew.swinobjectivecaptureposition
    954959msgid "Capture all special cells"
     
    962967msgid "Defeat all oponents"
    963968msgstr "Porazit všechny nepřátele"
     969
     970#: uformnew.swinobjectivenone
     971msgctxt "uformnew.swinobjectivenone"
     972msgid "None"
     973msgstr "Žádný"
    964974
    965975#: uformnew.swinobjectivestayaliveforturns
     
    10001010
    10011011#: ugame.sminimumplayers
    1002 msgid "You need at least two players"
    1003 msgstr "Potřebujete alespoň dva hráče"
     1012msgid "You need at least one player"
     1013msgstr "Potřebujete alespoň jednoho hráče"
    10041014
    10051015#: ugame.snewgamefile
  • trunk/Languages/xtactics.po

    r263 r265  
    901901
    902902#: uformnew.sgrownone
     903msgctxt "uformnew.sgrownone"
    903904msgid "None"
    904905msgstr ""
     
    928929msgstr ""
    929930
     931#: uformnew.swinobjectivecaptureentiremap
     932msgid "Capture entire map"
     933msgstr ""
     934
    930935#: uformnew.swinobjectivecaptureposition
    931936msgid "Capture all special cells"
     
    938943#: uformnew.swinobjectivedefeatalloponents
    939944msgid "Defeat all oponents"
     945msgstr ""
     946
     947#: uformnew.swinobjectivenone
     948msgctxt "uformnew.swinobjectivenone"
     949msgid "None"
    940950msgstr ""
    941951
     
    977987
    978988#: ugame.sminimumplayers
    979 msgid "You need at least two players"
     989msgid "You need at least one player"
    980990msgstr ""
    981991
  • trunk/UClientAI.pas

    r231 r265  
    4444  TotalAttackPower: Integer;
    4545  CanAttack: Integer;
     46  TargetPower: Integer;
    4647  TargetCells: TPlayerCells;
    4748  Cell: TPlayerCell;
     
    8182
    8283      // Attack if target is weaker
    83       if TotalPower >= (MapCell.Power + AttackDiff) then begin
     84      if Assigned(MapCell.OneUnit) then TargetPower := MapCell.OneUnit.Power
     85        else TargetPower := 0;
     86      if TotalPower >= (TargetPower + AttackDiff) then begin
    8487        TotalAttackPower := 0;
    8588        for NeighborCell in Neighbors do
    8689        if NeighborCell.MapCell.Player = ControlPlayer then begin
    8790          // Use only necessary power
    88           AttackPower := MapCell.Power - TotalAttackPower + AttackDiff;
     91          AttackPower := TargetPower - TotalAttackPower + AttackDiff;
    8992          if NeighborCell.GetAvialPower < AttackPower then
    9093            AttackPower := NeighborCell.GetAvialPower;
     
    141144      end;
    142145      // Attack if target is weaker
    143       if Game.AttackProbability(TotalPower, TargetCell.MapCell.Power) >=
     146      if Game.AttackProbability(TotalPower, TargetCell.MapCell.OneUnit.Power) >=
    144147        ComputerAggroProbability[ControlPlayer.Agressivity] then begin
    145148        // Try to limit total attacking power to necessary minimum
    146         while Game.AttackProbability(TotalPower - 1, TargetCell.MapCell.Power) >=
     149        while Game.AttackProbability(TotalPower - 1, TargetCell.MapCell.OneUnit.Power) >=
    147150          ComputerAggroProbability[ControlPlayer.Agressivity] do
    148151          Dec(TotalPower);
     
    306309    for I := 0 to Neighbors.Count - 1 do
    307310    if (Neighbors[I].MapCell.Player <> ControlPlayer) and (Neighbors[I].MapCell.Player <> nil) then begin
    308       Inc(EnemyPower, Neighbors[I].MapCell.Power);
     311      Inc(EnemyPower, Neighbors[I].MapCell.OneUnit.Power);
    309312    end;
    310313    if EnemyPower > (GetAvialPower + GetAttackPower) then begin
  • trunk/UClientGUI.pas

    r257 r265  
    190190
    191191    // Show cell text
    192     if (Cell.Power <> 0) or (Cell.Extra = etObjectiveTarget) then begin
     192    if (Cell.OneUnit.Power <> 0) or (Cell.Extra = etObjectiveTarget) then begin
    193193      Pen.Style := psSolid;
    194194      Font.Color := clWhite;
     
    319319          if Cell.MapCell.Player = ControlPlayer then
    320320            CellText := IntToStr(Cell.GetAvialPower)
    321             else CellText := IntToStr(Cell.MapCell.Power);
     321            else begin
     322              if Assigned(Cell.MapCell.OneUnit) then
     323                CellText := IntToStr(Cell.MapCell.OneUnit.Power)
     324                else CellText := '';
     325            end;
    322326          if Assigned(SelectedCell) and (SelectedCell = Cell) then
    323327              Brush.Color := clGreen
     
    349353        if (MapCell.Terrain <> ttVoid) and View.IsCellVisible(MapCell) then begin
    350354          Brush.Color := MapCell.GetColor;
    351           PaintMapCell(Canvas, MapCell.PosPx, IntToStr(MapCell.Power), View, MapCell);
     355          if Assigned(Cell.MapCell.OneUnit) then
     356            CellText := IntToStr(MapCell.OneUnit.Power)
     357            else CellText := '';
     358          PaintMapCell(Canvas, MapCell.PosPx, CellText, View, MapCell);
    352359        end;
    353360      end;
     
    514521          Player.Moves.Remove(SelectedCell.MovesFrom[I]);
    515522        end;
    516         TGame(Game).CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.Power, False);
     523        TGame(Game).CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.OneUnit.Power, False);
    517524        SelectedCell := nil;
    518525      end else
     
    522529        for I := SelectedCell.MovesFrom.Count - 1 downto 0 do
    523530          Player.Moves.Remove(SelectedCell.MovesFrom[I]);
    524         UnitMove := TGame(Game).CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.Power, False);
     531        UnitMove := TGame(Game).CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.OneUnit.Power, False);
    525532        if Assigned(UnitMove) then
    526533          UnitMove.CountRepeat := TGame(Player.Game).Map.MaxPower;
     
    528535          else SelectedCell := nil;
    529536      end else begin
    530         TGame(Game).CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.Power);
     537        TGame(Game).CurrentPlayer.SetMove(SelectedCell, NewSelectedCell, SelectedCell.MapCell.OneUnit.Power);
    531538        SelectedCell := nil;
    532539      end;
  • trunk/UCore.pas

    r254 r265  
    99  UGame, UApplicationInfo, UPersistentForm, UScaleDPI, UCoolTranslator,
    1010  URegistry, ULastOpenedList, UTheme, Registry, Menus, UFormClient, UPlayer,
    11   UGameServer, UGameClient, fgl, UServerList;
     11  UGameServer, UGameClient, fgl, UServerList, UGameSystem, UUnit;
    1212
    1313type
     
    8787    procedure UpdateOtherForms;
    8888    procedure FormClientActions;
     89    procedure InitGameSystems;
    8990  public
    9091    Game: TGame;
     
    99100    LocalClients: TClients;
    100101    ServerList: TServerList;
     102    GameSystems: TGameSystems;
    101103    procedure ReopenGameOnInit;
    102104    procedure LoadConfig;
     
    445447procedure TCore.DataModuleCreate(Sender: TObject);
    446448begin
     449  GameSystems := TGameSystems.Create;
     450  InitGameSystems;
    447451  Server := TServer.Create;
    448452  LocalClients := TClients.Create;
    449453  GameSettings := TGame.Create;
     454  GameSettings.GameSystem := GameSystems.First;
    450455  Game := TGame.Create;
    451456  Game.OnMoveUpdated := DoMoveUpdated;
     
    453458  Game.OnNewTurn := GameNewTurnExecute;
    454459  Game.OnPlayerChange := DoPlayerChange;
     460  Game.GameSystem := GameSystems.First;
    455461  Server.Game := Game;
    456462  LocalClients.Game := Game;
     
    481487  FreeAndNil(Game);
    482488  FreeAndNil(GameSettings);
     489  FreeAndNil(GameSystems);
    483490end;
    484491
     
    486493begin
    487494  LastOpenedList1.LoadToMenuItem(FormMain.MenuItemLoadRecent, LoadRecentExecute);
     495end;
     496
     497procedure TCore.InitGameSystems;
     498begin
     499  with GameSystems.AddNew('HexWars') do begin
     500    MaxPlayerCount := 3;
     501    with UnitKinds.AddNew('Unit') do begin
     502      Moves := 1;
     503      Stack := 99;
     504    end;
     505  end;
     506
     507  with GameSystems.AddNew('Civilization') do begin
     508    MaxPlayerCount := 3;
     509    with UnitKinds.AddNew('Scout') do begin
     510      Moves := 1;
     511      Stack := 1;
     512    end;
     513    with UnitKinds.AddNew('Settler') do begin
     514      Moves := 1;
     515      Stack := 1;
     516    end;
     517  end;
     518
     519  with GameSystems.AddNew('Dune 2') do begin
     520    MaxPlayerCount := 3;
     521    with UnitKinds.AddNew('Light Infantry') do begin
     522      Moves := 1;
     523    end;
     524    with UnitKinds.AddNew('Heavy Troopers') do begin
     525      Moves := 1;
     526    end;
     527    with UnitKinds.AddNew('Trike') do begin
     528      Moves := 1;
     529    end;
     530    with UnitKinds.AddNew('Quad') do begin
     531      Moves := 1;
     532    end;
     533  end;
     534
     535  with GameSystems.AddNew('Battle Isle 2') do begin
     536    MaxPlayerCount := 8;
     537    with UnitKinds.AddNew('Demon 132') do begin
     538      Moves := 4;
     539      Stack := 10;
     540    end;
     541    with UnitKinds.AddNew('Troll 142') do begin
     542      Moves := 3;
     543      Stack := 10;
     544    end;
     545    with UnitKinds.AddNew('Ranger 132') do begin
     546      Moves := 10;
     547      Stack := 10;
     548    end;
     549    with UnitKinds.AddNew('Buggy') do begin
     550      Moves := 10;
     551      Stack := 10;
     552    end;
     553  end;
    488554end;
    489555
  • trunk/UGame.pas

    r263 r265  
    88  Classes, SysUtils, ExtCtrls, Graphics, XMLConf, XMLRead, XMLWrite, Forms,
    99  DOM, Math, LazFileUtils, UXMLUtils, Dialogs, LCLType, LCLIntf, fgl,
    10   UGeometry, UPlayer, UMap, UMapType;
     10  UGeometry, UPlayer, UMap, UMapType, UUnit, UGameSystem;
    1111
    1212const
    1313  DefaultPlayerStartUnits = 5;
     14  MinPlayerCount = 1;
    1415  MaxPlayerCount = 8;
    1516
     
    2829  TGrowCells = (gcNone, gcPlayerCities, gcPlayerAll);
    2930  TMapType = (mtNone, mtHexagon, mtSquare, mtTriangle, mtRandom, mtIsometric);
    30   TWinObjective = (woDefeatAllOponents, woDefeatAllOponentsCities,
    31     woSpecialCaptureCell, woStayAliveForDefinedTurns);
     31  TWinObjective = (woNone, woDefeatAllOponents, woDefeatAllOponentsCities,
     32    woSpecialCaptureCell, woStayAliveForDefinedTurns, woCaptureEntireMap);
    3233
    3334  { TGame }
     
    3536  TGame = class
    3637  private
     38    FGameSystem: TGameSystem;
    3739    FMapType: TMapType;
    3840    FOnChange: TNotifyEvent;
     
    4648    ProbabilityMatrix: array of array of Single;
    4749    procedure RecordTurnStats;
     50    procedure SetGameSystem(AValue: TGameSystem);
    4851    procedure SetMapType(AValue: TMapType);
    4952    procedure SetRunning(AValue: Boolean);
     
    5760    DevelMode: Boolean;
    5861    Players: TPlayers;
     62    Units: TUnits;
    5963    Map: TMap;
    6064    MapImageFileName: string;
     
    7781    BridgeEnabled: Boolean;
    7882    MaxPower: Integer;
    79     EmptyCellsNeutral: Boolean;
    8083    procedure PostConfig;
    8184    procedure Assign(Source: TGame);
     
    9598    property Running: Boolean read FRunning write SetRunning;
    9699    property MapType: TMapType read FMapType write SetMapType;
     100    property GameSystem: TGameSystem read FGameSystem write SetGameSystem;
    97101  published
    98102    property OnMoveUpdated: TMoveUpdatedEvent read FOnMoveUpdated write FOnMoveUpdated;
     
    123127
    124128resourcestring
    125   SMinimumPlayers = 'You need at least two players';
     129  SMinimumPlayers = 'You need at least one player';
    126130  SHuman = 'Human';
    127131  SComputer = 'Computer';
     
    263267  if FRunning = AValue then Exit;
    264268  if AValue then begin
    265     if Players.Count < 2 then raise Exception.Create(SMinimumPlayers);
     269    if Players.Count < 1 then raise Exception.Create(SMinimumPlayers);
    266270    FRunning := AValue;
    267271  end else begin
     
    284288          else Terrain := ttNormal;
    285289      end;
    286     Power := Random(MaxNeutralUnits + 1);
     290    if not Assigned(OneUnit) then
     291      OneUnit := Units.AddNew(GameSystem.UnitKinds[0], Random(MaxNeutralUnits + 1));
    287292    Player := nil;
    288293  end;
     
    428433  BridgeEnabled := Source.BridgeEnabled;
    429434  MaxPower := Source.MaxPower;
    430   EmptyCellsNeutral := Source.EmptyCellsNeutral;
     435  GameSystem := Source.GameSystem;
    431436end;
    432437
     
    452457    SetValue(DOMString(Path + '/StayAliveForDefinedTurns'), StayAliveForDefinedTurns);
    453458    SetValue(DOMString(Path + '/SpecialCaptureCellCount'), SpecialCaptureCellCount);
    454     SetValue(DOMString(Path + '/EmptyCellsNeutral'), EmptyCellsNeutral);
    455459    Players.SaveConfig(Config, Path + '/Players');
    456460  end;
     
    488492    StayAliveForDefinedTurns := GetValue(DOMString(Path + '/StayAliveForDefinedTurns'), 20);
    489493    SpecialCaptureCellCount := GetValue(DOMString(Path + '/SpecialCaptureCellCount'), 1);
    490     EmptyCellsNeutral := GetValue(DOMString(Path + '/EmptyCellsNeutral'), False);
    491494    Players.LoadConfig(Config, Path + '/Players');
    492495  end;
     
    524527      WinObjective := TWinObjective(ReadInteger(RootNode, 'WinObjective', Integer(woDefeatAllOponents)));
    525528      StayAliveForDefinedTurns := ReadInteger(RootNode, 'StayAliveForDefinedTurns', 10);
    526       EmptyCellsNeutral := ReadBoolean(RootNode, 'EmptyCellsNeutral', False);
     529
     530      NewNode := FindNode('GameSystem');
     531      if Assigned(NewNode) then
     532        GameSystem.LoadFromNode(NewNode);
    527533
    528534      NewNode := FindNode('Map');
     
    536542        else CurrentPlayer := nil;
    537543
     544      NewNode := FindNode('Units');
     545      if Assigned(NewNode) then
     546        Units.LoadFromNode(NewNode);
     547
    538548      Map.Cells.FixRefId;
     549      Units.FixRefId;
    539550
    540551      for I := 0 to Players.Count - 1 do begin
     
    578589      WriteInteger(RootNode, 'WinObjective', Integer(WinObjective));
    579590      WriteInteger(RootNode, 'StayAliveForDefinedTurns', StayAliveForDefinedTurns);
    580       WriteBoolean(RootNode, 'EmptyCellsNeutral', EmptyCellsNeutral);
    581591      WriteBoolean(RootNode, 'Running', Running);
     592
     593      NewNode := OwnerDocument.CreateElement('GameSystem');
     594      AppendChild(NewNode);
     595      GameSystem.SaveToNode(NewNode);
    582596
    583597      NewNode := OwnerDocument.CreateElement('Map');
     
    588602      AppendChild(NewNode);
    589603      Players.SaveToNode(NewNode);
     604
     605      NewNode := OwnerDocument.CreateElement('Units');
     606      AppendChild(NewNode);
     607      Units.SaveToNode(NewNode);
    590608    end;
    591609    if ExtractFileDir(FileName) <> '' then
     
    633651    TurnStats.Add(NewStat);
    634652  end;
     653end;
     654
     655procedure TGame.SetGameSystem(AValue: TGameSystem);
     656begin
     657  if FGameSystem = AValue then Exit;
     658  FGameSystem := AValue;
    635659end;
    636660
     
    687711  R: Boolean;
    688712  I: Integer;
     713  PlayersCount: Integer;
    689714begin
    690715  Winner := nil;
     
    724749    if TurnCounter > StayAliveForDefinedTurns then
    725750      EndGame(nil);
     751  end else
     752  if WinObjective = woCaptureEntireMap then begin
     753    Player := nil;
     754    for I := 0 to Map.Cells.Count - 1 do
     755    if TCell(Map.Cells[I]).Terrain <> ttVoid then begin
     756      if (TCell(Map.Cells[I]).Player <> nil) then begin
     757        if Player = nil then begin
     758          // First player found
     759          Player := TPlayer(TCell(Map.Cells[I]).Player);
     760        end else
     761        if Player <> TCell(Map.Cells[I]).Player then begin
     762          // Multiple players still alive
     763          Player := nil;
     764          Break;
     765        end;
     766      end else begin
     767        // Neutral cell
     768        Player := nil;
     769        Break;
     770      end;
     771    end;
     772    if Player <> nil then
     773      EndGame(Player);
    726774  end;
    727775end;
     
    729777constructor TGame.Create;
    730778begin
     779  Units := TUnits.Create;
     780  Units.Game := Self;
    731781  Map := TMap.Create;
     782  Map.Game := Self;
    732783  Players := TPlayers.Create;
    733784  Players.Game := Self;
     
    742793  MaxNeutralUnits := Min(4, MaxPower);
    743794
    744   Map.Game := Self;
    745795  Map.Size := TPoint.Create(3, 3);
    746796end;
     
    750800  FreeAndNil(Players);
    751801  FreeAndNil(Map);
     802  FreeAndNil(Units);
    752803  inherited Destroy;
    753804end;
     
    784835  end;
    785836
    786   for Player in Players do Player.StartCell := nil;
     837  for Player in Players do begin
     838    Player.Reset;
     839    Player.StartCell := nil;
     840  end;
    787841  I := 0;
    788842  for Player in Players do
     
    797851        StartCell.Terrain := ttCity;
    798852        StartCell.Player := Player;
    799         StartCell.Power := Player.StartUnits;
     853        if not Assigned(StartCell.OneUnit) then
     854          StartCell.OneUnit := Units.AddNew(GameSystem.UnitKinds[0], Player.StartUnits);
     855        StartCell.OneUnit.Power := Player.StartUnits;
     856        StartCell.OneUnit.Kind := GameSystem.UnitKinds[0];
    800857      end;
    801858    end;
  • trunk/UMap.pas

    r258 r265  
    77uses
    88  Classes, SysUtils, Graphics, ExtCtrls, UGeometry, DOM, fgl,
    9   UXMLUtils;
     9  UXMLUtils, UUnit;
    1010
    1111const
     
    3030    FMap: TMap;
    3131    FPower: Integer;
     32    FUnit: TUnit;
     33    function GetPower: Integer;
    3234    procedure SetArea(AValue: TMapArea);
    3335    procedure SetId(AValue: Integer);
    3436    procedure SetPower(AValue: Integer);
     37    procedure SetUnit(AValue: TUnit);
    3538  public
    3639    PosPx: TPoint;
    3740    Polygon: TPolygon;
    3841    Terrain: TTerrainType;
    39     PlayerId: Integer;
     42    PlayerId: Integer; // Temporary value
    4043    Player: TObject; // TPlayer;
    4144    NeighborsId: array of Integer;
     
    4447    Weight: Integer; // Temporary value
    4548    Angle: Double; // Temporary value
    46     PlayerCell: Pointer; // Temporary value
     49    PlayerCell: TObject; // Temporary value
    4750    Links: TCellLinks;
    4851    Extra: TExtraType;
    49     property Id: Integer read FId write SetId;
     52    OneUnitId: Integer; // Temporary value
    5053    procedure ConnectTo(Cell: TCell);
    5154    procedure DisconnectFrom(Cell: TCell);
     
    6063    constructor Create;
    6164    destructor Destroy; override;
    62     property Power: Integer read FPower write SetPower;
     65    property Id: Integer read FId write SetId;
    6366    property Map: TMap read FMap write FMap;
    6467    property Area: TMapArea read FArea write SetArea;
     68    property OneUnit: TUnit read FUnit write SetUnit;
     69    //property Power: Integer read GetPower;
    6570  end;
    6671
     
    612617    with TPlayer(Player) do begin
    613618      Inc(TotalCells);
    614       Inc(TotalUnits, Power);
     619      if Assigned(OneUnit) then
     620        Inc(TotalUnits, OneUnit.Power);
    615621      if Terrain = ttCity then
    616622        Inc(TotalCities);
     
    656662  for C := 0 to (Cells.Count div 2) - 1 do begin
    657663    Cells[C].Terrain := Cells[Cells.Count - 1 - C].Terrain;
    658     Cells[C].Power := Cells[Cells.Count - 1 - C].Power;
     664    Cells[C].OneUnit.Power := Cells[Cells.Count - 1 - C].OneUnit.Power;
    659665
    660666    for I := Cells[C].Links.Count - 1 downto 0 do begin
     
    908914end;
    909915
     916procedure TCell.SetUnit(AValue: TUnit);
     917var
     918  OldValue: TUnit;
     919begin
     920  if FUnit = AValue then Exit;
     921  OldValue := FUnit;
     922  FUnit := nil;
     923  if Assigned(OldValue) then OldValue.MapCell := nil;
     924  FUnit := AValue;
     925  if Assigned(FUnit) then FUnit.MapCell := Self;
     926end;
     927
    910928procedure TCell.ConnectTo(Cell: TCell);
    911929begin
     
    950968end;
    951969
     970function TCell.GetPower: Integer;
     971begin
     972  if Assigned(OneUnit) then Result := OneUnit.Power
     973    else Result := 0;
     974end;
     975
    952976procedure TCell.SetId(AValue: Integer);
    953977begin
     
    973997begin
    974998  Player := TGame(Map.Game).Players.FindById(PlayerId);
     999  OneUnit := TGame(Map.Game).Units.FindById(OneUnitId);
    9751000
    9761001  Neighbors.Count := Length(NeighborsId);
     
    9931018begin
    9941019  Id := ReadInteger(Node, 'Id', 0);
    995   Power := ReadInteger(Node, 'Power', 0);
     1020  OneUnitId := ReadInteger(Node, 'Unit', 0);
    9961021  Terrain := TTerrainType(ReadInteger(Node, 'Terrain', Integer(ttVoid)));
    9971022  Extra := TExtraType(ReadInteger(Node, 'Extra', Integer(etNone)));
     
    10291054begin
    10301055  WriteInteger(Node, 'Id', Id);
    1031   WriteInteger(Node, 'Power', Power);
     1056  if Assigned(OneUnit) then
     1057    WriteInteger(Node, 'Unit', OneUnit.Id)
     1058    else WriteInteger(Node, 'Unit', 0);
    10321059  WriteInteger(Node, 'Terrain', Integer(Terrain));
    10331060  WriteInteger(Node, 'Extra', Integer(Extra));
     
    10901117  I: Integer;
    10911118begin
     1119  OneUnit := nil;
    10921120  for I := Links.Count - 1 downto 0 do
    10931121    FMap.CellLinks.Remove(Links[I]);
  • trunk/UPlayer.pas

    r262 r265  
    66
    77uses
    8   Classes, SysUtils, Graphics, UMap, DOM, fgl, XMLConf,
    9   UXMLUtils, Math, UGeometry;
     8  Classes, SysUtils, Graphics, UMap, DOM, fgl, XMLConf, UXMLUtils, Math,
     9  UGeometry, UUnit;
    1010
    1111type
     
    9696    FMode: TPlayerMode;
    9797    FOnMove: TMoveEvent;
     98    procedure MoveUnit(UnitMove: TUnitMove);
    9899    procedure SetGame(AValue: TObject); // TGame
    99100    procedure Attack(var AttackPower, DefendPower: Integer);
     
    118119    TurnStats: TGameTurnStats;
    119120    Moves: TUnitMoves;
     121    Units: TUnits;
    120122    procedure ReduceMovesPower;
    121123    procedure RemoveInvalidMoves;
     
    148150  public
    149151    Game: TObject; //TGame;
    150     NewPlayerId: Integer;
     152    NewId: Integer;
    151153    function FindById(Id: Integer): TPlayer;
    152154    procedure New(Name: string; Color: TColor; Mode: TPlayerMode);
    153     function GetNewPlayerId: Integer;
     155    function GetNewId: Integer;
    154156    procedure LoadFromNode(Node: TDOMNode);
    155157    procedure SaveToNode(Node: TDOMNode);
     
    259261  UnitMove: TUnitMove;
    260262begin
    261   Result := MapCell.Power;
     263  if Assigned(MapCell.OneUnit) then Result := MapCell.OneUnit.Power
     264    else Result := 0;
    262265  for UnitMove in MovesFrom do
    263266    Result := Result - UnitMove.CountOnce;
     
    433436  with TPlayerCell(Cells[I]) do begin
    434437    for J := 0 to MapCell.Neighbors.Count - 1 do
    435       ConnectTo(TCell(MapCell.Neighbors[J]).PlayerCell);
     438      ConnectTo(TPlayerCell(TCell(MapCell.Neighbors[J]).PlayerCell));
    436439  end;
    437440end;
     
    511514  NewPlayer.Color := Color;
    512515  NewPlayer.Mode := Mode;
    513   NewPlayer.Id := GetNewPlayerId;
     516  NewPlayer.Id := GetNewId;
    514517  if Mode = pmComputer then
    515518    NewPlayer.Agressivity := caMedium;
     
    517520end;
    518521
    519 function TPlayers.GetNewPlayerId: Integer;
    520 begin
    521   Result := NewPlayerId;
    522   Inc(NewPlayerId);
     522function TPlayers.GetNewId: Integer;
     523begin
     524  Result := NewId;
     525  Inc(NewId);
    523526end;
    524527
     
    554557begin
    555558  inherited;
    556   NewPlayerId := 1;
     559  NewId := 1;
    557560end;
    558561
     
    579582    Items[I].Game := Game;
    580583  end;
    581   NewPlayerId := Source.NewPlayerId;
     584  NewId := Source.NewId;
    582585end;
    583586
     
    589592  with Config do begin
    590593    NewCount := GetValue(DOMString(Path + '/Count'), -1);
    591     NewPlayerId := 1;
    592     if NewCount >= 2 then begin
     594    NewId := 1;
     595    if NewCount >= MinPlayerCount then begin
    593596      Self.Clear;
    594597      Count := NewCount;
    595598      for I := 0 to Count - 1 do begin
    596599        Items[I] := TPlayer.Create;
    597         Items[I].Id := GetNewPlayerId;
     600        Items[I].Id := GetNewId;
    598601        Items[I].Game := Game;
    599602        Items[I].LoadConfig(Config, Path + '/Player' + IntToStr(I));
     
    683686
    684687procedure TUnitMove.SetCellFrom(AValue: TPlayerCell);
     688var
     689  OldValue: TPlayerCell;
    685690begin
    686691  if FCellFrom = AValue then Exit;
    687   if Assigned(AValue) and not Assigned(FCellFrom) then begin
    688     if AValue.MovesFrom.IndexOf(Self) = -1 then
    689       AValue.MovesFrom.Add(Self)
     692  OldValue := FCellFrom;
     693  FCellFrom := nil;
     694  if Assigned(OldValue) then begin
     695    if OldValue.MovesFrom.IndexOf(Self) <> -1 then
     696      OldValue.MovesFrom.Remove(Self)
     697      else raise Exception.Create('Unit move not found');
     698  end;
     699  FCellFrom := AValue;
     700  if Assigned(FCellFrom) then begin
     701    if FCellFrom.MovesFrom.IndexOf(Self) = -1 then
     702      FCellFrom.MovesFrom.Add(Self)
    690703      else raise Exception.Create('Unit move already exists');
    691704  end else
    692   if not Assigned(AValue) and Assigned(FCellFrom) then begin
    693     if FCellFrom.MovesFrom.IndexOf(Self) <> -1 then
    694       FCellFrom.MovesFrom.Remove(Self)
     705end;
     706
     707procedure TUnitMove.SetCellTo(AValue: TPlayerCell);
     708var
     709  OldValue: TPlayerCell;
     710begin
     711  if FCellTo = AValue then Exit;
     712  OldValue := FCellTo;
     713  FCellTo := nil;
     714  if Assigned(OldValue) then begin
     715    if OldValue.MovesTo.IndexOf(Self) <> -1 then
     716      OldValue.MovesTo.Remove(Self)
    695717      else raise Exception.Create('Unit move not found');
    696718  end;
    697   FCellFrom := AValue;
    698 end;
    699 
    700 procedure TUnitMove.SetCellTo(AValue: TPlayerCell);
    701 begin
    702   if FCellTo = AValue then Exit;
    703   if Assigned(AValue) and not Assigned(FCellTo) then begin
    704     AValue.MovesTo.Add(Self);
     719  FCellTo := AValue;
     720  if Assigned(FCellTo) then begin
     721    if FCellTo.MovesTo.IndexOf(Self) = -1 then
     722      FCellTo.MovesTo.Add(Self)
     723      else raise Exception.Create('Unit move already exists');
    705724  end else
    706   if not Assigned(AValue) and Assigned(FCellTo) then begin
    707     FCellTo.MovesTo.Remove(Self);
    708   end;
    709   FCellTo := AValue;
    710725end;
    711726
     
    829844constructor TPlayer.Create;
    830845begin
     846  Units := TUnits.Create(False);
    831847  Moves := TUnitMoves.Create;
    832848  Moves.Player := Self;
     
    844860  FreeAndNil(PlayerMap);
    845861  FreeAndNil(Moves);
     862  FreeAndNil(Units);
    846863  inherited Destroy;
    847864end;
     
    937954
    938955function CellCompare(const Item1, Item2: TPlayerCell): Integer;
    939 begin
    940   if Item1.MapCell.Power > Item2.MapCell.Power then Result := 1
    941   else if Item1.MapCell.Power < Item2.MapCell.Power then Result := -1
     956var
     957  Stack1, Stack2: Integer;
     958begin
     959  if Assigned(Item1.MapCell.OneUnit) then Stack1 := Item1.MapCell.OneUnit.Power
     960    else Stack1 := 0;
     961  if Assigned(Item2.MapCell.OneUnit) then Stack2 := Item2.MapCell.OneUnit.Power
     962    else Stack2 := 0;
     963  if Stack1 > Stack1 then Result := 1
     964  else if Stack1 < Stack2 then Result := -1
    942965  else Result := 0;
    943966end;
    944967
    945968function CellCompareDescending(const Item1, Item2: TPlayerCell): Integer;
    946 begin
    947   if Item1.MapCell.Power > Item2.MapCell.Power then Result := -1
    948   else if Item1.MapCell.Power < Item2.MapCell.Power then Result := 1
     969var
     970  Stack1, Stack2: Integer;
     971begin
     972  if Assigned(Item1.MapCell.OneUnit) then Stack1 := Item1.MapCell.OneUnit.Power
     973    else Stack1 := 0;
     974  if Assigned(Item2.MapCell.OneUnit) then Stack2 := Item2.MapCell.OneUnit.Power
     975    else Stack2 := 0;
     976  if Stack1 > Stack2 then Result := -1
     977  else if Stack1 < Stack2 then Result := 1
    949978  else Result := 0;
    950979end;
    951980
    952 procedure TPlayer.MoveAll;
     981procedure TPlayer.MoveUnit(UnitMove: TUnitMove);
    953982var
    954983  AttackerPower: Integer;
    955984  DefenderPower: Integer;
    956985  UnitCount: Integer;
     986begin
     987  with UnitMove do begin
     988    UnitCount := CountOnce;
     989    if CountOnce > CellFrom.MapCell.OneUnit.Power then
     990      UnitCount := CellFrom.MapCell.OneUnit.Power;
     991    CountOnce := 0;
     992    if not Assigned(CellTo.MapCell.OneUnit) then begin
     993      CellTo.MapCell.OneUnit := TGame(Game).Units.AddNew(CellFrom.MapCell.OneUnit.Kind, 0);
     994      CellTo.MapCell.Player := Self;
     995    end;
     996
     997    if CellTo.MapCell.OneUnit.Player = Self then begin
     998      // Inner move
     999      CellTo.MapCell.OneUnit.Power := CellTo.MapCell.OneUnit.Power + UnitCount;
     1000    end else begin
     1001      AttackerPower := UnitCount;
     1002      if Assigned(CellTo.MapCell.OneUnit) then
     1003        DefenderPower := CellTo.MapCell.OneUnit.Power
     1004        else DefenderPower := 0;
     1005      Attack(AttackerPower, DefenderPower);
     1006      if DefenderPower = 0 then begin
     1007        // Attacker wins with possible loses
     1008        ClearMovesFromCell(CellTo);
     1009        CellTo.MapCell.Player := Self;
     1010        CellTo.MapCell.OneUnit.Player := Self;
     1011        CellTo.MapCell.OneUnit.Power := AttackerPower;
     1012      end else
     1013      if AttackerPower = 0 then begin
     1014        // Defender wins with possible loses
     1015        CellTo.MapCell.OneUnit.Power := DefenderPower;
     1016      end else
     1017        raise Exception.Create(SUnfinishedBattle);
     1018    end;
     1019    CellFrom.MapCell.OneUnit.Power := CellFrom.MapCell.OneUnit.Power - UnitCount;
     1020  end;
     1021end;
     1022
     1023procedure TPlayer.MoveAll;
     1024var
    9571025  UnitMove: TUnitMove;
    9581026begin
    9591027  for UnitMove in Moves do
    960   with UnitMove do begin
     1028  with UnitMove do
    9611029  if CountOnce > 0 then begin
    9621030    if CellFrom.MapCell.Player = Self then begin
    963       UnitCount := CountOnce;
    964       if CountOnce > CellFrom.MapCell.Power then
    965         UnitCount := CellFrom.MapCell.Power;
    966       CountOnce := 0;
    967       if CellTo.MapCell.Player = Self then begin
    968         // Inner move
    969         CellTo.MapCell.Power := CellTo.MapCell.Power + UnitCount;
    970       end else begin
    971         AttackerPower := UnitCount;
    972         DefenderPower := CellTo.MapCell.Power;
    973         Attack(AttackerPower, DefenderPower);
    974         if DefenderPower = 0 then begin
    975           // Attacker wins with possible loses
    976           ClearMovesFromCell(CellTo);
    977           CellTo.MapCell.Player := Self;
    978           CellTo.MapCell.Power := AttackerPower;
    979         end else
    980         if AttackerPower = 0 then begin
    981           // Defender wins with possible loses
    982           CellTo.MapCell.Power := DefenderPower;
    983         end else
    984           raise Exception.Create(SUnfinishedBattle);
    985       end;
    986       CellFrom.MapCell.Power := CellFrom.MapCell.Power - UnitCount;
    987     end;
     1031      MoveUnit(UnitMove);
    9881032    end;
    9891033  end;
     
    10201064var
    10211065  I: Integer;
    1022 begin
    1023   for I := Cell.MovesFrom.Count - 1 downto 0 do
    1024     Cell.MovesFrom.Delete(I);
     1066  OtherPlayerCell: TPlayerCell;
     1067begin
     1068  if Assigned(Cell.MapCell.Player) then
     1069  with TPlayer(Cell.MapCell.Player) do begin
     1070    OtherPlayerCell := PlayerMap.Cells.SearchCell(Cell.MapCell);
     1071    if Assigned(OtherPlayerCell) then begin
     1072    for I := OtherPlayerCell.MovesFrom.Count - 1 downto 0 do
     1073      Moves.Remove(OtherPlayerCell.MovesFrom[I]);
     1074    end;
     1075  end;
    10251076end;
    10261077
     
    10821133var
    10831134  Move: TUnitMove;
     1135  AvailPower: Integer;
    10841136begin
    10851137  for Move in Moves do
    10861138  with Move do begin
    1087     if CellFrom.MapCell.Player = Self then
    1088       if CountRepeat <= CellFrom.GetAvialPower then
     1139    if CellFrom.MapCell.Player = Self then begin
     1140      AvailPower := CellFrom.GetAvialPower + Move.CountOnce;
     1141      if CountRepeat <= AvailPower then
    10891142        CountOnce := CountRepeat
    1090         else CountOnce := CellFrom.GetAvialPower;
     1143        else CountOnce := AvailPower;
     1144    end;
    10911145  end;
    10921146  RemoveEmptyUnitMoves;
     
    10971151  I: Integer;
    10981152begin
    1099   if TGame(Game).EmptyCellsNeutral then
     1153  if TGame(Game).GameSystem.EmptyCellsNeutral then
    11001154  for I := 0 to PlayerMap.Cells.Count - 1 do
    11011155  with TPlayerCell(PlayerMap.Cells[I]) do begin
    1102     if MapCell.Power = 0 then MapCell.Player := nil;
     1156    if MapCell.OneUnit.Power = 0 then MapCell.Player := nil;
    11031157  end;
    11041158end;
     
    11081162  I: Integer;
    11091163begin
    1110   // Remove empty moves
    11111164  for I := Moves.Count - 1 downto 0 do
    11121165  if (TUnitMove(Moves[I]).CellFrom.MapCell.Player = Self) and
     
    11681221  with TGame(Game).Map do
    11691222  for I := 0 to Cells.Count - 1 do
    1170   with Cells[I] do begin
     1223  with TCell(Cells[I]) do begin
    11711224    if (Player = Self) and ((TGame(Game).GrowCells = gcPlayerAll) or
    11721225    ((TGame(Game).GrowCells = gcPlayerCities) and (Terrain = ttCity))) then begin
    1173       if Power < MaxPower then begin
     1226      if OneUnit.Power < MaxPower then begin
    11741227        // Increase units count
    11751228        Addition := 0;
     
    11781231        end else
    11791232        if TGame(Game).GrowAmount = gaBySquareRoot then begin
    1180           Addition := Trunc(Sqrt(Power));
     1233          Addition := Trunc(Sqrt(OneUnit.Power));
    11811234          if Addition = 0 then Addition := 1;
    11821235        end;
    1183         Power := Min(Power + Addition, MaxPower);
     1236        OneUnit.Power := Min(OneUnit.Power + Addition, MaxPower);
    11841237      end else
    1185       if Power > MaxPower then begin
     1238      if OneUnit.Power > MaxPower then begin
    11861239        // Reduce units count
    11871240        // If cell has more then MaxPower units then additional units dies
    11881241        // in twice of squeare root of unites over MaxPower
    1189         Dies := 2 * Trunc(Sqrt(Power - MaxPower));
    1190         Power := Max(Power - Dies, 0);
     1242        Dies := 2 * Trunc(Sqrt(OneUnit.Power - MaxPower));
     1243        OneUnit.Power := Max(OneUnit.Power - Dies, 0);
    11911244      end;
    11921245    end;
  • trunk/xtactics.lpi

    r253 r265  
    109109      </Item7>
    110110    </RequiredPackages>
    111     <Units Count="33">
     111    <Units Count="36">
    112112      <Unit0>
    113113        <Filename Value="xtactics.lpr"/>
     
    287287        <IsPartOfProject Value="True"/>
    288288      </Unit32>
     289      <Unit33>
     290        <Filename Value="UUnit.pas"/>
     291        <IsPartOfProject Value="True"/>
     292      </Unit33>
     293      <Unit34>
     294        <Filename Value="UGameSystem.pas"/>
     295        <IsPartOfProject Value="True"/>
     296      </Unit34>
     297      <Unit35>
     298        <Filename Value="UBuilding.pas"/>
     299        <IsPartOfProject Value="True"/>
     300      </Unit35>
    289301    </Units>
    290302  </ProjectOptions>
Note: See TracChangeset for help on using the changeset viewer.