Skip to content

Instantly share code, notes, and snippets.

@CyberShadow
Last active July 17, 2023 18:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CyberShadow/930bb7b89aa4073159955c5410d71154 to your computer and use it in GitHub Desktop.
Save CyberShadow/930bb7b89aa4073159955c5410d71154 to your computer and use it in GitHub Desktop.
Subnautica Cyclops energy efficiency Fandom table generator
import ae.utils.text;
import std.algorithm.comparison;
import std.algorithm.iteration;
import std.range;
import std.stdio;
/*
Old values:
|style="text-align: center; width: 25%;"|Ahead Slow
|style="text-align: center; width: 25%;"|9 ⚡/min
|style="text-align: center; width: 25%;"|7 m/sec
|style="text-align: center; width: 25%;"|45 m/⚡
|-
|style="text-align: center; width: 25%;"|Ahead Standard
|style="text-align: center; width: 25%;"|20 ⚡/min
|style="text-align: center; width: 25%;"|9 m/sec
|style="text-align: center; width: 25%;"|27 m/⚡
|-
|style="text-align: center; width: 25%;"|Ahead Flank
|style="text-align: center; width: 25%;"|40 ⚡/min
|style="text-align: center; width: 25%;"|12 m/sec
|style="text-align: center; width: 25%;"|16 m/⚡
*/
static immutable motorModeNoiseValues = [55, 70, 100];
static immutable motorModeSpeeds = [4.68, 6.27, 7.3];
static immutable motorModePowerConsumption = [0.075, 0.165, 0.33];
// Measured empirically
static immutable double[3] speeds = [
(1098-698)/60.,
8.9 /*(1005-578)/60.*/,
(866-242)/60.,
];
enum sonarPowerCost = 10f;
enum pingIterationDuration = 5f;
enum silentRunningPowerCost = 5f;
enum silentRunningIteration = 5f;
enum shieldPowerCost = 50f;
enum shieldRunningIteration = 5f;
enum maxNoiseRange = 150f; // AttackCyclops::UpdateAggression()
void main()
{
union Flags
{
struct
{
bool withSilentRunning;
bool withEfficiencyModule;
bool withSonar;
bool withShield;
}
bool[4] flags;
}
Flags flags;
static immutable string[] flagNames = [
"Silent Running",
"Engine Efficiency Module",
"Sonar",
"Shield Generator",
];
void iterateFlags(void delegate() cb, size_t index = 0)
{
if (index == flags.flags.length)
cb();
else
{
// writeln(`{{Clear}}`);
if (index == 0)
writeln(`<div class="MainPageBox"><div class="lostRiverTabber"><tabber>`);
else
writeln(`{{#tag:tabber|`);
foreach (value; [false, true])
{
flags.flags[index] = value;
writefln("%s %s=", ["Without", "With"][value], flagNames[index]);
iterateFlags(cb, index + 1);
if (value == false)
{
if (index == 0)
writeln("|-|");
else
writeln("{{!}}-{{!}}");
}
}
if (index == 0)
writeln(`</tabber></div></div>`);
else
writeln(`}}`);
}
}
writeln("<!-- Generated using https://gist.github.com/CyberShadow/930bb7b89aa4073159955c5410d71154 -->");
iterateFlags({
write(q"EOF
<table style="width: 100%;" class="article-table" cellspacing="1" cellpadding="1" border="1" align="center">
<tr>
<th scope="col" style="text-align: center; width: 25%;">'''Speed Setting'''</th>
<th scope="col" style="text-align: center; width: 25%;">'''Energy Consumption Rate (⚡/Min)'''</th>
<th scope="col" style="text-align: center; width: 25%;">'''Acceleration (Meters/Sec²)'''</th>
<th scope="col" style="text-align: center; width: 25%;">'''Top speed (Meters/Sec)'''</th>
<th scope="col" style="text-align: center; width: 25%;">'''Efficiency (Meters/⚡)'''</th>
<th scope="col" style="text-align: center; width: 25%;">'''Noise reach (Meters)'''</th>
</tr>
EOF");
struct Result
{
double energyConsumption;
double acceleration;
double topSpeed;
double noise;
double noiseRange;
double efficiency;
}
Result calculate(Flags flags, size_t motorMode)
{
Result result;
result.energyConsumption = motorModePowerConsumption[motorMode];
result.acceleration = motorModeSpeeds[motorMode];
result.topSpeed = speeds[motorMode];
result.noise = motorModeNoiseValues[motorMode];
if (flags.withSilentRunning)
{
result.energyConsumption += silentRunningPowerCost / silentRunningIteration;
result.noise /= 2;
}
if (flags.withEfficiencyModule)
result.energyConsumption /= 3;
if (flags.withSonar)
result.energyConsumption += (sonarPowerCost / pingIterationDuration);
if (flags.withShield)
result.energyConsumption += (shieldPowerCost / shieldRunningIteration);
result.efficiency = result.topSpeed / result.energyConsumption;
result.noiseRange = result.noise / 100 * maxNoiseRange;
return result;
}
Result[3] results = 3.iota.map!(motorMode => calculate(flags, motorMode)).array;
auto bestEfficiency = results[].map!(result => result.efficiency).reduce!max;
foreach (motorMode, result; results)
{
writef(q"EOF
<tr>
<td style="text-align: center; width: 25%%;">%s</td>
<td style="text-align: center; width: 25%%;">%1.1f ⚡/min</td>
<td style="text-align: center; width: 25%%;">%1.1f m/s²</td>
<td style="text-align: center; width: 25%%;">%1.1f m/s</td>
<td style="text-align: center; width: 25%%;">%s%1.1f m/⚡%s</td>
<td style="text-align: center; width: 25%%;">%s m</td>
</tr>
EOF",
["Ahead Slow", "Ahead Standard", "Ahead Flank"][motorMode],
result.energyConsumption * 60,
result.acceleration,
result.topSpeed,
result.efficiency == bestEfficiency ? "'''" : "", result.efficiency, result.efficiency == bestEfficiency ? "'''" : "",
result.noiseRange.doubleToString,
);
}
writeln("</table>");
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment