Jump to content

Questions about BG2EE Random Treasure Tables

Recommended Posts

I have some questions about the BG-style random treasure 2DA tables for BG2EE.

Question 1)
RNDEQUIP.2DA claims its item filenames are RNDEQUx#.ITM
RNDTREAS.2DA claims its item filenames are RNDTRE0#.ITM
RNDMAGIC.2DA claims its item filenames are RNDMAGx#.ITM
RNDWEAP.2DA claims its item filenames are RNDWEPx#.ITM
RNDSCROL.2DA claims its item filenames are RNDSCRx#.ITM

Where x=any character (even letters and symbols, and has no bearing on how RND*.2DA is read), and #=the row number of RND*.2DA to use (can be 1-9).  Of the above, RNDTREAS.2DA is the outlier with the second to last character being a static 0 instead of the variable x.  However, the rndtreas expansion topic indicates that, for the EEs, the 2nd to last character must ALWAYS be 0, and the 2DAs can in fact use more than Rows 1-9.  I take it the topic is correct and the IESDP was just never updated?

Question 2)
Is it necessary to have these random treasure table ITM files physically in the game, or is it enough simply to reference the relevant filename in the CREs, containers, etc.?

Question 3)
RNDEQUIP.2DA, RNDWEAP.2DA, and RNDSCROL.2DA have column headers from 1 to 20, but the IESDP claims 2D10 dice are rolled into a row of this table, meaning the possible values you can roll are 2 to 20. This means column 1 can never be rolled.

Conversely, RNDTREAS.2DA and RNDMAGIC.2DA have column headers from 2 to 20, but the IESDP claims 1D20 dice are rolled into a row of this table, meaning the possible values you can roll are 1 to 20.  This means that if you happen to roll a 1, you get nothing.

Don’t these dice rolls seem… backward?

Question 4)
Is it safe to make the assumption that when the engine “rolls a die”, it generates a random number from 1 to the maximum die face using a uniform distribution?  In other words, you have an equal chance of rolling any of the possible numbers on the die?  If so, then rolling onto these random loot tables with a 1D20 does NOT have the same probability distribution as rolling onto them with a 2D10.  Adding multiple uniformly distributed random numbers tends toward the shape of a  normal/Gaussian distribution:


In essence, if you roll using a 1D20 you have an even chance of getting any of the items on that row of the table.  If you roll using 2D10, you have a far higher chance of getting an item towards the middle of that row than you do getting an item towards the left or right ends…  If this is correct, then an item’s position within the row for the 2D10 2DAs is quite impactful…


Also, I found it useful to have a visual representation of which random treasure table 2DAs could reference which others, so here it is.


Link to comment

I can answer only two things from the POW of the originals:

- yes, the items must not exist, otherwise you'd get that item instead of it being resolved to something random. So reference away like before.

- of course 1d20 and 2d10 have different distributions, but I'm pretty sure this difference in use is real — it was also inherited by gemrb in 2007 for tables with weighted odds

- rand() is used, so the randomness is good enough, but not up to par with proper RNG

Link to comment

Very interesting that only the scroll/treasure tables have the 1/20 chance of giving nothing, I thought that applied to all tables and was the reason why I didn't continue working on using them to gear up enemies randomly (ToBEx raises them to 99 rows and I am going to (not really) use every single one of them).

Link to comment

For Question 3 and 4 I guess it can be tested: both distribution and what exact dice is rolling. One can simply replace all the items in a table with some stacking items (arrows, potions), create a script on a chest that if it is empty, another random item from the testing table appears and take the item from the chest couple of thousand times.

Link to comment

I have spent some time testing how various aspects of the RNDEQUIP, RNDTREAS, RNDMAGIC, RNDWEP, and RNDSCROL random treasure 2DA tables work in BG2EE v2.6.6.0 (Steam edition).  Some of my observations matched my expectations based on currently available descriptions of this mechanic, and some of them were surprises (at least to me).  I will attempt to summarize my findings here, along with any caveats about the scope of my testing.  Note that I have not yet tested RNDTRES.2DA at all.  Everything here pertains to the 5 I listed above.

There are either 19 or 20 columns of random treasure on any given row in these 2DAs that can be drawn.  I determined that making 2000 draws against these 19 or 20 potential items (a factor of two orders of magnitude) would be enough to draw sufficient statistical conclusions about the distributions.  To facilitate this in a somewhat timely manner, I wrote the following script, assigned it as the custom script on the PC, let it run to completion, and had them and an NPC collect and consolidate the results.  Note that the actual ITM name varied with the tests performed.

    RESPONSE #100


  1. My first observation is about the naming of the RND***x#.ITM files that point into these tables where *** depends on the 2DA and # is the row index in the table.  Some sources claim that the x must only be 0 (zero) in the EEs whereas other sources claim it can be any arbitrary character.  I found it could be any arbitrary character (I tested letters and numbers), subject to the restriction specified in the following point.  This applied to all 5 of the 2DAs.
  2. Generating the random items directly via the above script required the actual ITM file called out to actually exist in the game.  If it did not, nothing at all happened:  no real items nor any erroneous invisible and unmovable items were created.  I did not test if this hold true if the ITM files are referenced indirectly (from one random treasure 2DA into another).  This applies to Point# 1 insomuch as the second to last character can’t directly be any character not supported as a filename character by the OS.  This applied to all 5 of the 2DAs.
  3. When the “2DA Default Value” (line 2 of the file; not to be confused with line 2 of the table) is set to * (the value set in the unmodded game), then any call from an ITM pointing out of bounds in the table (such as pointing to the 4th row in a table with only 3 rows) generates an invisible, unmovable item.  This applies to all 5 of the 2DAs and is subject to Point# 2.
  4. The next logical question becomes what happens if the “2DA Default Value” is changed.  I found that changing this value in RNDEQUIP, RNDMAGIC, RNDWEP, and RNDSCROL and then referencing a row not in the table (like row 4 out of 3 as above) gave this default item instead of an error item.  In all 4 of these 2DAs, a quantity value was also supported here (e.g. MISC07*100).  However, I also found that if a valid row in the table contained any entries consisting of a plain asterisk (*), these generated invisible, unmovable items regardless of the “2DA Default Value”.  I found changing this value in RNDTREAS.2DA had no effect whatsoever.
  5. All 5 ransom treasure tables supported purely numeric entries which translated into that number of gold coins.  It was unnecessary to zero pad these numbers.  For example, column values of [001 01 1] all give 1gp.  I did not test the upper limits of how much gold can be specified at a time, nor did I test what happens when the value is 0.
  6. For each of the sets of 2,000 rolls I made into any of the treasure tables, I ALWAYS got exactly 2,000 items.  I was never shorted any, not even in RNDEQUIP.  The following chart summarizes the distributions I got rolling into each of these random treasure tables.









Column Headings






Estimated dice roll












RNDEQUIP has column headings from 1 to 20.  One might expect to roll onto this table with a 1D20 and get a uniform distribution (an equal chance of rolling any number from 1 to 20).  Alternatively one might expect to roll onto this table with a 2D20 and get a quasi-normal distribution where possible rolls fall between (inclusive) 2 and 20 with the greatest chances of rolling into the middle of these possibilities.  Neither of these appear to be the case.  It may be apparent that the first time I ran RNDEQUIP I couldn’t quite believe the results, so I rand them again and got the same result.  The dice roll appears to be something like a 2D10-1 meaning column 20 is impossible to roll instead of the expected column 1.

The bottom right plot in the above chart is what I get when I delete column 1 from RNDEQUIP and make the 2,000 rolls.  This matches what is expected from a 2D10 roll and all table columns are “rollable”.  I contest this is either an engine bug (it should be rolling 1D20 onto this table), or there is a bug in the 2DA and column 1 should be deleted and the entries there incorporated into the other columns on the same row.  Preferably supplanting a duplicated entry where possible.

Link to comment

The way it works for RNDEQUIP makes sense to me; after all, it's not like the game reads the header row when it's doing this stuff. All of those triangle-distribution cases look at column 2d10 - 1; it's just that that column is labeled with the number 1 higher in most of the tables.

This is a bug. The RNDEQUIP tables should either have one fewer column, or be interpreted with a flat 1d20 instead of a triangular 2d10. But it's not a priority to fix. It has absolutely no impact in the vanilla game, as there is no way to ever roll on the RNDEQUIP tables. They are completely unreachable, with no instances of those random treasure tokens existing in the game world and no references to them from the other random treasure tables..

It's not the only zero-impact bug out there. I've found a scripting bug in the trip to Hell at the end of SoA that permanently applies a "no permanent death" effect to Player 1. They'll never chunk so you can always resurrect them, once you continue to ToB (Offer void after Game Over).

Link to comment
4 hours ago, jmerry said:

The way it works for RNDEQUIP makes sense to me; after all, it's not like the game reads the header row when it's doing this stuff. All of those triangle-distribution cases look at column 2d10 - 1; it's just that that column is labeled with the number 1 higher in most of the tables.

I see your point.


The remainder of this post exclusively concerns RNDTRES.2DA, also in BG2EE v2.6.6.0 (Steam edition).  I’ll keep the topic of these observations consistent with the numbering from my previous post for clarity.

  1. N/A
  2. Using a script like the one in my previous post to directly generate random items from a new row in this table did nothing unless the actual ITM file named for the new row name in this table actually existed in the game.
  3. Item names pointing into this table correspond to the row names within the table, so obviously if you try pointing to a row name not in this table you aren’t actually pointing into this table at all.  Duh…
  4. Changing the “2DA Default Value” appeared to have no effect whatsoever.  If you do something against the rules, you get an invisible, unmovable item.
  5. This table supports purely numeric entries which translate into that number of gold coins.  It is unnecessary to zero pad these numbers.  For example, column values of [001 01 1] all give 1gp.  A value of 0 (zero) gives one gold.  The maximum number of gold coins that can be given at a time is 255.  The asterisk use of giving multiples of an item that is stackable does work here (e.g. MISC07*10 gives 10 gold coins).  The max stack using this method is also 255.  I didn’t bother discerning the logic behind how many you get if you exceed 255, but it is less.
  6. You get a uniform distribution (equal chance) of the valid values on a row from this table.  How the engine determines the valid values is outlined in the next point.
  7. The engine stops counting valid values with the first asterisk (*) it finds in the row reading from left to right.  If the first column in that row is an *, then you only get invisible, undroppable items.  If the 1st column has a valid item (or gold) and the 2nd column is an *, you only get what was in the first column, even if there was a valid item in the 3rd column.  Don’t use sparse "arrays" here.


Link to comment
48 minutes ago, Sam. said:

I didn’t bother discerning the logic behind how many you get if you exceed 255, but it is less.

Looks like conventional 8-bit overflow math. I modified the first row of RNDTREAS to be numbers from 513 to 531, then gave the Candlekeep rats each one instance of RNDTRE01 ... piles of 7, 8, 9, 10, and 14 gold. The gold you get is the remainder mod 256.

Second test ... what if that remainder is zero? Set all the entries in the table to 768, and the gold piles become 1 each. So numeric entries result in that much gold reduced mod 256, with a minimum of 1.

Link to comment

Yeah, this is the comment that we have:



if [the column] count is odd and the column titles start with 2, the random roll should be 2d((c+1)/2)-1


So 2d10-1 or 2d10-2 if you're counting from 0.

Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...