2026-07-15 14:44:29 +09:00
"use strict" ;
const fs = require ( "fs" ) ;
const vm = require ( "vm" ) ;
const path = require ( "path" ) ;
const root = path . join ( _ _dirname , ".." ) ;
const source = fs . readFileSync ( path . join ( root , "js" , "achievements.js" ) , "utf8" ) ;
class ClassList {
constructor ( ) { this . values = new Set ( [ "hidden" ] ) ; }
add ( ... names ) { names . forEach ( name => this . values . add ( name ) ) ; }
remove ( ... names ) { names . forEach ( name => this . values . delete ( name ) ) ; }
contains ( name ) { return this . values . has ( name ) ; }
toggle ( name , force ) { const next = force === undefined ? ! this . values . has ( name ) : Boolean ( force ) ; if ( next ) this . values . add ( name ) ; else this . values . delete ( name ) ; return next ; }
}
class Element {
constructor ( id = "" ) { this . id = id ; this . className = "" ; this . classList = new ClassList ( ) ; this . dataset = { } ; this . styles = new Map ( ) ; this . style = { setProperty : ( n , v ) => this . styles . set ( n , v ) , removeProperty : n => this . styles . delete ( n ) } ; this . children = [ ] ; this . textContent = "" ; this . tabIndex = - 1 ; this . isConnected = true ; this . hidden = true ; }
append ( ... children ) { this . children . push ( ... children ) ; } replaceChildren ( ... children ) { this . children = children ; } setAttribute ( ) { } addEventListener ( ) { } focus ( ) { } getBoundingClientRect ( ) { return { left : 0 , top : 0 , width : 100 , height : 30 } ; } get offsetWidth ( ) { return 100 ; }
}
function harness ( storage = new Map ( ) ) {
const elements = new Map ( ) ;
[ "achievementsBtn" , "achievementButtonCount" , "achievementsDialog" , "achievementDialogCount" , "achievementsCloseBtn" , "achievementsCloseIconBtn" , "achievementRefreshBtn" , "achievementResetBtn" , "achievementUnlockAllBtn" , "achievementList" , "achievementSharedStatus" , "achievementToast" , "achievementToastTitle" , "pauseBtn" ] . forEach ( id => elements . set ( id , new Element ( id ) ) ) ;
let timer = 0 ;
const c = { console , Date , Intl , Math , JSON , Object , Array , Map , Set , WeakMap , Promise , Number , String , Boolean , Error , AbortController , encodeURIComponent , URLSearchParams ,
location : { protocol : "file:" , search : "" } , crypto : { randomUUID : ( ) => "11111111-1111-4111-8111-111111111111" } ,
localStorage : { getItem : k => storage . has ( k ) ? storage . get ( k ) : null , setItem : ( k , v ) => storage . set ( k , String ( v ) ) , removeItem : k => storage . delete ( k ) } ,
document : { hidden : false , getElementById : id => elements . get ( id ) || null , createElement : ( ) => new Element ( ) , addEventListener ( ) { } } ,
2026-07-16 22:12:03 +09:00
TarinaiEvents : { emit ( ) { } } , showToast ( ) { } , TarinaiGameDialogs : { confirm : async ( ) => true } , audio : { uiClick ( ) { } } , setTimeout ( ) { return ++ timer ; } , clearTimeout ( ) { } , setInterval ( ) { return ++ timer ; } , clearInterval ( ) { } , fetch : async ( ) => { throw new Error ( "offline" ) ; } , TARINAI _VERSION : "39.16.65" } ;
2026-07-15 14:44:29 +09:00
c . window = c ; c . globalThis = c ; vm . createContext ( c ) ; vm . runInContext ( source , c , { filename : "achievements.js" } ) ;
return { c , api : c . TarinaiAchievements , storage , elements } ;
}
function assert ( v , m ) { if ( ! v ) throw new Error ( m ) ; } function off ( h , id ) { return ! h . api . isUnlocked ( id ) ; } function on ( h , id ) { return h . api . isUnlocked ( id ) ; }
function alive ( n ) { return Array . from ( { length : n } , ( _ , i ) => ( { id : ` t ${ i } ` , dead : false , x : i , y : 0 } ) ) ; }
function findCard ( h , id ) { const stack = [ h . elements . get ( "achievementList" ) ] ; while ( stack . length ) { const node = stack . shift ( ) ; if ( node ? . dataset ? . achievementId === id ) return node ; stack . push ( ... ( node ? . children || [ ] ) ) ; } return null ; }
( function run ( ) {
let h = harness ( ) ;
2026-07-16 22:12:03 +09:00
assert ( h . api . definitions . length === 64 , "must have 64 achievements" ) ;
2026-07-15 14:44:29 +09:00
h . api . open ( ) ;
const title = Object . fromEntries ( h . api . definitions . map ( d => [ d . id , d . title ] ) ) ;
assert ( title . medicine _ledger _all === "おくすり手帳全埋め" , "medicine title" ) ;
assert ( title . mercury _lifespan === "不老不死まであと一歩" , "mercury title" ) ;
const description = ( id ) => findCard ( h , id ) . children [ 1 ] . children [ 0 ] . children [ 1 ] . textContent ;
assert ( description ( "robot_cleaner_100" ) . includes ( "ずんち・死骸・汚れを累計200個処理させる。" ) , "cleaner condition disclosed in UI" ) ;
assert ( description ( "mercury_lifespan" ) . includes ( "水銀を使用したたりないが天寿を全うする。" ) , "mercury condition disclosed in UI" ) ;
assert ( findCard ( h , "enemy_enemy_friend" ) . children [ 1 ] . children . some ( node => node . textContent . includes ( "現在の達成率 0.0%" ) ) , "enemy progress shown in UI" ) ;
assert ( description ( "overprotective" ) === "? ? ? " , "other new condition hidden" ) ;
// One Undo only: multiple smaller Undo operations never aggregate.
h . api . recordHistoryAction ( "undo" , { deadRestored : 9 } ) ; h . api . recordHistoryAction ( "undo" , { deadRestored : 1 } ) ;
assert ( off ( h , "undo_mass_revival" ) , "mass undo aggregated across operations" ) ;
h . api . recordHistoryAction ( "undo" , { deadRestored : 10 } ) ; assert ( on ( h , "undo_mass_revival" ) , "mass undo boundary" ) ;
// Undo/Redo counters persist across field resets and reloads.
let storage = new Map ( ) ; h = harness ( storage ) ;
for ( let i = 0 ; i < 12 ; i ++ ) h . api . recordHistoryAction ( "undo" , { } ) ;
h . api . resetWorldProgress ( { } ) ;
h = harness ( storage ) ; for ( let i = 0 ; i < 7 ; i ++ ) h . api . recordHistoryAction ( "undo" , { } ) ;
assert ( off ( h , "undo_20" ) , "undo unlocked at 19" ) ; h . api . recordHistoryAction ( "undo" , { } ) ; assert ( on ( h , "undo_20" ) , "undo did not persist to 20" ) ;
for ( let i = 0 ; i < 11 ; i ++ ) h . api . recordHistoryAction ( "redo" , { } ) ; h = harness ( storage ) ; for ( let i = 0 ; i < 8 ; i ++ ) h . api . recordHistoryAction ( "redo" , { } ) ;
assert ( off ( h , "redo_20" ) , "redo unlocked at 19" ) ; h . api . recordHistoryAction ( "redo" , { } ) ; assert ( on ( h , "redo_20" ) , "redo did not persist to 20" ) ;
// Cleaner is field-local.
h = harness ( ) ; const wa = { time : 0 } , wb = { time : 0 } ; h . api . recordRobotClean ( { world : wa , type : "tarinai" } ) ; assert ( ( wa . achievementRobotCleanCount || 0 ) === 0 , "cleaner counted non-cleanup target" ) ;
for ( let i = 0 ; i < 199 ; i ++ ) h . api . recordRobotClean ( { world : wa , type : i % 2 ? "zunchi" : "trace" } ) ;
assert ( off ( h , "robot_cleaner_100" ) , "cleaner before 200" ) ; h . api . recordRobotClean ( { world : wb , type : "ant_corpse" } ) ; assert ( off ( h , "robot_cleaner_100" ) , "cleaner crossed field reset" ) ;
h . api . recordRobotClean ( { world : wa , type : "splat" } ) ; assert ( on ( h , "robot_cleaner_100" ) , "cleaner at 200" ) ;
// Continuous pinch must be uninterrupted and same individual.
h = harness ( ) ; const held = { dead : false , playerHeld : true } ; const hw = { tarinai : [ held ] } ;
h . api . recordHeldTarinai ( hw , 1000 ) ; h . api . recordHeldTarinai ( hw , 30999 ) ; assert ( off ( h , "held_30_seconds" ) , "held before 30s" ) ;
held . playerHeld = false ; h . api . recordHeldTarinai ( hw , 31000 ) ; held . playerHeld = true ; h . api . recordHeldTarinai ( hw , 40000 ) ; h . api . recordHeldTarinai ( hw , 69999 ) ; assert ( off ( h , "held_30_seconds" ) , "held did not reset after release" ) ;
h . c . document . hidden = true ; h . api . recordHeldTarinai ( hw , 70000 ) ; h . c . document . hidden = false ;
h . api . recordHeldTarinai ( hw , 70001 ) ; h . api . recordHeldTarinai ( hw , 100000 ) ; assert ( off ( h , "held_30_seconds" ) , "hidden tab time counted toward hold" ) ;
h . api . recordHeldTarinai ( hw , 100001 ) ; assert ( on ( h , "held_30_seconds" ) , "held at 30s after visible reset" ) ;
// Minimalist counts only surviving player placements.
h = harness ( ) ; let mw = { time : 0 , day : 5 , tarinai : alive ( 1 ) , ants : [ ] , items : Array . from ( { length : 11 } , ( ) => ( { _achievementPlayerPlaced : true , dead : false } ) ) } ;
h . api . evaluateWorld ( mw , { id : "happy" } ) ; assert ( off ( h , "minimalist_happy" ) , "minimalist allowed 11 items" ) ;
mw . items [ 10 ] . dead = true ; h . api . evaluateWorld ( mw , { id : "happy" } ) ; assert ( off ( h , "minimalist_happy" ) , "minimalist unlocked before day 6" ) ;
mw . day = 6 ; h . api . evaluateWorld ( mw , { id : "happy" } ) ; assert ( on ( h , "minimalist_happy" ) , "minimalist at day 6 with 10 items" ) ;
// Overprotective requires both thresholds on the same individual.
h = harness ( ) ; const cared = { dead : false } ; const cw = { time : 0 } ;
for ( let i = 0 ; i < 9 ; i ++ ) h . api . recordDirectFeed ( { world : cw , tarinai : cared , type : "food" } ) ;
for ( let i = 0 ; i < 3 ; i ++ ) h . api . recordDirectCare ( { world : cw , tarinai : cared , type : "first_aid" , treatment : true } ) ;
assert ( off ( h , "overprotective" ) , "overprotective before 10 feeds" ) ; h . api . recordDirectFeed ( { world : cw , tarinai : cared , type : "food" } ) ; assert ( on ( h , "overprotective" ) , "overprotective thresholds" ) ;
// Self-sufficient: 20+, no direct feed, no duplicator, 10 game minutes.
h = harness ( ) ; let sw = { time : 0 , tarinai : alive ( 20 ) , ants : [ ] , items : [ ] } ; h . api . evaluateWorld ( sw , { } ) ; sw . time = 599.99 ; h . api . evaluateWorld ( sw , { } ) ; assert ( off ( h , "self_sufficient" ) , "self sufficient early" ) ;
sw . items . push ( { type : "duplicator" , dead : false } ) ; sw . time = 600 ; h . api . evaluateWorld ( sw , { } ) ; assert ( off ( h , "self_sufficient" ) , "self sufficient with duplicator" ) ;
sw . items = [ ] ; sw . time = 700 ; h . api . evaluateWorld ( sw , { } ) ; sw . time = 1300 ; h . api . evaluateWorld ( sw , { } ) ; assert ( on ( h , "self_sufficient" ) , "self sufficient after clean 10m" ) ;
h = harness ( ) ; sw = { time : 0 , tarinai : alive ( 20 ) , ants : [ ] , items : [ ] } ; h . api . evaluateWorld ( sw , { } ) ; sw . time = 500 ; h . api . recordDirectFeed ( { world : sw , tarinai : sw . tarinai [ 0 ] , type : "food" } ) ; sw . time = 600 ; h . api . evaluateWorld ( sw , { } ) ; assert ( off ( h , "self_sufficient" ) , "direct feed did not reset self sufficient" ) ;
// Unplanned city is persistent and deletion must be within 30 seconds.
storage = new Map ( ) ; h = harness ( storage ) ; let qw = { time : 0 } ;
for ( let i = 0 ; i < 15 ; i ++ ) { const item = { } ; h . api . recordPlayerPlacement ( { world : qw , item } ) ; qw . time = 30 ; h . api . recordPlayerDeletion ( { world : qw , item } ) ; qw . time = 0 ; }
h = harness ( storage ) ; qw = { time : 0 } ; for ( let i = 0 ; i < 14 ; i ++ ) { const item = { } ; h . api . recordPlayerPlacement ( { world : qw , item } ) ; qw . time = 30 ; h . api . recordPlayerDeletion ( { world : qw , item } ) ; qw . time = 0 ; }
assert ( off ( h , "unplanned_city_30" ) , "unplanned at 29" ) ; let item = { } ; h . api . recordPlayerPlacement ( { world : qw , item } ) ; qw . time = 30.001 ; h . api . recordPlayerDeletion ( { world : qw , item } ) ; assert ( off ( h , "unplanned_city_30" ) , "late deletion counted" ) ;
item = { _achievementPlayerPlaced : true , _achievementPlacedAt : null } ; qw . time = 0 ; h . api . recordPlayerDeletion ( { world : qw , item } ) ; assert ( off ( h , "unplanned_city_30" ) , "missing placement timestamp counted" ) ;
item = { } ; qw . time = 0 ; h . api . recordPlayerPlacement ( { world : qw , item } ) ; qw . time = 30 ; h . api . recordPlayerDeletion ( { world : qw , item } ) ; assert ( on ( h , "unplanned_city_30" ) , "unplanned at 30" ) ;
// Sauna -> cold within 15 seconds; cold alone must never unlock.
h = harness ( ) ; const st = { dead : false , x : 0 , y : 0 } ; let temp = 0 ; const tw = { time : 0 , tarinai : [ st ] , ants : [ ] , items : [ ] , feltTemperatureFor ( ) { return temp ; } , temperatureStatusFor ( v ) { return { direction : v > 25 ? "hot" : v < 10 ? "cold" : "comfort" , comfortable : v >= 10 && v <= 25 } ; } } ;
temp = 0 ; h . api . evaluateWorld ( tw , { } ) ; assert ( off ( h , "sauna_cold_plunge" ) , "cold alone unlocked sauna" ) ; temp = 40 ; h . api . evaluateWorld ( tw , { } ) ; tw . time = 15 ; temp = 0 ; h . api . evaluateWorld ( tw , { } ) ; assert ( on ( h , "sauna_cold_plunge" ) , "sauna boundary 15s" ) ;
h = harness ( ) ; const st2 = { dead : false , x : 0 , y : 0 } ; temp = 40 ; const tw2 = { time : 0 , tarinai : [ st2 ] , ants : [ ] , items : [ ] , feltTemperatureFor ( ) { return temp ; } , temperatureStatusFor ( v ) { return { direction : v > 25 ? "hot" : "cold" , comfortable : false } ; } } ; h . api . evaluateWorld ( tw2 , { } ) ; tw2 . time = 15.01 ; temp = 0 ; h . api . evaluateWorld ( tw2 , { } ) ; assert ( off ( h , "sauna_cold_plunge" ) , "sauna allowed over 15s" ) ;
// Rain shelter requires all 20 and accepts nest/pipe via shelter system.
h = harness ( ) ; h . c . TarinaiRainShelterSystem = { isSheltered ( _w , _x , _y , t ) { return Boolean ( t . sheltered ) ; } } ;
const rw = { time : 0 , weather : "light_rain" , tarinai : alive ( 20 ) . map ( t => ( { ... t , sheltered : true } ) ) , ants : [ ] , items : [ ] } ; h . api . evaluateWorld ( rw , { } ) ; assert ( on ( h , "rain_shelter_all" ) , "all sheltered rain achievement" ) ;
h = harness ( ) ; h . c . TarinaiRainShelterSystem = { isSheltered ( _w , _x , _y , t ) { return Boolean ( t . sheltered ) ; } } ; rw . tarinai [ 19 ] . sheltered = false ; h . api . evaluateWorld ( rw , { } ) ; assert ( off ( h , "rain_shelter_all" ) , "rain achievement allowed one exposed" ) ;
// Nest boxes and pipes are genuine weather blockers, not only achievement stubs.
h = harness ( ) ;
vm . runInContext ( fs . readFileSync ( path . join ( root , "js" , "tarinai_local_environment_system.js" ) , "utf8" ) , h . c , { filename : "tarinai_local_environment_system.js" } ) ;
const nest = { id : "n1" , type : "nest_box" , dead : false } ;
const pipe = { id : "p1" , type : "pipe" , dead : false } ;
const shelterWorld = { items : [ nest , pipe ] , nestBoxById ( id ) { return this . items . find ( x => x . id === id ) || null ; } } ;
assert ( h . c . TarinaiRainShelterSystem . isSheltered ( shelterWorld , 0 , 0 , { insideNestBoxId : "n1" } ) , "nest box did not block weather" ) ;
assert ( h . c . TarinaiRainShelterSystem . isSheltered ( shelterWorld , 0 , 0 , { insideNestBoxId : "p1" } ) , "pipe did not block weather" ) ;
assert ( ! h . c . TarinaiRainShelterSystem . isSheltered ( shelterWorld , 0 , 0 , { } ) , "unsheltered target treated as sheltered" ) ;
// Nest-box and pipe occupants must also be insulated from weather temperature offsets.
{
class FakeWorld { }
const tc = { console , Math , Number , Object , Array , Set , Map , WeakMap , Date , CONFIG : { standardTemperature : 15 , temperatureItemRange : 190 } ,
World : FakeWorld , clamp : ( v , a , b ) => Math . max ( a , Math . min ( b , v ) ) , distXY : ( x1 , y1 , x2 , y2 ) => Math . hypot ( x1 - x2 , y1 - y2 ) ,
TarinaiParasolSystem : h . c . TarinaiRainShelterSystem } ;
tc . window = tc ; tc . globalThis = tc ; vm . createContext ( tc ) ;
vm . runInContext ( fs . readFileSync ( path . join ( root , "js" , "world_temperature_system.js" ) , "utf8" ) , tc , { filename : "world_temperature_system.js" } ) ;
const box = { id : "box" , type : "nest_box" , dead : false , x : 0 , y : 0 , r : 42 } ;
const pipeItem = { id : "pipe" , type : "pipe" , dead : false , x : 0 , y : 0 , r : 42 } ;
const weatherWorld = new FakeWorld ( ) ; Object . assign ( weatherWorld , { currentTemperature : 15 , temperatureAuto : true , groundType : "soil" , weather : "light_rain" , items : [ box , pipeItem ] ,
nearbyItems ( x , y , r ) { return this . items . filter ( it => Math . hypot ( it . x - x , it . y - y ) <= r ) ; } , nestBoxById ( id ) { return this . items . find ( x => x . id === id ) || null ; } , nestBoxBaseRect ( ) { return null ; } } ) ;
const outside = { x : 500 , y : 0 } ; const inBox = { x : 0 , y : 0 , insideNestBoxId : "box" } ; const inPipe = { x : 0 , y : 0 , insideNestBoxId : "pipe" } ;
assert ( weatherWorld . feltTemperatureFor ( outside ) < 15 , "rain weather offset missing outside" ) ;
assert ( weatherWorld . feltTemperatureFor ( inBox ) >= 15 , "nest box still received rain temperature offset" ) ;
assert ( weatherWorld . feltTemperatureFor ( inPipe ) >= 15 , "pipe still received rain temperature offset" ) ;
}
// Every medicine item once; chain and crown are explicitly excluded.
h = harness ( ) ; const meds = [ "first_aid" , "sedative" , "sleep_drug" , "laxative" , "protein" , "niteropu" , "ammo" , "mystery_drug" , "mercury" , "giant_drug" , "dwarf_drug" ] ;
meds . slice ( 0 , - 1 ) . forEach ( type => h . api . recordConsumableUse ( { type } ) ) ; assert ( off ( h , "medicine_ledger_all" ) , "medicine ledger early" ) ; h . api . recordConsumableUse ( { type : meds . at ( - 1 ) } ) ; assert ( on ( h , "medicine_ledger_all" ) , "medicine ledger complete" ) ;
// Mercury lifespan, revolution, fight mochi.
h = harness ( ) ; h . api . recordDeath ( { world : { time : 1 , tarinai : [ ] } , tarinai : { lifeItemMode : "mercury" } , reason : "天寿を全うした" } ) ; assert ( on ( h , "mercury_lifespan" ) , "mercury lifespan" ) ;
h = harness ( ) ; const slave = { id : "s" , isZunchiSlave : true , dead : false } ; const king = { id : "k" , isTarinaiChampion : true , dead : true , _achievementLastFightAttackerId : "s" , _achievementLastFightDamageAt : 5 } ; const revWorld = { time : 5 , tarinai : [ slave , king ] } ; h . api . recordDeath ( { world : revWorld , tarinai : king , reason : "喧嘩" , fromDamage : true } ) ; assert ( on ( h , "revolution" ) , "revolution" ) ;
h = harness ( ) ; const oil = { } ; const fw = { time : 0 } ; h . api . recordConsumableUse ( { world : fw , tarinai : oil , type : "fight_mochi" } ) ; fw . time = 30 ; h . api . recordFightStarted ( { world : fw , a : oil , b : { } } ) ; assert ( on ( h , "fuel_to_fire" ) , "fight mochi at 30s" ) ;
h = harness ( ) ; const noOil = { } ; h . api . recordFightStarted ( { world : { time : 0 } , a : noOil , b : { } } ) ; assert ( off ( h , "fuel_to_fire" ) , "fight without mochi unlocked at time zero" ) ;
h = harness ( ) ; const oil2 = { } ; const fw2 = { time : 0 } ; h . api . recordConsumableUse ( { world : fw2 , tarinai : oil2 , type : "fight_mochi" } ) ; fw2 . time = 30.01 ; h . api . recordFightStarted ( { world : fw2 , a : oil2 , b : { } } ) ; assert ( off ( h , "fuel_to_fire" ) , "fight mochi over 30s" ) ;
2026-07-16 22:12:03 +09:00
// Enemy's enemy: 30 alive, danger-item kills, and any dangerous tarinai hit resets the streak.
h = harness ( ) ; const ew = { time : 20 , tarinai : alive ( 30 ) } ;
2026-07-15 14:44:29 +09:00
for ( let i = 0 ; i < 9 ; i ++ ) { const ant = { world : ew } ; h . api . recordAntDamageSource ( ant , { type : "firecracker" } , { world : ew } ) ; h . api . recordAntKilled ( { world : ew , ant } ) ; }
2026-07-16 22:12:03 +09:00
assert ( off ( h , "enemy_enemy_friend" ) , "enemy achievement early" ) ;
h . api . recordDamageSource ( ew . tarinai [ 0 ] , { type : "firecracker" } , { world : ew } ) ;
assert ( ( ew . achievementEnemyAntKills || 0 ) === 0 , "dangerous tarinai damage did not reset enemy streak" ) ;
for ( let i = 0 ; i < 10 ; i ++ ) { const ant = { world : ew } ; h . api . recordAntDamageSource ( ant , { type : "firecracker" } , { world : ew } ) ; h . api . recordAntKilled ( { world : ew , ant } ) ; }
assert ( on ( h , "enemy_enemy_friend" ) , "enemy achievement did not unlock after 10 clean danger kills" ) ;
h = harness ( ) ; const ew2 = { time : 20 , tarinai : alive ( 30 ) } ;
for ( let i = 0 ; i < 5 ; i ++ ) { const ant = { world : ew2 } ; h . api . recordAntDamageSource ( ant , { type : "firecracker" } , { world : ew2 } ) ; h . api . recordAntKilled ( { world : ew2 , ant } ) ; }
ew2 . tarinai [ 0 ] . dead = true ; const resetAnt = { world : ew2 } ; h . api . recordAntDamageSource ( resetAnt , { type : "firecracker" } , { world : ew2 } ) ; h . api . recordAntKilled ( { world : ew2 , ant : resetAnt } ) ;
assert ( ( ew2 . achievementEnemyAntKills || 0 ) === 0 , "population below 30 did not reset enemy streak" ) ;
const ordinary = { world : ew2 } ; h . api . recordAntDamageSource ( ordinary , { type : "food" } , { world : ew2 } ) ; h . api . recordAntKilled ( { world : ew2 , ant : ordinary } ) ; assert ( ( ew2 . achievementEnemyAntKills || 0 ) === 0 , "non-danger ant kill counted" ) ;
h = harness ( ) ; const ew3 = { time : 20 , tarinai : alive ( 30 ) } ; const overwritten = { world : ew3 } ; h . api . recordAntDamageSource ( overwritten , { type : "firecracker" } , { world : ew3 } ) ; h . api . recordAntDamageSource ( overwritten , { id : "t0" } , { world : ew3 } ) ; h . api . recordAntKilled ( { world : ew3 , ant : overwritten } ) ; assert ( ( ew3 . achievementEnemyAntKills || 0 ) === 0 , "stale danger attribution survived later non-danger damage" ) ;
// New observation and sticky-bomb relay achievements.
h = harness ( ) ; const antWorld = { tarinai : [ ] , ants : [ ] , items : [ { type : "ant_nest" , dead : false } ] } ; h . api . evaluateWorld ( antWorld , { } ) ; assert ( on ( h , "ant_nest_without_tarinai" ) , "ant observation condition" ) ;
h = harness ( ) ; const bomb = { type : "sticky_bomb" , dead : false } ; for ( let i = 0 ; i < 14 ; i ++ ) h . api . recordStickyBombPass ( bomb , { } ) ; assert ( off ( h , "sticky_bomb_15_passes" ) , "sticky relay early" ) ; h . api . recordStickyBombPass ( bomb , { } ) ; assert ( on ( h , "sticky_bomb_15_passes" ) , "sticky relay at 15" ) ;
2026-07-15 14:44:29 +09:00
// Static integration guards for all production hook points.
const checks = {
"js/command_dispatcher.js" : [ "deadRestored" , "recordHistoryAction" ] ,
"js/robot_cleaner_system.js" : [ "recordRobotClean" ] ,
"js/world_tool_actions.js" : [ "recordPlayerDeletion" , "recordAntDamageSource" ] ,
"js/world_family_social.js" : [ "resetWorldProgress" , "recordFightStarted" ] ,
"js/tarinai_social_move_life.js" : [ "_achievementLastFightAttackerId" ] ,
"js/tarinai_direct_feeding_system.js" : [ "recordDirectCare" ] ,
"js/tarinai_consumable_behavior.js" : [ "recordConsumableUse" ] ,
"js/tarinai_contact_item_system.js" : [ "recordConsumableUse" , "slave_chain" , "golden_crown" ] ,
"js/world_combat_effects.js" : [ "recordAntDamageSource" , "source: it" ] ,
"js/impact_response_system.js" : [ "source: it" ] ,
"js/ants.js" : [ "recordAntDamageSource" , "tarinai_struggle" ] ,
"js/signal_system.js" : [ "recordAntDamageSource" , "electric_wire" ] ,
"js/tarinai_item_effects.js" : [ "recordAntDamageSource" , "tarinai_ammo_collision" ] ,
"js/tarinai_local_environment_system.js" : [ "enclosedShelterFor" , "nest_box" , "pipe" ] ,
"js/tarinai_update_step_frame.js" : [ "isSheltered?.(t.world, t.x, t.y, t)" ] ,
"js/tarinai_disease_nest.js" : [ "isSheltered?.(this.world, this.x, this.y, this)" ] ,
2026-07-16 22:12:03 +09:00
"js/item_dynamic_tool_system.js" : [ "recordStickyBombPass" , "reason === \"transfer\"" ] ,
"js/snapshot_system.js" : [ "stickyBombPassCount" ] ,
"js/save_codec.js" : [ "sticky_bomb" , "[0, -1, 0], 3" ] ,
2026-07-15 14:44:29 +09:00
} ;
for ( const [ file , needles ] of Object . entries ( checks ) ) { const text = fs . readFileSync ( path . join ( root , file ) , "utf8" ) ; for ( const needle of needles ) assert ( text . includes ( needle ) , ` ${ file } missing ${ needle } ` ) ; }
console . log ( "[OK] playstyle achievements: boundaries, reset scope, persistence, inline disclosures, and hook coverage passed" ) ;
} ) ( ) ;