資源

村人をグループ分けする

はじめに言っておきますが、村人一人一人に指示を送ることは出来ません。ですが逆にいえば、村人一人一人に細かく指示を送る必要はないということです。

村人は役割別にグループ分けされます。グループは以下の三つです。

  • 探検者 (explorers)
  • 建築者 (builders)
  • 採取者 (gathers)
まずはグループ分けの行われ方について解説したいと思います。

グループ分けを行うための命令には、大体以下のようなものがあります。

(set-strategic-number sn-percent-civilian-explorers 0)
(set-strategic-number sn-percent-civilian-builders 67)
(set-strategic-number sn-percent-civilian-gatherers 33)
(set-strategic-number sn-cap-civilian-explorers 0)
(set-strategic-number sn-cap-civilian-builders 999)
(set-strategic-number sn-cap-civilian-gatherers 1)

上の三つが配分割合で、下の三つが最大数です。公式ドキュメントによれば、村人のグループ分けには、まず配分割合を元に行われます。三つの配分割合には、パーセントで値を設定します。上の例では、探検者の割合を 0 に、建築者の割合を 67% に、採取者の割合を 33% にしています。グループ分けは大体この数値で決まるのですが、このあとに下の三つの最大数の設定により、最終的なグループ分けが決まります。下の三つの値は、各グループの人数制限をしていると考えてください。上の例では、採取者は全体の 33% の村人にすることにしていますが、下の設定により採取者の最大人数をたった一人にしています。ですから、基本的には採取者は最大で一人しか作らない、ということになります。

しかし、上のグループ分けはあくまで指示しただけです。コンピュータが上の指示に従ってグループ分けを行うと、配分割合で決めたグループ分けが、最大数によって制限される事で、どこのグループにも属さない村人が出てくるはずです。また、建築者は基本的には、建てる物が無いときはグループ自体が機能しないため、村人は建築者のグループに分けられる事はありません。つまり、指示上、どのグループにも属さない村人が出てくるわけです。このような村人は、コンピュータが勝手に適当な作業をさせてしまいます。ですから、グループ分けに関する指示は絶対ではありません。あくまで目安のようなものです。

1. 探検者 (explorers)

探検者グループに属した村人は、マップをくまなく探索します。特に指示がない限り、死ぬまで探索を続けるものと思います。

探検者グループを作るメリットは、私が思うには、最初の資源を発見するときぐらいだと思います。斥候が殺された時には探検者グループを作ると良いのかもしれませんが、我々人間がゲームをするときには、村人を探索に出す必要はないと思います。ですから、このグループには村人を割り当てない方が良いでしょう。

2. 建築者 (builders)

建築者グループは建物を建てます。建物の中には畑も含まれます。

私がこれまで見た限りでは、AI は一つの建物を二人以上の村人が協力して建てることはほとんどありません。しかし一応例外があって、一つの建物を建て終えた建築者の近くにたまたま建設中の建物があった場合は、その建築者その建物の建築にも協力します。

一つの建物を複数の村人が協力して建てる事ができないというのはなんとも嫌らしいのですが、これも AI の弱点だと思って諦めるしかないでしょう。特に、一番最初家を少なくとも一軒建てないと、村人をどんどん作る流れが止まってしまいます。城とか町の中心を建てるにも時間が掛かってしまいます。しかし、コンピュータ自体もともと反応早いので、割り切ってしまっても良いのではないかと思います。最初の家と二つ目の町の中心遅いのは気になりますが、建築に関しては人間より有利だと思います。

3. 採取者 (gathers)

採取者はさらに細かくグループ分けされます。グループ分けのためのコマンドは以下の通りです。

(set-strategic-number sn-food-gatherer-percentage 45)
(set-strategic-number sn-gold-gatherer-percentage 20)
(set-strategic-number sn-stone-gatherer-percentage 0)
(set-strategic-number sn-wood-gatherer-percentage 35)

簡単です。上から、食料、金、石、木の採取に割り当てる村人の割合をパーセンテージで設定するだけです。

ここで食料に関して注意しておきたいのは、畑は自動的には作られないということです。それと、手近に食料がない時は、かなり遠くまで食料を取りにいってしまいます。

グループ分けを制御する

グループ分けは、現在の資源の状態や、村人の人口、現在の時代、軍隊の構成によって、細かく制御してやる必要が出てくるでしょう。ここでは、グループ分けを変更するときの条件として使うと便利なものを説明したいと思います。

1. 現在の資源の状態

いまどのくらい資源を持っているのかを判断するための条件は以下の四つです。

(wood-amount < 300)
(food-amount == 100)
(stone-amount >= 650 )
(gold-amount <= 200)

等号や不等号のあとに数値を書くことで、それぞれの資源が式の通りになると条件を満たした事になります。等号は = ではなく == なので注意してください。また、不等号には less-than なども使うことができますが、我々は日本語を使う人間なので素直に記号で良いと思います。

以下は、金が足りなくなってきたら金に全力を注ぎ、金が十分にあるときは金を採掘しないようにする、という例です。

(defrule
  (gold-amount < 1000)
  =>
  (set-strategic-number sn-food-gatherer-percentage 45)
  (set-strategic-number sn-gold-gatherer-percentage 20)
  (set-strategic-number sn-stone-gatherer-percentage 0)
  (set-strategic-number sn-wood-gatherer-percentage 35)
)
(defrule
  (gold-amount >= 1000)
  =>
  (set-strategic-number sn-food-gatherer-percentage 0)
  (set-strategic-number sn-gold-gatherer-percentage 100)
  (set-strategic-number sn-stone-gatherer-percentage 0)
  (set-strategic-number sn-wood-gatherer-percentage 0)
)

しかし実際には、掘ろうにも金が無かったり遠かったりすることがありますので、上のような単純な切り替えだけではなく、他にいくつか条件をつけなければならないでしょう。

2. 村人や他のユニットの人口

村人を含めた特定のユニットの人数を条件にするには、以下のように書きます。

(unit-type-count villager > 10)
(unit-type-count-total man-at-arms < 5)

上の unit-type-count は、現在存在しているユニットだけを数え、下の unit-type-count-total は、現在生産中のユニットも数えます。man-at-arms軍兵です。

全人口を数える条件もあります。

(population > 50)

また、軍事ユニット全ての数を数える条件もあります。

(military-population >= 30)

3. 時代の条件

現在どの時代かによって実行する命令を変えることが出来ます。そのための条件は以下の通りです。

(current-age == dark-age)
(current-age >= feudal-age)
(current-age < castle-age)
(current-age <= imperial-age)

領主の時代になってからどのくらい時間が経ったか、というのも条件にする事が出来ます。

(current-age == feudal-age)
(current-age-time > 300)

上の条件は、現在の時代か領主の時代でかつ 5分(300秒)以上経っているかどうかをチェックするためのものです。

他のプレイヤーがどの時代かどうかを調べることもできますが、これはあとで解説したいと思います。
 

資源を採取する

近くの資源を採取したいときには、村人の配分さえしておけば問題ありません。しかし、遠くの資源を採取したいときには、粉引き所や伐採所や採掘場を建てる必要があります。これらを建てること自体は簡単です。

(build mill)          ; 粉引き所
(build lamber-camp)    ; 伐採所
(build mining-camp)    ; 採掘場

ただし、建て過ぎないように建築を制限するのを忘れないでください。

また、これらの建物は、資源から近い位置をコンピュータが勝手に判断して建ててしまいます。ですから、たとえばもし金や石を全く発見していない初期の段階で採掘場を建てようとすると、全然見当違いな場所に採掘場を建ててしまいます。また、ゲーム開始時に木は確実にありますが、森を発見していない状態で採掘場をすぐに建てようとすると、木が三本ぐらいしか立っていない位置に伐採場を建ててしまいます。これらを制御するには、以下のようにする必要があります。

(defrule
  (building-type-count-total mill < 1)
  (resource-found food)
  (can-build mill)
  =>
  (chat-local-to-self "粉引き所を建てます")
  (build mill)
)

上の例は、木苺を既に発見したときに、粉引き所を作るのに必要な木が十分にあって初めて最初の粉引き所を建てます。そのための条件が (resource-found <resource-type>) です。ちなみに、もし (building-type-count-total mill < 1) がなければ、木苺があって木が余っていると限りなく粉引き所を作ってしまうので注意してください。1度はやってみると笑えて面白いでしょう。

(defrule
  (current-age >= feudal-age)
  (resource-found gold)
  (dropsite-min-distance gold > 5)
  (can-build mining-camp)
  =>
  (build mining-camp)
)

上の例には、新しい条件 (dropsite-min-distance gold > 5) があります。この条件は、村人が資源を獲得してからその資源を格納するための場所が、資源採取場所からどのくらい離れているかを判定するためのものです。この場合は、金が採掘場か町の中心から距離にして 5タイル分以上離れているかどうかを調べています。そして、金が採掘場や町の中心から離れすぎていると採取に時間が掛かってしまうので、そのとき初めて新たな採掘場を建てる、という構文になります。

*

AI はいかなる建築物も自動的には建てません。そしてそれは、畑も同様です。畑を作る方法は、他の建築物を建てるのと同様に行えます。

(build farm)

ただし、畑を作るにはまず最低一個は粉引き所を建てている必要があるので注意してください。

余分な畑を作らないための条件も紹介しておいた方が良いでしょう。

(idle-farm-count == 0)

上の条件は、誰も食料を採取していない畑がゼロかどうかを調べるものです。この条件の下に畑を作成する命令 (build farm) を置くと良いでしょう。
 


 

次の時代へ進化する

資源がたまったら次の時代へと進化したいと思うでしょう。次の時代への進化も、研究の一種なので以下の命令で行うことが出来ます。

(research castle-age)

当然、次の時代へ進化するには時間が掛かります。AOK のうまいプレイ方法を紹介しているサイトの中には、たとえば領主の時代へ進化しようと進化ボタンを押したあとにすぐ戦士訓練場を建てるべきだと言っているところがあります。しかし、現在何かを研究している最中かどうかを判定する方法はありません。

どうしても戦士訓練場をすぐに建てたい場合には、二通りの方法があります。最初の方法は簡単です。戦士訓練場を建てられるだけの木を持っていることを進化の条件にして、進化への研究と同時に戦士訓練場を建てはじめることです。しかしそうすると、万が一木が集まっていない場合は進化が遅れてしまいます。それに、進化中にいくつも建物を建てたりユニットを作ったりすると、そのために必要な資源まで進化前に集めなければなりません。二番目の方法は、フラグを使うことです。フラグについては後述したいと思います。

1番目の方法を使うには、以下の条件も知っておいたほうがよいでしょう。

(can-research feudal-age)

これは領主の時代へ進化できるかどうかの条件です。
 

市場での取り引き

ここでは市場で資源を取引する方法を説明します。

資源を売るための命令は以下の通りです。

(sell-commodity wood)
(sell-commodity food)
(sell-commodity stone)

この命令を実行するたびに、資源が 100売られ、相場に応じた金が手に入ります。当然、売る資源を所持している必要があります。

資源を買うための命令は以下の通りです。

(buy-commodity wood)
(buy-commodity food)
(buy-commodity stone)

この命令を実行するたびに、金を 100使うことで、相場に応じた資源が手に入ります。当然、そのための金を持っている必要があります。

実用的な例としては、やはり余った木や食料を売って金に変えることでしょうか。木が余っているかどうかを調べて、余っていたら売る、ということをやるには以下のようにします。

(defrule
  (wood-amount > 1000)
  =>
  (sell-commodity wood)
)

市場での売買を制御するための命令もあります。

(set-strategic-number sn-minimum-amount-for-trading 50)

上の命令は、売買を行うのに最低限必要な資源量を指定するものと思われます(未実験)。
 

さぼる村人

村人の数が増えてくると、何もしない村人が増えてくる事があります。私は最初、これが AI の限界だと思っていました。しかし、それには全て理由があることが分かりました。その理由を一言で言うと、作業する場所に行けないか、作業する場所がふさがっているか、作業する条件が整っていないか、そのいずれかが複合しています。

1. AI が認識する資源

まず第一に考えなければいけないのは、AI が資源を認識しているか、ということです。どの資源を認識させるかどうかを決める命令は以下の通りです。

(set-strategic-number sn-maximum-wood-drop-distance 10)
(set-strategic-number sn-maximum-food-drop-distance -1)
(set-strategic-number sn-maximum-hunt-drop-distance 5)
(set-strategic-number sn-maximum-fish-boat-drop-distance 15)
(set-strategic-number sn-maximum-gold-drop-distance 20)
(set-strategic-number sn-maximum-stone-drop-distance 30)

これらの命令は、AI がどれだけ離れた資源までを認識するかどうかを決めるものです。距離の基点となるのは、木なら全ての伐採所か町の中心から、金や石なら全ての採掘所か町の中心から、となります。つまり、

(set-strategic-number sn-maximum-wood-drop-distance 10)

このように命令すると、AI は全ての伐採所と町の中心から 10タイル以内の木は認識しますが、10タイル以上離れた木があったとしても、AI は木がないものと判断します。ですから、当然その木は切られることがありません。ただし、その木の近くに新たに伐採所なり町の中心なりが建てられたら切られる可能性が出てきます。また、10タイル以内というのを 20タイルなり 30タイルなりにすることで範囲内に入ると切られる可能性が出てきます。

ちなみに、この値に -1 を指定すると、一つでも木や金などの資源を格納できる施設がある場合に、マップ上の全ての木や金などが採取されるようになります。

2. どれだけ離れたところまで

次に、たとえ AI が資源を認識していても、村人にその資源を採取させるための条件が満たされない場合があります。そしてそのような条件は、私たちが資源採取の効率化をするために敢えて設定している条件だったりするのです。以下がそのような条件です。

(set-strategic-number sn-food-dropsite-distance 5)
(set-strategic-number sn-wood-dropsite-distance 5)
(set-strategic-number sn-stone-dropsite-distance 5)
(set-strategic-number sn-gold-dropsite-distance 5)

上の命令はどれも、ある資源を村人が採取する際に、採取所から 5タイル以内の資源しか取らないようにする命令です。これらの命令は、村人が少ない時には有効に働きます。しかし、村人が多くなってくると、逆に資源採取の妨げになってしまいます。

その理由は、どうやら一箇所の資源で一度に採取に従事できる村人の数は制限されるからのようです。5タイル以内で採取できる資源が二箇所以上あれば問題ないのですが、一箇所だけだとどうしてもその資源を採取できる村人の数が制限されてしまい、その結果十分に村人が資源採取に参加できずに詰まってしまうようです。

うまく二箇所以上採取場所を作れると良いと思いますが、ちょっと工夫がいると思います。

3. 作業する条件が整っているか

畑を作って耕す場合、まず畑を作る必要があります。通常、畑を作り過ぎないように、(idle-farm-count <= 1) などの条件をつけて畑を作っていることが多いと思います。この条件を付け加えないと、村人が手を付けない畑が大量に出来てしまうからです。

しかし、この条件がまた、畑を同時に一つしか作れないという制限を作ってしまうようです。建設中の畑もまた idle-farm-count として計算されてしまうのだと思います。この制限を無くすには、時代の進化と共に、ほったらかしの畑が多く生まれることを許容してやるほかないと思います。たとえば帝王の時代に入ったら以下のようにしたらどうでしょうか。

(defrule
  (can-build farm)
  (idle-farm-count <= 4)
  =>
  (build farm)
)

無駄な畑が出来ても、畑待ちの村人が出来るより良いと思います。

4. retask に関する仮説

これまでの私の AI 観察の結果、ひょっとすると村人は、一度生産されてたときから、何をするかを決められてしまっているのではないかと思います。つまり、一度生産された時点で、村人の作業配分により、この村人は食料専門だとか、木の伐採専門だとかいうことです。そして、いったん決まった役割は、たとえ sn-food-gatherer-percentage の値をあとで変更しようと変わらないのではないかと私は推測しています。

では、なぜ木の伐採専門の人があるときは食料の採取をしにいったりするのでしょうか。それを制御するのが以下の命令だと思います。

(set-strategic-number sn-retask-gather-amount 20)
(set-strategic-number sn-max-retask-gather-amount 40)

これらの値は、各種資源採取の専門家である村人が、異なる資源の採取にまわったりする場合の許容数を決めているのではないかと思います。ちなみに上の 20 と 40 はデフォルト値(初期値)です。ですから、20人以上 40人以下の村人が、自分の専門とは異なる資源の採取に参加できるようになっているわけです。

ゲームが進むと、専門だろうが何だろうが訳がわからなくなってくるのだと思います。本当なら木の専門家のはずが、ずっと畑を耕していたり、金や石の採掘にまわされて、ちょうど現在地が金や石の近くだったりして、その金や石を取り尽くすまでは他の資源採取に行けないのではないでしょうか。ですから、人口制限75 のゲームではさぼらなかった村人が、人口制限125 とかだと 10人ぐらいさぼってしまったりするのも説明がつきます。これを避けるには、他のパラメータを綿密にいじるのが正しい AI の書き方、いえ少なくとも AI システムの製作者の意図だと思います。

しかし私たちには当然もっと簡単な解決策が用意されています。それは、単純に上の値を変えることです。

(set-strategic-number sn-retask-gather-amount 20)
(set-strategic-number sn-max-retask-gather-amount 999)

こうすることで、少なくともさぼる町の人はいなくなるのではないかと思いますが…。以上は仮説です。これから調査します。

 


 
(gomi@din.or.jp)