User Tools

Site Tools


cw4:4rpl_tools

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
cw4:4rpl_tools [2025/06/28 18:36] – [Next UseFul Function goes here] kallicw4:4rpl_tools [2025/08/29 21:04] (current) – [Pseudo RNG based on Linear congruential generator (LCG)] kalli
Line 3857: Line 3857:
  
  
-===== Pseudo Random Number Generator, type LCG =====+===== Pseudo Random Number Generator, based on sinus =====
  
 <hidden click here for source code> <hidden click here for source code>
  
-basic function to request a pseudo random number, based on the Linear Congruential Generator algorithm: https://en.wikipedia.org/wiki/Linear_congruential_generator+Several basic functions based on Grabz' rng lite function of "<-seed sinus 10000 mul dup floor sub".
  
  
-Input is an integer seed + the desired amount of digits+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.
  
  
-If you want no truncation, then use 0 for the desired amount of digitsIf you request more digits than your seed would generatethen the too short result is returned without truncation+Difference between the functions: 
 +  * "seeded": provide a seed to the generatorThe generated number will always be the same for the same seed
 +  * "index": these seeds are sequenced. In the same map for the same index, the generated number 1,2,3,... will be the same after map restart. 
 +  * "spiked": the generator is seeded with the elapsedtime of the gaming session, making the outcome uncontrollable. 
 +  * No prefix: these are sequenced seeds and they use index 0
  
-<code 4rpl file name.4rpl> +Example code with messages: 
-1111 @linearPRNG trace+<code example.4rpl> 
 +12345 ->int 
 +1 ->index 
 +0 ->first 
 +100 ->last # The last integer itself will be excluded. 
 +"sinRandInt" <-first <-last 2 listN sendmsg 
 +<-*sinRandInt trace 
 +"sinRand01" 0 sendmsg 
 +<-*sinRand01 trace 
 +"indexSinRandInt" <-index <-first <-last listN sendmsg 
 +<-*sinRandInt trace 
 +"indexSinRand01" <-index sendmsg 
 +<-*sinRand01 trace 
 +"spikedSinRandInt" <-first <-last 2 listN sendmsg 
 +<-*sinRandInt trace 
 +"spikedSinRand01" 0 sendmsg 
 +<-*sinRand01 trace 
 +"seededSinRandInt" <-seed <-first <-last 3 listN sendmsg 
 +<-*sinRandInt trace 
 +"seededSinRand01" <-seed sendmsg 
 +<-*sinRand01 trace 
 +</code>
  
-:linearPRNG  +---- 
-# INPUT: INTEGER SEED INTEGER for desired digit length->digits = no truncating of the output.  + 
-# OUTPUT: A pseudo random integer number of the desired length+<code SinusRNG.4rpl> 
-https://en.wikipedia.org/wiki/Linear_congruential_generator +:once 
-dup ->digits if + # Creating lists and a starting mapconstant for the seed sequences. 
- 16807 mul 2 31 pow 1 sub mod2 dup log10 ceil <-digits dup2 gt if sub 10 swap pow div asint else pop pop endif + createlist ->prevSeedList 
-else + createlist ->seedCountList 
- 16807 mul 2 31 pow 1 sub mod2  + getmapsize 2 div swap 2 div swap dup2 getterrain 1 add dup 99999 floodfillterrain getlistcount ->mapConstant 
-endif+  
 + # Setting up the messages so that other scripts can request a random seed. 
 + "sinRandInt" "sinRandInt_CALL" registerformsg 
 + "sinRand01" "sinRand01_CALL" registerformsg 
 + "indexSinRandInt" "indexSinRandInt_CALL" registerformsg 
 + "indexSinRand01" "indexSinRand01_CALL" registerformsg 
 + "spikedSinRandInt" "spikedSinRandInt_CALL" registerformsg 
 + "spikedSinRand01" "spikedSinRand01_CALL" registerformsg 
 + "seededSinRandInt" "seededSinRandInt_CALL" registerformsg 
 + "seededSinRand01" "seededSinRand01_CALL" registerformsg 
 + 
 +:sinRandInt_CALL 
 + <-_DATA listtostack @sinRandInt ->*sinRandInt 
 +:sinRand01_CALL 
 + @sinRand01 ->*sinRand01 
 +:indexSinRandInt_CALL 
 + <-_DATA listtostack @indexSinRandInt ->*sinRandInt 
 +:indexSinRand01_CALL 
 + <-_DATA @indexSinRand01 ->*sinRand01 
 +:spikedSinRandInt_CALL 
 + <-_DATA listtostack @spikedSinRandInt ->*sinRandInt 
 +:spikedSinRand01_CALL 
 + @spikedSinRand01 ->*sinRand01 
 +:seededSinRandInt_CALL 
 + <-_DATA listtostack @seededSinRandInt ->*sinRandInt 
 +:seededSinRand01_CALL 
 + <-_DATA @seededSinRand01 ->*sinRand01 
 + 
 +:sinRandInt # INPUT: integer first randInt integer last randIntOUTPUT: 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 
 + 
 +:indexSinRandInt # INPUT: the index of the seed sequence + integer first randInt + integer last randInt. OUTPUT: an integer in between the first and last randInt, excluding the last randInt
 +->last 
 +->first 
 + @indexSinRand01 <-last <-first sub mul <-first add asint 
 + 
 +:indexSinRand01 INPUT: the "index" of the seed sequence. OUTPUT: the next seed from that sequence. 
 +# The random numbers will be generated with the previous seed that is stored under that index. 
 +->i 
 + <-prevSeedList[<-i] eq0 if 
 + <-i <-mapConstant add 2357 mul @seededSinRand01 dup 10000000 mul 1 add asint ->prevSeedList[<-i] 
 + 1 ->seedCountList[<-i] 
 + else 
 + <-prevSeedList[<-i] @seededSinRand01 dup 10000000 mul <-seedCountList[<-i] 1 add dup ->seedCountList[<-i] add asint ->prevSeedList[<-i] 
 + endif 
 +  
 +:spikedSinRandInt # INPUT: integer first randInt + integer last randInt. OUTPUT: an integer in between the first and last randInt, excluding the last randInt
 +->last 
 +->first 
 + elapsedtime asint @seededSinRand01 <-last <-first sub mul <-first add asint  
 +  
 +:spikedSinRand01 
 + elapsedtime asint @seededSinRand01 
 + 
 +:seededSinRandInt INPUTinteger seed + integer first randInt + integer last randIntOUTPUT: an integer in between the first and last randInt, excluding the last randInt
 +->last 
 +->first 
 + @seededSinRand01 <-last <-first sub mul <-first add asint 
 + 
 +:seededSinRand01 
 + # abs <-power pow <-add add sin <-sinMul mul dup floor sub 
 + 1.05 pow 99419 sub sin 619 mul dup floor sub 
 +</code> 
 + 
 +</hidden> 
 + 
 +---- 
 + 
 + 
 +===== 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), but unsuited for generating random numbers larger than a few thousand.  
 + 
 +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, missed only 8 possible results. The same test with @sinRandInt missed 42458 possible results. 
 + 
 +<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 
 + 
 +:indexLcgRandInt # INPUT: the index of the seed sequence + integer first randInt + integer last randInt. OUTPUT: an integer in between the first and last randInt, excluding the last randInt. 
 +->last 
 +->first 
 + @indexLcgRand01 <-last <-first sub mul <-first add asint 
 + 
 +:indexLcgRand01 # INPUT: the "index" of the seed sequence. OUTPUT: the next seed from that sequence. 
 +# The random numbers will be generated with the previous seed that is stored under that index. 
 +->i 
 + <-prevSeedList[<-i] eq0 if 
 + <-i <-mapConstant add 13 mul @seededLcgRand01 dup 10000000 mul 1 add asint ->prevSeedList[<-i] 
 + 1 ->seedCountList[<-i] 
 + else 
 + <-prevSeedList[<-i] @seededLcgRand01 dup 10000000 mul <-seedCountList[<-i] 1 add dup ->seedCountList[<-i] add asint ->prevSeedList[<-i] 
 + endif 
 + 
 +:clearIndexSinLcgRand 
 + <-seedCountList clearlist 
 + <-prevSeedList clearlist 
 + 
 +:spikedLcgRandInt # INPUT: integer first randInt + integer last randInt. OUTPUT: an integer in between the first and last randInt, excluding the last randInt. 
 +->last 
 +->first 
 + elapsedtime dup 10 log ceil 7 sub neg 10 swap pow mul asint <-spikedLcgAdd 1 add dup ->spikedLcgAdd mul @seededLcgRand01 <-last <-first sub mul <-first add asint 
 +  
 +:spikedLcgRand01 
 + elapsedtime dup 10 log ceil 7 sub neg 10 swap pow mul asint <-spikedLcgAdd add dup ->spikedLcgAdd mul @seededLcgRand01 
 + 
 +:seededLcgRandInt # INPUT: integer seed + integer first randInt + integer last randInt. OUTPUT: an integer in between the first and last randInt, excluding the last randInt. 
 +->last 
 +->first 
 + @seededLcgRand01 <-last <-first sub mul <-first add asint 
 + 
 +:seededLcgRand01 
 + 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 ->prevSeedList 
 + createlist ->seedCountList 
 + getmapsize 2 div swap 2 div swap dup2 getterrain 1 add dup 99999 floodfillterrain getlistcount ->mapConstant  
 + # <-SEED ->mapconstant # Alternative for map constant.
 </code> </code>
  
cw4/4rpl_tools.1751135774.txt.gz · Last modified: 2025/06/28 18:36 by kalli