- 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:
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: