Prepare game updates and single-process PM2 deployment
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import { MATCH_COUNTDOWN_MS, REVEAL_DURATION_MS, TURN_DURATION_MS } from '../../constants/gameplay.js';
|
||||
import { MATCH_COUNTDOWN_MS, REVEAL_DURATION_MS } from '../../constants/gameplay.js';
|
||||
import { DEFAULT_GLOBAL_SETTINGS } from '../../constants/global-settings.js';
|
||||
import { matchPreparationDuration } from './match-introduction.js';
|
||||
import { chooseBotAction } from './bot.js';
|
||||
import { isLegalAction, resolveTurn } from './rules.js';
|
||||
import { emptyPlayerStats, type LocalEndReason, type LocalMatchState, type MatchCheckpoint, type MatchConfig } from './p2p-types.js';
|
||||
@@ -10,7 +12,7 @@ export function createMatchEngine(config: MatchConfig) {
|
||||
matchId: config.matchId, mode: config.mode, selfIndex: config.selfIndex, phase: 'countdown',
|
||||
version: 0, energy: [0, 0], turnId: 0, clockNow: config.clock.now(), startsAt: Infinity, deadline: 0,
|
||||
ownAction: null, rematch: [false, false], opponentPresent: true, opponentLeft: false,
|
||||
saveStatus: 'pending', aborted: false,
|
||||
saveStatus: 'pending', aborted: false, settings: { ...(config.settings ?? DEFAULT_GLOBAL_SETTINGS) },
|
||||
};
|
||||
function finish(winnerIndex: 0 | 1 | null, reason: LocalEndReason, aborted = false) {
|
||||
if (state.phase === 'finished') return;
|
||||
@@ -21,14 +23,14 @@ export function createMatchEngine(config: MatchConfig) {
|
||||
return {
|
||||
start(startsAt = config.clock.now()) {
|
||||
if (state.version !== 0) throw new Error('ALREADY_STARTED');
|
||||
state.startsAt = startsAt + MATCH_COUNTDOWN_MS; state.version++;
|
||||
state.startsAt = startsAt + (config.mode === 'friend' ? matchPreparationDuration(state.settings) : MATCH_COUNTDOWN_MS); state.version++;
|
||||
},
|
||||
beginTurn(startsAt = config.clock.now()): boolean {
|
||||
if (state.phase === 'selecting' || state.phase === 'finished') return false;
|
||||
const earliest = state.phase === 'countdown' ? state.startsAt : state.reveal!.revealEndsAt;
|
||||
if (startsAt < earliest || config.clock.now() < earliest) return false;
|
||||
state.phase = 'selecting'; state.turnId++; state.version++;
|
||||
state.startsAt = startsAt; state.deadline = startsAt + TURN_DURATION_MS;
|
||||
state.startsAt = startsAt; state.deadline = startsAt + (state.settings ?? DEFAULT_GLOBAL_SETTINGS).turnDurationMs;
|
||||
state.ownAction = null; state.reveal = undefined;
|
||||
bot = config.mode === 'bot' ? chooseBotAction(state.energy[1], state.energy[0], config.random) : null;
|
||||
return true;
|
||||
@@ -40,7 +42,7 @@ export function createMatchEngine(config: MatchConfig) {
|
||||
botAction: () => bot,
|
||||
resolve(actions: Pair<ActionId | null>): TurnResolution {
|
||||
if (state.phase !== 'selecting') throw new Error('NOT_SELECTING');
|
||||
if (config.clock.now() < state.deadline) throw new Error('BEFORE_DEADLINE');
|
||||
if (config.clock.now() < state.startsAt || (actions.includes(null) && config.clock.now() < state.deadline)) throw new Error('BEFORE_DEADLINE');
|
||||
if (actions.some((a, i) => a !== null && !isLegalAction(a, state.energy[i]))) throw new Error('INVALID_ACTION');
|
||||
if (actions[0] === null || actions[1] === null) {
|
||||
const winner = actions[0] === null && actions[1] === null ? null : actions[0] === null ? 1 : 0;
|
||||
@@ -70,7 +72,7 @@ export function createMatchEngine(config: MatchConfig) {
|
||||
state = { ...structuredClone(checkpoint.state), version: Math.max(state.version, checkpoint.state.version) };
|
||||
state.turnId = state.phase === 'revealing' ? state.turnId + 1 : Math.max(1, state.turnId);
|
||||
state.phase = 'selecting'; state.ownAction = null; state.reveal = undefined;
|
||||
state.startsAt = startsAt; state.deadline = startsAt + TURN_DURATION_MS; state.opponentPresent = true; state.version++;
|
||||
state.startsAt = startsAt; state.deadline = startsAt + (state.settings ?? DEFAULT_GLOBAL_SETTINGS).turnDurationMs; state.opponentPresent = true; state.version++;
|
||||
},
|
||||
abort(reason: 'connection_failed' | 'protocol_error') { finish(null, reason, true); },
|
||||
saved(stats: PlayerStats) {
|
||||
|
||||
Reference in New Issue
Block a user