Comando que ordena la arquitectura de la fortaleza enana

21

¿Cuál es la forma más elegante de implementar un sistema de orden de comandos para AI? por ejemplo, en la fortaleza enana cuando marcas un área boscosa para cortar madera, los enanos luego harían la siguiente secuencia:

  1. Ir al árbol
  2. Cortar el árbol
  3. Entregar madera a la reserva
  4. Ir a otro árbol
  5. y así..

Ya tengo un comando de pila trabajando no. 1 que pasa del estado inactivo a alcanzar el mosaico de destino del árbol.

De lo que me temo es de cómo esto se complicaría cuando creo más pedidos como este:

Construir una casa

  1. Ir a la reserva
  2. traer madera al área de construcción
  3. volver a la reserva
  4. Llevar piedra al área de construcción.
  5. sprite animado del edificio

Plantando

  1. Ir a la reserva
  2. traer semillas a la parcela agrícola

Fabricación de cerveza

  1. Ir a la reserva
  2. Trae la planta a todavía
  3. sprite animado de elaboración de cerveza

Entonces mi pregunta es, ¿cómo implemento un sistema de orden de comandos como fortaleza enana y evitando el código de espagueti al mismo tiempo? ¿Hay alguna estructura de datos que deba estudiar? ¿Necesito poner la secuencia de comandos en un archivo xml separado?

Jed T.
fuente
1
La fortaleza enana en realidad no tiene ese sistema. A los enanos se les asigna una tarea a la vez, y los enanos inactivos buscarán algo que hacer. ("Oye, hay un árbol marcado para cortar, ¡debería cortarlo!" / "Oye, hay un poco de madera que no está en una pila, ¡debería llevarlo a uno!")
user253751
1
El jugador no asigna nada a los enanos, pero el sistema les asigna tareas "asignadas", que es exactamente la arquitectura que Jed T. describe arriba. Crear orden, y el sistema asigna tareas de componentes individuales para cumplir con ese orden.
Attackfarm
2
Tenga en cuenta que esto se denomina asignación y programación de tareas, y se estudia ampliamente en varios campos de ingeniería. Encontrará muchos documentos sobre este problema, que podrían ser de interés.
TonioElGringo
@Attackfarm El sistema no decide todas las tareas por adelantado; ni asigna múltiples tareas al mismo enano. Inicialmente se asigna una tarea y, cuando se completa, tiene la consecuencia de hacer que otra tarea esté disponible.
user253751
2
Esto suena como un excelente caso de uso para la planificación de acciones orientadas
problemático del

Respuestas:

27

Al principio, verá que sus comandos tienen la forma de una lista , por lo que su primer instinto podría ser recrear esa estructura, y cada enano correrá por esa lista en secuencia. Sin embargo, lo que sugiero es dividir la lista en pasos , y cada paso tiene prerrequisitos , y luego ejecuta todo el comando en reversa . Déjame demostrarte con un ejemplo:

Corte de madera

  • ¿Estoy cargando madera y en un arsenal? : déjalo
  • ¿Estoy llevando madera? : ir a un arsenal
  • ¿Estoy en un árbol? : picarlo
  • No a todo lo anterior : ve a un árbol

Las ventajas de esto son:

  • Muy simple de implementar
  • Flexible: puede descomponer libremente esta lista, agregar elementos, eliminar elementos, combinar elementos
  • Sin estado: puede ejecutar esta lista desde arriba para cualquier enano en cualquier estado, y el enano simplemente hará lo correcto TM

Desventajas

  • Es fácil quedar atrapado en bucles, ya que no hay estado ni conciencia de estar atascado

Lógicamente, puede representar estos comandos como un diagrama de flujo, que se ejecuta desde arriba cada vez, y lo que haga depende de si responde sí / no en cada paso. Depende de usted si implementa esto en código o en un archivo externo como XML.

congusbongus
fuente
2
Esto también tiene la ventaja de dejar que el estado anule los comandos. ¿Tengo hambre? en caso afirmativo, suelte todo y establezca la tarea para "comer", siendo similar al trabajo de acarreo de madera.
Ratchet Freak
77
@ratchetfreak "Sé que la seguridad de mi fortaleza depende de mí luchando contra este monstruo para que no ataque a los civiles, pero ¡Dios mío, mi estómago gruñó!" Trate de no parecerse demasiado al DF en ese sentido: P
Coronel Treinta y Dos
Creo que esto se asemeja a los usos (o al menos utilizados) que permitieron el artefacto con errores de planepacked (esto se debió a un elemento prohibido, que causó dicho bucle)
Destrictor
3
@ColonelThirtyTwo ¿Dónde está funeso? ;)
Lasse
Recomiendo no utilizar la planificación de acciones simbólicas declarativas para esto. Es básicamente imposible de depurar, y fácilmente puede surgir un comportamiento indeseable. Mucho más fácil codificar las secuencias de acción para cada tarea de forma procesal.
mklingen
10

Si puede hacer que las secuencias sean bastante generales, no hay mucho código de espagueti.

En caso de entregas, por ejemplo: WorkTask funciona con un WorkPlan. El plan de trabajo dice qué tipo de unidad de recursos debe elegir, de qué tipo de casa, usando qué animación de paseo, usando qué animación de trabajo, tiempo para trabajar y todos esos detalles. Así que al final WorkTask podría verse así:

  1. Encuentra% resource1% en el mapa
  2. Ve a esa ubicación usando% animation_1%
  3. Trabajar en el lugar usando% animation_2% por% time%
  4. Tome% req_resource1% en% req_count1% count
  5. Vaya a% home% usando% animation%
  6. Inicie% animation_6% dentro por% time_2%
  7. etc.

Utilizamos con éxito el enfoque descrito. Tenemos ~ 15 tareas en nuestro juego. Algunos puntos destacados:

  • Las tareas dan acciones de la unidad (ir allí, entrar, salir, ir aquí, quedarse, trabajar, ir)
  • La acción finaliza con el estado Listo o Abortado y la pasa a la Tarea
  • Todo está codificado (no es necesario escribir analizador, métodos de interfaz, compatibilidad con versiones anteriores)
  • Cada tarea implementa la clase de tarea abstracta con solo unos pocos métodos comunes (crear, ejecutar, guardar, cargar)
  • Generalmente una tarea por módulo, pero hay tareas similares en un módulo
  • Tareas muy similares se encuentran dentro de una clase y se rigen por pocos IF (entrega a domicilio o entrega a unidad)
  • Cada tarea necesita un bloqueo y desbloqueo de recursos adecuados (por ejemplo, si la unidad muere en CUALQUIER paso, el recurso que bloqueó debe liberarse)
Kromster dice que apoya a Mónica
fuente
2
Este es el sistema que utilizamos en nuestro juego de fortaleza enana. Las tareas se realizan mediante árboles de comportamiento. Los recursos quedan bloqueados por comportamientos y desbloqueados por fallas. Es mucho más robusto y fácil de depurar que el enfoque de planificación de acción descrito por la respuesta principal
mklingen
5

Así que este es básicamente un problema de clasificación topográfica.

Tiene un gráfico, cada nodo es una tarea que debe realizarse, y algunos nodos dependen de otros nodos (esto se representa mediante un borde en el gráfico desde el nodo dependiente hasta el nodo del que depende). Desea realizar todas las tareas, por lo que debe producir ALGUNOS ordenamientos de los nodos que estén topográficamente correctos (los nodos dependientes están después de los nodos de los que dependen).

Ahora, generalmente hay muchos de esos ordenamientos (porque algunos nodos no tienen dependencias y pueden colocarse en cualquier lugar, y algunos nodos tienen las mismas dependencias y no dependen entre sí, por lo que pueden estar en cualquier orden entre ellos, y cualquier nodo puede se coloque en cualquier lugar después de que se hagan las dependencias y antes de que se hagan los nodos que dependen de él).

También es posible que no haya forma de ordenar un gráfico topográficamente: esto sucede cuando hay ciclos en el gráfico (no tiene madera, para obtener madera necesita cortar un árbol, cortar un árbol necesita un hacha, hacer un hacha) Necesito madera). En tal caso, el algoritmo probablemente debería indicarle al jugador que estas tareas no se pueden hacer.

También puede agregar prioridades a los nodos, y la tarea puede ser encontrar dicho orden, entre todos los pedidos que llenan las dependencias, que tiene los nodos de mayor prioridad realizados primero.

También puede agregar tareas de recreación: la forma más fácil probablemente será simplemente agregar la tarea con tiempo de espera nuevamente al gráfico cada vez que se realiza.

Ahora cómo resolverlo: http://en.wikipedia.org/wiki/Topological_sorting

Sebastian Pidek
fuente