AdaptiveTactics / tests /test_adaptation.js
EphAsad's picture
Upload 61 files
076c3cb verified
/**
* Adaptive Tactics - Adaptation Tests
* Tests for memory ledger, trigger evaluation, package selection
*/
import {
evaluateMajorPackages,
evaluateMinorModifiers,
applyPackageEffects,
applyModifierEffects,
updateMemoryAfterCycle,
getAdaptationHint
} from '../js/adaptation.js';
// Test utilities
function assert(condition, message) {
if (!condition) {
throw new Error(`FAILED: ${message}`);
}
console.log(`PASSED: ${message}`);
}
function createFreshMemory() {
return {
primary_lane_history: [],
eilisia_kill_leads: 0,
mirella_high_heal_cycles: 0,
fast_clear_count: 0,
fracture_line_cycles: 0,
bait_pull_cycles: 0,
throne_rush_count: 0,
last_carry_unit: null,
turns_to_clear_history: []
};
}
const mockPackages = {
western_denial: {
id: 'western_denial',
narrativeHint: 'The western path grows treacherous.',
effect: {
spawnBias: ['W1', 'W2'],
preferredUnits: ['hollow_archer', 'fallen_soldier_spear']
}
},
choke_hold: {
id: 'choke_hold',
narrativeHint: 'The center will not break so easily.',
effect: {
spawnBias: ['C1'],
preferredUnits: ['fallen_soldier_spear', 'enslaved']
}
},
mirellas_price: {
id: 'mirellas_price',
narrativeHint: 'His eyes turn toward your healer.',
effect: {
targetPriorityIncrease: 'mirella'
}
},
fast_pressure: {
id: 'fast_pressure',
narrativeHint: 'He will not wait for you this time.',
effect: {
engagementRadiusBonus: 1,
forwardFlexPlacement: true
}
}
};
const mockModifiers = {
spear_wall: {
id: 'spear_wall',
availableFromCycle: 5,
narrativeHint: 'The crossings bristle with spears.',
effect: {
spawnBias: 'crossings',
preferredUnits: ['fallen_soldier_spear']
}
},
cruel_recall: {
id: 'cruel_recall',
availableFromCycle: 5,
narrativeHint: 'He remembers who struck hardest.',
effect: {
carryTargetBiasMultiplier: 1.5
}
}
};
// Test: No Package in Early Cycles
function testNoPackageEarlyCycles() {
const memory = createFreshMemory();
const package1 = evaluateMajorPackages(memory, mockPackages, 1);
assert(package1 === null, 'Cycle 1 should have no package');
const package2 = evaluateMajorPackages(memory, mockPackages, 2);
assert(package2 === null, 'Cycle 2 should have no package');
}
// Test: Western Denial Trigger
function testWesternDenialTrigger() {
const memory = createFreshMemory();
memory.primary_lane_history = ['west', 'west'];
const pkg = evaluateMajorPackages(memory, mockPackages, 3);
assert(pkg === 'western_denial', `Should trigger western_denial, got ${pkg}`);
}
// Test: Choke Hold Trigger
function testChokeHoldTrigger() {
const memory = createFreshMemory();
memory.primary_lane_history = ['center', 'center'];
const pkg = evaluateMajorPackages(memory, mockPackages, 3);
assert(pkg === 'choke_hold', `Should trigger choke_hold, got ${pkg}`);
}
// Test: Mirella's Price Trigger
function testMirellasPriceTrigger() {
const memory = createFreshMemory();
memory.mirella_high_heal_cycles = 1;
const pkg = evaluateMajorPackages(memory, mockPackages, 3);
assert(pkg === 'mirellas_price', `Should trigger mirellas_price, got ${pkg}`);
}
// Test: Fast Pressure Trigger
function testFastPressureTrigger() {
const memory = createFreshMemory();
memory.fast_clear_count = 2;
const pkg = evaluateMajorPackages(memory, mockPackages, 3);
assert(pkg === 'fast_pressure', `Should trigger fast_pressure, got ${pkg}`);
}
// Test: No Modifier Before Cycle 5
function testNoModifierBeforeCycle5() {
const memory = createFreshMemory();
memory.last_carry_unit = 'eilisia';
const mod3 = evaluateMinorModifiers(memory, mockModifiers, 3);
assert(mod3 === null, 'Cycle 3 should have no modifier');
const mod4 = evaluateMinorModifiers(memory, mockModifiers, 4);
assert(mod4 === null, 'Cycle 4 should have no modifier');
}
// Test: Modifier Available at Cycle 5
function testModifierAtCycle5() {
const memory = createFreshMemory();
memory.last_carry_unit = 'eilisia';
const mod = evaluateMinorModifiers(memory, mockModifiers, 5);
assert(mod !== null, `Cycle 5 should have a modifier, got ${mod}`);
}
// Test: Package Effects Application
function testPackageEffectsApplication() {
const spawnConfig = {};
const aiConfig = {};
applyPackageEffects('western_denial', mockPackages, spawnConfig, aiConfig);
assert(spawnConfig.biasNodes !== undefined, 'Should set spawn bias nodes');
assert(spawnConfig.biasNodes.includes('W1'), 'Should include W1 in bias');
assert(spawnConfig.preferredUnits !== undefined, 'Should set preferred units');
}
// Test: Target Priority Effect
function testTargetPriorityEffect() {
const spawnConfig = {};
const aiConfig = {};
applyPackageEffects('mirellas_price', mockPackages, spawnConfig, aiConfig);
assert(aiConfig.targetPriority !== undefined, 'Should set target priority');
assert(aiConfig.targetPriority.mirella > 1, 'Mirella should have elevated priority');
}
// Test: Modifier Effects Application
function testModifierEffectsApplication() {
const spawnConfig = {};
const aiConfig = {};
applyModifierEffects('cruel_recall', mockModifiers, spawnConfig, aiConfig);
assert(aiConfig.carryBias === 1.5, `Should set carry bias to 1.5, got ${aiConfig.carryBias}`);
}
// Test: Memory Update After Cycle
function testMemoryUpdateAfterCycle() {
const memory = createFreshMemory();
const cycleMetrics = {
playerLaneMovement: { west: 5, center: 2, east: 1 },
eilisiaKills: 3,
mirellaHealCount: 4,
turnsElapsed: 7
};
updateMemoryAfterCycle(memory, cycleMetrics);
assert(memory.primary_lane_history[0] === 'west', 'Should record west as primary lane');
assert(memory.eilisia_kill_leads === 1, 'Should increment Eilisia kill leads');
assert(memory.mirella_high_heal_cycles === 1, 'Should increment Mirella heal cycles');
assert(memory.fast_clear_count === 1, 'Should increment fast clear (7 <= 8)');
assert(memory.turns_to_clear_history[0] === 7, 'Should record turn count');
}
// Test: Adaptation Hint Generation
function testAdaptationHintGeneration() {
const hint = getAdaptationHint('western_denial', null, mockPackages, mockModifiers);
assert(hint.includes('western'), `Hint should mention western, got: ${hint}`);
const combinedHint = getAdaptationHint('fast_pressure', 'cruel_recall', mockPackages, mockModifiers);
assert(combinedHint.includes('wait') || combinedHint.includes('remembers'),
`Combined hint should have both package and modifier content, got: ${combinedHint}`);
}
// Test: Priority of First Triggered Package
function testPackagePriority() {
const memory = createFreshMemory();
// Trigger multiple conditions
memory.primary_lane_history = ['west', 'west'];
memory.mirella_high_heal_cycles = 1;
memory.fast_clear_count = 2;
const pkg = evaluateMajorPackages(memory, mockPackages, 3);
// Should return first triggered (western_denial comes first in code)
assert(pkg === 'western_denial', `First triggered package should win, got ${pkg}`);
}
// Run all tests
function runAllTests() {
console.log('=== Running Adaptation Tests ===\n');
try {
testNoPackageEarlyCycles();
testWesternDenialTrigger();
testChokeHoldTrigger();
testMirellasPriceTrigger();
testFastPressureTrigger();
testNoModifierBeforeCycle5();
testModifierAtCycle5();
testPackageEffectsApplication();
testTargetPriorityEffect();
testModifierEffectsApplication();
testMemoryUpdateAfterCycle();
testAdaptationHintGeneration();
testPackagePriority();
console.log('\n=== All Adaptation Tests Passed ===');
} catch (e) {
console.error('\n=== Test Failed ===');
console.error(e.message);
throw e;
}
}
// Export for use in browser or Node
if (typeof window !== 'undefined') {
window.runAdaptationTests = runAllTests;
}
export { runAllTests };