feat(game): match Ref nation basic card
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { asRecord } from '@sammo-ts/common';
|
||||
|
||||
const STRATEGIC_COMMAND_NAMES = [
|
||||
'필사즉생',
|
||||
'백성동원',
|
||||
'수몰',
|
||||
'허보',
|
||||
'의병모집',
|
||||
'이호경식',
|
||||
'급습',
|
||||
'피장파장',
|
||||
] as const;
|
||||
|
||||
const readFiniteNumber = (value: unknown, fallback = 0): number => {
|
||||
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
||||
if (typeof value === 'string') {
|
||||
const parsed = Number(value);
|
||||
if (Number.isFinite(parsed)) return parsed;
|
||||
}
|
||||
return fallback;
|
||||
};
|
||||
|
||||
const clamp = (value: number, min: number, max: number): number => Math.min(max, Math.max(min, value));
|
||||
|
||||
export const splitNationTraitInfo = (info: string): { pros: string; cons: string } => {
|
||||
const tokens = info.trim().split(/\s+/u).filter(Boolean);
|
||||
return {
|
||||
pros: tokens.filter((token) => token.endsWith('↑')).join(' '),
|
||||
cons: tokens.filter((token) => token.endsWith('↓')).join(' '),
|
||||
};
|
||||
};
|
||||
|
||||
export const resolveMainNationTech = (options: {
|
||||
tech: number;
|
||||
currentYear: number;
|
||||
worldConfig: unknown;
|
||||
worldMeta: unknown;
|
||||
}): { level: number; limited: boolean } => {
|
||||
const config = asRecord(options.worldConfig);
|
||||
const constValues = asRecord(config.const ?? config.consts);
|
||||
const scenarioMeta = asRecord(asRecord(options.worldMeta).scenarioMeta);
|
||||
const maxLevel = Math.max(1, Math.floor(readFiniteNumber(constValues.maxTechLevel, 12)));
|
||||
const initialLevel = Math.max(1, Math.floor(readFiniteNumber(constValues.initialAllowedTechLevel, 1)));
|
||||
const increaseYears = Math.max(1, Math.floor(readFiniteNumber(constValues.techLevelIncYear, 5)));
|
||||
const startYear = readFiniteNumber(scenarioMeta.startYear, options.currentYear);
|
||||
const relativeMaximum = clamp(
|
||||
Math.floor((options.currentYear - startYear) / increaseYears) + initialLevel,
|
||||
1,
|
||||
maxLevel
|
||||
);
|
||||
const level = clamp(Math.floor(options.tech / 1000), 0, maxLevel);
|
||||
return { level, limited: level >= relativeMaximum };
|
||||
};
|
||||
|
||||
export const resolveImpossibleStrategicCommands = (
|
||||
nationMeta: unknown,
|
||||
currentYear: number,
|
||||
currentMonth: number
|
||||
): Array<{ name: string; remainingTurns: number; availableYear: number; availableMonth: number }> => {
|
||||
const meta = asRecord(nationMeta);
|
||||
const currentYearMonth = Math.floor(currentYear) * 12 + Math.floor(currentMonth) - 1;
|
||||
const result: Array<{ name: string; remainingTurns: number; availableYear: number; availableMonth: number }> = [];
|
||||
|
||||
for (const name of STRATEGIC_COMMAND_NAMES) {
|
||||
const nextAvailable = Math.floor(readFiniteNumber(meta[`next_execute_${name}`], 0));
|
||||
if (nextAvailable <= currentYearMonth) continue;
|
||||
result.push({
|
||||
name,
|
||||
remainingTurns: nextAvailable - currentYearMonth,
|
||||
availableYear: Math.floor(nextAvailable / 12),
|
||||
availableMonth: (nextAvailable % 12) + 1,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
};
|
||||
Reference in New Issue
Block a user