La pregunta que lo inicia todo
Hay una pregunta que llevo tiempo dando vueltas: ¿en qué punto deja una partícula de ser un punto en una cuadrícula y empieza a ser alguien? No es una pregunta retórica. Es la pregunta de diseño real detrás de este proyecto.
Un Mundo Para Isa es un simulador de vida artificial escrito en TypeScript. Backend con Node, frontend con Vite, comunicación vía WebSocket a 20 ticks por segundo. Suena técnico. Pero el núcleo del asunto es otro: intenté construir un mundo donde el comportamiento interesante no estuviera programado directamente, sino que emergiera de reglas simples compuestas.
FSM más goal planning: dos capas de decisión
Cada agente en la simulación tiene una máquina de estados finitos clásica. Los estados son los de siempre: IDLE, WANDERING, GATHERING, WORKING, FLEEING, BUILDING, RESTING. Hasta ahí, nada nuevo bajo el sol.
La parte interesante es la capa que se monta encima: un sistema de goal planning. Cada agente puede tener un currentGoal activo, con tipo, prioridad y timestamp de creación. El FSM solo entra en juego cuando no hay ningún goal activo. En la práctica eso significa que el comportamiento dirigido siempre tiene precedencia, pero el FSM sirve de red de seguridad cuando el agente no sabe qué quiere.
Hay además una interrupción de emergencia: si la energía del agente cae por debajo de 0.25, sin importar qué goal esté ejecutando, se reemplaza por FIND_FOOD con prioridad máxima. Los goals también tienen timeout: si llevan más de 1000 ticks activos (50 segundos de simulación), se descartan y el agente vuelve al estado IDLE. Esto evita que los agentes queden atascados persiguiendo objetivos inalcanzables indefinidamente.
Esa combinación, FSM como fallback y goal planning como capa deliberativa, reproduce de manera simplificada lo que la arquitectura SOAR intentaba en los años ochenta. La diferencia es que aquí cabe en un archivo de TypeScript y corre en un servidor Node.
Los campos: la física del mundo
Lo que le da vida al espacio no son los agentes sino los campos. El mundo tiene una cuadrícula de 512x512 celdas. Sobre esa cuadrícula viven múltiples capas de Float32Array con doble buffer: comida, agua, peligro, árboles, piedra, y cuatro canales de rastro (trail0 a trail3).
Cada campo tiene tres parámetros fundamentales: tasa de difusión, tasa de decay y valor máximo. La difusión expande el valor hacia las celdas vecinas; el decay lo reduce en cada tick; algunos campos tienen además crecimiento logístico con cap. El campo de peligro difunde rápido y decae rápido. El de nostalgia difunde despacio y decae muy lento.
Los rastros son lo más parecido a feromonas: los agentes los depositan al moverse y los leen para decidir hacia dónde ir. El gradiente resultante de food, water, trail, danger, crowding y exploration, ponderado por pesos configurables, determina la dirección de cada paso. Esto genera patrones de movimiento colectivo que nadie programó explícitamente: caminos espontáneos, zonas de evitación, concentraciones alrededor de recursos.
Campos semánticos: la física del estado emocional
Aquí es donde el proyecto se vuelve raro, en el mejor sentido.
Además de los campos físicos, el mundo tiene campos semánticos: joy, nostalgia, love, wonder, melancholy. Cada uno con sus propios parámetros de difusión, decay y radio de influencia. La melancolía difunde muy poco (0.03) y decae muy lento (0.01), así que se acumula en zonas. La alegría difunde rápido y desaparece pronto. El amor tiene un radio de influencia de 12 celdas y un efecto de comportamiento de 0.5, el más alto de todos.
Los campos emocionales se depositan a partir de eventos narrativos y del comportamiento de los agentes. No son decorativos: behaviorEffect es un modificador real sobre las decisiones. Un agente que opera en una zona de alta concentración de alegría se comporta diferente a uno en una zona de melancolía acumulada.
Esto es una apuesta de diseño bastante específica: que la emoción, como la comida o el peligro, puede tratarse como un campo físico con difusión y decay. Que tiene una geografía. Que esa geografía afecta la conducta sin que ningún agente la conozca explícitamente.
Materialización: de partícula a personaje
El tercer nivel del sistema es la materialización. Una partícula que persiste el tiempo suficiente puede convertirse en un Character con nombre, linaje, rasgos de personalidad y memoria de eventos. Si sus logros son suficientes, asciende a Hero con título, diálogos y legado.
Los nombres se generan desde el seed del agente. Los rasgos también. Los apellidos siguen patrones como "del Valle", "de la Luz", "del Río". Hay registro de eventos: nacimiento, encuentro de pareja, hijos, descubrimientos, migraciones, conflictos, supervivencias.
Esta capa me parece filosóficamente la más densa. Porque lo que estoy describiendo es el momento en que un estado en un array de Float32 adquiere historia. Adquiere nombre. Adquiere una narrativa que ninguna línea de código escribió directamente, sino que emerge de las interacciones acumuladas en la simulación.
Lo que esto enseña sobre sistemas
Hay una lección de arquitectura que este proyecto solidificó para mí: la diferencia entre complejidad programada y complejidad emergente no es filosófica, es estructural.
La complejidad programada es frágil porque cada comportamiento nuevo requiere código nuevo. La complejidad emergente es robusta porque los comportamientos nuevos aparecen como consecuencia de la composición de reglas ya existentes. El problema real de diseño es elegir bien las reglas simples.
En este caso las reglas simples son: campos con difusión y decay, agentes con necesidades y gradient-following, goals con prioridad y timeout, y campos emocionales con física propia. De esa composición salen caminos, comunidades, jerarquías implícitas, zonas con historia, agentes con carácter.
La otra lección es sobre el tiempo. Una simulación a 20 ticks por segundo está haciendo 1200 decisiones por minuto por agente. Esa densidad temporal es lo que permite que algo parecido a la historia ocurra. La emergencia requiere tiempo para desplegarse.
Por qué se llama así
Eso no lo voy a explicar aquí. Solo digo que hay proyectos que uno construye para aprender sobre sistemas y proyectos que uno construye porque necesita construirlos. Este fue las dos cosas al mismo tiempo.