• 🏆 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!

Need Help with VJASS script

Status
Not open for further replies.
Level 13
Joined
May 24, 2005
Messages
609
Hey there,

So I have a vjass library that throws an error but due to my absense and blackout I cannot handle to fix it on my own.

Here is the code:

JASS:
library Pool
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This script gives the user access to general integer pools. A pool is a data
//* structure that allows you to give entries to it a weight. This weight
//* essentially scales how likely certain random accesses to the pool will be
//* returned by the internal .getRandomInt method. Pools can be useful in any
//* number of ways, such as item drops, randomizing enemy encounters, randomly
//* selecting rects weighted by area, and so forth.
//*
//* Modified by Moco [2013-04-12]:
//*   - Fixed a critical issue with the RemoveInt function not properly updating the hashtable
//*   - Added a flush method to clear the whole pool
//*
//******************************************************************************
//*
//* Example usage:
//*    local intpool ip = intpool.create()
//*    call ip.addInt(1, 1.0)
//*    call ip.addInt(2, 0.5)
//*    call ip.getRandomInt()
//*    call ip.getChance(2)
//*    call ip.getWeight(2)
//*    call ip.removeInt(1)
//*
//* You will first need to create an intpool as shown above. Once you've done
//* that, you may use the .addInt method to add an entry to the pool with a
//* specific weight. The example above adds 2 integers, one twice as likely to
//* be randomly selected as the other. That means for the above example, the
//* .getRandomInt method will 66% of the time return 1 and 33% of the time
//* return 2. If you want to remove an entry from an intpool, the .removeInt
//* method is what you will want to use. If you would like to update an entry's
//* weight after already adding it, simply use .addInt again with the new
//* weight.
//*
//* The .getChance and .getWeight methods are there for convenience. If you are
//* interested in the exact chance of the intpool returning a specific entry,
//* then you should use .getChance to obtain the decimal chance out of 1. If you
//* want to know the weight input for a specific entry, .getWeight will return
//* that for you.
//*
//* When adding an entry to the intpool with .addInt, the actual magnitude of
//* the weight doesn't matter. What matters is its magnitude relative to the
//* magnitudes of all other entries in the intpool. This means that it is ok to
//* use very large or very small weights and is done at the user's discretion.
//*
//* It is worth noting that if you use .getRandomInt on an intpool with no
//* entries, the function will return INTPOOL_NO_ENTRIES, which is about as
//* random an integer as possible so as to avoid people accidentally using it.
//*
globals
    //These constants can be changed
    private constant integer MAX_INSTANCES         = 8191
    private constant integer MAX_ENTRIES           = 256
            constant integer INTPOOL_NO_ENTRIES    = 0x672819
          
    //Don't change the following global declaration
    private hashtable ht = InitHashtable()
endglobals

struct intpool[MAX_INSTANCES]
    private integer Cnt         = 0
    private real    WeightTotal = 0.
    private integer array Entries[MAX_ENTRIES]
    private real    array Weights[MAX_ENTRIES]
    private string name = " " // pool name for debug
  
    method getWeight takes integer entry returns real
        return Weights[LoadInteger(ht, integer(this), entry)]
    endmethod
  
    method getChance takes integer entry returns real
        if WeightTotal > 0. then
            return Weights[LoadInteger(ht, integer(this), entry)]/WeightTotal
        endif
        return 0.
    endmethod

  
method addInt takes integer entry, real weight returns nothing
local integer in = LoadInteger(ht, integer(this), entry)



if .Cnt == MAX_ENTRIES then
//Can't hold any more entries
debug call BJDebugMsg(SCOPE_PREFIX+"Error: .addEntry has reached MAX_ENTRIES")
endif



if weight <= 0 then

//Zero or negative weights make no sense
debug call BJDebugMsg(SCOPE_PREFIX+"Error: .addEntry can't take zero or negative weights (" +.name+")")

endif

eif in > 0 then

//Update old entry
set .WeightTotal = .WeightTotal - .Weights[in] + weight
set .Weights[in] = weight
//    debug call BJDebugMsg(SCOPE_PREFIX+"Pool updated existing entry: "+I2S(entry))

//else

//Make a new entry
set .Cnt           = .Cnt + 1
call SaveInteger(ht, integer(this), entry, .Cnt)
set .Entries[.Cnt] = entry
set .Weights[.Cnt] = weight
set .WeightTotal   = .WeightTotal + weight
//   debug call BJDebugMsg(SCOPE_PREFIX+"Pool New Entry: "+I2S(entry))
endif

// debug call BJDebugMsg("Pool added value: "+I2S(entry)+" with weight: "+R2S(weight))
endmethod
  
  
  
  
  
method flush takes nothing returns nothing
local integer c = 0
call FlushChildHashtable(ht, integer(this))
        loop
            exitwhen c > Cnt
            set .Entries[.Cnt] = 0
            set .Weights[.Cnt] = 0
            set c = c + 1
        endloop
        set .WeightTotal = 0
        set .Cnt         = 0
    endmethod
  
    method showEntries takes nothing returns nothing
        local integer c = 1
        call BJDebugMsg(" Pool count: "+I2S(Cnt))
        loop
            exitwhen c > Cnt
            call BJDebugMsg("Pool entry #"+I2S(c)+ ": "+I2S(.Entries[c]))
            set c = c + 1
        endloop
    endmethod
  
    method removeInt takes integer entry returns nothing
        local integer in = LoadInteger(ht, integer(this), entry)
        if in > 0 then
            call RemoveSavedInteger(ht, integer(this), entry)
          
            //Remove its entry in the arrays
            set .WeightTotal = .WeightTotal - .Weights[in]
          
            if in != .Cnt then         
                set .Entries[in] = .Entries[.Cnt]
                set .Weights[in] = .Weights[.Cnt]
                call SaveInteger(ht, integer(this), .Entries[in], in)
            endif
            set .Entries[.Cnt] = 0
            set .Weights[.Cnt] = 0
            set .Cnt         = .Cnt - 1
          
            if .Cnt == 0 then
                call this.flush()
            endif
        debug else
            debug call BJDebugMsg(SCOPE_PREFIX+"Error: .removeEntry entry doesn't exist")
        endif
    endmethod
  
    method getRandomInt takes nothing returns integer
        local real    r = GetRandomReal(0, .WeightTotal)
        local integer c = 0
        if .WeightTotal <= 0. then
            debug call BJDebugMsg(SCOPE_PREFIX+"Error: intpool has no entries (" +.name+")")
            return INTPOOL_NO_ENTRIES
        endif
        set r = GetRandomReal(0, .WeightTotal) // Double Random
        loop
            set r = r - .Weights[c]
            exitwhen r <= 0
            set c = c + 1
        endloop
        return .Entries[c]
    endmethod
  
    method setName takes string name returns nothing
        set this.name = name
    endmethod
  
endstruct
endlibrary
 
Last edited by a moderator:
Status
Not open for further replies.
Top