Command Ordering Architecture of Dwarf Fortress


21

Qual è il modo più elegante per implementare un sistema di ordinamento dei comandi per l'IA? ad esempio nella fortezza nana quando si contrassegna un'area boschiva per il taglio del legno, i nani eseguiranno quindi la seguente sequenza:

  1. Vai all'albero
  2. Taglia l'albero
  3. Consegna legna alla scorta
  4. Vai a un altro albero
  5. e così via..

Ho già un comando stack funzionante no. 1 che passa dallo stato inattivo al raggiungimento della piastrella di destinazione dell'albero.

Ciò di cui ho paura è come questo diventi disordinato quando creo più ordini come questo:

Costruire una casa

  1. Vai a scorta
  2. portare il legno nell'area di costruzione
  3. torna alle scorte
  4. Porta la pietra nell'area di costruzione
  5. animare lo sprite dell'edificio

Piantare

  1. Vai a scorta
  2. porta semi alla trama della fattoria

Brewing

  1. Vai a scorta
  2. Porta la pianta ferma
  3. animare lo spirito di birra

Quindi la mia domanda è: come posso implementare un sistema di ordinazione dei comandi come fortezza nana ed evitare allo stesso tempo il codice spaghetti? ci sono delle strutture di dati che devo studiare? Devo mettere la sequenza di comandi su un file XML separato?


1
La fortezza nana in realtà non ha un tale sistema. Ai nani viene assegnato un compito alla volta e i nani inattivi cercheranno qualcosa da fare. ("Ehi, c'è un albero contrassegnato per il taglio - dovrei tagliarlo!" / "Ehi, c'è del legno non in una scorta - dovrei portarlo a uno!")
user253751

1
Ai nani non viene assegnato nulla dal giocatore, ma vengono assegnati compiti "assegnati" dal sistema, che è esattamente l'architettura descritta da Jed T. sopra. Crea ordine e il sistema assegna le attività dei singoli componenti al fine di soddisfare tale ordine.
Attackfarm,

2
Si noti che questo è chiamato assegnazione e pianificazione delle attività ed è ampiamente studiato in diversi campi ingegneristici. Troverai molti articoli che parlano di questo problema, che potrebbero essere di interesse.
TonioElGringo,

@Attackfarm Il sistema non decide in anticipo tutte le attività; né assegna più attività allo stesso nano. Inizialmente viene assegnata un'attività e, una volta completata, ha la conseguenza di rendere disponibile un'altra attività.
user253751

Risposte:


27

All'inizio vedi che i tuoi comandi hanno la forma di un elenco , quindi il tuo primo istinto potrebbe essere quello di ricreare quella struttura, e ogni nano scorrerà attraverso quell'elenco in sequenza. Quello che suggerisco però è di spezzare l'elenco in passaggi , con ogni passaggio con i prerequisiti e quindi eseguire l'intero comando al contrario . Lasciami dimostrare con un esempio:

Taglio del legno

  • Sto portando la legna e una scorta? : rilascialo
  • Sto portando legno? : vai a una scorta
  • Sono ad un albero? : tritatelo
  • No a tutti sopra : vai a un albero

I vantaggi di questo sono:

  • Molto semplice da implementare
  • Flessibile: puoi decomporre liberamente questo elenco, aggiungere elementi, rimuovere elementi, combinare elementi
  • Nessuno stato: puoi eseguire questo elenco dall'alto per qualsiasi nano in qualsiasi stato e il nano farà semplicemente la cosa giusta TM

svantaggi:

  • È facile rimanere bloccati nei circuiti, poiché non c'è stato e consapevolezza di essere bloccati

Logicamente, puoi rappresentare questi comandi come un diagramma di flusso, che viene eseguito dall'alto ogni volta, e ciò che fai dipende dal fatto che rispondi sì / no ad ogni passaggio. Decidi tu se implementarlo nel codice o in un file esterno come XML.


2
Questo ha anche il vantaggio di lasciare che lo stato sovrascriva i comandi, ho fame? se sì, lascia cadere tutto e imposta il compito di "mangiare" con mangiare simile al lavoro di trasporto del legno.
maniaco del cricchetto,

7
@ratchetfreak "So che la sicurezza della mia fortezza si basa sul fatto che io combatto questo mostro in modo che non attacchi i civili, ma cavolo, il mio stomaco ha appena ringhiato!" Cerca di non renderlo troppo simile a DF in questo senso: P
Colonnello Trenta due

Penso che questo assomigli a ciò che usa (o almeno usa) che ha permesso al manufatto infilato di planepacked (questo era dovuto a un oggetto proibito, che causava detto loop)
Destrictor

3
@ColonelThirtyTwo Dov'è la funcosa? ;)
Lasse,

Consiglio vivamente di non utilizzare la pianificazione di azioni simboliche dichiarative per questo. È praticamente impossibile eseguire il debug e possono insorgere facilmente comportamenti indesiderati. Molto più semplice codificare le sequenze di azioni per ciascuna attività in modo procedurale.
mklingen,

10

Se riesci a rendere le sequenze piuttosto generali, non c'è molto di un codice spaghetti.

In caso di consegne, ad esempio: WorkTask funziona con un piano di lavoro. Il piano di lavoro dice quale tipo di unità di risorse deve scegliere, da quale tipo di casa, usando quale animazione di camminata, usando quale animazione di lavoro, tempo di lavoro e tutti questi dettagli. Quindi alla fine WorkTask potrebbe apparire come:

  1. Trova% resource1% sulla mappa
  2. Vai in quella posizione usando% animation_1%
  3. Lavora sul posto usando% animation_2% per% time%
  4. Prendi% req_resource1% nel conteggio% req_count1%
  5. Vai a% home% utilizzando% animazione%
  6. Avvia% animation_6% all'interno per% time_2%
  7. eccetera..

Usiamo con successo l'approccio descritto. Abbiamo ~ 15 compiti nel nostro gioco. Alcuni punti salienti:

  • Compiti forniscono azioni unitarie (vai lì, entra, esci, vai qui, rimani, lavora, vai)
  • L'azione termina con stato Fatto o Interrotto e la passa all'attività
  • Tutto è codificato (non è necessario scrivere parser, metodi di interfaccia, compatibilità all'indietro)
  • Ogni attività implementa la classe Task astratta con pochi metodi comuni (creare, eseguire, salvare, caricare)
  • Generalmente un'attività per modulo, ma attività simili si trovano in un modulo
  • Compiti molto simili rientrano in una classe e sono regolati da pochi IF (consegna a domicilio o consegna a unità)
  • Ogni attività richiede un corretto blocco e sblocco delle risorse (ad esempio se l'unità muore in QUALSIASI passaggio, la risorsa che ha bloccato deve essere rilasciata)

2
Questo è il sistema che usiamo nel nostro gioco di fortezza nana. Le attività vengono eseguite da alberi del comportamento. Le risorse vengono bloccate dai comportamenti e sbloccate per errore. È molto più robusto e facile da eseguire il debug dell'approccio di pianificazione dell'azione descritto dalla risposta principale
mklingen

5

Quindi questo è fondamentalmente un problema di ordinamento topografico.

Hai un grafico, ogni nodo è un'attività che deve essere eseguita e alcuni nodi dipendono da alcuni altri nodi (questo è rappresentato da un bordo nel grafico dal nodo dipendente al nodo da cui dipende). Si desidera eseguire tutte le attività, quindi è necessario produrre ALCUN ordine dei nodi che è topograficamente OK (i nodi dipendenti sono dopo i nodi da cui dipendono).

Ora, di solito ci sono molti di questi ordinamenti (perché alcuni nodi non hanno dipendenze e possono essere posizionati ovunque, e alcuni nodi hanno le stesse dipendenze e non sono dipendenti l'uno dall'altro, quindi possono essere in qualsiasi ordine tra loro e qualsiasi nodo può essere messo in qualsiasi posto dopo che sono state fatte le sue dipendenze e prima che siano fatti i nodi che dipendono da esso).

È anche possibile che non ci sia modo di ordinare un grafico per topografia - questo accade quando ci sono cicli nel grafico (non hai legno, per ottenere legno devi tagliare un albero, tagliare l'albero che ti serve ascia, per farti ascia bisogno di legno). In tal caso, l'algoritmo dovrebbe probabilmente indicare al giocatore che questi compiti non possono essere svolti.

È inoltre possibile aggiungere priorità ai nodi e il compito potrebbe essere quello di trovare tale ordinamento, tra tutti gli ordini che soddisfano le dipendenze, che abbia per primo i nodi con priorità maggiore.

Puoi anche aggiungere attività ricorrenti: il modo più semplice sarà probabilmente quello di aggiungere nuovamente l'attività con timeout al grafico ogni volta che viene eseguita.

Ora come risolverlo - http://it.wikipedia.org/wiki/Topological_sorting

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.