Compare commits

..

3 Commits

Author SHA1 Message Date
3faab5e206 basic brain 2026-03-30 16:31:19 +02:00
d2435eee7f auto resolve existance 2026-03-30 16:10:31 +02:00
5858e2808d use interaction resolve matching 2026-03-27 20:03:50 +01:00
12 changed files with 321 additions and 162 deletions

View File

@@ -1,4 +1,4 @@
<div class="bg-red-100 w-full max-w-[1024px] aspect-square"> <div class="bg-red-100 w-full max-w-[1024px] aspect-square">
<div class="text-lg text-primary-700">{{ chibi().state }}</div> <div class="text-lg text-primary-700">{{ chibi().currentStateName }}</div>
<canvas class="w-full h-full" #canvas></canvas> <canvas class="w-full h-full" #canvas></canvas>
</div> </div>

View File

@@ -1,7 +1,14 @@
import { Chibi, ChibiId } from "../../types/chibi/chibi"; import { Chibi, ChibiId, ChibiStatBar } from "../../types/chibi/chibi";
import { EChibiName } from "../../types/chibi/chibi-name"; import { EChibiName } from "../../types/chibi/chibi-name";
import { EChibiStateName } from "../../types/chibi/chibi-state-name"; import { EChibiStateName } from "../../types/chibi/chibi-state-name";
export const statBar = (current: number, max: number): ChibiStatBar => {
return {
current,
max
}
}
export const MAX_STAT_VALUE: number = 100000; export const MAX_STAT_VALUE: number = 100000;
export const CHIBIS: Chibi[] = [ export const CHIBIS: Chibi[] = [
@@ -12,16 +19,35 @@ export const CHIBIS: Chibi[] = [
spritePath: '', spritePath: '',
experience: 0, experience: 0,
unlocked: true, unlocked: true,
happyness: MAX_STAT_VALUE, happyness: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
health: MAX_STAT_VALUE, health: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
hunger: MAX_STAT_VALUE, hunger: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
boredom: MAX_STAT_VALUE, boredom: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
energy: MAX_STAT_VALUE, energy: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
attentionSpan: 1000, attentionSpan: 1000,
recoveryRate: 1000, recoveryRate: 1000,
constitution: 1000, constitution: 1000,
power: 1000, power: 1000,
maintenanceCals: 0, maintenanceCals: 0,
state: EChibiStateName.Sleeping currentStateName: EChibiStateName.Sleeping
},
{
id: '238df3e7-3003-4471-91f5-a7ecf3151e18' as ChibiId,
name: EChibiName.Caethya,
iconPath: '',
spritePath: '',
experience: 0,
unlocked: true,
happyness: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
health: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
hunger: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
boredom: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
energy: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
attentionSpan: 1000,
recoveryRate: 1000,
constitution: 1000,
power: 1000,
maintenanceCals: 0,
currentStateName: EChibiStateName.Idle
}, },
]; ];

View File

@@ -0,0 +1,91 @@
import { Chibi } from "../../types/chibi/chibi";
import { EChibiInteraction } from "../../types/chibi/chibi-interaction";
import { ChibiState, STATES } from "../../types/chibi/chibi-state";
import { EChibiStateName } from "../../types/chibi/chibi-state-name";
import { RandomService } from "../random.service";
import { IBrain } from "./brain";
export type InteractionMap = { [key in EChibiStateName]: InteractionRecord | undefined }
export type ChibiInteraction<T = null> = {
name: EChibiInteraction;
payload: T;
}
export type InteractionResolutionFunction = (interaction: ChibiInteraction<any>) => ChibiState;
export type InteractionRecord = Partial<Record<EChibiInteraction, InteractionResolutionFunction>>;
export type ResolutionFunction = () => ChibiState | undefined;
export type ResolutionMap = { [key in EChibiStateName]: ResolutionFunction | undefined }
export abstract class BasicBrain implements IBrain {
protected randomService!: RandomService;
protected chibi!: Chibi;
protected readonly defaultState: EChibiStateName = EChibiStateName.Sleeping;
protected hasBeenAwakeFor: number = 0;
protected timeSinceLastInteraction: number = 0;
protected timeInCurrentState: number = 0;
protected abstract interactionMap: InteractionMap;
protected abstract resolutionMap: ResolutionMap;
get state(): ChibiState {
return STATES[this.chibi.currentStateName];
}
init(chibi: Chibi, randomService: RandomService): void {
this.randomService = randomService;
this.chibi = chibi;
}
exist(): void {
this.timeInCurrentState++;
const resolution = this.matchResolution(this.resolutionMap, STATES[this.chibi.currentStateName]);
if (resolution) {
const newState = resolution();
if (newState && newState != STATES[this.chibi.currentStateName]) {
this.changeState(newState);
}
}
}
resolveInteraction(interaction: ChibiInteraction): void {
this.timeSinceLastInteraction = 0;
const resolution = this.matchInteraction(this.interactionMap, interaction.name, STATES[this.chibi.currentStateName]);
console.log('resolution', resolution);
console.log(`${this.chibi.name} should ${interaction.name} with payload: ${interaction.payload}`);
if (resolution) {
this.changeState(resolution(interaction));
}
}
matchInteraction(map: InteractionMap, interaction: EChibiInteraction, state: ChibiState): InteractionResolutionFunction | undefined {
const directMatch = map?.[state.name]?.[interaction];
if (directMatch) {
return directMatch;
}
if (state.parent) {
return this.matchInteraction(map, interaction, state.parent);
}
return undefined;
}
matchResolution(map: ResolutionMap, state: ChibiState): ResolutionFunction | undefined {
const directMatch = map?.[state.name];
if (directMatch) {
return directMatch;
}
if (state.parent) {
return this.matchResolution(map, state.parent);
}
return undefined;
}
protected changeState(state: ChibiState): void {
this.chibi.currentStateName = state.name;
this.timeInCurrentState = 0;
}
};

View File

@@ -1,15 +1,20 @@
import { EChibiName } from "../../types/chibi/chibi-name"; import { EChibiName } from "../../types/chibi/chibi-name";
import { IBrain } from "./brain"; import { IBrain } from "./brain";
import { Aperio } from "./brains/aperio.brain"; import { Aperio } from "./brains/aperio.brain";
import { Caethya } from "./brains/caethya.brain";
import { Haetor } from "./brains/haetor.brain";
const APERIO = new Aperio(); const APERIO = new Aperio();
const CAETHYA = new Caethya();
const HAETOR = new Haetor();
export const BRAIN_MAP: Record<EChibiName, IBrain> = { export const BRAIN_MAP: Record<EChibiName, IBrain> = {
[EChibiName.Aperio]: APERIO, [EChibiName.Aperio]: APERIO,
[EChibiName.Basra]: APERIO, [EChibiName.Basra]: APERIO,
[EChibiName.Caethya]: APERIO, [EChibiName.Caethya]: CAETHYA,
[EChibiName.Eos]: APERIO, [EChibiName.Eos]: APERIO,
[EChibiName.Evina]: APERIO, [EChibiName.Evina]: APERIO,
[EChibiName.Haetor]: HAETOR,
[EChibiName.Sol]: APERIO, [EChibiName.Sol]: APERIO,
[EChibiName.Sybil]: APERIO, [EChibiName.Sybil]: APERIO,
[EChibiName.Vinera]: APERIO [EChibiName.Vinera]: APERIO

View File

@@ -1,6 +1,6 @@
import { Chibi } from "../../types/chibi/chibi"; import { Chibi } from "../../types/chibi/chibi";
import { RandomService } from "../random.service"; import { RandomService } from "../random.service";
import { ChibiInteraction } from "./brains/aperio.brain"; import { ChibiInteraction } from "./basic.brain";
export interface IBrain { export interface IBrain {

View File

@@ -1,18 +1,9 @@
import { Chibi } from "../../../types/chibi/chibi";
import { EChibiInteraction } from "../../../types/chibi/chibi-interaction"; import { EChibiInteraction } from "../../../types/chibi/chibi-interaction";
import { ChibiState, isState, STATE_AWAKE, STATE_EATING, STATE_GRUMBLING, STATE_IDLE, STATE_SLEEPING, STATES } from "../../../types/chibi/chibi-state"; import { ChibiState, STATE_AWAKE, STATE_EATING, STATE_GRUMBLING, STATE_IDLE, STATE_SLEEPING } from "../../../types/chibi/chibi-state";
import { EChibiStateName } from "../../../types/chibi/chibi-state-name"; import { EChibiStateName } from "../../../types/chibi/chibi-state-name";
import { Food } from "../../../types/food"; import { Food } from "../../../types/food";
import { RandomOutcome, RandomService } from "../../random.service"; import { RandomOutcome, } from "../../random.service";
import { IBrain } from "../brain"; import { BasicBrain, ChibiInteraction, InteractionMap, ResolutionMap } from "../basic.brain";
export type ChibiInteraction<T = null> = {
name: EChibiInteraction;
payload: T;
}
type ResolutionFunction = (interaction: ChibiInteraction<any>) => ChibiState;
type InteractionRecord = Partial<Record<EChibiInteraction, ResolutionFunction>>;
const MAX_TIME_AWAKE: number = 10; const MAX_TIME_AWAKE: number = 10;
@@ -22,22 +13,12 @@ const SADNESS_FROM_NEGLECT: number = 50;
const MAX_DURATION_GRUMBLE: number = 1; const MAX_DURATION_GRUMBLE: number = 1;
const MAX_DURATION_EATING: number = 1; const MAX_DURATION_EATING: number = 1;
export class Aperio implements IBrain { export class Aperio extends BasicBrain {
private randomService!: RandomService;
private chibi!: Chibi;
private readonly defaultState: EChibiStateName = EChibiStateName.Sleeping;
private previousState: EChibiStateName = this.defaultState;
private hasBeenAwakeFor: number = 0;
private timeSinceLastInteraction: number = 0;
private timeInCurrentState: number = 0;
private lastConsumedFoods: string[] = []; private lastConsumedFoods: string[] = [];
private preferredFoods: string[] = []; private preferredFoods: string[] = [];
private state: ChibiState = STATES[this.defaultState]; protected override interactionMap: InteractionMap = {
private interactionMap: { [key in EChibiStateName]: InteractionRecord | undefined } = {
[EChibiStateName.Sleeping]: { [EChibiStateName.Sleeping]: {
[EChibiInteraction.WakeUp]: (interaction: ChibiInteraction): ChibiState => this.wakeUp(interaction), [EChibiInteraction.WakeUp]: (interaction: ChibiInteraction): ChibiState => this.wakeUp(interaction),
}, },
@@ -56,43 +37,26 @@ export class Aperio implements IBrain {
[EChibiStateName.Depressed]: undefined, [EChibiStateName.Depressed]: undefined,
[EChibiStateName.Tired]: undefined [EChibiStateName.Tired]: undefined
} }
protected override resolutionMap: ResolutionMap = {
init(chibi: Chibi, randomService: RandomService): void { [EChibiStateName.Sleeping]: (): ChibiState | undefined => this.resolveSleeping(),
this.randomService = randomService; [EChibiStateName.Awake]: (): ChibiState | undefined => this.resolveAwake(),
this.chibi = chibi; [EChibiStateName.Snoring]: undefined,
this.state = STATES[chibi.state]; [EChibiStateName.Nightmare]: undefined,
} [EChibiStateName.Grumbling]: (): ChibiState | undefined => this.resolveGrumbling(),
[EChibiStateName.Bored]: undefined,
exist(): void { [EChibiStateName.Idle]: undefined,
this.timeInCurrentState++; [EChibiStateName.Exited]: undefined,
this.resolveAwake(); [EChibiStateName.Fighting]: undefined,
this.resolveSleeping(); [EChibiStateName.Eating]: (): ChibiState | undefined => this.resolveEating(),
this.resolveGrumbling(); [EChibiStateName.Hungry]: undefined,
this.resolveEating(); [EChibiStateName.Depressed]: undefined,
} [EChibiStateName.Tired]: undefined
resolveInteraction(interaction: ChibiInteraction): void {
this.timeSinceLastInteraction = 0;
const specificMatch: ResolutionFunction | undefined = this.interactionMap[this.state.name]?.[interaction.name];
const awakeMatch: ResolutionFunction | undefined = this.interactionMap[EChibiStateName.Awake]?.[interaction.name];
const asleepMatch: ResolutionFunction | undefined = this.interactionMap[EChibiStateName.Sleeping]?.[interaction.name];
const resolution: ResolutionFunction | undefined = specificMatch || (this.isAwake() ? awakeMatch : asleepMatch);
console.log(`specific match: ${specificMatch}`);
console.log(`${this.chibi.name} should ${interaction.name} with payload: ${interaction.payload}`);
if (resolution) {
this.changeState(resolution(interaction));
}
}
isAwake(): boolean {
return isState(this.state, EChibiStateName.Awake);
} }
// resolvers // resolvers
// functions which auitomatically resolve based on the existence cycle // functions which automatically resolve based on the existence cycle
resolveAwake(): void { resolveAwake(): ChibiState | undefined {
if (this.isAwake()) {
console.log(`${this.chibi.name} is awake.`); console.log(`${this.chibi.name} is awake.`);
this.timeSinceLastInteraction++; this.timeSinceLastInteraction++;
this.hasBeenAwakeFor++; this.hasBeenAwakeFor++;
@@ -102,56 +66,48 @@ export class Aperio implements IBrain {
} }
if (this.hasBeenAwakeFor > MAX_TIME_AWAKE) { if (this.hasBeenAwakeFor > MAX_TIME_AWAKE) {
this.changeState(STATE_SLEEPING); return STATE_SLEEPING;
}
} }
return undefined;
} }
increaseHappyness(increase: number): void { resolveSleeping(): ChibiState | undefined {
console.log(`${this.chibi.name} happyness increases.`);
this.chibi.happyness = this.chibi.happyness + increase;
}
saddenedByNeglect(neglectTime: number, sadness: number): void {
console.log(`${this.chibi.name} happyness decreases.`);
this.chibi.happyness = this.chibi.happyness - (neglectTime * sadness);
}
resolveSleeping(): void {
if (isState(this.state, EChibiStateName.Sleeping)) {
console.log(`${this.chibi.name} is sleeping.`); console.log(`${this.chibi.name} is sleeping.`);
this.hasBeenAwakeFor = 0; this.hasBeenAwakeFor = 0;
this.increaseHappyness(HAPPINESS_FROM_SLEEP); this.increaseHappyness(HAPPINESS_FROM_SLEEP);
const awakeChance = this.randomService.obtainRandom(2048); const awakeChance = this.randomService.obtainRandom(2048);
if (awakeChance.matchesChance(1)) { if (awakeChance.matchesChance(1)) {
this.changeState(STATE_AWAKE); return STATE_AWAKE;
}
} }
return undefined;
} }
resolveGrumbling(): void { resolveGrumbling(): ChibiState | undefined {
if (isState(this.state, EChibiStateName.Grumbling)) { console.log(`${this.chibi.name} is grumbling. ${this.timeInCurrentState}`);
console.log(`${this.chibi.name} is grumbling.`);
if (this.timeInCurrentState > MAX_DURATION_GRUMBLE) { if (this.timeInCurrentState > MAX_DURATION_GRUMBLE) {
this.changeState(STATE_SLEEPING); return STATE_SLEEPING;
}
}
} }
resolveEating(): void { return undefined;
if (isState(this.state, EChibiStateName.Eating)) { }
console.log(`${this.chibi.name} is eating.`);
resolveEating(): ChibiState | undefined {
console.log(`${this.chibi.name} is eating. ${this.timeInCurrentState}`);
if (this.timeInCurrentState > MAX_DURATION_EATING) { if (this.timeInCurrentState > MAX_DURATION_EATING) {
this.changeState(STATES[this.previousState]); return STATE_IDLE;
}
} }
return undefined;
} }
private changeState(state: ChibiState): void {
this.previousState = this.state.name; private increaseHappyness(increase: number): void {
this.state = state; console.log(`${this.chibi.name} happyness increases.`);
this.chibi.state = this.state.name; this.chibi.happyness.current = this.chibi.happyness.current + increase;
this.timeInCurrentState = 0; }
private saddenedByNeglect(neglectTime: number, sadness: number): void {
console.log(`${this.chibi.name} happyness decreases.`);
this.chibi.happyness.current = this.chibi.happyness.current - (neglectTime * sadness);
} }
/* /*

View File

@@ -0,0 +1,36 @@
import { EChibiStateName } from "../../../types/chibi/chibi-state-name";
import { BasicBrain, InteractionMap, ResolutionMap } from "../basic.brain";
export class Caethya extends BasicBrain {
protected override interactionMap: InteractionMap = {
[EChibiStateName.Sleeping]: undefined,
[EChibiStateName.Awake]: undefined,
[EChibiStateName.Snoring]: undefined,
[EChibiStateName.Nightmare]: undefined,
[EChibiStateName.Grumbling]: undefined,
[EChibiStateName.Bored]: undefined,
[EChibiStateName.Idle]: undefined,
[EChibiStateName.Exited]: undefined,
[EChibiStateName.Fighting]: undefined,
[EChibiStateName.Eating]: undefined,
[EChibiStateName.Hungry]: undefined,
[EChibiStateName.Depressed]: undefined,
[EChibiStateName.Tired]: undefined
};
protected override resolutionMap: ResolutionMap = {
[EChibiStateName.Sleeping]: undefined,
[EChibiStateName.Snoring]: undefined,
[EChibiStateName.Nightmare]: undefined,
[EChibiStateName.Grumbling]: undefined,
[EChibiStateName.Awake]: undefined,
[EChibiStateName.Bored]: undefined,
[EChibiStateName.Idle]: undefined,
[EChibiStateName.Exited]: undefined,
[EChibiStateName.Fighting]: undefined,
[EChibiStateName.Eating]: undefined,
[EChibiStateName.Hungry]: undefined,
[EChibiStateName.Depressed]: undefined,
[EChibiStateName.Tired]: undefined
};
}

View File

@@ -0,0 +1,36 @@
import { EChibiStateName } from "../../../types/chibi/chibi-state-name";
import { BasicBrain, InteractionMap, ResolutionMap } from "../basic.brain";
export class Haetor extends BasicBrain {
protected override interactionMap: InteractionMap = {
[EChibiStateName.Sleeping]: undefined,
[EChibiStateName.Awake]: undefined,
[EChibiStateName.Snoring]: undefined,
[EChibiStateName.Nightmare]: undefined,
[EChibiStateName.Grumbling]: undefined,
[EChibiStateName.Bored]: undefined,
[EChibiStateName.Idle]: undefined,
[EChibiStateName.Exited]: undefined,
[EChibiStateName.Fighting]: undefined,
[EChibiStateName.Eating]: undefined,
[EChibiStateName.Hungry]: undefined,
[EChibiStateName.Depressed]: undefined,
[EChibiStateName.Tired]: undefined
};
protected override resolutionMap: ResolutionMap = {
[EChibiStateName.Sleeping]: undefined,
[EChibiStateName.Snoring]: undefined,
[EChibiStateName.Nightmare]: undefined,
[EChibiStateName.Grumbling]: undefined,
[EChibiStateName.Awake]: undefined,
[EChibiStateName.Bored]: undefined,
[EChibiStateName.Idle]: undefined,
[EChibiStateName.Exited]: undefined,
[EChibiStateName.Fighting]: undefined,
[EChibiStateName.Eating]: undefined,
[EChibiStateName.Hungry]: undefined,
[EChibiStateName.Depressed]: undefined,
[EChibiStateName.Tired]: undefined
};
}

View File

@@ -14,6 +14,7 @@
} }
</div> </div>
<div class="h-1/3 min-h-20 bg-primary-300 relative"> <div class="h-1/3 min-h-20 bg-primary-300 relative">
@if (chibi()) {
<ff-food-pantry <ff-food-pantry
[isVisible]="shownMenu == EInteractionMenuState.Pantry" [isVisible]="shownMenu == EInteractionMenuState.Pantry"
(onClose)="closeMenu()" (onClose)="closeMenu()"
@@ -43,14 +44,15 @@
lang.game.actions.inviteVisitor lang.game.actions.inviteVisitor
}}</ff-button> }}</ff-button>
@if (isAwake()) { @if (isAwake()) {
<ff-button (click)="interact(EChibiInteraction.WakeUp)">{{
lang.game.actions.wakeUp
}}</ff-button>
} @else {
<ff-button (click)="interact(EChibiInteraction.PutToSleep)">{{ <ff-button (click)="interact(EChibiInteraction.PutToSleep)">{{
lang.game.actions.putToSleep lang.game.actions.putToSleep
}}</ff-button> }}</ff-button>
} @else {
<ff-button (click)="interact(EChibiInteraction.WakeUp)">{{
lang.game.actions.wakeUp
}}</ff-button>
}
</div>
} }
</div> </div>
</div> </div>
</div>

View File

@@ -12,12 +12,12 @@ import { IBrain } from '../../logic/chibi-behaviour/brain';
import { BRAIN_MAP } from '../../logic/chibi-behaviour/brain-map'; import { BRAIN_MAP } from '../../logic/chibi-behaviour/brain-map';
import { TranslateableComponent } from '../../components/translateable.component'; import { TranslateableComponent } from '../../components/translateable.component';
import { Food } from '../../types/food'; import { Food } from '../../types/food';
import { interval, Subscribable, Subscription } from 'rxjs'; import { interval, Subscription } from 'rxjs';
import { RandomService } from '../../logic/random.service'; import { RandomService } from '../../logic/random.service';
import { ChibiInteraction } from '../../logic/chibi-behaviour/brains/aperio.brain';
import { isState, STATES } from '../../types/chibi/chibi-state'; import { isState, STATES } from '../../types/chibi/chibi-state';
import { EChibiStateName } from '../../types/chibi/chibi-state-name'; import { EChibiStateName } from '../../types/chibi/chibi-state-name';
import { VisitorListComponent } from "../../components/interaction-menus/visitor-list/visitor-list.component"; import { VisitorListComponent } from "../../components/interaction-menus/visitor-list/visitor-list.component";
import { ChibiInteraction } from '../../logic/chibi-behaviour/basic.brain';
enum EInteractionMenuState { enum EInteractionMenuState {
Neutral, Neutral,
@@ -70,7 +70,7 @@ export class InteractionsComponent extends TranslateableComponent implements OnD
} }
public isAwake(): boolean { public isAwake(): boolean {
return isState(STATES[this.chibi().state], EChibiStateName.Awake); return isState(STATES[this.chibi().currentStateName], EChibiStateName.Awake);
} }
public interact(interaction: EChibiInteraction, item?: Food): void { public interact(interaction: EChibiInteraction, item?: Food): void {
@@ -78,6 +78,7 @@ export class InteractionsComponent extends TranslateableComponent implements OnD
this.brain.resolveInteraction({ name: interaction, payload: item } as ChibiInteraction<Food>); this.brain.resolveInteraction({ name: interaction, payload: item } as ChibiInteraction<Food>);
} }
public openFoodPantry(): void { public openFoodPantry(): void {
this.interactionMenuState.set(EInteractionMenuState.Pantry); this.interactionMenuState.set(EInteractionMenuState.Pantry);
} }

View File

@@ -4,6 +4,7 @@ export enum EChibiName {
Caethya = 'Caethya', Caethya = 'Caethya',
Eos = 'Eos', Eos = 'Eos',
Evina = 'Evina', Evina = 'Evina',
Haetor = 'Haetor',
Sol = 'Sol', Sol = 'Sol',
Sybil = 'Sybil', Sybil = 'Sybil',
Vinera = 'Vinera' Vinera = 'Vinera'

View File

@@ -8,7 +8,7 @@ export type ChibiPreview = {
id: ChibiId; id: ChibiId;
name: EChibiName; name: EChibiName;
iconPath: string; iconPath: string;
happyness: number; happyness: ChibiStatBar;
level: number; level: number;
}; };
@@ -19,15 +19,15 @@ export type Chibi = {
spritePath: string; spritePath: string;
experience: number; experience: number;
unlocked: boolean; unlocked: boolean;
state: EChibiStateName; currentStateName: EChibiStateName;
} & ChibiWellnessStats & ChibiTraits; } & ChibiWellnessStats & ChibiTraits;
export type ChibiWellnessStats = { export type ChibiWellnessStats = {
happyness: number; happyness: ChibiStatBar;
health: number; health: ChibiStatBar;
hunger: number; //feed them hunger: ChibiStatBar; //feed them
boredom: number; //do activities to alleviate boredom boredom: ChibiStatBar; //do activities to alleviate boredom
energy: number; //let them rest energy: ChibiStatBar; //let them rest
}; };
export type ChibiTraits = { export type ChibiTraits = {
@@ -37,3 +37,8 @@ export type ChibiTraits = {
power: number; //how much damage they deal power: number; //how much damage they deal
maintenanceCals: number; //how quickly they get hungry maintenanceCals: number; //how quickly they get hungry
}; };
export type ChibiStatBar = {
current: number;
max: number;
}