Playing the bot yourself #
./scripts/build.sh # once, and again after any bridge change
./sds.sh play
That opens MegaMek — the real one, its own Swing client — with you in one seat
and sds-bot in the other. Close the window to end the match.
What it is #
One container, three processes:
SdsHost, running a real MegaMekServerwith the bot seats attachedsds-bot, a child process of that JVM, on the other side- MegaMek's own client, drawing on your X server
Everything talks over 127.0.0.1 inside the container. Nothing is
published, so two of these cannot collide with each other or with a benchmark,
and the only thing that leaves the container is the display.
Picking a scenario and a side #
./sds.sh play --scenario scenarios/suite/4v4-jihad-s102040.mms
./sds.sh play --side South
--scenario takes any .mms with exactly two factions;
scenarios/suite/2v2-jihad-s102020.mms is the default. --side takes a
faction name from that file's Factions= line, and defaults to the first one.
The command prints which seat is which before it starts anything:
bot : /work/target/release/sds-bot
scenario : .../scenarios/suite/2v2-jihad-s102020.mms
you : human North
opponent : sds South
human North is also the name to look for in MegaMek's own report and in the
unit tooltips, and the name the client connects under.
--bot puts something else on the other side — the floor bot is
--bot "python3 /work/bots/random_bot.py" — and the first line always says
which one is actually playing.
What you get afterwards #
The same files a benchmarked match leaves, in the same place:
runs/<timestamp>-play/
<tag>.json the result document
<tag>.report.html MegaMek's round report: rolls, hits, criticals
<tag>-sds_South.decisions.jsonl every candidate the bot scored
<tag>-sds_South.weights.json the weights it scored them with
<tag>.logs/ MegaMek's own scratch for this match
So the two readers work on a game you played exactly as they work on a benchmarked one:
./sds.sh explain runs/<the run> --phase FIRING
./sds.sh view runs/<the run>
That is the point of playing. A win rate cannot tell you why the bot walked into the open; the decision log can, and now you can provoke the situation yourself instead of waiting for it to turn up in a batch.
There is no lounge #
A scenario-hosted game does not have one. ScenarioLoader hands the server a
game that opens on Initiative Phase for Start of Game Deployment, so the
window appears with the board already drawn and your first deployment turn
waiting. Nothing readies you and nothing is synthesised on your behalf: the
server simply holds your turn until your client is there to take it, however
long MegaMek spent loading its unit cache. The terminal says server is up
when the client is being started.
The cost of no lounge is that the scenario's own force list, skills and camo
are what you get; there is no screen on which to change them. Edit the .mms
if you want different ones.
Timeouts #
Every watchdog is off on this path. --max-rounds, --stall-seconds and the
wall clock exist because two bots that stop making progress must not hang a
hundred-game batch, and all three are tuned for players that answer in
milliseconds. A person deciding a movement phase would trip them. --play-max-rounds N
puts a round limit back if you want one.
The bot's own per-decision budget is unchanged, because it is a budget on the bot and not on the match: it never waits for you.
X11, and the one-time setup #
./sds.sh play --check-display
runs xdpyinfo in the match image and says whether it can draw on your
display. If that works, play works.
The mechanism is the X11 socket bind-mounted in, DISPLAY passed through, and
your session's X authority cookie mounted read-only at /tmp/.sds-xauth. On
this machine — a Wayland session with XWayland — that cookie is the file
XAUTHORITY points at, and no further setup is needed.
Nothing here will run xhost for you. If --check-display fails it prints the
command that would grant access, and running it is yours to decide, because it
changes your whole session's X permissions and not just this container's.
MegaMek's client settings — window sizes, the game options panel — are kept in
~/.cache/sds-play/mmconf, seeded from the install's mmconf/ the first time
and left alone afterwards. The MegaMek install itself is not written to, so a
game here does not change what a benchmark or a sibling repo sees.
Container names #
A play container is named sdsplay-<tag>, deliberately not sds-*.
sds clean kills every sds-* container on the machine whoever started it; a
benchmark losing that race costs a rerun, and a person losing it costs the
game. Your own play still kills its container when it exits.