mischief: the town gets a say before the monster lands

M2 — the window between a contract being placed and the monster finding its
target. Anyone can ward the victim (!mischief bless, €25, three max, +10% MaxHP
of temp HP each) or pay the tier delta to send something worse (!mischief
escalate, one step, boss is the ceiling). TwinBee DMs the victim on placement so
they can go and ask for wards.

Escalation money joins the payout basis, so piling on raises the purse the target
walks away with if they live — and an escalator is unsealed on a survival exactly
like the buyer. Cruelty and generosity are the same button.

Both commands are CAS-then-refund: the ward cap and the one-step limit live in
the UPDATE's WHERE clause, because a scramble is precisely when four people press
the button in the same second.

Also fixes a real bug this exposed: the delivery built its fight from the copy of
the contract the due-sweep handed it, but the window keeps writing to an open row
right up to the claim. A last-second escalation was paid for and then delivered
the old tier's monster. The claim is the fence; read on that side of it.
This commit is contained in:
prosolis
2026-07-13 21:00:34 -07:00
parent f7ddbf8858
commit c368257896
4 changed files with 674 additions and 13 deletions

View File

@@ -448,6 +448,10 @@ func runMigrations(d *sql.DB) error {
// leader's own level — his party fled 5 runs out of 640 where the human
// party fled 56.
`ALTER TABLE expedition_party ADD COLUMN companion_hp INTEGER NOT NULL DEFAULT -1`,
// Mischief M2 — whoever paid to bump a contract up a tier. Named alongside
// the buyer when the target survives (the unseal), so piling on carries the
// same exposure the original purchase does.
`ALTER TABLE mischief_contracts ADD COLUMN escalated_by TEXT`,
}
for _, stmt := range columnMigrations {
if _, err := d.Exec(stmt); err != nil {
@@ -1754,6 +1758,7 @@ CREATE TABLE IF NOT EXISTS mischief_contracts (
status TEXT NOT NULL,
signed INTEGER NOT NULL DEFAULT 0,
escalation_count INTEGER NOT NULL DEFAULT 0,
escalated_by TEXT,
blessing_count INTEGER NOT NULL DEFAULT 0,
source TEXT NOT NULL DEFAULT 'matrix',
outcome TEXT,