Ramirez wrote:Commander McLane wrote:
Whoever scripts commodities.plists should do his maths well, or all the Jamesons will get unforeseen opportunities.
That'll be me then! I think my intention was to get furs available as highly-priced rare items, the idea being that an industrial factory wouldn't usually have that sort of thing in stock. However, looking at the plist I think the price and quantity adjusters do seem rather excessive and so are probably causing the rollover effect you describe. To be honest I never did understand exactly how the pricing mechanism worked and so I had to resort to trial and error - if you can give me a simple explanation I'd be grateful.
You're welcome, Ramirez.
*** WARNING: HOPEFULLY SIMPLE STEP-BY-STEP, BUT RATHER EXCESSIVE ANSWER FOLLOWING ***
All you need to know is in the
commodities.plist document in the wiki. The formula for calculation of prices is this:
Code: Select all
price = (MARKET_BASE_PRICE + (MARKET_RND & MARKET_MASK_PRICE) + (economy * MARKET_ECO_ADJUST_PRICE)) & 255
Now what you have to consider is that this is a formula for a
binary calculation, not decimal. Just think of the price as one byte, ranging in value from 0..255. The '&'-operation that is performed a couple of times is a logical AND applied to the 8 bits of the byte. Therefore the final '& 255' cuts out everything above these 8 bits. So if the sum has reached 256 before this step it will be Zero afterwards, because 256 & 255 = 0. To make this clearer I write the same as binary numbers:
The AND sets only those bits of the resulting byte to '1', where both of the bits in the summands are '1'. In this equation this is not the case, as either the upper or the lower line reads '0'. So the result is
Code: Select all
11111111
AND 100000000
=============
000000000
The same kind of calculation is applied to the '(MARKET_RND & MARKET_MASK_PRICE)'-part.
The '+'- and '*'-operators are handled in the same way as if they were decimal operators.
So, given your current entries for furs in the commodities.plist, their price is calculated as follows step by step. We start from the left side of the equation and take the arguments in brackets as one:
MARKET_BASE_PRICE: Well, that's the base from which the calculation starts. It has very little to do with the final price, as it's going to be manipulated in the rest of the equation. And it can be manipulated so harshly, you won't recognize it in the end result. For the furs in the astrofactory it's 20.
Code: Select all
price = (20 + (MARKET_RND & MARKET_MASK_PRICE) + (economy * MARKET_ECO_ADJUST_PRICE)) & 255
(MARKET_RND & MARKET_MASK_PRICE): MARKET_RND ('market-random') is a random value from 0..255 that is produced by the engine whenever you enter a new system and is saved in the player's save-file. Obviously if you have a final range of prices from 0..255 with a rollover an added random factor of 0..255 is absurd, therefore the random that finally enters into the calculation is limited. This is done by
masking the random-byte with MARKET_MASK_PRICE, which is ANDed with the random number. E.g. if you set it to 7, the random added to the final price can only be in the range of 0..7. 7 in binary notation is 00000111, so only the last three bits of MARKET_RND enter into the equation. Another example: If you set MARKET_MASK_PRICE to 65, things get more complicated, because the random won't be evenly divided in the range of 0..65, as it may look at first glimpse. In binary notation 65 reads 01000001, so only two bits, the first and the seventh from the right, are used. Only these bits of MARKET_RND, if set to '1', can make it into the equation through the mask. So only the values 0, 1, 64 and 65 can be added to MARKET_BASE_PRICE. This makes the price randomly
either quite high
or quite low with
nothing in-between. And, last example, if MARKET_MASK_PRICE is set to 0, the random element is completely eliminated.
Now we run into a problem. MARKET_MASK_PRICE should
always have a positive value, as negatives will behave unexpectedly. Due to the binary nature of the calculation performed in this bracket they will roll over as well (there is no '-' in the binary 8-bit-world). -1 will be treated as 255, -2 as 254 and so on.
Your MARKET_MASK_PRICE for furs is -1. Now this is the case mentioned just right now. Binary -1 equates to 255. That means the mask is fully open, any MARKET_RND from 0..255 will be added to MARKET_BASE_PRICE, the outcome is completely unpredictable. That also means that the next step, the influence of the systems economy, is meaningless, as it cannot change anymore the complete randomness of the prices. (From a systematic point of view, 'complete random' is the same as 'complete random + x'.)
We won't give up at this point, however, but take out the negative number. One would expect it to work like this: Negative numbers would be treated analogous to positives, but get subtracted. So the '-1' would mean the random in the equation is limited to leaving MARKET_BASE_PRICE as it is or subtract 1. In numbers: 20 - 0 = 20 or 20 - 1 = 19.
As we know now, it doesn't work like this. But we can get exactly the same effect by setting MARKET_MASK_PRICE to 1 instead of -1 and MARKET_BASE_PRICE to 19 instead of 20.
Code: Select all
price = (19 + (0..1) + (economy * MARKET_ECO_ADJUST_PRICE)) & 255
(economy * MARKET_ECO_ADJUST_PRICE): The next modification to the price depends on the system economy, Rich Industrial to Poor Agricultural, represented by a number from 0..7. The lower the number, the better the economy (have a look at the
planetinfo.plist document in the wiki for all information on system variables).
MARKET_ECO_ADJUST_PRICE is a factor that determines how big a difference the economy makes for prices. It represents the step in which the price rises or sinks from economy to economy. If it is set to 1, the difference between two neighbouring economies will be 1, if it set to 10, the difference will be 10.
By choosing positive or negative values you determine whether a commodity will be cheap in agricultural worlds and expensive in industrial worlds, or vice versa. So here negatives are welcome. The 'economy'-value of a Rich Industial world is 0, so, given a small base price, the commodity will be cheap here. If you go down the economic levels to Poor Agricultural (= 7) the price will grow according to MARKET_ECO_ADJUST_PRICE. Let's say a commodity's base price is 0, there is no random and MARKET_ECO_ADJUST_PRICE is something big like 36. Then in a Rich Industrial system the price is 0 * 36 = 0, in an Average Industrial it's 1 * 36 = 36, in a Poor Industrial it's 2 * 36 = 72, in a Mainly Industrial it's 3 * 36 = 108, and so on up to the Poor Agricultural with 7 * 36 = 252. The result is a huge fluctuation, covering almost the whole possible range, depending only on the economy. Now if you have a big base price like 252 and set MARKET_ECO_ADJUST_PRICE to -36 you get the same steps and range, but this time the commodity will be cheap in low economy worlds and expensive in high economies. And, of course, if you set MARKET_ECO_ADJUST_PRICE to a low level the price differences between the economies will be minute. If you set it to 0 there won't be any. If you do so, the price will only vary randomly, as determined in the first brackets, and therefore be completely unforeseeable. (And if you set MARKET_MASK_PRICE and MARKET_ECO_ADJUST_PRICE both to 0, the price will be the base price wherever you are. Period.)
MARKET_ECO_ADJUST_PRICE for furs in astrofactories is set to -9, which means the price shall drop from industrial to agricultural worlds.
Code: Select all
price = (19 + (0..1) + (ONEOF -63, -54, -45, -36, -27, -18, -9, 0)) & 255
So, what do we have up to now? MARKET_BASE_PRICE is 19, random adds 0 or 1. The second bracket will subtract a value from 0 to -63 (= 7 * -9) according to the economy. Let's list the possible results:
Code: Select all
MARKET_BASE_PRICE + (MARKET_RND & MARKET_MASK_PRICE) + (economy * MARKET_ECO_ADJUST_PRICE)
the first bracket results to either 0 or 1, so I list both possibilities:
Rich Industrial: 19 + 0 + (0 * -9) = 19
or 19 + 1 + (0 * -9) = 20
Average Industrial: 19 + 0 + (1 * -9) = 10
or 19 + 1 + (1 * -9) = 11
Poor Industrial: 19 + 0 + (2 * -9) = 1
or 19 + 1 + (2 * -9) = 2
Mainly Industrial: 19 + 0 + (3 * -9) = -8
or 19 + 1 + (3 * -9) = -7
Mainly Agricultural: 19 + 0 + (4 * -9) = -17
or 19 + 1 + (4 * -9) = -16
Rich Agricultural: 19 + 0 + (5 * -9) = -26
or 19 + 1 + (5 * -9) = -25
Average Agricultural: 19 + 0 + (6 * -9) = -35
or 19 + 1 + (6 * -9) = -34
Poor Agricultural: 19 + 0 + (7 * -9) = -44
or 19 + 1 + (7 * -9) = -43
Now you see the rollover effect, marked by breaking the zero-barrier. The result of the final ' & 255' in the equation is that 256 will be added to all negative values, so we get the following list of possible values:
Code: Select all
Rich Industrial: 19 or 20
Average Industrial: 10 or 11
Poor Industrial: 1 or 2
Mainly Industrial: 248 or 249
Mainly Agricultural: 239 or 240
Rich Agricultural: 230 or 231
Average Agricultural: 221 or 222
Poor Agricultural: 212 or 213
Above I called this final result the 'price', but that's not really true. To get the final price from the numbers shown they are multiplied by 0.4. So on the market screen the player should see the following prices (and due to our calculation these prices
only):
Code: Select all
Rich Industrial: 7.6 or 8.0 cr
Average Industrial: 4.0 or 4.4 cr
Poor Industrial: 0.4 or 0.8 cr
Mainly Industrial: 99.2 or 99.6 cr
Mainly Agricultural: 95.6 or 96.0 cr
Rich Agricultural: 92.0 or 92.4 cr
Average Agricultural: 88.4 or 88.8 cr
Poor Agricultural: 84.8 or 85.2 cr
I guess that's not what you intended. The price is very high in Mainly Industrial Dictatorships, then lowers slowly in Agricultural Dictatorships, and surprisingly drops in the well industrialised systems, with its absolute low in Poor Industrial Dictatorships.
So, what could you do? I am now assuming you want the price to be highest in Rich Industrial systems and lowest in Poor Agricultural ones, but on a high level in all of them, as furs are rare in astrofactories. If so, then you just need to adjust the base price to a high value. So set MARKET_BASE_PRICE to 254, which will allow for the peak price of 102 cr (255 * 0.4). If you don't want the peak price, then subtract just a little bit from MARKET_BASE_PRICE and set it to something like 251 or 246.
The next thing I would introduce is a little more random flucuation, by setting MARKET_MASK_PRICE to 3 or even 7. If you set it to 15 the random fluctuation will become larger than the economic steps, meaning that the highest possible price in a system with any economic level is higher than the lowest possible price in the system one level higher. The price-scales will overlap somehow. Therefore trading up the economical chain wouldn't always guarantee a profit. (Well, it still would if you trade to a system two economic steps up. And on the other hand, I don't suppose trading from one astrofactory to another a main trade route.) So, why not 15?
Note, however, that a change of MARKET_MASK_PRICE will also require you to change MARKET_BASE_PRICE in the opposite direction. If a random value of up to 15 can be added, you have to reduce the base price by these 15, or you get another rollover again.
These changes would result in the following list of results to the equation and prices:
Code: Select all
MARKET_BASE_PRICE = 240 MARKET_MASK_PRICE = 15
Rich Industrial: 240..255 => 96.0--102.0 cr
Average Industrial: 231..246 => 92.4--98.4 cr
Poor Industrial: 222..237 => 88.8--94.8 cr
Mainly Industrial: 213..228 => 85.2--93.2 cr
Mainly Agricultural: 204..219 => 81.6--87.6 cr
Rich Agricultural: 195..210 => 78.0--84.0 cr
Average Agricultural: 186..210 => 74.4--80.4 cr
Poor Agricultural: 177..201 => 70.8--76.8 cr
The credits rise always in steps of 0.4 cr.
If you're happy with that, than your commodities.plist entry will look like this:
Code: Select all
<array>
<string>Furs</string>
<integer>0</integer>
<integer>0</integer>
<integer>240</integer>
<integer>-9</integer>
<integer>-9</integer>
<integer>0</integer>
<integer>15</integer>
<integer>-1</integer>
<integer>0</integer>
</array>
Now you have three possibilities for tweaking with it:
(1) You can lessen the influence of random by reducing the '15' to 7, 3 or 1, while at the same time raising the base price by the same amount you have subtracted off the '15'. Of course you can also increase the randomness by setting the '15' to 31 or 63, while at the same time reducing the base price accordingly.
(2) You can widen the price-gap between different economies by exchanging the first '-9' with an even lower negative value (e.g. -15). Or you can close the gap by setting it closer to 0.
(3) And of course you can reduce the base price, making the furs cheaper all over the Dictatorship astrofactories.
*************
Finally a word on the quantity-calculation: The formula is almost the same, the only difference being a minus in front of the second brackets, where there is a plus in the price formula. And there are some restrictions that don't apply to the price calculation. These are namely (quoted from wiki):
Code: Select all
// if the quantity gets too high it's zeroed
if (quantity > 127) quantity = 0
// limit the quantity to 0..63 units
quantity &= 63
So the calculation should not come up with a value above 63, if possible.
Otherwise the same applies as to prices, namely: MARKET_MASK_QUANTITY shouldn't be negative. So perhaps have a fiddle with that as well.
Now I hope you're still there and could follow this non-brief explanation. If you've got further questions, you're welcome as well.
Greetings
Commander McLane