Ground Combat Calculation (success chance of invasion)

Ground Combat Calculation (success chance of invasion); support/discussion/questions

Moderator: thunderchero

Post Reply
User avatar
Gowron
Code Master
Code Master
Posts: 304
Joined: Sat Apr 26, 2008 2:00 am
Location: 50° N, 11° E

Ground Combat Calculation (success chance of invasion)

Post by Gowron » Sun Aug 01, 2010 12:02 pm

Here's how the game determines the success chance for invasion attempts:

(1) Calculate the combined ground combat strengths of the attacking task force and multiply by the race-specific ground combat factor. Square the result.
(2) Multiply the result of (1) by the empire-wide bonus factor of the attacking empire.
(3) Calculate the ground defense value of the defending star system, including all bonuses. Square the result.
(4) Add the results of (2) and (3).
(5) Divide the result of (2) by the result of (4).

The result of (5) is then compared to a randomly generated value between 0 and 1. This comparison decides if the invasion succeeds.

So the success probability depends on the ratio of the squares of the ground combat values (of attackers and defenders), with the squared ground combat strength of the attackers being multiplied by their empire-wide bonus factor (if present).
It is a little bit odd that the empire-wide bonus of the attackers is included in the calculation although it does not affect the (displayed) ground combat values of troop transports.


--------------------------------------------------
link to ground combat strength explanation:
viewtopic.php?name=Forums&file=viewtopic&t=56

link to ground combat tech level multiplier topic:
viewtopic.php?name=Forums&file=viewtopic&t=67
--------------------------------------------------


The corresponding assembler code is part of subroutine 466CF0. Although that subroutine is quite huge, I think I've identified most of the relevant code sections for ground combat calculation.

Surprisingly there does not seem to be a loop over the attacking task forces (if more than one task force attacks). It seems that they are processed one by one.

Although it's quite obvious that var_10C contains the race-specific ground combat factor for the attacking task force, I've still added question marks for this variable because it does not seem to be assigned within subroutine 466CF0.

Code: Select all

AUTO:0046706E                 mov     eax, [esp+420h+var_20] ; data offset for attacking task force
AUTO:00467075                 xor     ecx, ecx
AUTO:00467077                 mov     ebx, [eax+4]    ; ship count of attacking task force
AUTO:0046707A                 mov     [esp+420h+var_18], ecx ; 0
AUTO:00467081                 test    ebx, ebx
AUTO:00467083                 jle     short loc_4670EB ; jump if attacking task force is empty
AUTO:00467085                 mov     ebx, eax        ; data offset for attacking task force
AUTO:00467087

AUTO:00467087                 mov     eax, [ebx+6]    ; start of loop over ships in attacking task force
AUTO:0046708A                 sar     eax, 10h        ; ship ID
AUTO:0046708D                 call    sub_44A690      ; get data offset for current ship
AUTO:00467092                 mov     dl, [eax+58h]
AUTO:00467095                 and     dl, 0FEh
AUTO:00467098                 mov     esi, [eax+70h]  ; base ground combat strength (= production value if TT) of current ship
AUTO:0046709B                 mov     [eax+58h], dl
AUTO:0046709E                 test    esi, esi
AUTO:004670A0                 jbe     loc_467449      ; jump if base ground combat strength is zero (not a TT)
AUTO:004670A6                 xor     ecx, ecx
AUTO:004670A8                 mov     dword ptr [esp+420h+var_B0], esi ; base ground combat strength of current ship
AUTO:004670AF                 mov     dword ptr [esp+420h+var_B0+4], ecx ; 0
AUTO:004670B6                 fild    [esp+420h+var_B0] ; base ground combat strength of current ship
AUTO:004670BD                 fadd    [esp+420h+var_100] ; add to base ground combat strength of task force
AUTO:004670C4                 fstp    [esp+420h+var_100] ; combined base ground combat strength of task force

AUTO:004670CB                 mov     esi, [esp+420h+var_18] ; loop counter
AUTO:004670D2                 mov     edx, [esp+420h+var_20] ; data offset for attacking task force
AUTO:004670D9                 add     ebx, 4          ; increase data offset to get next ship
AUTO:004670DC                 inc     esi             ; loop counter
AUTO:004670DD                 mov     edi, [edx+4]    ; ship count of attacking task force
AUTO:004670E0                 mov     [esp+420h+var_18], esi ; loop counter
AUTO:004670E7                 cmp     esi, edi
AUTO:004670E9                 jl      short loc_467087 ; loop over ships of attacking task force

-------------

AUTO:00467562                 mov     edx, [esp+420h+var_28] ; data offset for defending system
AUTO:00467569                 xor     ah, ah
AUTO:0046756B                 mov     al, [edx+4Ch]   ; empire which controls defending system
AUTO:0046756E                 jmp     loc_467289

-------------

AUTO:00467270                 mov     eax, [esp+420h+var_28] ; ID of defending system
AUTO:00467277                 mov     dh, [eax+4Ch]   ; owner of defending system
AUTO:0046727A                 xor     ebx, ebx
AUTO:0046727C                 cmp     dh, 5           ; check if defending system belongs to a major empire
AUTO:0046727F                 jb      loc_467562      ; use controlling race instead of inhabitant race if system belongs to an empire
AUTO:00467285                 mov     ax, [eax+44h]   ; inhabitant race of defending system

AUTO:00467289                 mov     word ptr [esp+420h+var_8], ax ; defending race ID (empire resp. inhabitants)
AUTO:00467291                 mov     eax, [esp+420h+var_20] ; data offset for attacking task force
AUTO:00467298                 mov     cx, [eax+34h]   ; race ID of attacking task force
AUTO:0046729C                 cmp     cx, 5
AUTO:004672A0                 jnb     short loc_4672D4 ; jump if not a major empire
AUTO:004672A2                 xor     edx, edx
AUTO:004672A4                 mov     dx, cx
AUTO:004672A7                 lea     eax, ds:0[edx*8]
AUTO:004672AE                 add     eax, edx
AUTO:004672B0                 shl     eax, 2
AUTO:004672B3                 add     eax, edx
AUTO:004672B5                 shl     eax, 2
AUTO:004672B8                 mov     edx, eax
AUTO:004672BA                 shl     eax, 2
AUTO:004672BD                 sub     eax, edx        ; eax = 444 * (ID of attacking empire)
AUTO:004672BF                 add     eax, offset st_empsInfo ; data offset for attacking empire
AUTO:004672C4                 lea     ebx, [eax+0F6h]
AUTO:004672CA                 mov     bx, [ebx+18h]   ; empire-wide ground combat bonus factor in percent
AUTO:004672CE                 and     ebx, 0FFFFh

AUTO:004672D4                 mov     eax, [esp+420h+var_20] ; data offset for attacking task force
AUTO:004672DB                 xor     ecx, ecx
AUTO:004672DD                 mov     ax, [eax+34h]   ; race ID of attacking task force
AUTO:004672E1                 mov     cx, ax          ; race ID of attacking task force
AUTO:004672E4                 lea     esi, [esp+420h+var_174]
AUTO:004672EB                 mov     eax, ecx        ; race ID of attacking task force
AUTO:004672ED                 mov     edx, 5          ; tech area "weapons"
AUTO:004672F2                 call    sub_4AED50
AUTO:004672F7                 mov     eax, ecx        ; race ID of attacking task force
AUTO:004672F9                 call    GetTechLevel    ; write weapon tech level of attackers to eax
AUTO:004672FE                 mov     [esp+420h+var_10], eax ; weapon tech level of attackers
AUTO:00467305                 fild    [esp+420h+var_10] ; weapon tech level of attackers
AUTO:0046730C                 fmul    ds:GrndCmbTechMul2 ; 0.1 (tech level bonus factor for attackers)
AUTO:00467312                 fld1
AUTO:00467314                 faddp   st(1), st       ; tech bonus = 1 + factor * (weapon tech level)
AUTO:00467316                 fmul    [esp+420h+var_10C] ; multiply by race-specific combat factor for attackers?
AUTO:0046731D                 fmul    [esp+420h+var_100] ; multiply by combined base ground combat strength of attacking task force
AUTO:00467324                 add     ebx, 64h        ; add 100 to empire-wide combat bonus
AUTO:00467327                 fst     [esp+420h+var_100] ; store result of multiplication
AUTO:0046732E                 fmul    [esp+420h+var_100] ; square the above result
AUTO:00467335                 mov     [esp+420h+var_10], ebx ; 100 * (ground combat factor from empire-wide bonus) for attackers
AUTO:0046733C                 fstp    [esp+420h+var_100]
AUTO:00467343                 fild    [esp+420h+var_10]
AUTO:0046734A                 fmul    [esp+420h+var_100] ; apply empire-wide ground combat factor (not squared)
AUTO:00467351                 mov     eax, [esp+420h+var_28] ; ID of defending system
AUTO:00467358                 fmul    ds:dbl_57AC6C   ; 0.01
AUTO:0046735E                 movsx   eax, word ptr [eax] ; ID of defending system
AUTO:00467361                 fstp    [esp+420h+var_100]
AUTO:00467368                 call    GrndDefStrength ; get ground defense strength of defending system
AUTO:0046736D                 mov     [esp+420h+var_10], eax ; ground defense strength of defending system
AUTO:00467374                 fild    [esp+420h+var_10] ; ground defense strength of defending system
AUTO:0046737B                 fmul    st, st          ; square ground defense strength of defending system
AUTO:0046737D                 fadd    [esp+420h+var_100] ; calculate...
AUTO:00467384                 fdivr   [esp+420h+var_100] ; ... success chance of invasion
AUTO:0046738B                 mov     edx, 1041h
AUTO:00467390                 mov     eax, offset a____SourceG_14 ; "..\\..\\source\\game\\military\\military.c"
AUTO:00467395                 fstp    [esp+420h+var_60] ; success chance of invasion
AUTO:0046739C                 call    random2         ; loads a random value between 0 and 1 into the FPU
AUTO:004673A1                 fld     [esp+420h+var_60] ; success chance of invasion
AUTO:004673A8                 fstp    [esp+420h+var_C0] ; success chance of invasion
AUTO:004673AF                 fcomp   [esp+420h+var_C0] ; check if invasion is successful (compare random value to success chance)
AUTO:004673B6                 fnstsw  ax
AUTO:004673B8                 sahf
AUTO:004673B9                 jnb     loc_467573      ; jump if invasion is not successful
A discovery consists in seeing something everybody has seen and at the same time thinking something nobody has thought yet.

User avatar
Peter1981
Rear-Admiral
Rear-Admiral
Posts: 1118
Joined: Tue May 06, 2008 2:00 am
Location: England

Post by Peter1981 » Sun Aug 15, 2010 6:09 am

this code suggest that if a non-tt ship is given a production value or a colony ship attacks a planet in a task-force with a tt then the ground combat values (production values) are all used?

So there would be a use for giving all ships a production value?

I the above questions are rigth then this is an amazing find -- ALL HAIL THE EMPEROR!!

User avatar
Spocks-cuddly-tribble
Code Master
Code Master
Posts: 723
Joined: Sun Apr 27, 2008 2:00 am

Post by Spocks-cuddly-tribble » Sun Nov 28, 2010 7:02 am

Gowron wrote:It is a little bit odd that the empire-wide bonus of the attackers is included in the calculation although it does not affect the (displayed) ground combat values of troop transports.
Well, so at least this statement isn't untruth:
BotF Patch Version 1.0.1 Changes wrote:Ground combat bonuses from structures such as the Angosian Super Soldier Academy are now applied to troop transports and ground forces.
But the code disproves a random bonus for attackers when freeing systems as false evidence by the game manual.:(

However, probability calculation doesn't need any tweak IMO.

So for example (barring the the display omision / not squared attacker disadvantage w.r.t. the global building bonus):

~ 80% success probability for superior number 2:1

~ 20% if outnumbered 2:1

Gowron wrote:Surprisingly there does not seem to be a loop over the attacking task forces (if more than one task force attacks). It seems that they are processed one by one.
The lack of global task force handling is an overall issue in BotF.

I remember simultaneous conquests (i.e. message "invasion successful" & "system conquered /lost" afterwards). I'd be funny to see what happens if BotF sorts many taskforces in alternating series. Should result in a lot of messages (and a very shell-shocked population, of course ^^).

Gowron wrote:Although it's quite obvious that var_10C contains the race-specific ground combat factor for the attacking task force, I've still added question marks for this variable because it does not seem to be assigned within subroutine 466CF0.
4672F2 call sub_4AED50 (write race.rst entry for race Id (eax) to [esi])

Since esi =[esp+2ACh] +68h(ground combat position race.rst) =[esp+314h] (var_10C) = race ground combat value

Peter1981 wrote:this code suggest that if a non-tt ship is given a production value or a colony ship attacks a planet in a task-force with a tt then the ground combat values (production values) are all used?
No, 'base ground combat strength (= production value if TT)' is just an unfortunate choice of words. TT production value /10 (unmodded) is stored at [GShipList+70h] as ground combat value - only for TT's (see 2nd link above). The production value itself is only used for construction of stations (also only TT - this time due to trek.exe check).
On the verge of a nervous breakdown? Try the relaxing tribble sounds.

User avatar
Spocks-cuddly-tribble
Code Master
Code Master
Posts: 723
Joined: Sun Apr 27, 2008 2:00 am

Post by Spocks-cuddly-tribble » Sat Feb 26, 2011 5:27 am

In response to a very interesting suggestion by Callahan (see below), I continued the code analysis by Gowron. Additionally, I added a tweak option for the ground combat strength of AI troop transports. :)




:arrow: Number of lost Troop Transports (limited by the number of attacking TTs of course)


Nominal loss by success = [ecx * failing chance] + 0.5 (rounded down)

ecx = 1 +[1 for each iteration of loop: failing chance vs. random value between 0 and 1]

Minimum loss = 1 TT (at 0x669D0 & 0x669D8)

Nominal loss when invasion fails = up to 1000 TTs (at 0x669FC)

Code: Select all

4673BF                 fld1   // load 1 into FPU
4673C1                 fsub    qword ptr [esp+360h] // 1 - success chance of invasion
4673C8                 xor     esi, esi          // esi = 0  (=invasion successful)
4673CA                 fstp    qword ptr [esp+398h] // store reversed success (i.e. failing) chance

4673D1                 mov     ecx, 1

4673E4                 call    507E50 // load random value between 0 and 1 into FPU
4673E9                 fcomp   qword ptr [esp+398h] // compare random value to failing chance
4673F0                 fnstsw  ax
4673F2                 sahf
4673F3                 jnb     467599 // exit loop if failing chance is lower
4673F9                 inc     ecx       // ecx + 1
4673FA                 jmp     short loc_4673E0 // iterate random loop

467599                 mov     [esp+410h], ecx  // result of above loop
4675A0                 fild    dword ptr [esp+410h] // load in FPU
4675A7                 fmul    qword ptr [esp+398h] // ecx * failing chance
4675AE                 fst     qword ptr [esp+398h]
4675B5                 fadd    ds:57AC74 (0.5 shared vulue)  // (ecx * failing chance) + 0.5
4675BB                 call    51D6D4   // round down
4675C0                 fistp   dword ptr [esp+3C8h] // store result as integer
4675C7                 mov     edi, [esp+3C8h] // number of lost TTs when invasion successful
4675CE                 cmp     edi, 1 // minimum number of lost TTs when invasion successful
4675D1                 jge     467A58
4675D7                 mov     edx, 1 // minimum number of lost TTs when invasion successful

4675F7                 test    esi, esi // if invasion successful...
4675F9                 jz      short 467600 // ...skip next
4675FB                 mov     edx, 3E8h // number of lost TTs when invasion fails
Result and calculation of ecx is shared for various purposes, so modding this part probably won't be very practical.

However, we can skip this part:

[ecx * failing chance] + 0.5 (rounded down)

Code: Select all

trek exe at 0x669C7
8B BC 24 C8 03 00 00 -> 8B F9 90 90 90 90 90

4675C7                 mov     edi, ecx // number of lost TTs
This increases the (by default too low) chance to lose additional TTs by success. :)


Callahan wrote:Use up all involved transports on invasion.
I do not like the current way of being overrun by the enemy as he only has to build 1 new TRN after capturing even a strong system.
Using em up all would make it more difficult to decide on how many to be used, and would slow down any war as one will have to build more TRNs in order to proceed.
Minimum loss of TTs by success is at 0x669D0 & 0x669D8. The first value is a 1 byte signed, but 0x64 at both locations should do fine.

This, indeed, could make the game more pretentious and also redress some bizarre strategies from low tech games (i.e. build tons of TTs, conquer a superior system, scrap TTs & from money build warships to destroy the next enemy's fleet or bribe the next minor).





:arrow: Modifying the AI's offensive ground combat strength


Due to the AI's inefficient system attack assessment (apparently sub_479AD0), it tends to bring too less TTs, resulting in a fatal waste of resources. In later stages of game, this oftentimes leads to destroyed instead of conquered systems, in earlier stages to crippled AI fleets due to the repeated failures.

As a workaround we can enhance the base ground combat strength of AI TTs. This of course works not only against minor and player systems, but also against other AI majors (so the dominat AI retains more of its resources). :)

The following code example gives the AI a bonus of 50% per difficulty level above 'simple'.

Code: Select all

Trek.exe at 0x49C35 
replace: (74  bytes)
31 D2 8A 94 24 2A 01 00 00 8D 04 95 00 00 00 00 29 D0 C1 E0 03 01 D0 01 C0 31 D2 89 41 6C 66 8B 94 24 16 01 00 00 BB 0A 00 00 00 89 D0 C1 FA 1F F7 FB 89 41 70 81 C4 3C 01 00 00 59 5B C3 00 00 00 00 00 00 00 00 00 00 00 00
with:
8A 9C 24 2A 01 00 00 6B DB 32 89 59 6C 0F B7 94 24 16 01 00 00 8B D9 8A 49 28 B5 01 D2 E5 84 2D 28 2B 5A 00 75 0D A0 44 2B 5A 00 04 01 0F AF D0 C1 EA 01 33 C9 B1 0A 8B C2 C1 FA 1F F7 F9 89 43 70 81 C4 3C 01 00 00 59 5B C3


44A835     8A9C24 2A010000     MOV BL, [ESP+12A] // construction tech from shiptech.sst
44A83C     6BDB 32             IMUL EBX, EBX, 32 // *50
44A83F     8959 6C             MOV [ECX+6C], EBX // store in GShipList
44A842     0FB79424 16010000   MOVZX EDX, WORD [ESP+116] // TT production value from shiplist.sst
44A84A     8BD9                MOV EBX, ECX // GShipList entry
0044A84C     8A49 28             MOV CL, [ECX+28] // race ID
44A84F     B5 01               MOV CH, 1
44A851     D2E5                SHL CH, CL
44A853     842D 282B5A00       TEST [5A2B28], CH // if not AI...
44A859     75 0D               JNZ SHORT 44A868  // ...skip AI bonus
44A85B     A0 442B5A00         MOV AL, [5A2B44] // difficulty level
44A860     04 01               ADD AL, 1        // difficulty level + 1  -> factor A
44A862     0FAFD0              IMUL EDX, EAX // production value * (difficulty level +A)
44A865     C1EA 01             SHR EDX, 1  // divide by 2^1  -> factor B
44A868     33C9                XOR ECX, ECX
44A86A     B1 0A               MOV CL, 0A // default ground combat divisor 10
44A86C     8BC2                MOV EAX, EDX
44A86E     C1FA 1F             SAR EDX, 1F
44A871     F7F9                IDIV ECX
44A873     8943 70             MOV [EBX+70], EAX // store TT ground combat value in GShipList
44A876     81C4 3C010000       ADD ESP, 13C
44A87C     59                  POP ECX
44A87D     5B                  POP EBX
44A87E     C3                  RETN
Thanks to an inspiration from Peter1981 the bonus can be adapted according to:

[ground combat strength] * [difficulty level +A] / 2^B

Factor A at 0x49C61 (default 1)
Factor B at 0x49C67 (default 1)

Hence for the factors A / B the bonuses per difficulty level above 'simple' are:

0/0 = +100%
1/1 = +50%
3/2 = +25%
7/3 = +12.5%

This is performed before the default integer division, so the AI gets a bit more than expected.

Note: Since the ground combat value of TTs is stored at [GShipList+70h] i.e. the savegame, this modification won't work for present TTs if applied afterwards, and also the AI bonus will be not removed from existing TTs when switching player race via savegame editing (see changing AI controling race of a savegame)!
On the verge of a nervous breakdown? Try the relaxing tribble sounds.

User avatar
EnPhreg
Lieutenant-Commander
Lieutenant-Commander
Posts: 130
Joined: Thu Jul 10, 2008 2:00 am

Re: Ground Combat Calculation (success chance of invasion)

Post by EnPhreg » Fri Aug 12, 2016 9:09 am

However, we can skip this part:

[ecx * failing chance] + 0.5 (rounded down)

Code: Select all
trek exe at 0x669C7
8B BC 24 C8 03 00 00 -> 8B F9 90 90 90 90 90

4675C7 mov edi, ecx // number of lost TTs

This increases the (by default too low) chance to lose additional TTs by success. :)
installed the above code, but can't watch any additional loss of transports. made several attacks with different configurations on different planets.
what's the chance for loosing an additional transport in % ? it's possible to increase this value?

User avatar
thunderchero
Site Administrator aka Fleet Admiral
Site  Administrator aka Fleet Admiral
Posts: 6058
Joined: Fri Apr 25, 2008 2:00 am
Location: On a three month training mission, in command of the USS Valiant.
Contact:

Re: Ground Combat Calculation (success chance of invasion)

Post by thunderchero » Fri Aug 12, 2016 9:44 am

EnPhreg wrote:it's possible to increase this value?
what value? if you want to change the 0.5 of this statement [ecx * failing chance] + 0.5 (rounded down)

it is a shared value at 57AC74 or 0x178a74 - 00 00 00 00 00 00 E0 3F
but SCT warns this is a shared value and I am not sure what else shares this value.
EnPhreg wrote:what's the chance for loosing an additional transport in % ?
it would depend on many other variables. and don't think it has a single editable value.

Post Reply

Return to “Ground Combat Calculation (success chance of invasion)”

Who is online

Users browsing this forum: No registered users