Terraforming Fix for Additional Starting Systems and Minors

Terraforming Fix for Additional Starting Systems and Minors; 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

Terraforming Fix for Additional Starting Systems and Minors

Post by Gowron »

Finally :)

Additional starting systems of major empires can often contain un-terraformed planets, and sometimes this results in really bad (and unfair) starting systems. Up to now there was no way to bypass this problem other than using class M planets exclusively. But this will change now :)

Subroutine 4518F0 is responsible for freeing up enough population space in a newly generated additional starting system. At a first glance, it seems to do what it should: if there's not enough pop space, then a loop is entered, and planet after planet is terraformed until the pop space requirement is met or until the loop has been entered as many times as there are planets in the star system.

But the problem is that the planets are not tested one by one. Instead, each time the loop is entered, a random planet is chosen. Of course this can always be the same planet, so the star system may even end up with only one habitable planet!
I don't know if this is was a programming mistake by the makers of BotF or an attempt to be extraordinarily inventive, but either way I think we're just going to fix it ;)

This is the original subroutine (it is also used for minor races each time they grow):

Code: Select all

=========
:004518F0 53                      push ebx
:004518F1 51                      push ecx
:004518F2 52                      push edx
:004518F3 56                      push esi
:004518F4 57                      push edi
:004518F5 89C7                    mov edi, eax                      // system ID
:004518F7 69C028030000            imul eax, 00000328                // multiply by size of a system entry
:004518FD 8B0DC8365A00            mov ecx, dword[005A36C8]          // base offset of star system entry array
:00451903 31DB                    xor ebx, ebx
:00451905 01C1                    add ecx, eax                      // get base offset of specified star system entry
---------
:00451907 0FBFD7                  movsx edx, di                     // system ID
:0045190A 89D0                    mov eax, edx                      // system ID
:0045190C E85F21FFFF              call 00443A70                     // write current system population capacity to eax
:00451911 3B4140                  cmp eax, dword[ecx+40]            // compare it to the initial population number
:00451914 733F                    jae 00451955                      // jump if there is enough pop space
:00451916 31F6                    xor esi, esi
:00451918 668B716A                mov si, word[ecx+6A]              // number of planets
:0045191C 39F3                    cmp ebx, esi
:0045191E 742B                    je 0045194B                       // exit loop
:00451920 BA81000000              mov edx, 00000081
:00451925 B860935700              mov eax, 00579360
                      (StringData)"..\..\source\game\setup\civstart.c"
:0045192A E8C1660B00              call 00507FF0                     // random integer generator
:0045192F 89C2                    mov edx, eax                      // prepare...
:00451931 C1FA1F                  sar edx, 1F                       // ... for integer division
:00451934 F7FE                    idiv esi                          // divide random integer by number of planets
:00451936 6BC24C                  imul eax, edx, 4C                 // multiply the remainder by 0x4C (size of a planet entry)
:00451939 8B91B0000000            mov edx, dword[ecx+000000B0]      // base offset of planet entry array
:0045193F 01D0                    add eax, edx                      // get base offset of (randomly) specified planet entry
:00451941 6683783A00              cmp word[eax+3A], 000             // read required terraforming amount (0 = class M or already terraformed)
:00451946 7513                    jne 0045195B                      // jump if not habitable yet
:00451948 43                      inc ebx                           // increase loop counter
:00451949 EBBC                    jmp 00451907                      // loop
---------
:0045194B 89D0                    mov eax, edx                      // system ID
:0045194D E81E21FFFF              call 00443A70                     // write current system population capacity to eax
:00451952 894140                  mov dword[ecx+40], eax            // update population number
---------
:00451955 5F                      pop edi
:00451956 5E                      pop esi
:00451957 5A                      pop edx
:00451958 59                      pop ecx
:00451959 5B                      pop ebx
:0045195A C3                      ret

---------
:0045195B 66C7403A0000            mov word[eax+3A], 0000            // terraform planet
:00451961 43                      inc ebx                           // increase loop counter
:00451962 EBA3                    jmp 00451907                      // loop

:00451964 00 00 00 00 00 00 00 00 00 00 00 00               ............

=========

This fixes the subroutine by terraforming planets one by one: :!: Improved Code Below :!:

Code: Select all

:0045192F 89D8                    mov eax, ebx                      // loop counter
:00451931 6BC04C                  imul eax, 4C                      // multiply by size of a planet entry
:00451934 9090909090              nop
Optionally, you can also make the game terraform every planet regardless of the pop requirement. In this case, apply the following change in addition to the above fix:

Code: Select all

:00451911 9090909090              nop
Be warned, this second change will make minor races grow to their maximum population at their first "growth jump".
A discovery consists in seeing something everybody has seen and at the same time thinking something nobody has thought yet.
User avatar
Tethys
Past Administrator
Past Administrator
Posts: 2403
Joined: Fri Jul 18, 2008 2:00 am
Location: Your mom's bed ;)
Contact:

Post by Tethys »

woohoo!!! this is going into GM for sure! excellent i am very well pleased!
Not for the weak of heart...
Galaxies MOD v0.4.0 <--- GALM/Galaxies Mod latest version
User avatar
ruthlessferengi
Multiple Tournament Champion
Multiple Tournament Champion
Posts: 880
Joined: Sat Apr 26, 2008 2:00 am
Location: GMT- 5

Post by ruthlessferengi »

fluids mp, vanilla with fixes and other mods will need to be updated.. great find!
Relevance is a post hoc phenomenon

На безптичье и жопа воробей...
Ancient Klingon Battlecry
User avatar
Gowron
Code Master
Code Master
Posts: 304
Joined: Sat Apr 26, 2008 2:00 am
Location: 50° N, 11° E

Post by Gowron »

This issue kept bothering me, so I decided to re-write the subroutine, replacing the loop counter by a bitmask to keep track which planets have already been terraformed. If all planets have been terraformed (or if there's enough pop space), the loop is exited.

Code: Select all

=========
:004518F0 53                      push ebx
:004518F1 51                      push ecx
:004518F2 52                      push edx
:004518F3 56                      push esi
:004518F4 57                      push edi
:004518F5 89C7                    mov edi, eax                      // system ID
:004518F7 69C028030000            imul eax, 00000328                // multiply by size of a system entry
:004518FD 8B35C8365A00            mov esi, dword[005A36C8]          // base offset of star system entry array
:00451903 31DB                    xor ebx, ebx
:00451905 01C6                    add esi, eax                      // get base offset of specified star system entry
---------
:00451907 0FBFD7                  movsx edx, di                     // system ID
:0045190A 89D0                    mov eax, edx                      // system ID
:0045190C E85F21FFFF              call 00443A70                     // write current system population capacity to eax
:00451911 3B4640                  cmp eax, dword[esi+40]            // compare it to the initial population number
:00451914 734C                    jae 00451962                      // jump if there is enough pop space
:00451916 31C9                    xor ecx, ecx
:00451918 31C0                    xor eax, eax
:0045191A 668B4E6A                mov cx, word[esi+6A]              // number of planets
:0045191E 40                      inc eax
:0045191F D3E0                    shl eax, cl
:00451921 48                      dec eax
:00451922 39C3                    cmp ebx, eax                      // check if all planets have been terraformed 
:00451924 7432                    je 00451958                       // exit loop
:00451926 BA81000000              mov edx, 00000081
:0045192B B860935700              mov eax, 00579360
                      (StringData)"..\..\source\game\setup\civstart.c"
:00451930 E8BB660B00              call 00507FF0                     // random integer generator
:00451935 89C2                    mov edx, eax                      // prepare...
:00451937 C1FA1F                  sar edx, 1F                       // ... for integer division
:0045193A F7F9                    idiv ecx                          // divide random integer by number of planets
:0045193C 31C0                    xor eax, eax
:0045193E 89D1                    mov ecx, edx                      // index of planet to terraform
:00451940 40                      inc eax
:00451941 D3E0                    shl eax, cl
:00451943 09C3                    or ebx, eax                       // update bitmask
:00451945 6BC24C                  imul eax, edx, 4C                 // multiply the remainder by 0x4C (size of a planet entry)
:00451948 8B96B0000000            mov edx, dword[esi+000000B0]      // base offset of planet entry array
:0045194E 01D0                    add eax, edx                      // get base offset of (randomly) specified planet entry
:00451950 66C7403A0000            mov word[eax+3A], 0000            // terraform planet
:00451956 EBAF                    jmp 00451907                      // loop
---------
:00451958 89D0                    mov eax, edx                      // system ID
:0045195A E81121FFFF              call 00443A70                     // write current system population capacity to eax
:0045195F 894640                  mov dword[esi+40], eax            // update population number
---------
:00451962 5F                      pop edi
:00451963 5E                      pop esi
:00451964 5A                      pop edx
:00451965 59                      pop ecx
:00451966 5B                      pop ebx
:00451967 C3                      ret
Uncommented version for copy&paste (start in trek.exe at 0x50CF0, length 0x78 bytes):

Code: Select all

535152565789C769C0280300008B35C8365A0031DB01C60FBFD789D0E85F21FFFF3B4640734C31C931C0668B4E6A40D3E04839C37432BA81000000
B860935700E8BB660B0089C2C1FA1FF7F931C089D140D3E009C36BC24C8B96B000000001D066C7403A0000EBAF89D0E81121FFFF8946405F5E5A595BC3
A discovery consists in seeing something everybody has seen and at the same time thinking something nobody has thought yet.
Post Reply

Return to “Terraforming Fix for Additional Starting Systems and Minors”