Cómo se construye
Un desarrollador, un asistente de programación con IA y muchas reglas comprobadas por máquinas.
Por Nick
Prison Life lo escribo yo junto con Claude Code (el agente de programación de Anthropic). Yo decido qué es el juego y qué opciones tomamos; el asistente hace la mayor parte de la escritura. Como nadie revisa el código salvo yo y un agente de IA de revisión, me apoyo en la automatización: las reglas las hacen cumplir comprobaciones automáticas y la compilación, no las buenas intenciones.
Delegación
La sesión principal de Claude Code planifica el trabajo y lleva el gestor de tareas, el registro escrito de las decisiones de diseño y el historial de cambios. No escribe código: cada cambio, por pequeño que sea, lo delega en un agente de IA especializado. Cada uno tiene su propia definición escrita que fija su rol y su modelo.
| Rol | Nivel de modelo | Trabajo |
|---|---|---|
| Arquitectura | Opus | modelo de datos, tick, hilos, búsqueda de caminos, decisiones |
| Código de simulación | Opus | sistemas de simulación, IA de personajes, bucles críticos |
| Rendimiento | Opus | perfilado, regresiones del benchmark |
| Revisión (solo lectura) | Opus | revisa un diff; no puede editar archivos |
| Cliente y herramientas | Sonnet | cliente de Godot, interfaz, herramientas |
| Pruebas | Sonnet | pruebas a partir de criterios de aceptación |
| Datos de contenido | Sonnet | definiciones JSON a partir de un esquema |
| Búsqueda, ejecución de comprobaciones | Haiku | búsqueda en el código; ejecutar comprobaciones y resumir los fallos |
El trabajo difícil va al modelo más potente, y el rutinario a los más baratos. Si un agente de IA más barato falla las comprobaciones dos veces, la tarea sube un nivel; si falla dos veces el nivel superior, se detiene y me pregunta.
Hooks que dicen no
Los hooks de Claude Code son scripts que se ejecutan alrededor de las acciones del asistente. Los míos hacen cumplir tres reglas:
- No se termina en rojo. Cuando una sesión o un agente de IA intenta detenerse después de cambiar código, un hook ejecuta la comprobación rápida (compilación más las pruebas rápidas). Si falla, se rechaza la parada.
- La sesión principal no puede editar código. Un hook rechaza las escrituras en el código fuente, las pruebas, el contenido y las herramientas desde la sesión principal.
- El revisor es de solo lectura. Se le quitan las herramientas de edición y un hook rechaza los comandos que cambian archivos o el historial del proyecto.
Estas medidas protegen de errores, no de una elusión deliberada: un truco de shell decidido puede saltárselas, y uno de los hooks detecta una comprobación en rojo en un agente de IA pero no puede impedir que continúe (el hook de parada de la sesión principal sigue atrapándolo). Prefiero decirlo claramente.
Decisiones y comprobaciones por escrito
- Toda decisión no trivial queda por escrito. Las tareas, los hitos y las decisiones de diseño se guardan como texto plano junto al código, en un gestor de tareas. Cuando elegimos entre opciones que afectan a más de una tarea, la elección se anota con su contexto y sus consecuencias.
- Las comprobaciones se ejecutan en mi máquina. Sin CI en la nube. Un script local tiene cuatro modos:
fast,test,benchyfull. Los scripts y los hooks son PowerShell 7 tanto en Windows como en macOS. - Comprobaciones en cada cambio. La automatización local rechaza un cambio mal descrito o mal formateado. Para los cambios de código, además ejecuta la comprobación rápida; los cambios que solo tocan notas o el sitio web se saltan la compilación.
- Los archivos de referencia están protegidos. Los hashes de determinismo fijados, los archivos de guardado de referencia y la línea base del benchmark solo cambian con mi aprobación explícita, nunca en silencio.
- El propio proyecto es la fuente de verdad. Una herramienta de memoria local indexa el proyecto y las conversaciones pasadas para poder buscar en ellos, pero todo lo que importa es además una tarea, una decisión registrada o un documento.
El núcleo determinista
La simulación vive en una biblioteca .NET sin referencias a Godot; el cliente de Godot solo lee su estado y envía comandos. El núcleo sigue reglas fijas: el mundo cambia solo mediante comandos, el tiempo son ticks enteros y la aleatoriedad proviene únicamente de los generadores con semilla del mundo. La misma semilla y el mismo registro de comandos deben dar el mismo mundo. Estas reglas las comprueban el compilador y las pruebas, no solo la revisión; consulta el devlog #1 para ver cómo, y el devlog #2 para el mundo, las partidas guardadas y las repeticiones.
- Los comandos son la única vía de entrada. Cada uno tiene un identificador de tipo estable y una codificación binaria, y todos se registran con su resultado, incluidos los rechazados.
- El tick tiene tres fases en un orden fijo. El orden de los sistemas se establece en un único lugar del código, y cambiarlo cambia todos los hashes.
- La aleatoriedad usa generadores propios (SplitMix64 y xoshiro256**). Los flujos con nombre se derivan de la semilla del mundo y se guardan en su estado. Un generador con clave y sin estado, gobernado por un dominio, una clave y el tick, atiende el trabajo en el que el orden no importa.
- El hash del estado es un hash de 64 bits sensible al orden para las comprobaciones de determinismo. No es criptográfico.
- El mundo es una cuadrícula de baldosas de 1×1 m en niveles discretos; las paredes, las puertas y los suelos solo cambian con comandos de construcción.
- Las partidas guardadas y las repeticiones comparten un contenedor de archivo verificado. Una repetición es la semilla más el registro de comandos, con hashes de control por el camino, y se comprueba paso a paso al reproducirla.
- Los benchmarks provienen de un ejecutor de escenarios sin interfaz, con una línea base por máquina y una condición de cero reservas de memoria por tick.
El objetivo de diseño es hasta 1.000 reclusos y empleados a 20 ticks por segundo. Es un objetivo: todavía no hay personajes, así que el ejecutor de benchmarks existe pero no se ha medido nada a esa escala.