Skill rebalancing, analytic data tracking

This commit is contained in:
Pyrex 2025-02-08 20:35:36 -08:00
parent 5ecafa0d4a
commit bd48a26adf
7 changed files with 55 additions and 16 deletions

View File

@ -13,6 +13,7 @@ export type SkillGoverning = {
cost: number, cost: number,
note: string, note: string,
scoring: SkillScoring, scoring: SkillScoring,
mortalServantValue: number,
}; };
export type SkillProfile = { export type SkillProfile = {
name: string, name: string,

View File

@ -20,9 +20,9 @@ export class EndgameModal {
this.#drawpile = new DrawPile(); this.#drawpile = new DrawPile();
this.#page = 0; this.#page = 0;
this.show(getScorer().pickEnding()); this.#ending = null;
// debug // this.show(getScorer().pickEnding());
} }
get isShown(): boolean { get isShown(): boolean {
@ -58,17 +58,35 @@ export class EndgameModal {
D.drawText(rank, new Point(WIDTH / 2, 64), FG_BOLD, {alignX: AlignX.Center}) D.drawText(rank, new Point(WIDTH / 2, 64), FG_BOLD, {alignX: AlignX.Center})
D.drawText("You have achieved a DOMICILE STATUS of:", new Point(0, 96), FG_TEXT) D.drawText("You have achieved a DOMICILE STATUS of:", new Point(0, 96), FG_TEXT)
D.drawText(domicile, new Point(WIDTH / 2, 128), FG_BOLD, {alignX: AlignX.Center}) D.drawText(domicile, new Point(WIDTH / 2, 128), FG_BOLD, {alignX: AlignX.Center})
D.drawText("where you live with many friends.", new Point(0, 160), FG_TEXT) // TODO: Vary this text let whereLabel =
mortalServants >= 25 ? "where you live with many friends." :
mortalServants >= 1 ? "where you live with a couple of friends." :
"where you live completely alone.";
D.drawText(whereLabel, new Point(0, 160), FG_TEXT)
D.drawText("You have achieved:", new Point(0, 192), FG_TEXT) D.drawText("You have achieved:", new Point(0, 192), FG_TEXT)
let itemsPurloinedText = itemsPurloined == 1 ? "item purloined" : "items purloined";
let vampiricSkillsText = vampiricSkills == 1 ? "vampiric skill" : "vampiric skills";
let mortalServantsText = mortalServants == 1 ? "mortal servant" : "mortal servants";
let itemsPurloinedSpcr = itemsPurloined == 1 ? " " : " ";
let vampiricSkillsSpcr = vampiricSkills == 1 ? " " : " ";
let mortalServantsSpcr = mortalServants == 1 ? " " : " ";
D.drawText( D.drawText(
`${itemsPurloined} items purloined\n${vampiricSkills} vampiric skills\n${mortalServants} mortal servants`, `${itemsPurloined} ${itemsPurloinedText}\n${vampiricSkills} ${vampiricSkillsText}\n${mortalServants} ${mortalServantsText}`,
new Point(WIDTH / 2, 224), FG_TEXT, {alignX: AlignX.Center} new Point(WIDTH / 2, 224), FG_TEXT, {alignX: AlignX.Center}
) )
D.drawText( D.drawText(
`${itemsPurloined} \n${vampiricSkills} \n${mortalServants} `, `${itemsPurloined} ${itemsPurloinedSpcr}\n${vampiricSkills} ${vampiricSkillsSpcr}\n${mortalServants} ${mortalServantsSpcr}`,
new Point(WIDTH / 2, 224), FG_BOLD, {alignX: AlignX.Center} new Point(WIDTH / 2, 224), FG_BOLD, {alignX: AlignX.Center}
); );
D.drawText("That feels like a lot!", new Point(0, 288), FG_TEXT) // TODO: Vary this text let msg = "That's pretty dreadful."
if (mortalServants >= 10) {
msg = "That's more than zero."
}
if (mortalServants >= 30) {
msg = "That feels like a lot!"
}
D.drawText(msg, new Point(0, 288), FG_TEXT)
D.drawText("Your reign continues unimpeded from the shadows. It is now time to", new Point(0, 320), FG_TEXT, {forceWidth: WIDTH}) D.drawText("Your reign continues unimpeded from the shadows. It is now time to", new Point(0, 320), FG_TEXT, {forceWidth: WIDTH})
}) })
addButton( addButton(

View File

@ -89,6 +89,7 @@ export class HuntMode {
let amount = 1; let amount = 1;
present.content = {type: "empty"}; present.content = {type: "empty"};
getPlayerProgress().add(stat, amount); getPlayerProgress().add(stat, amount);
getPlayerProgress().purloinItem();
} }
if (present.content.type == "resourcePickup") { if (present.content.type == "resourcePickup") {
@ -96,6 +97,7 @@ export class HuntMode {
switch(resource) { switch(resource) {
case "EXP": case "EXP":
getPlayerProgress().addExperience(25); getPlayerProgress().addExperience(25);
getPlayerProgress().purloinItem();
break; break;
default: default:
throw `not sure how to add ${resource}` throw `not sure how to add ${resource}`

View File

@ -5,6 +5,7 @@ export class PlayerProgress {
#stats: Record<Stat, number> #stats: Record<Stat, number>
#exp: number; #exp: number;
#blood: number #blood: number
#itemsPurloined: number
#skillsLearned: number[] // use the raw ID representation for indexOf #skillsLearned: number[] // use the raw ID representation for indexOf
#untrimmedSkillsAvailable: Skill[] #untrimmedSkillsAvailable: Skill[]
@ -17,6 +18,7 @@ export class PlayerProgress {
}; };
this.#exp = 0; this.#exp = 0;
this.#blood = 0; this.#blood = 0;
this.#itemsPurloined = 0;
this.#skillsLearned = []; this.#skillsLearned = [];
this.#untrimmedSkillsAvailable = [] this.#untrimmedSkillsAvailable = []
@ -74,6 +76,14 @@ export class PlayerProgress {
return true; return true;
} }
purloinItem() {
this.#itemsPurloined += 1;
}
getItemsPurloined() {
return this.#itemsPurloined
}
add(stat: Stat, amount: number) { add(stat: Stat, amount: number) {
if (amount != Math.floor(amount)) { if (amount != Math.floor(amount)) {
throw `stat increment must be integer: ${amount}` throw `stat increment must be integer: ${amount}`

View File

@ -13,13 +13,21 @@ class Scorer {
let learnedSkills = getPlayerProgress().getLearnedSkills(); let learnedSkills = getPlayerProgress().getLearnedSkills();
let scores: Record<string, number> = {}; let scores: Record<string, number> = {};
let itemsPurloined = getPlayerProgress().getItemsPurloined();
let vampiricSkills = 0;
let mortalServants = itemsPurloined / 10;
for (const skill of learnedSkills.values()) { for (const skill of learnedSkills.values()) {
let data = getSkills().get(skill); let data = getSkills().get(skill);
for (let [category, number] of Object.entries(data.governing.scoring)) { for (let [category, number] of Object.entries(data.governing.scoring)) {
scores[category] = (scores[category] ?? 0) + number; scores[category] = (scores[category] ?? 0) + number;
} }
mortalServants += data.governing.mortalServantValue;
vampiricSkills += 1;
} }
mortalServants = Math.floor(mortalServants);
// NOTE: This approach isn't efficient but it's easy to understand // NOTE: This approach isn't efficient but it's easy to understand
// and it allows me to arbitrate ties however I want // and it allows me to arbitrate ties however I want
let runningScores: Record<string, number> = {...scores}; let runningScores: Record<string, number> = {...scores};
@ -79,11 +87,11 @@ class Scorer {
// TODO: Analytics tracker // TODO: Analytics tracker
let analytics = { let analytics = {
itemsPurloined: 0, itemsPurloined,
vampiricSkills: 0, vampiricSkills,
mortalServants: 0, mortalServants,
} }
let successorOptions = generateSuccessors(0); // TODO: generate nImprovements from score let successorOptions = generateSuccessors(0); // TODO: generate nImprovements from mortalServants and the player's bsae improvements
let wishOptions = generateWishes(); let wishOptions = generateWishes();
return { return {

View File

@ -102,11 +102,12 @@ function governing(track: Track, difficulty: Difficulty): SkillGoverning {
let underTarget: number let underTarget: number
let target: number let target: number
let cost: number let cost: number
let mortalServantValue: number;
switch(difficulty) { switch(difficulty) {
case 0: underTarget = 5; target = 15; cost = 50; break; case 0: underTarget = 5; target = 15; cost = 50; mortalServantValue = 1; break;
case 1: underTarget = 15; target = 40; cost = 100; break; case 1: underTarget = 15; target = 40; cost = 100; mortalServantValue = 2; break;
case 2: underTarget = 100; target = 150; cost = 250; break; case 2: underTarget = 30; target = 70; cost = 125; mortalServantValue = 3; break;
case 3: underTarget = 175; target = 250; cost = 500; break; case 3: underTarget = 50; target = 100; cost = 150; mortalServantValue = 10; break;
} }
return { return {
stats: template.stats, stats: template.stats,
@ -115,6 +116,7 @@ function governing(track: Track, difficulty: Difficulty): SkillGoverning {
cost: cost, cost: cost,
note: template.note, note: template.note,
scoring: template.scoring, scoring: template.scoring,
mortalServantValue: mortalServantValue
} }
} }

View File

@ -2,8 +2,6 @@ import {ALL_STATS, Stat, SuccessorOption} from "./datatypes.ts";
import {generateName, generateTitle} from "./namegen.ts"; import {generateName, generateTitle} from "./namegen.ts";
import {choose} from "./utils.ts"; import {choose} from "./utils.ts";
// TODO: Take a "number of improvements", use that to improve
// each successor N times
export function generateSuccessors(nImprovements: number): SuccessorOption[] { export function generateSuccessors(nImprovements: number): SuccessorOption[] {
let options = []; let options = [];
while (options.length < 3) { while (options.length < 3) {