landlord-ts 1.0.4 → 2.0.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/README.md +45 -2
- package/data/all_cards.json.gz +0 -0
- package/dist/chunk-W62VFBCF.js +1895 -0
- package/dist/index.cjs +1644 -201
- package/dist/index.d.cts +340 -47
- package/dist/index.d.ts +340 -47
- package/dist/index.js +469 -107
- package/dist/simulation-worker.cjs +51 -2
- package/dist/simulation-worker.js +1 -1
- package/package.json +10 -4
- package/dist/chunk-I6ETCO5F.js +0 -803
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# landlord-ts
|
|
2
2
|
|
|
3
|
-
Pure TypeScript Monte Carlo simulator for Magic: The Gathering on-curve probabilities.
|
|
3
|
+
Pure TypeScript Monte Carlo simulator for Magic: The Gathering on-curve probabilities, plus exact hypergeometric draw odds. Started as a port of the Rust [landlord](https://github.com/mtgoncurve/landlord) engine used by [mtgoncurve.com](https://mtgoncurve.com); since 2.0.0 it sequences land drops optimally and models how each land enters and what mana it makes (see [Land sequencing](#land-sequencing)).
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
6
|
|
|
@@ -29,6 +29,7 @@ const input = {
|
|
|
29
29
|
mulliganDownTo: 5,
|
|
30
30
|
mulliganOnLands: [0, 1, 6, 7],
|
|
31
31
|
acceptableHandList: [],
|
|
32
|
+
landSequencing: 'optimal' as const, // default; 'draw-order' reruns the v1.x land model
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
const output = run(input);
|
|
@@ -53,7 +54,9 @@ for (const row of output.cards) {
|
|
|
53
54
|
pCastOnCurve: row.pCastOnCurve,
|
|
54
55
|
pManaGivenCmc: row.pManaGivenCmc,
|
|
55
56
|
notEnoughLands: row.notEnoughLands,
|
|
56
|
-
colorOrTimingFail: row.colorOrTimingFail,
|
|
57
|
+
colorOrTimingFail: row.colorOrTimingFail, // = colorFail + timingFail
|
|
58
|
+
colorFail: row.colorFail, // enough lands, wrong colors
|
|
59
|
+
timingFail: row.timingFail, // the land was in hand on time but entered tapped
|
|
57
60
|
manaOkUndrawn: row.manaOkUndrawn,
|
|
58
61
|
});
|
|
59
62
|
}
|
|
@@ -64,6 +67,8 @@ for (const land of output.landCounts) {
|
|
|
64
67
|
kind: land.kind,
|
|
65
68
|
copies: land.copies,
|
|
66
69
|
producedMana: land.producedMana,
|
|
70
|
+
manaPerTap: land.manaPerTap, // most mana one tap makes (2 for bounce lands)
|
|
71
|
+
landFace: land.landFace, // set when a spell//land MDFC is played as its land face
|
|
67
72
|
});
|
|
68
73
|
}
|
|
69
74
|
```
|
|
@@ -77,6 +82,44 @@ For the full `RunInput` / `RunOutput` contract, `runAsync` (progress callbacks),
|
|
|
77
82
|
- [landlord-ts API](https://github.com/lggarrison/landlord-ts/blob/develop/wiki/concepts/landlord-ts-api.md)
|
|
78
83
|
- [Streaming progress](https://github.com/lggarrison/landlord-ts/blob/develop/wiki/concepts/streaming-progress.md)
|
|
79
84
|
|
|
85
|
+
## Exact draw odds
|
|
86
|
+
|
|
87
|
+
For quick, simulation-free answers ("how likely am I to have three lands by turn 3?"), the hypergeometric helpers compute exact probabilities from a parsed deck. They count draws only, from a random opening seven with no mulligans; whether a spell is castable still needs `run()`.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { decklist, drawOdds, keepability } from 'landlord-ts';
|
|
91
|
+
|
|
92
|
+
const deck = decklist(code);
|
|
93
|
+
|
|
94
|
+
// Every land by default; pass `groups` to track other cards
|
|
95
|
+
const { groups } = drawOdds({ deck, onThePlay: true, maxTurn: 4 });
|
|
96
|
+
for (const t of groups[0].byTurn) {
|
|
97
|
+
console.log(t.turn, t.seen, t.atLeast1, t.expected);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Opening-hand land counts: keep = 2–5 lands, screw = 0–1, flood = 6–7
|
|
101
|
+
console.log(keepability(deck));
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`landDistributionOpeningHand`, `cardsSeenByTurn` and the `hyperPMF` / `hyperAtLeast` / `hyperAtMost` / `hyperMean` core are exported too. See [Hypergeometric draw odds](https://github.com/lggarrison/landlord-ts/blob/develop/wiki/entities/hypergeometric.md).
|
|
105
|
+
|
|
106
|
+
## Land sequencing
|
|
107
|
+
|
|
108
|
+
By default (`landSequencing: 'optimal'`), each spell is checked against the best legal land drops by its target turn: one land per turn, each land only once drawn. Enters-tapped rules are applied to that sequence, and lands whose mana depends on other permanents (Verges, filter lands, bounce lands, fetches) are modeled. Pass `landSequencing: 'draw-order'` to rerun the landlord-ts v1.x land model, which played lands in the order they were drawn. Its mana-miss totals match v1.x (except where card data changed), but its buckets split like `optimal`'s: a land in hand on time that entered tapped is a timing miss, not "not enough lands". Before/after numbers are in the [land sequencing benchmark](https://github.com/lggarrison/landlord-ts/blob/develop/wiki/concepts/land-sequencing-benchmark.md).
|
|
109
|
+
|
|
110
|
+
**Divergence from Rust landlord.** The Rust engine counts every land in hand by the target turn as available, with no enters-tapped gating. landlord-ts gates every land by its enters-tapped rule and sequences land drops optimally, so its numbers differ for decks with tapped or conditional lands. `draw-order` is the v1.x TypeScript behavior, not the Rust behavior. For decks of basics and untapped lands the two agree, and the Karsten tables match.
|
|
111
|
+
|
|
112
|
+
## Upgrading from 1.x
|
|
113
|
+
|
|
114
|
+
2.0.0 changes no function signatures, and every new input is optional. It is a major release because the numbers change:
|
|
115
|
+
|
|
116
|
+
- **Rates move.** `pCastOnCurve`, `pManaGivenCmc` and the failure buckets change for decks with tapped or conditional lands (fast, slow, check, battle, reveal, Verge, filter, bounce, pathway, fetch) and for lands the card data had wrong. Decks of basics and always-untapped lands are unchanged.
|
|
117
|
+
- **Buckets moved.** A land that was in hand on time but entered tapped is now a color / timing miss (`timingFail`), not `notEnoughLands`.
|
|
118
|
+
- **Land kinds changed.** Six new `CardKind` values (`ReverseSlowLand`, `RevealLand`, `BasicCheckLand`, `CountedTypeLand`, `TappedFetchLand`, `PlayOrderLand`); 119 lands change kind and 299 change colors in the shipped data. Spell//land MDFCs report their land face's kind instead of `ForcedLand`; use `landFace` to spot them. If you switch on `kind`, handle the new values.
|
|
119
|
+
- **Card data refreshed** from the 2026-10-16 Scryfall bulk (35 new cards).
|
|
120
|
+
|
|
121
|
+
To compare against 1.x, pass `landSequencing: 'draw-order'`. The full list is in [CHANGELOG.md](./CHANGELOG.md).
|
|
122
|
+
|
|
80
123
|
## Development
|
|
81
124
|
|
|
82
125
|
```bash
|
package/data/all_cards.json.gz
CHANGED
|
Binary file
|