Credibility pass: one teleport step, one bell, one step type, and the comments that argued are gone
Since 6e49fc9. Engine: the teleport BFS in the view and the engine's
wallIgnoringDistance share teleportStep; the counter trail is weighed
between steps instead of on six arms; the bush attack takes its
adjacency from SIDES like the wall does; a dead redirected clause, a
one-member set, an identity ternary, and a stray try/catch are gone;
two tests now assert what their names promise. Server: KEEPER and
MAX_SEATS live in rooms.ts, the three Sentry bells ring through one
helper, the unread reply field is dropped, actingSeat comes from the
engine, and the protocol header names every message. Web: ReplayStep
is one type, cardName one helper, the say box and the reference section
one snippet each, the keeper's name arrives from the server rather than
the source, and the lifesaver ruling that ruled nothing is out.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
c4a555f8df
commit
66b5c06f17
@@ -733,7 +733,7 @@ function deliveryWins(view: GameView, p: { id: PlayerId; home: Cell; carriedTrea
|
||||
/** Treasures a wizard has delivered: the scoreboard the table reads. */
|
||||
function bankedBy(view: GameView, p: { id: PlayerId; home: Cell }): number {
|
||||
return view.treasures.filter(
|
||||
(t) => t.owner !== p.id && t.position && !t.carriedBy && cellKey(t.position) === cellKey(p.home)).length;
|
||||
(t) => t.owner !== p.id && t.position && cellKey(t.position) === cellKey(p.home)).length;
|
||||
}
|
||||
|
||||
/** The enemy whose delivery in progress would end the game, if any. */
|
||||
@@ -769,8 +769,8 @@ export function interceptCell(
|
||||
if (theirs == null || toHome == null || mine == null) continue;
|
||||
if (theirs + toHome !== road || mine > theirs) continue;
|
||||
if (!best || mine < best.mine || (mine === best.mine && toHome < best.toHome)) {
|
||||
const [x, y] = k.split(",").map(Number);
|
||||
best = { cell: { x: x!, y: y! }, mine, toHome };
|
||||
const [x, y] = k.split(",").map(Number) as [number, number];
|
||||
best = { cell: { x, y }, mine, toHome };
|
||||
}
|
||||
}
|
||||
return best?.cell ?? carrier.home;
|
||||
@@ -1509,19 +1509,19 @@ export function automatonCommand(
|
||||
// would not have died anyway.
|
||||
const weakest = [...visible].sort((a, b) => a.life - b.life)[0]!;
|
||||
const finisher = bestAttack(view, weakest.id, tier);
|
||||
const thiefInSight = thief && visible.some((p) => p.id === thief.id) ? thief : null;
|
||||
const runner = visible.find((p) => deliveryWins(view, p));
|
||||
const myBank = bankedBy(view, self);
|
||||
const leader = [...visible]
|
||||
.filter((p) => bankedBy(view, p) > myBank)
|
||||
.sort((a, b) => bankedBy(view, b) - bankedBy(view, a) || a.life - b.life)[0];
|
||||
const target = thief && visible.some((p) => p.id === thief.id) ? thief
|
||||
: finisher && finisher.damage >= weakest.life ? weakest
|
||||
: runner ?? leader ?? weakest;
|
||||
const target = thiefInSight
|
||||
?? (finisher && finisher.damage >= weakest.life ? weakest : null)
|
||||
?? runner ?? leader ?? weakest;
|
||||
// DROP OBJECT shakes the treasure out of the hands that matter:
|
||||
// the thief of my gold, or any carrier whose delivery wins.
|
||||
{
|
||||
const mark = (thief && visible.some((p) => p.id === thief.id)) ? thief
|
||||
: visible.find((p) => deliveryWins(view, p));
|
||||
const mark = thiefInSight ?? runner;
|
||||
const dob = mark ? inHand(view, "drop-object") : undefined;
|
||||
if (mark && dob) {
|
||||
return {
|
||||
@@ -1749,8 +1749,7 @@ export function automatonCommand(
|
||||
// BANK GUARD: enemy gold delivered to my home is my scoreboard, and
|
||||
// anyone may snatch it off the floor. A raider nearer my bank than I
|
||||
// am, with the bank stocked, outranks the next grab — run home.
|
||||
const bankedCount = view.treasures.filter(
|
||||
(t) => t.owner !== you && t.position && cellKey(t.position) === cellKey(self.home)).length;
|
||||
const bankedCount = bankedBy(view, self);
|
||||
// The predicate reads only ENEMY positions — my own steps must not
|
||||
// flip it mid-march or the walker shuttles between goals.
|
||||
const bankThreatened = bankedCount > 0 && !self.carriedTreasureId &&
|
||||
|
||||
Reference in New Issue
Block a user