Jump to content

Procedurally generated maps - algorithm?


Maurice76

Recommended Posts

Below is the map generation code for the T'Leth stage 1 maptype (map type 15):

 

Special blocks: 00 (corner blocks), 01, 02 (entrance zones), 03 (exit zone)

Filler blocks, 1x1: 04, 05, 06, 07, 08, 09, 10

Filler blocks, 2x2: 11, 12, 13, 14, 15, 16, 17

 

Code legend

SS = Start of subroutine in the executable

ES = End of subroutine in the executable

AC = Attempt Counter for placement of map blocks

CC = Cycle Counter

OF = Offset value for the range

RA = Range for the randomizer (from 0 to the stated value)

ST = Specific Type (see comments)

The location is the hexadecimal offset from the start of the GeoScope.exe file.

The value listed is the value located at that particular offset.

The offsets are based on the DOS version of Terror from the Deep, v1.0.

 

Subroutine: T'Leth stage 1 map generation

Code Location Value Comment

SS 404E0h - -

ES 409A0h - -

 

Step 1: initialising the variables

Code Location Value Comment

ST 40594h 06 X- and Y-dimension of the map.

ST 40599h 02 Z-dimension of the map.

ST 4059Eh 0F Map type for the stage 1 map.

ST 405DCh 24 Number of bytes to check for map blocks and RMP blocks to be placed.

ST 405F0h FC Filler value for the map blocks in the GeoData.dat array.

ST 405F8h 01 Filler value for the RMP blocks in the GeoData.dat array.

ST 40612h 24 Number of bytes to initialise in the GeoData.dat array for map blocks and RMP blocks.

 

Step 2: placing the exit zones and two entrance zones

Code Location Value Comment

Note: the game clears a register (so its value becomes 0) and then assigns this value to four bytes in the GeoData.dat array: byte 13, byte 18, byte 43 and byte 48. Those bytes form the four corners of the map and this instruction assigns map block 00 to them.

ST 40631h 03 Range offset for possible exit zone location.

ST 4063Dh 1F Offset for the exit zone location relative to position (0, 0). Together with the random value, this yields a spot on the bottom row of the map, between the two corner blocks there.

ST 4064Ah FC The value used to check against the calculated position. The map byte is written there if the array holds this value at that spot (redundant calculation as all viable positions hold the initial value of FC, so the check always evaluates as true).

ST 40653h 03 The map block value to be placed there. Map block 03 is the exit zone. Based on the random value, the map block value will be written to byte 44, 45, 46 or 47 of the GeoData.dat array.

ST 40655h 03 Range offset for possible entrance zone locations. There is no offset value defined, but the outcome of the random number generation is increased by 1. This yields a position on the top row, between the two corner map blocks.

ST 4066Ah FC The value used to check against the calculated position. The map byte is written there if the array holds this value at that spot (redundant calculation as all viable positions hold the initial value of FC, so the check always evaluates as true).

ST 40673h 01 The map block value to be placed there. Map block 01 is one of the two entrance zones. Based on the random value, the map block value will be written to byte 14, 15, 16 or 17 of the GeoData.dat array.

ST 40675h 05 Range for the second entrance map block. In contrast to the first one, this one gets a random value in the range [0 - 5], which could be any of the blocks in the top row. Three of those have already been occupied: two corners and the first entrance zone.

ST 40689h FC The value used to check against the calculated position. The map byte is written there if the array holds this value at that spot. In this case it's not redundant, as the random value can point to a location already occupied by another map block. If that's the case, it determines a new random value.

Note: as can be seen, the generation will place an exit zone at the bottom row and two entrance zones at the top row. This means that X-Com has to traverse the entire map from top to bottom to reach the next stage of the mission.

 

Step 3: determining the 2x2 map blocks

Code Location Value Comment

ST 4069Ah 04 Used in the randomizer to find a random value for both X and Y in the range [0 - 4]. Used to determine valid positions for 2x2 blocks.

ST 406CBh 06 The Y-offset is multiplied by this value to find a specific map block for the top left corner of the 2x2 map block.

ST 406DDh FC The four map blocks covered by the selected position for the 2x2 map block are checked against this value for validity in placement.

ST 406F7h 06 Same Y-offset multiplier as above, except this is used to actually place the map block number in the proper spot.

RA 406F9h 06 Range of available 2x2 map blocks for random placement.

OF 40709h 0B -

ST 40715h FE Filler value for the three other corners of the 2x2 map block.

AC 40743h 14 -

CC 40756h 03 -

 

Step 4: filling up the empty blocks with 1x1 blocks

Code Location Value Comment

RA 40769h 06 -

OF 40781h 04 -

End of Subroutine: T'Leth stage 1 map generation

Link to comment
Share on other sites

Below is the map generation code for the T'Leth stage 2 maptype (map type 16):

 

Special blocks: 00, 01, 02, 03, 04, 05, 06, 07, 08 (the map is static).

 

Code legend

SS = Start of subroutine in the executable

ES = End of subroutine in the executable

AC = Attempt Counter for placement of map blocks

CC = Cycle Counter

OF = Offset value for the range

RA = Range for the randomizer (from 0 to the stated value)

ST = Specific Type (see comments)

The location is the hexadecimal offset from the start of the GeoScope.exe file.

The value listed is the value located at that particular offset.

The offsets are based on the DOS version of Terror from the Deep, v1.0.

 

Subroutine: T'Leth stage 2 map generation

Code Location Value Comment

SS 409B0h - -

ES 40E12h - -

 

Step 1: Initialising variables

Code Location Value Comment

ST 409BAh 06 X- and Y- dimension of the map

ST 409CEh 02 Z-dimension of the map

ST 409D3h 10 The map type.

ST 409E2h FC Initialisation value for the map blocks.

ST 40A02h 01 Initialisation value for the RMP blocks.

ST 40A32h 24 Number of bytes to initialise for the map blocks and RMP blocks.

 

Step 2: filling the GeoData.dat array with valid data

Code Location Value Comment

Note: the game will then loop through some code to write the T'Leth stage 2 map blocks to the GeoData.dat array. Two counters have been set to zero by clearing the corresponding registers at this point: EAX and ESI.

ST 40A39h 01 The starting map block number of the 9 in total.

ST 40A6Eh 02 The first one, EAX, keeps track of the offset in the GeoData.dat array. Everytime it writes a map block to it, it is then raised by this value.

ST 40A8Eh 02 The second counter, ESI, counts the number of rows that have been filled with 2x2 blocks. Since there are 3 rows of 2x2 blocks possible in a 6x6 map, the subroutine has to break from placing them once the third row of 2x2 blocks has been filled.

ST 40A5Eh FF Filler value for the top right corner of the 2x2 map block.

ST 40A6Ch FE Filler value for the bottom left corner of the 2x2 map block.

ST 40A7Ah FD Filler value for the bottom right corner of the 2x2 map block.

Note 1: the actual value assigned to the GeoData.dat array is coming from a third counter, see above. It is increased by 1 through an operand. As such, the map block values are hard coded.

Note 2: even though the Alien Colony stage 1 map is written in the same manner (writing 9 map blocks in sequence into a 6x6 grid), the subroutine used to handle it is significantly different. Rather than adding 6 to EAX when it skips to the next set of rows, this subroutine simply resets EAX to zero and increases the row counter by 2. To find the relevant byte range, the row counter is multiplied by the map dimension (6 in this case), to which the EAX value is added. Essentially the same result, but the code is cleaner than for the Alien Colony in that it uses less hard coded values. However, the code is somewhat larger since it calculates several values during runtime.

End of Subroutine: T'Leth stage 2 map generation

Link to comment
Share on other sites

Below is the map generation code for the T'Leth stage 3 maptype (map type 17):

 

Special blocks: 00, 01, 02, 03, 04, 05, 06, 07, 08 (the map is static).

 

Code legend

SS = Start of subroutine in the executable

ES = End of subroutine in the executable

AC = Attempt Counter for placement of map blocks

CC = Cycle Counter

OF = Offset value for the range

RA = Range for the randomizer (from 0 to the stated value)

ST = Specific Type (see comments)

The location is the hexadecimal offset from the start of the GeoScope.exe file.

The value listed is the value located at that particular offset.

The offsets are based on the DOS version of Terror from the Deep, v1.0.

 

Subroutine: T'Leth stage 3 map generation

Code Location Value Comment

SS 40E20h - -

ES 41282h - -

 

Step 1: Initialising variables

Code Location Value Comment

ST 40E2Ah 06 X- and Y- dimension of the map

ST 40E3Eh 02 Z-dimension of the map

ST 40E43h 11 The map type.

ST 40E52h FC Initialisation value for the map blocks.

ST 40E79h 01 Initialisation value for the RMP blocks.

ST 40EA2h 24 Number of bytes to initialise for the map blocks and RMP blocks.

 

Step 2: filling the GeoData.dat array with valid data

Code Location Value Comment

Note: the game will then loop through some code to write the T'Leth stage 2 map blocks to the GeoData.dat array. Two counters have been set to zero by clearing the corresponding registers at this point: EAX and ESI.

ST 40EA9h 01 The starting map block number of the 9 in total.

ST 40EDCh 02 The first one, EAX, keeps track of the offset in the GeoData.dat array. Everytime it writes a map block to it, it is then raised by this value.

ST 40EFBh 02 The second counter, ESI, counts the number of rows that have been filled with 2x2 blocks. Since there are 3 rows of 2x2 blocks possible in a 6x6 map, the subroutine has to break from placing them once the third row of 2x2 blocks has been filled.

ST 40ECCh FF Filler value for the top right corner of the 2x2 map block.

ST 40EDAh FE Filler value for the bottom left corner of the 2x2 map block.

ST 40EE8h FD Filler value for the bottom right corner of the 2x2 map block.

Note 1: the actual value assigned to the GeoData.dat array is coming from a third counter, see above. It is increased by 1 through an operand ('43' at address 40EE9h). As such, the map block values are semi hard coded; only the starting block can be specified.

Note 2: essentially, this is the same code as was used to generate the stage 2 map.

End of Subroutine: T'Leth stage 3 map generation

 

As an aside, is the site having issues? I frequently have connection time-outs, some days it's worse than other days. Quite annoying while I'm editting posts.

Link to comment
Share on other sites

Below is the map generation code for the X-Com base maptype (map type 18):

 

Special blocks: essentially all of them, as the X-Com bases are built by players. Map blocks 16, 17, 18 and 19 form the subpens. Map block 20 is the unused space map block (completely filled).

 

Code legend

SS = Start of subroutine in the executable

ES = End of subroutine in the executable

AC = Attempt Counter for placement of map blocks

CC = Cycle Counter

OF = Offset value for the range

RA = Range for the randomizer (from 0 to the stated value)

ST = Specific Type (see comments)

The location is the hexadecimal offset from the start of the GeoScope.exe file.

The value listed is the value located at that particular offset.

The offsets are based on the DOS version of Terror from the Deep, v1.0.

 

Subroutine: X-Com Base map generation

Code Location Value Comment

SS 3F760h - -

ES 3FAE3h - -

 

Step 1: initialising variables

Code Location Value Comment

ST 3F787h 12 Map type for the X-Com base defense.

ST 3F7A7h 04 Z-dimension of the map.

ST 3F7B1h 06 X- and Y-dimension of the map.

ST 3F7EEh FF Initialisation value for the map blocks.

ST 3F7F2h 01 Initialisation value for the RMP blocks.

ST 3F812h 24 Number of bytes to initialise for the map blocks and RMP blocks.

 

Step 2: filling the GeoData.dat array with valid data

Note: most of the data is directly read from a file, because X-Com bases are built by players. No randomisation takes place in forming the map. However, it does go through some loops to fill the GeoData.dat array. Instead of looping from 1 to 36 it uses two nested loops of length 6 each.

Code Location Value Comment

ST 3F81Fh 06 Used to calculate the specific byte to check by multiplying the Y-offset with this value.

ST 3F832h FF Used to check if the map block is unused (i.e. nothing has been built there).

ST 3F83Ch 00 Even if a map block is used, it may be under construction. This value is compared to the value of the construction timer.

ST 3F840h FF If the block is unused, or the contruction timer is non-zero, the value assigned to the map block for tactical combat purposes is set to this value.

ST 3F846h FF The map block value is compared against this value.

ST 3F853h 14 If it is equal to it, this value is written in its place. The value 14h is the map block that's completely filled up.

ST 3F85Ch 06 Used to calculate the specific byte to write by multiplying the Y-offset with this value.

ST 3F86Bh 06 Used to check against the number of blocks placed on a row. If it reaches this value, it's reset to 0 and the number of rows is increased by 1. These are hard-coded operands, no explicit 0 or 1 is in the code.

ST 3F872h 06 Used to check against the number of rows that have been filled. If it reaches this value, it breaks out of the map building section.

End of Subroutine: X-Com Base map generation

 

This concludes the map generation subroutines, all map types have been covered - albeit that some have been placed out of order. Would it be useful to link here from other forum sections, like the Modding section? Is there any useful data in here that is worth preserving on the UfoPedia site?

Link to comment
Share on other sites

Is there any useful data in here that is worth preserving on the UfoPedia site?

 

Definitely. All of this is fairly useful information that's not on Ufopaedia.org. I guess where to put it is the question. Under the Battlescape or technical.

 

- NKF

Link to comment
Share on other sites

Definitely. All of this is fairly useful information that's not on Ufopaedia.org. I guess where to put it is the question. Under the Battlescape or technical.

 

Good to know smile.png. Just let me know if I can assist with any of that.

 

I do plan to do something similar for Enemy Unknown, too, since the games are fairly similar. I don't know when I get around to that, though; as it is, other games are creeping up close to release (X-Com2 among them wink.png) as well as reallife stuff - and yesterday I also started working on the Tactical.exe; there's quite a lot more to discover smile.png. I figured it would be somewhat hard to get a hook in that one, but I already found the subroutines that detail the start of turn initialisation, discovering a few formulas there, like TU reduction due to leg wounds (current TU's = base TU's * (1 - (sum legwounds)/10) ... but I guess there may be some truncations in there too) as well as the subroutine that pops the Zombie or Tentaculat (same subroutine, it makes a distinction between them - is it weird to think of the sadistical concept of having a Zombie spawn instead of a Tentaculat when a Zombie dies? Zombacolyps! :P).

 

I'm trying to see if I can figure out two aspects in particular:

- Weird placements of units (in my expanded Artefact Stage 2 mission, despite the more numerous available spawn points, I still ended up with a Hallucinoid with X-coordinates at 246-247)

- Placement within Colony Stage 2 missions;

 

Both are handled in the Tactical.exe, so hopefully I can figure out which subroutine handles the placement and figure out why it botches up sometimes.

Link to comment
Share on other sites

I've made some progress in the Tactical.exe, but it's slow going for sure ... I found 110 explicit references to the base address of the UnitPos.dat data array (which is then used to read and/or write data to its various bytes depending on what the subroutines "do") and in a bunch of cases, the reference was passed on through other subroutines by storing it in one of the registers. Figuring out when it's assigning the units to a spawn node is also somewhat hard, as the units' coordinates are also referenced all over the place. After all, every subroutine that somehow needs the coordinates of units will address them.

 

Furthermore, the UnitPos.dat file isn't saved when the mission is generated, it's saved when the mission ends, even though its contents have long since been determined - this pretty much means you can't pinpoint it easily through the debugger. IDA 5.0 is also not very helpful in this aspect, as it creates crossreferences to other areas in the .exe file, while those references are to memory locations (so they don't exist when you're not running the game); I'm having a hard to clearing those crossreferences to make the references readable. Subroutines also appear to be generally larger in size than in the GeoScope.exe, even though the Tactical.exe is smaller. Still, the thing I am lacking for the most part is time; it's extremely time-consuming to analyse everything.

 

I did find the subroutine that seems to load up the MCD files for a mission, as well as a few other tidbits here and there, including what I think is used as RNG. The code for that one is only slightly different from the one used in the GeoScope.exe, which made it recognizable enough to find it in the first place.

 

I also found the location of the bug with the energy regeneration being depended on the left arm. Easy enough to fix.

Link to comment
Share on other sites

Even though this concerns TFTD, would it be better to post my explorations in the MODS section? I already made a post there earlier with regards to the map generator, but I am now diving (pun intended tongue.png) into the Tactical.exe. Tonight I made some real progress: I had given up a little on finding the unit spawn subroutine directly and was checking through the code for large unit validations (check on byte 0A of the UNITPOS.DAT file for bit 4), when I found an interesting code section that I decided to follow and got sidetracked ... sidetracked right into the unit spawn routine tongue.png.

 

My analysis has yielded some interesting results to say the least!

 

- Let me start with a bug: units that get displaced within Artefact Stage 2 missions. This one is not caused by the code that spawns the units, but by a corrupted node in the GRUNGE12.RMP file! The node at address 2A0h in that file (node 28) has the values "FE F6" for respectively the Y and X coordinates! For the bug to occur, two things need to happen: first of all, the game obviously has to include GRUNGE12 in its buildup of the map. Secondly, when it randomly picks spawn points to place aliens, it actually has to pick the bugged one. The Alien unit spawned there will then be placed at that spot, relative to the top left tile of the GRUNGE12 block in the map. The bugged node appears to be empty, by the way, so I suspect that it somehow got shifted out of the visible map during development phase. Deletion is not a bright idea as 3 more nodes follow it in the file and those are referred to by relative position from other nodes. The only way deletion works is by changing the references of the other nodes to those final 3:

22h: 1F -> 1E

52h: 1E -> 1D

2BCh: 1F -> 1E

2BFh: 1E -> 1D

2D7h: 1D -> 1C

2EFh: 1D -> 1C

This reduces the relevant node references all by one. Then delete the bytes at the range [2A0h - 2B7h] to delete the node. This will fix the out-of-place error for aliens on Artefact missions Stage 2.

 

- There is another bug in this RMP file, although it's far less intrusive. Node 11 (decimal, not hex wink.png ) has a value of '09' for spawn type, while the range for spawn types is '00' to '08'. MapView also complains about an "out of range" error when you select this node. It's the spawn node on the second floor inside the small room in the bottom (southeast) corner. Checking the other three chambers, they have two nodes with a spawn type of 7 and one of 6, so setting this one to 6 as well would make it nicely symmetric:

11Ch: 09 -> 06

 

- I've identified the purpose of a data section within the Tactical.exe. Offset based on the DOS version, v1.0, starting at address 5FA95h. Starting at that address is a string of 9 x 7 bytes, which are used to determine valid spawnpoints for units. Writing the bytes out, it's possible to assign ranks to each string:

00 00 00 00 00 00 00 = unused (the starting 00 is referred to, however, to determine the rank offset. They can be considered padding bytes, as a result - or maybe used for Civilians; will need to check).

04 03 05 08 07 02 00 = Alien Commander

04 03 05 08 07 02 00 = Alien Squad Leader (note it's identical to that of the Commander)

05 04 03 02 07 08 00 = Alien Technician

07 06 02 08 03 04 00 = Alien Medic

03 04 05 02 07 08 00 = Alien Navigator

02 05 03 04 06 08 00 = Alien Soldier

02 05 03 04 06 08 00 = Alien Terrorist

01 00 02 00 00 00 00 = X-Com units

The game will start with the first column of the proper unit type and rank. It will scan through the available nodes which have byte 14h (in the ROUTES.DAT file) set to that number and randomly place it on one. Once the number has been depleted, it will move on to the next column and work through those, comparing those against byte 14h. Column 06 is a special one, that's only used when the Deployment byte of the unit is equal to 1 (byte 2Bh in the UNITREF.DAT data). Also, it appears to go down through the ranks, first spawning Commanders, then Squad Leaders, etc (but maybe it's the follow up order for the mission type in question - I couldn't verify that one yet with certainty). In essence, it will occupy nodes of the given number at byte 14h, until those are depleted, moving on to the next column until those are depleted too, etc. If it runs out of valid positions, it will skip the unit and move on to the next one. A check is made to distinguish between X-Com units and Aliens.

 

Edit: If I am reading the code right, it will just loop through all the nodes of the map, starting at the first one till the last one, collecting the node numbers that correspond to the value in the column. It collects the first 30 with that number and omits the rest, or less if there are less than 30. The randomizer then randomly picks one of those to assign the unit it's evaluating to. The list is built newly for each new unit. I am getting a hunch that the node numbers for Alien Colony Stage 2 may actually be almost all of the same type.

Edit 2: My assumption was correct. Except for less than a dozen spawn nodes across all the Alien Colony stage 2 RMPs, all of them are of type 2. There are hardly any "no spawn" nodes, a few of type "0" and of course the 3 of type 4 where the commanders are spawned. Since it only evaluates the first 30 nodes of type 2, it's pretty much done with those in the top row of the Colony. There is also no easy way to fix this, it requires major editing of all the RMP files of Colony Stage 2 to change most of those nodes to other types or be of "no spawn". It could be possible to extend the 30 node check to encompass some ~240 (the number I encountered in one base), but I don't know how the game will respond to that. It might have been reduced to just 30 for performance reasons, though ...

 

- I've also made a proper identification of byte 13h in the ROUTES.DAT file:

Bit 1: 0 = Ground Units and Flying Units allowed, 1 = Only Flying Units allowed;

Bit 2: 0 = Small Units and Large Units allowed, 1 = Only Small Units allowed;

Bit 3: 0 = (edit: need to investigate this one further; seems to be related to movement type, where 0 is for any type and 1 seems to refer to flying - not sure what to make of it in relation to bit 1. Maybe used for pathing towards a destination node? It's only used in 1 subroutine as far as I can see).

When the game starts to scan all spawn nodes, it explicitely sets bit 4 equal to 0. When it starts placing Aliens, it will update this bit to 1 when it placed an Alien on it, so it will skip it while trying to place the remaining Aliens. In essence:

Bit 4: 0 = No Unit present on it, 1 = A Unit has been spawned here.

This bit seems only relevant during the spawning phase (though reading the UfoPedia section about this, it may also have a function when it decides to move Aliens around; maybe it will invalidate this node as a possible destination when an Alien is on top of it? I have my doubts though, as I once had 8 aliens bunched up on a node. With one of the 8 tiles directly around the node taken out due to an object, the alien on the node couldn't move away from there and the 7 aliens around it couldn't move onto it).

Link to comment
Share on other sites

Based on the bug I found in GRUNGE12, I decided to load up all the RMPs of the game into Excel and make a cross check for out of bounds values on nodes. I have to say that the amount of them is fairly staggering, though most of them appear to be unused. In those cases, I can only wonder why they left them in, instead of removing them altogether.

 

Bugged nodes of consequence:

LINERT01: Node 81 (Y value is at 52; arguably though, whether it's of consequence: it is a spawn node for flyers and the coordinate of 52 means it's actually placed on the map of LINERT00, the bow section. Spawn location would be in the gambling hall, along the southernmost wall there. It's not referenced by any other node and doesn't refer to any other node by itself. LINERT02 has the same bug, but LINERT02 is not used by the game.)

GRUNGE12: Node 28 (Y value of 254, X value of 246)

Edit:As an aside to fixing this one by removing the node (see instructions above), it's also possible to just disable the node altogether as a valid spawn node; this can be done by setting the byte at 2B7h from 05 to 00. That's the only change needed, the node can then simply be left in the RMP file as a bugged node without consequence.

 

Bugged nodes without consequence (either it's no Spawn Node and not referred to by other nodes as destination, or a Spawn Node with a Spawn Type that is out of bounds so nothing will spawn there - in the latter case, Nodes marked for spawning by byte 23 are underlined):

ALART00: Node 0 (X value at 255; the only node on this map block, by the way)

ALSHIP02: Node 17 (X value at 252)

ALSHIP05: Nodes 0, 1, 2 (all have Spawn Type 9)

ALSHIP12: Nodes 0, 1 , 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 (all have Spawn Type 9)

ALSHIP13: Nodes 0, 1, 2, 3, 4, 5, 6 (all have Spawn Type 9)

ALSHIP14: Nodes 9, 10, 11, 12, 13 (all have Spawn Type 9)

ALSHIP15: Nodes 8, 9, 10 (all have Spawn Type 9)

A_BASE03: Node 1 (Y and X are both 255)

A_BASE04: Node 6 (X value at 255)

A_BASE18: Node 1 (Y and X are both 255)

A_BASE19: Node 1 (Y and X are both 255)

GRUNGE12: Node 11 (Spawn Type of 9)

UFO07: Node 67 (Spawn Type 9)

ISLAND12: Node 3 (X value of 254)

LEVEL01: Node 24 , 25 (Spawn Type 9)

LEVEL03: Node 4 , 5 (Spawn Type 9)

LEVEL09: Node 0 , 1 (Spawn Type 9)

MU03: Node 2, 4 (Y value of 255, X value of 255), 3 (X value of 255)

PORT05: Node 7 (X value at 255)

XBASES06: Node 10 (X value at 255)

 

Nodes that can be considered bugged due to inconsistencies with regards to the map design (those of the X-Com base could be considered added difficulty, though, with aliens already infiltrated into the base ... but it seems odd to have them behind your lines or amongst your Troops. As it is, most of them have the Spawn Byte 23 at 0, i.e. no spawn):

A_BASE01: Node 6 (defined as an X-Com spawn spot, while it's not an entrance zone block)

A_BASE07: Node 4 (defined as an X-Com spawn spot, while it's not an entrance zone block)

XBASES01: Node 0, 3 , 6 , 7 (d efined as Ali en spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES02: Node 11 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES03: Node 12, 13 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES04: Node 7, 8 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES05: Node 8, 9 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES06: Node 9, 11, 12 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES07: Node 7, 8 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES08: Node 8, 9 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES09: Node 7, 8 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES10: Node 6, 7 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES11: Node 6 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES12: Node 6, 7, 8 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

XBASES12: Node 8 (defined as Alien spawn spot, while it's not a Hangar Bay or the Airlock Elevator)

 

I've also made a cross check for the RMP's that have bit 3 on byte 13h turned on. There are only 3 of them:

ISLAND03: A patrol node only on the ground floor.

CRYPT05: A spawn node for a flyer in the central chamber on the first floor.

PORT17: A patrol node for a flyer on the first floor.

Given how rare they are and that the three nodes aren't in any other particular way interesting to set them apart from all other nodes, I wonder if the presence of bit 3 isn't simply an error - also in light of the RMP bugs I've listed above.

Link to comment
Share on other sites

The UfoPedia says this in the ROUTES.DAT description:

 

Each record is 24 bytes, so the total file size is equal to that times the amount of records in the entire map.

 

This is untrue, there is actually an upper limit. I encountered an effect of it, when I noticed that my Alien Colony stage 2 mission only held 241 nodes, cutting off the last four blocks on the map. The Tactical.exe (once again, DOS 1.0 version) has a value of FAh at address 3CBD7h. The game checks against this value when it attempts to load another RMP block by adding the total nodes placed in the ROUTES.DAT file so far to the number it attempts to load. If that sum exceeds the value 'FA' (250 in decimals), it will cut out of the loading procedure and not load that RMP file into it.

 

As such, any mission will only ever have at most 250 nodes, but likely less since it likely won't exactly reach 250 with the RMPs it did manage to load before breaking from the subroutine.

 

I couldn't clearly see from the code if the game doesn't continue with the next block if there are more to go, or that it really breaks. I think it will still attempt further remaining blocks (though success is unlikely on those too, given how close it is to the cut-off already).

 

As it is, it's only a limit it will touch upon on the larger maps: Alien Colony stage 2 missions and X-Com Base missions (and that one only if the base has been relatively fully developed).

Link to comment
Share on other sites

  • 2 weeks later...

The above also applies to T'leth Stage 1, which is random too.

 

I've also seen that there are more maps that suffer the "too many viable spawn nodes" issue, which causes some to never get populated in any game. Alien Colony Stage 2 suffer from it, but missions like Ship Terror missions (hence you encounter most aliens on the ground floor; applies to both Stage 1 and Stage 2 of either ship type) and T'Leth Stage 3 also suffer from it. The latter one is a pity, as you will encounter virtually all Aliens in that mission in the first part (roughly 1/3rd) of Stage 3, with just a few stragglers throughout the remainder.

 

The only way to solve this is to edit the RMP files and make sure to do two things:

- Make sure the total number of nodes is roughly equal to ~7 per 1x1 block (so 2x2 blocks have 4 times that number, 28), so you won't exceed the 250-node limit;

- Make sure the total number of valid nodes for each priority level doesn't exceed ~40 across the entire map, so ~1 of each priority type per 1x1 map block (and likewise, ~4 for 2x2 blocks);

 

It might be worth experimenting a little with the maximum limit, see if it can be raised higher. That would at least remedy the first issue. I assume that both limits are for performance reasons, actually ...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...