Random Sequence Generator
by Gibby · in Torque 3D Professional · 03/08/2014 (10:58 am) · 11 replies
Greets all;
I'm submitiing an entry for the PDL game jame and as the title suggests, I'm wondering if anyone has implemented a Random Sequence Generator in TorqueScript.
What I need to do is:
Define range of numbers range
generate n unique numbers within the range .
What I need to do is pick 12 random models from a selection of 36 without duplicates.
I thought of adding this function:
www.cplusplus.com/reference/algorithm/random_shuffle/
but if I could do it in TorqueScript it would be easier to share with non-coders...
I'm submitiing an entry for the PDL game jame and as the title suggests, I'm wondering if anyone has implemented a Random Sequence Generator in TorqueScript.
What I need to do is:
Define range of numbers range
generate n unique numbers within the range .
What I need to do is pick 12 random models from a selection of 36 without duplicates.
I thought of adding this function:
www.cplusplus.com/reference/algorithm/random_shuffle/
but if I could do it in TorqueScript it would be easier to share with non-coders...
#2
EDIT:
Here's the code sample if you're too lazy to link (I've edited it a little)
03/09/2014 (3:33 pm)
Adjust my second code sample in this resource to return the values you need, making use of the engine's random deck will help you out here. :)EDIT:
Here's the code sample if you're too lazy to link (I've edited it a little)
String generateNRNumberString(S32 min, S32 max, S32 amount, String tokenStr) {
if(((max - min)+1) < amount) {
Con::errorf("generateNRNumberString: Cannot generate NR number string with given max/min/amount parameters");
return "";
}
String out;
//Generate the number list.
MRandomDeck<S32> mVals;
for(S32 i = min; i <= max; i++) {
mVals.addToPile(i);
}
mVals.shuffle();
//Pull 'amount' values from the list.
S32 currentItem;
for(S32 i = 0; i < amount; i++) {
mVals.draw(¤tItem);
out += String::toString("%i", currentItem);
if(i != amount-1) {
out += tokenStr;
}
}
return out;
}
#3
Before I had a chance to try either solution I changed my needs. What I've done is create 24 tiles, now I need to choose 16 unique tiles out of the 24...
Last night I tried using an ArrayObject to generate the sequnce, but in my over-caffienated state have had no luck. Any suggestions on how to do this in torqueScript?
[edit]FWIW I thought about using the ArrayOject because I want to procedurally ruin the city later ;P
03/10/2014 (6:57 am)
Wow, thanks guys!Before I had a chance to try either solution I changed my needs. What I've done is create 24 tiles, now I need to choose 16 unique tiles out of the 24...
Last night I tried using an ArrayObject to generate the sequnce, but in my over-caffienated state have had no luck. Any suggestions on how to do this in torqueScript?
[edit]FWIW I thought about using the ArrayOject because I want to procedurally ruin the city later ;P
#4
Forgot to post my ArrayObject attempt. This generates the array just fine, I just can't figure out how to generate the unique numerical names. I guess the hardest part of a game jam is staying conscious...
03/10/2014 (7:29 am)
doh!Forgot to post my ArrayObject attempt. This generates the array just fine, I just can't figure out how to generate the unique numerical names. I guess the hardest part of a game jam is staying conscious...
function generateTiles(%range, %count)
{
//%range is total number of tiles
//%count is number of tiles to be used
echo( " >> randomCity.cs->generateTiles range " @ %range @ " count: " @%count);
//create the array
%array = new ArrayObject(tileArray) {};
MissionCleanup.add(%array);
//Atile is a 128 x 128 section of city - we'll assign it a prefab number here.
for (%tile = 1; %tile <= %count; %tile++)
{
//generate a random number within the range
%random = getRandom(1, %range);
echo( " >> randomCity.cs->generateTiles value for random is: " @%random);
//tileArray.add(%tile, %random);//Obviously, adding here works but the numbers aren't unique
//check for duplicates
for (%i = 1; %i <= %tile; %i++)
{
%val = tileArray.getValue(%i);
echo( " >> randomCity.cs->generateTiles index is: "@%i@" value is: " @%val);
//If we have a dupe, skip and go to the next
if(%val $= %random)
{
echo( " >> randomCity.cs->generateTiles val "@%val@" $= random "@%random);
continue;
}
else
{
//Add the unique number to the array
tileArray.add(%tile, %random);
%test = tileArray.getValue(%tile);
echo( " >> randomCity.cs->generateTiles tileArray index "@%tile@" value is "@%test);
}
}
}
}
#5
03/10/2014 (10:03 am)
Try this out. You load your array with the tile numbers, pick a random one and save it to a sequence, then erase it from the array.function generateTiles(%range, %count)
{
//%range is total number of tiles
//%count is number of tiles to be used
%array = new ArrayObject(tileArray);
MissionCleanup.add(%array);
//fill the array with tile numbers
for(%tile = 1; %tile <= %range; %tile++)
{
tileArray.add(%tile, %null);
}
for(%i = 0; %i < %count; %i++)
{
%index = getRandom(0, %range-1);
%sequenceList[%i] = tileArray.getKey(%index);
tileArray.erase(%index);
%range--;
}
for(%i = 0; %i < %count; %i++)
{
echo(%sequenceList[%i]);
}
}
#7
03/10/2014 (12:00 pm)
template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last,
RandomNumberGenerator& gen)
{
iterator_traits<RandomAccessIterator>::difference_type i, n;
n = (last-first);
for (i=n-1; i>0; --i) {
swap (first[i],first[gen(i+1)]);
}
}You understand this, right? Sort the array randomly, swapping the elements to the top of the range - then when it's done take n elements from the start of your range as your set. If you're swapping array members you can't possibly get duplicates unless there are duplicate elements in the array.
#8
Yeah, I understand it, swapping is the foolproof way but after adding the code to my project I couldn't seem to access it from TorqueScript...
03/10/2014 (12:11 pm)
@Richard:Yeah, I understand it, swapping is the foolproof way but after adding the code to my project I couldn't seem to access it from TorqueScript...
#9
03/10/2014 (12:42 pm)
Ah - how are you accessing it from script? Do you have an engine-side data structure you're iterating through? Is it exposed to script?
#11
I now have to randomly rotate and then spawn them in-game, but that'll be after a long nap...
03/10/2014 (2:42 pm)
Okay, after considerable help from Sean Rice, and borrowing from Joseph Mueller, I got it working, and added extensibility to it so I can make it more procedural later...function generateCity(%range, %count)
{
//echo( " >> randomCity.cs->generateCity called: range " @ %range @ " count: " @%count);
//scriptObject here that we'll unhook later and add to theLevelInfo
//or alternately, parse the file names from a folder and assemble into this list...
if(theLevelInfo.tileList $= "")
%tileList = new ScriptObject(TileList)
{
key[1] = "tileA.prefab";
key[2] = "tileB.prefab";
key[3] = "tileC.prefab";
key[4] = "tileD.prefab";
key[5] = "tileE.prefab";
key[6] = "tileF.prefab";
key[7] = "tileG.prefab";
key[8] = "tileH.prefab";
key[9] = "tileI.prefab";
key[10] = "tileJ.prefab";
key[11] = "tileK.prefab";
key[12] = "tileL.prefab";
key[13] = "tileM.prefab";
key[14] = "tileN.prefab";
key[15] = "tileO.prefab";
key[16] = "tileP.prefab";
key[17] = "tileQ.prefab";
key[18] = "tileR.prefab";
key[19] = "tileS.prefab";
key[20] = "tileT.prefab";
key[21] = "tileU.prefab";
key[22] = "tileV.prefab";
key[23] = "tileW.prefab";
key[24] = "tileX.prefab";
};
else
%tileList = theLevelInfo.tileList;
//setup a list of placeholders we'll delete later
for(%i = 1; %i <= %count;%i++)
{
%temp[%i] = %tileList.key[%i];
}
//crate the array
if(!isObject(cityArray))
%cityArray = new ArrayObject(cityArray) {};
MissionCleanup.add(%cityArray);
//add new elements to the array for each number of the count
%dex = 0;
while(%dex < %count)
{
//cycle through the numbers within our range
for (%r = 1;%r <= %range;%r++)
{
%number = getRandom(1, %range);
if (%temp[%number] $= "")
continue;
else
{
%dex++;
if(%dex > %count)
break;
cityArray.add(%dex,%temp[%number]);
%temp[%number] = "";
}
}
}
}I now have to randomly rotate and then spawn them in-game, but that'll be after a long nap...
Torque Owner Daniel Buckmaster
T3D Steering Committee
function swapWords(%string, %w0, %w1) { %stash = getWord(%string, %w0); %string = setWord(%string, %w0, getWord(%string, %w1)); %string = setWord(%string, %w1, %stash); return %string; } $str = swapWords("hello world", 0, 1);