Alle Formatseiten ↓
Einheiten, Skripte, Konfiguration

KI – Profile für Computergegner

Aus coreprime/kbot @ 0ab97bf · Auf GitHub bearbeiten

Die Dateien in ai/*.txt sind 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üssel aiprofile= 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 // note schadet 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: Das Limit CORFORT O (ein Buchstabe O) in krogoth.txt der Verkaufsversion verbietet CORFORT, und Limit ARM DECOM 4 begrenzt 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.txt der Verkaufsversion beginnt mit zwei solchen Zeilen (weight cormakr 0.2, weight armmakr 0.2). KI-Dateien von TA: Kingdoms verwenden plan ü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 UnitName einer 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ätere Weight-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 Feld Category= 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 0 oder jedes negative Limit außer -1 verbietet der KI, das Ziel zu bauen. -1 hebt 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/*.fbi der Installation (Name und Category=) 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 (O wird 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 .1 oder 0.10, nicht.
  • At game start (Studio; kbot mount gibt 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

Siehe auch

  • TDF – die Karten-Metadaten der .ota, die ein KI-Profil auswählen.
  • Glossar – side, category.