Bots trainieren
Kobaltmeer enthält eine Lernumgebung und einen trainierbaren NeuroBot. Er braucht nur NumPy und die vorhandene Engine, keine weiteren KI-Pakete und keinen externen Dienst.
Was lernt der NeuroBot?
Der NeuroBot hat 118 Gewichte. Für jede mögliche Schiffsaktion bewertet ein kleines Netz 14 Merkmale, darunter Abbauertrag, Fracht, Fortschritt zum Ziel oder Hafen, Restzeit, Treibstoff, Gegnernähe und Relaisbau. Weitere acht Gewichte entscheiden über den Schiffbau. Die Gewichte stehen in einer lesbaren JSON-Datei.
Zielauswahl, Merkmalsberechnung und die kollisionsfreie Flottenkoordination sind fest programmiert. Das Netz lernt, Möglichkeiten zu bewerten, nicht die ganze Navigation.
Trainiert wird mit der Cross-Entropy-Methode: Kandidaten aus einer Gewichtsverteilung ziehen, in echten Partien spielen lassen, die besten auswählen und die Verteilung in ihre Richtung verschieben. Gestartet wird mit sinnvollen, von Hand gesetzten Gewichten.
Einen Lauf starten
./start.sh train --out models/mein-lauf --generations 12 --population 16
Dieser Lauf dauert auf einem üblichen Rechner etwa eine Minute. Standard: Karte 16, zwei Flotten,
160 Runden, Profil Kobaltmeer, Gegner collector, beide Startplätze. Die Karten sind strikt getrennt:
| Zweck | Seeds (Standard) | Verwendung |
|---|---|---|
| Training | 11, 22 | Bestimmen die neuen Gewichte |
| Validierung | 101, 202 | Wählen das beste Modell („Champion“) aus |
| Abschlusstest | 1001, 2002, 3003 | Erst ganz am Ende, unabhängig von der Auswahl |
Nach jeder Generation erscheint eine Zeile wie
Generation 8 · Training -0.102 · Validierung -0.443 · Modell g1 · Gewichtsänderung 4.638.
Training und Validierung sind die mittlere Fitness (siehe Reward
und Fitness) auf den Trainings- bzw. Validierungskarten. Sie reicht etwa von −3 bis +3: Werte um +2 bis +3
bedeuten fast immer Sieg, um 0 ausgeglichen, um −2 bis −3 fast immer Niederlage. Modell g1 sagt, aus welcher Generation der aktuelle
Champion stammt, Gewichtsänderung, wie weit er sich vom Ausgangsmodell entfernt hat.
Bleiben die Werte stehen, findet die Evolution gerade nichts Besseres.
Erwarte nicht zu viel: Ein kleiner Lauf schlägt den collector selten. Er zeigt, wie
das Verfahren funktioniert; für einen starken Bot brauchst du größere Läufe, mehr Karten und Geduld,
oder du verbesserst die Merkmale selbst.
Ein größerer Lauf:
./start.sh train --out models/groesserer-lauf --generations 20 --population 24 \
--train-seeds 11 22 33 44 --validation-seeds 101 202 303 --test-seeds 4001 4002 4003 \
--opponents collector courier --size 24 --turns 240 --inspiration
Auch --profile classic und alle Regelschalter sind möglich.
Fortsetzen und testen
Nach jeder Generation werden Modell, Bericht und Checkpoint gespeichert. Bei Strg+C bleibt der letzte vollständige Stand erhalten.
# Weitere acht Generationen
./start.sh train --resume models/mein-lauf/checkpoint.json --generations 8
# Abschlusstest
./start.sh train --resume models/mein-lauf/checkpoint.json --generations 0 --final-test
Der Abschlusstest spielt Ausgangsmodell und Champion auf den bisher unbenutzten Test-Seeds und speichert die Replays. Danach ist der Lauf für weiteres Training versiegelt. Wer weiter experimentiert, beginnt einen neuen Lauf mit neuen Test-Seeds:
./start.sh train --out models/fortsetzung --founder models/mein-lauf/champion.json \
--test-seeds 5001 5002 5003 --generations 12
Reward und Fitness
Lagerdifferenz = eigenes Lager − mittleres Lager der Gegner
Potential = tanh(Lagerdifferenz / (10 × Schiffskosten))
Reward je Zug = neues Potential − altes Potential
Am Spielende + 2 × Ergebnis (+1 Sieg, 0 gleicher Rang, −1 Niederlage)
Bei vier Flotten wird der Rangvergleich gegen jeden Gegner gemittelt. Die Evolution maximiert den mittleren Gesamtreward. Siege zählen dadurch mehr als die Höhe eines Vorsprungs. Ein besserer Score bedeutet deshalb nicht zwingend ein höheres Lager. Die Berichte nennen beides, Fitness und Lager.
Ein auf kleinen Karten trainierter Bot kann auf großen Karten, mit anderen Regeln oder gegen andere Gegner deutlich schlechter spielen. Teste ihn dort, wo er antreten soll.
Dateien eines Laufs
| Datei | Inhalt |
|---|---|
baseline.json |
Das Ausgangsmodell |
champion.json |
Das nach Validierung ausgewählte Modell |
baseline_bot.py, champion_bot.py |
Fertige Python-Bots mit eingebetteten Gewichten |
checkpoint.json |
Kompletter Trainingsstand zum Fortsetzen |
report.json |
Konfiguration und Messwerte je Generation, Validierung und Test |
test-replays/ |
Die Partien des Abschlusstests |
Alle Dateien sind reines JSON bzw. Python-Quelltext, ohne Pickle.
Trainierte Bots einsetzen
./start.sh gui --bots model:models/mein-lauf/champion.json collector --size 16 --turns 160
./start.sh tournament --bots model:models/mein-lauf/champion.json collector courier \
--size 16 --turns 160 --league runs/neuro-liga.json
champion_bot.py funktioniert wie jeder eigene Python-Bot und kann auch in die
Heimnetz-Arena hochgeladen werden. Im Replay zeigt „Ziele & Gründe“ die
Bewertungen des Netzes.
Eigene Lernverfahren
LearningEnv bietet eine Umgebung mit reset() und step() für eigene Verfahren:
from kobaltmeer.engine import Rules, Orders
from kobaltmeer.learning_env import LearningEnv
with LearningEnv(Rules(size=16, players=2, turns=160), ["collector"]) as env:
observation, info = env.reset(seed=42, options={"player": 0})
while not env.finished:
action = Orders() # hier deine Policy
observation, reward, terminated, truncated, info = env.step(action)
Die Beobachtung ist ein Dictionary:
| Feld | Form | Inhalt |
|---|---|---|
map |
(8, Größe, Größe) |
Ressourcen, eigene/fremde Fracht, Schiffe und Häfen, Inspiration |
ships |
(eigene Schiffe, 7) |
Position, Fracht, Feldvorkommen, Hafenabstand, Treibstoff, Inspiration |
ship_ids |
(eigene Schiffe,) |
IDs zur Rückübersetzung in Orders |
action_mask |
(eigene Schiffe, 6) |
Mögliche Aktionen in der Reihenfolge O,N,E,S,W,B |
global |
(6,) |
Restzeit, Lager, Flottengrößen und Relaiszahl |
env.raw liefert zusätzlich die normale SDK-Beobachtung. Die Schnittstelle ähnelt Gymnasium,
ist aber kein gymnasium.Env mit Spaces, weil die Schiffsliste eine variable Länge hat.