当资源快要用尽时,如何在工厂之间公平地分配资源?


12

我游戏的主要资源是mass,存储为随时间变化的浮点数。资源节点增加了质量,工厂将其排干了。例如,如果我有一个资源节点每秒产生5个质量,那么我将在5 * deltaT每个游戏步骤中获得质量。质量显示四舍五入到最接近的整数,并且增益/损耗指示器显示十分之一。

我应该如何处理质量达到零的问题?如果多个工厂试图一次建立工厂,这将产生竞争条件:工厂排在第一位,或者消耗较少资源的工厂一旦获得更多资源而获得优先权,因此建造速度比其他工厂快。

我该如何处理?我应该完全跳过这一步吗?


ah,我的评论没有保存。我的爆炸效果更好。基本上,我有一个资源,每个对象的每一步都可以访问。每个对象从资源中增加或减少资源。我的问题是,如果资源为0,我不知道该怎么办。我应该排队吗?我应该跳过对象的步骤。什么?
暴徒

3
轮巡。问题解决了。
Patrick Hughes 2012年

下面来自Roy的答案加上对它的评论,描述了一个体面,易于维护和调整的循环系统。只要您解决了当下的设计问题,一切都会很好=)
Patrick Hughes

Answers:


9

我同意彼得的观点:没有固定的方法可以做到。您想怎么做取决于您想如何设计游戏。

但是,在这种情况下,我认为您要尝试达到的机制很明显:您只希望事物在尽可能多的质量范围内尽可能快地生产。

产能内生产

我要从“最高指挥官”的书中抽出一片,因为您的系统非常类似于他们的系统:如果您生产的产能超过了产能,那么处理它的最简洁的方法就是全面降低产能。降低生产能力实际上非常简单。

生产速度技工

在每个更新步骤中,您的工厂不仅会生产固定数量的产品:它们以生产速度运行,这决定了他们在每个步骤中取得了多少进展以及消耗了多少质量。当您以75%的产能生产时,您的工厂每一步的进度可提高75%,并且与100%的产能相比,将消耗75%的质量。

为了计算生产速度,在完全构建任何东西之前,您应该查询工厂以确定该步骤将满负荷使用的总资源。然后执行一个简单的计算:

production speed = (total mass capacity / mass required this step)
if (production speed > 1.0) production speed = 1.0

假设此步骤需要125质量才能满负荷生产,但此步骤只有100质量。该方程式的生产速度为0.8(十进制表示为80%)。当您告诉工厂实际执行建造时,您便将这个值交给他们,以告诉他们建造的速度:现在,您的生产全线减慢。

备择方案

您也可以开始暂时关闭工厂,直到生产能力释放为止,并且当产能极低时,远离发电机的工厂会发生这种情况可能非常有趣。

多种资源?

由您决定如何处理;有很多选择。最简单的方法可能是计算每种资源的生产能力,然后选择最低的资源,这样,最弱的资源将成为所有其他资源的瓶颈。


我认为您甚至不需要告诉工厂以80%的速度生产,因为工厂创建的任何东西都会使用固定的质量。例如:您建造了一个要制造100质量的水箱,通常工厂每个周期可以使用2质量。这意味着需要50个周期来完成储罐,并且每个周期将储罐的当前质量加2。现在,您只有1个可用质量,这意味着在此循环中,当前消耗的坦克的质量增加了1,而不是2。在每个周期之后,只需检查当前质量与所需的总质量即可,以查看坦克是否已完全建造。
托马斯

如果您有0质量可用,那就不要在水箱中增加任何质量。以这种方式构建某些东西所需的时间可能会因您的大量收入而异。如果您有2个工厂可以使用2个质量/周期,并且只有3个收入,则将1个罐构建为50个周期,将2个罐构建为100个。另一种方法是将可用质量的总量除以使用它的所有工厂(积极建立东西)。通过增加工厂级别,可以升级工厂可以使用的总质量。例如,在1级时,他们可以花费2倍质量,在2级时:3
Thomas

@Thomas与仅完成一定百分比的产品相比,在制造过程中向产品添加质量似乎过于复杂。尤其是这样,因为您的工厂必须了解所有有关资源系统的知识,而不是简单的“生产率”属性。如果给玩家的结果是相同的,则使实施尽可能简单。这也使得将来进行更改(例如添加/删除资源)时更加容易。
Hackworth

@Hackworth我倾向于不同意,工厂不需要了解资源系统。工厂只知道它在建造什么以及距离有多远。资源系统只是告诉工厂将X数量添加到构建中。这样,您无需计算该工厂拥有的资源收入的百分比,也不需要将资源收入转换为增加的完工百分比。
托马斯

6

尽管我喜欢Jonathan Hobbs的回答,但我认为队列系统甚至更简单:

Queue<Factory> queue = ...;
int numFactories = ...;

Update()
{
    int resources = GetAllResourcesForThisStep();
    for(int i = 0; i < numFactories; i++)
    {
        if(queue.Peak().RequiredResources <= resources)
        {
            Factory f = queue.Pop();
            resources -= f.RequiredResources;
            queue.Push(f);
        }
        else
        {
            break;
        }
    }
}

平均而言,这可能与乔纳森(Jonathan)的实施方式相同。但是,如果将工作速度设置得很低,并且我的实现中可能有一个工厂对此资源有很高的请求,而乔纳森的解决方案可能会阻塞其他工厂几个框架,那么乔纳森的解决方案可能会出现问题。


+1我正在开发具有双重资源的游戏,就像在问题中一样,当我着手解决供应锁定问题时,我计划使用与此类似的东西。不是确切的代码,而是背后的想法。能够在一刻内使用资源的消费者在下一个刻内将获得较低的优先级。我还计划添加一个标志以指示此使用者是否具有较高的优先级,并将对该标志的控制权交给用户。
约翰·麦克唐纳

如果给他们单独的优先级,请当心饥饿。:)
Roy T.

饥饿的目的却是单独的。曾经玩过《定居者4》或《骑士与商人》吗?如果您过度建造建筑物,则有限的资源将流向随机的建筑物,并且永久性地完成任何事情。但是,它们还允许您选择建筑物是否重要,在这种情况下,资源将首先用于那些重要的建筑物。关键是永远不要过度构建,或者如果可能的话,则尽可能减少过度构建。
约翰·麦当劳

5

我正在自己的游戏中开发类似的供应系统,因此我也一直在思考如何解决供应锁定问题和偏爱。为了说明问题,我将创建一个简单的示例:

如果您有一个列表:[生产者1,消费者1,消费者2,消费者3],并且从供应= 0开始按顺序进行更新,则会得到以下信息:

producer1 produces 5 mass. You now have 5 mass
consumer1 wants 3 mass. Success, you now have 2 mass
consumer2 wants 3 mass. Fail
consumer3 wants 3 mass. Fail
[next tick]
producer1 produces 5 mass. You now have 7 mass
consumer1 wants 3 mass. Success, you now have 4 mass
consumer2 wants 3 mass. Success, you now have 1 mass
consumer3 wants 3 mass. Fail
etc...

消费者1得到所有的乐趣,而消费者2和3则挨饿,直到满足消费者1。根据您的游戏,这可能不是理想的。我知道在我的游戏中不是。当我解决这个问题时,我将创建一个队列,在此队列中被喂食的消费者将移至队列的下一个队列,这是Roy T.所追求的。上面的示例如下所示:

producer1 produces 5 mass. You now have 5 mass
consumer1 wants 3 mass. Success, you now have 2 mass. <-- Move to end of queue
consumer2 wants 3 mass. Fail
consumer3 wants 3 mass. Fail
[next tick]
producer1 produces 5 mass. You now have 7 mass
consumer2 wants 3 mass. Success, you now have 4 mass  <-- Note the order change
consumer3 wants 3 mass. Success, you now have 1 mass
consumer1 wants 3 mass. Fail
etc...

这样,每个人都将获得应有的资源份额。

我还计划实现一个用作优先级队列的附加队列,以便用户可以选择某些具有资源优先级的结构。优先级队列将始终在标准队列之前提供。确保首先更新所有生产者,然后再消耗所有资源,否则当您在生产价格变动的途中生产资源并且某些消费者已经挨饿时,队列将中断。

总结一下:更新生产者,然后更新优先级队列,将联邦消费者移至优先队列的末尾,然后更新标准队列,将联邦消费者移至标准队列的末尾。


达到极限,这可能意味着没有一个消费者能够完成,直到每个消费者都能完成。在现实的生产链场景中,这不太可能发生,如果有人想为一支庞大的军队提供建造队列,那将是灾难性的。在军队建设的整个过程中,他几乎都不会成为部队。
Cardin

这个答案是我阅读问题时最初的想法。另外,应该注意的是,每次报价消耗的质量不一定是创建一个完整单位的质量,而是在所需时间内的单位成本,因此,我不确定@Cardin的关注点是否有效,除非您的单位每跳成本非常接近您的总收集率。我只是简单地让玩家明确管理优先级队列,以便他决定谁饿了。
brice 2012年

@Cardin,您说得很对,但是它也可以用作游戏机制。定居者4,骑士与商人,彻底歼灭,最高统帅是我所知道的做到这一点的游戏。诀窍是不要触及该电源锁,如果确实如此,请确保尽快离开电源锁。添加优先级队列可以使人们更轻松地出门。
约翰·麦当劳

3

好吧,由于我们在聊天中对此进行了一些讨论,因此我将继续介绍John的想法。

编辑:实际上,仅当consumableAmount与工厂应多长时间获取一批资源相关时,此解决方案才是首选方案。如果都一样,那么您确实可以只使用一个队列。

我的解决方案:优先级队列中列出的所有工厂。由于工厂遭受饥饿之害,优先级增加了。工厂消耗资源时,饥饿优先级设置为零。头等大事总是获得下一批资源。

在确定哪个工厂获得什么资源时,采用某种伪代码:

iterator i = factoryqueue.start()
bool starvation = false
while(i.next())
  if(i.ready)
    if (!starvation) 
      if (i.consumeAmount < resource.count) starvation = true
      else 
        i.consume(resource)
        i.priority = 0
    if (starvation)
      i.priority += 1

这样,您的工厂将依次生产1种产品,如果您想通过考虑消耗量来进行调整,以便更便宜地生产便宜的产品,则可以将优先级提高1 / consumeAmount。


我想对此表示赞成,但我不确定这是要做什么-它可以跟踪饥饿,但否则(大概)只是像通常一样在队列中轮换,并且饥饿和优先级都永远不会消失做任何事。
doppelgreener 2012年

如果将优先级增加+ = 1 / amountThisFactoryConsumes,则区别变得明显,那么需要更多资源来创建产品的优先级将滞后一点,从而使较便宜的资源可以按比例分配更多批资源。这将使每个工厂的资源比例平均化。但是,这仍然不是万无一失的证明,因为每次工厂消耗资源时,饥饿编号就设置为魔术数字0,因此当资源更新动荡时,它不会被完全均匀地分配。
托尼2012年

实际上,我现在不确定是否真的不能保证。我将需要绘制一些图形并进行测试以确保。
托尼2012年

哦,优先级是优先级队列本身的质量。我不会费心解释如何构建一个。优先级队列本身总是根据其成员的优先级值进行排序。
托尼2012年

+1知道这是一个优先级队列,它的工作现在看起来很简单:在队列中进行筛选,并找出可能消耗资源的最快事物。如果容量被严重分配(此刻您有1,000个资源,而构建100个资源却有100个资源),这应该不成问题,并且一切都很好。即使此刻某个东西远远超出您的资源,它最终也可能会节省足够的钱来取得一些进步-这会减慢它的速度,或者将大型事物完全拒之门外,而有利于较小的事物,这是一件好事。我喜欢这个。:)
doppelgreener 2012年

2

奇怪的问题。

我的问题是,如果资源为0,我不知道该怎么办。我应该排队吗?我应该跳过对象的步骤。什么?

您需要做什么,取决于创建的游戏逻辑。您可以做一个队列,也可以跳过。取决于您对游戏行为的看法。如果我对您的问题不对,请纠正我。


1

您可以为所有构造保留每个刻度的总资源需求数量。如果一个资源存储命中的数量少于此所需数量,则所有构建将完全停止,直到该存储收集到足以支持至少1个生产周期的价格为止。然后可以恢复生产。

因此,它不是二进制存储生产率,而是二进制的-您的工厂以全速生产还是不以全速生产。

话虽这么说,这种方法与乔纳森(Jonathan)的答案基本相同,在生产率特殊情况下为0.0和1.0的情况下,当0.0 <= f <= 1.0时,任意浮点f可能会更优雅,因为您不会出现不稳定的存储量移动,但逻辑应该更简单一些。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.