Jump to content

random number generator help (weidu)


smeagolheart

Recommended Posts

So I've been using the random (1 x) thing. It has been okay, but I was wondering if someone knew a way to get a little more desirable results.

 

Here's the scenario with simple numbers:

Let's say that I want to pick 5 numbers.

Let's say the range from 1-4.

With that range and that amount of picks, it's possible the random numbers picked come back 4, 1, 4, 4, and 2, right?

 

Can someone out suggest a way to make a function or something that uses up the 1-4 combinations before picking a new number? So it could be 4, 2, 1, 3 and then after all numbers are used up it could pick a 2 again. Does that make sense?

 

Basically, I'd like to use all the available numbers before picking a repeating number. Is this possible with a function or something in Weidu?

Link to comment

A random seed is a random seed... that being said, what are you seeding ?
A dialog is a lot different than seeding an variable(timers for example) in a .spl file. Like:

OUTER_SET timer1 = RANDOM(1 100)
...
PATCH_IF (~spell_level~ = 1) BEGIN
WRITE_LONG ("%fx_off%" + 0x0e) (timer1) // User-defined values
END

 

 

Aka can it be done via "in game scripting" or ?

Link to comment

So I've been using the random (1 x) thing. It has been okay, but I was wondering if someone knew a way to get a little more desirable results.

 

Here's the scenario with simple numbers:

Let's say that I want to pick 5 numbers.

Let's say the range from 1-4.

With that range and that amount of picks, it's possible the random numbers picked come back 4, 1, 4, 4, and 2, right?

 

Can someone out suggest a way to make a function or something that uses up the 1-4 combinations before picking a new number? So it could be 4, 2, 1, 3 and then after all numbers are used up it could pick a 2 again. Does that make sense?

 

Basically, I'd like to use all the available numbers before picking a repeating number. Is this possible with a function or something in Weidu?

Link to comment

If it's for weidu directly, just create a list or array of all the seen variables. Here's some pseudocode:

seen = []
final = []
N=10
r = lerandom(1,4)
while r in seen and N > 0:
  r = lerandom(1,4)
  if r in seen: continue
  seen += r
  N--
  if seen.length % 4 == 0:
    final += seem
    seen = []
Link to comment

If it's for weidu directly, just create a list or array of all the seen variables. Here's some pseudocode:

seen = []final = []N=10r = lerandom(1,4)while r in seen and N > 0:  r = lerandom(1,4)  if r in seen: continue  seen += r  N--  if seen.length % 4 == 0:    final += seem    seen = []
The code is not for dialogue so I won't be patching individual baf files. I think lynx might be closest.

 

Let me see if I understand that correctly..

 

N is equal to the number of picks right? And it's a counter that counts down and when it hits 0 it resets?

 

That really sounds like what I need, now to test it out...

Link to comment

Here's my attempt at converting that into weidu tp2... I'm sure it's not right yet...

BACKUP ~Test/backup~
AUTHOR ~Smeagolheart~
VERSION ~1.0~

BEGIN ~Test~
    DESIGNATED 0
    
    DEFINE_ACTION_MACRO ~GetRndNumber~
        INT_VAR
        "Max"                     = "0"
        BEGIN
            OUTER_SET $seen(x) = ~~
            // seen     = []
            
            OUTER_SET $final(x) = ~~
            // final     = []
                    
            OUTER_SET r = RANDOM ( 1 ~%Max%~ )        
            // r = lerandom(1,4)
            
            WHILE (r IN seen) AND (N > 0) BEGIN
            // WHILE r in seen and N > 0     
                OUTER_SET r = RANDOM ( 1 ~%Max%~ )    
                // r = lerandom(1,4)        
                ACTION_IF (r IN seen) BEGIN
                // if r in seen: continue            
                    OUTER_SET seen += r        
                    OUTER_SET n -= 1
                    // n--
                END            
                ACTION_IF (seen.length % 4 == 0) BEGIN
                // if seen.length % 4 == 0:                
                    OUTER_SET final += seen
                    OUTER_SET $seen(x) = ~~
                    // seen = []
                END
            END
        END    
        
    //variables...
    OUTER_SET maxnumber     = 4
    OUTER_SET maxnumberB    = 32
    OUTER_SET N             = 10

    LAUNCH_ACTION_MACRO ~GetRndNumber~
        INT_VAR
        "Max"        = ~%maxnumber%~
    END

    /*  etc
    LAUNCH_ACTION_MACRO ~GetRndNumber~
        INT_VAR
        "Max"        = ~%maxnumberB%~
    END
    */
            
END
Link to comment

Come to think of it, it would be faster if you took a different approach. Generate all possible numbers and add them to a list. Then use random indices and resizing. Can't loop indefinitely that way. :)

Link to comment
Generate all possible numbers and add them to a list.

 

 

Ok I can do that.

 

Then use random indices and resizing.

 

 

Yeah that part I have no idea in Weidu how to do it.

 

EDIT:

Now that I think about it, I'm going to be passing multiple numbers (set of numbers A, B, C, etc) to this random thing so I'm going to need multiple lists to maintain of my numbers. That will get unwieldy fast.

Link to comment

Well, I tried to tackle the problem myself (loosely based on the algorithm lynx had in mind):

// Global definitions
OUTER_SET randomRangeMin  = 0     // lower bound
OUTER_SET randomRangeMax  = 1     // upper bound
OUTER_SET randomNumValues = 0     // internally used to keep track of spent values
OUTER_SET randomResult    = randomRangeMin // contains the random value from the last GetUniqueRandom call
// RANDOM_SEED 1234          // uncomment and set to get reproducible results

// Returns a random value in "randomResult" that does not repeat until all values of the defined range have been spent
DEFINE_ACTION_MACRO GetUniqueRandom
BEGIN
  LOCAL_SET rangeCount = randomRangeMax - randomRangeMin + 1
  LOCAL_SET idx = 0
  LOCAL_SET value = 0

  // array initialization
  ACTION_IF (randomNumValues = 0) BEGIN
    LOG ~DEBUG: Initializing random list~

    OUTER_WHILE (randomNumValues < rangeCount) BEGIN
      OUTER_SET value = RANDOM (randomRangeMin randomRangeMax)
      OUTER_FOR (idx = 0; idx < randomNumValues; ++idx) BEGIN
        ACTION_IF (EVAL "randomArray_%idx%" = value) BEGIN
          OUTER_SET value = randomRangeMin - 1
          OUTER_SET idx = randomNumValues
        END
      END
      ACTION_IF (value >= randomRangeMin) BEGIN
        OUTER_SET EVAL "randomArray_%randomNumValues%" = value
        OUTER_SET randomNumValues += 1
      END
    END
  END

  // "randomResult" contains the new random value
  OUTER_SET randomNumValues -= 1
  OUTER_SET randomResult = EVAL "randomArray_%randomNumValues%"
END

I had some trouble using the array notation "$myArray(x)", so I used the slightly more complicated notation of EVAL "myArray_%x%".

And a short test sequence:

OUTER_SET randomRangeMin = 1
OUTER_SET randomRangeMax = 8
OUTER_FOR (idx = 0; idx < 24; ++idx) BEGIN
  LAM GetUniqueRandom
  PRINT ~Random value: %randomResult%~
END
Link to comment

@Mike1072

 

This is for a portraits mod I'm making that's going to cover all portraits for IWDEE, BGEE and BG2EE. It should go well with EET. The number of things that speak in those games is around 4500. That's a big number. I'm not going to make individual portraits for all of them, that's just too many so I'm creating banks of pictures - eg Drow, Elf, Halfling, Human, etc etc etc.that I will hand out at install time. There are two ways to hand them out in order or randomly. I've got install options for either. I don't know about you but I tend to restart games often and with different loads of mods sometimes and I like the idea of random guys getting random portraits.

 

I have this working now (install options of sequential or random application of my portrait banks). The random option uses repeats some as you would expect with random numbers - you can get 5 guys using portrait #6 before using up all combinations. So I'd prefer it to use up all the portraits before reusing them. To be clear - if you have 45 drow male speakers and only 20 portraits, there will be repeats anyway but I just want to reduce the repeats a bit.

 

These portrait banks will be for guys named generically like "Drow" or "Guard". I try and make individual drow unique like Captain Elgard or something would get his own portrait.

 

@argent77

If that code works on the code framework there then it should work for the mod. I'll test it out and report back. I'm going to have to keep track of each bank with separate counters (drow random index, Halfling random index, etc)

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...