HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Loops

10-03-2007, 01:08 PM#1
Pheonix-IV
Alrighty, i'm trying to make a system which randomly generates buildings for little villages. Now what i can do is take a point and start making buildings at random points around my start point, the problem is that sometimes buildings end up inside of each other.

If i stick in a check to see if the new point is too close to a previous point, that's fine, but it will only check once, and it's fairly likely that some of the points after this check will end up inside another point.

So what i need is some way to loop indefinitely, checking the points until i find a location which does not have any other points near it. Normally i'd just use a loop or while function, but i don't believe WCIII has those?
10-03-2007, 01:21 PM#2
Tide-Arc Ephemera
Um... how about storing the points and not deleting them until the end, or using a system of dummy units and then seeing if they are too close together or something?

The dummy units would be easier but not quite optimal (as far as I know).
10-03-2007, 01:25 PM#3
Castlemaster
Here's my crack at it.
I assume you have a wait command in your loop, or are using the periodic timer event to space out building placement.

First make 2 array variables with a limit capped at the max # of buildings you want to place. These two variables will be X and Y coordinates. Now when you run the loop, have a tempcount global variable that will tell you the number of times you have placed a building. When a building is placed, set the coordinates to BuildingX[tempcount] and BuildingY[tempcount]. Before you place the building, make a loop within the loop that will check if your randomly generated point is too close to one you've already done. This can be done by making a loop that uses a counting variable for said loop and compares your random X and Y to udg_BuildingX[countingvariable] and udg_BuildingY[countingvariable]. If the points are too close, it will generate a new point. I would write out a JASS example, but I'd be late for class.
10-03-2007, 04:53 PM#4
PipeDream
The way I would do it is create a regular grid of sufficiently spaced points and shuffle out N of them as building locations. If you don't want your buildings to be on a regular grid, then randomly displace each point a bit.

Regardless you most certainly can loop, either using the loop ... endloop statements or recursion. Read some JASS tutorials.
10-03-2007, 07:04 PM#5
Salbrismind
Give us your triggers/map so we can really give it a good try!
10-03-2007, 10:11 PM#6
TaintedReality
Quote:
Originally Posted by Phoenix-IV
Normally i'd just use a loop or while function, but i don't believe WCIII has those?

??? http://jass.sourceforge.net/doc/statements.shtml
10-03-2007, 10:16 PM#7
Pheonix-IV
Heres the trigger, there's literally only this in it atm.

Trigger:
TrollVillage
Collapse Events
Map initialization
Conditions
Collapse Actions
Set tempint = 0
Set tempgroup = (Units in (Playable map area) matching ((Unit-type of (Matching unit)) Equal to Troll Village))
Collapse Unit Group - Pick every unit in tempgroup and do (Actions)
Collapse Loop - Actions
Set temppoint = (Position of (Picked unit))
Set tempint = (tempint + 1)
Collapse For each (Integer A) from 1 to (Random integer number between 2 and 4), do (Actions)
Collapse Loop - Actions
Set temppoint2 = (temppoint offset by (Random real number between 300.00 and 700.00) towards (Random angle) degrees)
Collapse Unit Group - Pick every unit in TrollVillage[tempint] and do (Actions)
Collapse Loop - Actions
Set temppoint3 = (Position of (Picked unit))
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
(Distance between temppoint2 and temppoint3) Less than or equal to 200.00
Collapse Then - Actions
Set temppoint2 = (temppoint2 offset by (Random real number between 200.00 and 300.00) towards (Random angle) degrees)
Else - Actions
Custom script: call RemoveLocation( udg_temppoint3 )
Unit - Create 1 Troll Lodge 1 for Neutral Passive at temppoint2 facing ((Angle from temppoint2 to temppoint) + (Random real number between -45.00 and 45.00)) degrees
Unit Group - Add (Last created unit) to TrollVillage[tempint]
Collapse For each (Integer B) from 1 to ((Integer((Distance between temppoint and temppoint2))) / 50), do (Actions)
Collapse Loop - Actions
Set temppoint4 = (temppoint offset by ((Real((Integer B))) x 50.00) towards (Angle from temppoint to temppoint2) degrees)
Environment - Change terrain type at temppoint4 to Ashenvale - Dirt using variation -1 in an area of size 1 and shape Circle
Set temppoint5 = (temppoint4 offset by (Random real number between 100.00 and 150.00) towards 90.00 degrees)
Environment - Change terrain type at temppoint5 to Ashenvale - Grassy Dirt using variation -1 in an area of size 1 and shape Circle
Custom script: call RemoveLocation( udg_temppoint5 )
Set temppoint5 = (temppoint4 offset by (Random real number between 100.00 and 150.00) towards -90.00 degrees)
Environment - Change terrain type at temppoint5 to Ashenvale - Grassy Dirt using variation -1 in an area of size 1 and shape Circle
Custom script: call RemoveLocation( udg_temppoint5 )
Set tempint2 = (Random integer number between 1 and 5)
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
tempint2 Equal to 1
Collapse Then - Actions
Set temppoint5 = (temppoint4 offset by (Random real number between 175.00 and 250.00) towards 90.00 degrees)
Environment - Change terrain type at temppoint5 to Ashenvale - Leaves using variation -1 in an area of size 1 and shape Circle
Custom script: call RemoveLocation( udg_temppoint5 )
Else - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
tempint2 Equal to 2
Collapse Then - Actions
Set temppoint5 = (temppoint4 offset by (Random real number between 175.00 and 250.00) towards -90.00 degrees)
Environment - Change terrain type at temppoint5 to Ashenvale - Leaves using variation -1 in an area of size 1 and shape Circle
Custom script: call RemoveLocation( udg_temppoint5 )
Else - Actions
Custom script: call RemoveLocation( udg_temppoint4 )
Custom script: call RemoveLocation( udg_temppoint2 )
Unit - Remove (Picked unit) from the game
Custom script: call RemoveLocation( udg_temppoint )
Custom script: call DestroyGroup( udg_tempgroup )

All this has is the building placement and terrain changing, as you can see i tend to use different temppoints rather than reusing the same ones, i've had a few nasty experiences with reusing temppoints in the past (basically sometimes i reused a temppoint when it was still being used and spent the next 3 hours trying to work out why my SFX was spawning at the wrong location.)

And yes, it's in GUI, i havn't seen a need to start using JASS on this one yet, although i may need to for the loop.
10-03-2007, 10:19 PM#8
TaintedReality
Ohh sorry didn't realize you were using GUI. Maybe to get the while-loop effect you could just use the "For each integer variable, do multiple actions" action, and set the variable back to 0 each time, until you want it to exit. Then set it to whatever the end value is. Not sure if you can do that but I think you can.
10-03-2007, 10:34 PM#9
Pheonix-IV
Discovered i don't need the loop and i can use WCIII's pathing system to my advantage.

Trigger:
TrollVillage
Collapse Events
Map initialization
Conditions
Collapse Actions
Set tempint = 0
Set tempgroup = (Units in (Playable map area) matching ((Unit-type of (Matching unit)) Equal to Troll Village))
Collapse Unit Group - Pick every unit in tempgroup and do (Actions)
Collapse Loop - Actions
Set temppoint = (Position of (Picked unit))
Set tempint = (tempint + 1)
Collapse For each (Integer A) from 1 to (Random integer number between 2 and 4), do (Actions)
Collapse Loop - Actions
Set temppoint3 = (temppoint offset by (Random real number between 300.00 and 700.00) towards (Random angle) degrees)
Destructible - Create a dead Pathing Blocker (Ground) (Large) at temppoint3 facing 0.00 with scale 1.00 and variation 0
Set temppoint2 = (Position of (Last created destructible))
Custom script: call RemoveLocation( udg_temppoint3 )
Unit - Create 1 Troll Lodge 1 for Neutral Passive at temppoint2 facing ((Angle from temppoint2 to temppoint) + (Random real number between -15.00 and 45.00)) degrees
Unit Group - Add (Last created unit) to TrollVillage[tempint]
Collapse For each (Integer B) from 1 to ((Integer((Distance between temppoint and temppoint2))) / 50), do (Actions)
Collapse Loop - Actions
Set temppoint4 = (temppoint offset by ((Real((Integer B))) x 50.00) towards (Angle from temppoint to temppoint2) degrees)
Environment - Change terrain type at temppoint4 to Ashenvale - Dirt using variation -1 in an area of size 1 and shape Circle
Set temppoint5 = (temppoint4 offset by (Random real number between 100.00 and 150.00) towards 90.00 degrees)
Environment - Change terrain type at temppoint5 to Ashenvale - Grassy Dirt using variation -1 in an area of size 1 and shape Circle
Custom script: call RemoveLocation( udg_temppoint5 )
Set temppoint5 = (temppoint4 offset by (Random real number between 100.00 and 150.00) towards -90.00 degrees)
Environment - Change terrain type at temppoint5 to Ashenvale - Grassy Dirt using variation -1 in an area of size 1 and shape Circle
Custom script: call RemoveLocation( udg_temppoint5 )
Set tempint2 = (Random integer number between 1 and 5)
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
tempint2 Equal to 1
Collapse Then - Actions
Set temppoint5 = (temppoint4 offset by (Random real number between 175.00 and 250.00) towards 90.00 degrees)
Environment - Change terrain type at temppoint5 to Ashenvale - Leaves using variation -1 in an area of size 1 and shape Circle
Custom script: call RemoveLocation( udg_temppoint5 )
Else - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
tempint2 Equal to 2
Collapse Then - Actions
Set temppoint5 = (temppoint4 offset by (Random real number between 175.00 and 250.00) towards -90.00 degrees)
Environment - Change terrain type at temppoint5 to Ashenvale - Leaves using variation -1 in an area of size 1 and shape Circle
Custom script: call RemoveLocation( udg_temppoint5 )
Else - Actions
Custom script: call RemoveLocation( udg_temppoint4 )
Custom script: call RemoveLocation( udg_temppoint2 )
Unit - Remove (Picked unit) from the game
Custom script: call RemoveLocation( udg_temppoint )
Custom script: call DestroyGroup( udg_tempgroup )

Unless the pathing blocker spawns directly on top of another one (possible, but far less likely) WCIII will move it to the nearest available position, which works perfectly.

But it is nice to know i can use a loop if i need it, just a pity i have to use JASS to do it :P
10-03-2007, 11:30 PM#10
Pheonix-IV
New problem and double post!

Can i check what the pathing type at a specified point is? I can't find any conditions that relate to pathing.

Also, does this leak?

Trigger:
TrollVillagersCollisionCheck
Collapse Events
Time - Every 1.00 seconds of game time
Conditions
Collapse Actions
Collapse For each (Integer A) from 1 to VillageNum, do (Actions)
Collapse Loop - Actions
Collapse Unit Group - Pick every unit in TrollVillage[(Integer A)] and do (Actions)
Collapse Loop - Actions
Set temppoint2 = (Position of (Picked unit))
Collapse Unit Group - Pick every unit in TrollVillagers[(Integer A)] and do (Actions)
Collapse Loop - Actions
Set temppoint = (Position of (Picked unit))
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
((Region centered at temppoint with size (150.00, 150.00)) contains temppoint2) Equal to True
Collapse Then - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
(Custom value of (Picked unit)) Equal to 1
Then - Actions
Collapse Else - Actions
Set temppoint3 = ((Position of (Picked unit)) offset by (Random real number between 150.00 and 300.00) towards ((Facing of (Picked unit)) + (Random real number between 150.00 and 210.00)) degrees)
Unit - Order (Picked unit) to Move To temppoint3
Custom script: call RemoveLocation( udg_temppoint2 )
Else - Actions
Custom script: call RemoveLocation( udg_temppoint )
10-03-2007, 11:47 PM#11
TEC_Ghost
Quote:
Originally Posted by Pheonix-IV
New problem and double post!

Can i check what the pathing type at a specified point is? I can't find any conditions that relate to pathing.

Also, does this leak?

Trigger:
TrollVillagersCollisionCheck
Collapse Events
Time - Every 1.00 seconds of game time
Conditions
Collapse Actions
Collapse For each (Integer A) from 1 to VillageNum, do (Actions)
Collapse Loop - Actions
Collapse Unit Group - Pick every unit in TrollVillage[(Integer A)] and do (Actions)
Collapse Loop - Actions
Set temppoint2 = (Position of (Picked unit))
Collapse Unit Group - Pick every unit in TrollVillagers[(Integer A)] and do (Actions)
Collapse Loop - Actions
Set temppoint = (Position of (Picked unit))
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
((Region centered at temppoint with size (150.00, 150.00)) contains temppoint2) Equal to True
Collapse Then - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
(Custom value of (Picked unit)) Equal to 1
Then - Actions
Collapse Else - Actions
Set temppoint3 = ((Position of (Picked unit)) offset by (Random real number between 150.00 and 300.00) towards ((Facing of (Picked unit)) + (Random real number between 150.00 and 210.00)) degrees)
Unit - Order (Picked unit) to Move To temppoint3
Custom script: call RemoveLocation( udg_temppoint2 )
Else - Actions
Custom script: call RemoveLocation( udg_temppoint )

Collapse JASS:
function Trig_Jass_Pathable_Actions13 takes nothing returns nothing
   
local real X = GetRectCenterX(udg_GridX)
local real Y = GetRectCenterY(udg_GridX)

    if not(IsTerrainPathable(X, Y, PATHING_TYPE_WALKABILITY)) then

    //call DisplayTimedTextToForce(bj_FORCE_ALL_PLAYERS,30,"Object Was Placeable at X Y")
    else
    //call DisplayTimedTextToForce(bj_FORCE_ALL_PLAYERS,30,"Object Wasnt Placeable at X Y")
    endif
endfunction

I dont think there's a GetTearrainPathableType you'll just have to run a few checks with this. I could be wrong though :)
10-04-2007, 06:56 AM#12
Pyrogasm
There is the function GetTerrainType(...) which will return an integer id for the type of tile there (Lordaeron Dirt is 'Ldrt').

I would assume that the ids for all the other tiles can be found in some SLK file somewhere (though I'm not sure where it would be), and the only other way to get them would to be to convert the following condition to custom text and see what it's compared to:
Trigger:
Conditions
(Terrain type at (Center of (Playable map area))) Equal to Lordaeron Summer - Dirt