• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Random always generating the same number

Status
Not open for further replies.

EdgeOfChaos

E

EdgeOfChaos

Before you tell me to uncheck "Fixed Random Seed", I've done that and I'm not using "Test Map"

So my brother and I are having a very strange issue with a map. GetRandomInt and GetRandomReal are always generating the same number. This is in relation to a -random command for hero choice. The code is pretty simple, this is the function to generate random hero. The relevant part is the first lines, until the "Create 1 unitType" line.

  • Gen Random
    • Events
    • Conditions
    • Actions
      • Set unitType = RandomHeroes[(Random integer number between 1 and 20)]
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • unitType Equal to PlayerHeroType[(Integer A)]
            • Then - Actions
              • Trigger - Run (This trigger) (checking conditions)
              • Skip remaining actions
            • Else - Actions
      • Unit - Create 1 unitType for TempPlayer at (TempPlayer start location) facing Default building facing degrees
      • For each (Integer A) from 1 to 20, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • unitType Equal to RandomHeroes[(Integer A)]
            • Then - Actions
              • Player Group - Pick every player in (All allies of TempPlayer) and do (Actions)
                • Loop - Actions
                  • Set TempGroup = (Units owned by (Picked player) matching ((Unit-type of (Matching unit)) Equal to NecessaryUnit[(Integer A)]))
                  • Unit Group - Pick every unit in TempGroup and do (Actions)
                    • Loop - Actions
                      • Unit - Remove (Picked unit) from the game
                  • Custom script: call DestroyGroup(udg_TempGroup)
              • Player Group - Pick every player in Subs and do (Actions)
                • Loop - Actions
                  • Set TempGroup = (Units owned by (Picked player) matching ((Unit-type of (Matching unit)) Equal to NecessaryUnit[(Integer A)]))
                  • Unit Group - Pick every unit in TempGroup and do (Actions)
                    • Loop - Actions
                      • Unit - Remove (Picked unit) from the game
                  • Custom script: call DestroyGroup(udg_TempGroup)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (TempPlayer is in Subs) Equal to True
        • Then - Actions
          • Game - Display to (All players) the text: (PlayerArray[(Player number of TempPlayer)] + ((Name of TempPlayer) + (|r + ( is a Substitute, but randomed + (Name of (Last created unit))))))
        • Else - Actions
          • Game - Display to (All players) the text: (PlayerArray[(Player number of TempPlayer)] + ((Name of TempPlayer) + (|r + ( has randomed + (Name of (Last created unit))))))
      • Set PlayerHeroes[(Player number of TempPlayer)] = (Last created unit)
      • Set Chosen[(Player number of TempPlayer)] = True
      • Set HeroesChosen = (HeroesChosen + 1)
      • Set PlayerHeroType[(Player number of TempPlayer)] = (Unit-type of (Last created unit))
      • Set TempGroup = (Units owned by TempPlayer matching ((Unit-type of (Matching unit)) Equal to Hero Selector))
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Unit - Remove (Picked unit) from the game
      • Custom script: call DestroyGroup(udg_TempGroup)
      • Unit - Hide (Last created unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • HeroesChosen Equal to (Number of players in (All players matching (((Matching player) slot status) Equal to Is playing)))
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • HeroesChosen Equal to 1
            • Then - Actions
              • Game - Display to (All players) the text: There is only one p...
              • Set SinglePlayer = True
              • Quest - Create a Required quest titled Single Player Mode with the description If you can see this..., using icon path ReplaceableTextures\CommandButtons\BTNAmbush.blp
            • Else - Actions
          • Countdown Timer - Pause ForceRandomTimer
          • Trigger - Run Create Peons <gen> (checking conditions)
          • Set RoundsStarting = True
          • For each (Integer A) from 0 to 3, do (Actions)
            • Loop - Actions
              • Unit - Hide Taverns[(Integer A)]
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FirstTime Equal to False
            • Then - Actions
              • For each (Integer A) from 1 to 12, do (Actions)
                • Loop - Actions
                  • Unit - Unhide Peon[(Integer A)]
                  • Unit - Unhide PartsCollector[(Integer A)]
            • Else - Actions
              • Trigger - Run Multiboard Init <gen> (checking conditions)
          • Set FirstTime = False
          • Trigger - Run Round Init <gen> (checking conditions)
        • Else - Actions
This is called by this function:
  • Random
    • Events
      • Player - Player 1 (Red) types a chat message containing -random as An exact match
      • Player - Player 2 (Blue) types a chat message containing -random as An exact match
      • Player - Player 3 (Teal) types a chat message containing -random as An exact match
      • Player - Player 4 (Purple) types a chat message containing -random as An exact match
      • Player - Player 5 (Yellow) types a chat message containing -random as An exact match
      • Player - Player 6 (Orange) types a chat message containing -random as An exact match
      • Player - Player 7 (Green) types a chat message containing -random as An exact match
      • Player - Player 8 (Pink) types a chat message containing -random as An exact match
      • Player - Player 9 (Gray) types a chat message containing -random as An exact match
      • Player - Player 10 (Light Blue) types a chat message containing -random as An exact match
      • Player - Player 11 (Dark Green) types a chat message containing -random as An exact match
      • Player - Player 12 (Brown) types a chat message containing -random as An exact match
    • Conditions
      • PlayerHeroes[(Player number of (Triggering player))] Equal to No unit
    • Actions
      • Set TempPlayer = (Triggering player)
      • Trigger - Run Gen Random <gen> (checking conditions)
When the following runs, it always generates 15. It's so strange and I can't imagine what's causing it.

I have tried the following to debug it:
- I added text to verify it wasn't a problem with the recursion. It's not, it always gives 15.
- I changed from GetRandomInt(1,20) to (GetRandomReal(0,1)*19)+ 1. With this code, it always generates 9.
- I recoded it in JASS using a proper loop rather than the function call as follows:
JASS:
    local integer i = 0
    local integer rng
    local real rng2
    local boolean exit = false
    loop
    exitwhen exit == true
    set i = 0
    set rng2 = GetRandomReal(0, 1)
    set rng = R2I(rng2 * 19) + 1
    call BJDebugMsg(I2S(rng))
    set udg_unitType = udg_RandomHeroes[rng]
    loop
    exitwhen i >= 12
    if(udg_PlayerHeroType[i] != udg_unitType)then
    set exit = true
    endif
    set i = i + 1
    endloop
    endloop
And it gave the same result.
- I changed it from a trigger to a vjass library, and then called the function rather than running the trigger. Nothing was changed.
- I ran this on current version of WC3 as well as 1.28.5. Same results.
- I created a new map with the following trigger, and it worked fine (generated random numbers correctly):
  • Melee Initialization
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Game - Display to (All players) the text: (String((Random integer number between 1 and 20)))
So this tells me that it's something wrong with the map, and not wrong with my WC3 setup or something.

Do you know any kind of code that could cause a map-wide fixed seed for random number generators?
(and no, we're not calling SetRandomSeed anywhere, unfortunately.. I already looked through the entire script)
 
Last edited by a moderator:
Level 39
Joined
Feb 27, 2007
Messages
5,013
Are you using the SetRandomSeed native anywhere in your map? That would do it. If you're not sure you can open the map with a mpq or casc editor, extract the war3map.j file, and then search it for any instances.

Also there is one cinematic function that sets the seed back to 0 every time:
JASS:
function CinematicModeExBJ takes boolean cineMode, force forForce, real interfaceFadeTime returns nothing
   // If the game hasn't started yet, perform interface fades immediately
    if (not bj_gameStarted) then
        set interfaceFadeTime = 0
    endif

    if (cineMode) then
       // Save the UI state so that we can restore it later.
        if (not bj_cineModeAlreadyIn) then
            set bj_cineModeAlreadyIn = true
            set bj_cineModePriorSpeed = GetGameSpeed()
            set bj_cineModePriorFogSetting = IsFogEnabled()
            set bj_cineModePriorMaskSetting = IsFogMaskEnabled()
            set bj_cineModePriorDawnDusk = IsDawnDuskEnabled()
            set bj_cineModeSavedSeed = GetRandomInt(0, 1000000)
        endif

       // Perform local changes
        if (IsPlayerInForce(GetLocalPlayer(), forForce)) then
           // Use only local code (no net traffic) within this block to avoid desyncs.
            call ClearTextMessages()
            call ShowInterface(false, interfaceFadeTime)
            call EnableUserControl(false)
            call EnableOcclusion(false)
            call SetCineModeVolumeGroupsBJ()
        endif

       // Perform global changes
        call SetGameSpeed(bj_CINEMODE_GAMESPEED)
        call SetMapFlag(MAP_LOCK_SPEED, true)
        call FogMaskEnable(false)
        call FogEnable(false)
        call EnableWorldFogBoundary(false)
        call EnableDawnDusk(false)

       // Use a fixed random seed, so that cinematics play consistently.
        call SetRandomSeed(0)
    else
        set bj_cineModeAlreadyIn = false

       // Perform local changes
        if (IsPlayerInForce(GetLocalPlayer(), forForce)) then
           // Use only local code (no net traffic) within this block to avoid desyncs.
            call ShowInterface(true, interfaceFadeTime)
            call EnableUserControl(true)
            call EnableOcclusion(true)
            call VolumeGroupReset()
            call EndThematicMusic()
            call CameraResetSmoothingFactorBJ()
        endif

       // Perform global changes
        call SetMapFlag(MAP_LOCK_SPEED, false)
        call SetGameSpeed(bj_cineModePriorSpeed)
        call FogMaskEnable(bj_cineModePriorMaskSetting)
        call FogEnable(bj_cineModePriorFogSetting)
        call EnableWorldFogBoundary(true)
        call EnableDawnDusk(bj_cineModePriorDawnDusk)
        call SetRandomSeed(bj_cineModeSavedSeed)
    endif
endfunction
 

EdgeOfChaos

E

EdgeOfChaos

I am not using SedRandomSeed.
Thanks for the tip, that's very interesting that cinematic mode would mess it up.
It was one of these three lines calling it:
  • Cinematic - Turn cinematic mode Off for (Player group((Player((Integer A)))))
  • Cinematic - Turn off letterbox mode (show interface) for (Player group((Picked player))): fade in over 2.00 seconds
  • Cinematic - Enable user control for (Player group((Picked player)))
Probably the first one based off what you said. What a strange WC3 bug (or at least unexpected behavor, I guess). It's fixed now, thank you.
 
Status
Not open for further replies.
Top