// scripts/repro-pause-bug.js // Minimal repro: pause+resume causes nextTurn to repeat same participant forever. 'use strict'; const shared = require('../shared'); const { makeParticipant, startEncounter, nextTurn, togglePause, addParticipant } = shared; function p(id, init) { return makeParticipant({ id, name: id, type: 'monster', initiative: init, maxHp: 100, currentHp: 100 }); } let e = { name: 't', participants: [p('a', 20), p('b', 15), p('c', 10)], isStarted: false, isPaused: false, round: 0, currentTurnParticipantId: null, turnOrderIds: [], }; e = { ...e, ...startEncounter(e).patch }; console.log('start:', { current: e.currentTurnParticipantId, order: e.turnOrderIds, round: e.round }); // advance 1 turn e = { ...e, ...nextTurn(e).patch }; console.log('turn1:', { current: e.currentTurnParticipantId, round: e.round }); // pause then resume immediately e = { ...e, ...togglePause(e).patch }; console.log('paused:', { isPaused: e.isPaused, current: e.currentTurnParticipantId, order: e.turnOrderIds }); e = { ...e, ...togglePause(e).patch }; console.log('resumed:', { isPaused: e.isPaused, current: e.currentTurnParticipantId, order: e.turnOrderIds }); // advance 5 turns — should visit b, c, a, b, c const visited = [e.currentTurnParticipantId]; for (let i = 0; i < 5; i++) { e = { ...e, ...nextTurn(e).patch }; visited.push(e.currentTurnParticipantId); } console.log('5 turns after resume:', visited); // now repro with addParticipant while paused let e2 = { name: 't', participants: [p('a', 20), p('b', 15), p('c', 10)], isStarted: false, isPaused: false, round: 0, currentTurnParticipantId: null, turnOrderIds: [], }; e2 = { ...e2, ...startEncounter(e2).patch }; e2 = { ...e2, ...nextTurn(e2).patch }; // current=b const newP = makeParticipant({ id: 'x', name: 'x', type: 'monster', initiative: 25, maxHp: 100, currentHp: 100 }); e2 = { ...e2, ...addParticipant(e2, newP).patch }; console.log('\nadded x while running:', { current: e2.currentTurnParticipantId, order: e2.turnOrderIds }); e2 = { ...e2, ...togglePause(e2).patch }; e2 = { ...e2, ...togglePause(e2).patch }; console.log('after pause/resume:', { current: e2.currentTurnParticipantId, order: e2.turnOrderIds }); const v2 = [e2.currentTurnParticipantId]; for (let i = 0; i < 5; i++) { e2 = { ...e2, ...nextTurn(e2).patch }; v2.push(e2.currentTurnParticipantId); } console.log('5 turns after add+pause/resume:', v2); // repro 3: addParticipant WHILE paused, then resume let e3 = { name: 't', participants: [p('a', 20), p('b', 15), p('c', 10)], isStarted: false, isPaused: false, round: 0, currentTurnParticipantId: null, turnOrderIds: [], }; e3 = { ...e3, ...startEncounter(e3).patch }; e3 = { ...e3, ...nextTurn(e3).patch }; // current=b console.log('\n--- add while PAUSED ---'); e3 = { ...e3, ...togglePause(e3).patch }; // pause console.log('paused:', { current: e3.currentTurnParticipantId, order: e3.turnOrderIds }); const np = makeParticipant({ id: 'x', name: 'x', type: 'monster', initiative: 25, maxHp: 100, currentHp: 100 }); e3 = { ...e3, ...addParticipant(e3, np).patch }; console.log('add-while-paused:', { current: e3.currentTurnParticipantId, order: e3.turnOrderIds }); e3 = { ...e3, ...togglePause(e3).patch }; // resume (rebuilds order) console.log('resumed:', { current: e3.currentTurnParticipantId, order: e3.turnOrderIds }); const v3 = [e3.currentTurnParticipantId]; for (let i = 0; i < 5; i++) { e3 = { ...e3, ...nextTurn(e3).patch }; v3.push(e3.currentTurnParticipantId); } console.log('5 turns after add-while-paused+resume:', v3);