added arg for pre-computed sum for weightedChoice

This commit is contained in:
Darren Ranalli 2004-05-29 02:46:07 +00:00
parent 24638f7e96
commit f919dc99ab
3 changed files with 21 additions and 14 deletions

View File

@ -1,6 +1,11 @@
import random import random
# DCR: I added a weightedChoice() function to PythonUtil that supports
# floating-point weights and is intended for one-shot choices. It
# has an optional 'sum' argument that you can pass in if you know the
# sum of the weights and want to make repeated choices.
class WeightedChoice: class WeightedChoice:
def __init__(self, listOfLists, weightIndex=0): def __init__(self, listOfLists, weightIndex=0):
t=0 t=0

View File

@ -6,8 +6,7 @@ import DistributedObjectAI
import Level import Level
import DirectNotifyGlobal import DirectNotifyGlobal
import EntityCreatorAI import EntityCreatorAI
import WeightedChoice from PythonUtil import Functor, weightedChoice
from PythonUtil import Functor
class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI, class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
Level.Level): Level.Level):
@ -74,8 +73,7 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
# make list of lists: [(weight, scenarioIndex), ...] # make list of lists: [(weight, scenarioIndex), ...]
lol = zip([1] * levelSpec.getNumScenarios(), lol = zip([1] * levelSpec.getNumScenarios(),
range(levelSpec.getNumScenarios())) range(levelSpec.getNumScenarios()))
wc = WeightedChoice.WeightedChoice(lol) scenarioIndex = weightedChoice(lol)
scenarioIndex = wc.choose()[1]
Level.Level.initializeLevel(self, self.doId, levelSpec, scenarioIndex) Level.Level.initializeLevel(self, self.doId, levelSpec, scenarioIndex)

View File

@ -841,20 +841,24 @@ def mostDerivedLast(classList):
return result return result
classList.sort(compare) classList.sort(compare)
def weightedChoice(choiceList, rng=random.random): def weightedChoice(choiceList, rng=random.random, sum=None):
"""given a list of (probability,item) pairs, chooses an item based on the """given a list of (weight,item) pairs, chooses an item based on the
probabilities. rng must return 0..1""" weights. rng must return 0..1. if you happen to have the sum of the
sum = 0. weights, pass it in 'sum'."""
for prob, item in choiceList: if sum is None:
sum += prob sum = 0.
for weight, item in choiceList:
sum += weight
rand = rng() rand = rng()
accum = rand * sum accum = rand * sum
for prob, item in choiceList: for weight, item in choiceList:
accum -= prob accum -= weight
if accum <= 0.: if accum <= 0.:
return item return item
# rand must be ~1., and floating-point error prevented accum from # rand is ~1., and floating-point error prevented accum from hitting 0.
# hitting 0. Return the last item. # Or you passed in a 'sum' that was was too large.
# Return the last item.
return item return item
def randFloat(a, b, rng=random.random): def randFloat(a, b, rng=random.random):