Creating units randomly in the map

skyblader

You're living only because it's illegal killing.
Reaction score
159
[Solved]Creating units randomly in the map

[SOLVED]

I think it's possible, but is there a simple way to do this? The idea in my head seems unnecessarily long o.o

I was thinking creating the amount of units i want, then set a random point in region, set another random point, check if the region is within ___ range of the other, otherwise set another point within ___ range. It's endless isn't it.

The idea is, create ___ amount of units randomly in the map, and each cannot be too near to each other.
 

DioD

New Member
Reaction score
57
Allocate cells over your map, place cells handles into array.
you dont need any objects, this is pure logic.

if your map is 30*30 cells - then you will have 900 cells total, you will first 900 slots of array with integers 1-900.

to fill array of 8190 you need 90 wide grid, if you want more, you will need multiple arrays or hashtable.

to get cell size, you simply divide you map wide-height by value of cells you want.

then choose random slot of array, create unit inside this cell, remove closest cells from array, repeat.

Draw this on paper, you will see how its easy to do.

after some time you will distribute units around with no units too far and no units too close.

note: this is heavy calculations, i suggest you to allocate 100-200 units per cycle with timer 0.1
 

skyblader

You're living only because it's illegal killing.
Reaction score
159
Okay the numbers here are really big and stuff, which adds on to the confusion I have because I'm new to this cells thing.. could you use simpler values if I tell you , I wanted to spread about 10-20 units around an 84x84 map.
 

TomTTT

New Member
Reaction score
44
I don't think it's immpossible, but may be a little problem. Maybe try adding the created unit into a group, then set a temp group that are the units around the unit you just created. If a unit from the same type is in that group - remove last created unit.
 

DioD

New Member
Reaction score
57
more cells you allocate, less size everyone have, soo units will have less difference in positioning.

since every unit will have +-cell distance to other unit (if cell size is 1000 on same map units will be 1000-2000 distance to each other), with large amount of small cells allocation will be smooth, 84 map is 42000 range.
 

Ryushi

"I will stand, or I will fall. I will not sit."
Reaction score
59
If I understand what your trying to do, I think something like this would work:
Trigger:
  • Trigger 1
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Point[1] = (Random point in (Playable map area))
      • Set Int = 2
      • Trigger - Run Trigger 2 <gen> (ignoring conditions)


Trigger:
  • Trigger 2
    • Events
    • Conditions
    • Actions
      • Set Point[Int] = (Random point in (Playable map area))
      • Set Bool = False
      • For each (Integer B) from 1 to (Int - 1), do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between Point[Int] and Point[(Integer B)]) Less than X
            • Then - Actions
              • Set Bool = True
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Bool Equal to True
        • Then - Actions
          • Trigger - Run (This trigger) (ignoring conditions)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Int Not equal to Y
            • Then - Actions
              • Set Int = (Int + 1)
              • Trigger - Run (This trigger) (ignoring conditions)
            • Else - Actions
              • Create your units at each point

X would be the minimum distance between units and Y would be the number of units.
 

skyblader

You're living only because it's illegal killing.
Reaction score
159
Okay I think I get the idea.. but what are cells arrays, is there a cell variable? or is that JASS? How to remove from the array?
 

TomTTT

New Member
Reaction score
44
Okay I think I get the idea.. but what are cells arrays, is there a cell variable? or is that JASS? How to remove from the array?

I think he mean the cell is a point variable in the center of the cell. No, there is no cell variable. I never saw the word "Cell" in the world editor. :D
 

DioD

New Member
Reaction score
57
this is area 3*3 with 9 cells.
every cell have its number, nothing more.
we dont need its coordinates, or size.

if we know size of area and size of cells, we can easily calculate its position onfly.

Code:
|1|2|3|
|4|5|6|
|7|8|9|

if we take cell 9 to place unit, we shoud remove cells 5-6-8-9 from array.

its very easy to calculate cell up-down, we just substract or add size of area to current cell number.

9 - 3 = 6
9 - 3 - 1 = 5
9 - 3 + 1 = unused, since 6 is last in its row
9 - 1 = 8
9 + 1 = unused, since 9 is last in its row


Code:
|1|2|3|
|4|X|X|
|7|X|X|

Now we can choose 1 2 3 4 or 7 to place other unit, as you can see, its not possible for unit to be placed closer then 1 cell to other one.

Ryushi
this will not work, since you check for last created unit only, it will collide with units created on prevous cycles.


inside cell you also able to choose random position for unit (you know max-min coordinates for every cell) also you may allocate subcells for every cell.

Code:
|1|2|
|3|4|

if you place unit to subcell 4, then you will remove blocks 6 8 9 only


Code:
|1|2|3|
|4|5|X|
|7|X|X|
 

Ryushi

"I will stand, or I will fall. I will not sit."
Reaction score
59
Ryushi
this will not work, since you check for last created unit only, it will collide with units created on prevous cycles.
The Loop using Integer B runs from 1 to 1 less than the current integer value, so it will do the check for every point currently stored.
 

skyblader

You're living only because it's illegal killing.
Reaction score
159
If I understand what your trying to do, I think something like this would work:
Trigger:
  • Trigger 1
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Point[1] = (Random point in (Playable map area))
      • Set Int = 2
      • Trigger - Run Trigger 2 <gen> (ignoring conditions)


Trigger:
  • Trigger 2
    • Events
    • Conditions
    • Actions
      • Set Point[Int] = (Random point in (Playable map area))
      • Set Bool = False
      • For each (Integer B) from 1 to (Int - 1), do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between Point[Int] and Point[(Integer B)]) Less than X
            • Then - Actions
              • Set Bool = True
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Bool Equal to True
        • Then - Actions
          • Trigger - Run (This trigger) (ignoring conditions)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Int Not equal to Y
            • Then - Actions
              • Set Int = (Int + 1)
              • Trigger - Run (This trigger) (ignoring conditions)
            • Else - Actions
              • Create your units at each point

X would be the minimum distance between units and Y would be the number of units.

What if bool is false? If they're to near each other. It seems you didn't give it what to do if bool was false o.o

And doesn't this only check point 1 and point 2, whether theyre far enough, thn point 2 and 3, wad about 1 and 3? o.o

@DioD I have no idea what a cell is..
 

Ryushi

"I will stand, or I will fall. I will not sit."
Reaction score
59
The If/Then/Else statement checking if Bool is true has some actions in the Else part. Those are going to run if Bool is false, i.e., if the point is at least Y units from all the other points.

Also, it will check to all previous points, look at the Integer B loop. Say Int was 4, i.e., you are getting the 4th point. The Integer B loop will run from 1 to 3, and check point 4 to each point 1, 2, and 3. If any of them are too close, Bool becomes true. I tested the trigger and it worked the way I wanted it to.
 

skyblader

You're living only because it's illegal killing.
Reaction score
159
The If/Then/Else statement checking if Bool is true has some actions in the Else part. Those are going to run if Bool is false, i.e., if the point is at least Y units from all the other points.

Also, it will check to all previous points, look at the Integer B loop. Say Int was 4, i.e., you are getting the 4th point. The Integer B loop will run from 1 to 3, and check point 4 to each point 1, 2, and 3. If any of them are too close, Bool becomes true. I tested the trigger and it worked the way I wanted it to.
My bad, overlooked that.

Okay so I thought I'd test it out.. These are my triggers, and the result is, all pings at the extreme bottom left of the map.

Trigger:
  • Setup Resources
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set ResourcePoint[1] = (Random point in (Playable map area))
      • Set ResourceInteger = 2
      • Trigger - Run Resource Points <gen> (ignoring conditions)


Trigger:
  • Resource Points
    • Events
    • Conditions
    • Actions
      • Set ResourcePoint[ResourceInteger] = (Random point in (Playable map area))
      • Set ResourceBoolean = False
      • For each (Integer A) from 1 to (ResourceInteger - 1), do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between ResourcePoint[ResourceInteger] and ResourcePoint[(Integer A)]) Less than 1000.00
            • Then - Actions
              • Set ResourceBoolean = True
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ResourceBoolean Equal to True
        • Then - Actions
          • Trigger - Run (This trigger) (ignoring conditions)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ResourceInteger Not equal to 15
            • Then - Actions
              • Set ResourceInteger = (ResourceInteger + 1)
              • Trigger - Run (This trigger) (ignoring conditions)
            • Else - Actions
              • For each (Integer B) from 1 to 15, do (Actions)
                • Loop - Actions
                  • Unit - Create 1 Resources for Player 12 (Brown) at ResourcePoint[(Integer B)] facing Default building facing degrees
                  • Cinematic - Ping minimap for (All players) at ResourcePoint[(Integer B)] for 5.00 seconds


And also.. This leaks 15 points right? I can't remember how to clear arrays..
 

Ryushi

"I will stand, or I will fall. I will not sit."
Reaction score
59
Well that's odd. Does it always create the 15 units in the bottom left corner of the map every time you run it?

Also, if I remember right, for cleaning the leaks, add the two lines of custom script:

Trigger:
  • Resource Points
    • Events
    • Conditions
    • Actions
      • Set ResourcePoint[ResourceInteger] = (Random point in (Playable map area))
      • Set ResourceBoolean = False
      • For each (Integer A) from 1 to (ResourceInteger - 1), do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between ResourcePoint[ResourceInteger] and ResourcePoint[(Integer A)]) Less than 1000.00
            • Then - Actions
              • Set ResourceBoolean = True
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ResourceBoolean Equal to True
        • Then - Actions
          • Custom script: call RemoveLocation(udg_ResourcePoint[udg_ResourceInteger])
          • Trigger - Run (This trigger) (ignoring conditions)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ResourceInteger Not equal to 15
            • Then - Actions
              • Set ResourceInteger = (ResourceInteger + 1)
              • Trigger - Run (This trigger) (ignoring conditions)
            • Else - Actions
              • For each (Integer B) from 1 to 15, do (Actions)
                • Loop - Actions
                  • Unit - Create 1 Resources for Player 12 (Brown) at ResourcePoint[(Integer B)] facing Default building facing degrees
                  • Cinematic - Ping minimap for (All players) at ResourcePoint[(Integer B)] for 5.00 seconds
                  • Custom script: call RemoveLocation(udg_ResourcePoint[bj_forLoopBIndex])


EDIT: Well I copied your triggers exactly into another map, and it still works for me. Here's the map.
 

Attachments

  • RandomUnits.w3x
    17 KB · Views: 98

skyblader

You're living only because it's illegal killing.
Reaction score
159
Okay.. So the units are spread out nicely, but the pings are only pinging the bottom left part..

And also, how do I check if the point is in an area I don't want, such as rivers... or in between trees... (Yeah I tried, found one in the river o.o)

Edit: I tried opening your map and inserting the ping, at the start of the map. All the pings were at bottom left. However, when I typed 1, means everything is run again right, the pings work fine. Why's that? o.o
 

Ryushi

"I will stand, or I will fall. I will not sit."
Reaction score
59
Apparently the game can't ping on map intialization. I changed the event to time elapsed is 0 seconds and the pings worked fine.

For preventing the units from being created in places you don't want, after the line that sets the Boolean to equal false, you need to check the point, and if it is a location you don't want, set the Boolean to true. You are also going to need to modify the first trigger to check the random point and if it's no good, then to run that trigger again.

I can check if the point is in a location you don't want, and the easiest that I can come up with is this:
Place invisible units that won't affect gameplay over top of areas that you don't want the units to spawn in. Then, if the point is within a 200 radius or so of any of these units, you know that the point is no good.

Another alternative could be creating regions over all the areas you don't want units to spawn, and checking if the point is within one of those regions.
 

skyblader

You're living only because it's illegal killing.
Reaction score
159
Tried putting dummy units... Works pretty good, except, the map takes like 5-10 seconds to load before everything comes out. So kinda like the game starts, freezes for 5-10 seconds, then everything comes out. Too many dummy units?
 

Ryushi

"I will stand, or I will fall. I will not sit."
Reaction score
59
The game may be taking a few seconds to start because it has to loop through every dummy for every time a new point is set.

Unfortunately I can't think of a reliable way to check if a point is in an area you don't want. Perhaps you could add a wait of 0.1 seconds after the action that adds one to your integer. The units would then be placed 1.5 seconds into the game, but it might help with the slowdown at the beginning of the game.
 

TomTTT

New Member
Reaction score
44
Okay.. So the units are spread out nicely, but the pings are only pinging the bottom left part..

And also, how do I check if the point is in an area I don't want, such as rivers... or in between trees... (Yeah I tried, found one in the river o.o)

Edit: I tried opening your map and inserting the ping, at the start of the map. All the pings were at bottom left. However, when I typed 1, means everything is run again right, the pings work fine. Why's that? o.o

About the trees or river things, just create a region on the, and when a unit enters that region, move it.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top