根据距离点的距离从列表中选择一个随机项?

时间:2012-07-23 00:40:42

标签: python random statistics twisted distribution

我在Twisted的帮助下用Python编写游戏服务器。我有一个Map类,它为游戏生成地图。在我的游戏中,我有一个中心点,每个特定距离向外的项目环。我想随机化项目,还要加权项目,以便它们在地图外部更常见。目前这是我用于构建地图的代码,其中一些变量和函数名称已更改:

def generate():
    centralItem = Item(ITEM_TYPE_GOLD, 0, 0, ITEM_SIZE_GIANT, None)
    self.items.append(centralItem)
    distance = 10000
    numberOfRings = 100
    for ring in range(numberOfRings):
        itemsInRing = (ring + 1) * 100
        distanceToRing = (ring + 1) * distance
        for item in range(itemsInRing):
            angle = math.radians(float(360) / itemsInRing) * item
            xPos = math.cos(angle) * distanceToRing
            yPos = math.sin(angle) * distanceToRing
            # set variable itemSize using method described above (details below)
            # set variable itemType using method described above (details below)

我还有一个用于创建项目的初始化程序。

class Item:

def __init__(self, type, posX, posY, size, owner):
    self.type = type
    self.posX = float(posX)
    self.posY = float(posY)
    self.size = size
    self.owner = owner

这些是我的定义。

ITEM_TYPE_FIRE = 0
ITEM_TYPE_ICE = 1
ITEM_TYPE_WIND = 2
ITEM_TYPE_EARTH = 3
ITEM_TYPE_GOLD = 4

ITEM_SIZE_SMALL = 200
ITEM_SIZE_MEDIUM = 350
ITEM_SIZE_LARGE = 500
ITEM_SIZE_GIANT = 1000

基于generate方法中的distanceToRing,我想使,例如,当distanceToRing为1,000,000时,ITEM_SIZE_SMALL最常见,而当distanceToRing为10,000时,最不常见。我还希望ITEM_SIZE_LARGE与其相反,ITEM_SIZE_MEDIUM在中间更常见。至于项目类型,我需要ITEM_TYPE_FIRE和ITEM_TYPE_ICE最常见的1,000,000。对于10,000,ITEM_TYPE_WIND和ITEM_TYPE_EARTH应该更常见。

我知道要提出这个问题很多,但是如果你能提出一种处理这种分配的方法并解释它,我认为我可以解决它。另外,我因为缺乏Python技能而提前道歉。我没有长时间使用它来理解最佳实践甚至一些基础知识。

谢谢你的时间, 布赖恩

1 个答案:

答案 0 :(得分:2)

显然,您需要准确确定每种商品类型/尺寸与距离的概率。最简单的答案是制作一个三角形,其峰值位于您喜欢的位置和一致的范围(我将说10000到1000000),如下所示:

item_sizes = [ITEM_SIZE_SMALL, ITEM_SIZE_MEDIUM, ITEM_SIZE_LARGE]

def get_item_weights(distance):
    return [1010000 - distance, 1000000 - abs((505000-distance)*2), distance]

这将为您提供10000件小件物品,大部分物品为1000000件,中间约25/50/25件。也许你不喜欢它的工作方式,但我无从知晓。在构建随机过程时,可能需要一些反复试验才能找到您喜欢的内容。 (从技术上讲,由于505000不是有效距离,因此中间重量将达到990000,但我认为值得花时间修复,尤其是因为您可能不喜欢这种分布。)

要选择给定权重的项目,我会做这样的事情:

import random

random.seed()

def get_random_index(weights):
    n = random.randint(1, sum(weights))
    cumsum = 0
    for index, weight in enumerate(weights):
        cumsum += weight
        if n <= cumsum:
            return index

def get_random_size(distance):
    return item_sizes[get_random_index(get_item_weights(distance))]

...

itemSize = get_random_size(distanceToRing)