Changeset 274 for trunk


Ignore:
Timestamp:
Feb 3, 2019, 8:32:20 PM (6 years ago)
Author:
chronos
Message:
  • Added: Keep information about available unit moves during turn.
  • Added: Allow to move units instantly during turn.
  • Added: Game system parameter to play without possibility to merge/split units.
Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Forms/UFormClient.pas

    r273 r274  
    155155    FormMove.TrackBarRepeat.Max := FormMove.SpinEditRepeat.MaxValue;
    156156    FormMove.TrackBarRepeat.Position := FormMove.SpinEditRepeat.Value;
     157
     158    FormMove.AllowChangeOnce := Client.Game.GameSystem.UnitsSplitMerge;
     159
    157160    if Assigned(CellTo.MapCell.OneUnit) then
    158161      FormMove.DefendCount := CellTo.MapCell.OneUnit.Power
  • trunk/Forms/UFormMove.pas

    r272 r274  
    4848    AttackCount: Integer;
    4949    ShowWinProbability: Boolean;
     50    AllowChangeOnce: Boolean;
    5051    procedure UpdateView;
    5152  end;
     
    102103    SpinEditRepeat.SetFocus;
    103104  end else begin
    104     SpinEditOnce.Enabled := True;
    105     TrackBarOnce.Enabled := True;
    106     SpinEditOnce.SetFocus;
     105    SpinEditOnce.Enabled := AllowChangeOnce;
     106    TrackBarOnce.Enabled := AllowChangeOnce;
     107    ButtonOnceMax.Enabled := AllowChangeOnce;
     108    ButtonOnceMin.Enabled := AllowChangeOnce;
     109    if SpinEditOnce.Enabled then SpinEditOnce.SetFocus
     110    else if SpinEditRepeat.Enabled then SpinEditRepeat.SetFocus
     111    else ButtonOk.SetFocus;
    107112  end;
    108113  UpdateView;
  • trunk/Forms/UFormNew.lfm

    r273 r274  
    3333      object Panel3: TPanel
    3434        Left = 0
    35         Height = 655
     35        Height = 652
    3636        Top = 0
    37         Width = 739
     37        Width = 796
    3838        Align = alClient
    3939        BevelOuter = bvNone
    40         ClientHeight = 655
    41         ClientWidth = 739
     40        ClientHeight = 652
     41        ClientWidth = 796
    4242        TabOrder = 0
    4343        object RadioButtonModeLocal: TRadioButton
     
    103103        object ListViewServers: TListView
    104104          Left = 26
    105           Height = 423
     105          Height = 420
    106106          Top = 181
    107107          Width = 334
     
    131131          Left = 27
    132132          Height = 31
    133           Top = 616
     133          Top = 613
    134134          Width = 94
    135135          Action = AServerAdd
     
    140140          Left = 240
    141141          Height = 31
    142           Top = 616
     142          Top = 613
    143143          Width = 94
    144144          Action = AServerRemove
     
    149149          Left = 136
    150150          Height = 30
    151           Top = 616
     151          Top = 613
    152152          Width = 94
    153153          Action = AServerModify
     
    326326        object ComboBoxGridType: TComboBox
    327327          Left = 146
    328           Height = 42
     328          Height = 38
    329329          Top = 104
    330330          Width = 208
     
    343343        object ComboBoxMapShape: TComboBox
    344344          Left = 146
    345           Height = 42
     345          Height = 38
    346346          Top = 144
    347347          Width = 208
     
    587587        object ComboBoxWinObjective: TComboBox
    588588          Left = 224
    589           Height = 42
     589          Height = 38
    590590          Top = 244
    591591          Width = 328
     
    702702          TabOrder = 5
    703703        end
     704        object CheckBoxUnitsSplitMerge: TCheckBox
     705          Left = 336
     706          Height = 30
     707          Top = 101
     708          Width = 231
     709          Caption = 'Units can split or merge'
     710          TabOrder = 6
     711        end
     712        object CheckBoxUnitsMoveImmediately: TCheckBox
     713          Left = 336
     714          Height = 30
     715          Top = 141
     716          Width = 234
     717          Caption = 'Units move immediately'
     718          TabOrder = 7
     719        end
    704720      end
    705721    end
  • trunk/Forms/UFormNew.pas

    r273 r274  
    3232    ButtonPlayerModify: TButton;
    3333    ButtonPlayerRemove: TButton;
     34    CheckBoxUnitsSplitMerge: TCheckBox;
    3435    CheckBoxEmptyCellsNeutral: TCheckBox;
    3536    CheckBoxBridges: TCheckBox;
     
    3839    CheckBoxFogOfWar: TCheckBox;
    3940    CheckBoxSymetricMap: TCheckBox;
     41    CheckBoxUnitsMoveImmediately: TCheckBox;
    4042    CheckBoxVoid: TCheckBox;
    4143    ComboBoxGridType: TComboBox;
     
    360362    SpinEditSpecialCells.Value := SpecialCaptureCellCount;
    361363    CheckBoxEmptyCellsNeutral.Checked := GameSystem.EmptyCellsNeutral;
     364    CheckBoxUnitsSplitMerge.Checked := GameSystem.UnitsSplitMerge;
     365    CheckBoxUnitsMoveImmediately.Checked := GameSystem.UnitsMoveImmediately;
    362366  end;
    363367end;
     
    389393    SpecialCaptureCellCount := SpinEditSpecialCells.Value;
    390394    GameSystem.EmptyCellsNeutral := CheckBoxEmptyCellsNeutral.Checked;
     395    GameSystem.UnitsSplitMerge := CheckBoxUnitsSplitMerge.Checked;
     396    GameSystem.UnitsMoveImmediately := CheckBoxUnitsMoveImmediately.Checked;
    391397  end;
    392398end;
  • trunk/Languages/xtactics.cs.po

    r273 r274  
    438438msgid "Symetric map"
    439439msgstr "Symetrická mapa"
     440
     441#: tformnew.checkboxunitsmoveimmediately.caption
     442msgid "Units move immediately"
     443msgstr "Okamžitý pohyb jednotek"
     444
     445#: tformnew.checkboxunitssplitmerge.caption
     446msgid "Units can split or merge"
     447msgstr "Dělení nebo slučování jednotek"
    440448
    441449#: tformnew.checkboxvoid.caption
  • trunk/Languages/xtactics.po

    r273 r274  
    424424#: tformnew.checkboxsymetricmap.caption
    425425msgid "Symetric map"
     426msgstr ""
     427
     428#: tformnew.checkboxunitsmoveimmediately.caption
     429msgid "Units move immediately"
     430msgstr ""
     431
     432#: tformnew.checkboxunitssplitmerge.caption
     433msgid "Units can split or merge"
    426434msgstr ""
    427435
  • trunk/UClientAI.pas

    r273 r274  
    6969
    7070  // Sort ascending to attack cells with lower power first
    71   // Low power cells are better for expanding our teritorry
     71  // Low power cells are better for expanding our territory
    7272  TargetCells.Sort(CellCompare);
    7373
     
    7979      for NeighborCell in Neighbors do
    8080      if NeighborCell.MapCell.Player = ControlPlayer then
    81         TotalPower := TotalPower + NeighborCell.GetAvialPower;
     81        TotalPower := TotalPower + NeighborCell.GetAvialPowerForMove;
    8282
    8383      // Attack if target is weaker
     
    195195  for C := 0 to AllCells.Count - 1 do
    196196  with AllCells[C] do begin
    197     if (MapCell.Player <> ControlPlayer) and (MapCell.Player <> nil) and (MapCell.Terrain <> ttVoid) then begin
     197    if (MapCell.Player <> ControlPlayer) and (MapCell.Terrain <> ttVoid) then begin
    198198      CanAttack := 0;
    199199      for I := 0 to Neighbors.Count - 1 do
     
    307307  // Move all units back to inner area from weak border cells
    308308  for C := 0 to BorderCells.Count - 1 do
    309   with BorderCells[C] do begin
     309  with TPlayerCell(BorderCells[C]) do begin
    310310    // Calculate enemy power
    311311    // TODO: Do not sum different enemy power to one value
  • trunk/UClientGUI.pas

    r273 r274  
    352352          if Assigned(SelectedCell) and (SelectedCell = Cell) then
    353353              Brush.Color := clGreen
    354             else if Assigned(SelectedCell) and TGame(Game).Map.IsCellsNeighbor(SelectedCell.MapCell, Cell.MapCell) then
     354            else if Assigned(SelectedCell) and ControlPlayer.IsAllowedMoveTarget(SelectedCell, Cell) then
    355355              Brush.Color := clPurple
    356356            else if TGame(Game).FogOfWar then begin
     
    616616  if Assigned(NewSelectedCell) then begin
    617617    if Assigned(SelectedCell) and (NewSelectedCell <> SelectedCell) and
    618       TGame(Game).Map.IsCellsNeighbor(NewSelectedCell.MapCell, SelectedCell.MapCell) then begin
     618    TGame(Game).CurrentPlayer.IsAllowedMoveTarget(SelectedCell, NewSelectedCell) then begin
    619619      if ssShift in ShiftState then begin
    620620        // Make maximum unit move without confirmation dialog
     
    640640      end;
    641641    end else
    642     if (NewSelectedCell <> SelectedCell) and (NewSelectedCell.MapCell.Player = Player) then begin
     642    if not Assigned(SelectedCell) and (NewSelectedCell <> SelectedCell) and (NewSelectedCell.MapCell.Player = Player) then begin
    643643      SelectedCell := NewSelectedCell
    644644    end else
  • trunk/UCore.pas

    r273 r274  
    106106    procedure LoadConfig;
    107107    procedure SaveConfig;
     108    procedure SaveConfigAll;
    108109    procedure Spectate(Player: TPlayer);
    109110    procedure UpdateInterface;
     
    225226end;
    226227
     228procedure TCore.SaveConfigAll;
     229begin
     230  GameSettings.SaveConfig(XMLConfig1, 'Game');
     231  Server.SaveConfig(XMLConfig1, 'Server');
     232  ServerList.SaveConfig(XmlConfig1, 'ServerList');
     233  SaveConfig;
     234  XMLConfig1.Flush;
     235end;
     236
    227237procedure TCore.CommandLineParams;
    228238var
     
    348358      GameSettings.PostConfig;
    349359      Game.Assign(GameSettings);
     360      SaveConfigAll;
    350361      StartNewGame;
    351362      GameLoaded := False;
     
    758769procedure TCore.Done;
    759770begin
    760   GameSettings.SaveConfig(XMLConfig1, 'Game');
    761   Server.SaveConfig(XMLConfig1, 'Server');
    762   ServerList.SaveConfig(XmlConfig1, 'ServerList');
    763   SaveConfig;
    764   XMLConfig1.Flush;
     771  SaveConfigAll;
    765772end;
    766773
  • trunk/UGame.pas

    r273 r274  
    349349        StartCell.OneUnit.Power := Player.StartUnits;
    350350        StartCell.OneUnit.Kind := GameSystem.UnitKinds[0];
     351        StartCell.OneUnit.Player := Player;
    351352      end;
    352353    end;
     354    InitUnitMoves;
    353355    PlayerMap.CheckVisibility;
    354356    Inc(I);
     
    524526    SetValue(DOMString(Path + '/MaxPower'), MaxPower);
    525527    Players.SaveConfig(Config, Path + '/Players');
     528    GameSystem.SaveConfig(Config, Path + '/GameSystem');
    526529  end;
    527530end;
     
    562565    MaxPower := GetValue(DOMString(Path + '/MaxPower'), 99);
    563566    Players.LoadConfig(Config, Path + '/Players');
     567    GameSystem.LoadConfig(Config, Path + '/GameSystem');
    564568  end;
    565569end;
     
    771775  CurrentPlayer.ReduceMovesPower;
    772776  CurrentPlayer.RemoveInvalidMoves;
     777  CurrentPlayer.InitUnitMoves;
    773778  if Assigned(FOnChange) then
    774779    FOnChange(Self);
  • trunk/UGameSystem.pas

    r265 r274  
    66
    77uses
    8   Classes, SysUtils, fgl, UUnit, DOM, UXMLUtils;
     8  Classes, SysUtils, fgl, UUnit, DOM, UXMLUtils, XMLConf;
    99
    1010type
     
    1515  TGameSystem = class
    1616    Name: string;
    17     ActionExecutionPhase: TActionExecutionPhase;
    1817    MaxPlayerCount: Integer;
    1918    UnitKinds: TUnitKinds;
    20     CanSplitMerge: Boolean;
     19    UnitsSplitMerge: Boolean;
    2120    EmptyCellsNeutral: Boolean;
     21    UnitsMoveImmediately: Boolean;
    2222    constructor Create;
    2323    destructor Destroy; override;
     
    2727    procedure LoadFromFile(FileName: string);
    2828    procedure SaveToFile(FileName: string);
     29    procedure LoadConfig(Config: TXmlConfig; Path: string);
     30    procedure SaveConfig(Config: TXmlConfig; Path: string);
    2931  end;
    3032
     
    6264begin
    6365  Name := Source.Name;
     66  UnitsMoveImmediately := Source.UnitsMoveImmediately;
    6467  MaxPlayerCount := Source.MaxPlayerCount;
    65   CanSplitMerge := Source.CanSplitMerge;
     68  UnitsSplitMerge := Source.UnitsSplitMerge;
    6669  EmptyCellsNeutral := Source.EmptyCellsNeutral;
    6770end;
     
    7275begin
    7376  Name := ReadString(Node, 'Name', '');
    74   CanSplitMerge := ReadBoolean(Node, 'CanSplitMerge', False);
     77  UnitsSplitMerge := ReadBoolean(Node, 'UnitsSplitMerge', False);
    7578  EmptyCellsNeutral := ReadBoolean(Node, 'EmptyCellsNeutral', False);
     79  UnitsMoveImmediately := ReadBoolean(Node, 'UnitsMoveImmediately', False);
    7680
    7781  NewNode := Node.FindNode('UnitKinds');
     
    8589begin
    8690  WriteString(Node, 'Name', Name);
    87   WriteBoolean(Node, 'CanSplitMerge', CanSplitMerge);
     91  WriteBoolean(Node, 'UnitsSplitMerge', UnitsSplitMerge);
    8892  WriteBoolean(Node, 'EmptyCellsNeutral', EmptyCellsNeutral);
     93  WriteBoolean(Node, 'UnitsMoveImmediately', UnitsMoveImmediately);
    8994
    9095  NewNode := Node.OwnerDocument.CreateElement('UnitKinds');
     
    103108end;
    104109
     110procedure TGameSystem.LoadConfig(Config: TXmlConfig; Path: string);
     111begin
     112  with Config do begin
     113    Self.Name := string(GetValue(DOMString(Path + '/Name'), DOMString('')));
     114    UnitsSplitMerge := GetValue(DOMString(Path + '/UnitsSplitMerge'), True);
     115    EmptyCellsNeutral := GetValue(DOMString(Path + '/EmptyCellsNeutral'), False);
     116    UnitsMoveImmediately := GetValue(DOMString(Path + '/UnitsMoveImmediately'), False);
     117  end;
     118end;
     119
     120procedure TGameSystem.SaveConfig(Config: TXmlConfig; Path: string);
     121begin
     122  with Config do begin
     123    SetValue(DOMString(Path + '/Name'), DOMString(Self.Name));
     124    SetValue(DOMString(Path + '/UnitsSplitMerge'), UnitsSplitMerge);
     125    SetValue(DOMString(Path + '/EmptyCellsNeutral'), EmptyCellsNeutral);
     126    SetValue(DOMString(Path + '/UnitsMoveImmediately'), UnitsMoveImmediately);
     127  end;
     128end;
     129
    105130end.
    106131
  • trunk/UPlayer.pas

    r273 r274  
    2828    procedure DisconnectFrom(Cell: TPlayerCell);
    2929    function GetAvialPower: Integer;
     30    function GetAvialPowerForMove: Integer;
    3031    function GetAttackPower: Integer;
    3132    procedure LoadFromNode(Node: TDOMNode);
     
    102103    procedure CheckCounterMove(Move: TUnitMove);
    103104    procedure SetMode(AValue: TPlayerMode);
    104     procedure RemoveEmptyUnitMoves;
    105105  public
    106106    Id: Integer;
     
    120120    Moves: TUnitMoves;
    121121    Units: TUnits;
     122    function IsAllowedMoveTarget(CellFrom, CellTo: TPlayerCell): Boolean;
    122123    procedure ReduceMovesPower;
    123124    procedure RemoveInvalidMoves;
    124125    procedure RemoveEmptyUnits;
     126    procedure InitUnitMoves;
    125127    procedure UpdateRepeatMoves;
    126128    procedure UpdateEmptyCellsNeutral;
     
    205207
    206208uses
    207   UGame;
     209  UGame, UGameSystem;
    208210
    209211resourcestring
     
    262264  UnitMove: TUnitMove;
    263265begin
    264   if Assigned(MapCell.OneUnit) then Result := MapCell.OneUnit.Power
    265     else Result := 0;
     266  Result := 0;
     267  if Assigned(MapCell.OneUnit) then
     268    Result := MapCell.OneUnit.Power;
     269  for UnitMove in MovesFrom do
     270    Result := Result - UnitMove.CountOnce;
     271end;
     272
     273function TPlayerCell.GetAvialPowerForMove: Integer;
     274var
     275  UnitMove: TUnitMove;
     276begin
     277  Result := 0;
     278  if Assigned(MapCell.OneUnit) then
     279    if MapCell.OneUnit.Moves > 0 then Result := MapCell.OneUnit.Power;
    266280  for UnitMove in MovesFrom do
    267281    Result := Result - UnitMove.CountOnce;
     
    9991013      // Inner move
    10001014      CellTo.MapCell.OneUnit.Power := CellTo.MapCell.OneUnit.Power + UnitCount;
     1015      Dec(CellTo.MapCell.OneUnit.Moves);
    10011016    end else begin
    10021017      AttackerPower := UnitCount;
     
    10151030        // Defender wins with possible loses
    10161031        CellTo.MapCell.OneUnit.Power := DefenderPower;
     1032        CellTo.MapCell.OneUnit.Moves := CellFrom.MapCell.OneUnit.Moves - 1;
    10171033      end else
    10181034        raise Exception.Create(SUnfinishedBattle);
     
    10201036    CellFrom.MapCell.OneUnit.Power := CellFrom.MapCell.OneUnit.Power - UnitCount;
    10211037  end;
     1038
     1039  // Clean from cell from empty units
     1040  if UnitMove.CellFrom.MapCell.OneUnit.Power = 0 then begin
     1041    Units.Remove(UnitMove.CellFrom.MapCell.OneUnit);
     1042    UnitMove.CellFrom.MapCell.OneUnit := nil;
     1043  end;
     1044
     1045  // Remove empty move
     1046  if (UnitMove.CellFrom.MapCell.Player = Self) and
     1047    (UnitMove.CountOnce = 0) and (UnitMove.CountRepeat = 0) then
     1048    Moves.Remove(UnitMove);
    10221049end;
    10231050
    10241051procedure TPlayer.MoveAll;
    10251052var
    1026   UnitMove: TUnitMove;
    1027 begin
    1028   for UnitMove in Moves do
    1029   with UnitMove do
     1053  I: Integer;
     1054begin
     1055  for I := Moves.Count - 1 downto 0 do
     1056  with Moves[I] do
    10301057  if CountOnce > 0 then begin
    10311058    if CellFrom.MapCell.Player = Self then begin
    1032       MoveUnit(UnitMove);
    1033     end;
    1034   end;
    1035 
    1036   RemoveEmptyUnitMoves;
     1059      MoveUnit(Moves[I]);
     1060    end;
     1061  end;
    10371062end;
    10381063
     
    10771102end;
    10781103
     1104procedure TPlayer.InitUnitMoves;
     1105var
     1106  I: Integer;
     1107begin
     1108  for I := 0 to Units.Count - 1 do
     1109    TUnit(Units[I]).Moves := TUnit(Units[I]).Kind.Moves;
     1110end;
     1111
    10791112procedure TPlayer.ClearMovesFromCell(Cell: TPlayerCell);
    10801113var
     
    11051138
    11061139  if Assigned(Result) then begin
     1140    // Update existing move
    11071141    CountOnce := Result.CountOnce;
    11081142    CountRepeat := Result.CountRepeat;
     
    11111145        FOnMove(CellFrom, CellTo, CountOnce, CountRepeat, True, Confirm);
    11121146  end else begin
     1147    // Create new move
    11131148    CountOnce := Power;
    11141149    CountRepeat := 0;
     
    11391174        Result := NewMove;
    11401175        CheckCounterMove(NewMove);
     1176        if TGame(Game).GameSystem.UnitsMoveImmediately then begin
     1177          MoveUnit(NewMove);
     1178        end;
    11411179      end;
    11421180    end;
     
    11601198    end;
    11611199  end;
    1162   RemoveEmptyUnitMoves;
    11631200end;
    11641201
     
    11731210      MapCell.Player := nil;
    11741211  end;
    1175 end;
    1176 
    1177 procedure TPlayer.RemoveEmptyUnitMoves;
    1178 var
    1179   I: Integer;
    1180 begin
    1181   for I := Moves.Count - 1 downto 0 do
    1182   if (TUnitMove(Moves[I]).CellFrom.MapCell.Player = Self) and
    1183     (TUnitMove(Moves[I]).CountOnce = 0) and (TUnitMove(Moves[I]).CountRepeat = 0) then
    1184     Moves.Delete(I);
    11851212end;
    11861213
     
    12301257end;
    12311258
     1259function TPlayer.IsAllowedMoveTarget(CellFrom, CellTo: TPlayerCell): Boolean;
     1260var
     1261  CellToHasOwnUnit: Boolean;
     1262  UnitHasMoveEnergy: Boolean;
     1263begin
     1264  CellToHasOwnUnit := Assigned(CellTo.MapCell.OneUnit) and
     1265    (CellTo.MapCell.OneUnit.Player = Self) and (CellTo.MapCell.OneUnit.Power > 0);
     1266  UnitHasMoveEnergy := Assigned(CellFrom.MapCell.OneUnit) and
     1267    (CellFrom.MapCell.OneUnit.Moves > 0);
     1268  Result := UnitHasMoveEnergy and
     1269  TGame(Game).Map.IsCellsNeighbor(CellFrom.MapCell, CellTo.MapCell)
     1270    and (TGame(Game).GameSystem.UnitsSplitMerge or
     1271    (not TGame(Game).GameSystem.UnitsSplitMerge and not CellToHasOwnUnit));
     1272end;
     1273
    12321274procedure TPlayer.Grow;
    12331275var
     
    12351277  Addition: Integer;
    12361278  Dies: Integer;
     1279  NewUnit: TUnit;
    12371280begin
    12381281  with TGame(Game).Map do
     
    12411284    if (Player = Self) and ((TGame(Game).GrowCells = gcPlayerAll) or
    12421285    ((TGame(Game).GrowCells = gcPlayerCities) and (Terrain = ttCity))) then begin
     1286      if not Assigned(OneUnit) then begin
     1287        NewUnit := TGame(Game).Units.AddNew(TGame(Game).GameSystem.UnitKinds.First, 0);
     1288        NewUnit.Player := Self;
     1289        NewUnit.MapCell := TCell(Cells[I]);
     1290        Units.Add(NewUnit);
     1291      end;
    12431292      if OneUnit.Power < MaxPower then begin
    12441293        // Increase units count
Note: See TracChangeset for help on using the changeset viewer.