Advertisement
glank

Dampé writeup for ZFG

May 26th, 2019
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.72 KB | None | 0 0
  1. Alright, I'll start with the way Dampé uses the RNG, and then I can talk a bit
  2. about the RNG itself.
  3.  
  4. First, a random 32-bit floating-point number is generated between 0 and 1.
  5. Greater than or equal to zero, and less than one. I can talk about how floating
  6. point numbers work if you want. This number is used to choose one out of four
  7. possible rewards, numbered 0 to 3. If the random value is less than 0.4, the
  8. reward is set to 0. Otherwise if it is less than 0.7, the reward is set to 1.
  9. Otherwise if it is less than 0.9, it is set to 2. Otherwise, it is set to 3.
  10. 0.0 - 0.4: 0 (green rupee)
  11. 0.4 - 0.7: 1 (blue rupee)
  12. 0.7 - 0.9: 2 (red rupee)
  13. 0.9 - 1.0: 3 (purple rupee)
  14. So the probabilities for each reward is 40%, 30%, 20%, and 10% respectively.
  15.  
  16. Next, the game checks how many times the randomly selected reward has been
  17. awarded already. Each possible reward has a max number of times it can be
  18. awarded.
  19. 0 (green rupee): 8
  20. 1 (blue rupee): 4
  21. 2 (red rupee): 2
  22. 3 (purple rupee): 1
  23. If the randomized reward is not "saturated", the reward selection process
  24. completes and the corresponding reward counter is incremented. If the randomized
  25. reward is saturated, the random value is discarded and the selection process
  26. continues to "phase two". At this point, each of the four possible rewards is
  27. tested in order lowest to highest. When a reward is encountered that is not
  28. saturated, that reward is selected and its counter is incremented. In other
  29. words, the game chooses the worst possible reward that is left to give. If there
  30. are no rewards left to give (all rewards are saturated), phase two fails, and
  31. the selection process moves on to the final phase. That is where the "cycle
  32. reset" happens, where all reward counters are reset to zero. But, instead of
  33. starting the selection process over for this dig, at this point the game simply
  34. selects reward 0 (green rupee). You'd think the first attempt in each 15 attempt
  35. cycle would have an equal reward probability distribution, but actually, on
  36. every 15th attempt starting on attempt 16, you're guaranteed to receive a green
  37. rupee.
  38.  
  39. So, that's the reward selection process. The heart piece is not actually part of
  40. the selection process itself. When the reward has been selected, the game checks
  41. if the selected reward is 3 (purple rupee). If it is, and if the Dampé HP flag
  42. is not set, the game sets the reward to 4 (heart piece), and sets the Dampé HP
  43. flag. So for the purpose of reward selection, the purple rupee and the heart
  44. piece are identical.
  45.  
  46. Alright, that's it for dampe I think. Now, on to the RNG.
  47.  
  48. OoT uses a very common type of RNG called a Linear Congruential Generator (LCG).
  49. An RNG, as the name suggests, is just a thing that produces random numbers.
  50. LCG's are common because they're fast, easy to implement, and produce pretty
  51. good randomness, certainly good enough for videogames. An LCG has an internal
  52. state, which consists of just a single number, which is the last number that was
  53. produced in the random number sequence. Whenever the game needs some randomness,
  54. it asks the RNG to produce the next number in the sequence, and then uses that
  55. number to determine the outcome of some event, or to set some variable. The LCG
  56. produces the next number in the sequence with a simple formula. I don't know how
  57. much you care about the details and mathematics behind the RNG, but here's the
  58. formula;
  59. (x * a + c) % m
  60. x is the previous number in the sequence. a, c, m are some predetermined
  61. constants, and % is the modulo operator (division remainder).
  62.  
  63. OoT's rng uses these constants;
  64. a = 1664525
  65. c = 1013904223
  66. m = 4294967296
  67. You want your constants to satisfy certain conditions if you care about the
  68. strength of your RNG. But if you just want some numbers that look random enough,
  69. the choice of constants isn't that important. These particular constants come
  70. from a 1986 book called Numerical Recipes. This m was chosen because it is the
  71. numerical limit of a 32-bit value. As such, the modular arithmetic is implicit
  72. in the way the cpu does its computations (if you increment a 32-bit number past
  73. 4294967295 it rolls over to zero). The formula can thus be simplified to
  74. x <- x * 1664525 + 1013904223,
  75. And that's really all that the RNG does.
  76.  
  77. Now, obviously there's nothing random about this (which is why it's called a
  78. pseudo-random number generator, it's not actually random). For any given x in
  79. the sequence, the next x will always be the same. If you know the starting x,
  80. any number further down the sequence is dead simple to predict. What's not so
  81. easy to predict is the starting value of x, the seed. Assigning a starting value
  82. of x is known as seeding, and this is done at every scene load (i.e. after
  83. entering a new scene, voiding out, etc). The LCG is seeded with the CPU counter.
  84. The CPU counter is simply a 32-bit number in the CPU that counts up at a
  85. constant rate of 46875000 ticks per second. When it reaches its numerical limit,
  86. it rolls over to zero and starts over. This happens roughly every 91.63 seconds.
  87.  
  88. Now, in order to predict the value of the RNG, you must know when the seeding
  89. happened, to a precision of about 20 nanoseconds (in order to know what the
  90. value of the CPU counter was at the time), and you must know exactly how many
  91. times the RNG sequence has advanced since then. I'll stop here for now, let me
  92. know if there's anything you want me to clarify or elaborate on, or if there's
  93. something else in particular you want to know.
  94.  
  95. Addendum; Randomization of floating-point numbers.
  96. The LCG produces 32-bit integers, but Dampé uses a floating-point number to
  97. choose a reward. For this purpose, the LCG is not used directly, but instead a
  98. different function which transforms a random integer from the LCG into a
  99. floating-point number.
  100.  
  101. The floating-point random number function calls the LCG to produce a random
  102. integer number. The lower 23 bits of this number are put in the significand of a
  103. floating point number with an exponent of 0, and the rest are thrown away. The
  104. resulting number is in the range 1 <= x < 2. One is subtracted from the number
  105. to put it in the range 0 <= x < 1, and then it is returned to the user. It is
  106. common practice for the user to multiply the number by n to produce a number in
  107. the range 0 <= x < n, where n is the desired range, but Dampé does not do this
  108. because the number is already in the desired range.
  109.  
  110. The exponent is not randomized, because the distribution of the resulting
  111. numbers would not be uniform. If a random exponent in the range (-128) - (-1)
  112. were used, the number would have a 1/128 chance of being in the range 0.5 - 1,
  113. and a 127/128 chance of being in the range 0 - 0.5. Using an exponent of 0 and
  114. then subtracting 1 is the easiest way of producing a uniform distribution with a
  115. range of 1.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement