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
weights, pass it in 'sum'."""
if sum is None:
sum = 0. sum = 0.
for prob, item in choiceList: for weight, item in choiceList:
sum += prob 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):