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
Code: Select all
:00451911 9090909090 nop