smeagolheart Posted July 27, 2016 Author Share Posted July 27, 2016 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
argent77 Posted July 27, 2016 Share Posted July 27, 2016 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
smeagolheart Posted July 27, 2016 Author Share Posted July 27, 2016 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
argent77 Posted July 28, 2016 Share Posted July 28, 2016 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
smeagolheart Posted July 28, 2016 Author Share Posted July 28, 2016 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
Recommended Posts
Archived
This topic is now archived and is closed to further replies.