Thank you all for the accolades.
I do wonder how you managed to fix the Phantom Resource Bug
Ah right, I explained the other bugs and their fixes but overlooked this one. The phantom resource bug fix is unlike the others since the "bug" is not exactly a bug but more like a limitation in the game's programming. Hence the fix is more like implementing a new feature than doing a surgical change to the code, for example the submarine bug required weeks of analysis but in the end the fix only flips a single critical bit.
First an explanation of the bug: The way the game was originally programmed, each city has a 32-bit integer, treated as a set of 32 bits, that's used to record resource access info for when the city is not connected to the main trade network (the one that includes the capital). For an unconnected city, the first bit gets set to 1 to indicate that that city has access to the game's first resource, the second bit gets set to indicate access to the second, and so on. If a game has more than 32 resources the count "wraps around" and the bits are shared, so access to the 33rd resource is also recorded in the first bit, the 34th resource in the second bit, etc. That sharing of bits is what causes the phantom resource bug, as unconnected cities are marked as having access to resources that they shouldn't have.
With all that in mind, the fix is conceptually simple. It removes the limitation by creating extra space to store resource access info. The hard part is modifying the code to use the additional space. The reason I was able to remove this limitation, unlike the city limit or 31 civ limit, is that the game code only operates on those sets of 32 bits in two places (actually there are a couple more places but they're not important, see note below). So there are only two places where I needed to alter the code, one where the bits are checked and another where they are set.
The bits are checked in City::has_resource (GOG address 0x4B4E10), the function that the game logic uses to ask if a city has access to a particular resource. That function I simply replaced with one that additionally checks for a set bit in the extra space. The second place, where the bits are set, is in Trade_Net::recompute_resources (GOG addr 0x58B1A0). In that case I needed to modify the code so that, when it goes to mark access for resources beyond the first 32, it does so in the extra space instead of the original set of 32 bits. That modification required me to insert a function call into a stream of instructions, which is more difficult than replacing a function, but not so difficult since I was able to reuse some code I wrote to do that same thing for the AI production ranking & perfuming.
That's basically it, except for a couple of implementation issues like the extra space must be cleared when the game goes to recompute resource access and it must be expanded as necessary for how many cities there are on the map. This was a case where I was able to remove a limit from the game because it only required modifying a couple of places in the code. Removing the city limit would be more difficult since it would require creating extra space for the game to store city connection info and that info is accessed from many different locations (maybe not so many that I couldn't modify them all but I'd have to look into it). Removing the 31 civ limit is impossible because there are thousands of references to the 31 civ slots scattered throughout the code.
NOTE: What about the unimportant places? I did some investigating and found two additional locations where the sets of 32 bits are used. Those locations are not part of the game logic so that's why I don't consider them important. They check the resource access bits for the purpose (I'm pretty sure) of computing player score and power rankings. I didn't bother modifying those locations to check the extra space, meaning player score won't account for resources beyond the first 32. That's technically a bug but I'm not worried about it because (1) the original code was bugged anyway, with the phantom resources, and (2) if I hadn't pointed this out I doubt anyone would have ever noticed.