| 01-23-2004, 06:52 AM | #1 |
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 |
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 |
thats a good idea,, thanks and yet so simple... |
| 01-23-2004, 07:10 AM | #4 |
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 | |
Quote:
i think that's much wiser lol |
| 01-23-2004, 07:54 AM | #6 |
I agree that's better. :D |
| 01-23-2004, 08:45 AM | #7 |
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 |
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 |
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 |
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 |
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 | |
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:
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 | |
Quote:
is it for a musical chairs kind of thing map? |
