This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| cw4:4rpl_tools [2025/06/28 18:29] – kalli | cw4:4rpl_tools [2025/08/29 21:04] (current) – [Pseudo RNG based on Linear congruential generator (LCG)] kalli | ||
|---|---|---|---|
| Line 3857: | Line 3857: | ||
| - | ===== Next UseFul Function goes here ===== | + | ===== Pseudo Random Number Generator, based on sinus ===== |
| <hidden click here for source code> | <hidden click here for source code> | ||
| - | <code 4rpl file name.4rpl> | + | Several basic functions based on Grabz' rng lite function of "<-seed sinus 10000 mul dup floor sub". |
| + | |||
| + | Copy the functions directly into your script or run the below script in your cpack and have other scripts send messages to request a randfloat or randint. | ||
| + | |||
| + | |||
| + | Difference between the functions: | ||
| + | * " | ||
| + | * " | ||
| + | * " | ||
| + | * No prefix: these are sequenced seeds and they use index 0. | ||
| + | |||
| + | Example code with messages: | ||
| + | <code example.4rpl> | ||
| + | 12345 ->int | ||
| + | 1 ->index | ||
| + | 0 ->first | ||
| + | 100 ->last # The last integer itself will be excluded. | ||
| + | " | ||
| + | < | ||
| + | " | ||
| + | < | ||
| + | " | ||
| + | < | ||
| + | " | ||
| + | < | ||
| + | " | ||
| + | < | ||
| + | " | ||
| + | < | ||
| + | " | ||
| + | < | ||
| + | " | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | <code SinusRNG.4rpl> | ||
| + | :once | ||
| + | # Creating lists and a starting mapconstant for the seed sequences. | ||
| + | createlist -> | ||
| + | createlist -> | ||
| + | getmapsize 2 div swap 2 div swap dup2 getterrain 1 add dup 99999 floodfillterrain getlistcount -> | ||
| + | |||
| + | # Setting up the messages so that other scripts can request a random seed. | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | |||
| + | : | ||
| + | <-_DATA listtostack @sinRandInt -> | ||
| + | : | ||
| + | @sinRand01 -> | ||
| + | : | ||
| + | <-_DATA listtostack @indexSinRandInt -> | ||
| + | : | ||
| + | <-_DATA @indexSinRand01 -> | ||
| + | : | ||
| + | <-_DATA listtostack @spikedSinRandInt -> | ||
| + | : | ||
| + | @spikedSinRand01 -> | ||
| + | : | ||
| + | <-_DATA listtostack @seededSinRandInt -> | ||
| + | : | ||
| + | <-_DATA @seededSinRand01 -> | ||
| + | |||
| + | :sinRandInt # INPUT: integer first randInt + integer last randInt. OUTPUT: an integer in between the first and last randInt, excluding the last randInt. | ||
| + | ->last | ||
| + | ->first | ||
| + | 0 @indexSinRand01 <-last <-first sub mul <-first add asint | ||
| + | |||
| + | :sinRand01 # INPUT: none. | ||
| + | 0 @indexSinRand01 | ||
| + | |||
| + | : | ||
| + | ->last | ||
| + | ->first | ||
| + | @indexSinRand01 <-last <-first sub mul <-first add asint | ||
| + | |||
| + | : | ||
| + | # The random numbers will be generated with the previous seed that is stored under that index. | ||
| + | ->i | ||
| + | < | ||
| + | <-i < | ||
| + | 1 -> | ||
| + | else | ||
| + | < | ||
| + | endif | ||
| + | |||
| + | : | ||
| + | ->last | ||
| + | ->first | ||
| + | elapsedtime asint @seededSinRand01 <-last <-first sub mul <-first add asint | ||
| + | |||
| + | : | ||
| + | elapsedtime asint @seededSinRand01 | ||
| + | |||
| + | : | ||
| + | ->last | ||
| + | ->first | ||
| + | @seededSinRand01 <-last <-first sub mul <-first add asint | ||
| + | |||
| + | : | ||
| + | # abs <-power pow <-add add sin <-sinMul mul dup floor sub | ||
| + | 1.05 pow 99419 sub sin 619 mul dup floor sub | ||
| + | </ | ||
| + | |||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | |||
| + | ===== Pseudo RNG based on Linear congruential generator (LCG) ===== | ||
| + | |||
| + | The downside of the above sinus based functions, is that they have few resulting digits. They are more than adequate to pick a random cell on a map (max 512 possibilities), | ||
| + | |||
| + | The below LCG functions should work for up to 6 digits = 10^6, but I've only done a test up to 10^5. Rolling 1 million random integers between 0 and 10^5 with @lcgRandInt, | ||
| + | |||
| + | <hidden click here for source code> | ||
| + | |||
| + | <code LinearCongruentialGenerator.4rpl> | ||
| + | # Quick Example. | ||
| + | 0 10000 @lcgRandInt | ||
| + | |||
| + | :lcgRandInt # INPUT: integer first randInt + integer last randInt. OUTPUT: an integer in between the first and last randInt, excluding the last randInt. | ||
| + | ->last | ||
| + | ->first | ||
| + | 0 @indexLcgRand01 <-last <-first sub mul <-first add asint | ||
| + | |||
| + | :lcgRand01 # INPUT: none. | ||
| + | 0 @indexLcgRand01 | ||
| + | |||
| + | : | ||
| + | ->last | ||
| + | ->first | ||
| + | @indexLcgRand01 <-last <-first sub mul <-first add asint | ||
| + | |||
| + | : | ||
| + | # The random numbers will be generated with the previous seed that is stored under that index. | ||
| + | ->i | ||
| + | < | ||
| + | <-i < | ||
| + | 1 -> | ||
| + | else | ||
| + | < | ||
| + | endif | ||
| + | |||
| + | : | ||
| + | < | ||
| + | < | ||
| + | |||
| + | : | ||
| + | ->last | ||
| + | ->first | ||
| + | elapsedtime dup 10 log ceil 7 sub neg 10 swap pow mul asint < | ||
| + | |||
| + | : | ||
| + | elapsedtime dup 10 log ceil 7 sub neg 10 swap pow mul asint < | ||
| + | |||
| + | : | ||
| + | ->last | ||
| + | ->first | ||
| + | @seededLcgRand01 <-last <-first sub mul <-first add asint | ||
| + | |||
| + | : | ||
| + | asint 1103515245 mul 12345 add abs asfloat 2147483647 div 10 mul dup floor sub | ||
| + | |||
| + | :once | ||
| + | # Creating lists and a starting mapconstant for the seed sequences. | ||
| + | createlist -> | ||
| + | createlist -> | ||
| + | getmapsize 2 div swap 2 div swap dup2 getterrain 1 add dup 99999 floodfillterrain getlistcount -> | ||
| + | # <-SEED -> | ||
| </ | </ | ||