ドワーフ要塞の命令順序アーキテクチャ


21

AI用のコマンドオーダーシステムを実装する最もエレガントな方法は何ですか?たとえば、小人の要塞では、森林伐採エリアに木材の切断をマークすると、小人は次のシーケンスを実行します。

  1. 木に行く
  2. 木を切る
  3. 備蓄に木材を届ける
  4. 別の木に行く
  5. 等々..

私はすでにスタックコマンドが動作していません。アイドル状態からツリーの宛先タイルに到達する1。

私が恐れているのは、このような注文をさらに作成すると、これがどのように面倒になるかです:

家を建てる

  1. 備蓄に行く
  2. 建設エリアに木材を持ち込む
  3. 備蓄に戻る
  4. 建設エリアに石を持参
  5. 建物のスプライトをアニメートする

植付

  1. 備蓄に行く
  2. 種を農場に持ち込む

醸造

  1. 備蓄に行く
  2. 植物を静止させる
  3. 醸造スプライトをアニメートする

だから私の質問は、ドワーフ要塞のようなコマンド順序システムをどのように実装し、同時にスパゲッティコードを回避するのですか?調査する必要があるデータ構造はありますか?コマンドシーケンスを別のxmlファイルに配置する必要がありますか?


1
ドワーフ要塞には実際にそのようなシステムはありません。ドワーフには一度に1つのタスクが割り当てられ、アイドルドワーフは何かすることを探します。(「ねえ、チョッピング用にマークされたツリーがあります-チョップする必要があります!」/「ねえ、備蓄されていない木材があります
持って行ってください

1
ドワーフはプレイヤーによって何も割り当てられませんが、システムによって「割り当てられた」タスクです。これはまさに、Jed T.が説明したアーキテクチャです。注文を作成すると、システムはその注文を満たすために個々のコンポーネントタスクを割り当てます。
アタックファーム

2
これはタスクの割り当てとスケジューリングと呼ばれ、いくつかの工学分野で広く研究されていることに注意してください。この問題を議論する多くの論文がありますが、これは興味深いものです。
-TonioElGringo

@Attackfarmシステムはすべてのタスクを事前に決定しません。また、複数のタスクを同じドワーフに割り当てません。最初に1つのタスクが割り当てられ、完了すると、別のタスクが使用可能になります。
user253751

回答:


27

最初は、コマンドがリストの形式であることがわかります。したがって、最初の本能はその構造を再作成することであり、各ドワーフはそのリストを順番に実行します。ただし、リストをステップ分割し、各ステップに前提条件を設定してから、コマンド全体を逆に実行することをお勧めします。例を示してみましょう。

木材切断

  • 木材を積んでいますか?はい:降ろします
  • 木材を運んでいますか?はい:備蓄に行きます
  • 私は木ですか?はい:チョップ
  • 上記のすべてにいいえ:木に行きます

これの利点は次のとおりです。

  • 実装が非常に簡単
  • 柔軟性-このリストを自由に分解し、アイテムを追加し、アイテムを削除し、アイテムを結合できます
  • 状態なし-任意の状態の任意のドワーフに対してこのリストを上から実行できます。ドワーフはDo the Right Thing TMを実行します

短所:

  • 状態がなく、スタックしていることを認識していないため、ループでスタックするのは簡単です

論理的に、これらのコマンドはフローチャートとして表すことができ、毎回上から実行されます。実行することは、各ステップでyes / noで答えるかどうかによって異なります。これをコードで実装するか、XMLなどの外部ファイルで実装するかはユーザー次第です。


2
これには、ステータスをコマンドに優先させるという利点もあります。「はい」の場合、すべてをドロップし、タスクを「食べる」に設定します
ラチェットフリーク

7
@ratchetfreak「要塞の安全性は私がこのモンスターと戦うことに依存していることを知っているので、民間人を攻撃することはありませんが、まあ、私の胃はうなりました!」その点ではあまりDFのようなことをしないようにしてみてください。P
大佐の32個の

私はこの似ているが、どのような用途(あるいは少なくとも、使用)の盗聴アーティファクト許可されていると思いますplanepackedを(これはルーピング言っ引き起こし、禁止項目、によるものであった)
Destrictor

3
@ColonelThirtyTwo funその中のどこに?;)
ラッセ

このために宣言的なシンボリックアクションプランニングを使用しないことを強くお勧めします。デバッグすることは基本的に不可能であり、望ましくない動作が簡単に発生する可能性があります。手順ごとに各タスクのアクションシーケンスをハードコードする方がはるかに簡単です。
mklingen

10

シーケンスを非常に一般的にすることができる場合、スパゲッティコードはあまりありません。

たとえば、配達の場合:WorkTaskはWorkPlanで動作します。ワークプランでは、どの種類のリソースユニットを選択する必要があるか、どの種類の家から、どの歩行アニメーションを使用するか、どの作業アニメーションを使用するか、作業時間など、すべての詳細を説明しています。したがって、最終的にWorkTaskは次のようになります。

  1. マップで%resource1%を見つける
  2. %animation_1%を使用してその場所に移動します
  3. %time%で%animation_2%を使用してその場で作業する
  4. %req_count1%カウントで%req_resource1%を取る
  5. %animation%を使用して%home%に移動します
  6. %time_2%で内部で%animation_6%を開始します
  7. 等..

説明されたアプローチをうまく使用しています。ゲームには〜15個のタスクがあります。いくつかのハイライト:

  • タスクはユニットアクションを提供します(そこに行く、入る、出る、ここに行く、滞在する、働く、行く)
  • アクションは「完了」または「中止」状態で終了し、タスクに渡します
  • すべてがハードコーディングされています(パーサー、インターフェイスメソッド、後方互換性を記述する必要はありません)
  • 各タスクは、いくつかの一般的なメソッド(作成、実行、保存、ロード)だけで抽象タスククラスを実装します
  • 通常、モジュールごとに1つのタスクですが、同様のタスクは1つのモジュールにあります
  • 非常によく似たタスクが1つのクラス内にあり、少数のIFによって支配されています(家への配達またはユニットへの配達)
  • 各タスクには、リソースの適切なロックおよびロック解除が必要です(ユニットが任意のステップで停止した場合、ロックしたリソースを解放する必要があります)

2
これは、ドワーフ要塞のようなゲームで使用するシステムです。タスクは動作ツリーによって達成されます。リソースは動作によってロックされ、障害によってロック解除されます。トップアンサー
-mklingen

5

したがって、これは基本的に地形的なソートの問題です。

グラフがあり、各ノードは実行する必要があるタスクであり、一部のノードは他のノードに依存しています(これは、依存ノードから依存ノードまでのグラフのエッジで表されます)。すべてのタスクを実行するため、地形的に問題のないノードの順序を作成する必要があります(依存ノードは依存ノードの後に​​あります)。

現在、通常、このような順序が多数あります(一部のノードは依存関係がなく、どこにでも配置でき、一部のノードは同じ依存関係を持ち、相互に依存していないため、ノード間の順序は任意です。依存関係が完了した後、およびそれに依存するノードが実行される前に、任意の場所に配置してください)。

グラフを地形的にソートする方法がないことも可能です-これは、グラフにサイクルがある場合に発生します(木がない、木を切る必要がある木を得る、needを切る木を切る、,を作る木材が必要です)。このような場合、アルゴリズムはおそらくこれらのタスクを実行できないことをプレーヤーに示す必要があります。

ノードに優先順位を追加することもできます。タスクは、依存関係を完全に満たすすべての順序付けのうち、優先順位の高いノードが最初に実行されるような順序付けを見つけることです。

繰り返しタスクを追加することもできます-最も簡単な方法は、おそらくタイムアウトが発生するたびに、タスクが完了するたびにグラフに再度追加することです。

今それを解決する方法-http://en.wikipedia.org/wiki/Topological_sorting

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.