Proyectos / Motive
¿Qué es Motive?
Este es un videojuego impulsado por IA en el que el jugador debe resolver la escena de un crimen. Para hacerlo, tiene que descubrir cuatro elementos: el oficio del asesino, el lugar del crimen, la causa de la muerte y el arma homicida. La mecánica es simple pero desafiante: se puede formular cualquier tipo de pregunta, pero la IA solo puede responder “sí” o “no”.

¿Cómo nació la idea?
En 2022, cuando conocí ChatGPT y comencé a experimentar pidiéndole poemas y resúmenes, me surgió una pregunta: ¿podría ser el chat un buen anfitrión para un juego de adivinanzas al estilo Clue? Más concretamente: ¿sería la IA capaz de “pensar” en la escena de un crimen y, sin revelarla, responder por “sí” o por “no” a mis preguntas hasta resolver el misterio?
Aunque hoy la respuesta parece evidente, en aquel entonces la tecnología era nueva y todavía estábamos explorando sus límites. Pero sí: el experimento fue terrible. Para la IA era imprescindible que la palabra estuviera explícitamente escrita en su contexto; al no estarlo, comenzaba a alucinar, se contradecía o revelaba el supuesto misterio tras mi primera pregunta. Además, no tardaba en romper la consigna y empezaba a responder con frases que no eran estrictamente “sí” y “no”.
Tras varios ajustes en el prompt, logré que el comportamiento se mantuviera consistente durante las primeras preguntas… pero, con el tiempo, siempre terminaba desvirtuándose. Un chat, con su historial conversacional acumulativo, simplemente no es un formato adecuado para este tipo de juegos.
Tiempo después, al lanzar whatMLmodel —una aplicación con un LLM integrado— entendí que por primera vez contaba con las herramientas necesarias para comprobar si aquel juego de adivinanzas era algo plausible. Ya sabía cómo utilizar las llamadas a la API; ahora quería ver si, manteniendo un contexto bien definido y acotando las respuestas de la IA, era posible jugar de una forma medianamente satisfactoria a resolver la escena de un crimen.

¿Cómo funcionaría?
La idea era que el jugador pudiera enfrentarse a múltiples casos y que, en cada uno, tuviera que descubrir las mismas cuatro consignas: oficio, lugar, causa y arma. Primero pensé en que los casos fueran generados por la IA en tiempo real, pero rápidamente entendí que esta gran base del juego requería de muchos criterios que no convenían delegar. De todas maneras, me ayudé con ChatGPT dándole una consigna simple: crear casos donde los cuatro ítems estuvieran bien relacionados, con algún giro inesperado y una dificultad razonable.
Tras varios ajustes, los resultados fueron tan buenos como “Un entrenador personal que envenena a su víctima con un batido de proteínas en un gimnasio”. Cosas muy ingeniosas, sí, pero que a veces carecían de chispa o rompían la coherencia entre los elementos. Por esa razón, refiné cerca de sesenta casos que se elegirían aleatoriamente al comenzar las partidas.
Los misterios se mantendrían ocultos a los ojos del jugador y se utilizarían para construir un prompt que se enviaría a la IA con la siguiente información:
- El ítem a resolver y su respuesta (por ejemplo, “Oficio del asesino: Ingeniero”).
- La pregunta del usuario sobre ese ítem (por ejemplo, “¿Requiere estudios avanzados?”).
- Los otros tres ítems, también con sus respuestas, para enriquecer el contexto.
El modelo devolvería entonces true o false según si la pregunta del jugador esté o no bien encaminada. El principal desafío en este punto fue lograr que la IA comprendiera el concepto de “adivinar”. En las primeras pruebas, los falsos positivos y negativos aparecían con demasiada frecuencia y, aunque extender el prompt parecía una opción para reducir ambigüedades, en realidad era un arma de doble filo: al contar con ciertas features, la aplicación necesitaba realizar otras consultas —en la misma llamada para optimizar recursos— y esta request compuesta, si no era corta y concisa, derivaba en muchas alucinaciones.
En definitiva, necesitaba que la IA tradujera cada pregunta del jugador en un conjunto claro de claves de estado:
isGuessed: booleano que indica si la pregunta dio exactamente con la respuesta correcta (por ejemplo: “¿Es un ingeniero?” → true);isAFact: booleano que señala si la pregunta revela un dato importante sobre la respuesta, aun cuando no la haya adivinado exactamente (“¿Trabaja con planos o diseños?” → true);factSentence: en caso de queisAFactsea true, contiene la frase derivada de ese dato (“En esta profesión se suele trabajar con planos y diseños recurrentemente.”);isPositive: booleano que indica simplemente si la pregunta del jugador es positiva para la respuesta, por más queisGuessedeisAFactsean negativas (“¿Requiere estudios avanzados?” → true);isContinuation: booleano que indica si la pregunta actual del jugador está vinculada con sus preguntas anteriores (enseguida explicaré el motivo de este ítem).
Luego veremos qué prompt funcionó para lograr esas respuestas, pero lo que realmente optimizó los resultados fue hacerlo dinámico: no se trataba solo de insertar información en un string, sino que el mismo string debía variar según el ítem a resolver. De esta manera pude definir reglas y ejemplos específicos para oficio, lugar, causa y arma.
Otro punto clave fue mantener a la IA focalizada y veloz, y para eso necesitaba un contexto lo más reducido posible. El prompt dinámico formaría parte de ese contexto, pero ¿valía la pena reenviar todo el historial de preguntas y respuestas en cada llamada? Mi intuición fue que no; sin embargo, no hacerlo impedía que el juego funcionara como un auténtico chat: no se podían encadenar preguntas como “¿Requiere de estudios avanzados?” y “¿Muy avanzados?”.
Esa es la razón de la clave isContinuation. En cada request se incluye la pregunta actual y la inmediatamente anterior; si esta última está marcada un isContinuation igual a true, se incorpora también la precedente, y así sucesivamente hasta que alguna indique false. De este modo fue posible conservar la dinámica conversacional sin sobrecargar el contexto.
El motor del juego
Mi primera intención fue utilizar webLLM, un motor que ejecuta modelos generativos directamente en el navegador —de forma local y sin llamadas a una API—. Sin embargo, aparecieron varios problemas: dependencia de WebGPU (poco compatible con teléfonos móviles), tiempos de descarga elevados, bajo rendimiento incluso para preguntas simples y modelos poco confiables, que arrojaban falsos positivos y negativos con demasiada frecuencia. Por todo esto, tomé la misma iniciativa que en whatMLmodel: llamadas a la API de Gemini, cuya capa gratuita resultaba más que suficiente.
El frontend centraliza la lógica en un servicio orquestador que captura la pregunta del usuario, la empaqueta con el estado actual del juego (ítems y sus respuestas) y envía todo al servidor. El backend recibe esta request, selecciona el prompt correspondiente según el ítem a adivinar, inserta los datos y realiza la llamada a Gemini. Aquí implementé una estrategia de fallback entre modelos para asegurar la estabilidad: si el más liviano y rápido falla, la aplicación escala automáticamente a uno más potente —aunque más lento— sin que el usuario lo perciba. Además, diseñé un mecanismo de rotación de claves para ampliar aún más el margen de la capa gratuita: cuatro API keys gestionadas mediante un contador en Firebase.
Pero el corazón de todo fueron los prompts: para cada categoría construí indicaciones que instruyen al modelo para comparar la pregunta del jugador con la solución secreta, y responder únicamente en un formato JSON predefinido. Así, la IA distingue si existe una suposición exacta (isGuessed), un dato relevante (isAFact), una afirmación positiva (isPositive) y una continuación directa de preguntas (isContinuation). Aquí se el fragmento del prompt correspondiente al oficio del asesino:
El arte
Desde un principio tuve claro que Motive debía ser un juego en pixel art. Se trataba de un gusto personal, pero también de una oportunidad: al no requerir una gran cantidad de ilustraciones, podía tomarme el tiempo de experimentar por primera vez con este estilo.
Me enfrenté a varios desafíos de diseño, pero el verdadero reto llegó con el desarrollo: el elemento más recurrente —en botones, contenedores, etc.— era un cajón pixelado aparentemente sencillo, pero imposible de reproducir con opciones nativas de CSS. Así que tuve que pensar en un componente capaz de adaptarse en alto y ancho, y de renderizar múltiples divs dentro de sí para simular un borde pixelado.
La selección tipográfica fue más sencilla: necesitaba una fuente minimalista para los textos y otra más adornada para el logotipo. Para los textos elegí VP Pixel Simplified (completándola manualmente para soportar caracteres especiales en español) y, para el logotipo, Alagard, que encajó perfectamente con el nombre del juego.
Pero sí, Motive necesitaba algunas ilustraciones para cobrar vida. La idea fue tener el avatar de un detective siempre presente, para que el chat se sintiera como tal. Tras explorar diseños con modelos de generación de imágenes, di con uno muy bonito que repliqué manualmente en un layout de 26×26 píxeles. Así nació Motiveman, un personaje que reacciona a las acciones del jugador mediante un pequeño sistema de sprites: piensa, asiente y niega según el estado del juego. Este diseño, al mismo tiempo, determinó la paleta de colores. Sumándole efectos de sonido y música de misterio, la experiencia dejó de sentirse como una simple interfaz para convertirse en un videojuego con identidad propia.
El resultado
La navegación del menú se basa en un array que funciona como un breadcrumb: tenemos una secuencia de claves —por ejemplo, home/settings/createAccount— y, por cada una, se renderiza un layout diferente. Al hacer clic en una opción, se agrega un ítem al breadcrumb y se anima con un slide hacia la izquierda. Al hacer clic en “Volver”, ocurre lo opuesto: primero hay una traslación hacia la derecha y luego se elimina el ítem. El resultado es un sistema versátil que me permitió encadenar tantas pantallas como fuera necesario.
Al iniciar una partida aparece una introducción y, si es la primera vez que se juega, un tutorial que guía al jugador por las funcionalidades. Aquí se me ocurrió justificar la mecánica del “sí” y “no” de una forma bastante simple: se estaría interrogando a un testigo que está en shock y que únicamente puede negar o asentir con la cabeza.
En la parte superior se elige el ítem a investigar y, debajo, se muestra el chat para hacer las preguntas. Además de “sí” y “no”, existe la respuesta “hm…” para preguntas ambiguas o que no pueden responderse de ninguna de las dos formas. Un desafío importante fue lograr que el juego no resultara frustrante, y por eso aparece un mensaje de “Necesitas ser más específico” si la respuesta es “hm…” con demasiada frecuencia.
Cuando se descubre un nuevo hecho, el mismo se agrega a un Panel de Hechos. Esta mecánica surgió en una etapa avanzada del desarrollo, pero terminó siendo clave para orientar al jugador. Si aun así se necesita una pista explícita, puede pedirse una mediante una lupa verde que añade una frase —también generada por IA— a esa misma lista.
Resultaba fundamental relevar falsos positivos y negativos para mejorar, más adelante, el razonamiento de la IA. Para ello diseñé un sistema de reportes que permite describir el problema y marcar respuestas conflictivas. La idea es construir una base de datos sólida que sirva como insumo para mejorar el LLM output.
Cuando el jugador considera que ha identificado la respuesta, puede validarla mencionándola explícitamente. Si acierta, el misterio se revela y se resalta en verde. Para este evento, implementé una animación dedicada del avatar, que levanta el pulgar en señal de aprobación.
Hacia el final del desarrollo se me ocurrió una idea adicional: un quinto misterio que dio sentido al nombre del juego. El objetivo sería entonces identificar el motivo del homicidio, es decir, el móvil que llevó al asesino a cometer el crimen. Para no extender tanto la experiencia, decidí limitar esta etapa a una cantidad reducida de preguntas. El detective lo justifica explicando que el testigo necesita descansar y que su abogado accede a concedernos cinco preguntas más. En ese punto, la música cambia y el juego adopta un tono más tenso y emocionante.
Al finalizar la partida, se calcula el puntaje considerando factores como el tiempo de juego o la cantidad de pistas solicitadas. Algunos impactan de forma positiva y otros de manera negativa en el resultado final. Si el usuario no está registrado, el juego lo invita a crearse una cuenta para formar parte del ranking de jugadores.
