@storylet-studio/runtime 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +22 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +22 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -72,6 +72,9 @@ interface OutcomeView {
|
|
|
72
72
|
gameId: string;
|
|
73
73
|
title?: string;
|
|
74
74
|
purpose?: string;
|
|
75
|
+
/** The outcome's fields, exactly as the bundle carries them: game data
|
|
76
|
+
* declared by the box's `outcomeFields`, never read by the engine. */
|
|
77
|
+
fields?: Record<string, ScalarValue>;
|
|
75
78
|
/** Evaluated against CURRENT state at the moment of the ask. */
|
|
76
79
|
available: boolean;
|
|
77
80
|
}
|
|
@@ -130,7 +133,8 @@ type TraceEvent = {
|
|
|
130
133
|
card: string;
|
|
131
134
|
reason: TraceVerdict | "hand-condition" | "vanished";
|
|
132
135
|
}
|
|
133
|
-
/** Card and outcome gameIds
|
|
136
|
+
/** Card and outcome gameIds; `outcome` is "" for a card with no outcomes,
|
|
137
|
+
* played with none. */
|
|
134
138
|
| {
|
|
135
139
|
type: "play";
|
|
136
140
|
card: string;
|
|
@@ -657,7 +661,16 @@ declare class Flow {
|
|
|
657
661
|
outcomes(cardId: string, from: string): OutcomeView[];
|
|
658
662
|
/** Apply an outcome (schema 3.7): the card must sit in a hand on the
|
|
659
663
|
* board (you never play a card from inside the deck). Throws before any
|
|
660
|
-
* mutation on a gated-shut outcome or a bad write target.
|
|
664
|
+
* mutation on a gated-shut outcome or a bad write target.
|
|
665
|
+
*
|
|
666
|
+
* A card with NO outcomes is played with none, named as "" (the
|
|
667
|
+
* no-outcome-play brief, 2026-09-14): a masthead, a notice, a codex entry,
|
|
668
|
+
* whose play means "shown". It is everything a play is except the writes:
|
|
669
|
+
* the play log and the history functions count it, the box's turn moves by
|
|
670
|
+
* the usual rule, the redraw rests it and it leaves its hand. "" is the one
|
|
671
|
+
* spelling in all four runtimes, because a Blueprint pin cannot be absent.
|
|
672
|
+
* Only the empty-for-empty case is new: "" on a card that has outcomes is
|
|
673
|
+
* refused, and a named outcome on a card with none is refused as before. */
|
|
661
674
|
play(cardId: string, outcomeGameId: string, from: string, opts?: PlayOptions): void;
|
|
662
675
|
/** One owned property's address, owner segment and all (4.4). */
|
|
663
676
|
private address;
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,9 @@ interface OutcomeView {
|
|
|
72
72
|
gameId: string;
|
|
73
73
|
title?: string;
|
|
74
74
|
purpose?: string;
|
|
75
|
+
/** The outcome's fields, exactly as the bundle carries them: game data
|
|
76
|
+
* declared by the box's `outcomeFields`, never read by the engine. */
|
|
77
|
+
fields?: Record<string, ScalarValue>;
|
|
75
78
|
/** Evaluated against CURRENT state at the moment of the ask. */
|
|
76
79
|
available: boolean;
|
|
77
80
|
}
|
|
@@ -130,7 +133,8 @@ type TraceEvent = {
|
|
|
130
133
|
card: string;
|
|
131
134
|
reason: TraceVerdict | "hand-condition" | "vanished";
|
|
132
135
|
}
|
|
133
|
-
/** Card and outcome gameIds
|
|
136
|
+
/** Card and outcome gameIds; `outcome` is "" for a card with no outcomes,
|
|
137
|
+
* played with none. */
|
|
134
138
|
| {
|
|
135
139
|
type: "play";
|
|
136
140
|
card: string;
|
|
@@ -657,7 +661,16 @@ declare class Flow {
|
|
|
657
661
|
outcomes(cardId: string, from: string): OutcomeView[];
|
|
658
662
|
/** Apply an outcome (schema 3.7): the card must sit in a hand on the
|
|
659
663
|
* board (you never play a card from inside the deck). Throws before any
|
|
660
|
-
* mutation on a gated-shut outcome or a bad write target.
|
|
664
|
+
* mutation on a gated-shut outcome or a bad write target.
|
|
665
|
+
*
|
|
666
|
+
* A card with NO outcomes is played with none, named as "" (the
|
|
667
|
+
* no-outcome-play brief, 2026-09-14): a masthead, a notice, a codex entry,
|
|
668
|
+
* whose play means "shown". It is everything a play is except the writes:
|
|
669
|
+
* the play log and the history functions count it, the box's turn moves by
|
|
670
|
+
* the usual rule, the redraw rests it and it leaves its hand. "" is the one
|
|
671
|
+
* spelling in all four runtimes, because a Blueprint pin cannot be absent.
|
|
672
|
+
* Only the empty-for-empty case is new: "" on a card that has outcomes is
|
|
673
|
+
* refused, and a named outcome on a card with none is refused as before. */
|
|
661
674
|
play(cardId: string, outcomeGameId: string, from: string, opts?: PlayOptions): void;
|
|
662
675
|
/** One owned property's address, owner segment and all (4.4). */
|
|
663
676
|
private address;
|
package/dist/index.js
CHANGED
|
@@ -2054,33 +2054,48 @@ var Flow = class {
|
|
|
2054
2054
|
gameId: effectiveGameId(o),
|
|
2055
2055
|
...o.title !== void 0 ? { title: o.title } : {},
|
|
2056
2056
|
...o.purpose !== void 0 ? { purpose: o.purpose } : {},
|
|
2057
|
+
...o.fields !== void 0 ? { fields: o.fields } : {},
|
|
2057
2058
|
available: this.passes(o.condition, ctx)
|
|
2058
2059
|
}));
|
|
2059
2060
|
}
|
|
2060
2061
|
/** Apply an outcome (schema 3.7): the card must sit in a hand on the
|
|
2061
2062
|
* board (you never play a card from inside the deck). Throws before any
|
|
2062
|
-
* mutation on a gated-shut outcome or a bad write target.
|
|
2063
|
+
* mutation on a gated-shut outcome or a bad write target.
|
|
2064
|
+
*
|
|
2065
|
+
* A card with NO outcomes is played with none, named as "" (the
|
|
2066
|
+
* no-outcome-play brief, 2026-09-14): a masthead, a notice, a codex entry,
|
|
2067
|
+
* whose play means "shown". It is everything a play is except the writes:
|
|
2068
|
+
* the play log and the history functions count it, the box's turn moves by
|
|
2069
|
+
* the usual rule, the redraw rests it and it leaves its hand. "" is the one
|
|
2070
|
+
* spelling in all four runtimes, because a Blueprint pin cannot be absent.
|
|
2071
|
+
* Only the empty-for-empty case is new: "" on a card that has outcomes is
|
|
2072
|
+
* refused, and a named outcome on a card with none is refused as before. */
|
|
2063
2073
|
play(cardId, outcomeGameId, from, opts = {}) {
|
|
2064
2074
|
this.assertOpen();
|
|
2065
2075
|
const { entry, ask } = this.resolveDealt(cardId, from);
|
|
2066
|
-
const
|
|
2067
|
-
if (
|
|
2076
|
+
const bare = outcomeGameId === "";
|
|
2077
|
+
if (bare && entry.card.outcomes.length > 0) {
|
|
2078
|
+
throw new Error(`card "${effectiveGameId(entry.card)}" has outcomes (${entry.card.outcomes.map((o) => effectiveGameId(o)).join(", ")}); name the one played`);
|
|
2079
|
+
}
|
|
2080
|
+
const outcome = bare ? void 0 : entry.card.outcomes.find((o) => effectiveGameId(o) === outcomeGameId);
|
|
2081
|
+
if (!bare && !outcome) throw new Error(`card "${effectiveGameId(entry.card)}" has no outcome "${outcomeGameId}"`);
|
|
2068
2082
|
const handEnv = this.buildHandEnv(ask);
|
|
2069
2083
|
const ctx = this.evalCtx(entry.box, entry.deck, handEnv);
|
|
2070
|
-
if (!this.passes(outcome.condition, ctx)) {
|
|
2084
|
+
if (outcome && !this.passes(outcome.condition, ctx)) {
|
|
2071
2085
|
throw new Error(`outcome "${outcomeGameId}" on "${effectiveGameId(entry.card)}" is gated shut`);
|
|
2072
2086
|
}
|
|
2073
2087
|
const perPlay = entry.box.turn !== void 0 ? 0 : this.internals.bundle.settings.playAdvancesTurns;
|
|
2074
2088
|
const newTurn = (this.turnCounts.get(entry.box.id) ?? 0) + (opts.advanceTurns ?? perPlay);
|
|
2075
2089
|
const writes = [];
|
|
2076
|
-
for (const [target, expr] of Object.entries(outcome
|
|
2090
|
+
for (const [target, expr] of Object.entries(outcome?.changes ?? {})) {
|
|
2077
2091
|
writes.push({ target, value: this.eval(expr, ctx) });
|
|
2078
2092
|
}
|
|
2079
2093
|
for (const { target, value } of writes) {
|
|
2080
2094
|
const { path, prev } = this.applyWrite(target, value, entry, handEnv);
|
|
2081
2095
|
if (this.tracing) this.emit({ type: "write", target, path, value, ...prev !== void 0 ? { prev } : {} }, newTurn);
|
|
2082
2096
|
}
|
|
2083
|
-
const
|
|
2097
|
+
const outcomeId = outcome ? effectiveGameId(outcome) : "";
|
|
2098
|
+
const record = { card: effectiveGameId(entry.card), outcome: outcomeId, turn: newTurn };
|
|
2084
2099
|
this.playLog.push(record);
|
|
2085
2100
|
this.indexPlay(record);
|
|
2086
2101
|
if (entry.card.redraw === "never") {
|
|
@@ -2095,7 +2110,7 @@ var Flow = class {
|
|
|
2095
2110
|
(this.boardContents.get(handId) ?? []).filter((id) => id !== entry.card.id)
|
|
2096
2111
|
);
|
|
2097
2112
|
this.turnCounts.set(entry.box.id, newTurn);
|
|
2098
|
-
if (this.tracing) this.emit({ type: "play", card: effectiveGameId(entry.card), outcome:
|
|
2113
|
+
if (this.tracing) this.emit({ type: "play", card: effectiveGameId(entry.card), outcome: outcomeId, turn: newTurn }, newTurn);
|
|
2099
2114
|
}
|
|
2100
2115
|
/** One owned property's address, owner segment and all (4.4). */
|
|
2101
2116
|
address(kind, id) {
|