import { describe, it, expect } from 'vitest'; import { parchis } from '../server/games/parchis-classic.mjs'; describe('parchís individual de un dado', () => { it('usa la salida elegida al calcular capturas y conserva partidas antiguas', () => { const state = parchis.create(2, ['verde', 'rojo']); expect(parchis.view(state).starts).toEqual([55, 38]); state.pieces[0][0] = 0; state.pieces[1][0] = 18; state.die = 1; const moved = parchis.apply(state, { type: 'move', piece: 0 }, 0).state; expect(moved.pieces[1][0]).toBe(-1); expect(moved.die).toBe(20); const old = parchis.create(2); delete old.starts; expect(parchis.view(old).starts).toEqual([4, 21, 38, 55]); expect(() => parchis.create(2, ['verde', 'verde'])).toThrow('distintos'); }); it('resuelve tiradas sin movimientos automáticamente y permite actuar al siguiente jugador', () => { const next = parchis.apply( parchis.create(4), { type: 'roll' }, 0, () => 3, ).state; expect(next.turn).toBe(1); expect(next.die).toBeNull(); expect(parchis.legal(next, 0)).toEqual([]); expect(parchis.legal(next, 1)).toEqual([{ type: 'roll' }]); const moved = parchis.apply( parchis.apply(next, { type: 'roll' }, 1, () => 5).state, { type: 'move', piece: 0 }, 1, ).state; expect(moved.turn).toBe(2); expect(moved.pieces[1][0]).toBe(0); }); it('conserva el seis sin movimiento y penaliza el tercero consecutivo', () => { let state = parchis.create(2); for (let n = 0; n < 2; n++) { state = parchis.apply(state, { type: 'roll' }, 0, () => 6).state; expect(state.turn).toBe(0); expect(state.die).toBeNull(); } state = parchis.apply(state, { type: 'roll' }, 0, () => 6).state; expect(state.turn).toBe(1); state = parchis.create(2); state.pieces[0][0] = 8; for (let n = 0; n < 2; n++) { state = parchis.apply(state, { type: 'roll' }, 0, () => 6).state; state = parchis.apply(state, { type: 'move', piece: 0 }, 0).state; } state = parchis.apply(state, { type: 'roll' }, 0, () => 6).state; expect(state.pieces[0][0]).toBe(-1); expect(state.turn).toBe(1); }); it('no devuelve a casa la última ficha si está en el pasillo final', () => { const state = parchis.create(2); state.pieces[0][0] = 67; state.sixes = 2; state.lastMoved = 0; expect( parchis.apply(state, { type: 'roll' }, 0, () => 6).state.pieces[0][0], ).toBe(67); }); it('cuenta siete sin fichas en casa y obliga a abrir barrera', () => { const state = parchis.create(2); state.pieces[0] = [0, 0, 20, 72]; const next = parchis.apply(state, { type: 'roll' }, 0, () => 6).state; expect(next.die).toBe(7); expect(parchis.legal(next, 0).map((a) => a.piece)).toEqual([0, 1]); }); it('comparte un seguro con un rival y atraviesa dos colores distintos', () => { const state = parchis.create(3); state.pieces[0][0] = 15; state.pieces[1][0] = 0; state.die = 2; const shared = parchis.apply(state, { type: 'move', piece: 0 }, 0).state; expect(shared.pieces[1][0]).toBe(0); expect(shared.pieces[0][0]).toBe(17); state.pieces[0][0] = 16; state.pieces[2][0] = 51; state.die = 3; expect(parchis.legal(state, 0).some((a) => a.piece === 0)).toBe(true); }); it('captura al último rival en una salida llena y concede el premio', () => { const state = parchis.create(3); state.pieces[1][0] = 51; state.pieces[2][0] = 34; state.arrivals[1][0] = 1; state.arrivals[2][0] = 2; state.die = 5; const next = parchis.apply(state, { type: 'move', piece: 0 }, 0).state; expect(next.pieces[2][0]).toBe(-1); expect(next.pieces[1][0]).toBe(51); expect(next.die).toBe(20); expect(next.turn).toBe(0); }); it('descarta premios imposibles sin pedir pasar turno y conserva una repetición por seis', () => { const state = parchis.create(2); state.pieces[0] = [71, 72, 72, -1]; state.die = 1; const next = parchis.apply(state, { type: 'move', piece: 0 }, 0).state; expect(next.turn).toBe(1); expect(next.die).toBeNull(); expect(next.bonus).toBe(false); state.extraTurn = true; expect(parchis.apply(state, { type: 'move', piece: 0 }, 0).state.turn).toBe( 0, ); }); it('termina solo con entrada exacta a meta y mantiene el último seguro antes del pasillo', () => { const state = parchis.create(2); state.pieces[0] = [72, 72, 72, 71]; state.die = 2; expect(parchis.legal(state, 0)).toEqual([{ type: 'pass' }]); state.die = 1; expect(parchis.apply(state, { type: 'move', piece: 3 }, 0).result).toEqual({ winner: 0, reason: 'cuatro fichas en meta', }); state.pieces[0] = [63, 72, 72, 72]; state.die = 1; const next = parchis.apply(state, { type: 'move', piece: 0 }, 0).state; expect(next.pieces[0][0]).toBe(64); expect(parchis.view(next).outerLength).toBe(65); expect(parchis.view(next).safe).toHaveLength(16); }); });