@rpgm-tools/neo-angband-core 0.24.0 → 0.26.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.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/entity-views.d.ts +62 -0
  3. package/dist/agent/entity-views.d.ts.map +1 -0
  4. package/dist/agent/entity-views.js +195 -0
  5. package/dist/agent/entity-views.js.map +1 -0
  6. package/dist/agent/index.d.ts +5 -1
  7. package/dist/agent/index.d.ts.map +1 -1
  8. package/dist/agent/index.js +2 -0
  9. package/dist/agent/index.js.map +1 -1
  10. package/dist/agent/loadout.d.ts +97 -0
  11. package/dist/agent/loadout.d.ts.map +1 -0
  12. package/dist/agent/loadout.js +312 -0
  13. package/dist/agent/loadout.js.map +1 -0
  14. package/dist/agent/perceive.d.ts.map +1 -1
  15. package/dist/agent/perceive.js +16 -162
  16. package/dist/agent/perceive.js.map +1 -1
  17. package/dist/agent/types.d.ts +167 -2
  18. package/dist/agent/types.d.ts.map +1 -1
  19. package/dist/agent/types.js +10 -1
  20. package/dist/agent/types.js.map +1 -1
  21. package/dist/game/context.d.ts +15 -0
  22. package/dist/game/context.d.ts.map +1 -1
  23. package/dist/game/context.js.map +1 -1
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/mod/registry-host.d.ts +97 -0
  29. package/dist/mod/registry-host.d.ts.map +1 -1
  30. package/dist/mod/registry-host.js +7 -0
  31. package/dist/mod/registry-host.js.map +1 -1
  32. package/dist/mod/save-blocks.d.ts +1 -1
  33. package/dist/player/calcs.d.ts +9 -0
  34. package/dist/player/calcs.d.ts.map +1 -1
  35. package/dist/player/calcs.js +13 -1
  36. package/dist/player/calcs.js.map +1 -1
  37. package/dist/player/loadout.d.ts +178 -0
  38. package/dist/player/loadout.d.ts.map +1 -0
  39. package/dist/player/loadout.js +172 -0
  40. package/dist/player/loadout.js.map +1 -0
  41. package/dist/player/spell.d.ts +21 -1
  42. package/dist/player/spell.d.ts.map +1 -1
  43. package/dist/player/spell.js +53 -14
  44. package/dist/player/spell.js.map +1 -1
  45. package/dist/session/game.d.ts +39 -0
  46. package/dist/session/game.d.ts.map +1 -1
  47. package/dist/session/game.js +201 -31
  48. package/dist/session/game.js.map +1 -1
  49. package/dist/version.d.ts +1 -1
  50. package/dist/version.js +1 -1
  51. package/package.json +1 -1
  52. package/src/agent/entity-views.ts +227 -0
  53. package/src/agent/index.ts +9 -0
  54. package/src/agent/loadout.ts +400 -0
  55. package/src/agent/perceive.ts +22 -168
  56. package/src/agent/types.ts +166 -2
  57. package/src/game/context.ts +18 -0
  58. package/src/index.ts +1 -0
  59. package/src/mod/registry-host.ts +108 -0
  60. package/src/player/calcs.ts +22 -1
  61. package/src/player/loadout.ts +331 -0
  62. package/src/player/spell.ts +67 -16
  63. package/src/session/game.ts +287 -35
  64. package/src/version.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/session/game.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/session/game.ts"],"names":[],"mappings":"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"}
@@ -85,7 +85,7 @@ import { displayFeeling, installCaveCommands, movementAutoDig } from "../game/ca
85
85
  import { installSteal } from "../game/steal.js";
86
86
  import { calcUnlockingChance, installChunkFeatHook, installTrap, installTraps, playerIsTrapsafe, squareDoorPower, squareIsPlayerTrap, squareIsWarded, squareIsWebbed, squareRemoveAllTraps, squareSetDoorLock, trapPredicates, } from "../game/trap.js";
87
87
  import { lookupTrap } from "../world/trap.js";
88
- import { calcMana, calcSpells, cumberArmorFrom, playerSpellsInit, registerBookKinds, } from "../player/spell.js";
88
+ import { calcMana, calcSpells, cumberArmorFrom, playerSpellsInit, registerBookKinds, wornArmorWeight, } from "../player/spell.js";
89
89
  import { installSpellCommands, makeSpellChanceEnv } from "../game/spell-cmd.js";
90
90
  import { installRangedCommands } from "../game/ranged-cmd.js";
91
91
  import { markNoscore, NOSCORE } from "../game/wizard.js";
@@ -351,6 +351,20 @@ function wireGame(state, reg, players, pstate, seedFlavor) {
351
351
  state.knownPlayerState = known;
352
352
  state.actor.knownCombat = toCombatState(known);
353
353
  };
354
+ /**
355
+ * The calc_bonuses options bag for the world as it stands, minus the loadout.
356
+ * ONE definition, because a hypothetical derive that reads a different bag
357
+ * from the live one is a derive that quietly answers a different question -
358
+ * the curse traversal in particular is easy to leave out and impossible to
359
+ * notice from the number that comes back.
360
+ */
361
+ const liveBonusOptions = (update) => ({
362
+ timedEffects: players.timed,
363
+ curses: reg.objects.curses,
364
+ update,
365
+ depth: state.chunk.depth,
366
+ isDaytime: isDaytime(state.turn, state.z.dayLength),
367
+ });
354
368
  const refreshDerived = () => {
355
369
  const p = state.actor.player;
356
370
  const equipment = p.equipment.map((h) => h ? gearGet(state.gear, h) : null);
@@ -358,14 +372,7 @@ function wireGame(state, reg, players, pstate, seedFlavor) {
358
372
  /* p->state before the memcpy at the end of calc_bonuses: the encumbrance
359
373
  * notices below diff against it (player-calcs.c:2412-2453). */
360
374
  const before = derived;
361
- const bonusOptions = {
362
- equipment,
363
- timedEffects: players.timed,
364
- curses: reg.objects.curses,
365
- update: true,
366
- depth: state.chunk.depth,
367
- isDaytime: daytime,
368
- };
375
+ const bonusOptions = { ...liveBonusOptions(true), equipment };
369
376
  derived = calcBonuses(p, bonusOptions);
370
377
  state.playerState = derived;
371
378
  refreshKnownCombat(p, bonusOptions);
@@ -410,6 +417,22 @@ function wireGame(state, reg, players, pstate, seedFlavor) {
410
417
  }
411
418
  };
412
419
  state.updateBonuses = refreshDerived;
420
+ /**
421
+ * calc_bonuses for a loadout the player is NOT wearing (update=false, so the
422
+ * derive keeps its hands off p->timed[TMD_FASTCAST] and the town-light redraw),
423
+ * over the same options bag the live refresh uses.
424
+ *
425
+ * This is the one thing a hypothetical derive could not do from outside: the
426
+ * bag carries the bound timed table and the curse registry, and a caller
427
+ * assembling its own would silently drop whichever it did not know about. It is
428
+ * installed here for the same reason updateBonuses is - the session is the only
429
+ * place that has all of it.
430
+ */
431
+ state.derivedFor = (equipment, totalWeight) => calcBonuses(state.actor.player, {
432
+ ...liveBonusOptions(false),
433
+ equipment: equipment.slice(),
434
+ ...(totalWeight === undefined ? {} : { totalWeight }),
435
+ });
413
436
  /**
414
437
  * update_stuff's PU_UPDATE_VIEW arm (player-calcs.c:2608), as the DEFAULT.
415
438
  *
@@ -2309,6 +2332,163 @@ function makeChangeLevel(state, reg, trapDeps, opts = {}) {
2309
2332
  state.chunk.onlyPartial = false;
2310
2333
  };
2311
2334
  }
2335
+ /**
2336
+ * reincarnate_borg (borg/borg-reincarnate.c:408): wipe the live player in place,
2337
+ * roll a new one, and carry on in the SAME session.
2338
+ *
2339
+ * WHAT MAKES THIS DIFFERENT FROM A NEW GAME. Upstream never exits to a menu and
2340
+ * never opens a second savefile. It saves the level off, calls `player_init` and
2341
+ * `player_generate` on the same `struct player *`, restores the level, and returns
2342
+ * to the game loop. Everything a session owns - the turn counter, the RNG stream,
2343
+ * the message log, the option store, the mod manifest, the save slot - is still
2344
+ * the same object afterwards. This does the same thing for the same reason: a host
2345
+ * that reloaded the page or claimed a new slot would be a different program that
2346
+ * happens to end up somewhere similar.
2347
+ *
2348
+ * THE PLAYER OBJECT IS MUTATED, NOT REPLACED, and that is load-bearing rather than
2349
+ * incidental. wireGame's closures captured `state`, and a good number of them
2350
+ * captured `state.actor.player` - the same reason a level change swaps the chunk in
2351
+ * place. Upstream reuses the pointer for the identical reason.
2352
+ *
2353
+ * WHERE THE NEW CHARACTER COMES FROM. `generatePlayer` and `outfitPlayer`, the
2354
+ * same two functions `startGame` births from. Upstream's `borg_roll_hp` and
2355
+ * `borg_outfit_player` are near-copies of `roll_hp` and `player_outfit` that exist
2356
+ * because the borg cannot run the interactive birth UI; this port's birth pipeline
2357
+ * is not interactive, so the real one is reachable and the copies are not needed.
2358
+ * The one upstream detail with no equivalent here is `create_random_name`'s
2359
+ * per-race syllable tables - this port has `playerRandomName`, so a caller passes
2360
+ * `fullName` from that rather than a second name generator landing in core.
2361
+ *
2362
+ * WHAT IT DELIBERATELY DOES NOT DO. Upstream re-seeds `seed_flavor` and, under
2363
+ * `birth_randarts`, `seed_randart`. Both are seeds this port's savefile stores and
2364
+ * re-derives the world from (docs/PARITY.md names them as the two places a stream
2365
+ * change IS a defect), so moving either mid-session would make the save describe a
2366
+ * world the game is not in. The flavour KNOWLEDGE is reset instead, which is the
2367
+ * half a player can observe: the new character does not inherit what the dead one
2368
+ * identified.
2369
+ */
2370
+ function makeReincarnate(state, reg, players, flavor, everseen, changeLevel) {
2371
+ return (opts = {}) => {
2372
+ const rng = state.rng;
2373
+ /* "save the existing dungeon. It is cleared later but needs to be blank when
2374
+ * creating the new player" (borg-reincarnate.c:414-418). Nothing below clears
2375
+ * it here - the wipe is confined to the player and their gear - so the restore
2376
+ * at the end is a no-op in the ordinary case. It is still written both ways,
2377
+ * because the pair is what says the level is not this function's to touch. */
2378
+ const savedChunk = state.chunk;
2379
+ const savedMonsters = state.monsters;
2380
+ const savedGroups = state.groups;
2381
+ const savedFloor = state.floor;
2382
+ const savedTraps = state.traps;
2383
+ const savedKnown = state.known;
2384
+ const savedGrid = state.actor.grid;
2385
+ /* Roll up a new character (borg-reincarnate.c:465-476). A named race or class
2386
+ * that no pack defines falls through to the roll rather than throwing: the
2387
+ * caller is a mod's configuration, and a typo there should cost a reroll. */
2388
+ const race = (opts.raceName ? players.raceByName(opts.raceName) : null) ??
2389
+ players.races[rng.randint0(players.races.length)];
2390
+ const cls = (opts.className ? players.classByName(opts.className) : null) ??
2391
+ players.classes[rng.randint0(players.classes.length)];
2392
+ const body = players.bodies[race.body] ?? players.bodies[0];
2393
+ const birth = generatePlayer(race, cls, { body, historyChart: players.historyChart(race) }, rng);
2394
+ /* player_init(player) then player_generate(player, race, class, false)
2395
+ * (borg-reincarnate.c:435, :476), on the same object. Every own key goes and
2396
+ * the fresh character's keys land, so a field added to Player later is carried
2397
+ * across without this function being edited - the alternative, a field-by-field
2398
+ * copy, is a list that silently stops being complete. */
2399
+ const live = state.actor.player;
2400
+ for (const key of Object.keys(live))
2401
+ delete live[key];
2402
+ Object.assign(live, birth.player);
2403
+ const p = state.actor.player;
2404
+ /* player_quests_reset (player-quest.c:157), as at birth. */
2405
+ playerQuestsReset(p, reg.quests);
2406
+ /* The dead character's belongings do not come forward. Emptied IN PLACE for
2407
+ * the same reason the player object is: `state.gear` is captured. */
2408
+ state.gear.store.clear();
2409
+ state.gear.next = 1;
2410
+ state.gear.pack.length = 0;
2411
+ state.gear.inven = [];
2412
+ state.gear.quiver = [];
2413
+ /* Nor does what they identified. Upstream reaches this through flavor_init's
2414
+ * reshuffle; see the header for why the seed itself is left alone. */
2415
+ flavor.restore({ aware: [], tried: [] });
2416
+ /* borg_outfit_player (borg-reincarnate.c:521) is player_outfit. */
2417
+ const startKinds = [];
2418
+ outfitPlayer(state.gear, p, reg.objects, rng, reg.constants, {
2419
+ opt: (name) => state.options?.get(name) ?? false,
2420
+ onStartKind: (kind) => void startKinds.push(kind),
2421
+ });
2422
+ /* The same three passes over the new kit startGame runs after birth:
2423
+ * kind->everseen (player-birth.c:658), object_flavor_aware (:650) and
2424
+ * obj->known->effect (:650). */
2425
+ for (const obj of state.gear.store.values())
2426
+ everseen.markKind(obj.kind);
2427
+ for (const kind of startKinds) {
2428
+ flavor.objectFlavorAware(kind, NOOP_FLAVOR_AWARE_DEPS);
2429
+ }
2430
+ for (const obj of state.gear.store.values())
2431
+ obj.knownEffect = obj.effect;
2432
+ /* player_spells_init (borg-reincarnate.c:518), then the derived recompute -
2433
+ * PU_BONUS | PU_HP | PU_MANA - which is what turns the rolled hitdice into
2434
+ * mhp and the worn armour into the mana penalty. calcSpells wants the stat
2435
+ * indices that recompute produces, so it follows rather than leads. */
2436
+ playerSpellsInit(p);
2437
+ state.updateBonuses?.();
2438
+ calcSpells(p, state.statInd ?? [], (text) => state.msg?.(text));
2439
+ /* rd_gear's tail / the first update_stuff after player_outfit. The ammo tval
2440
+ * is the NEW class's, so it is read back off the recompute above. */
2441
+ buildGearViews(state, reg, state.playerState?.ammoTval ?? 0);
2442
+ /* player_learn_innate (borg-reincarnate.c:515) and the worn kit's obvious
2443
+ * runes, exactly as startGame does them after the rune env exists. */
2444
+ playerLearnInnate(p, state.runeEnv);
2445
+ for (let i = 0; i < p.body.count; i++) {
2446
+ const worn = state.runeEnv.slotObject(i);
2447
+ if (worn)
2448
+ objectLearnOnWield(p, worn, state.runeEnv);
2449
+ }
2450
+ /* "fully healed and rested" (borg-reincarnate.c:569-571). */
2451
+ p.chp = p.mhp;
2452
+ p.csp = p.msp;
2453
+ /* Mark the savefile (borg-reincarnate.c:587-589). One-way. */
2454
+ if (opts.noscore)
2455
+ p.noscore = markNoscore(p.noscore, opts.noscore);
2456
+ if (opts.fullName !== undefined)
2457
+ p.fullName = opts.fullName;
2458
+ /* The new player is now ready (borg-reincarnate.c:585). Cheating death is
2459
+ * upstream's other branch and not this one, so any suspended fatal blow is
2460
+ * dropped with the character that took it. */
2461
+ state.isDead = false;
2462
+ state.playing = true;
2463
+ state.pendingDeath = undefined;
2464
+ /* Restore the level (borg-reincarnate.c:579-582). */
2465
+ state.chunk = savedChunk;
2466
+ state.monsters = savedMonsters;
2467
+ state.groups = savedGroups;
2468
+ state.floor = savedFloor;
2469
+ state.traps = savedTraps;
2470
+ state.known = savedKnown;
2471
+ state.actor.grid = savedGrid;
2472
+ installChunkFeatHook(state);
2473
+ /* store_reset() and chunk_list_max = 0 (borg-reincarnate.c:534-535): the new
2474
+ * character does not inherit the dead one's shopping, its home stash, or any
2475
+ * frozen level. Dropping `stores` is what makes refreshTownStores rebuild them
2476
+ * from scratch on arrival rather than age the old ones forward. */
2477
+ delete state.stores;
2478
+ state.daycount = 0;
2479
+ state.levelCache?.clear();
2480
+ state.townChunk = null;
2481
+ /* "Start in town" plus generate_level = true (borg-reincarnate.c:483, :524).
2482
+ * Upstream's restored cave survives only until run_game_loop's next pass calls
2483
+ * prepare_next_level at the new depth of 0; changeLevel IS that call, so it is
2484
+ * made here and the flag is left down rather than handed to the host as a
2485
+ * second thing to remember. */
2486
+ changeLevel(0);
2487
+ state.generateLevel = false;
2488
+ delete state.targetDepth;
2489
+ return { raceName: race.name, className: cls.name };
2490
+ };
2491
+ }
2312
2492
  /**
2313
2493
  * Resolve the quest guardians to place on a freshly generated level
2314
2494
  * (generate.c L1170-1191). Returns one QuestSpawn per active quest whose
@@ -2798,6 +2978,10 @@ export function startGame(pack, opts = {}) {
2798
2978
  search(state); /* on_new_level (game-world.c:1052). */
2799
2979
  state.chunk.onlyPartial = false;
2800
2980
  }
2981
+ /* One instance, shared: reincarnate ends by asking for the town, and it must be
2982
+ * the same level changer the host drives so the arena bookkeeping inside it is
2983
+ * not split across two closures with separate `inArena` flags. */
2984
+ const changeLevel = makeChangeLevel(state, reg, wired.trapDeps);
2801
2985
  return {
2802
2986
  state,
2803
2987
  registry: wired.registry,
@@ -2815,7 +2999,8 @@ export function startGame(pack, opts = {}) {
2815
2999
  orphansAcknowledged: false,
2816
3000
  options,
2817
3001
  randartSeed,
2818
- changeLevel: makeChangeLevel(state, reg, wired.trapDeps),
3002
+ changeLevel,
3003
+ reincarnate: makeReincarnate(state, reg, players, wired.flavor, wired.everseen, changeLevel),
2819
3004
  wizardBundles: wired.wizardBundles,
2820
3005
  ...makeStoreApi(state, reg, wired.flavor, options),
2821
3006
  };
@@ -3102,24 +3287,6 @@ function swapRandartSet(reg, seed, timedFoil, activationSummarize) {
3102
3287
  reg.objects.artifacts.length = 0;
3103
3288
  reg.objects.artifacts.push(...randarts);
3104
3289
  }
3105
- /** The worn-armor weight calc_mana penalizes (non-weapon/bow/jewelry slots). */
3106
- function wornArmorWeight(player, equipment) {
3107
- let weight = 0;
3108
- for (let i = 0; i < player.body.count; i++) {
3109
- const slotType = player.body.slots[i]?.type ?? "";
3110
- if (slotType === "WEAPON" ||
3111
- slotType === "BOW" ||
3112
- slotType === "RING" ||
3113
- slotType === "AMULET" ||
3114
- slotType === "LIGHT") {
3115
- continue;
3116
- }
3117
- const worn = equipment[i];
3118
- if (worn)
3119
- weight += worn.weight;
3120
- }
3121
- return weight;
3122
- }
3123
3290
  /** Serialize a started game into the JSON save format (decision 9). */
3124
3291
  export function saveGame(game) {
3125
3292
  const ids = new ContentIdResolver(game.booted.registries);
@@ -3487,6 +3654,10 @@ export function loadGame(pack, saveDocument, present = new Set(["core"]), opts =
3487
3654
  };
3488
3655
  /* Resuming in town: re-stock the shops (store stock is not persisted). */
3489
3656
  refreshTownStores(state, reg);
3657
+ /* One level changer, shared with reincarnate - see the note at startGame's. */
3658
+ const changeLevel = makeChangeLevel(state, reg, wired.trapDeps, {
3659
+ inArena: !!save.arena,
3660
+ });
3490
3661
  return {
3491
3662
  state,
3492
3663
  registry: wired.registry,
@@ -3505,9 +3676,8 @@ export function loadGame(pack, saveDocument, present = new Set(["core"]), opts =
3505
3676
  : {}),
3506
3677
  options,
3507
3678
  randartSeed,
3508
- changeLevel: makeChangeLevel(state, reg, wired.trapDeps, {
3509
- inArena: !!save.arena,
3510
- }),
3679
+ changeLevel,
3680
+ reincarnate: makeReincarnate(state, reg, players, wired.flavor, wired.everseen, changeLevel),
3511
3681
  wizardBundles: wired.wizardBundles,
3512
3682
  ...makeStoreApi(state, reg, wired.flavor, options),
3513
3683
  };