Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Optimization 在快进中播放模拟_Optimization_Simulation - Fatal编程技术网

Optimization 在快进中播放模拟

Optimization 在快进中播放模拟,optimization,simulation,Optimization,Simulation,我正在做一个简单的游戏,用户在一个扇区中创建结构,这是一个10x10的网格。有些结构生成资源,有些结构消耗资源。该部门本身可能包含任何结构之外的一些资源。发电机和用户是相关的。例如,一口井可能在产水,然后一个分离器在耗水并制造氢气和氧气,而一个炼油厂在消耗氢气和氧气并制造火箭燃料,等等 它们产生或消耗资源的速率可能因结构而异——我称之为滴答率。每次消费者点击时,它都会首先尝试从行业中围绕它的结构中提取这些资源。如果数量不够,它将尝试从该部门的存储中获取这些数据。如果仍然不够,结构将停止。结构将其

我正在做一个简单的游戏,用户在一个扇区中创建结构,这是一个10x10的网格。有些结构生成资源,有些结构消耗资源。该部门本身可能包含任何结构之外的一些资源。发电机和用户是相关的。例如,一口井可能在产水,然后一个分离器在耗水并制造氢气和氧气,而一个炼油厂在消耗氢气和氧气并制造火箭燃料,等等

它们产生或消耗资源的速率可能因结构而异——我称之为滴答率。每次消费者点击时,它都会首先尝试从行业中围绕它的结构中提取这些资源。如果数量不够,它将尝试从该部门的存储中获取这些数据。如果仍然不够,结构将停止。结构将其生成的资源保存到某个最大值。一旦它们吃饱了,它们就不会产生更多的能量,直到有一部分被消耗掉。如果一个结构停止,它也不会生成更多的资源,但是它已经拥有的资源仍然可以被另一个相邻的结构使用

存在模式并不罕见。例如,如果油井速度非常慢,那么当油井的水用完时,分离器将关闭,然后当分离器的气体用完时,炼油厂将关闭。然后当油井再次生成时,一切都会重新启动

当用户在玩一个扇区时,我以扇区结构的最短滴答率的分辨率连续滴答该扇区。这个很好用。伪代码如下所示:

const numTicks = (Date.now() - lastTickTime) / shortestTickTime;
let currentTickTime = lastTickTime;
for (i = 0; i < numTicks; i++) {
    currentTickTime += shortestTickTime;
    // check the consumers - all structures that are consumers
    for (curConsumer of consumers) {
       if (curConsumer.isRunning && 
           (currentTickTime - curConsumer.lastTickTime >= curConsumer.tickRate) {
           ... check surrounding structures for resources
           if (curConsumer.stillNeedsResources) {
               ... check sector for researches
           }
           if (curConsumer.stillNeedsResources) {
              ... no resources available
              curConsumer.isRunning = false;
           }
        }
        // check the generators - all structures that are generators
        for (curGenerator of generators) {
           if (curGenerator.isRunning && 
               (currentTickTime - curGenerator.lastTickTime >= curGenerator.tickRate) {
               ... add the generated resources
           }
        }
    }
}
          |
        (fuel)
          |
  Refinery output buffer
          |
        (fuel)
          |
       Refinery
        /   \
       /     \
(hydrogen) (oxygen)
    |         |
 Hydrogen   Oxygen
  output    output
  buffer    buffer
    |         |
(hydrogen) (oxygen)
       \     /
        \   /
       Splitter
          |
       (water)
          |
   Well output buffer
          |
       (water)
          |
         well
const numTicks=(Date.now()-lastTickTime)/shortesticktime;
让currentTickTime=lastTickTime;
对于(i=0;i=curConsumer.tickRate){
…检查周围结构的资源
if(curConsumer.stillNeedsResources){
…检查部门进行研究
}
if(curConsumer.stillNeedsResources){
…没有可用的资源
curConsumer.isRunning=false;
}
}
//检查发电机-所有属于发电机的结构
用于(发电机中的发电机){
如果(curGenerator.isRunning&&
(currentTickTime-curGenerator.lastTickTime>=curGenerator.tickRate){
…添加生成的资源
}
}
}
}
现在,我要处理的是一个用户在长时间缺席(比如几天)后返回某个扇区,这时数百或数千个滴答声已经过去。如果我只是天真地尝试播放所有滴答声,可能需要几秒钟或几分钟才能完成


我想知道,对于这种模拟,是否有一些技巧或窍门可以在不打勾的情况下计算净变化。或者,我可以对模拟进行一些更改,使其更易于计算。谢谢!

步骤1:将原始数据转换为“节点图”表单,其中每个节点代表一台机器,生产者位于底部,消费者位于顶部。例如,它可能看起来像:

          |
        (fuel)
          |
       Refinery
        /   \
       /     \
(hydrogen) (oxygen)
       \     /
        \   /
       Splitter
          |
       (water)
          |
         well
注意:如果一台机器有一个输出缓冲区(或输入缓冲区),那么这些缓冲区应该是单独的节点。例如,如果所有东西都有输出缓冲区,则可能如下所示:

const numTicks = (Date.now() - lastTickTime) / shortestTickTime;
let currentTickTime = lastTickTime;
for (i = 0; i < numTicks; i++) {
    currentTickTime += shortestTickTime;
    // check the consumers - all structures that are consumers
    for (curConsumer of consumers) {
       if (curConsumer.isRunning && 
           (currentTickTime - curConsumer.lastTickTime >= curConsumer.tickRate) {
           ... check surrounding structures for resources
           if (curConsumer.stillNeedsResources) {
               ... check sector for researches
           }
           if (curConsumer.stillNeedsResources) {
              ... no resources available
              curConsumer.isRunning = false;
           }
        }
        // check the generators - all structures that are generators
        for (curGenerator of generators) {
           if (curGenerator.isRunning && 
               (currentTickTime - curGenerator.lastTickTime >= curGenerator.tickRate) {
               ... add the generated resources
           }
        }
    }
}
          |
        (fuel)
          |
  Refinery output buffer
          |
        (fuel)
          |
       Refinery
        /   \
       /     \
(hydrogen) (oxygen)
    |         |
 Hydrogen   Oxygen
  output    output
  buffer    buffer
    |         |
(hydrogen) (oxygen)
       \     /
        \   /
       Splitter
          |
       (water)
          |
   Well output buffer
          |
       (water)
          |
         well
第2步:通过(最初)自下而上(从生产者到消费者)确定“当前稳态平均速率”例如,如果一口井每4滴水产1单位水,那么假设它每滴水产0.25单位水;如果一个分离器每3滴水能将1单位水转化为2单位氢和1单位氧,那么最大转化率为0.333水转化为0.666氢和0.333氧,但你已经知道井isn的产水速度不够快,可以确定分离器实际将消耗0.25水来生产0.5氢气和0.25氧气

请注意,如果生产商生产过剩,您需要回溯。例如,如果一口井每2个刻度产生1单位的水,那么您可以假设它每刻度平均产生0.5水;如果分离器每3个刻度可以将1单位的水转化为2单位的氢和1单位的氧,那么您就知道该井正在生产更多的水比分离器所能消耗的水量还多,必须返回油井,并将其产量限制在每滴水0.333

第3步:确定下一件事情发生前的时间(多少滴答声)将改变“当前稳态平均速率”。如果资源可能耗尽(如油井干涸),您需要知道何时会发生。同样,如果“储存容器”(输出缓冲区、输入缓冲区、水箱、燃料储存箱等)变满或变空,然后您需要知道何时也会发生。这一切都基于您拥有的“当前稳态平均速率”——例如,如果一口井的输出缓冲区是空的,并且以每滴水0.5的速率(从井中)取水,然后失水(到分离器)以每滴答0.33水的速率;然后您可以计算它存储的水量以“0.5-0.33=0.17每滴答”的速率增加,并(结合缓冲区的容量)计算输出缓冲区何时将满

请注意,“下一件事情发生前的滴答声数”也必须限制在您希望停止模拟的时间

步骤4:将时间提前到下一件事情发生。这主要意味着使用您拥有的“当前稳态平均速率”更新“存储容器”中存储的物料量;然后修改任何信息(例如,将油井设置为“非功能”)