HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

I need help with a really weird trigger...

01-23-2004, 06:52 AM#1
Dark_Baron_Prot
Can somebody help me with this trigger..

I want to make it so when a unit enters an area (75 in total) the game will pick a random number between 1 and 74. now thats not the confusing part, I need it so each time they enter an area, the same number can't be used again.

For example..

the first time they enter an area, it might pick random number 30, but after that, 30 can not be used again, I need to do this untill all 75 numbers are used...

Can this be done, and if so, does anybody have this trigger, or know how to make it?

Thanks.
01-23-2004, 07:02 AM#2
Krakou
I would try something like this:
- create 75 dummy units called 1,2,3...75
- place this units in a hidden corner of the map
- at map initialization add this units in a group
- when a unit enters a region pick a random unit in the group and use convert string(unitname) to integer
- remove the picked unit from the group

Haven't tried but should work.
01-23-2004, 07:08 AM#3
Dark_Baron_Prot
thats a good idea,, thanks

and yet so simple...
01-23-2004, 07:10 AM#4
Bulletcatcher
Here's what I'd do.

First, I'd make an array of booleans 'numberUsed', size 74.

When a random number is to be chosen, it first picks one and then checks the corresponding boolean. if the boolean is 'false', fine, do whatever the trigger does and set that boolean to 'true'. If, however, the boolean is already 'true', pick a new random number and check that one instead, regenerating numbers until you get one that hasn't been used.

75 units on the map would create more lag than a simple array, for one thing.
01-23-2004, 07:19 AM#5
SektorGaza
Quote:
Originally posted by Bulletcatcher
Here's what I'd do.

First, I'd make an array of booleans 'numberUsed', size 74.

When a random number is to be chosen, it first picks one and then checks the corresponding boolean. if the boolean is 'false', fine, do whatever the trigger does and set that boolean to 'true'. If, however, the boolean is already 'true', pick a new random number and check that one instead, regenerating numbers until you get one that hasn't been used.

75 units on the map would create more lag than a simple array, for one thing.


i think that's much wiser lol
01-23-2004, 07:54 AM#6
Krakou
I agree that's better. :D
01-23-2004, 08:45 AM#7
Grater
Um there is a really easy and effective way:
Create an array of integers, set the values in the array 1 to 74.

for each integer A from 1 to 74
set array[Integer A] = Integer A

Have another integer count = 74
You'll also need a couple of temporary integers here I use i and tempint.

then when you want a random number do this:

set i = random number between 1 and count
set tempint = array[i]
set array[i] = array[count]
set count = count - 1

tempint now holds your unique random number.

This method is about as simple as it gets and reliable. Altough unlikely it would be possible for bulletcatchers method to break your map, for if it keeps "missing" it might run long enough that WC3 will forcefully terminate the trigger with unpredictable consequences (the chances of this become very high when theres only a few random numbers left)
01-23-2004, 10:29 AM#8
Scarlet-Russian
it's best to use the boolean array method, but instead pick a random number only once, then count from that number up to 74 (while checking), then count from 0 to that number, checking if its picked.
01-23-2004, 09:33 PM#9
Grater
uh no it's not. My method uses 2 variables and to get a random number involves a guaranteed four lines of code with no loop involved.

I'll demonstrate how simple it is because this is an important method - altough understanding the method is not nessecary to be able to use it.

Say you want unique random numbers between 1 and 9. Start with an array of all the numbers:
123456789
Choose a random position in the array, lets say "3", in that position is "3". Now we swap it with the number at the end of the array and reduce the length of the available-number array by one.
12945678|3 3

Now choose one between 1 and 8, lets say "1".
8294567|13 1

Then 6
829457|613 6
A number between 1 and 7, lets say 3 again. In that position is 9.
82745|9613 9
A number between 1 and 5, lets say 5. The swap swaps 5 with itself - no problem.
8274|59613 5
824|759613 7
82|4759613 4
2|84759613 8
|284759613 2

No more numbers available, altough you can always just restart the process.

As you can see the method uses a single array, at the front of the array is numbers which havn't been used, and at the end of the array are the numbers that have been used, the "count" variable is a marker dividing the two parts of the array.

This method can just as easily be used to randomize the order of elements in an array - in the example above changing the order from 123456789 to 284759613, but they dont have to be integers in an array - they could be unit types for example.

The astute reader will notice I dont actually do the full swap in my earlier code, if all you want is unique random numbers the contents of the end of the array don't matter.
01-23-2004, 10:56 PM#10
SektorGaza
grater, now you are going to extremes :), this method is good if you don't need your list of numbers in order and if you don't plan to use it again, but if you do, it becomes a pain
01-23-2004, 11:30 PM#11
Grater
My mind boggles as to how something involving loops can be simpler than something which doesn't.

OMG the fearsome intilization trigger!
Code:
Setup Array
    Events
        Map initialization
    Conditions
    Actions
        Set RandomNumberCount = 74
        For each (Integer A) from 1 to RandomNumberCount, do (Actions)
            Loop - Actions
                Set RandomNumberArray[(Integer A)] = (Integer A)

The uber scary actions to get a random number!!!
Code:
Get Random Number
    Actions
        Set i = (Random integer number between 1 and RandomNumberCount)
        Set TempInt = RandomNumberArray[i]
        Set RandomNumberArray[i] = RandomNumberArray[RandomNumberCount]
        Set RandomNumberArray[RandomNumberCount] = TempInt
        Set RandomNumberCount = (RandomNumberCount - 1)
        -------- TempInt contains your random number --------

I challenge anyone to write shorter, cleaner triggers using the boolean method (the triggers have to work too). The only advantage of the boolean array method is it conceptually slightly easier to understand.

in this thread i advocate this solution for a slightly different problem.
01-24-2004, 01:04 AM#12
RaeVanMorlock
I originally thought of Bulletcatcher's method, understanding that generating an unused unique number towards the end of the process could take considerably longer than in the beginning. After reading Grater's description of his method though, that's gotta be the better choice. No matter how many random numbers you need, it'll take the same amount of time to get each one. I think I actually saw that months ago in an Assembler course.


Quote:
SektorGaza said...
grater, now you are going to extremes :), this method is good if you don't need your list of numbers in order and if you don't plan to use it again, but if you do, it becomes a pain

I don't understand what you're talking about. If you needed to restart the process with the boolean array, you'd need to set each value back to false. If you need to with the integer array, you just need to reset all the values back to their indices.


Anyhoo.. regardless of which method one understands more clearly, the argument comes down to the age-old size over speed problem. The boolean solution, using bit values, would certainly take less memory -- but in the end, the integers would provide better performance. This is if we assume, and I would safely assume, that the any processor in use today would be able to randomly pick an unused index in a somewhat fashionable time using the boolean method. So don't argue which solution is better, just which fits the job better.

There, I've said my peace, I'm going to go watch The Incredible Hulk now. La dee da.
01-24-2004, 02:04 AM#13
|LMM|Duff_Man
Quote:
Originally posted by Dark_Baron_Prot
Can somebody help me with this trigger..

I want to make it so when a unit enters an area (75 in total) the game will pick a random number between 1 and 74. now thats not the confusing part, I need it so each time they enter an area, the same number can't be used again.

For example..

the first time they enter an area, it might pick random number 30, but after that, 30 can not be used again, I need to do this untill all 75 numbers are used...

Can this be done, and if so, does anybody have this trigger, or know how to make it?

Thanks.


is it for a musical chairs kind of thing map?