KI – Profile für Computergegner
Die Dateien in
ai/*.txtsind Profile für Computergegner im Klartext. Jedes Profil legt pro Schwierigkeitsgrad Bauprioritäten und Einheitenobergrenzen fest; die Engine liest sie, wenn für eine Karte ein KI-Gegner eingerichtet wird. Der Schlüsselaiprofile=in der OTA wählt, mit welchem Profil eine Karte startet, aber der Spieler kann das in der Lobby überschreiben.
Tip
Probier es selbst.
# Plain-text — just read them
ls $(kbot ctx path)/ai/
head -40 $(kbot ctx path)/ai/default.txt
In kbot. Der Asset-Explorer des Studios zeigt ein Profil auf seinem
Tab AI Profile, und kbot mount gibt es mit describe ai/<name>.txt
aus (siehe Was kbot zeigt).
Aus Go heraus. Verwende formats/ai aus kbot-io:
import "github.com/coreprime/kbot-io/formats/ai"
raw, _ := os.ReadFile("ai/default.txt")
profile, _ := ai.Parse(raw)
// profile.Preamble: lines before the first plan; profile.Plans: plan.Name,
// plan.Weights, plan.Limits; profile.Diagnostics: lines read unusually.
settings := ai.NewResolver(units).Apply(profile, ai.Easy) // per-unit result
Auf einen Blick
Ein Profil ist eine Folge von Plänen, einer pro Schwierigkeitsgrad.
Jeder Plan enthält Direktiven Weight und Limit, deren Ziel ein
einzelner Einheitenname (ARMCOM), ein Kategoriewort (PLANT, LEVEL3,
SPECIAL) oder ALL ist.
plan easy
Weight ARM 0.2
Weight CORE 0.2
Weight PLANT 2
Weight CONSTR 3
Weight ARMACK 2
Weight CORACK 2
Limit ARMSILO 1
Limit CORSILO 1
plan medium
Weight ARM 1.0
Weight CORE 1.0
...
Direktiven
| Direktive | Syntax | Bedeutung |
|---|---|---|
plan <word>… |
plan easy |
Beginnt einen neuen Planblock. Die folgenden Weight-/Limit-Zeilen gelten bis zum nächsten plan nur dann, wenn der Plan zum Schwierigkeitsgrad des Spiels passt. |
Weight <target> <value> |
Weight ARMCK 0.5 |
Multipliziert die Baupriorität des Ziels (siehe wie Gewichte zusammenwirken). |
Limit <target> <value> |
Limit ARMSILO 1 |
Begrenzt, wie viele Einheiten des Ziels ein Computergegner besitzt: -1 heißt unbegrenzt, 0 oder jeder andere negative Wert verbietet es. |
Wie TA 3.1c den Text liest (formats/ai
aus kbot-io folgt dem):
- Eine Zeile wird an beliebigem Leerraum in Wörter zerlegt –
Leerzeichen, Tabs, CR, VT, FF –, und
#beendet die Zeile, wo immer es steht, sogar mitten in einem Wort. - Das erste Wort ist die Direktive, verglichen ohne Rücksicht auf
Groß- und Kleinschreibung. Eine Zeile, deren erstes Wort etwas anderes
ist, wird ignoriert; so werden die
// comment-Zeilen der Verkaufsversion übersprungen. Wörter nach dem Wert werden ebenfalls ignoriert, ein angehängtes// noteschadet also nicht. - Ein Wert ist der numerische Anfang des dritten Worts. Ein Gewicht
ist eine Dezimalzahl (
0.5,.5,2,1e1); ein Limit ist eine Ganzzahl, die auf 32 Bit überläuft. Ein Wertwort, das keine Zahl ist, wird als 0 gelesen, und die Direktive gilt trotzdem: DasLimit CORFORT O(ein Buchstabe O) inkrogoth.txtder Verkaufsversion verbietet CORFORT, undLimit ARM DECOM 4begrenzt die ganze Kategorie ARM auf 0. - Zeilen vor der ersten
plan-Zeile werden beim Spielstart ignoriert, weil noch kein Plan gepasst hat. Sie können greifen, wenn das Profil während eines Spiels neu geladen wird.krogoth.txtder Verkaufsversion beginnt mit zwei solchen Zeilen (weight cormakr 0.2,weight armmakr 0.2). KI-Dateien von TA: Kingdoms verwendenplanüberhaupt nicht – siehe TA: Kingdoms – Profile ohne plan weiter unten.
Schwierigkeitsgrade
Die Originalprofile enthalten drei Pläne namens easy, medium und
hard. Ein Plan gilt bei einem Schwierigkeitsgrad, wenn eines seiner
Wörter (ohne Rücksicht auf Groß- und Kleinschreibung) diesen
Schwierigkeitsgrad nennt – plan medium hard deckt beide ab – oder wenn
sein erstes Wort any ist. Ein Plan, dessen Wörter keinen
Schwierigkeitsgrad nennen (plan brutal, ein nacktes plan), passt auf
nichts: Die Zeilen darunter werden bis zur nächsten plan-Zeile
ignoriert.
Einheitennamen und Kategoriewörter
Weight und Limit können beide Folgendes zum Ziel haben:
- Den
UnitNameeiner Einheit – z. B.ARMCOM,CORRAID(verglichen ohne Rücksicht auf Groß- und Kleinschreibung). Die Direktive gilt nur für diese Einheit und fixiert sie: SpätereWeight-Zeilen (bei einem Gewicht) bzw.Limit-Zeilen (bei einem Limit) ändern sie nicht mehr. - Ein Kategoriewort –
ARM,CORE,PLANT,CONSTR,LEVEL3,SPECIAL, … –, das mit den Wörtern im FeldCategory=jeder Einheit abgeglichen wird. Es gilt für jede passende Einheit, die nicht fixiert ist. ALL– jede Einheit, die nicht fixiert ist.
Jede Einheit beginnt mit 100 % Priorität und ohne Limit. Ein
Gewicht multipliziert den aktuellen Prozentwert, schneidet ihn auf eine
ganze Zahl ab und begrenzt ihn auf 0–100 %; ein Gewicht über 1 kann
also eine zuvor herabgesetzte Einheit wiederherstellen, hebt sie aber nie
über 100 %. Ein Limit ersetzt das aktuelle. Im Plan easy von
default.txt lässt Weight ARM 0.2 jede Arm-Einheit bei 20 %; das
spätere Weight ARMRAD 0.25 bringt den Arm-Radarturm auf 5 % und fixiert
ihn; Weight PLANT 2 holt jede Arm-Fabrik von 20 % auf 40 % zurück.
Important
Kategorie-Aliasse werden mit der Token-Liste Category= der Einheit
abgeglichen, nicht mit irgendeiner Taxonomiedatei. Ein
Kategorie-Alias „existiert“ nur, wenn mindestens eine Einheit ihn
deklariert. Schreib LEVL3, und die Direktive bewirkt stillschweigend
nichts (die Ansichten von kbot kennzeichnen sie mit matches no unit).
Beispiel im Detail – Ausschnitt aus default.txt
// DEFAULT PROFILE
//--------------------------- EASY
plan easy
Weight ARM 0.2 // Every Arm unit to 20%
Weight CORE 0.2
Weight ARMRAD 0.25 // Radar towers to 5%, locked
Weight CORRAD 0.25
Weight ARMMAKR .1 // …metal makers to 2%, locked
Weight CORMAKR .1
Weight PLANT 2 // Factories back up to 40%
Weight CONSTR 3 // Constructors to 60%
// encourages advanced units
Weight ARMACK 2 // Advanced Construction Kbots
Weight CORACK 2
Weight ARMACV 2
Weight CORACV 2
Weight ARMACA 2
Weight CORACA 2
Weight SPECIAL 2
Weight LEVEL3 2
So liest man das: Auf dem Schwierigkeitsgrad easy fällt jede Einheit von
Arm und Core auf 20 % Priorität; Radartürme fallen auf 5 % und
Metallerzeuger auf 2 % (beide danach fixiert); Fabriken (PLANT) und
Baueinheiten (CONSTR) steigen wieder auf 40 % bzw. 60 %, und die
eigenen Zeilen der fortgeschrittenen Baueinheiten verdoppeln deren 60 %
bis zur Obergrenze von 100 % und fixieren sie.
Kartenspezifische Profile
Cavedog liefert eine Handvoll auf bestimmte Karten abgestimmter Profile aus:
| Profil | Verwendet von |
|---|---|
default.txt |
den meisten allgemeinen Karten |
metal.txt |
metallreichen Karten (Metal Heck und Co.) |
airbattle.txt |
Karten mit Schwerpunkt auf Luftkampf |
seabattle.txt |
Karten mit Schwerpunkt auf Seekampf |
hover.txt |
Karten mit vielen Hovercrafts |
acid.txt |
Karten der Säurewelt |
urban.txt |
Stadtkarten |
waterwrld.txt |
Karten der Wasserwelt |
krogoth.txt |
der Bossmission mit dem Krogoth |
missions.txt |
Kampagnenmissionen |
Die .ota der Karte wählt das Profil über aiprofile=, z. B.
aiprofile=metal.
TA: Kingdoms – Profile ohne plan
Note
Dieser Abschnitt beschreibt nur die Abweichungen von TA:K. TAK
verwendet dieselbe Namenskonvention ai/*.txt und dieselbe Syntax der
Direktiven weight/limit, behandelt die Direktive plan aber als
optional.
Jedes KI-Profil der Verkaufsversion von TA: Kingdoms (ai/default.txt,
der Satz ai/mission*.txt der Kampagne) führt weight-/limit-Direktiven
ganz ohne plan-Zeile auf – es gibt nur einen impliziten
Schwierigkeitsgrad pro Datei. Die Struktur ist ein langer Block mit
Gewichten, gefolgt von einem langen Block mit Limits, nach Seiten anhand
des Präfixes im Einheitennamen gruppiert.
Beispiel im Detail – die ersten 30 Zeilen von ai/default.txt
// Kingdoms Default AI Profile 3-28-99
weight araarch 5
weight araat 1
weight arabow 8
weight arabroad 5
weight arabuild 10
weight aracan 4
weight aracastl 10
weight araclay 5
weight aradrag 25 // Dragons: top priority
weight arafast 1
weight arakeep 10
weight araknigh 5
weight aralode 10
weight aramana 5
weight arangate 0 // 0 = never build
weight arapal 8
weight arapries 10
weight arapult 1
weight arasmith 8
weight araspy 4
weight arassh 1
weight arasword 5
weight aratre 1
weight arawall 0
weight arawar 1
Ein Blick auf die Gewichtungen in default.txt zeigt Cavedogs
Prioritäten:
aradrag 25– der Drache von Aramon ist absichtlich übergewichtet; die KI baut Drachen eifriger als alles andere.arabuild 10,aracastl 10,arakeep 10,arapries 10– jeder Wirtschafts- und Baueinheitentyp steht bei Gewicht 10.arawall 0,arangate 0– ausdrücklich null, werden nie gebaut.araat 1,arafast 1,arassh 1– Basiseinheiten, die die KI zugunsten höherstufiger Alternativen zurückstellt.
Dasselbe Muster wiederholt sich weiter unten in der Datei für die
Einheiten tar*, ver* und zon*.
Block mit Limits
Unter dem Block mit den Gewichten folgt ein paralleler Block mit Limits:
limit araarch 16
limit araat 8
limit arabow 16
limit arabroad 16
limit arabuild 10
limit aracan 3
limit aracastl 2 // Only 2 castles per game
limit araclay 3
limit aradrag 1 // ONE dragon, even though weight=25
limit arafast 4
limit arakeep 2
limit araknigh 16
…
Beachte die Asymmetrie: aradrag hat das Gewicht 25 (hohe Priorität),
aber das Limit 1 (nie mehr als einer). So baut die KI von TA:K auf eine
Heldeneinheit hin – das hohe Gewicht sorgt dafür, dass sie früh gebaut
wird, das niedrige Limit hält die Zusammensetzung der Armee vernünftig.
Statistik der Profile
default.txt und die Dateien der Kampagnenmissionen folgen alle
derselben Form:
| Profil | Weight-Zeilen | Limit-Zeilen | Pläne |
|---|---|---|---|
ai/default.txt |
104 | 104 | 0 |
ai/mission06.txt |
104 | 104 | 0 |
ai/mission08.txt (Mission von Iron Plague) |
161 | 162 | 0 |
Die Missionsdateien von Iron Plague haben umfangreichere Tabellen mit
Gewichten und Limits, weil sie Einheiten von Creon (Präfix CRE) abdecken,
die in der default.txt des Grundspiels fehlen.
Wie kbot mit Dateien ohne plan umgeht
ai.Parse aus kbot-io legt jede Zeile vor der ersten plan-Zeile in
AIFile.Preamble ab, was dem entspricht, was TA mit ihnen macht (siehe
oben); bei einem Profil von TA: Kingdoms liest
ai.ParseWith(data, ai.ParseOptions{DefaultPlan: true}) sie in einen
impliziten Plan, der auf jeden Schwierigkeitsgrad passt. Die Ansichten von
kbot zeigen sie auf einem eigenen Tab Before first plan und sagen
beides: TA ignoriert sie beim Spielstart, Profile von TA: Kingdoms, die
keine plan-Zeilen haben, wenden sie auf jedem Schwierigkeitsgrad an. kbot
bildet nicht nach, wie TA: Kingdoms Gewichte über 1 anwendet.
ai.IsAIFile() sieht sich das erste Wort jeder Zeile an: Eine Datei
ist ein Profil, wenn irgendeine Zeile mit einer Direktive in der üblichen
Schreibweise beginnt (einer plan-Zeile, die easy, medium, hard
oder any nennt, oder einer weight-/limit-Zeile, deren Wert mit einer
Zahl beginnt). Das erkennt TAK-Profile, die kein plan haben, und durch
Tabs getrennte Profile, während eine .txt, die „weight“ oder „limit“
bloß im Fließtext erwähnt, nicht für ein Profil gehalten wird.
Stolperfallen
Warning
Das Spiel meldet nichts. Ein falsch geschriebener Einheitenname wird
als Kategorie gelesen, die auf keine Einheit passt, und bewirkt nichts;
ein Wert, der keine Zahl ist, wird als 0 gelesen (ein Limit verbietet
dann das Ziel); Zeilen vor dem ersten plan werden beim Spielstart
ignoriert. Das erste Anzeichen eines kaputten Profils ist meist „die KI
verhält sich seltsam“. Die Ansichten von kbot markieren jeden dieser
Fälle (siehe unten).
Limit 0oder jedes negative Limit außer-1verbietet der KI, das Ziel zu bauen.-1hebt die Obergrenze auf.#beendet eine Zeile an jeder Stelle, sogar mitten in einem Wort; Blockkommentare gibt es nicht.//funktioniert nur, weil eine Zeile, deren erstes Wort keine Direktive ist, ignoriert wird und angehängte Wörter nach dem Wert ebenfalls ignoriert werden.- Ein Gewicht über 1 hebt eine Einheit nie über 100 %. Es kann nur eine Einheit wiederherstellen, die zuvor ein Kategoriegewicht herabgesetzt hat.
- Die erste Zeile, die eine Einheit nennt, fixiert sie. Setze einheitenspezifische Zeilen hinter die Kategoriezeilen, die sie verfeinern sollen.
- Leerraum zwischen Tokens ist nur als Trennzeichen von Bedeutung – Tabs, Leerzeichen und mehrere Leerzeichen funktionieren alle gleich.
- Keine Unterstützung für verschachtelte oder gemeinsam genutzte
Abschnitte. Jeder
plan-Block muss jedes Gewicht und jedes Limit, auf das es ihm ankommt, erneut deklarieren.
Was kbot zeigt
Der Asset-Explorer des Studios (Tab AI Profile) und describe von
kbot mount lesen das Profil so, wie das Spiel es tut:
- Before first plan – die Zeilen der Präambel, gekennzeichnet als beim Spielstart ignoriert.
- Ein Tab pro Plan, auf dem jedes Ziel anhand der
units/*.fbider Installation (Name undCategory=) als unit, category oder all units gekennzeichnet ist. Eine Kategorie, die keine Einheit hat – so wird ein falsch geschriebener Einheitenname gelesen –, ist mit matches no unit markiert. Gewichte werden als Multiplikatoren angezeigt, mit einem Balken für den Prozentwert, der einer Einheit mit 100 % bleibt; Limits als ∞ Unlimited, Disabled (0 oder jeder negative Wert außer -1) oder Max: N. - Zeilen, die das Spiel anders liest – die Diagnosen von kbot-io, etwa
ein Wertwort, das keine Zahl ist (
Owird als 0 gelesen), oder Wörter nach dem Wert. Ein Wertwort, das nicht der Zahl entspricht, die das Spiel liest, wird daneben angezeigt (written "O"); eine andere Schreibweise derselben Zahl, etwa.1oder0.10, nicht. - At game start (Studio;
kbot mountgibt die Anzahlen aus) – für easy, medium und hard jede Einheit, deren Gewicht oder Limit das Profil ändert, mit 🔒 bei Werten, die eine Einheitenzeile fixiert hat.
Typische Größen
| Kennzahl | Beobachteter Bereich in Cavedogs Profilen |
|---|---|
| Dateigröße | 1–4 KB |
| Pläne pro Datei | 3 (easy/medium/hard) |
| Weight-Direktiven pro Plan | 20–80 |
| Limit-Direktiven pro Plan | 0–10 |