Exemplo n.º 1
0
class MagicItemDistribution(object):

    # these are the names (and order) of the stats that all magical
    # items will have
    stats_names = ("dexterity", "constitution", "strength",
                   "intelligence", "wisdom", "charisma")

    def __init__(self, bonus_probs, stats_probs, rso=np.random):
        """Initialize a magic item distribution parameterized by `bonus_probs`
        and `stats_probs`.

        Parameters
        ----------
        bonus_probs: numpy array of length m
            The probabilities of the overall bonuses. Each index in
            the array corresponds to the bonus of that amount (e.g.
            index 0 is +0, index 1 is +1, etc.)

        stats_probs: numpy array of length 6
            The probabilities of how the overall bonus is distributed
            among the different stats. `stats_probs[i]` corresponds to
            the probability of giving a bonus point to the ith stat,
            i.e. the value at `MagicItemDistribution.stats_names[i]`.

        rso: numpy RandomState object (default: np.random)
            The random number generator

        """
        # Create the multinomial distributions we'll be using
        self.bonus_dist = MultinomialDistribution(bonus_probs, rso=rso)
        self.stats_dist = MultinomialDistribution(stats_probs, rso=rso)

    def sample(self):
        """Sample a random magical item.

        Returns
        -------
        dictionary
            The keys are the names of the stats, and the values are
            the bonus conferred to the corresponding stat.

        """
        stats = self._sample_stats()
        item_stats = dict(zip(self.stats_names, stats))
        return item_stats

    def log_pmf(self, item):
        """Compute the log probability the given magical item.

        Parameters
        ----------
        item: dictionary
            The keys are the names of the stats, and the values are
            the bonus conferred to the corresponding stat.

        Returns
        -------
        float
            The value corresponding to log(p(item))

        """
        # First pull out the bonus points for each stat, in the
        # correct order, then pass that to _stats_log_pmf.
        stats = np.array([item[stat] for stat in self.stats_names])
        log_pmf = self._stats_log_pmf(stats)
        return log_pmf

    def pmf(self, item):
        """Compute the probability the given magical item.

        Parameters
        ----------
        item: dictionary
            The keys are the names of the stats, and the values are
            the bonus conferred to the corresponding stat.

        Returns
        -------
        float
            The value corresponding to p(item)

        """
        return np.exp(self.log_pmf(item))

    def _sample_bonus(self):
        """Sample a value of the overall bonus.

        Returns
        -------
        integer
            The overall bonus

        """
        # The bonus is essentially just a sample from a multinomial
        # distribution with n=1; i.e., only one event occurs.
        sample = self.bonus_dist.sample(1)

        # `sample` is an array of zeros and a single one at the
        # location corresponding to the bonus. We want to convert this
        # one into the actual value of the bonus.
        bonus = np.argmax(sample)
        return bonus

    def _sample_stats(self):
        """Sample the overall bonus and how it is distributed across the
        different stats.

        Returns
        -------
        numpy array of length 6
            The number of bonus points for each stat

        """
        # First we need to sample the overall bonus
        bonus = self._sample_bonus()

        # Then, we use a different multinomial distribution to sample
        # how that bonus is distributed. The bonus corresponds to the
        # number of events.
        stats = self.stats_dist.sample(bonus)
        return stats

    def _bonus_log_pmf(self, bonus):
        """Evaluate the log-PMF for the given bonus.

        Parameters
        ----------
        bonus: integer
            The total bonus.

        Returns
        -------
        float
            The value corresponding to log(p(bonus))

        """
        # Make sure the value that is passed in is within the
        # appropriate bounds
        if bonus < 0 or bonus >= len(self.bonus_dist.p):
            return -np.inf

        # Convert the scalar bonus value into a vector of event
        # occurrences
        x = np.zeros(len(self.bonus_dist.p))
        x[bonus] = 1

        return self.bonus_dist.log_pmf(x)

    def _stats_log_pmf(self, stats):
        """Evaluate the log-PMF for the given distribution of bonus points
        across the different stats.

        Parameters
        ----------
        stats: numpy array of length 6
            The distribution of bonus points across the stats

        Returns
        -------
        float
            The value corresponding to log(p(stats))

        """
        # There are never any leftover bonus points, so the sum of the
        # stats gives us the total bonus.
        total_bonus = np.sum(stats)

        # First calculate the probability of the total bonus
        logp_bonus = self._bonus_log_pmf(total_bonus)

        # Then calculate the probability of the stats
        logp_stats = self.stats_dist.log_pmf(stats)

        # Then multiply them together (using addition, because we are
        # working with logs)
        log_pmf = logp_bonus + logp_stats
        return log_pmf
Exemplo n.º 2
0
class MagicItemDistribution(object):

    # these are the names (and order) of the stats that all magical
    # items will have
    stats_names = ("dexterity", "constitution", "strength",
                   "intelligence", "wisdom", "charisma")

    def __init__(self, bonus_probs, stats_probs, rso=np.random):
        """Initialize a magic item distribution parameterized by `bonus_probs`
        and `stats_probs`.

        Parameters
        ----------
        bonus_probs: numpy array of length m
            The probabilities of the overall bonuses. Each index in
            the array corresponds to the bonus of that amount (e.g.
            index 0 is +0, index 1 is +1, etc.)

        stats_probs: numpy array of length 6
            The probabilities of how the overall bonus is distributed
            among the different stats. `stats_probs[i]` corresponds to
            the probability of giving a bonus point to the ith stat,
            i.e. the value at `MagicItemDistribution.stats_names[i]`.

        rso: numpy RandomState object (default: np.random)
            The random number generator

        """
        # Create the multinomial distributions we'll be using
        self.bonus_dist = MultinomialDistribution(bonus_probs, rso=rso)
        self.stats_dist = MultinomialDistribution(stats_probs, rso=rso)

    def sample(self):
        """Sample a random magical item.

        Returns
        -------
        dictionary
            The keys are the names of the stats, and the values are
            the bonus conferred to the corresponding stat.

        """
        stats = self._sample_stats()
        item_stats = dict(zip(self.stats_names, stats))
        return item_stats

    def log_pmf(self, item):
        """Compute the log probability the given magical item.

        Parameters
        ----------
        item: dictionary
            The keys are the names of the stats, and the values are
            the bonus conferred to the corresponding stat.

        Returns
        -------
        float
            The value corresponding to log(p(item))

        """
        # First pull out the bonus points for each stat, in the
        # correct order, then pass that to _stats_log_pmf.
        stats = np.array([item[stat] for stat in self.stats_names])
        log_pmf = self._stats_log_pmf(stats)
        return log_pmf

    def pmf(self, item):
        """Compute the probability the given magical item.

        Parameters
        ----------
        item: dictionary
            The keys are the names of the stats, and the values are
            the bonus conferred to the corresponding stat.

        Returns
        -------
        float
            The value corresponding to p(item)

        """
        return np.exp(self.log_pmf(item))

    def _sample_bonus(self):
        """Sample a value of the overall bonus.

        Returns
        -------
        integer
            The overall bonus

        """
        # The bonus is essentially just a sample from a multinomial
        # distribution with n=1, i.e., only one event occurs.
        sample = self.bonus_dist.sample(1)

        # `sample` is an array of zeros and a single one at the
        # location corresponding to the bonus. We want to convert this
        # one into the actual value of the bonus.
        bonus = np.argmax(sample)
        return bonus

    def _sample_stats(self):
        """Sample the overall bonus and how it is distributed across the
        different stats.

        Returns
        -------
        numpy array of length 6
            The number of bonus points for each stat

        """
        # First we need to sample the overall bonus.
        bonus = self._sample_bonus()

        # Then, we use a different multinomial distribution to sample
        # how that bonus is distributed. The bonus corresponds to the
        # number of events.
        stats = self.stats_dist.sample(bonus)
        return stats

    def _bonus_log_pmf(self, bonus):
        """Evaluate the log-PMF for the given bonus.

        Parameters
        ----------
        bonus: integer
            The total bonus.

        Returns
        -------
        float
            The value corresponding to log(p(bonus))

        """
        # Make sure the value that is passed in is within the
        # appropriate bounds.
        if bonus < 0 or bonus >= len(self.bonus_dist.p):
            return -np.inf

        # Convert the scalar bonus value into a vector of event
        # occurrences
        x = np.zeros(len(self.bonus_dist.p))
        x[bonus] = 1

        return self.bonus_dist.log_pmf(x)

    def _stats_log_pmf(self, stats):
        """Evaluate the log-PMF for the given distribution of bonus points
        across the different stats.

        Parameters
        ----------
        stats: numpy array of length 6
            The distribution of bonus points across the stats

        Returns
        -------
        float
            The value corresponding to log(p(stats))

        """
        # There are never any leftover bonus points, so the sum of the
        # stats gives us the total bonus.
        total_bonus = np.sum(stats)

        # First calculate the probability of the total bonus
        logp_bonus = self._bonus_log_pmf(total_bonus)

        # Then calculate the probability of the stats
        logp_stats = self.stats_dist.log_pmf(stats)

        # Then multiply them together (using addition, because we are
        # working in log-space)
        log_pmf = logp_bonus + logp_stats
        return log_pmf
Exemplo n.º 3
0
class MagicItemDistribution(object):
    """rpg游戏中杀死怪物后掉落魔法装备的概率采样"""

    stats_names = ('dexterity', 'constitution', 'strength',
                   'intelligence', 'wisdom', 'charisma')

    def __init__(self, bonus_probs, stats_probs, rso=np.random):
        """初始化魔法装备的随机分布

        :param bonus_probs: 奖励的概率
        :param stats_probs: 奖励在玩家的各个属性中的分布
        """
        self.bonus_dist = MultinomialDistribution(bonus_probs, rso=rso)
        self.stats_dist = MultinomialDistribution(stats_probs, rso=rso)

    def _sample_bonus(self):
        """采样奖励"""

        # 只有一个事件发生
        sample = self.bonus_dist.sample(1)

        bonus = np.argmax(sample)
        return bonus

    def _sample_stats(self):
        """采样所有的奖励,以及奖励在不同的属性中如何分布"""

        bonus = self._sample_bonus()
        stats = self.stats_dist.sample(bonus)
        return stats

    def sample(self):
        """采样获得一个随机的魔法装备"""

        stats = self._sample_stats()
        item_stats = dict(zip(self.stats_names, stats))
        return item_stats

    def log_pmf(self, item):
        """计算给定的魔法装备的概率质量函数对数"""

        stats = np.array([item[stat] for stat in self.stats_names])
        log_pmf = self._stats_log_pmf(stats)
        return log_pmf

    def pmf(self, item):
        """计算给定装备的概率质量函数"""

        return np.exp(self.log_pmf(item))

    def _stats_log_pmf(self, stats):

        total_bonus = np.sum(stats)
        logp_bonus = self._bonus_log_pmf(total_bonus)
        logp_stats = self.stats_dist.log_pmf(stats)

        log_pmf = logp_bonus + logp_stats
        return log_pmf

    def _bonus_log_pmf(self, bonus):

        if bonus < 0 or bonus >= len(self.bonus_dist.p):
            return -np.inf

        x = np.zeros(len(self.bonus_dist.p))
        x[bonus] = 1

        return self.bonus_dist.log_pmf(x)