Lección 43 de 170

Orquestar actores sin duplicar la autoridad

Curso de desarrollo de videojuegos con IA

Construye un tablero de encuentro que coordine apariciones, eventos de combate, fases, reinicios y reactivaciones sin quitar a cada sistema la autoridad sobre su propio estado.

629. Identidad de la lección

Módulo
2.3 — Aparición de actores y encuentros
Tipo académico
Construcción guiada
Tipo de esquema
Práctica
Tiempo estimado
35–45 minutos, incluida la práctica

La lección anterior definió el encuentro como un ciclo de vida delimitado. Ahora convertirás ese límite en un sistema de coordinación con fases explícitas, contratos de eventos, responsabilidades claras, reglas de interrupción y una identidad de ejecución que impida que el trabajo retrasado afecte a una activación posterior.

630. Objetivo de aprendizaje

Al terminar esta lección, podrás crear un tablero de encuentro que solicite la aparición de actores, avance por fases explícitas, gestione entradas tardías válidas, rechace eventos obsoletos o duplicados y se reinicie sin apropiarse del registro, la salud, la derrota ni el estado local de los actores.

631. Distinción central: coordinar no equivale a controlar todo

El controlador del encuentro es responsable del estado de coordinación del encuentro. No debe convertirse en un segundo sistema de actores, aparición o combate.

El tablero puede controlar:

  • si el encuentro está inactivo, activo, terminado o reiniciándose;
  • la fase actual;
  • la identidad de la activación vigente;
  • las solicitudes de aparición que ha emitido;
  • los contadores de coordinación derivados de eventos aceptados;
  • los identificadores de eventos que ya ha consumido.

Los demás sistemas conservan la autoridad en sus respectivos ámbitos:

  • el generador o sistema de actores crea y registra los actores;
  • cada actor controla su comportamiento y estado local;
  • el sistema de combate resuelve el daño y decide cuándo un actor ha sido derrotado;
  • los sistemas de recompensas o progresión controlan sus propias consecuencias.

El tablero puede solicitar trabajo y consumir hechos informados por otros sistemas. No debe copiar la salud para decidir una derrota, registrar directamente actores en el registro de otro sistema ni simular por su cuenta el reinicio de un actor.

Los eventos informan hechos. Los comandos solicitan trabajo. El sistema responsable de cada ámbito determina el resultado. El tablero del encuentro solo decide qué significa ese resultado para el avance del encuentro.

632. Modelo Tablero–Ejecución–Actores–Eventos

Participante Estado bajo su autoridad Recibe Envía
Tablero del encuentro Fase, finalización, identidad de la ejecución activa y eventos ya consumidos Activador, registro de actor, derrota confirmada por combate, salida de actor Solicitud de aparición, cambio de fase, solicitud de reinicio
Generador o sistema de actores Creación y registro de actores Solicitudes de aparición y reinicio Actor registrado, actor salido
Actor Comportamiento y estado local Comandos de comportamiento, combate y reinicio Hechos de su ciclo de vida
Sistema de combate Resolución del daño y decisión de derrota Ataques y objetivos Evento de actor derrotado confirmado por combate

El tablero solo debe aceptar un evento cuando:

existe una ejecución activa
Y coincide event.encounterId
Y coincide event.runId
Y la fase actual admite ese evento
Y event.eventId todavía no se ha consumido

La validación de fase y la validación de ejecución resuelven problemas distintos. Una fase puede repetirse tras una reactivación; por eso, compartir la misma fase no demuestra que el evento pertenezca a la activación actual.

633. Contrato correcto de reinicio

El reinicio debe distinguir entre la ejecución interrumpida y la identidad de cualquier ejecución futura. Primero se captura la ejecución interrumpida, después se invalida en el tablero y, por último, se solicita al sistema responsable de los actores que reinicie los asociados a esa ejecución.

se solicita el reinicio
    -> capturar interruptedRunId
    -> invalidar activeRunId de inmediato
    -> borrar el estado de coordinación del tablero
    -> solicitar el reinicio con targetRunId = interruptedRunId
    -> permanecer inactivo
    -> una activación posterior recibe un runId nuevo
    -> se rechazan los eventos de interruptedRunId

No envíes una identidad recién creada como si identificara a los actores de la ejecución interrumpida.

634. Ejemplo concreto

run 8, PHASE_ONE
  el tablero solicita dos exploradores con runId 8
  el generador informa tarde el registro de un explorador con runId 8
  el tablero lo acepta porque la fase permite entradas tardías
  combate confirma ambas derrotas con runId 8
  el tablero avanza a PHASE_TWO

reinicio durante PHASE_TWO
  el tablero guarda interruptedRunId = 8
  el tablero establece activeRunId = null
  el tablero borra sus contadores de fase y eventos consumidos
  el tablero solicita el reinicio con targetRunId = 8

activación posterior
  el tablero crea runId 9 y entra en PHASE_ONE

derrota tardía de run 8
  el tablero la rechaza porque 8 no es la ejecución activa

Un contrato mínimo puede representarse así:

type EncounterPhase = "inactive" | "phase-one" | "phase-two" | "complete";

type EncounterBoard = {
  encounterId: string;
  activeRunId: number | null;
  nextRunId: number;
  phase: EncounterPhase;
  defeatedByPhase: Record<string, number>;
  consumedEventIds: Set<string>;
};

type DefeatEvent = {
  eventId: string;
  encounterId: string;
  runId: number;
  phase: EncounterPhase;
  actorId: string;
};

function activate(board: EncounterBoard) {
  if (board.activeRunId !== null) return;
  const runId = board.nextRunId++;
  board.activeRunId = runId;
  board.phase = "phase-one";
  events.emit("encounter.spawnRequested", {
    encounterId: board.encounterId,
    runId,
    group: "scouts"
  });
}

function acceptsDefeat(board: EncounterBoard, event: DefeatEvent) {
  return board.activeRunId !== null
    && event.encounterId === board.encounterId
    && event.runId === board.activeRunId
    && event.phase === board.phase
    && !board.consumedEventIds.has(event.eventId);
}

function reset(board: EncounterBoard) {
  const interruptedRunId = board.activeRunId;

  // Invalida la ejecución antes de que el trabajo externo informe más eventos.
  board.activeRunId = null;
  board.phase = "inactive";
  board.defeatedByPhase = {};
  board.consumedEventIds.clear();

  if (interruptedRunId !== null) {
    events.emit("encounter.actorsResetRequested", {
      encounterId: board.encounterId,
      targetRunId: interruptedRunId
    });
  }
}

Combate sigue siendo el sistema que decide si un actor fue derrotado. El tablero usa el evento resultante únicamente para evaluar una regla del encuentro. Del mismo modo, el generador o sistema de actores realiza el reinicio efectivo; el tablero solo identifica la ejecución interrumpida que debe reiniciarse.

635. Decisiones que debes registrar

Antes de implementar, decide:

  1. Entrada tardía: ¿Puede incorporarse a la fase un actor registrado después de su inicio? Si puede, ¿modifica la cantidad esperada?
  2. Aparición pendiente: ¿Qué ocurre si se solicita un reinicio antes de que aparezca el actor pedido?
  3. Evento tardío de fase: ¿Se ignora, registra o trata mediante otro contrato un evento de la ejecución actual que pertenece a una fase anterior?
  4. Entrega duplicada: ¿Qué eventId estable impide contar dos veces el mismo hecho?
  5. Reactivación: ¿Qué mecanismo asigna una identidad nueva?

Estas decisiones deben formar parte del contrato; no conviene dejarlas al orden accidental de ejecución.

636. Flujo de trabajo con IA

  1. Escribe primero la tabla de responsabilidades. Indica qué sistema controla las fases, el registro, el estado local de los actores, la resolución del daño y la decisión de derrota.
  2. Proporciona las interfaces existentes. Pide a la IA el cambio mínimo necesario para transmitir encounterId, runId, phase y eventId por las solicitudes y los eventos pertinentes.
  3. Limita la solicitud. Prohíbe expresamente copiar la salud, duplicar indicadores de derrota, crear un segundo registro autoritativo de actores o modificar directamente su estado desde el tablero.
  4. Revisa el orden del reinicio. Comprueba que el tablero invalide la ejecución activa antes de que el trabajo externo pueda producir más eventos y que el comando de reinicio apunte a la ejecución interrumpida.
  5. Prueba un caso límite cada vez. Comprueba el registro tardío, la derrota llegada desde una fase anterior, la aparición pendiente durante el reinicio, la entrega de eventos antiguos tras reactivar y la entrega duplicada.

La IA puede proponer el cableado de eventos, pero las responsabilidades y reglas de aceptación son decisiones de diseño que debes revisar.

637. Construcción guiada

Paso 1 — Crea una tabla de responsabilidades

Para el tablero, el generador o sistema de actores, el actor y el sistema de combate, indica:

  • un estado que controle cada participante;
  • un hecho que informe;
  • un comando que reciba o envíe.

Enumera todos los campos propuestos de actividad, salud, derrota, registro, fase y finalización. Asigna un único sistema responsable a cada uno. Sustituye cualquier campo del tablero que duplique la autoridad de otro sistema por un evento, comando, referencia o contador de coordinación.

Incluye esta regla en la especificación:

Combate decide la derrota; el tablero del encuentro solo cuenta los eventos de derrota confirmados por combate que superan sus validaciones.

Paso 2 — Define fases y contexto de eventos

Define al menos estas fases:

  • inactivo;
  • primera oleada activa;
  • segunda oleada activa;
  • terminado.

Añade una identidad para la ejecución activa y otra estable para cada evento. Documenta la condición de finalización y los tipos de evento admitidos en cada fase.

Paso 3 — Conecta la activación y la entrada tardía

Crea la ruta mínima que permita:

  • activar el tablero desde un activador;
  • emitir una solicitud de aparición con la identidad vigente;
  • consumir registros informados por el generador o sistema de actores;
  • aplicar una regla explícita de entrada tardía;
  • consumir derrotas confirmadas por combate solo después de validar encuentro, ejecución, fase e identidad del evento;
  • avanzar de fase o completar el encuentro.

Paso 4 — Añade interrupción y reinicio

Captura la ejecución interrumpida, invalídala en el tablero, borra únicamente el estado de coordinación que pertenece al tablero y emite una solicitud cuyo targetRunId identifique esa ejecución. La activación posterior debe usar una identidad nueva.

Paso 5 — Prueba los casos límite

Registra el resultado observado cuando:

  • se produce un registro tardío válido en la ejecución actual;
  • llega una derrota de la ejecución actual, pero de una fase anterior;
  • se solicita el reinicio mientras hay una aparición pendiente;
  • llega un registro o una derrota de una ejecución anterior tras la reactivación;
  • se entrega dos veces el mismo evento.

En cada caso, identifica qué sistema tiene la autoridad y explica por qué el tablero acepta, rechaza o ignora el evento sin modificar el estado interno de ese sistema.

638. Evidencia y evaluación

Entrega el tablero y sus pruebas mediante la evaluación práctica vinculada. El trabajo debe mostrar límites de responsabilidad, contratos de fase y ejecución, entrada tardía, interrupción, reinicio dirigido a la ejecución correcta, reactivación y rechazo de eventos obsoletos o duplicados.

El trabajo debe revisarse si el tablero:

  • mantiene un segundo registro autoritativo de actores;
  • decide la derrota a partir de una copia de la salud o del estado activo;
  • acepta eventos sin comprobar las identidades del encuentro y de la ejecución;
  • envía una identidad nueva como destino del reinicio de los actores interrumpidos;
  • permite que un evento antiguo o duplicado avance la fase actual.

639. Ideas clave

  • La autoridad de coordinación no equivale a la autoridad sobre la aparición, los actores o el combate.
  • Combate decide la derrota; el tablero determina qué significa ese hecho aceptado para el avance de la fase.
  • Los comandos solicitan trabajo al sistema responsable y los eventos informan resultados.
  • La identidad de ejecución evita que el trabajo retrasado cruce los límites entre activaciones.
  • El reinicio debe apuntar a la ejecución interrumpida e invalidarla en el tablero antes de continuar con trabajo externo.
  • La entrada tardía, la interrupción y la entrega duplicada requieren contratos explícitos.

640. Siguiente lección

Continúa con 2.4 — Diseño de jefes: Un jefe es un contrato legible. El diseño de jefes reutiliza el razonamiento sobre responsabilidades, fases y eventos obsoletos, y añade la promesa dirigida al jugador que hace que esas fases resulten legibles y significativas.

641. Comprobación

Responde estas preguntas por tu cuenta antes de leer las respuestas.

¿Qué responsabilidad corresponde al tablero del encuentro?

  • A. Resolver el daño y decidir si un actor ha sido derrotado
  • B. Crear todos los actores y controlar su registro
  • C. Controlar la fase del encuentro y la identidad de la ejecución activa
  • D. Conceder recompensas y modificar la progresión del jugador
Mostrar respuesta y explicación

Respuesta: Controlar la fase del encuentro y la identidad de la ejecución activa

Por qué: El tablero controla el estado de coordinación, como la fase, la finalización y la identidad de la ejecución activa. Los sistemas de aparición, actores, combate y progresión conservan la autoridad en sus respectivos ámbitos.

¿Cuál es la relación correcta entre una derrota confirmada por combate y una transición de fase del encuentro?

  • A. Combate informa la derrota y el tablero usa el hecho aceptado para evaluar su regla de transición
  • B. El tablero modifica la salud del actor antes de procesar el evento
  • C. El evento modifica directamente el estado del encuentro y del actor
  • D. El tablero ignora el evento y consulta una copia de la salud
Mostrar respuesta y explicación

Respuesta: Combate informa la derrota y el tablero usa el hecho aceptado para evaluar su regla de transición

Por qué: Combate conserva la autoridad sobre la decisión de derrota. El tablero valida y consume ese hecho únicamente para determinar el avance del encuentro.

¿Por qué debe incluir un evento del encuentro una identidad de ejecución o generación?

  • A. Para que el tablero sustituya el estado interno del actor
  • B. Para hacer que el evento controle las apariciones futuras
  • C. Para evitar la definición de reglas de fase explícitas
  • D. Para rechazar eventos retrasados de una activación interrumpida o anterior
Mostrar respuesta y explicación

Respuesta: Para rechazar eventos retrasados de una activación interrumpida o anterior

Por qué: La identidad de ejecución distingue la activación actual de las anteriores, incluso cuando se repiten las fases o los identificadores de actores.

¿Qué debe hacer el tablero cuando un reinicio interrumpe una ejecución activa?

  • A. Asignar directamente valores de salud y actividad a todos los actores
  • B. Mantener activa la ejecución hasta que terminen por casualidad todos los eventos pendientes
  • C. Capturar e invalidar la ejecución interrumpida y solicitar después el reinicio de sus actores usando esa ejecución como destino
  • D. Generar una identidad nueva y usarla como destino para reiniciar los actores antiguos
Mostrar respuesta y explicación

Respuesta: Capturar e invalidar la ejecución interrumpida y solicitar después el reinicio de sus actores usando esa ejecución como destino

Por qué: El tablero debe invalidar la ejecución interrumpida antes de que otros eventos puedan afectarla. La solicitud de reinicio apunta a esa ejecución, mientras que una activación posterior recibe otra identidad nueva.

Apoyar