Changeset 465 for branches/highdpi/UnitProcessing.pas
- Timestamp:
- Nov 30, 2023, 10:16:14 PM (6 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/highdpi/UnitProcessing.pas
r303 r465 13 13 TMoveInfo = record 14 14 MoveType: TMoveType; 15 Cost, ToMaster, EndHealth, Defender, Dcix, Duix, EndHealthDef: integer;16 MountainDelay: boolean;15 Cost, ToMaster, EndHealth, Defender, Dcix, Duix, EndHealthDef: Integer; 16 MountainDelay: Boolean; 17 17 end; 18 18 19 19 var 20 uixSelectedTransport: integer;21 Worked: array [0 .. nPl - 1] of integer; { settler work statistics }20 uixSelectedTransport: Integer; 21 Worked: array [0 .. nPl - 1] of Integer; { settler work statistics } 22 22 23 23 // Moving/Combat 24 function HostileDamage( p, mix, Loc, MP: integer): integer;25 function CalculateMove( p, uix, ToLoc, MoveLength: integer; TestOnly: boolean;26 var MoveInfo: TMoveInfo): integer;27 function GetBattleForecast(Loc: integer; var BattleForecast: TBattleForecast;28 var Duix, Dcix, AStr, DStr, ABaseDamage, DBaseDamage: integer): integer;29 function LoadUnit( p, uix: integer; TestOnly: boolean): integer;30 function UnloadUnit( p, uix: integer; TestOnly: boolean): integer;31 procedure Recover( p, uix: integer);32 function GetMoveAdvice( p, uix: integer; var a: TMoveAdviceData): integer;33 function CanPlaneReturn( p, uix: integer;34 PlaneReturnData: TPlaneReturnData): boolean;24 function HostileDamage(P, mix, Loc, MP: Integer): Integer; 25 function CalculateMove(P, uix, ToLoc, MoveLength: Integer; TestOnly: Boolean; 26 var MoveInfo: TMoveInfo): Integer; 27 function GetBattleForecast(Loc: Integer; var BattleForecast: TBattleForecast; 28 var Duix, Dcix, AStr, DStr, ABaseDamage, DBaseDamage: Integer): Integer; 29 function LoadUnit(P, uix: Integer; TestOnly: Boolean): Integer; 30 function UnloadUnit(P, uix: Integer; TestOnly: Boolean): Integer; 31 procedure Recover(P, uix: Integer); 32 function GetMoveAdvice(P, uix: Integer; var A: TMoveAdviceData): Integer; 33 function CanPlaneReturn(P, uix: Integer; 34 PlaneReturnData: TPlaneReturnData): Boolean; 35 35 36 36 // Terrain Improvement 37 function StartJob( p, uix, NewJob: integer; TestOnly: boolean): integer;38 function Work( p, uix: integer): boolean;39 function GetJobProgress( p, Loc: integer;40 var JobProgressData: TJobProgressData): integer;37 function StartJob(P, uix, NewJob: Integer; TestOnly: Boolean): Integer; 38 function Work(P, uix: Integer): Boolean; 39 function GetJobProgress(P, Loc: Integer; 40 var JobProgressData: TJobProgressData): Integer; 41 41 42 42 // Start/End Game 43 43 procedure InitGame; 44 44 procedure ReleaseGame; 45 45 46 46 47 implementation … … 73 74 74 75 type 75 TToWorkList = array [0 .. INFIN, 0 .. nJob - 1] of word;76 TToWorkList = array [0 .. INFIN, 0 .. nJob - 1] of Word; 76 77 77 78 var … … 82 83 ____________________________________________________________________ 83 84 } 84 function HostileDamage( p, mix, Loc, MP: integer): integer;85 var 86 Tile: integer;85 function HostileDamage(P, mix, Loc, MP: Integer): Integer; 86 var 87 Tile: Integer; 87 88 begin 88 89 Tile := RealMap[Loc]; 89 if (RW[ p].Model[mix].Domain >= dSea) or (RW[p].Model[mix].Kind = mkSettler)90 and (RW[ p].Model[mix].Speed >= 200) or90 if (RW[P].Model[mix].Domain >= dSea) or (RW[P].Model[mix].Kind = mkSettler) 91 and (RW[P].Model[mix].Speed >= 200) or 91 92 (Tile and (fCity or fRiver or fCanal) <> 0) or (Tile and fTerImp = tiBase) 92 or (GWonder[woGardens].EffectiveOwner = p) then93 result := 093 or (GWonder[woGardens].EffectiveOwner = P) then 94 Result := 0 94 95 else if (Tile and fTerrain = fDesert) and 95 96 (Tile and fSpecial <> fSpecial1 { Oasis } ) then 96 97 begin 97 assert((Tile and fTerImp <> tiIrrigation) and (Tile and fTerImp <> tiFarm));98 result := (DesertThurst * MP - 1) div RW[p].Model[mix].Speed + 198 Assert((Tile and fTerImp <> tiIrrigation) and (Tile and fTerImp <> tiFarm)); 99 Result := (DesertThurst * MP - 1) div RW[P].Model[mix].Speed + 1 99 100 end 100 101 else if Tile and fTerrain = fArctic then 101 102 begin 102 assert((Tile and fTerImp <> tiIrrigation) and (Tile and fTerImp <> tiFarm));103 result := (ArcticThurst * MP - 1) div RW[p].Model[mix].Speed + 1103 Assert((Tile and fTerImp <> tiIrrigation) and (Tile and fTerImp <> tiFarm)); 104 Result := (ArcticThurst * MP - 1) div RW[P].Model[mix].Speed + 1 104 105 end 105 106 else 106 result := 0107 end; 108 109 function Controlled( p, Loc: integer; IsDest: boolean): integer;107 Result := 0; 108 end; 109 110 function Controlled(P, Loc: Integer; IsDest: Boolean): Integer; 110 111 { whether tile at Loc is in control zone of enemy unit 111 112 returns combination of tile control flags } 112 113 var 113 Loc1, V8: integer;114 Loc1, V8: Integer; 114 115 Adjacent: TVicinity8Loc; 115 116 begin 116 result := 0;117 if IsDest and (Occupant[Loc] = p) and (ZoCMap[Loc] > 0) then118 exit;117 Result := 0; 118 if IsDest and (Occupant[Loc] = P) and (ZoCMap[Loc] > 0) then 119 Exit; 119 120 // destination tile, not controlled if already occupied 120 121 121 if (RealMap[Loc] and fCity = 0) or ( integer(RealMap[Loc] shr 27) <> p) and122 (ServerVersion[ p] >= $000EF0) then122 if (RealMap[Loc] and fCity = 0) or (Integer(RealMap[Loc] shr 27) <> P) and 123 (ServerVersion[P] >= $000EF0) then 123 124 begin // not own city 124 125 V8_to_Loc(Loc, Adjacent); … … 127 128 Loc1 := Adjacent[V8]; 128 129 if (Loc1 >= 0) and (Loc1 < MapSize) and (ZoCMap[Loc1] > 0) and 129 (Occupant[Loc1] >= 0) and (Occupant[Loc1] <> p) and130 (RW[ p].Treaty[Occupant[Loc1]] < trAlliance) then131 if ObserveLevel[Loc1] and (3 shl ( p* 2)) > 0 then130 (Occupant[Loc1] >= 0) and (Occupant[Loc1] <> P) and 131 (RW[P].Treaty[Occupant[Loc1]] < trAlliance) then 132 if ObserveLevel[Loc1] and (3 shl (P * 2)) > 0 then 132 133 begin // p observes tile 133 result := coKnown or coTrue;134 exit134 Result := coKnown or coTrue; 135 Exit; 135 136 end 136 137 else 137 result := coTrue; // p does not observe tile138 end; 139 end 140 end; 141 142 function GetMoveCost( p, mix, FromLoc, ToLoc, MoveLength: integer;143 var MoveCost: integer): integer;138 Result := coTrue; // p does not observe tile 139 end; 140 end; 141 end; 142 143 function GetMoveCost(P, mix, FromLoc, ToLoc, MoveLength: Integer; 144 var MoveCost: Integer): Integer; 144 145 // MoveLength - 2 for short move, 3 for long move 145 146 var 146 FromTile, ToTile: integer;147 begin 148 result := eOK;147 FromTile, ToTile: Integer; 148 begin 149 Result := eOK; 149 150 FromTile := RealMap[FromLoc]; 150 151 ToTile := RealMap[ToLoc]; 151 with RW[ p].Model[mix] do152 with RW[P].Model[mix] do 152 153 begin 153 154 case Domain of … … 159 160 if (FromTile and (fRR or fCity) <> 0) and 160 161 (ToTile and (fRR or fCity) <> 0) then 161 if GWonder[woShinkansen].EffectiveOwner = pthen162 if GWonder[woShinkansen].EffectiveOwner = P then 162 163 MoveCost := 0 163 164 else … … 173 174 MoveCost := 20 174 175 else if Cap[mcOver] > 0 then 175 result := eNoRoad176 Result := eNoRoad 176 177 else 177 178 case Terrain[ToTile and fTerrain].MoveCost of … … 180 181 2: 181 182 begin 182 assert(Speed - 150 <= 600);183 Assert(Speed - 150 <= 600); 183 184 MoveCost := 50 + (Speed - 150) * 13 shr 7; // heavy terrain 184 185 end; … … 186 187 begin 187 188 MoveCost := Speed; 188 result := eMountains;189 exit189 Result := eMountains; 190 Exit; 190 191 end; 191 192 end; … … 193 194 end 194 195 else 195 result := eDomainMismatch;196 Result := eDomainMismatch; 196 197 197 198 dSea: … … 201 202 MoveCost := 50 * MoveLength { valid move } 202 203 else 203 result := eNoNav { navigation required for open sea }204 else 205 result := eDomainMismatch;204 Result := eNoNav { navigation required for open sea } 205 else 206 Result := eDomainMismatch; 206 207 207 208 dAir: 208 209 MoveCost := 50 * MoveLength; { always valid move } 209 end 210 end 211 end; 212 213 function CalculateMove( p, uix, ToLoc, MoveLength: integer; TestOnly: boolean;214 var MoveInfo: TMoveInfo): integer;210 end; 211 end; 212 end; 213 214 function CalculateMove(P, uix, ToLoc, MoveLength: Integer; TestOnly: Boolean; 215 var MoveInfo: TMoveInfo): Integer; 215 216 var 216 217 uix1, p1, FromLoc, DestControlled, AStr, DStr, ABaseDamage, 217 DBaseDamage: integer;218 DBaseDamage: Integer; 218 219 PModel: ^TModel; 219 220 BattleForecast: TBattleForecast; 220 221 begin 221 with RW[ p], Un[uix] do222 with RW[P], Un[uix] do 222 223 begin 223 224 PModel := @Model[mix]; 224 225 FromLoc := Loc; 225 226 226 BattleForecast.pAtt := p;227 BattleForecast.pAtt := P; 227 228 BattleForecast.mixAtt := mix; 228 229 BattleForecast.HealthAtt := Health; … … 230 231 BattleForecast.FlagsAtt := Flags; 231 232 BattleForecast.Movement := Movement; 232 result := GetBattleForecast(ToLoc, BattleForecast, MoveInfo.Duix,233 Result := GetBattleForecast(ToLoc, BattleForecast, MoveInfo.Duix, 233 234 MoveInfo.Dcix, AStr, DStr, ABaseDamage, DBaseDamage); 234 235 235 if result = eHiddenUnit then236 if Result = eHiddenUnit then 236 237 if TestOnly then 237 result := eOK // behave just like unit was moving238 Result := eOK // behave just like unit was moving 238 239 else if Mode > moLoading_Fast then 239 240 Map[ToLoc] := Map[ToLoc] or fHiddenUnit; 240 if result = eStealthUnit then241 if Result = eStealthUnit then 241 242 if TestOnly then 242 result := eOK // behave just like unit was moving243 Result := eOK // behave just like unit was moving 243 244 else if Mode > moLoading_Fast then 244 245 Map[ToLoc] := Map[ToLoc] or fStealthUnit; 245 if result < rExecuted then246 exit;247 248 case result of246 if Result < rExecuted then 247 Exit; 248 249 case Result of 249 250 eOK: 250 251 MoveInfo.MoveType := mtMove; … … 260 261 begin 261 262 p1 := RealMap[ToLoc] shr 27; 262 if (p1 < nPl) and (p1 <> p) and263 if (p1 < nPl) and (p1 <> P) and 263 264 ((RealMap[Loc] shr 27 <> Cardinal(p1)) and (PModel.Kind <> mkDiplomat) 264 265 and (Treaty[p1] >= trPeace) and (Treaty[p1] < trAlliance) or 265 266 (RealMap[ToLoc] and fCity <> 0) and (Treaty[p1] >= trPeace)) then 266 267 begin 267 result := eTreaty;268 exit268 Result := eTreaty; 269 Exit; 269 270 end; // keep peace treaty! 270 271 end; 271 272 if (RealMap[ToLoc] and fCity <> 0) and 272 (RealMap[ToLoc] shr 27 <> Cardinal( p)) then // empty enemy city273 (RealMap[ToLoc] shr 27 <> Cardinal(P)) then // empty enemy city 273 274 if PModel.Kind = mkDiplomat then 274 275 begin … … 279 280 if PModel.Flags and mdCivil <> 0 then 280 281 begin 281 result := eNoCapturer;282 exit282 Result := eNoCapturer; 283 Exit; 283 284 end; 284 285 MoveInfo.MoveType := mtCapture; … … 288 289 if (PModel.Domain = dSea) and (PModel.Cap[mcArtillery] = 0) then 289 290 begin 290 result := eDomainMismatch;291 exit291 Result := eDomainMismatch; 292 Exit; 292 293 end 293 294 else if (PModel.Attack = 0) and … … 295 296 then 296 297 begin 297 result := eNoBombarder;298 exit298 Result := eNoBombarder; 299 Exit; 299 300 end 300 301 else if Movement < 100 then 301 302 begin 302 result := eNoTime_Bombard;303 exit303 Result := eNoTime_Bombard; 304 Exit; 304 305 end; 305 306 MoveInfo.MoveType := mtBombard; 306 result := eBombarded;307 end 308 end; 309 310 MoveInfo.MountainDelay := false;307 Result := eBombarded; 308 end; 309 end; 310 311 MoveInfo.MountainDelay := False; 311 312 if MoveInfo.MoveType in [mtAttack, mtBombard, mtExpel] then 312 313 begin … … 316 317 then 317 318 begin 318 result := eViolation;319 exit319 Result := eViolation; 320 Exit; 320 321 end; 321 322 if MoveInfo.MoveType = mtBombard then … … 328 329 MoveInfo.EndHealth := BattleForecast.EndHealthAtt; 329 330 MoveInfo.EndHealthDef := BattleForecast.EndHealthDef; 330 end 331 end; 331 332 end 332 333 else // if MoveInfo.MoveType in [mtMove,mtCapture,mtSpyMission] then … … 336 337 MoveInfo.Cost := PModel.Speed; 337 338 if RealMap[ToLoc] and fTerrain < fGrass then 338 result := eDomainMismatch;339 Result := eDomainMismatch; 339 340 end 340 341 else 341 342 begin 342 result := GetMoveCost(p, mix, FromLoc, ToLoc, MoveLength,343 Result := GetMoveCost(P, mix, FromLoc, ToLoc, MoveLength, 343 344 MoveInfo.Cost); 344 if result = eMountains then345 begin 346 result := eOK;347 MoveInfo.MountainDelay := true345 if Result = eMountains then 346 begin 347 Result := eOK; 348 MoveInfo.MountainDelay := True 348 349 end; 349 350 end; 350 if ( result >= rExecuted) and (MoveInfo.MoveType = mtSpyMission) then351 result := eMissionDone;351 if (Result >= rExecuted) and (MoveInfo.MoveType = mtSpyMission) then 352 Result := eMissionDone; 352 353 353 354 MoveInfo.ToMaster := -1; 354 if ( result = eDomainMismatch) and (PModel.Domain < dSea) and355 if (Result = eDomainMismatch) and (PModel.Domain < dSea) and 355 356 (PModel.Cap[mcOver] = 0) then 356 357 begin … … 360 361 (TroopLoad < Model[mix].MTrans * Model[mix].Cap[mcSeaTrans]) then 361 362 begin 362 result := eLoaded;363 Result := eLoaded; 363 364 MoveInfo.Cost := PModel.Speed; 364 365 MoveInfo.ToMaster := uix1; … … 377 378 (AirLoad < Model[mix].MTrans * Model[mix].Cap[mcCarrier]) then 378 379 begin // load plane to ship 379 result := eLoaded;380 Result := eLoaded; 380 381 MoveInfo.ToMaster := uix1; 381 382 if (uixSelectedTransport >= 0) and (uix1 = uixSelectedTransport) 382 383 then 383 384 Break; 384 end 385 end; 385 386 end; 386 if result < rExecuted then387 exit;387 if Result < rExecuted then 388 Exit; 388 389 389 390 if (Master < 0) and (MoveInfo.ToMaster < 0) then 390 MoveInfo.EndHealth := Health - HostileDamage( p, mix, ToLoc,391 MoveInfo.EndHealth := Health - HostileDamage(P, mix, ToLoc, 391 392 MoveInfo.Cost) 392 393 else … … 394 395 395 396 if (Mode = moPlaying) and (PModel.Flags and mdZOC <> 0) and (Master < 0) 396 and (MoveInfo.ToMaster < 0) and (Controlled( p, FromLoc, false) >= coTrue)397 and (MoveInfo.ToMaster < 0) and (Controlled(P, FromLoc, False) >= coTrue) 397 398 then 398 399 begin 399 DestControlled := Controlled( p, ToLoc, true);400 DestControlled := Controlled(P, ToLoc, True); 400 401 if DestControlled >= coTrue + coKnown then 401 402 begin 402 result := eZOC;403 exit403 Result := eZOC; 404 Exit; 404 405 end 405 406 else if not TestOnly and (DestControlled >= coTrue) then 406 407 begin 407 result := eZOC_EnemySpotted;408 exit409 end 408 Result := eZOC_EnemySpotted; 409 Exit; 410 end; 410 411 end; 411 if (Movement = 0) and (ServerVersion[ p] >= $0100F1) or412 if (Movement = 0) and (ServerVersion[P] >= $0100F1) or 412 413 (MoveInfo.Cost > Movement) then 413 414 if (Master >= 0) or (MoveInfo.ToMaster >= 0) then 414 415 begin 415 result := eNoTime_Load;416 exit416 Result := eNoTime_Load; 417 Exit; 417 418 end 418 419 else 419 420 begin 420 result := eNoTime_Move;421 exit421 Result := eNoTime_Move; 422 Exit; 422 423 end; 423 424 if (MoveInfo.EndHealth <= 0) or (MoveInfo.MoveType = mtSpyMission) then 424 result := result or rUnitRemoved;425 Result := Result or rUnitRemoved; 425 426 // spy mission or victim of HostileDamage 426 427 … … 433 434 MoveInfo.Defender := RealMap[ToLoc] shr 27; 434 435 SearchCity(ToLoc, MoveInfo.Defender, MoveInfo.Dcix); 435 end 436 end 437 end; // CalculateMove438 439 function GetBattleForecast(Loc: integer; var BattleForecast: TBattleForecast;440 var Duix, Dcix, AStr, DStr, ABaseDamage, DBaseDamage: integer): integer;441 var 442 Time, Defender, ABon, DBon, DCnt, MultiDamage: integer;436 end; 437 end; 438 end; 439 440 function GetBattleForecast(Loc: Integer; var BattleForecast: TBattleForecast; 441 var Duix, Dcix, AStr, DStr, ABaseDamage, DBaseDamage: Integer): Integer; 442 var 443 Time, Defender, ABon, DBon, DCnt, MultiDamage: Integer; 443 444 PModel, DModel: ^TModel; 444 445 begin … … 448 449 if (Defender < 0) or (Defender = pAtt) then 449 450 begin 450 result := eOK;451 exit451 Result := eOK; 452 Exit; 452 453 end; // no attack, simple move 453 454 … … 458 459 EndHealthAtt := HealthAtt; 459 460 EndHealthDef := RW[Defender].Un[Duix].Health; 460 result := eOK;461 exit461 Result := eOK; 462 Exit; 462 463 end; 463 464 … … 469 470 (ObserveLevel[Loc] shr (2 * pAtt) and 3 < lObserveAll) then 470 471 begin 471 result := eHiddenUnit;472 exit;472 Result := eHiddenUnit; 473 Exit; 473 474 end; // attacking submarine not allowed 474 475 if (DModel.Cap[mcStealth] > 0) and 475 476 (ObserveLevel[Loc] shr (2 * pAtt) and 3 <> lObserveSuper) then 476 477 begin 477 result := eStealthUnit;478 exit;478 Result := eStealthUnit; 479 Exit; 479 480 end; // attacking stealth aircraft not allowed 480 481 if (DModel.Domain = dAir) and (DModel.Kind <> mkSpecial_Glider) and 481 482 (PModel.Domain <> dAir) then 482 483 begin 483 result := eDomainMismatch;484 exit484 Result := eDomainMismatch; 485 Exit; 485 486 end; // can't attack plane 486 487 end; … … 491 492 (PModel.Domain = dSea) and (RealMap[Loc] and fTerrain >= fGrass)) then 492 493 begin 493 result := eDomainMismatch;494 exit494 Result := eDomainMismatch; 495 Exit; 495 496 end; 496 497 if (PModel.Attack = 0) and not((PModel.Cap[mcBombs] > 0) and 497 498 (FlagsAtt and unBombsLoaded <> 0) and (DModel.Domain < dAir)) then 498 499 begin 499 result := eInvalid;500 exit500 Result := eInvalid; 501 Exit; 501 502 end; 502 503 503 504 if Movement = 0 then 504 505 begin 505 result := eNoTime_Attack;506 exit507 end; 508 509 {$IFOPT O-} assert(InvalidTreatyMap = 0); {$ENDIF}506 Result := eNoTime_Attack; 507 Exit; 508 end; 509 510 {$IFOPT O-}Assert(InvalidTreatyMap = 0); {$ENDIF} 510 511 if RW[pAtt].Treaty[Defender] >= trPeace then 511 512 begin 512 513 if (PModel.Domain <> dAir) and (PModel.Attack > 0) and 513 ( integer(RealMap[Loc] shr 27) = pAtt) then514 (Integer(RealMap[Loc] shr 27) = pAtt) then 514 515 if Movement >= 100 then 515 516 begin // expel friendly unit 516 517 EndHealthDef := RW[Defender].Un[Duix].Health; 517 518 EndHealthAtt := HealthAtt; 518 result := eExpelled519 Result := eExpelled 519 520 end 520 521 else 521 result := eNoTime_Expel522 Result := eNoTime_Expel 522 523 else 523 result := eTreaty;524 exit;524 Result := eTreaty; 525 Exit; 525 526 end; 526 527 … … 533 534 (Continent[RW[Defender].City[Dcix].Loc] = GrWallContinent[Defender])) 534 535 then 535 inc(DBon, 8)536 Inc(DBon, 8) 536 537 else if (PModel.Domain = dSea) and 537 538 (RW[Defender].City[Dcix].Built[imCoastalFort] = 1) then 538 inc(DBon, 4)539 Inc(DBon, 4) 539 540 else if (PModel.Domain = dAir) and 540 541 (RW[Defender].City[Dcix].Built[imMissileBat] = 1) then 541 inc(DBon, 4);542 Inc(DBon, 4); 542 543 if RW[Defender].City[Dcix].Built[imBunker] = 1 then 543 inc(DBon, 4)544 Inc(DBon, 4) 544 545 end; 545 546 if (PModel.Domain = dAir) and (DModel.Cap[mcAirDef] > 0) then 546 inc(DBon, 4);547 Inc(DBon, 4); 547 548 DStr := DModel.Defense * DBon * 100; 548 549 if (DModel.Domain = dAir) and ((RealMap[Loc] and fCity <> 0) or … … 577 578 DBaseDamage := 1; 578 579 if DBaseDamage > RW[Defender].Un[Duix].Health then 579 DBaseDamage := RW[Defender].Un[Duix].Health 580 DBaseDamage := RW[Defender].Un[Duix].Health; 580 581 end; 581 582 … … 589 590 ABaseDamage := 1; 590 591 if ABaseDamage > HealthAtt then 591 ABaseDamage := HealthAtt 592 ABaseDamage := HealthAtt; 592 593 end; 593 594 … … 621 622 622 623 if EndHealthDef > 0 then 623 result := eLost624 Result := eLost 624 625 else if EndHealthAtt > 0 then 625 result := eWon626 Result := eWon 626 627 else 627 result := eBloody628 end 629 end; // GetBattleForecast630 631 function LoadUnit( p, uix: integer; TestOnly: boolean): integer;632 var 633 uix1, d, Cost, ToMaster: integer;634 begin 635 result := eOK;636 with RW[ p].Un[uix] do637 begin 638 d := RW[p].Model[mix].Domain;639 if (Master >= 0) or ( d= dSea) or640 (RW[ p].Model[mix].Cap[mcAirTrans] + RW[p].Model[mix].Cap[mcOver] > 0) then641 result := eViolation628 Result := eBloody; 629 end; 630 end; 631 632 function LoadUnit(P, uix: Integer; TestOnly: Boolean): Integer; 633 var 634 uix1, D, Cost, ToMaster: Integer; 635 begin 636 Result := eOK; 637 with RW[P].Un[uix] do 638 begin 639 D := RW[P].Model[mix].Domain; 640 if (Master >= 0) or (D = dSea) or 641 (RW[P].Model[mix].Cap[mcAirTrans] + RW[P].Model[mix].Cap[mcOver] > 0) then 642 Result := eViolation 642 643 else 643 644 begin 644 645 ToMaster := -1; 645 for uix1 := 0 to RW[ p].nUn - 1 do646 if RW[ p].Un[uix1].Loc = Loc then647 with RW[ p].Un[uix1], RW[p].Model[mix] do648 if ( d< dSea) and646 for uix1 := 0 to RW[P].nUn - 1 do 647 if RW[P].Un[uix1].Loc = Loc then 648 with RW[P].Un[uix1], RW[P].Model[mix] do 649 if (D < dSea) and 649 650 (TroopLoad < MTrans * (Cap[mcSeaTrans] + Cap[mcAirTrans])) or 650 ( d= dAir) and (AirLoad < MTrans * Cap[mcCarrier]) then651 (D = dAir) and (AirLoad < MTrans * Cap[mcCarrier]) then 651 652 begin { load onto unit uix1 } 652 653 if (uixSelectedTransport < 0) or (uix1 = uixSelectedTransport) … … 654 655 begin 655 656 ToMaster := uix1; 656 Break 657 Break; 657 658 end 658 659 else if ToMaster < 0 then … … 660 661 end; 661 662 if ToMaster < 0 then 662 result := eNoLoadCapacity663 Result := eNoLoadCapacity 663 664 else 664 665 begin 665 if d= dAir then666 if D = dAir then 666 667 Cost := 100 667 668 else 668 Cost := RW[ p].Model[mix].Speed;669 Cost := RW[P].Model[mix].Speed; 669 670 if Movement < Cost then 670 result := eNoTime_Load671 Result := eNoTime_Load 671 672 else if not TestOnly then 672 673 begin 673 FreeUnit( p, uix);674 dec(Movement, Cost);675 if d= dAir then676 inc(RW[p].Un[ToMaster].AirLoad)674 FreeUnit(P, uix); 675 Dec(Movement, Cost); 676 if D = dAir then 677 Inc(RW[P].Un[ToMaster].AirLoad) 677 678 else 678 inc(RW[p].Un[ToMaster].TroopLoad);679 Inc(RW[P].Un[ToMaster].TroopLoad); 679 680 Master := ToMaster; 680 681 UpdateUnitMap(Loc); 681 end 682 end 683 end 684 end 685 end; 686 687 function UnloadUnit( p, uix: integer; TestOnly: boolean): integer;688 var 689 Cost: integer;690 begin 691 result := eOK;692 with RW[ p].Un[uix] do682 end; 683 end; 684 end; 685 end; 686 end; 687 688 function UnloadUnit(P, uix: Integer; TestOnly: Boolean): Integer; 689 var 690 Cost: Integer; 691 begin 692 Result := eOK; 693 with RW[P].Un[uix] do 693 694 if Master < 0 then 694 result := eNotChanged695 else if (RW[ p].Model[mix].Domain < dSea) and695 Result := eNotChanged 696 else if (RW[P].Model[mix].Domain < dSea) and 696 697 (RealMap[Loc] and fTerrain < fGrass) then 697 result := eDomainMismatch698 Result := eDomainMismatch 698 699 // else if (RW[p].Model[mix].Domain<dSea) 699 700 // and (RW[p].Model[mix].Flags and mdCivil<>0) … … 701 702 else 702 703 begin 703 if RW[ p].Model[mix].Domain = dAir then704 if RW[P].Model[mix].Domain = dAir then 704 705 Cost := 100 705 706 else 706 Cost := RW[ p].Model[mix].Speed;707 Cost := RW[P].Model[mix].Speed; 707 708 if Movement < Cost then 708 result := eNoTime_Load709 Result := eNoTime_Load 709 710 else if not TestOnly then 710 711 begin 711 dec(Movement, Cost);712 if RW[ p].Model[mix].Domain = dAir then713 dec(RW[p].Un[Master].AirLoad)714 else 715 begin 716 dec(RW[p].Un[Master].TroopLoad);712 Dec(Movement, Cost); 713 if RW[P].Model[mix].Domain = dAir then 714 Dec(RW[P].Un[Master].AirLoad) 715 else 716 begin 717 Dec(RW[P].Un[Master].TroopLoad); 717 718 // Movement:=0 // no more movement after unload 718 719 end; 719 720 Master := -1; 720 PlaceUnit( p, uix);721 PlaceUnit(P, uix); 721 722 UpdateUnitMap(Loc); 722 723 end; 723 end 724 end; 725 726 procedure Recover( p, uix: integer);727 var 728 cix, Recovery: integer;729 begin 730 with RW[ p], Un[uix] do724 end; 725 end; 726 727 procedure Recover(P, uix: Integer); 728 var 729 cix, Recovery: Integer; 730 begin 731 with RW[P], Un[uix] do 731 732 begin 732 733 if (Master >= 0) and (Model[Un[Master].mix].Cap[mcSupplyShip] > 0) then … … 738 739 cix := nCity - 1; 739 740 while (cix >= 0) and (City[cix].Loc <> Loc) do 740 dec(cix);741 Dec(cix); 741 742 if City[cix].Flags and chDisorder <> 0 then 742 743 Recovery := NoCityRecovery … … 761 762 if Recovery > 100 - Health then 762 763 Recovery := 100 - Health; 763 inc(Health, Recovery);764 Inc(Health, Recovery); 764 765 end; 765 766 end; 766 767 767 function GetMoveAdvice( p, uix: integer; var a: TMoveAdviceData): integer;768 function GetMoveAdvice(P, uix: Integer; var A: TMoveAdviceData): Integer; 768 769 const 769 770 // domains … … 777 778 gmaAlpine = 8; 778 779 var 779 i, FromLoc, EndLoc, T, T1, maxmov, initmov, Loc, Loc1, FromTile, ToTile, V8,780 I, FromLoc, EndLoc, T, T1, maxmov, initmov, Loc, Loc1, FromTile, ToTile, V8, 780 781 MoveInfo, HeavyCost, RailCost, MoveCost, AddDamage, MaxDamage, 781 MovementLeft: integer;782 MovementLeft: Integer; 782 783 Map: ^TTileList; 783 784 Q: TIPQ; 784 785 Adjacent: TVicinity8Loc; 785 From: array [0 .. lxmax * lymax - 1] of integer;786 Time: array [0 .. lxmax * lymax - 1] of integer;787 Damage: array [0 .. lxmax * lymax - 1] of integer;788 MountainDelay, Resistant: boolean;786 From: array [0 .. lxmax * lymax - 1] of Integer; 787 Time: array [0 .. lxmax * lymax - 1] of Integer; 788 Damage: array [0 .. lxmax * lymax - 1] of Integer; 789 MountainDelay, Resistant: Boolean; 789 790 // tt,tt0: int64; 790 791 begin 791 792 // QueryPerformanceCounter(tt0); 792 793 793 MaxDamage := RW[ p].Un[uix].Health - 1;794 if MaxDamage > a.MaxHostile_MovementLeft then795 if a.MaxHostile_MovementLeft >= 0 then796 MaxDamage := a.MaxHostile_MovementLeft794 MaxDamage := RW[P].Un[uix].Health - 1; 795 if MaxDamage > A.MaxHostile_MovementLeft then 796 if A.MaxHostile_MovementLeft >= 0 then 797 MaxDamage := A.MaxHostile_MovementLeft 797 798 else 798 799 MaxDamage := 0; 799 800 800 Map := @(RW[ p].Map^);801 if ( a.ToLoc <> maNextCity) and ((a.ToLoc < 0) or (a.ToLoc >= MapSize)) then802 begin 803 result := eInvalid;804 exit801 Map := @(RW[P].Map^); 802 if (A.ToLoc <> maNextCity) and ((A.ToLoc < 0) or (A.ToLoc >= MapSize)) then 803 begin 804 Result := eInvalid; 805 Exit; 805 806 end; 806 if ( a.ToLoc <> maNextCity) and (Map[a.ToLoc] and fTerrain = fUNKNOWN) then807 begin 808 result := eNoWay;809 exit807 if (A.ToLoc <> maNextCity) and (Map[A.ToLoc] and fTerrain = fUNKNOWN) then 808 begin 809 Result := eNoWay; 810 Exit; 810 811 end; 811 812 812 with RW[ p].Model[RW[p].Un[uix].mix] do813 with RW[P].Model[RW[P].Un[uix].mix] do 813 814 case Domain of 814 815 dGround: 815 if ( a.ToLoc <> maNextCity) and (Map[a.ToLoc] and fTerrain = fOcean) then816 begin 817 result := eDomainMismatch;818 exit816 if (A.ToLoc <> maNextCity) and (Map[A.ToLoc] and fTerrain = fOcean) then 817 begin 818 Result := eDomainMismatch; 819 Exit; 819 820 end 820 821 else … … 825 826 MoveInfo := gmaGround_NoZoC; 826 827 if Cap[mcOver] > 0 then 827 inc(MoveInfo, gmaOver);828 Inc(MoveInfo, gmaOver); 828 829 if Cap[mcAlpine] > 0 then 829 inc(MoveInfo, gmaAlpine);830 Inc(MoveInfo, gmaAlpine); 830 831 HeavyCost := 50 + (Speed - 150) * 13 shr 7; 831 if GWonder[woShinkansen].EffectiveOwner = pthen832 if GWonder[woShinkansen].EffectiveOwner = P then 832 833 RailCost := 0 833 834 else … … 835 836 maxmov := Speed; 836 837 initmov := 0; 837 Resistant := (GWonder[woGardens].EffectiveOwner = p) or838 Resistant := (GWonder[woGardens].EffectiveOwner = P) or 838 839 (Kind = mkSettler) and (Speed >= 200); 839 840 end; 840 841 dSea: 841 if ( a.ToLoc <> maNextCity) and (Map[a.ToLoc] and fTerrain >= fGrass) and842 (Map[ a.ToLoc] and (fCity or fUnit or fCanal) = 0) then843 begin 844 result := eDomainMismatch;845 exit842 if (A.ToLoc <> maNextCity) and (Map[A.ToLoc] and fTerrain >= fGrass) and 843 (Map[A.ToLoc] and (fCity or fUnit or fCanal) = 0) then 844 begin 845 Result := eDomainMismatch; 846 Exit; 846 847 end 847 848 else … … 849 850 MoveInfo := gmaSea; 850 851 if Cap[mcNav] > 0 then 851 inc(MoveInfo, gmaNav);852 maxmov := UnitSpeed( p, RW[p].Un[uix].mix, 100);853 initmov := maxmov - UnitSpeed( p, RW[p].Un[uix].mix,854 RW[ p].Un[uix].Health);852 Inc(MoveInfo, gmaNav); 853 maxmov := UnitSpeed(P, RW[P].Un[uix].mix, 100); 854 initmov := maxmov - UnitSpeed(P, RW[P].Un[uix].mix, 855 RW[P].Un[uix].Health); 855 856 end; 856 857 dAir: … … 859 860 maxmov := Speed; 860 861 initmov := 0; 861 end 862 end; 863 864 FromLoc := RW[ p].Un[uix].Loc;862 end; 863 end; 864 865 FromLoc := RW[P].Un[uix].Loc; 865 866 FillChar(Time, SizeOf(Time), 255); { -1 } 866 867 Damage[FromLoc] := 0; 867 868 Q := TIPQ.Create(MapSize); 868 Q.Put(FromLoc, (maxmov - RW[ p].Un[uix].Movement) shl 8);869 Q.Put(FromLoc, (maxmov - RW[P].Un[uix].Movement) shl 8); 869 870 while Q.Get(Loc, T) do 870 871 begin 871 872 Time[Loc] := T; 872 if T >= ( a.MoreTurns + 1) shl 20 then873 if T >= (A.MoreTurns + 1) shl 20 then 873 874 begin 874 875 Loc := -1; 875 Break 876 Break; 876 877 end; 877 878 FromTile := Map[Loc]; 878 if (Loc = a.ToLoc) or (a.ToLoc = maNextCity) and (FromTile and fCity <> 0)879 if (Loc = A.ToLoc) or (A.ToLoc = maNextCity) and (FromTile and fCity <> 0) 879 880 then 880 881 Break; 881 882 if T and $FFF00 = $FFF00 then 882 inc(T, $100000); // indicates mountain delay883 Inc(T, $100000); // indicates mountain delay 883 884 V8_to_Loc(Loc, Adjacent); 884 885 for V8 := 0 to 7 do … … 888 889 begin 889 890 ToTile := Map[Loc1]; 890 if (Loc1 = a.ToLoc) and (ToTile and (fUnit or fOwned) = fUnit) and891 if (Loc1 = A.ToLoc) and (ToTile and (fUnit or fOwned) = fUnit) and 891 892 not((MoveInfo and 3 = gmaSea) and (FromTile and fTerrain >= fGrass)) 892 893 and not((MoveInfo and 3 = gmaAir) and ((FromTile and fCity <> 0) or … … 897 898 end 898 899 else if (ToTile and fTerrain <> fUNKNOWN) and 899 ((Loc1 = a.ToLoc) or (ToTile and (fCity or fOwned) <> fCity))900 ((Loc1 = A.ToLoc) or (ToTile and (fCity or fOwned) <> fCity)) 900 901 // don't move through enemy cities 901 and ((Loc1 = a.ToLoc) or (ToTile and (fUnit or fOwned) <> fUnit))902 and ((Loc1 = A.ToLoc) or (ToTile and (fUnit or fOwned) <> fUnit)) 902 903 // way is blocked 903 904 and (ToTile and not FromTile and fPeace = 0) and … … 909 910 // calculate move cost, must be identic to GetMoveCost function 910 911 AddDamage := 0; 911 MountainDelay := false;912 MountainDelay := False; 912 913 case MoveInfo of 913 914 … … 955 956 begin 956 957 MoveCost := maxmov; 957 MountainDelay := true;958 MountainDelay := True; 958 959 end; 959 960 end; … … 989 990 if (MoveCost > 0) and not MountainDelay then 990 991 if V8 and 1 <> 0 then 991 inc(MoveCost, MoveCost * 2)992 Inc(MoveCost, MoveCost * 2) 992 993 else 993 inc(MoveCost, MoveCost);994 Inc(MoveCost, MoveCost); 994 995 995 996 if (MoveInfo and 2 <> 0) // ground unit, check transport load/unload … … 1010 1011 if FromTile and (fTerrain or fCity or fRiver or fCanal or 1011 1012 fSpecial1 { Oasis } ) = fDesert then 1012 inc(AddDamage, (DesertThurst * (maxmov - T shr 8 and $FFF) -1013 Inc(AddDamage, (DesertThurst * (maxmov - T shr 8 and $FFF) - 1013 1014 1) div maxmov + 1) 1014 1015 else if FromTile and (fTerrain or fCity or fRiver or fCanal) = fArctic 1015 1016 then 1016 inc(AddDamage, (ArcticThurst * (maxmov - T shr 8 and $FFF) -1017 Inc(AddDamage, (ArcticThurst * (maxmov - T shr 8 and $FFF) - 1017 1018 1) div maxmov + 1); 1018 1019 … … 1029 1030 From[Loc1] := Loc; 1030 1031 Damage[Loc1] := Damage[Loc] + AddDamage; 1031 end 1032 end 1033 end 1034 end 1035 end 1032 end; 1033 end; 1034 end; 1035 end; 1036 end; 1036 1037 end; 1037 1038 FreeAndNil(Q); 1038 if (Loc = a.ToLoc) or (a.ToLoc = maNextCity) and (Loc >= 0) and1039 if (Loc = A.ToLoc) or (A.ToLoc = maNextCity) and (Loc >= 0) and 1039 1040 (Map[Loc] and fCity <> 0) then 1040 1041 begin 1041 a.MoreTurns := T shr 20;1042 A.MoreTurns := T shr 20; 1042 1043 EndLoc := Loc; 1043 a.nStep := 0;1044 A.nStep := 0; 1044 1045 while Loc <> FromLoc do 1045 1046 begin 1046 1047 if Time[Loc] < $100000 then 1047 inc(a.nStep);1048 Inc(A.nStep); 1048 1049 Loc := From[Loc]; 1049 1050 end; 1050 1051 Loc := EndLoc; 1051 i := a.nStep;1052 I := A.nStep; 1052 1053 while Loc <> FromLoc do 1053 1054 begin 1054 1055 if Time[Loc] < $100000 then 1055 1056 begin 1056 dec(i);1057 if i< 25 then1058 begin 1059 a.dx[i] := ((Loc mod lx * 2 + Loc div lx and 1) -1057 Dec(I); 1058 if I < 25 then 1059 begin 1060 A.dx[I] := ((Loc mod lx * 2 + Loc div lx and 1) - 1060 1061 (From[Loc] mod lx * 2 + From[Loc] div lx and 1) + 3 * lx) 1061 1062 mod (2 * lx) - lx; 1062 a.dy[i] := Loc div lx - From[Loc] div lx;1063 A.dy[I] := Loc div lx - From[Loc] div lx; 1063 1064 end 1064 1065 end; 1065 1066 Loc := From[Loc]; 1066 1067 end; 1067 a.MaxHostile_MovementLeft := maxmov - Time[EndLoc] shr 8 and $FFF;1068 if a.nStep > 25 then1069 a.nStep := 25;1070 result := eOK1068 A.MaxHostile_MovementLeft := maxmov - Time[EndLoc] shr 8 and $FFF; 1069 if A.nStep > 25 then 1070 A.nStep := 25; 1071 Result := eOK 1071 1072 end 1072 1073 else 1073 result := eNoWay;1074 Result := eNoWay; 1074 1075 1075 1076 // QueryPerformanceCounter(tt);{time in s is: (tt-tt0)/PerfFreq} 1076 end; // GetMoveAdvice1077 1078 function CanPlaneReturn( p, uix: integer;1079 PlaneReturnData: TPlaneReturnData): boolean;1077 end; 1078 1079 function CanPlaneReturn(P, uix: Integer; 1080 PlaneReturnData: TPlaneReturnData): Boolean; 1080 1081 const 1081 1082 mfEnd = 1; 1082 1083 mfReached = 2; 1083 1084 var 1084 uix1, T, T1, Loc, Loc1, FromTile, ToTile, V8, MoveCost, maxmov: integer;1085 uix1, T, T1, Loc, Loc1, FromTile, ToTile, V8, MoveCost, maxmov: Integer; 1085 1086 Map: ^TTileList; 1086 1087 Q: TIPQ; 1087 1088 Adjacent: TVicinity8Loc; 1088 MapFlags: array [0 .. lxmax * lymax - 1] of byte;1089 begin 1090 Map := @(RW[ p].Map^);1089 MapFlags: array [0 .. lxmax * lymax - 1] of Byte; 1090 begin 1091 Map := @(RW[P].Map^); 1091 1092 1092 1093 // calculate possible return points 1093 1094 FillChar(MapFlags, SizeOf(MapFlags), 0); 1094 if RW[ p].Model[RW[p].Un[uix].mix].Kind = mkSpecial_Glider then1095 if RW[P].Model[RW[P].Un[uix].mix].Kind = mkSpecial_Glider then 1095 1096 begin 1096 1097 for Loc := 0 to MapSize - 1 do … … 1105 1106 (Map[Loc] and (fUnit or fOwned) <> fUnit) then 1106 1107 MapFlags[Loc] := MapFlags[Loc] or mfEnd; 1107 if RW[ p].Model[RW[p].Un[uix].mix].Cap[mcAirTrans] = 0 then1108 if RW[P].Model[RW[P].Un[uix].mix].Cap[mcAirTrans] = 0 then 1108 1109 // plane can land on carriers 1109 for uix1 := 0 to RW[ p].nUn - 1 do1110 with RW[ p].Un[uix1], RW[p].Model[mix] do1110 for uix1 := 0 to RW[P].nUn - 1 do 1111 with RW[P].Un[uix1], RW[P].Model[mix] do 1111 1112 if AirLoad < MTrans * Cap[mcCarrier] then 1112 1113 MapFlags[Loc] := MapFlags[Loc] or mfEnd; 1113 1114 end; 1114 1115 1115 with RW[ p].Un[uix] do1116 with RW[P].Un[uix] do 1116 1117 begin 1117 1118 if Master >= 0 then // can return to same carrier, even if full now 1118 1119 MapFlags[Loc] := MapFlags[Loc] or mfEnd; 1119 maxmov := RW[ p].Model[mix].Speed;1120 maxmov := RW[P].Model[mix].Speed; 1120 1121 end; 1121 1122 1122 result := false;1123 Result := False; 1123 1124 Q := TIPQ.Create(MapSize); 1124 1125 Q.Put(PlaneReturnData.Loc, (maxmov - PlaneReturnData.Movement) shl 8); … … 1128 1129 if T >= (PlaneReturnData.Fuel + 1) shl 20 then 1129 1130 begin 1130 result := false;1131 Break 1131 Result := False; 1132 Break; 1132 1133 end; 1133 1134 if MapFlags[Loc] and mfEnd <> 0 then 1134 1135 begin 1135 result := true;1136 Break 1136 Result := True; 1137 Break; 1137 1138 end; 1138 1139 FromTile := Map[Loc]; … … 1161 1162 T1 := T + MoveCost shl 8; 1162 1163 Q.Put(Loc1, T1); 1163 end 1164 end 1165 end 1164 end; 1165 end; 1166 end; 1166 1167 end; 1167 1168 FreeAndNil(Q); 1168 end; // CanPlaneReturn1169 end; 1169 1170 1170 1171 { … … 1172 1173 ____________________________________________________________________ 1173 1174 } 1174 function CalculateJobWork( p, Loc, Job: integer; var JobWork: integer): integer;1175 var 1176 TerrType: integer;1177 begin 1178 result := eOK;1175 function CalculateJobWork(P, Loc, Job: Integer; var JobWork: Integer): Integer; 1176 var 1177 TerrType: Integer; 1178 begin 1179 Result := eOK; 1179 1180 TerrType := RealMap[Loc] and fTerrain; 1180 1181 with Terrain[TerrType] do … … 1182 1183 jCity: 1183 1184 if RealMap[Loc] and fCity <> 0 then 1184 result := eInvalid1185 Result := eInvalid 1185 1186 else if IrrEff = 0 then 1186 result := eNoCityTerrain1187 Result := eNoCityTerrain 1187 1188 else 1188 1189 JobWork := CityWork; … … 1192 1193 JobWork := MoveCost * RoadWork; 1193 1194 if RealMap[Loc] and fRiver <> 0 then 1194 if RW[ p].Tech[adBridgeBuilding] >= tsApplicable then1195 inc(JobWork, RoadBridgeWork) { across river }1195 if RW[P].Tech[adBridgeBuilding] >= tsApplicable then 1196 Inc(JobWork, RoadBridgeWork) { across river } 1196 1197 else 1197 result := eNoBridgeBuilding1198 Result := eNoBridgeBuilding; 1198 1199 end 1199 1200 else 1200 result := eInvalid;1201 Result := eInvalid; 1201 1202 jRR: 1202 1203 if RealMap[Loc] and fRoad = 0 then 1203 result := eNoPreq1204 Result := eNoPreq 1204 1205 else if RealMap[Loc] and fRR <> 0 then 1205 result := eInvalid1206 Result := eInvalid 1206 1207 else 1207 1208 begin 1208 1209 JobWork := MoveCost * RRWork; 1209 1210 if RealMap[Loc] and fRiver <> 0 then 1210 inc(JobWork, RRBridgeWork); { across river }1211 Inc(JobWork, RRBridgeWork); { across river } 1211 1212 end; 1212 1213 jClear: 1213 if (TerrType = fDesert) and (GWonder[woGardens].EffectiveOwner <> p)1214 if (TerrType = fDesert) and (GWonder[woGardens].EffectiveOwner <> P) 1214 1215 then 1215 result := eInvalid1216 Result := eInvalid 1216 1217 else if ClearTerrain >= 0 then 1217 1218 JobWork := IrrClearWork 1218 1219 else 1219 result := eInvalid;1220 Result := eInvalid; 1220 1221 jIrr: 1221 1222 begin … … 1223 1224 if (IrrEff = 0) or (RealMap[Loc] and fTerImp = tiIrrigation) or 1224 1225 (RealMap[Loc] and fTerImp = tiFarm) then 1225 result := eInvalid1226 Result := eInvalid; 1226 1227 end; 1227 1228 jFarm: 1228 1229 if RealMap[Loc] and fTerImp <> tiIrrigation then 1229 result := eNoPreq1230 Result := eNoPreq 1230 1231 else 1231 1232 begin 1232 1233 JobWork := IrrClearWork * FarmWork; 1233 1234 if (JobWork <= 0) or (RealMap[Loc] and fTerImp = tiFarm) then 1234 result := eInvalid1235 Result := eInvalid; 1235 1236 end; 1236 1237 jAfforest: … … 1238 1239 JobWork := MineAfforestWork 1239 1240 else 1240 result := eInvalid;1241 Result := eInvalid; 1241 1242 jMine: 1242 1243 begin 1243 1244 JobWork := MineAfforestWork; 1244 1245 if (MineEff = 0) or (RealMap[Loc] and fTerImp = tiMine) then 1245 result := eInvalid1246 Result := eInvalid; 1246 1247 end; 1247 1248 jFort: … … 1249 1250 JobWork := MoveCost * FortWork 1250 1251 else 1251 result := eInvalid;1252 Result := eInvalid; 1252 1253 jCanal: 1253 1254 if (RealMap[Loc] and fCanal = 0) and (TerrType in TerrType_Canalable) … … 1255 1256 JobWork := CanalWork 1256 1257 else 1257 result := eInvalid;1258 Result := eInvalid; 1258 1259 jTrans: 1259 1260 begin 1260 1261 JobWork := TransWork; 1261 1262 if JobWork <= 0 then 1262 result := eInvalid1263 Result := eInvalid; 1263 1264 end; 1264 1265 jPoll: … … 1266 1267 JobWork := PollWork 1267 1268 else 1268 result := eInvalid;1269 Result := eInvalid; 1269 1270 jBase: 1270 1271 if RealMap[Loc] and fTerImp <> tiBase then 1271 1272 JobWork := MoveCost * BaseWork 1272 1273 else 1273 result := eInvalid;1274 Result := eInvalid; 1274 1275 jPillage: 1275 1276 if RealMap[Loc] and (fRoad or fRR or fCanal or fTerImp) <> 0 then 1276 1277 JobWork := PillageWork 1277 1278 else 1278 result := eInvalid;1279 end; 1280 end; // CalculateJobWork1281 1282 function StartJob( p, uix, NewJob: integer; TestOnly: boolean): integer;1283 var 1284 JobWork, Loc0, p1, uix1, TerrType: integer;1285 begin 1286 {$IFOPT O-} assert(1 shl pand InvalidTreatyMap = 0); {$ENDIF}1287 result := eOK;1288 with RW[ p].Un[uix] do1279 Result := eInvalid; 1280 end; 1281 end; 1282 1283 function StartJob(P, uix, NewJob: Integer; TestOnly: Boolean): Integer; 1284 var 1285 JobWork, Loc0, p1, uix1, TerrType: Integer; 1286 begin 1287 {$IFOPT O-}Assert(1 shl P and InvalidTreatyMap = 0); {$ENDIF} 1288 Result := eOK; 1289 with RW[P].Un[uix] do 1289 1290 begin 1290 1291 if NewJob = Job then 1291 1292 begin 1292 result := eNotChanged;1293 exit1293 Result := eNotChanged; 1294 Exit; 1294 1295 end; 1295 1296 if NewJob = jNone then … … 1297 1298 if not TestOnly then 1298 1299 Job := jNone; 1299 exit1300 Exit; 1300 1301 end; 1301 1302 Loc0 := Loc; … … 1303 1304 (NewJob <> jRR) then 1304 1305 begin 1305 result := eDeadLands;1306 exit1306 Result := eDeadLands; 1307 Exit; 1307 1308 end; 1308 1309 TerrType := RealMap[Loc0] and fTerrain; 1309 1310 if (RealMap[Loc0] and fCity <> 0) or (TerrType < fGrass) or (Master >= 0) or 1310 not((NewJob = jPillage) and (RW[ p].Model[mix].Domain = dGround) or1311 (RW[ p].Model[mix].Kind = mkSettler) or (NewJob <> jCity) and1312 (RW[ p].Model[mix].Kind = mkSlaves) and (GWonder[woPyramids].EffectiveOwner1311 not((NewJob = jPillage) and (RW[P].Model[mix].Domain = dGround) or 1312 (RW[P].Model[mix].Kind = mkSettler) or (NewJob <> jCity) and 1313 (RW[P].Model[mix].Kind = mkSlaves) and (GWonder[woPyramids].EffectiveOwner 1313 1314 >= 0)) then 1314 1315 begin 1315 result := eInvalid;1316 exit1316 Result := eInvalid; 1317 Exit; 1317 1318 end; 1318 1319 if (JobPreq[NewJob] <> preNone) and 1319 (RW[ p].Tech[JobPreq[NewJob]] < tsApplicable) then1320 begin 1321 result := eNoPreq;1322 exit1323 end; 1324 1325 result := CalculateJobWork(p, Loc0, NewJob, JobWork);1326 if (Mode = moPlaying) and ( result = eOK) and (NewJob <> jPoll) then1320 (RW[P].Tech[JobPreq[NewJob]] < tsApplicable) then 1321 begin 1322 Result := eNoPreq; 1323 Exit; 1324 end; 1325 1326 Result := CalculateJobWork(P, Loc0, NewJob, JobWork); 1327 if (Mode = moPlaying) and (Result = eOK) and (NewJob <> jPoll) then 1327 1328 begin // not allowed in territory of friendly nation 1328 1329 p1 := RealMap[Loc0] shr 27; // owner of territory 1329 if (p1 < nPl) and (p1 <> p) and (RW[p].Treaty[p1] >= trPeace) then1330 result := eTreaty; // keep peace treaty!1331 end; 1332 if TestOnly or ( result < rExecuted) then1333 exit;1330 if (p1 < nPl) and (p1 <> P) and (RW[P].Treaty[p1] >= trPeace) then 1331 Result := eTreaty; // keep peace treaty! 1332 end; 1333 if TestOnly or (Result < rExecuted) then 1334 Exit; 1334 1335 1335 1336 if (ToWork[Loc0, NewJob] = 0) or (ToWork[Loc0, NewJob] > JobWork) then … … 1337 1338 Job := NewJob; 1338 1339 Flags := Flags and not unFortified; 1339 for uix1 := 0 to RW[ p].nUn - 1 do1340 if (RW[ p].Un[uix1].Loc = Loc) and1341 (RW[ p].Un[uix1].Job in ContraJobs[NewJob]) then1342 RW[ p].Un[uix1].Job := jNone; // stop contradictive jobs1343 if ServerVersion[ p] < $000EF0 then1344 if Work( p, uix) then1345 result := eJobDone;1346 if (NewJob = jCity) and ( result = eJobDone) then1347 begin 1348 RemoveUnit_UpdateMap( p, uix);1349 result := eCity1340 for uix1 := 0 to RW[P].nUn - 1 do 1341 if (RW[P].Un[uix1].Loc = Loc) and 1342 (RW[P].Un[uix1].Job in ContraJobs[NewJob]) then 1343 RW[P].Un[uix1].Job := jNone; // stop contradictive jobs 1344 if ServerVersion[P] < $000EF0 then 1345 if Work(P, uix) then 1346 Result := eJobDone; 1347 if (NewJob = jCity) and (Result = eJobDone) then 1348 begin 1349 RemoveUnit_UpdateMap(P, uix); 1350 Result := eCity; 1350 1351 end 1351 1352 else if Health <= 0 then 1352 1353 begin // victim of HostileDamage 1353 RemoveUnit_UpdateMap( p, uix);1354 result := result or rUnitRemoved;1354 RemoveUnit_UpdateMap(P, uix); 1355 Result := Result or rUnitRemoved; 1355 1356 end; 1356 1357 if Mode > moLoading_Fast then 1357 1358 begin 1358 if result = eCity then1359 begin 1360 ObserveLevel[Loc0] := ObserveLevel[Loc0] and not(3 shl (2 * p));1361 Discover21(Loc0, p, lObserveUnhidden, true, true);1359 if Result = eCity then 1360 begin 1361 ObserveLevel[Loc0] := ObserveLevel[Loc0] and not(3 shl (2 * P)); 1362 Discover21(Loc0, P, lObserveUnhidden, True, True); 1362 1363 // CheckContact; 1363 end 1364 end 1365 end; // with1366 end; // StartJob1367 1368 function Work( p, uix: integer): boolean;1369 var 1370 uix1, j0: integer;1371 begin 1372 result := false;1373 with RW[ p].Un[uix] do1364 end; 1365 end; 1366 end; 1367 end; 1368 1369 function Work(P, uix: Integer): Boolean; 1370 var 1371 uix1, j0: Integer; 1372 begin 1373 Result := False; 1374 with RW[P].Un[uix] do 1374 1375 if Movement >= 100 then 1375 1376 begin 1376 assert(ToWork[Loc, Job] < $FFFF); // should have been set by StartJob1377 Assert(ToWork[Loc, Job] < $FFFF); // should have been set by StartJob 1377 1378 if Job >= jRoad then 1378 if integer(Movement) >= integer(ToWork[Loc, Job]) then { work complete }1379 begin 1380 result := true;1379 if Integer(Movement) >= Integer(ToWork[Loc, Job]) then { work complete } 1380 begin 1381 Result := True; 1381 1382 if Job <> jIrr then 1382 Health := Health - HostileDamage( p, mix, Loc, ToWork[Loc, Job]);1383 dec(Movement, ToWork[Loc, Job]);1383 Health := Health - HostileDamage(P, mix, Loc, ToWork[Loc, Job]); 1384 Dec(Movement, ToWork[Loc, Job]); 1384 1385 if not(Job in [jCity, jPillage, jPoll]) then 1385 inc(Worked[p], ToWork[Loc, Job]);1386 Inc(Worked[P], ToWork[Loc, Job]); 1386 1387 if Job = jCity then 1387 1388 begin // found new city 1388 FoundCity( p, Loc);1389 inc(Founded[p]);1390 with RW[ p].City[RW[p].nCity - 1] do1389 FoundCity(P, Loc); 1390 Inc(Founded[P]); 1391 with RW[P].City[RW[P].nCity - 1] do 1391 1392 begin 1392 ID := p shl 12 + Founded[p] - 1;1393 ID := P shl 12 + Founded[P] - 1; 1393 1394 Flags := chFounded; 1394 1395 end; 1395 1396 if Mode = moPlaying then 1396 1397 begin 1397 LogCheckBorders( p, RW[p].nCity - 1);1398 RecalcPeaceMap( p);1398 LogCheckBorders(P, RW[P].nCity - 1); 1399 RecalcPeaceMap(P); 1399 1400 end; 1400 1401 {$IFOPT O-} if Mode < moPlaying then 1401 InvalidTreatyMap := not(1 shl p); {$ENDIF}1402 InvalidTreatyMap := not(1 shl P); {$ENDIF} 1402 1403 // territory should not be considered for the rest of the command 1403 1404 // execution, because during loading a game it's incorrect before 1404 1405 // subsequent sIntExpandTerritory is processed 1405 RW[ p].Un[uix].Health := 0; // causes unit to be removed later1406 RW[P].Un[uix].Health := 0; // causes unit to be removed later 1406 1407 end 1407 1408 else 1408 CompleteJob( p, Loc, Job);1409 CompleteJob(P, Loc, Job); 1409 1410 ToWork[Loc, Job] := 0; 1410 1411 j0 := Job; 1411 for uix1 := 0 to RW[ p].nUn - 1 do1412 if (RW[ p].Un[uix1].Loc = Loc) and (RW[p].Un[uix1].Job = j0) then1413 RW[ p].Un[uix1].Job := jNone1412 for uix1 := 0 to RW[P].nUn - 1 do 1413 if (RW[P].Un[uix1].Loc = Loc) and (RW[P].Un[uix1].Job = j0) then 1414 RW[P].Un[uix1].Job := jNone 1414 1415 end 1415 1416 else 1416 1417 begin 1417 dec(ToWork[Loc, Job], Movement);1418 Dec(ToWork[Loc, Job], Movement); 1418 1419 if not(Job in [jCity, jPillage, jPoll]) then 1419 inc(Worked[p], Movement);1420 Health := Health - HostileDamage( p, mix, Loc, Movement);1420 Inc(Worked[P], Movement); 1421 Health := Health - HostileDamage(P, mix, Loc, Movement); 1421 1422 Movement := 0; 1422 1423 end 1423 1424 end 1424 end; // work1425 1426 function GetJobProgress( p, Loc: integer;1427 var JobProgressData: TJobProgressData): integer;1428 var 1429 Job, JobResult, uix: integer;1425 end; 1426 1427 function GetJobProgress(P, Loc: Integer; 1428 var JobProgressData: TJobProgressData): Integer; 1429 var 1430 Job, JobResult, uix: Integer; 1430 1431 begin 1431 1432 for Job := 0 to nJob - 1 do 1432 1433 begin 1433 JobResult := CalculateJobWork( p, Loc, Job, JobProgressData[Job].Required);1434 JobResult := CalculateJobWork(P, Loc, Job, JobProgressData[Job].Required); 1434 1435 if JobResult = eOK then 1435 1436 begin … … 1438 1439 else 1439 1440 JobProgressData[Job].Done := JobProgressData[Job].Required - 1440 ToWork[Loc, Job] 1441 ToWork[Loc, Job]; 1441 1442 end 1442 1443 else … … 1447 1448 JobProgressData[Job].NextTurnPlus := 0; 1448 1449 end; 1449 for uix := 0 to RW[ p].nUn - 1 do1450 if (RW[ p].Un[uix].Loc = Loc) and (RW[p].Un[uix].Movement >= 100) then1451 inc(JobProgressData[RW[p].Un[uix].Job].NextTurnPlus,1452 RW[ p].Un[uix].Movement);1453 result := eOK;1450 for uix := 0 to RW[P].nUn - 1 do 1451 if (RW[P].Un[uix].Loc = Loc) and (RW[P].Un[uix].Movement >= 100) then 1452 Inc(JobProgressData[RW[P].Un[uix].Job].NextTurnPlus, 1453 RW[P].Un[uix].Movement); 1454 Result := eOK; 1454 1455 end; 1455 1456
Note:
See TracChangeset
for help on using the changeset viewer.