HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

[SNIPPET] PseudoRandom_Index

12-12-2011, 06:09 PM#1
cohadar
Collapse JASS:
library PseudoRandom

globals
    private integer seed = 1
endglobals

//=====================================================================
//  Return pseudorandom integer that can be used as struct/array index
//  Has full number period (8190).
//  Do not change constants - you will get non-optimal period
//=====================================================================
public function Index takes nothing returns integer 
    set seed = seed * 5 + 17
    set seed = ModuloInteger(seed, 8192)
    if seed == 0 then 
        set seed = 17
    elseif seed == 8191 then
        set seed = 12
    endif
    return seed
endfunction

endlibrary

Tested the function with array sorting.
All numbers are there except number 22. (talk about weird math)

Not much but it does its job.
Wish we had a section for jass functions like on that site I used so long ago I can't even remember it's name....
12-12-2011, 10:15 PM#2
tamisrah
Would you care to provide a sample use case? I can't think of any reason to go through the whole index range of an array randomly.

Why wouldn't there be 22? 5+17=22 if im not totally mistaken.

Does this generate each index once? What happens after 8192 steps?


You meant this site?

EDIT:
So this actually generates every possible index exactly once... How the hell did you create a function like this?
I would totally prefer a small tutorial on how to create those functions over this snippet. xD
12-12-2011, 11:15 PM#3
cohadar
Quote:
Originally Posted by tamisrah
Why wouldn't there be 22? 5+17=22 if im not totally mistaken.
Ah ofc, 22 is the first generated number and it got lost because I sorted array from 1 instead of 0.
I guess all numbers are there.

Quote:
Originally Posted by tamisrah
So this actually generates every possible index exactly once... How the hell did you create a function like this?
I would totally prefer a small tutorial on how to create those functions over this snippet. xD
Galois groups, basic algebra really.
Btw 8192 is the biggest Galois group you can create with 32-bit jass integers without getting negative values due to overflow, a really lucky coincidence. :)

Quote:
Originally Posted by tamisrah
Would you care to provide a sample use case? I can't think of any reason to go through the whole index range of an array randomly.
Hashtables are fastest when keys are random and distributed far from each other.

I was hacking around jasshelper and when I saw function vexorian was using for generating hashtable keys I got a headache so I created a proper one.
Than I thought it might be useful to someone in the map as well so I created a jass version too.
12-13-2011, 07:05 AM#4
Anitarf
Unfortunately, array index 8191 can bug out so the effective limit is actually 8190.
12-13-2011, 07:39 AM#5
cohadar
Wasn't that fixed with one of the latest patches?

If not I just need to add one if statement there.

Remind me what was that bug about? Something about campaigns I think...
12-13-2011, 09:32 AM#6
Anitarf
The values stored under that index don't get saved correctly when you save a game or something like that.
12-13-2011, 10:20 AM#7
cohadar
Updated to skip indexes 0 and 8191 because they can be problematic.
12-13-2011, 03:00 PM#8
Anitarf
Okay. Now please also tell me what this is supposed to be useful for.
12-13-2011, 03:53 PM#9
cohadar
Pseudorandom numbers are generally always useful when you want to have random things, but also have them repeat in the exact same order for the same input values.

Remember this option from WE:
File -> Preferences -> Test Map -> Use Fixed Random Seed.

Great stuff for debugging random events.

In vJass compiler it is used for:
Generating random names for 'secret' initstruct functions.
Generating random prefixes for private members of scopes and libraries.
Generating nicely distributed hashtable keys that can also be used as jass array indexes. (keyword key)
12-13-2011, 04:33 PM#10
Bribe
1. InitStruct functions can just use "private keyword initStruct"

2. Random prefixes are handled by the vJass preprocessor

3. Structs generate a unique integer, too, I can't imagine why you'd want the keys 18 and 56, for example, instead of just 1 and 2. However you can easily recycle those whereas there would be a bit of issues trying to recycle with this, including a fairly consistent scraping of the max array bounds which brings a lot of trouble for efficiency. Compare that to structs which keep the indices as low as possible.

I'm not saying this doesn't have some use, it's just that the reasons you gave are not good reasons. Just looking at it sparks creativity for me, I just don't know of anything specific, offhand. I will let you know if something comes to mind.
12-13-2011, 05:19 PM#11
cohadar
Quote:
Originally Posted by cohadar
In vJass compiler it is used for:
Generating random names for 'secret' initstruct functions.
Generating random prefixes for private members of scopes and libraries.
Generating nicely distributed hashtable keys that can also be used as jass array indexes. (keyword key)

That is it is used in the compiler version I am doing right now.

Collapse pascal:
//==============================================================================
//  Some things need to be random, yet compiled map should always be the same.
//  So we use fixed random seed and pseudorandom number generator.
//  Number is kept positive because we use it in random names.
//  It is also always between [1..8190] so it can be used as array index as well
//==============================================================================
unit PseudoRandom

interface

function GetPseudoRandom(): integer
function GetPrivatePrefix(): string
function GetHashtableKey(): string

//==============================================================================
//  WARNING: Do NOT change any constants in this file.
//==============================================================================
implementation
uses SysUtils

var
  name_seed : integer = 1
  key_seed: integer = 1
  alternator: boolean = false

//==============================================================================
//  PRIVATE: generates next pseudo random number for a given seed.
//==============================================================================
procedure NextPseudoRandom(var seed:integer)
begin
  seed := seed * 5 + 17
  seed := seed mod 8192
  if seed < 0 then seed := seed + 8192
  if seed = 0 then seed := 17
  if seed = 8191 then seed := 12
end

//==============================================================================
// This function is called once for every line of text jasshelper parses.
// It is used to generate random names.
// You always get same random names for same script input.   (pseudorandom)
//==============================================================================
function GetPseudoRandom(): integer
begin
  NextPseudoRandom(name_seed)
  Result := name_seed
end

//==============================================================================
//  Pseudo random hashtable keys.
//==============================================================================
function GetHashtableKey:string
begin
  NextPseudoRandom(key_seed)
  Result := IntToStr(key_seed)
end

//==============================================================================
//  Returns random prefix for private stuff in scopes and libraries.
//==============================================================================
function GetPrivatePrefix():string
begin
  if (GetPseudoRandom() mod 2 = 0) then Result := '__'
  else Result := '___'
end                            

end.

EDIT:
In case someone wonders why I put this into jasshelper, it is because Vex was using real random numbers,
That means that you could not test-compare two compiled outputwar3map.j files because you always get different results.
This way same input script always produces same output script.
But if you change a single line of code it changes all random stuff. (names, prefixes, keys)
12-13-2011, 05:51 PM#12
Anitarf
Quote:
Originally Posted by cohadar
Pseudorandom numbers are generally always useful...
Okay, now how about an example of how this resource is specifically useful, especially considering we already have a pseudo-random number generator built into the game.
12-13-2011, 06:06 PM#13
cohadar
The built in generator produces random integers,
this produces random array indexes (in circular fashion, without repeating indexes until it does all 8190).

If you are asking about specific use case in a map I don't know any because resource did not exist before.

But I can bet you now that it does exist someone will come up with a reason to use it.

Replayable Random events in RPG, save/load codes, who knows, there is a lot of crazy people out there.
12-13-2011, 09:18 PM#14
Fledermaus
Quote:
Originally Posted by cohadar
Updated to skip indexes 0 and 8191 because they can be problematic.
Why is 0 problematic?
12-13-2011, 10:06 PM#15
Troll-Brain
He is just following the vJass struct standard :

null instance == 0

Ofc there is no problem of using the index 0 of an array variable by itself.

And for the index 8191, it makes a saved game unabled to be loaded (wc3 crashes), but i have not tested if this lame bug was fixed ot not in the newest patches.