openttd 工厂的发展基本逻辑是物流越发达,运货效率越高发展越快,没有交通接入的工厂发展缓慢,最后甚至从地图消失,我们从 OpenTTD | Game Mechanics 可以了解到工厂发展的算法逻辑,简单讲就是每个月会有一定概率改变产量,交通运输服务越好的工厂,变好的概率越高,交通运输服务越差的工厂,变坏的概率越高,工厂产量变化逻辑如下:
1.每个月4.5%概率发生变化
2.不同交通服务变化比例:poor- 33%增产 67%减产: good 67%增产 33%减少; excellent 83%增产 17% 减产
3.上面两者相乘:poor- 1.5%增产 3%减产: good 3%增产 1.5%减少; excellent 3.75%增产 0.75% 减产
有一个特例,Temperate terrain Oil Wells 只会减产不会增产 0%-4.5%概率之间
我们今天从源代码角度看看,它是怎么实现的。 首先我们根据文件名,找到 industry_cmd.cpp 然后搜索 函数,找到 ChangeIndustryProduction(),这里应该就是产量变化的相关逻辑。
工业企业产量变化调用链
industry_cmd.cpp ChangeIndustryProduction() <= 每一个工业设施分别进行调整
<- IndustryMonthlyLoop() <= 大循环,依次处理Industry 这个pool的工业设施
<- date.cpp OnNewMonth() <= 工业产量变化是在每一个月头发生的
<- IncreaseDate() <= 每一天发生的事情
<- openttd.cpp StateGameLoop() <= 单机模式的大循环
首先,关闭工厂的逻辑非常简单 i->prod_level = PRODLEVEL_CLOSURE; level 为 0x00 工厂就关张了。增产和减产稍微复杂一点复杂,我们直接修改 incrment和mul 为1 ,程序会报错,直接会闪退。
Level一共有6个档次:
lowest 0x04 / lower 0x08 / normal 0x10/ higher 0x20/ higher 0x40/ highest 0x80
增长有一个循环,需要在这个循环体里面进行操作。
industry_cmd.cpp Line2672
static void ChangeIndustryProduction(Industry *i, bool monthly)
{
...
/* For industries with only_decrease flags (temperate terrain Oil Wells),
* the multiplier will always be -1 so they will only decrease. */
if (only_decrease) {
mult = -1;
/* For normal industries, if over 60% is transported, 33% chance for decrease.
* Bonus for very high station ratings (over 80%): 16% chance for decrease. */
} else if (Chance16I(1, ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
mult *= -1;
}
mult=1; <- 正数1表示产量增长,负数的-1表示产量减少,我们这里强制改为增长
/* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
* determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
if (Chance16I(1, 22, r >> 16)) {
// new_prod += mult * (std::max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
new_prod += mult * (std::max(((RandomRange(50) + 10) * old_prod) >> 2, 1U)); <- 根据随机产生的新的产量,这里我们把数字 向右移动2位 增长概率增大4倍
}
...
我们可以新增两行代码做一个实验,地图所有工厂在短时间内会达到最高产量。我们可以修改重新编译程序,看看每一种类工业的最高产量具体值是多少。