Changeset 59 for trunk/UGame.pas


Ignore:
Timestamp:
Sep 26, 2014, 12:05:30 AM (10 years ago)
Author:
chronos
Message:
  • Added: Move win probability calculation.
  • Fixed: Attack processing to be same as Risk game system.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UGame.pas

    r58 r59  
    252252    StayAliveForDefinedTurns: Integer;
    253253    MaxNeutralUnits: Integer;
     254    function AttackProbability(AttackCount, DefendCount: Integer): Double;
    254255    procedure SaveConfig(Config: TXmlConfig; Path: string);
    255256    procedure LoadConfig(Config: TXmlConfig; Path: string);
     
    10871088{ TGame }
    10881089
     1090function ComparePointer(Item1, Item2: Pointer): Integer;
     1091begin
     1092  Result := -CompareValue(Integer(Item1), Integer(Item2));
     1093end;
     1094
    10891095procedure TGame.Attack(var AttackPower, DefendPower: Integer);
    10901096var
     
    10941100  DefenderHighestRoll: Integer;
    10951101  RollResult: Integer;
    1096   LoseCount: Integer;
    1097   I: Integer;
    1098 begin
     1102  S: string;
     1103  I: Integer;
     1104  AttackRolls: TList;
     1105  DefendRolls: TList;
     1106begin
     1107  AttackRolls := TList.Create;
     1108  DefendRolls := TList.Create;
    10991109  if AttackPower < 1 then
    11001110    raise Exception.Create('Attacker power have to be higher then 0.');
     
    11041114    // Risk game rules:
    11051115    // Each side do their dice roll and compare result. Defender wins tie.
    1106     // Attacer can use three dices and defender two
    1107     if AttackPower < 3 then AttackerDiceCount := AttackPower
    1108       else AttackerDiceCount := 3;
    1109     if DefendPower < 2 then DefenderDiceCount := DefendPower
    1110       else DefenderDiceCount := 2;
    1111     // Roll and calculate each side highest number
    1112     AttackerHighestRoll := 1;
     1116    // Attacker can use three dices and defender two
     1117    AttackerDiceCount := Min(AttackPower, 3);
     1118    DefenderDiceCount := Min(DefendPower, 2);
     1119    // Roll and sort numbers
     1120    AttackRolls.Count := AttackerDiceCount;
    11131121    for I := 0 to AttackerDiceCount - 1 do begin
    1114       RollResult := Random(7);
    1115       if RollResult > AttackerHighestRoll then
    1116         AttackerHighestRoll := RollResult;
    1117     end;
    1118     DefenderHighestRoll := 1;
     1122      AttackRolls[I] := Pointer(Random(7));
     1123    end;
     1124    AttackRolls.Sort(ComparePointer);
     1125    S := 'Att:';
     1126    for I := 0 to AttackerDiceCount - 1 do
     1127      S := S + InTToStr(Integer(AttackRolls[I])) + ', ';
     1128    DefendRolls.Count := DefenderDiceCount;
    11191129    for I := 0 to DefenderDiceCount - 1 do begin
    1120       RollResult := Random(7);
    1121       if RollResult > DefenderHighestRoll then
    1122         DefenderHighestRoll := RollResult;
    1123     end;
     1130      DefendRolls[I] := Pointer(Random(7));
     1131    end;
     1132    DefendRolls.Sort(ComparePointer);
     1133    S := S + ' Def:';
     1134    for I := 0 to DefenderDiceCount - 1 do
     1135      S := S + IntToStr(Integer(DefendRolls[I])) + ', ';
    11241136    // Resolution
    1125     LoseCount := Min(AttackerDiceCount, DefenderDiceCount);
    1126     if AttackerHighestRoll > DefenderHighestRoll then Dec(DefendPower, LoseCount)
    1127       else Dec(AttackPower, LoseCount);
    1128   end;
     1137    for I := 0 to Min(AttackerDiceCount, DefenderDiceCount) - 1 do
     1138      if AttackRolls[I] > DefendRolls[I] then Dec(DefendPower)
     1139      else Dec(AttackPower);
     1140  end;
     1141  AttackRolls.Free;
     1142  DefendRolls.Free;
     1143end;
     1144
     1145function TGame.AttackProbability(AttackCount, DefendCount: Integer): Double;
     1146var
     1147  OA, OD: Integer;
     1148begin
     1149  if AttackCount = 0 then begin
     1150    Result := 0;
     1151    Exit;
     1152  end else Result := 1;
     1153  if DefendCount = 0 then Exit;
     1154
     1155  OA := Min(AttackCount, 3);
     1156  OD := Min(DefendCount, 2);
     1157
     1158  if (OA = 1) and (OD = 1) then
     1159    Result := 0.4167 * AttackProbability(AttackCount, DefendCount - 1) +
     1160      0.5833 * AttackProbability(AttackCount - 1, DefendCount)
     1161  else if (OA = 2) and (OD = 1) then
     1162    Result := 0.5787 * AttackProbability(AttackCount, DefendCount - 1) +
     1163      0.4213 * AttackProbability(AttackCount - 1, DefendCount)
     1164  else if (OA = 3) and (OD = 1) then
     1165    Result := 0.6597 * AttackProbability(AttackCount, DefendCount - 1) +
     1166      0.3403 * AttackProbability(AttackCount - 1, DefendCount)
     1167  else if (OA = 1) and (OD = 2) then
     1168    Result := 0.2546 * AttackProbability(AttackCount, DefendCount - 1) +
     1169      0.7454 * AttackProbability(AttackCount - 1, DefendCount)
     1170  else if (OA = 2) and (OD = 2) then
     1171    Result := 0.2276 * AttackProbability(AttackCount, DefendCount - 2) +
     1172      0.4483 * AttackProbability(AttackCount - 2, DefendCount) +
     1173      0.3241 * AttackProbability(AttackCount - 1, DefendCount - 1)
     1174  else if (OA = 3) and (OD = 2) then
     1175    Result := 0.3717 * AttackProbability(AttackCount, DefendCount - 2) +
     1176      0.2926 * AttackProbability(AttackCount - 2, DefendCount) +
     1177      0.3358 * AttackProbability(AttackCount - 1, DefendCount - 1);
    11291178end;
    11301179
Note: See TracChangeset for help on using the changeset viewer.