Diseñé un juego de rol que tiene múltiples hilos de historia, lo que significa que, dependiendo de la elección del usuario, algunas cosas pueden suceder o no, puede lograr lo mismo de varias maneras, el final puede ser diferente, etc.
Implementé un motor de decisión simple, que funciona bien pero tiene un gran defecto, en el momento en que tomas una decisión, la historia está influenciada inmediatamente por tu decisión, lo que significa que no puedes tomar una decisión que te afectará en el futuro lejano. . Esto se debe a que la historia se desarrolla como una rama en una estructura de árbol, y siempre necesita saber qué nodo es el siguiente. Bajo el capó, las decisiones se implementan utilizando una cola: cada nodo conoce el nodo anterior y el siguiente (o si es un nodo de decisión, espera la entrada del usuario para establecer el siguiente nodo)
Vi muchos juegos que tienen motores de decisión complejos, y me pregunto, ¿cómo se hacen? ¿Existe un diseño especial que haga las cosas realmente fáciles? ¿Alguien hizo algo similar y me puede dar una pista sobre cómo abordar esto?
ACTUALIZACIÓN 1:
Un aspecto importante es lograr mantener de alguna manera el código de la historia independiente, para que pueda ser manipulado desde un archivo externo. Planeo usar esto como un motor, por lo que incluso las posibles opciones tienen que venir de un archivo externo. El código tiene que ser totalmente abstracto.
Además, estoy interesado en una solución de diseño, una buena manera de hacerlo, cómo lo hacen o lo hacen otros.
fuente
if (isTree)
o mantener unaisTree
var global porque la historia puede tener o no esa opción. ¿Ya tu sabes? Es más como un motor de elección que servirá múltiples historias.isTree=true
, sin embargo, más tarde, hace algo más, como pelear contra un compañero de escuela, quien a cambio va y corta su árbol mientras el árbol aún es joven. porque le patearon el trasero. Ahora, tenemos 2 variables que influyen en la existencia del árbolisTree==true' and
didFightBrat == false`. ¿Ya tu sabes? Y la cadena puede continuar para siempre, la existencia del árbol puede verse influenciada por un número desconocido de factores. ¿Ya tu sabes?Respuestas:
También puede generalizar la cola en un gráfico acíclico dirigido (DAG). Puedes leer sobre esto en Wikipedia. Básicamente, cada nodo puede tener uno o más nodos principales de los que "depende". Los ciclos no están permitidos, es decir, si A depende de B, B no puede depender de A (directamente o mediante cualquier cadena indirecta de otros nodos).
Cada nodo está en un estado "activo" o "inactivo", y solo se permite que se active si todos sus padres ya están activos. La estructura del gráfico (qué nodos hay y cómo están conectados) es parte de los datos del juego, pero el estado activo / inactivo es parte de los datos guardados del jugador.
De esa manera, puede modelar cosas como: cuando planta un árbol, marca una tarea "árbol plantado" como activa; luego, más adelante en el juego, otra tarea "treeGrown" nombra tanto "plantedTree" como algún otro nodo (parte de la historia) como sus padres. Entonces, "treeGrown" solo se activa cuando el jugador llega a ese punto en la historia, y también "plantedTree" está activo.
Puede incluir otras funciones, como nodos que se activan si alguno de sus padres se activa, o nodos que son activados por un padre y desactivados por otro, y así sucesivamente. Es un marco bastante general para crear historias con múltiples hilos interdependientes.
fuente
Por lo que entiendo, lo que quieres no es solo un motor de decisión, sino también un motor de reglas. Para cada decisión, ejecuta un subconjunto de reglas definidas por esa decisión. La ejecución de esas reglas a menudo depende del estado de ciertas entidades como su ejemplo de árbol.
Básicamente, cuando su jugador toma una decisión, busque esa decisión, ejecute las reglas y luego proporcione el siguiente conjunto de decisiones disponibles de manera normal. Sin embargo, sus reglas son dinámicas ya que algunas de ellas solo se ejecutarán en función de otras reglas que ya se han ejecutado.
Un poco más en Wikipedia .
De su subtítulo Cuándo usar los motores de reglas (el énfasis es mío):
Una cosa a tener en cuenta es que, en ocasiones, un motor de reglas se implementa mejor utilizando un "lenguaje" específico de dominio simplificado, o algo así como YAML. No sugeriría XML.
fuente
Debe tener en cuenta que un evento no se basa únicamente en la decisión del usuario. Como notó, algún evento debe agregarse cuando se toman un conjunto de secuencias de decisiones y luego se agrega algo más (como dos días después).
Lo que creo que necesita es una forma de modelar eventos y una forma de activarlo. Mientras que el primero está más limitado a su caso específico, el segundo puede ser modelado por una máquina de estado jerárquico (HSM) que activa sus eventos de forma directa o indirecta.
Tenga en cuenta que una máquina de estados sufre la maldición de la dimensionalidad que solo es mitigada por una estructura jerárquica. Pronto comprenderá que necesita modelar el significado complejo del estado utilizando un HMS, pero también proporcionar una forma de consultarlo.
En este escenario, tiene eventos básicos (decisiones del usuario, tiempo, cambios en el clima, etc.) que son procesados tanto por HSM como por devoluciones de llamadas de eventos básicos. El HSM proporciona un modelo para la "memoria" y las devoluciones de llamada proporcionan una forma de describir cómo debe usarse esa memoria para calcular las consecuencias de una secuencia de decisiones / eventos externos.
También puede terminar usando un dictonario (o alguna otra estructura de recopilación) de HMS, uno para cada "aspecto" del estado que tiene que calcular. Un ejemplo puede ser el uso de un evento HMS relacionado y uno para las decisiones que toman las devoluciones de llamada para desencadenar eventos.
Toda esta infraestructura sirve para imitar el comportamiento de un Dungeon Master humano: generalmente toma un registro mental de la situación actual (HMS ["externo"]) debido a las decisiones del jugador y las condiciones ambientales; cuando algo se agrega, puede tomar decisiones utilizando su registro mental y también registrar algún estado de estrategia interna (HSM ["interno"]) para evitar reaccionar de manera similar si, por ejemplo, se produce alguna situación.
fuente