Jump to content

random number generator help (weidu)


smeagolheart

Recommended Posts

Argent77's code seems to be doing exactly what I was looking for.

 

The only thing left is to modularize it so it can be used to handle different lists of numbers. Need to track the count numbers of goblins, drow, beholders, and whatever my ever expanding list of creatures and classifications ends up being. As I'm reading the creature files, they won't all go in order either so one creature will call one set and maybe the next will call a different counter...

 

I think maybe a header for the variables is the way to go, unless that's dumb and I should do something else.

 

Like adjust this:

	OUTER_SET randomRangeMin  = 0     // lower bound
	OUTER_SET randomRangeMax  = 1     // upper bound
	OUTER_SET randomNumValues = 0     // internally used to keep track of spent values
	OUTER_SET randomResult    = randomRangeMin // contains the random value from the last GetUniqueRandom call

to something like this:

	OUTER_SET %tempvar%randomRangeMin  = 0     // lower bound
	OUTER_SET %tempvar%randomRangeMax  = 1     // upper bound
	OUTER_SET %tempvar%randomNumValues = 0     // internally used to keep track of spent values
	OUTER_SET %tempvar%randomResult    = randomRangeMin // contains the random value from the last GetUniqueRandom call

and then

OUTER_SPRINT ~tempvar ~ ~Halflings~

(call the random macro)

then

OUTER_SPRINT ~tempvar ~ ~Ghosts~

(call the random macro)

 

then

OUTER_SPRINT ~tempvar ~ ~Goblins~

(call the random macro)

etc

etc

etc

 

That look like a good way to go then?

Link to comment

Setting a dynamic variable name can be done with the EVAL keyword:

OUTER_TEXT_SPRINT race ~halfling~
OUTER_SET EVAL "%race%randomRangeMin"  = 0
OUTER_SET EVAL "%race%randomRangeMax"  = 8
OUTER_SET EVAL "%race%randomNumValues" = 0
OUTER_SET EVAL "%race%randomResult"    = EVAL "%race%randomRangeMin"   // not sure if this is possible
You also have to update the relevant variable names in the macro definition.

 

Alternatively you can try to sort the groups by race beforehand. Then you don't need to change variable names at all. Just reinitialize the required variables before starting a new group:

// Halflings
OUTER_SET randomRangeMin  = 0  // you probably set this only once
OUTER_SET randomRangeMax  = 8  // set for each group
OUTER_SET randomNumValues = 0  // to force reinitialization of randomizer
// calling macro...

// Ghosts
OUTER_SET randomRangeMax  = 12 // set for each group
OUTER_SET randomNumValues = 0  // to force reinitialization of randomizer
// calling macro...

// and so on...
Link to comment
BACKUP ~test/backup~
AUTHOR ~Smeagolheart~
VERSION ~1.0~

BEGIN ~Test~
	DESIGNATED 0


// Global definitions
//OUTER_SET rndRangeMin  = 0     	// lower bound   <- this var will always be one and never change.  I removed it..
//OUTER_SET rndRangeMax  = 1     	// upper bound  <- equiv to EVAL "%S9Description%_max" in my code at the moment..
//RANDOM_SEED 1234          		// uncomment and set to get reproducible results

// Returns a rnd value in "rndResult" that does not repeat until all values of the defined range have been spent
DEFINE_ACTION_MACRO GetUniqueRandom
BEGIN
	LOCAL_SET idx = 0
	//LOCAL_SET rangeCount = EVAL "%S9Description%_max" - 1   // do we need this variable? or just adjust the OUTER_WHILE below..
	LOCAL_SET value = 0

	ACTION_IF (rndNumValues = 0) BEGIN
		LOG ~DEBUG: Initializing Random list~
		OUTER_WHILE (rndNumValues < EVAL "%S9Description%_max") BEGIN
			OUTER_SET value = RANDOM(1 EVAL "%S9Description%_max") // RANDOM(1 rndRangeMax)
			OUTER_FOR (idx = 0; idx < rndNumValues; ++idx) BEGIN
				ACTION_IF (EVAL "rndArray_%idx%" = value) BEGIN
					OUTER_SET value = 0 - 1							// not sure what we're doing here other than ensuring next action_if is skipped
					OUTER_SET idx = rndNumValues
					END
				END
				ACTION_IF (value >= 1) BEGIN
					OUTER_SET EVAL "rndArray_%rndNumValues%" = value
					OUTER_SET rndNumValues += 1
					END
			END
		END
	OUTER_SET rndNumValues -= 1
	OUTER_SET rndResult = EVAL "rndArray_%rndNumValues%"	// contains the new rnd value
END

OUTER_SET rndNumValues = 0     	// internally used to keep track of spent values
									// * I will need unique ones of these right?  %S9Description%rndNumValues
OUTER_SET rndResult    = 0		// contains the rnd value from the last GetUniquernd call
									// * I will need unique ones of these right?  %S9Description%rndResult

//OUTER_SET rndRangeMax = 8
OUTER_SET ffmale_max 		= 5
OUTER_SET fff_max 			= 6
OUTER_FOR (idx = 0; idx < 30; ++idx) BEGIN
	OUTER_SPRINT ~S9Description~ ~ffmale~
	LAM GetUniqueRandom
	PRINT ~Random value A: %rndResult%~
	OUTER_SPRINT ~S9Description~ ~fff~
	LAM GetUniqueRandom
	LOG ~B: %rndResult%~
END


EDIT:

Here's what I have at the moment. I've hosed something up.

Link to comment

Using dynamic variable declarations is somewhat tricky and takes some time to get used to it. Give this code a try:

 

 

/**
 * Returns a random value in "%group%_result" that does not repeat until all values of the defined range 
 * have been spent.
 *
 * You need to set the following variables beforehand:
 * OUTER_SET EVAL "%group%_min" = 0     // lower bound
 * OUTER_SET EVAL "%group%_max" = 0     // upper bound
 * More relevant variables:
 * OUTER_SET EVAL "%group%_remain" = 0  // internally used to keep track of spent values for that group
 * OUTER_SET EVAL "%group%_result" = 0  // the random value from the last GetUniqueRandom call
 * RANDOM_SEED 1234                     // set to get reproducible results
 */
DEFINE_ACTION_MACRO GetUniqueRandom
BEGIN
  // must always be set first
  LOCAL_SET rndMin = 0
  LOCAL_SET rndMax = 0
  LOCAL_SET rndRemain = 0
  LOCAL_SET rangeCount = 0
  LOCAL_SET idx = 0
  LOCAL_SET value = 0

  ACTION_IF (NOT VARIABLE_IS_SET EVAL "%group%_min" OR
             NOT VARIABLE_IS_SET EVAL "%group%_max")
  BEGIN
    FAIL ~Lower or upper bound not defined.~
  END

  ACTION_IF (NOT VARIABLE_IS_SET EVAL "%group%_remain") BEGIN
    OUTER_SET EVAL "%group%_remain" = 0
  END

  OUTER_SET rndMin = EVAL "%group%_min"
  OUTER_SET rndMax = EVAL "%group%_max"
  OUTER_SET rndRemain = EVAL "%group%_remain"
  OUTER_SET rangeCount = rndMax - rndMin + 1

  // array initialization
  ACTION_IF (rndRemain = 0) BEGIN
    LOG ~DEBUG: Initializing random list: %group%~

    OUTER_WHILE (rndRemain < rangeCount) BEGIN
      OUTER_SET value = RANDOM (rndMin rndMax)
      OUTER_FOR (idx = 0; idx < rndRemain; ++idx) BEGIN
        ACTION_IF (EVAL "%group%Array_%idx%" = value) BEGIN
          OUTER_SET value = rndMin - 1
          OUTER_SET idx = rndRemain
        END
      END
      ACTION_IF (value >= rndMin) BEGIN
        OUTER_SET EVAL "%group%Array_%rndRemain%" = value
        OUTER_SET rndRemain += 1
      END
    END
  END

  // "%group%_result" contains the new random value
  OUTER_SET rndRemain -= 1
  OUTER_SET EVAL "%group%_remain" = rndRemain
  OUTER_SET EVAL "%group%_result" = EVAL "%group%Array_%rndRemain%"
END

 

An a test sequence:

 

 

OUTER_TEXT_SPRINT gnomes ~gnomes~
OUTER_SET EVAL "%gnomes%_min" = 0
OUTER_SET EVAL "%gnomes%_max" = 3

OUTER_TEXT_SPRINT elves ~elves~
OUTER_SET EVAL "%elves%_min" = 0
OUTER_SET EVAL "%elves%_max" = 7

OUTER_FOR (idx = 0; idx < 24; ++idx) BEGIN
  OUTER_TEXT_SPRINT group ~%elves%~
  LAM GetUniqueRandom
  OUTER_SET value = EVAL "%group%_result"
  PRINT ~%group% value #%idx%: %value%~

  OUTER_TEXT_SPRINT group ~%gnomes%~
  LAM GetUniqueRandom
  OUTER_SET value = EVAL "%group%_result"
  PRINT ~%group% value #%idx%: %value%~
END

 

Link to comment

Perfect argent77. I took out the _min number since it's a constant 1 for all my groups. All 39 groups I currently have start at 1 and I don't want to specify that.

 

Thanks a lot argent77, lynx and all.

 

Here's the code with the last tinkering:

 

Thanks again..

/**
 * Returns a random value in "%group%_result" that does not repeat until all values of the defined range 
 * have been spent.
 *
 * You need to set the following variables beforehand:
 * OUTER_SET EVAL "%group%_min" = 0     // lower bound
 * OUTER_SET EVAL "%group%_max" = 0     // upper bound
 * More relevant variables:
 * OUTER_SET EVAL "%group%_remain" = 0  // internally used to keep track of spent values for that group
 * OUTER_SET EVAL "%group%_result" = 0  // the random value from the last GetUniqueRandom call
 * 
 */
DEFINE_ACTION_MACRO GetUniqueRandom
BEGIN	
	// Code Courtesy of argent77 based on idea by lynx @ Gibberlings3 forum.
	// must always be set first
	LOCAL_SET rndMin = 1
	LOCAL_SET rndMax = 0
	LOCAL_SET rndRemain = 0
	LOCAL_SET rangeCount = 0
	LOCAL_SET idx = 0
	LOCAL_SET value = 0

	ACTION_IF (NOT VARIABLE_IS_SET EVAL "%group%_max")
	BEGIN
		FAIL ~Upper bound not defined.~
	END

	ACTION_IF (NOT VARIABLE_IS_SET EVAL "%group%_remain") BEGIN
		OUTER_SET EVAL "%group%_remain" = 0
	END

	//OUTER_SET rndMin = EVAL "%group%_min"
	OUTER_SET rndMax = EVAL "%group%_max"
	OUTER_SET rndRemain = EVAL "%group%_remain"
	OUTER_SET rangeCount = rndMax - rndMin + 1

	// array initialization
	ACTION_IF (rndRemain = 0) BEGIN
		LOG ~DEBUG: Initializing random list: %group%~

		OUTER_WHILE (rndRemain < rangeCount) BEGIN
			OUTER_SET value = RANDOM (rndMin rndMax)
			OUTER_FOR (idx = 0; idx < rndRemain; ++idx) BEGIN
				ACTION_IF (EVAL "%group%Array_%idx%" = value) BEGIN
					OUTER_SET value = rndMin - 1
					OUTER_SET idx = rndRemain
				END
			END
			ACTION_IF (value >= rndMin) BEGIN
				OUTER_SET EVAL "%group%Array_%rndRemain%" = value
				OUTER_SET rndRemain += 1
			END
		END
	END
	// "%group%_result" contains the new random value
	OUTER_SET rndRemain -= 1
	OUTER_SET EVAL "%group%_remain" = rndRemain
	OUTER_SET EVAL "%group%_result" = EVAL "%group%Array_%rndRemain%"
END	
	//RANDOM_SEED 1234                     // set to get reproducible results
	RANDOM_SEED ~Last~                     // set to get reproducible results
	OUTER_TEXT_SPRINT gnomes ~gnomes~
	OUTER_SET EVAL "%gnomes%_max" = 4

	OUTER_TEXT_SPRINT elves ~elves~
	OUTER_SET EVAL "%elves%_max" = 7

	OUTER_FOR (idx = 0; idx < 24; ++idx) BEGIN
		OUTER_TEXT_SPRINT group ~%elves%~
		LAM GetUniqueRandom
		OUTER_SET value = EVAL "%group%_result"
		PRINT ~%group% value #%idx%: %value%~

		OUTER_TEXT_SPRINT group ~%gnomes%~
		LAM GetUniqueRandom
		OUTER_SET value = EVAL "%group%_result"
		PRINT ~%group% value #%idx%: %value%~
	END
Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...