@adam0white/human-framework 2.23.0 → 3.1.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 +169 -55
- package/dist/agenda/agenda.js +1 -1
- package/dist/beliefs/beliefs.js +2 -2
- package/dist/cognition/cognition.d.ts +6 -1
- package/dist/cognition/cognition.js +1 -1
- package/dist/conscience/conscience.d.ts +2 -4
- package/dist/conscience/conscience.js +3 -5
- package/dist/conversation/conversation.d.ts +0 -41
- package/dist/conversation/conversation.js +5 -5
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +0 -1
- package/dist/core/libm.js +20 -0
- package/dist/core/math.d.ts +0 -2
- package/dist/core/math.js +3 -3
- package/dist/family/family.d.ts +5 -6
- package/dist/family/family.js +34 -12
- package/dist/habits/habits.js +5 -5
- package/dist/impression.d.ts +6 -8
- package/dist/impression.js +7 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/longrun.d.ts +2 -2
- package/dist/longrun.js +1 -2
- package/dist/memory/memory.d.ts +0 -4
- package/dist/memory/memory.js +20 -6
- package/dist/migrate.js +5 -0
- package/dist/person.d.ts +11 -4
- package/dist/person.js +24 -7
- package/dist/persona.js +2 -1
- package/dist/prospection/forecast.d.ts +10 -5
- package/dist/prospection/forecast.js +11 -6
- package/dist/sim/index.d.ts +1 -1
- package/dist/sim/index.js +1 -1
- package/dist/sim/longrun.d.ts +24 -6
- package/dist/sim/longrun.js +43 -13
- package/dist/sim/sim.d.ts +28 -2
- package/dist/sim/sim.js +146 -36
- package/dist/social/impressions.d.ts +0 -12
- package/dist/social/impressions.js +13 -8
- package/dist/social/social.js +2 -2
- package/dist/types.d.ts +5 -2
- package/dist/types.js +5 -2
- package/package.json +1 -1
package/dist/family/family.d.ts
CHANGED
|
@@ -40,11 +40,6 @@ export declare function conceptionChance(mother: Person, father: Person, days: n
|
|
|
40
40
|
* median (an engineering bound against extreme draws). Returns the pregnancy, or undefined if one is already open.
|
|
41
41
|
*/
|
|
42
42
|
export declare function conceive(mother: Person, father: Person | PersonId, seed: number, at: Minute): Pregnancy | undefined;
|
|
43
|
-
/** @deprecated since 2.1: pass `at` (and the optional knobs) positionally. Removed in 3.0. */
|
|
44
|
-
export declare function conceive(mother: Person, father: Person | PersonId, opts: {
|
|
45
|
-
at: Minute;
|
|
46
|
-
seed: number;
|
|
47
|
-
}): Pregnancy | undefined;
|
|
48
43
|
/**
|
|
49
44
|
* Weeks since conception (0 when not pregnant). Counted from conception, not from the last menstrual period, which
|
|
50
45
|
* is where obstetric weeks and trimesters are conventionally counted from (about two weeks earlier). The second
|
|
@@ -79,6 +74,8 @@ export interface Household {
|
|
|
79
74
|
caregivers: readonly Person[];
|
|
80
75
|
}
|
|
81
76
|
export interface RaiseOptions {
|
|
77
|
+
/** Explicit household influence through young adulthood. Omit for exact legacy behavior. Pin in host saves. */
|
|
78
|
+
model?: 'warmth-through-25';
|
|
82
79
|
/** Also move the child's trust in voices the caregivers trust (default true). */
|
|
83
80
|
voices?: boolean;
|
|
84
81
|
}
|
|
@@ -86,6 +83,8 @@ export interface RaiseOptions {
|
|
|
86
83
|
* Apply `minutes` of upbringing in `household` to `child`, at `child.now`. Warmth-weighted: a caregiver with no
|
|
87
84
|
* warmth toward the child teaches nothing. Values, norm understanding, attachment and (optionally) trust in the
|
|
88
85
|
* household's voices move by the age plasticities in the SCOPE paragraph. Returns the warmth-weighted
|
|
89
|
-
* responsiveness the child experienced (0..1).
|
|
86
|
+
* responsiveness the child experienced (0..1) in legacy mode. With `warmth-through-25`, returns effective
|
|
87
|
+
* responsiveness weighted by mean warmth and age plasticity, approaching zero with either. The host supplies
|
|
88
|
+
* this model again after restoring a save. Raised minutes count even when warmth or plasticity is zero.
|
|
90
89
|
*/
|
|
91
90
|
export declare function raise(child: Person, household: Household, minutes: number, opts?: RaiseOptions): Unit;
|
package/dist/family/family.js
CHANGED
|
@@ -29,12 +29,20 @@
|
|
|
29
29
|
* security starts at 0.6 (58% of nonclinical mothers are secure-autonomous, F12) and moves toward the caregivers'
|
|
30
30
|
* responsiveness (warmth and mood) at 50% per year, most in the first three years, with a floor of 0.1 of that
|
|
31
31
|
* plasticity by age 12 (responsiveness and intergenerational correspondence, F10, F11; rates assumed). Optionally a
|
|
32
|
-
* child comes to trust the voices the household trusts (`adoptVoiceTrust`). This file writes `values`
|
|
32
|
+
* child comes to trust the voices the household trusts (`adoptVoiceTrust`). This file writes `values` through young adulthood: one of the
|
|
33
33
|
* documented exceptions to values being fixed at creation (docs/framework.md); the opt-in `character/` drift is
|
|
34
34
|
* the other. It does not model siblings'
|
|
35
35
|
* influence, peers, schooling, abuse, divorce or temperament-by-parenting interactions, and it never assigns a
|
|
36
36
|
* religious obligation by age: a child holds only the understanding the household lived.
|
|
37
37
|
*
|
|
38
|
+
* Opt-in `RaiseOptions.model: 'warmth-through-25'` scales norm and attachment relaxation rates by mean warmth,
|
|
39
|
+
* as values and voice trust already do. All influence tapers continuously to zero at 25 using `valuePlasticity`;
|
|
40
|
+
* attachment also keeps its early-life plasticity. The return is responsiveness × mean warmth × value plasticity.
|
|
41
|
+
* These coefficients and the age horizon are engineering assumptions, not empirical calibration or rulings.
|
|
42
|
+
* F7–F11 in research/family-environment-sources.md support the shapes, not these rates. No abuse, schooling or
|
|
43
|
+
* adult culture diffusion is modelled. Without this option, arithmetic and the normalized return stay unchanged.
|
|
44
|
+
* Hosts must pin this option in saved-run configuration and supply it again after restore; no state infers it.
|
|
45
|
+
*
|
|
38
46
|
* Aptitudes are read by the composite as a multiplier on learning (`aptitudeOf`); they are drawn at birth by
|
|
39
47
|
* `createChild` (`ChildSpec.aptitudes`).
|
|
40
48
|
*/
|
|
@@ -161,19 +169,25 @@ export function conceptionChance(mother, father, days) {
|
|
|
161
169
|
return 0;
|
|
162
170
|
return clamp01(1 - dpow(1 - c, days / FAMILY_DEFAULTS.cycleDays));
|
|
163
171
|
}
|
|
164
|
-
|
|
165
|
-
|
|
172
|
+
/**
|
|
173
|
+
* Record that `mother` has conceived by `father` at `at`. The due date is drawn from a stream derived from `seed`;
|
|
174
|
+
* `seed` also becomes the child's seed at delivery. The drawn length is clamped to 4 sd below and 3 sd above the
|
|
175
|
+
* median (an engineering bound against extreme draws). Returns the pregnancy, or undefined if one is already open.
|
|
176
|
+
*/
|
|
177
|
+
export function conceive(mother, father, seed, at) {
|
|
178
|
+
if (!Number.isFinite(at))
|
|
179
|
+
throw new TypeError('conceive requires a finite positional time');
|
|
166
180
|
const fam = familyOf(mother);
|
|
167
181
|
if (fam.pregnancy)
|
|
168
182
|
return undefined;
|
|
169
|
-
const rng = createRng((
|
|
183
|
+
const rng = createRng((seed ^ 0x9e3779b9) >>> 0);
|
|
170
184
|
const F = FAMILY_DEFAULTS;
|
|
171
185
|
const days = clamp(normal(rng, F.gestationDays, F.gestationSdDays), F.gestationDays - 4 * F.gestationSdDays, F.gestationDays + 3 * F.gestationSdDays);
|
|
172
186
|
const pregnancy = {
|
|
173
187
|
fatherId: typeof father === 'string' ? father : father.id,
|
|
174
|
-
conceivedAt:
|
|
175
|
-
dueAt:
|
|
176
|
-
seed
|
|
188
|
+
conceivedAt: at,
|
|
189
|
+
dueAt: at + Math.round(days * MINUTES_PER_DAY),
|
|
190
|
+
seed,
|
|
177
191
|
};
|
|
178
192
|
fam.pregnancy = pregnancy;
|
|
179
193
|
return { ...pregnancy };
|
|
@@ -240,13 +254,17 @@ const relax = (rate, years) => clamp01(1 - dpow(1 - clamp01(rate), years));
|
|
|
240
254
|
* Apply `minutes` of upbringing in `household` to `child`, at `child.now`. Warmth-weighted: a caregiver with no
|
|
241
255
|
* warmth toward the child teaches nothing. Values, norm understanding, attachment and (optionally) trust in the
|
|
242
256
|
* household's voices move by the age plasticities in the SCOPE paragraph. Returns the warmth-weighted
|
|
243
|
-
* responsiveness the child experienced (0..1).
|
|
257
|
+
* responsiveness the child experienced (0..1) in legacy mode. With `warmth-through-25`, returns effective
|
|
258
|
+
* responsiveness weighted by mean warmth and age plasticity, approaching zero with either. The host supplies
|
|
259
|
+
* this model again after restoring a save. Raised minutes count even when warmth or plasticity is zero.
|
|
244
260
|
*/
|
|
245
261
|
export function raise(child, household, minutes, opts = {}) {
|
|
246
262
|
if (!(minutes > 0) || !child.body.alive)
|
|
247
263
|
return 0;
|
|
248
264
|
const F = FAMILY_DEFAULTS;
|
|
249
|
-
const
|
|
265
|
+
const continuous = opts.model === 'warmth-through-25';
|
|
266
|
+
const eligible = household.caregivers.filter((c) => c.id !== child.id && c.body.alive);
|
|
267
|
+
const carers = continuous ? [...new Map(eligible.map((c) => [c.id, c])).values()] : eligible;
|
|
250
268
|
const warmth = carers.map((c) => Math.max(0, relationshipWith(c, child.id).affection));
|
|
251
269
|
const total = warmth.reduce((s, w) => s + w, 0);
|
|
252
270
|
const fam = familyOf(child);
|
|
@@ -257,6 +275,8 @@ export function raise(child, household, minutes, opts = {}) {
|
|
|
257
275
|
const age = ageYears(child);
|
|
258
276
|
const meanWarmth = total / carers.length;
|
|
259
277
|
const vp = valuePlasticity(age);
|
|
278
|
+
if (continuous && vp <= 0)
|
|
279
|
+
return 0;
|
|
260
280
|
// Values.
|
|
261
281
|
if (vp > 0) {
|
|
262
282
|
const k = relax(F.valueRatePerYear * meanWarmth, years * vp);
|
|
@@ -273,7 +293,7 @@ export function raise(child, household, minutes, opts = {}) {
|
|
|
273
293
|
if (vp > 0) {
|
|
274
294
|
const since = child.now - MINUTES_PER_YEAR;
|
|
275
295
|
const ids = [...new Set(carers.flatMap((c) => c.conscience.norms.map((n) => n.normId)))].sort();
|
|
276
|
-
const k = relax(F.normRatePerYear, years * vp);
|
|
296
|
+
const k = relax(continuous ? F.normRatePerYear * meanWarmth : F.normRatePerYear, years * vp);
|
|
277
297
|
for (const id of ids) {
|
|
278
298
|
let target = 0;
|
|
279
299
|
let standing;
|
|
@@ -308,7 +328,9 @@ export function raise(child, household, minutes, opts = {}) {
|
|
|
308
328
|
responsiveness += w * clamp01(0.7 * w + 0.3 * ((c.affect.mood.valence + 1) / 2));
|
|
309
329
|
});
|
|
310
330
|
responsiveness /= total;
|
|
311
|
-
const ka =
|
|
331
|
+
const ka = continuous
|
|
332
|
+
? relax(F.attachmentRatePerYear * meanWarmth, years * attachmentPlasticity(age) * vp)
|
|
333
|
+
: relax(F.attachmentRatePerYear, years * attachmentPlasticity(age));
|
|
312
334
|
const att = fam.attachment ?? F.attachmentStart;
|
|
313
335
|
fam.attachment = clamp01(att + ka * (responsiveness - att));
|
|
314
336
|
// Trust in the household's voices (an elder, a teacher, a host's voice): not the caregivers themselves.
|
|
@@ -331,5 +353,5 @@ export function raise(child, household, minutes, opts = {}) {
|
|
|
331
353
|
adoptVoiceTrust(child, id, target / wsum, kv);
|
|
332
354
|
}
|
|
333
355
|
}
|
|
334
|
-
return clamp01(responsiveness);
|
|
356
|
+
return clamp01(continuous ? responsiveness * meanWarmth * vp : responsiveness);
|
|
335
357
|
}
|
package/dist/habits/habits.js
CHANGED
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
* assumption. Does not claim: pharmacology, dependence severity or relapse probabilities.
|
|
29
29
|
*
|
|
30
30
|
* SCOPE (habit ease, N4): `habitEase` is a multiplier < 1 on the initiation and attentional parts of an
|
|
31
|
-
* option's effort cost for a cued habitual action.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
31
|
+
* option's effort cost for a cued habitual action. `test/habits-lane.test.ts` compares candidate effort
|
|
32
|
+
* formulas under authored fatigue and sleepiness. That engineering comparison is not a restraint-depletion
|
|
33
|
+
* manipulation, participant-data replication, or full choice experiment; it does not validate a fungible
|
|
34
|
+
* willpower fuel. Physical exertion is not eased (habit does not make a walk lighter). Does not claim:
|
|
35
|
+
* a measured effect size, an empirically established explanation, or that automaticity removes intention.
|
|
36
36
|
*/
|
|
37
37
|
import { clamp01, decay, dexp, hourOf, minuteOfDay } from '../core/index.js';
|
|
38
38
|
import { MINUTES_PER_DAY, } from '../types.js';
|
package/dist/impression.d.ts
CHANGED
|
@@ -6,14 +6,9 @@ export declare function outwardSigns(target: Person): OutwardSigns;
|
|
|
6
6
|
/** What `target` says of themself: words hide more than faces (`wordsReserve`), and a limp is not mentioned. */
|
|
7
7
|
export declare function selfReport(target: Person): OutwardSigns;
|
|
8
8
|
/** `observer` looks at `target` at `at` (clarity 0..1: a clear look near by, or a distant figure; default 1). */
|
|
9
|
-
export declare function
|
|
10
|
-
/** @deprecated since 2.1: pass `at` (and the optional knobs) positionally. Removed in 3.0. */
|
|
11
|
-
export declare function glimpseOf(observer: Person, target: Person, opts: {
|
|
12
|
-
at: Minute;
|
|
13
|
-
clarity?: Unit;
|
|
14
|
-
}): void;
|
|
9
|
+
export declare function glimpsePerson(observer: Person, target: Person, at: Minute, clarity?: Unit): void;
|
|
15
10
|
/** `observer` has known `target` for a long time (familiarity 0..1): traits and family ties, condensed. */
|
|
16
|
-
export declare function
|
|
11
|
+
export declare function acquaintPerson(observer: Person, target: Person, familiarity: Unit, at: Minute): void;
|
|
17
12
|
/** How sure the observer is of the things that drive an answer: traits and the state cues, 0..1. */
|
|
18
13
|
export declare function impressionConfidence(observer: Person, targetId: PersonId, now: Minute): Unit;
|
|
19
14
|
/**
|
|
@@ -31,9 +26,12 @@ export declare function predictAs(observer: Person, target: Person, affordances:
|
|
|
31
26
|
others?: readonly Suggestion[];
|
|
32
27
|
scarcity?: Unit;
|
|
33
28
|
now?: Minute;
|
|
29
|
+
forecastContext?: 'conditioned';
|
|
34
30
|
}): ImpressionPrediction;
|
|
35
31
|
/** Whether `observer` expects a command on `target` to hold and at what price (pure; see `imagine`). */
|
|
36
|
-
export declare function previewCommandAs(observer: Person, target: Person, affordances: readonly Affordance[], cmd: Command, now?: Minute
|
|
32
|
+
export declare function previewCommandAs(observer: Person, target: Person, affordances: readonly Affordance[], cmd: Command, now?: Minute, opts?: {
|
|
33
|
+
forecastContext?: 'conditioned';
|
|
34
|
+
}): {
|
|
37
35
|
outcome: CommandOutcome;
|
|
38
36
|
confidence: Unit;
|
|
39
37
|
};
|
package/dist/impression.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* - `outwardSigns(target)`: perceived fatigue, pain and fear and the felt mood, each reduced by the target's reserve;
|
|
5
5
|
* a limp (lost moving capacity) shows through any reserve. `selfReport(target)` is the same in words, which hide
|
|
6
6
|
* more (`IMPRESSION_DEFAULTS.wordsReserve`): "I'm fine".
|
|
7
|
-
* - `
|
|
7
|
+
* - `glimpsePerson(observer, target, at, clarity?)` = `glimpse` of the target's outward signs; `acquaintPerson` hands the target's
|
|
8
8
|
* traits and family ties (public roles) to `acquaint`.
|
|
9
9
|
* - `imagine(observer, target, now)`: the target as the observer pictures them — a copy whose traits, fear, pain,
|
|
10
10
|
* fatigue, mood, ties and trust in voices are the observer's beliefs (each pulled to the prior by its uncertainty)
|
|
@@ -61,14 +61,12 @@ export function selfReport(target) {
|
|
|
61
61
|
s.pain = round(body.perceived.pain * (1 - clamp01(reserveOf(target, 'pain') * IMPRESSION_DEFAULTS.wordsReserve)));
|
|
62
62
|
return s;
|
|
63
63
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
else
|
|
68
|
-
glimpse(observer, target.id, outwardSigns(target), when.at, when.clarity);
|
|
64
|
+
/** `observer` looks at `target` at `at` (clarity 0..1: a clear look near by, or a distant figure; default 1). */
|
|
65
|
+
export function glimpsePerson(observer, target, at, clarity) {
|
|
66
|
+
glimpse(observer, target.id, outwardSigns(target), at, clarity);
|
|
69
67
|
}
|
|
70
68
|
/** `observer` has known `target` for a long time (familiarity 0..1): traits and family ties, condensed. */
|
|
71
|
-
export function
|
|
69
|
+
export function acquaintPerson(observer, target, familiarity, at) {
|
|
72
70
|
const ties = {};
|
|
73
71
|
for (const r of target.social.relationships)
|
|
74
72
|
if (r.roles.some((x) => PUBLIC_ROLES.includes(x)))
|
|
@@ -160,10 +158,10 @@ export function predictAs(observer, target, affordances, suggestion, opts = {})
|
|
|
160
158
|
};
|
|
161
159
|
}
|
|
162
160
|
/** Whether `observer` expects a command on `target` to hold and at what price (pure; see `imagine`). */
|
|
163
|
-
export function previewCommandAs(observer, target, affordances, cmd, now = target.now) {
|
|
161
|
+
export function previewCommandAs(observer, target, affordances, cmd, now = target.now, opts = {}) {
|
|
164
162
|
const model = imagine(observer, target, now);
|
|
165
163
|
return {
|
|
166
|
-
outcome: previewCommand(model, affordances, cmd),
|
|
164
|
+
outcome: previewCommand(model, affordances, cmd, opts),
|
|
167
165
|
confidence: impressionConfidence(observer, target.id, now),
|
|
168
166
|
};
|
|
169
167
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Human Framework public surface. */
|
|
2
|
-
export declare const FRAMEWORK_VERSION = "
|
|
2
|
+
export declare const FRAMEWORK_VERSION = "3.1.0";
|
|
3
3
|
export type { CrisisEvent, PracticeKind } from './affect/index.ts';
|
|
4
4
|
export { AFFECT_DEFAULTS, actionTendencies, advanceAffect, appraise, breakAllows, breakBehaviour, breakHazard, CRISIS_DEFAULTS, checkCrisis, createAffect, easeBreak, emotionLevel, enableBreaks, feel, inBreak, readAffect, regulate, release as releaseEmotion, skipCrisis, strain, tendencyEmotions, } from './affect/index.ts';
|
|
5
5
|
export type { GoalTemplate, MakeUpReceipt, PrayerCalendar, PrayerSchedule, PrayerTimes, Retimer, } from './agenda/index.ts';
|
|
@@ -46,5 +46,6 @@ export * from './scenarios/index.ts';
|
|
|
46
46
|
export * from './sim/index.ts';
|
|
47
47
|
export * from './skills/index.ts';
|
|
48
48
|
export * from './social/index.ts';
|
|
49
|
+
export { canonicalTickInputs, type TickInput, type TickInputKey } from './tick-input.ts';
|
|
49
50
|
export * from './types.ts';
|
|
50
51
|
export * from './will/index.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Human Framework public surface. */
|
|
2
|
-
export const FRAMEWORK_VERSION = '
|
|
2
|
+
export const FRAMEWORK_VERSION = '3.1.0';
|
|
3
3
|
export { AFFECT_DEFAULTS, actionTendencies, advanceAffect, appraise, breakAllows, breakBehaviour, breakHazard, CRISIS_DEFAULTS, checkCrisis, createAffect, easeBreak, emotionLevel, enableBreaks, feel, inBreak, readAffect, regulate, release as releaseEmotion, skipCrisis, strain, tendencyEmotions, } from './affect/index.js';
|
|
4
4
|
// `agenda.release` collides with `affect.release`; the agenda one is re-exported under a clearer name.
|
|
5
5
|
export { AGENDA_DEFAULTS, abandonGoal, adoptGoal, advanceAgenda, agendaTerms, applyExemptions, CARE_DEFAULTS, calendarRetimer, careDuty, commitmentPressure, createAgenda, DEFAULT_PRAYER_TIMES, EID_PRAYER_IMPORTANCE, EXEMPTION_DEFAULTS, eidPrayer, eidWindow, fastWindow, iftarWindow, inMakruhTime, isContinuingCommitment, isUnderWay, MAKRUH_DEFAULTS, makruhWindows, missedExcuse, onFinished, owedMakeUps, PRAYER_IMPORTANCE, PURPOSE_DEFAULTS, prayerWindows, pressureReachedAt, promise, proposeGoals, RAMADAN_DEFAULTS, ramadanFast, ramadanMeals, release as releaseCommitment, retimeCommitments, retirePaidMakeUps, revisePurposes, scheduleMakeUp, spanMeetsWindow, suhoorWindow, timesFor, violatesAbstention, } from './agenda/index.js';
|
|
@@ -42,5 +42,6 @@ export * from './scenarios/index.js';
|
|
|
42
42
|
export * from './sim/index.js';
|
|
43
43
|
export * from './skills/index.js';
|
|
44
44
|
export * from './social/index.js';
|
|
45
|
+
export { canonicalTickInputs } from './tick-input.js';
|
|
45
46
|
export * from './types.js';
|
|
46
47
|
export * from './will/index.js';
|
package/dist/longrun.d.ts
CHANGED
|
@@ -87,8 +87,8 @@ export interface RoutineDay {
|
|
|
87
87
|
* Live one routine day from `p.now` (see SCOPE). A dead person only moves the clock. Returns what happened.
|
|
88
88
|
*/
|
|
89
89
|
export declare function routineDay(p: Person, routine: Routine, opts?: RoutineOptions): RoutineDay;
|
|
90
|
-
/**
|
|
91
|
-
export type RoutineSource =
|
|
90
|
+
/** Choose a routine for a person at the start of an absolute day. Capture host context in a closure. */
|
|
91
|
+
export type RoutineSource = (p: Person, day: number) => Routine;
|
|
92
92
|
/**
|
|
93
93
|
* Live from `p.now` to `to` by routine (see SCOPE): the running activity is dropped and the open chronicle day closed
|
|
94
94
|
* first, whole days are lived with `routineDay`, a remainder shorter than a day is skipped (`skip`), and past
|
package/dist/longrun.js
CHANGED
|
@@ -181,7 +181,6 @@ export function routineDay(p, routine, opts = {}) {
|
|
|
181
181
|
report.stage = stageAfter;
|
|
182
182
|
return report;
|
|
183
183
|
}
|
|
184
|
-
const routineOf = (src, p) => typeof src === 'function' ? src(p, dayOf(p.now)) : src;
|
|
185
184
|
/**
|
|
186
185
|
* Live from `p.now` to `to` by routine (see SCOPE): the running activity is dropped and the open chronicle day closed
|
|
187
186
|
* first, whole days are lived with `routineDay`, a remainder shorter than a day is skipped (`skip`), and past
|
|
@@ -199,7 +198,7 @@ export function liveRoutine(p, to, routine, opts = {}) {
|
|
|
199
198
|
endDay(p);
|
|
200
199
|
p.activity = null;
|
|
201
200
|
while (p.now + MINUTES_PER_DAY <= to && p.body.alive) {
|
|
202
|
-
const r = routineDay(p,
|
|
201
|
+
const r = routineDay(p, routine(p, dayOf(p.now)), opts);
|
|
203
202
|
if (r.episodes.length > 0 || r.onsets.length > 0 || r.stage || r.died)
|
|
204
203
|
out.push(r);
|
|
205
204
|
}
|
package/dist/memory/memory.d.ts
CHANGED
|
@@ -139,10 +139,6 @@ export interface RetellOptions {
|
|
|
139
139
|
* from the listener to others (a host may call it again with the listener as teller).
|
|
140
140
|
*/
|
|
141
141
|
export declare function retell(teller: Person, listener: Person, at: Minute, opts?: RetellOptions): Gist[];
|
|
142
|
-
/** @deprecated since 2.1: pass `at` (and the optional knobs) positionally. Removed in 3.0. */
|
|
143
|
-
export declare function retell(teller: Person, listener: Person, opts: RetellOptions & {
|
|
144
|
-
at: Minute;
|
|
145
|
-
}): Gist[];
|
|
146
142
|
/** Encode an episode. Evicts the weakest (salience × recency) episode beyond the bound. */
|
|
147
143
|
export declare function remember(p: Person, e: Omit<Episode, 'id' | 'salience'> & {
|
|
148
144
|
salience?: Unit;
|
package/dist/memory/memory.js
CHANGED
|
@@ -287,8 +287,22 @@ export const RETELL_DEFAULTS = {
|
|
|
287
287
|
/** Gists weaker than this (teller's salience) are not worth telling. */
|
|
288
288
|
minSalience: 0.1,
|
|
289
289
|
};
|
|
290
|
-
|
|
291
|
-
|
|
290
|
+
/**
|
|
291
|
+
* `teller` tells `listener` at `at` the gist of what mattered to them (2.0, L2: stories passed in a household or around a
|
|
292
|
+
* fire). The listener must have gists on (`enableGists`); otherwise nothing happens. The teller's strongest gists
|
|
293
|
+
* (up to `limit`, optionally only those about `placeIds`) become the listener's own gists with the tag `told`, the
|
|
294
|
+
* teller's valence and summary, and a salience of the teller's × `trust` × `RETELL_DEFAULTS.share`. A listener who
|
|
295
|
+
* already holds a gist about the same thing (kind, action, target and place, whoever was there) from their own
|
|
296
|
+
* experience keeps it unchanged; one told before keeps the
|
|
297
|
+
* stronger telling (retelling the same story does not keep raising it). So a child of parents who fear a place
|
|
298
|
+
* weighs that fear (cognition's `memory` term, by place at half weight) before ever standing there, and their own
|
|
299
|
+
* later visits outweigh it as they would any gist. No randomness; returns the gists written or strengthened.
|
|
300
|
+
* It does not model distortion in the retelling, the listener doubting the teller beyond `trust`, or retelling on
|
|
301
|
+
* from the listener to others (a host may call it again with the listener as teller).
|
|
302
|
+
*/
|
|
303
|
+
export function retell(teller, listener, at, opts = {}) {
|
|
304
|
+
if (!Number.isFinite(at))
|
|
305
|
+
throw new TypeError('retell requires a finite positional time');
|
|
292
306
|
const told = teller.memory.gists;
|
|
293
307
|
const list = listener.memory.gists;
|
|
294
308
|
if (!told || !list || teller.id === listener.id)
|
|
@@ -312,7 +326,7 @@ export function retell(teller, listener, when, knobs = {}) {
|
|
|
312
326
|
if (salience > mine.salience) {
|
|
313
327
|
mine.salience = salience;
|
|
314
328
|
mine.weight = salience;
|
|
315
|
-
mine.lastAt =
|
|
329
|
+
mine.lastAt = at;
|
|
316
330
|
out.push(mine);
|
|
317
331
|
}
|
|
318
332
|
continue;
|
|
@@ -321,15 +335,15 @@ export function retell(teller, listener, when, knobs = {}) {
|
|
|
321
335
|
listener.memory.nextGist = (listener.memory.nextGist ?? 0) + 1;
|
|
322
336
|
const g = {
|
|
323
337
|
id,
|
|
324
|
-
at
|
|
338
|
+
at,
|
|
325
339
|
kind: src.kind,
|
|
326
340
|
valence: src.valence,
|
|
327
341
|
salience,
|
|
328
342
|
summary: src.summary,
|
|
329
343
|
tags: ['told', ...src.tags.filter((t) => t !== 'told')].slice(0, GIST_DEFAULTS.maxTags),
|
|
330
344
|
count: 0,
|
|
331
|
-
firstAt:
|
|
332
|
-
lastAt:
|
|
345
|
+
firstAt: at,
|
|
346
|
+
lastAt: at,
|
|
333
347
|
weight: salience,
|
|
334
348
|
peak: salience,
|
|
335
349
|
};
|
package/dist/migrate.js
CHANGED
|
@@ -41,6 +41,11 @@ function renameAmbient(json) {
|
|
|
41
41
|
}
|
|
42
42
|
/** The chain, keyed by the version each step upgrades from. */
|
|
43
43
|
export const MIGRATIONS = {
|
|
44
|
+
'2.23.0': {
|
|
45
|
+
to: '3.1.0',
|
|
46
|
+
note: 'version stamp only; existing state and RNG are unchanged, and new behaviour requires explicit opt-in',
|
|
47
|
+
apply: stamp,
|
|
48
|
+
},
|
|
44
49
|
'2.21.0': {
|
|
45
50
|
to: '2.23.0',
|
|
46
51
|
note: 'shape unchanged; doze delivery and plain narration fixes apply to opted-in runs',
|
package/dist/person.d.ts
CHANGED
|
@@ -102,6 +102,13 @@ export interface PerceiveOptions {
|
|
|
102
102
|
*/
|
|
103
103
|
export declare function perceive(p: Person, percepts: readonly Percept[], options?: PerceiveOptions): Percept[];
|
|
104
104
|
export interface DecideOptions {
|
|
105
|
+
/**
|
|
106
|
+
* Q26: forecast with current pregnancy and surroundings held through the bounded horizon.
|
|
107
|
+
* Approximation, not future conditions. Absent preserves legacy. Pin in host saved-run config;
|
|
108
|
+
* restore never infers this choice from Person state. Changes only the bodily forecast term.
|
|
109
|
+
* planRoute and begin pursuit fallback have no bodily forecast term and keep their existing inputs.
|
|
110
|
+
*/
|
|
111
|
+
forecastContext?: 'conditioned';
|
|
105
112
|
suggestion?: Suggestion;
|
|
106
113
|
/** Several voices in one decision (N1); merged with `suggestion`, one per voice id. */
|
|
107
114
|
suggestions?: readonly Suggestion[];
|
|
@@ -124,7 +131,7 @@ export interface DecideOptions {
|
|
|
124
131
|
* How this person would answer a suggestion right now, without changing them or consuming randomness
|
|
125
132
|
* (hover telegraph). Does not advance time. With `temperature > 0`, read `likelihood` rather than the verdict.
|
|
126
133
|
*/
|
|
127
|
-
export declare function predict(p: Person, affordances: readonly Affordance[], suggestion: Suggestion, opts?: {
|
|
134
|
+
export declare function predict(p: Person, affordances: readonly Affordance[], suggestion: Suggestion, opts?: Pick<DecideOptions, 'forecastContext'> & {
|
|
128
135
|
necessity?: boolean;
|
|
129
136
|
others?: readonly Suggestion[];
|
|
130
137
|
scarcity?: Unit;
|
|
@@ -138,7 +145,7 @@ export declare function predict(p: Person, affordances: readonly Affordance[], s
|
|
|
138
145
|
* or record a trace entry; a later decision on the same standing suggestion counts again (hosts that answer
|
|
139
146
|
* now should drop the suggestion once it is refused).
|
|
140
147
|
*/
|
|
141
|
-
export declare function answerNow(p: Person, affordances: readonly Affordance[], suggestion: Suggestion, opts?: {
|
|
148
|
+
export declare function answerNow(p: Person, affordances: readonly Affordance[], suggestion: Suggestion, opts?: Pick<DecideOptions, 'forecastContext'> & {
|
|
142
149
|
necessity?: boolean;
|
|
143
150
|
others?: readonly Suggestion[];
|
|
144
151
|
scarcity?: Unit;
|
|
@@ -178,7 +185,7 @@ export declare function releaseCommand(p: Person, reason?: string): boolean;
|
|
|
178
185
|
* (a UI showing "they will do it, but would rather eat" before the host takes control). `margin` is the gap
|
|
179
186
|
* the hourly autonomy and trust costs scale with.
|
|
180
187
|
*/
|
|
181
|
-
export declare function previewCommand(p: Person, affordances: readonly Affordance[], cmd: Command): CommandOutcome;
|
|
188
|
+
export declare function previewCommand(p: Person, affordances: readonly Affordance[], cmd: Command, opts?: Pick<DecideOptions, 'forecastContext'>): CommandOutcome;
|
|
182
189
|
export interface BeginOptions {
|
|
183
190
|
/**
|
|
184
191
|
* Make a commitment at begin (e.g. carrying the injured): a pending commitment for this action and target,
|
|
@@ -271,7 +278,7 @@ export declare function nafsReading(p: Person): NafsPattern[];
|
|
|
271
278
|
* The person's own forecast of their body through an offer and its `followedBy` spans (2.5.0, read-only), with a
|
|
272
279
|
* first-person line ("I can do it, but I'll be spent for the descent."). Empty spans without `followedBy`.
|
|
273
280
|
*/
|
|
274
|
-
export declare function bodyForecast(p: Person, aff: Affordance): {
|
|
281
|
+
export declare function bodyForecast(p: Person, aff: Affordance, opts?: Pick<DecideOptions, 'forecastContext'>): {
|
|
275
282
|
spans: BodyForecastSpan[];
|
|
276
283
|
line: string;
|
|
277
284
|
};
|
package/dist/person.js
CHANGED
|
@@ -29,7 +29,8 @@ import { ageCharacter, enableCharacterChange, noteCharacterDay, noteCharacterSoc
|
|
|
29
29
|
import { closeDay, enableYearbook, endDay, noteAnswer, noteCommitments, noteDecision, noteMood, noteOutcome, trimChronicle, } from './chronicle/index.js';
|
|
30
30
|
import { decide as cognitionDecide, desperationOf, prospectiveRoute, scoreAll } from './cognition/index.js';
|
|
31
31
|
import { createConscience, guiltLoad, heldNorms, normVeto, recordDeed, recordRepair, repent, } from './conscience/index.js';
|
|
32
|
-
import { clamp01, clampSigned, createRng, dayOf, isObj,
|
|
32
|
+
import { clamp01, clampSigned, createRng, dayOf, isObj, minuteOfDay, round } from './core/index.js';
|
|
33
|
+
import { keysOf } from './core/keys.js';
|
|
33
34
|
import { enableCuriosity, noteCuriosity } from './curiosity/index.js';
|
|
34
35
|
import { ambientBodyParams, ambientModifiers, ambientMood, ambientNeeds } from './environment/index.js';
|
|
35
36
|
import { aptitudeOf, createFamily, pregnancyModifiers } from './family/index.js';
|
|
@@ -905,6 +906,15 @@ function currentOffer(p) {
|
|
|
905
906
|
return undefined;
|
|
906
907
|
return { ...act.affordance, duration: act.endsAt - p.now };
|
|
907
908
|
}
|
|
909
|
+
/** Q26: compose one held snapshot for all public forecast paths; does not alter Person or ordinary scoring. */
|
|
910
|
+
function bodyForecastContext(p, opts) {
|
|
911
|
+
return opts.forecastContext === 'conditioned'
|
|
912
|
+
? {
|
|
913
|
+
mods: segmentModifiers(p),
|
|
914
|
+
params: p.ambient ? ambientBodyParams(p, BODY_DEFAULTS) : BODY_DEFAULTS,
|
|
915
|
+
}
|
|
916
|
+
: { mods: lifeModifiers(p), params: BODY_DEFAULTS };
|
|
917
|
+
}
|
|
908
918
|
/** Offers (plus the current activity) and the scoring context for a decision at `p.now`. Reads only. */
|
|
909
919
|
function decisionInputs(p, affordances, id, opts) {
|
|
910
920
|
const list = [...affordances];
|
|
@@ -933,6 +943,8 @@ function decisionInputs(p, affordances, id, opts) {
|
|
|
933
943
|
const perception = fastingCtx(p);
|
|
934
944
|
if (perception)
|
|
935
945
|
ctx.perception = perception;
|
|
946
|
+
if (opts.forecastContext === 'conditioned')
|
|
947
|
+
ctx.forecastContext = bodyForecastContext(p, opts);
|
|
936
948
|
if (opts.suggestion)
|
|
937
949
|
ctx.suggestion = opts.suggestion;
|
|
938
950
|
// Only set when voices were given this way, so single-voice records keep their shape.
|
|
@@ -965,6 +977,8 @@ function commandOf(c) {
|
|
|
965
977
|
export function predict(p, affordances, suggestion, opts = {}) {
|
|
966
978
|
const others = (opts.others ?? []).filter((s) => s.voiceId !== suggestion.voiceId);
|
|
967
979
|
const decideOpts = { suggestion };
|
|
980
|
+
if (opts.forecastContext !== undefined)
|
|
981
|
+
decideOpts.forecastContext = opts.forecastContext;
|
|
968
982
|
if (others.length > 0)
|
|
969
983
|
decideOpts.suggestions = others;
|
|
970
984
|
if (opts.necessity !== undefined)
|
|
@@ -989,6 +1003,8 @@ export function predict(p, affordances, suggestion, opts = {}) {
|
|
|
989
1003
|
export function answerNow(p, affordances, suggestion, opts = {}) {
|
|
990
1004
|
const others = (opts.others ?? []).filter((s) => s.voiceId !== suggestion.voiceId);
|
|
991
1005
|
const decideOpts = { suggestion };
|
|
1006
|
+
if (opts.forecastContext !== undefined)
|
|
1007
|
+
decideOpts.forecastContext = opts.forecastContext;
|
|
992
1008
|
if (others.length > 0)
|
|
993
1009
|
decideOpts.suggestions = others;
|
|
994
1010
|
if (opts.necessity !== undefined)
|
|
@@ -1161,8 +1177,8 @@ export function releaseCommand(p, reason = 'released') {
|
|
|
1161
1177
|
* (a UI showing "they will do it, but would rather eat" before the host takes control). `margin` is the gap
|
|
1162
1178
|
* the hourly autonomy and trust costs scale with.
|
|
1163
1179
|
*/
|
|
1164
|
-
export function previewCommand(p, affordances, cmd) {
|
|
1165
|
-
const { list, ctx } = decisionInputs(p, affordances, 'preview', { command: cmd });
|
|
1180
|
+
export function previewCommand(p, affordances, cmd, opts = {}) {
|
|
1181
|
+
const { list, ctx } = decisionInputs(p, affordances, 'preview', { ...opts, command: cmd });
|
|
1166
1182
|
const { considered, willCtx } = scoreAll(p, list, ctx);
|
|
1167
1183
|
return resolveCommand(p, considered, willCtx);
|
|
1168
1184
|
}
|
|
@@ -1390,7 +1406,7 @@ function respondToConscience(p, act, now, completed, minutes) {
|
|
|
1390
1406
|
// Worship closes breaches against God alone; guilt toward a wronged person waits for repair.
|
|
1391
1407
|
const repented = new Set();
|
|
1392
1408
|
for (const b of p.conscience.breaches) {
|
|
1393
|
-
if (!b.repaired && b.victimId === undefined && repent(p, b.id
|
|
1409
|
+
if (!b.repaired && b.victimId === undefined && repent(p, b.id))
|
|
1394
1410
|
repented.add(b.normId);
|
|
1395
1411
|
}
|
|
1396
1412
|
for (const b of p.conscience.breaches)
|
|
@@ -1401,7 +1417,7 @@ function respondToConscience(p, act, now, completed, minutes) {
|
|
|
1401
1417
|
regulate(p, minutes, 'worship');
|
|
1402
1418
|
}
|
|
1403
1419
|
if (completed && (tags.includes('repair') || tags.includes('apologize')) && aff.targetId !== undefined) {
|
|
1404
|
-
recordRepair(p, aff.targetId
|
|
1420
|
+
recordRepair(p, aff.targetId);
|
|
1405
1421
|
release(p, { id: 'guilt', targetId: aff.targetId });
|
|
1406
1422
|
socialEvent(p, { at: now, kind: 'apology', otherId: aff.targetId, byMe: true, magnitude: 0.7 });
|
|
1407
1423
|
}
|
|
@@ -1694,8 +1710,9 @@ export function nafsReading(p) {
|
|
|
1694
1710
|
* The person's own forecast of their body through an offer and its `followedBy` spans (2.5.0, read-only), with a
|
|
1695
1711
|
* first-person line ("I can do it, but I'll be spent for the descent."). Empty spans without `followedBy`.
|
|
1696
1712
|
*/
|
|
1697
|
-
export function bodyForecast(p, aff) {
|
|
1698
|
-
const
|
|
1713
|
+
export function bodyForecast(p, aff, opts = {}) {
|
|
1714
|
+
const { mods, params } = bodyForecastContext(p, opts);
|
|
1715
|
+
const spans = bodyForecastFor(p, aff, mods, fastingCtx(p), params);
|
|
1699
1716
|
return {
|
|
1700
1717
|
spans,
|
|
1701
1718
|
line: forecastLine(spans, forecastThresholds(aff), { plainEnglish: p.lexicon?.plainEnglish }),
|
package/dist/persona.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* identity, age, family and health compatibility before returning a new Person. Neither input is mutated.
|
|
5
5
|
* This is not a world migration, identity registry, transport, hash, authentication or general calendar mapper.
|
|
6
6
|
* v1 admits zero-duration travel and healthy compatible bodies only; family/bonds remain host-authored and must
|
|
7
|
-
* match source provenance. Portable v1 accepts its published 2.14.1 and 2.
|
|
7
|
+
* match source provenance. Portable v1 accepts its published 2.14.1, 2.17.0, 2.21.0 and 2.23.0 stamps and the current engine;
|
|
8
8
|
* the bodily opt-ins change no portable field semantics. Pregnancy and nonempty temporal bonds are unsupported in v1. All other world-dependent stores stay with the source and are disclosed as omitted.
|
|
9
9
|
*/
|
|
10
10
|
import { hasUnresolvedMakeUps, sameChain } from './agenda/agenda.js';
|
|
@@ -188,6 +188,7 @@ export function validatePersonaProjection(input) {
|
|
|
188
188
|
keys(input.source, ['schema', 'engine', 'id', 'now']);
|
|
189
189
|
// The 2.14.1 and 2.17.0 portable fields retain their semantics across the bodily opt-ins.
|
|
190
190
|
const compatibleEngine = input.source.engine === ENGINE_VERSION ||
|
|
191
|
+
input.source.engine === '2.23.0' ||
|
|
191
192
|
input.source.engine === '2.21.0' ||
|
|
192
193
|
input.source.engine === '2.17.0' ||
|
|
193
194
|
input.source.engine === '2.14.1';
|
|
@@ -11,15 +11,20 @@
|
|
|
11
11
|
* current effort; only a person with the opt-in fatigue store (2.6.0, `enableFatigueStore`) carries accumulated
|
|
12
12
|
* exertion, so only then does a long climb by itself leave them more spent for the descent; unfelt
|
|
13
13
|
* sleep debt stays unfelt in the forecast; an open fast's damping of hunger and thirst applies (2.6.0) as it is
|
|
14
|
-
* now, held for the whole forecast even if the fast would end during it
|
|
15
|
-
*
|
|
14
|
+
* now, held for the whole forecast even if the fast would end during it. By default host surroundings are not
|
|
15
|
+
* applied. Q26: explicit per-call conditioned forecasts instead hold current age, pregnancy and ambient
|
|
16
|
+
* modifiers AND ambient body parameters through the bounded horizon (four follow-on spans, 1440 minutes).
|
|
17
|
+
* This is a frozen current-conditions approximation: no future weather, pregnancy progression or world
|
|
18
|
+
* lookahead. Readouts remain perceived; integration and interpolation retain the existing body model's limits.
|
|
19
|
+
* Direct helpers retain caller-supplied modifiers and default body parameters unless given other parameters.
|
|
20
|
+
* Existing bleeding, illness and healing run in the copy, so an
|
|
16
21
|
* open wound can read as being spent, and death in the forecast reads as fully spent. The term is absolute
|
|
17
22
|
* (see `bodyForecastTerm`). It does not plan, search routes, schedule rests on the way or
|
|
18
23
|
* predict injuries, and it is not a calibrated estimate of human anticipation. Every number is an engineering
|
|
19
24
|
* default. 2.8.0: an offer may carry its own thresholds (`Affordance.forecastAt`, from The Glance's night
|
|
20
25
|
* keepers); offers without it read exactly as before.
|
|
21
26
|
*/
|
|
22
|
-
import { type BodyForecastSpan, type BodyPerceptionContext } from '../body/index.ts';
|
|
27
|
+
import { type BodyForecastSpan, type BodyParams, type BodyPerceptionContext } from '../body/index.ts';
|
|
23
28
|
import type { Affordance, LifeModifiers, Person, Term } from '../types.ts';
|
|
24
29
|
export declare const FORECAST_DEFAULTS: {
|
|
25
30
|
/** Worst perceived readout during a follow-on from which the forecast starts to weigh. */
|
|
@@ -41,7 +46,7 @@ export declare function forecastThresholds(aff: Pick<Affordance, 'forecastAt'>):
|
|
|
41
46
|
spentAt: number;
|
|
42
47
|
};
|
|
43
48
|
/** The person's forecast for an offer: the act, then its follow-on spans. Empty without `followedBy`. Pure. */
|
|
44
|
-
export declare function bodyForecastFor(p: Person, aff: Affordance, mods: LifeModifiers, perception?: BodyPerceptionContext): BodyForecastSpan[];
|
|
49
|
+
export declare function bodyForecastFor(p: Person, aff: Affordance, mods: LifeModifiers, perception?: BodyPerceptionContext, params?: BodyParams): BodyForecastSpan[];
|
|
45
50
|
/**
|
|
46
51
|
* The `forecast:body` term for an offer, or undefined (no follow-on, or not expected to weigh). Absolute by
|
|
47
52
|
* design: it weighs being in that state *while doing* the follow-on, so a person already sleepy or thirsty is
|
|
@@ -49,7 +54,7 @@ export declare function bodyForecastFor(p: Person, aff: Affordance, mods: LifeMo
|
|
|
49
54
|
* costs more than staying home). A resting baseline was tried and rejected: thirst and sleepiness rise at rest
|
|
50
55
|
* too, which cancelled the very case the forecast exists for. Pure.
|
|
51
56
|
*/
|
|
52
|
-
export declare function bodyForecastTerm(p: Person, aff: Affordance, mods: LifeModifiers, perception?: BodyPerceptionContext): Term | undefined;
|
|
57
|
+
export declare function bodyForecastTerm(p: Person, aff: Affordance, mods: LifeModifiers, perception?: BodyPerceptionContext, params?: BodyParams): Term | undefined;
|
|
53
58
|
/** A first-person line for the forecast (narration only); `at` is the offer's thresholds (2.8.0, default as before). */
|
|
54
59
|
export declare function forecastLine(spans: readonly BodyForecastSpan[], at?: {
|
|
55
60
|
comfortAt: number;
|
|
@@ -11,8 +11,13 @@
|
|
|
11
11
|
* current effort; only a person with the opt-in fatigue store (2.6.0, `enableFatigueStore`) carries accumulated
|
|
12
12
|
* exertion, so only then does a long climb by itself leave them more spent for the descent; unfelt
|
|
13
13
|
* sleep debt stays unfelt in the forecast; an open fast's damping of hunger and thirst applies (2.6.0) as it is
|
|
14
|
-
* now, held for the whole forecast even if the fast would end during it
|
|
15
|
-
*
|
|
14
|
+
* now, held for the whole forecast even if the fast would end during it. By default host surroundings are not
|
|
15
|
+
* applied. Q26: explicit per-call conditioned forecasts instead hold current age, pregnancy and ambient
|
|
16
|
+
* modifiers AND ambient body parameters through the bounded horizon (four follow-on spans, 1440 minutes).
|
|
17
|
+
* This is a frozen current-conditions approximation: no future weather, pregnancy progression or world
|
|
18
|
+
* lookahead. Readouts remain perceived; integration and interpolation retain the existing body model's limits.
|
|
19
|
+
* Direct helpers retain caller-supplied modifiers and default body parameters unless given other parameters.
|
|
20
|
+
* Existing bleeding, illness and healing run in the copy, so an
|
|
16
21
|
* open wound can read as being spent, and death in the forecast reads as fully spent. The term is absolute
|
|
17
22
|
* (see `bodyForecastTerm`). It does not plan, search routes, schedule rests on the way or
|
|
18
23
|
* predict injuries, and it is not a calibrated estimate of human anticipation. Every number is an engineering
|
|
@@ -52,7 +57,7 @@ const smooth = (a, b, x) => {
|
|
|
52
57
|
return t * t * (3 - 2 * t);
|
|
53
58
|
};
|
|
54
59
|
/** The person's forecast for an offer: the act, then its follow-on spans. Empty without `followedBy`. Pure. */
|
|
55
|
-
export function bodyForecastFor(p, aff, mods, perception) {
|
|
60
|
+
export function bodyForecastFor(p, aff, mods, perception, params = BODY_DEFAULTS) {
|
|
56
61
|
const follow = aff.followedBy;
|
|
57
62
|
if (!Array.isArray(follow) || follow.length === 0 || !p.body.alive)
|
|
58
63
|
return [];
|
|
@@ -83,7 +88,7 @@ export function bodyForecastFor(p, aff, mods, perception) {
|
|
|
83
88
|
load: { effort: clamp01(f.effort), focus: clamp01(f.focus ?? 0), mode: 'awake' },
|
|
84
89
|
});
|
|
85
90
|
}
|
|
86
|
-
return forecastBody(p, spans, mods,
|
|
91
|
+
return forecastBody(p, spans, mods, params, 30, perception);
|
|
87
92
|
}
|
|
88
93
|
/**
|
|
89
94
|
* The `forecast:body` term for an offer, or undefined (no follow-on, or not expected to weigh). Absolute by
|
|
@@ -92,8 +97,8 @@ export function bodyForecastFor(p, aff, mods, perception) {
|
|
|
92
97
|
* costs more than staying home). A resting baseline was tried and rejected: thirst and sleepiness rise at rest
|
|
93
98
|
* too, which cancelled the very case the forecast exists for. Pure.
|
|
94
99
|
*/
|
|
95
|
-
export function bodyForecastTerm(p, aff, mods, perception) {
|
|
96
|
-
const spans = bodyForecastFor(p, aff, mods, perception).slice(1);
|
|
100
|
+
export function bodyForecastTerm(p, aff, mods, perception, params = BODY_DEFAULTS) {
|
|
101
|
+
const spans = bodyForecastFor(p, aff, mods, perception, params).slice(1);
|
|
97
102
|
if (spans.length === 0)
|
|
98
103
|
return undefined;
|
|
99
104
|
const D = FORECAST_DEFAULTS;
|
package/dist/sim/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './longrun.ts';
|
|
2
|
-
export
|
|
2
|
+
export { acceptJoint, addPerson, birth, type Community, type CommunityState, communityState, createCommunity, declineJoint, interruptPerson, interrupts, type JointProposal, jointSuccessChance, type LifecourseOptions, mirrorAffordance, nextEventAt, preview, proposeJoint, runSilent, SIM_DEFAULTS, type SilentRun, type SimEvent, type SimEventKind, type StepOptions, sharesPlace, standingHeard, stepCommunity, tellDeath, type World, } from './sim.ts';
|