[Solved] Move units to random region without repeats

Level 3
Joined
Mar 8, 2024
Messages
10
Hello
I am trying to make a system where each players units will be moved to a random location chosen from a pool of 8 locations without being moved to the same region.
Out of curiosity and my lack of skill i asked ChatGPT to help me as it actually helped create some other triggers. As i expected ChatGPT cant do everything and the triggers it helped me make doesnt do what i want it to.
This is where i am looking for advice from actual people with brighter minds than me.

The units are all moved to a region but some of the players end up in the same region.

Variables: (this is ChatGPT describtion of the variables used)
PlayerRegions: (Region Array [1-8]): Stores each player’s starting region.
AvailableRegions: (Region Array [1-8]): Tracks which regions are available for the current round.
PlayerAssignedRegion: (Integer Array [1-8]): Stores the region index currently assigned to each player.
RandomRegionIndex (Integer): Temporarily stores a random number for region selection.
RegionCount (Integer): Tracks the number of available regions during selection.

  • RegionArray
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set PlayerRegions[1] = 1 <gen>
      • Set PlayerRegions[2] = 2 <gen>
      • Set PlayerRegions[3] = 3 <gen>
      • Set PlayerRegions[4] = 4 <gen>
      • Set PlayerRegions[5] = 5 <gen>
      • Set PlayerRegions[6] = 6 <gen>
      • Set PlayerRegions[7] = 7 <gen>
      • Set PlayerRegions[8] = 8 <gen>
  • SetAvailableRegions
    • Events
      • Map initialization
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 8, do (Actions)
        • Loop - Actions
          • Set AvailableRegions[(Integer A)] = PlayerRegions[(Integer A)]
      • For each (Integer A) from 1 to 8, do (Actions)
        • Loop - Actions
          • Set PlayerAssignedRegion[(Integer A)] = 0
      • Set RegionCount = 8
      • Trigger - Run AssignRandomRegions <gen> (ignoring conditions)
  • AssignRandomRegions
    • Events
    • Conditions
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Set RandomRegionIndex = (Random integer number between 1 and RegionCount)
          • For each (Integer A) from 1 to 8, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Picked player) Equal to (Player((Integer A)))
                • Then - Actions
                  • Set PlayerAssignedRegion[(Integer A)] = RandomRegionIndex
                  • Set AvailableRegions[RandomRegionIndex] = AvailableRegions[RegionCount]
                  • Set RegionCount = (RegionCount - 1)
                • Else - Actions
      • Trigger - Run MoveToAssigendRegion <gen> (ignoring conditions)
  • MoveToAssigendRegion
    • Events
    • Conditions
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • For each (Integer A) from 1 to 8, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Picked player) Equal to (Player((Integer A)))
                • Then - Actions
                  • Unit Group - Pick every unit in (Units in AbilityGiveRegion <gen> owned by (Picked player)) and do (Actions)
                    • Loop - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • ((Picked unit) is A structure) Equal to False
                        • Then - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (Unit-type of (Picked unit)) Not equal to Peasant
                            • Then - Actions
                              • Unit - Move (Picked unit) instantly to (Center of PlayerRegions[PlayerAssignedRegion[(Integer A)]])
                              • Camera - Pan camera for (Player((Integer A))) to (Center of PlayerRegions[PlayerAssignedRegion[(Integer A)]]) over 0.00 seconds
                            • Else - Actions
                        • Else - Actions
                • Else - Actions
 
I would probably do it super simple and stupid, because it wounds like this is something that isn't run all the time so performance isn't critical. It sounds like typically no unit is in these regions (like an empty arena) and after it everyone is teleported to one of them. If so, a it's simple to check if a unit is already in the region.

This means, RegionArray still needs to be setup.
When you want to make it happen, then move one players unit to one random region. For example try to find a random one 999 times, check if unoccupied and if so, move unit. It's possible to do something smarter than this, but this is simple and should work. Last region should take 8 attempts on average, so the 999 attempts is a bit over-kill and should make it work 100%. There are other solution to make this work 100% but I keep it simple here.

  • MoveToRandomRegion
    • Events
    • Conditions
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • For each (Integer A) from 1 to 999, do (Actions)
            • Loop - Actions
              • Set RandomRegionIndex = (Random integer number between 1 and 8)
              • Set tempUnitGroup = Units in Region (PlayerRegions[RandomRegionIndex])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Number of units in (tempUnitGroup) is equal to 0
                • Then - Actions
                  • //MOVE UNIT to PlayerRegions[RandomRegionIndex]
                  • Set HasMovedUnit = true
                  • Custom Script: call DestroyGroup(tempUnitGroup)
                  • Skip Remaining Actions
                • Else - Actions
              • Custom Script: call DestroyGroup(tempUnitGroup)
I don't have access to the editor right now, so this is untested and I'm not 100% sure that Skip Remaining Actions works as I expect in this case. I know how I'd do it in jass, but that makes it less accessible :p
That's why I tried to describe how my solution would look like and tried to write triggers for it, although some action names could be slightly wrong.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Are your Players assigned to Player Numbers 1 to 8? Red, Blue, Teal, etc.

Because the For Loop is assuming that you're using those Players. Also, you're initializing two sets of data, with one trigger only working if it initialized AFTER the other trigger. You should just have one central Setup trigger. Lastly, make sure the Units you want to move are actually in this region -> AbilityGiveRegion <gen>.

SETUP:
  • SetupAvailableRegions
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set PlayerRegions[1] = 1 <gen>
      • Set PlayerRegions[2] = 2 <gen>
      • Set PlayerRegions[3] = 3 <gen>
      • Set PlayerRegions[4] = 4 <gen>
      • Set PlayerRegions[5] = 5 <gen>
      • Set PlayerRegions[6] = 6 <gen>
      • Set PlayerRegions[7] = 7 <gen>
      • Set PlayerRegions[8] = 8 <gen>
      • For each (Integer PN) from 1 to 8, do (Actions)
        • Loop - Actions
          • Set AvailableRegions[PN] = PlayerRegions[PN]
      • Set RegionCount = 8
      • Trigger - Run AssignRandomRegions <gen> (ignoring conditions)
ASSIGN:
  • AssignRandomRegions
    • Events
    • Conditions
    • Actions
      • For each (Integer PN) from 1 to 8, do (Actions)
        • Loop - Actions
          • Set RandomRegionIndex = (Random integer number between 1 and RegionCount)
          • Set PlayerAssignedRegion[PN] = AvailableRegions[RandomRegionIndex]
          • Set AvailableRegions[RandomRegionIndex] = AvailableRegions[RegionCount]
          • Set RegionCount = (RegionCount - 1)
      • Trigger - Run MoveToAssignedRegions <gen> (ignoring conditions)
MOVE:
  • MoveToAssignedRegions
    • Events
    • Conditions
    • Actions
      • For each (Integer PN) from 1 to 8, do (Actions)
        • Loop - Actions
          • Set RegionPlayer = (Player(PN))
          • Set RegionPoint = (Center of PlayerAssignedRegion[PN])
          • Camera - Pan camera for RegionPlayer to RegionPoint over 0.00 seconds
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in (Units in AbilityGiveRegion <gen> owned by RegionPlayer) and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) is A structure) Equal to False
                  • (Unit-type of (Picked unit)) Not equal to Peasant
                • Then - Actions
                  • Unit - Move (Picked unit) instantly to RegionPoint
                • Else - Actions
          • Custom script: call RemoveLocation( udg_RegionPoint )
I've introduced three new variables:
PN = Integer
RegionPlayer = Player
RegionPoint = Point


I've changed one old variable:
PlayerAssignedRegion = Region (array)

I also cleaned up the memory leaks.

Lastly, to reiterate, this is where the Units need to be to get moved:
  • Unit Group - Pick every unit in (Units in AbilityGiveRegion <gen> owned by RegionPlayer) and do (Actions)
Ensure that's the correct Region and that it will work for all of the involved Players.
 
Last edited:
Level 3
Joined
Mar 8, 2024
Messages
10
Thank you so much for both of you guys ideas.
I made it work with your input Uncle. Thank you so much.
I also tried with ThompZons idea but it made my game lack quite a bit. It might just be me doing something wrong :)
It works like a charm now!
 
Top