id: setup-tree
title: Match setup is one tree, rendered as a lobby and as a scenario file
status: open
repos: [headquarters, arena]
dependsOn: [lobby]
exitCriterion: >
A new kind of match is a new tree, and neither the lobby nor the .mms
writer needs a branch for it. #
setup-tree #
A direction jmm sketched, not a decision. Locking is the right idea, but it
wants to be AST-like rather than a flag per setting: Locked(Choice(x, y, z)),
so that lobby logic is something to iterate on quickly instead of something to
rewrite per feature.
What is behind it: a daily challenge is not a match type. It is a scenario plus
a set of locked lobby settings — the scenario is fixed, both seats are fixed,
chat is gone. Everything distinctive about it is a control a player would
otherwise have, taken away. Duel is the same trick weaker: a Choice over
two-slot scenarios where Scenario has a Choice over the whole catalog.
The shape #
A value that is free, Locked(x), Choice(a, b, c), and Locked(Choice(…))
as the composition — a tutorial that offers force A, B or C and nothing else.
One tree, two renderings. The lobby greys out what is locked and offers what is
a choice; the .mms writer emits whatever the tree resolved to. A scenario
kind — tutorial, co-op, weekly, ladder — is then a tree rather than a code path,
and the fourth one costs a tree rather than a fourth branch in lobbyScreen.
What a V1 file can already lock #
crates/mms reads and writes MMSVersion=1, so this part needs no new format
work. Checked against ScenarioV1.java and MegaMekGUI.java in MegaMek
0.51.0:
SinglePlayer=trueskips both setup dialogs — player assignment and host — and makes every faction after the first a bot.FixedGameOptions=trueskips the Game Options dialog.GameOptionsFile=names the ruleset it would otherwise have asked for.FixedPlanetaryConditions=trueskips the Planetary Conditions dialog.team_<faction>,Location_<faction>andcamo_<faction>fix a faction's team, deployment edge and paint.
The case of those three is a trap, and whatever writes them has to know it.
ScenarioV1.getFactionParam is param + "_" + faction, and the constants are
team and camo lower case but Location capitalised — so Team_X and
Camo_X are read as nothing and dropped in silence. crates/mms already
reports that as a Quirk. Omitting team_ is not neutral either: MegaMek then
gives every faction its own team.
Deployment edges are IStartingPositions.START_LOCATION_NAMES, which carries
CTR alongside the compass points, so a fixed centre deployment is already
expressible.
What V1 cannot express and V2 can #
- A per-player
bot:node — Princess's behaviour. MegaMek ships 14 named presets inmmconf/princessBehaviors.xml(Striker, Scout, Brawler, …), and which bot you are fighting is exactly the sort of thing a tree would want to lock or to offer. - Board files resolved relative to the scenario file, multi-board and
embed,postprocessterrain edits, and hex-area deployment rather than an edge.
So the V2 migration belongs to this epic rather than being a separate format chore: the tree wants nodes V1 has no line for.
arena has to catch up either way. MatchHost.java builds
new Princess(p.getName(), LOCALHOST, a.port) and never consults the scenario,
so a bot: node today is ignored rather than broken. That is a safe order to
do it in, but it means "arena reads the scenario and applies what it says" is
this epic's work too, not a one-off.
What neither can express #
Equipment modes. Nothing in either loader sets one, so stealth armour cannot be
switched on at scenario start — Mek.isStealthActive wants
curMode().equals("On") and hasActiveECM(). A tree offering "stealth on"
would be promising something the file cannot carry, so either arena applies it
after load or the node does not exist.
Still open #
-
`content/overrides.ts` already splits its own list this way, with a `Disclosure` of `"visible" | "silent"` and a `VISIBLE_RULES` set deciding which is which. That is the same distinction arrived at from the other end, and the tree should carry it as a property of a node rather than leaving each renderer to keep its own list of what is worth mentioning.
Open questions #
Related #
lobby is what would be rendered from the tree, and its Duel-is-only-a-filter note is the same observation from the other side. scenarios is the file the writer emits; daily-challenge is the first tree, written by hand.
Done #
-
The lobby's columns follow it live, so moving a seat regroups the screen — which is the whole point for Monte Diablo, whose description reads like an alliance. Changing it drops every readiness in the lobby, which falls out of going through `broadcast_seats` and is the right answer anyway: who is allied with whom is exactly what somebody who already pressed Ready should be asked about again. This is the first node of the tree this epic is about, built as a node rather than as a flag: free in an ordinary lobby, and fixed in a daily, which renders a pill instead of a control because its sides *are* the challenge.