Fix the numbers

This commit is contained in:
Pyrex 2025-02-23 16:23:54 -08:00
parent 5ab3778074
commit 81f498c804
12 changed files with 83 additions and 38 deletions

View File

@ -106,6 +106,7 @@ export type SuccessorOption = {
name: string;
title: string;
template: Thrall;
nImprovements: number;
note: string | null; // ex "already a vampire"
stats: Record<Stat, number>;
talents: Record<Stat, number>;

View File

@ -206,7 +206,9 @@ export class HuntMode {
this.floatingPlayer = this.floatingPlayer.offset(displacement);
this.velocity = dxy;
// let friction do it
getPlayerProgress().spendBlood(displacement.distance(new Point(0, 0)) * 10);
if (this.map.imposesBloodCosts) {
getPlayerProgress().spendBlood(displacement.distance(new Point(0, 0)) * 10 / 3);
}
}
#updateFov() {

View File

@ -34,6 +34,7 @@ const BASIC_PLAN = Grid.createGridFromMultilineString(`
export function generateManor(): LoadedNewMap {
let map = new LoadedNewMap("manor", BASIC_PLAN.size);
map.imposesBloodCosts = false;
let thralls = getThralls().getAll();
for (let y = 0; y < BASIC_PLAN.size.h; y++) {

View File

@ -15,8 +15,8 @@ import {
import { getPlayerProgress } from "./playerprogress.ts";
import { ItemStage } from "./thralls.ts";
const WIDTH = 21;
const HEIGHT = 21;
const WIDTH = 19;
const HEIGHT = 19;
const MIN_VAULTS = 1;
const MAX_VAULTS = 2;
@ -24,7 +24,7 @@ const NUM_VAULT_TRIES = 90;
const NUM_ROOM_TRIES = 90;
const NUM_STAIRCASE_TRIES = 90;
const NUM_STAIRCASES_DESIRED = 3;
const NUM_ROOMS_DESIRED = 4;
const NUM_ROOMS_DESIRED = 1;
const EXTRA_CONNECTOR_CHANCE = 0.15;
const WINDING_PERCENT = 50;

View File

@ -30,6 +30,7 @@ export class LoadedNewMap {
#id: string;
#size: Size;
#entrance: Point | null;
#imposesBloodCosts: boolean;
#architecture: Grid<Architecture>;
#pickups: Grid<Pickup | null>;
#provinces: Grid<string | null>; // TODO: Does this just duplicate zoneLabels
@ -40,6 +41,7 @@ export class LoadedNewMap {
this.#id = id;
this.#size = size;
this.#entrance = null;
this.#imposesBloodCosts = true;
this.#architecture = new Grid<Architecture>(size, () => Architecture.Wall);
this.#pickups = new Grid<Pickup | null>(size, () => null);
this.#provinces = new Grid<string | null>(size, () => null);
@ -58,6 +60,14 @@ export class LoadedNewMap {
return this.#entrance;
}
set imposesBloodCosts(value: boolean) {
this.#imposesBloodCosts = value;
}
get imposesBloodCosts() {
return this.#imposesBloodCosts;
}
get size(): Size {
return this.#size;
}

View File

@ -201,7 +201,7 @@ export class StatPickupCallbacks {
}
get cost(): number {
return 100;
return 30;
}
obtain() {
@ -248,7 +248,7 @@ export class ExperiencePickupCallbacks {
constructor() {}
get cost(): number {
return 100;
return 30;
}
obtain() {
@ -319,7 +319,9 @@ export class LadderPickup {
update() {}
onClick(): boolean {
getPlayerProgress().addBlood(1000);
if (getHuntMode().map.imposesBloodCosts) {
getPlayerProgress().addBlood(100); // this used to award 1k; 100 now is equivalent to what 300 blood used to be
}
initHuntMode(new HuntMode(getHuntMode().depth + 1, generateMap()));
return false;
}

View File

@ -5,6 +5,7 @@ import { getThralls, ItemStage, LifeStage, Thrall } from "./thralls.ts";
export class PlayerProgress {
#name: string;
#thrallTemplate: number;
#nImprovements: number;
#stats: Record<Stat, number>;
#talents: Record<Stat, number>;
#isInPenance: boolean;
@ -22,6 +23,7 @@ export class PlayerProgress {
constructor(asSuccessor: SuccessorOption, withWish: Wish | null) {
this.#name = asSuccessor.name;
this.#thrallTemplate = asSuccessor.template.id;
this.#nImprovements = asSuccessor.nImprovements;
this.#stats = { ...asSuccessor.stats };
this.#talents = { ...asSuccessor.talents };
this.#isInPenance = asSuccessor.inPenance;
@ -53,12 +55,16 @@ export class PlayerProgress {
return { id: this.#thrallTemplate };
}
get nImprovements(): number {
return this.#nImprovements;
}
get isInPenance(): boolean {
return this.#isInPenance;
}
refill() {
this.#blood = 2000;
this.#blood = 1000;
let learnableSkills = []; // TODO: Also include costing info
for (let skill of getSkills()

View File

@ -122,7 +122,7 @@ class Scorer {
vampiricSkills,
mortalServants,
};
let successorOptions = generateSuccessors(0, penance); // TODO: generate nImprovements from mortalServants and the player's bsae improvements
let successorOptions = generateSuccessors(getPlayerProgress().nImprovements + 2, penance); // TODO: generate nImprovements from mortalServants and the player's bsae improvements
let wishOptions = generateWishes(penance);
let progenerateVerb = penance ? "Repent" : "Progenerate";

View File

@ -38,16 +38,22 @@ class SkillsTable {
}
computeCost(skill: Skill) {
const _STAT_TO_TRIPS: Record<Stat, number> = {
"AGI": 1/7.2, // 8.4 is what I measured, but this seems very overpriced in practice
"INT": 1/5.4,
"CHA": 1/4.8,
"PSI": 1/7.0,
};
let data = this.get(skill);
let governingStatValue = 0;
for (let stat of data.governing.stats.values()) {
governingStatValue +=
getPlayerProgress().getStat(stat) / data.governing.stats.length;
getPlayerProgress().getStat(stat) * _STAT_TO_TRIPS[stat] / data.governing.stats.length;
}
if (data.governing.flipped) {
governingStatValue = -governingStatValue + 10;
governingStatValue = -governingStatValue + 1;
}
let mult = getCostMultiplier(getPlayerProgress().getWish(), skill);
@ -94,7 +100,7 @@ function geomInterpolate(
return lowOut * Math.pow(highOut / lowOut, proportion);
}
type Difficulty = 0 | 1 | 1.25 | 2 | 3;
type Difficulty = -0.25 | -0.125 | 0 | 1 | 1.25 | 2 | 3;
type GoverningTemplate = {
stats: Stat[];
note: string;
@ -158,34 +164,46 @@ function governing(
let cost: number;
let mortalServantValue: number;
switch (difficulty) {
case -0.25:
underTarget = 0.0;
target = 3.9;
cost = 50;
mortalServantValue = 1;
break;
case -0.125:
underTarget = 0.25;
target = 4.25;
cost = 50;
mortalServantValue = 1;
break;
case 0:
underTarget = 5;
target = 15;
underTarget = 0.5;
target = 4.5;
cost = 50;
mortalServantValue = 1;
break;
case 1:
underTarget = 15;
target = 40;
cost = 100;
underTarget = 4;
target = 10;
cost = 50;
mortalServantValue = 2;
break;
case 1.25:
underTarget = 17;
target = 42;
cost = 100;
underTarget = 5;
target = 12;
cost = 50;
mortalServantValue = 2;
break;
case 2:
underTarget = 30;
target = 70;
cost = 125;
underTarget = 10;
target = 18;
cost = 75;
mortalServantValue = 3;
break;
case 3:
underTarget = 50;
target = 100;
cost = 150;
underTarget = 14;
target = 23;
cost = 100;
mortalServantValue = 10;
break;
}
@ -247,7 +265,7 @@ export let bat3 = table.add({
});
export let stealth0 = table.add({
governing: governing("stealth", 0),
governing: governing("stealth", -0.25),
profile: {
name: "Be Quiet",
description:
@ -284,7 +302,7 @@ export let stealth3 = table.add({
});
export let charm0 = table.add({
governing: governing("charm", 0),
governing: governing("charm", -0.125),
profile: {
name: "Flatter",
description:

View File

@ -10,6 +10,7 @@ import { openingScene } from "./openingscene.ts";
import { generateName } from "./namegen.ts";
import { photogenicThralls } from "./thralls.ts";
import { choose } from "./utils.ts";
import {generateSuccessor} from "./successors.ts";
const N_TURNS: number = 9;
@ -34,6 +35,7 @@ export class StateManager {
{
name: generateName(),
template: choose(photogenicThralls),
nImprovements: 0,
title: "",
note: null,
stats: { AGI: 10, INT: 10, CHA: 10, PSI: 10 },

View File

@ -37,6 +37,7 @@ export function generateSuccessorFromPlayer(): SuccessorOption {
let successor = {
name: progress.name,
template: progress.template,
nImprovements: progress.nImprovements - 2,
title: "Penitent",
note: "Failed at Master's bidding",
stats: { ...progress.getStats() },
@ -78,8 +79,9 @@ export function generateSuccessor(nImprovements: number): SuccessorOption {
talents[choose(ALL_STATS)] += 1;
},
];
let nTotalImprovements = nImprovements + 5;
for (let i = 0; i < nTotalImprovements; i++) {
let nTotalImprovements = nImprovements;
let mult = 1;
for (let i = 0; i < nTotalImprovements * mult; i++) {
let improvement =
improvements[Math.floor(Math.random() * improvements.length)];
improvement();
@ -91,6 +93,7 @@ export function generateSuccessor(nImprovements: number): SuccessorOption {
return {
name,
template,
nImprovements,
title,
note,
stats,

View File

@ -140,7 +140,7 @@ export let thrallParty = table.add({
'"Oh, that? Yeah, I won it." And then lost it, apparently.\n\nHe\'s elated. He will never leave.',
rewardMessage: "Garrett showers you with INT!",
rewardCallback: (spawn) => {
for (let i = 0; i < 30; i++) {
for (let i = 0; i < 12; i++) {
spawn("INT");
}
},
@ -216,7 +216,7 @@ export let thrallLore = table.add({
"Lupin looks at his own reflection -- with interest, confusion, dismissal, and then deep satisfaction. He loves it. He will never leave.",
rewardMessage: "Lupin showers you with AGI!",
rewardCallback: (spawn) => {
for (let i = 0; i < 30; i++) {
for (let i = 0; i < 12; i++) {
spawn("AGI");
}
},
@ -289,10 +289,10 @@ export let thrallBat = table.add({
'Monica salivates. "This is... this is... simply exquisite!"\n\nShe is happy. She will never leave.',
rewardMessage: "Monica showers you with CHA and INT!",
rewardCallback: (spawn) => {
for (let i = 0; i < 15; i++) {
for (let i = 0; i < 8; i++) {
spawn("CHA");
}
for (let i = 0; i < 15; i++) {
for (let i = 0; i < 4; i++) {
spawn("INT");
}
},
@ -365,7 +365,7 @@ export let thrallCharm = table.add({
"Renfield inhales sharply and widens his stance, trying to hide his physical reaction to your face. He is elated and will never leave.",
rewardMessage: "Renfield showers you with PSI!",
rewardCallback: (spawn) => {
for (let i = 0; i < 24; i++) {
for (let i = 0; i < 12; i++) {
spawn("PSI");
}
},
@ -439,10 +439,10 @@ export let thrallStealth = table.add({
"\"That? That's not mine.\" But she wants it. Now it's hers. She will never leave.",
rewardMessage: "Narthyss showers you with CHA and AGI!",
rewardCallback: (spawn) => {
for (let i = 0; i < 15; i++) {
for (let i = 0; i < 8; i++) {
spawn("CHA");
}
for (let i = 0; i < 15; i++) {
for (let i = 0; i < 4; i++) {
spawn("AGI");
}
},
@ -516,7 +516,7 @@ export let thrallStare = table.add({
"Ridley admires the gear but -- to your surprise -- refuses to jam it into its brain.\n\nThe pup is elated and will never leave.",
rewardMessage: "Ridley showers you with EXP!",
rewardCallback: (spawn) => {
for (let i = 0; i < 10; i++) {
for (let i = 0; i < 12; i++) {
spawn("EXP");
}
},