本篇教程由作者设定使用 CC BY-NC-SA 协议。

写在前面的声明

本教程的Minecraft版本为1.12.2,对应的血魔法2mod版本为2.4.3-105且无任何魔改;

本教程所得出的结论仅由个人理论,AI检验和游戏内单人测试得到,并未得到广泛测试;

本教程有关血之祭坛容量部分均不考虑缓冲区,经游戏内单人测试缓冲区对结果无影响;

本教程有关数值计算方面均默认生物一直在苦难之井范围内,无游戏/网络延迟导致的TPS变化,未使用其他模组来加速 ;

本教程中若无特别说明默认时间单位为t/tick,流体单位为mB。

大体思路

在科技包多模组环境下,游戏流程对血魔法的涉及基本只包含部分魔改合成所需物品,且在科技包的游玩过程中挂机是常态,一并结合科技包逐渐模块化、封包合成的趋势,故对于LP我们可以选择苦难之井生产,其他各种模组的管道抽取,AE系统存储的思路来大批量可挂机获取——故本教程采用血魔法产LP,Mek终极机械管道抽取,AE存储的方式来进行演示。

血之祭坛符文选择

敲定了思路下一步便要聚焦于血之祭坛——血之祭坛在苦难之井产LP中的作用大致有三点:①容纳苦难之井产生的LP;②传输LP给管道/AE/其他存储系统;③在多方块结构中放置符文给仪式产生增益。特别要注意的是如果苦难之井单次产生的LP大于此时血之祭坛空余容量,那么多余的部分便会被浪费。结合以上血之祭坛用途和注意事项,我们可以总结出血之祭坛需要的符文种类:增容/超容促进/转位牺牲/献祭,下列对这些符文逐项对比。


    增容or超容?

    关于增容和超容的问题早有讨论,得出的结论是超容在数量达到15个的时候效果开始超过同数量增容,本教程为了方便及泛用性后述均采用超容符文,故在此给出超容转换为增容的公式:

怎样配比收益最大化?——关于苦难之井产LP方法中血之祭坛符文搭配的研究-第1张图片            即为超容符文计算公式除以增容符文计算公式所得结果向上取整。


    促进or转位?

    促进符文和转位符文之间的区别和高下通过介绍很难阐明,故在此给出数学上的分析:

        每一个促进符文都能加快血之祭坛的LP转移速率,具体说是通过加快转移频率来加快转移速率,故这里以s作为时间单位可以得到转移速率和促进符文数量的关系:
怎样配比收益最大化?——关于苦难之井产LP方法中血之祭坛符文搭配的研究-第2张图片

        而每一个转位符文也能加快血之祭坛的LP转移速率,具体说是通过加快单次转移LP数量来加快转移速率,故这里以s作为时间单位可以得到转移速率和转位符文数量的关系:

怎样配比收益最大化?——关于苦难之井产LP方法中血之祭坛符文搭配的研究-第3张图片                我们可以令h(x)=g(x)-f(x)并求其零点,其非零零点大约在19.42左右,而我们已知转位符文最多生效19个,所以h(x)在问题所在区间上恒为正值,当然我们也可以构造出例如y=20·1.2x-400·1.2x-19(x∈[19,+∞)且x为正整数)的函数来验证双管齐下和只用转位符文的区别和高下,但是这类函数在问题所在区间上均是恒为正值,即在增加LP转移速率方面,转位符文全方面优于促进符文虽然很反直觉


    牺牲or献祭?

    这个简单,既然我们最初确定的思路是通过苦难之井大批量可挂机获取LP,故一定选择献祭符文

综上,我们可以确定血之祭坛应该使用超容、转位、献祭三种符文


最优化求解

既然是最优化问题,就请出模拟退火算法来解决问题即可:

#default_time_scale=tick
#default_volume_scale=mB
#Rune of Augmented Capacity=超容符文
#Displacement Rune=转位符文
#Rune of Sacrifice=献祭符文
#1s=20ticks

import random
import math

global sacrifice_nums,sacrifice_cooldown,initial_vol,total_upgrades,initial_sacrifice_speed
sacrifice_nums=1    #参与献祭的生物数量,请自行修改
sacrifice_cooldown=25    #每25ticks苦难之井伤害一次范围内生物
initial_vol=10000    #血之祭坛初始容量
total_upgrades=184    #血之祭坛能承载的符文数,这里以六级祭坛为例,请自行修改
initial_transfer_speed=1    #血之祭坛初始转移速率
initial_sacrifice_speed=sacrifice_nums*100/sacrifice_cooldown    '''苦难之井初始生产LP速度,这里以中立/友好生物为
                                                                 例,更换生物种类请自行修改数字,女巫请改成25'''
def generate_new():
    augmented_capacity=random.randint(0,total_upgrades)
    displacement=random.randint(0,total_upgrades-augmented_capacity)
    sacrifice=total_upgrades-augmented_capacity-displacement
    return [augmented_capacity,displacement,sacrifice]

def output_caculate(initial):
    augmented_capacity=initial[0]
    displacement=initial[1]
    sacrifice=initial[2]
    transfer_speed=1.2**displacement
    vol=initial_vol*(1.1**augmented_capacity)
    sacrifice_speed=(initial_sacrifice_speed*sacrifice_cooldown)*(1+0.1*sacrifice)/sacrifice_cooldown
    waste=0
    if sacrifice_speed*sacrifice_cooldown>=vol:
        waste+=sacrifice_speed*sacrifice_cooldown-vol
        sacrifice_speed=vol/sacrifice_cooldown
    if sacrifice_speed>=transfer_speed:
        waste+=(sacrifice_speed-transfer_speed)*sacrifice_cooldown
        sacrifice_speed=transfer_speed
    return sacrifice_speed,waste

while True:
    initial=generate_new()
    output,waste=output_caculate(initial)
    if waste==0 and output>initial_sacrifice_speed:
        initial.extend([output,waste])
        break

temperature=1000000
max_iteration=10
while temperature>0.001:
    for _ in range(max_iteration):
        temp=initial[:-2]
        while True:
            k0,k1=random.sample([0,1,2], 2)
            delta=random.randint(-1,1)
            if temp[k0]+delta>=0 and temp[k1]-delta>=0:
                temp[k0]+=delta
                temp[k1]-=delta
                if sum(temp)==total_upgrades:
                    break
        outputtemp,wastetemp=output_caculate(temp)
        temp.extend([outputtemp,wastetemp])
        if temp[-1]==0:    #这里是以中间任意过程均不浪费任何LP为前提条件进行判断的
            if temp[-2]>initial_sacrifice_speed:
                if temp[-2]>=initial[-2]:
                    initial=temp[:]
                else:
                    p=math.exp((temp[-2]-initial[-2])/temperature)
                    if random.random()<p:
                        initial=temp[:]
    temperature*=0.95
print("参与献祭生物个数:%d,超容符文:%d,转位符文:%d,献祭符文:%d,产出:%.2f"%(sacrifice_nums,initial[0],initial[1],
                                                                                        initial[2],initial[3]))
'''注:此问题的最优解不是唯一的,参与献祭生物个数较少的情况下转移速率会比苦难之井生产LP速率大相当一部分即存在
多余的转位符文,故会出现多余的符文位给了超容符文的情况出现'''

结果及结论&大体规律

先说结果:

    当血之祭坛为五级时:

参与献祭生物个数超容符文转位符文献祭符文产出(LP/t)
10218738.8
20248475.2
302682110.4
402880144
502979178
603078211.2
703177243.6
...............
1213374403.2

            当血之祭坛为六级时:

参与献祭生物个数超容符文转位符文献祭符文产出(LP/t)
102416068
2027157

133.6

3030154196.8
4031153260.8
5032152324
6033151386.4
7234148442.4
8335146499.2
9435145558

再说结论&大体规律:

    根据不断改变参与献祭的生物个数获得的数据,可大致绘出如下图像:

怎样配比收益最大化?——关于苦难之井产LP方法中血之祭坛符文搭配的研究-第4张图片

    故我们可以大致得出结论&大体规律:参与献祭生物个数与血之祭坛产出基本上是线性正相关的,与献祭符文数量是线性负相关的,由于血之祭坛存在初始容量和初始转移速率,超容符文和转位符文的数量存在阈值,但整体上是线性正相关的。

使用说明、应用及其他杂项

由于苦难之井涉及到生物即实体,不同的多模组环境及其不同的游玩方式会导致对生物数量或产出速度有不同的要求,故在此建议拷贝上述代码并根据自身需求更改相应参数以获得特定条件下的最优解

以下是游戏内应用:

    参与献祭生物这里选择的是鸡,因为在服务器环境里动物更不易被刷新掉且一格内可以放多只鸡;给鸡回血这里采用的是星辉魔法中的生息座

怎样配比收益最大化?——关于苦难之井产LP方法中血之祭坛符文搭配的研究-第5张图片

    如果只产LP抽LP的话可以采用Mek的终极机械管道,抽取速度远大于上述所有速度,绝对够用。

怎样配比收益最大化?——关于苦难之井产LP方法中血之祭坛符文搭配的研究-第6张图片

    但是考虑到苦难之井每攻击一个生物就要消耗灵魂网络/自身2LP且LP产量过大时对AE网络存在不小的压力,故可以将终极机械管道替换为ME流体输入总线+ME流体标准发信器+ME触发总线的组合来实现双形态转化:

怎样配比收益最大化?——关于苦难之井产LP方法中血之祭坛符文搭配的研究-第7张图片


            血之祭坛上放已绑定自身的气血宝珠,下面放ME流体输入总线+ME流体标准发信器+ME触发总线的组合(由于空间不足无法直接用ME流体标准发信器直接控制ME流体输入总线,且ME流体输入总线即使放满四个加速卡也只有12000mB/次的抽取速率,极端情况下并不能满足需求);这样在AE网络中LP不足时抽取血之祭坛内的LP进入AE网络,在AE网络中LP充足时血之祭坛内的LP可以通过气血宝珠添加到灵魂网络中,实现双形态转换。(由于Mek终极机械管道存在内部缓存,双形态转换的血之祭坛并不建议使用Mek终极机械管道)