169 lines
6.3 KiB
TypeScript
169 lines
6.3 KiB
TypeScript
import { EChibiInteraction } from "../../../types/chibi/chibi-interaction";
|
|
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 { Food } from "../../../types/food";
|
|
import { RandomOutcome, } from "../../random.service";
|
|
import { BasicBrain, ChibiInteraction, InteractionMap, ResolutionMap } from "../basic.brain";
|
|
|
|
const MAX_TIME_AWAKE: number = 10;
|
|
|
|
const HAPPINESS_FROM_SLEEP: number = 100;
|
|
const SADNESS_FROM_NEGLECT: number = 50;
|
|
|
|
const MAX_DURATION_GRUMBLE: number = 1;
|
|
const MAX_DURATION_EATING: number = 1;
|
|
|
|
export class Aperio extends BasicBrain {
|
|
|
|
private lastConsumedFoods: string[] = [];
|
|
private preferredFoods: string[] = [];
|
|
|
|
protected override interactionMap: InteractionMap = {
|
|
[EChibiStateName.Sleeping]: {
|
|
[EChibiInteraction.WakeUp]: (interaction: ChibiInteraction): ChibiState => this.wakeUp(interaction),
|
|
},
|
|
[EChibiStateName.Awake]: {
|
|
[EChibiInteraction.Feed]: (interaction: ChibiInteraction<Food>): ChibiState => this.feedTo(interaction),
|
|
},
|
|
[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]: (): ChibiState | undefined => this.resolveSleeping(),
|
|
[EChibiStateName.Awake]: (): ChibiState | undefined => this.resolveAwake(),
|
|
[EChibiStateName.Snoring]: undefined,
|
|
[EChibiStateName.Nightmare]: undefined,
|
|
[EChibiStateName.Grumbling]: (): ChibiState | undefined => this.resolveGrumbling(),
|
|
[EChibiStateName.Bored]: undefined,
|
|
[EChibiStateName.Idle]: undefined,
|
|
[EChibiStateName.Exited]: undefined,
|
|
[EChibiStateName.Fighting]: undefined,
|
|
[EChibiStateName.Eating]: (): ChibiState | undefined => this.resolveEating(),
|
|
[EChibiStateName.Hungry]: undefined,
|
|
[EChibiStateName.Depressed]: undefined,
|
|
[EChibiStateName.Tired]: undefined
|
|
}
|
|
|
|
// resolvers
|
|
// functions which automatically resolve based on the existence cycle
|
|
|
|
resolveAwake(): ChibiState | undefined {
|
|
console.log(`${this.chibi.name} is awake.`);
|
|
this.timeSinceLastInteraction++;
|
|
this.hasBeenAwakeFor++;
|
|
|
|
if (this.timeInCurrentState % 10 === 0) {
|
|
this.saddenedByNeglect(this.timeSinceLastInteraction, SADNESS_FROM_NEGLECT);
|
|
}
|
|
|
|
if (this.hasBeenAwakeFor > MAX_TIME_AWAKE) {
|
|
return STATE_SLEEPING;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
resolveSleeping(): ChibiState | undefined {
|
|
console.log(`${this.chibi.name} is sleeping.`);
|
|
this.hasBeenAwakeFor = 0;
|
|
this.increaseHappyness(HAPPINESS_FROM_SLEEP);
|
|
const awakeChance = this.randomService.obtainRandom(2048);
|
|
if (awakeChance.matchesChance(1)) {
|
|
return STATE_AWAKE;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
resolveGrumbling(): ChibiState | undefined {
|
|
console.log(`${this.chibi.name} is grumbling. ${this.timeInCurrentState}`);
|
|
if (this.timeInCurrentState > MAX_DURATION_GRUMBLE) {
|
|
return STATE_SLEEPING;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
resolveEating(): ChibiState | undefined {
|
|
console.log(`${this.chibi.name} is eating. ${this.timeInCurrentState}`);
|
|
if (this.timeInCurrentState > MAX_DURATION_EATING) {
|
|
return STATE_IDLE;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
|
|
private increaseHappyness(increase: number): void {
|
|
console.log(`${this.chibi.name} happyness increases.`);
|
|
this.chibi.happyness.current = this.chibi.happyness.current + increase;
|
|
}
|
|
|
|
private saddenedByNeglect(neglectTime: number, sadness: number): void {
|
|
console.log(`${this.chibi.name} happyness decreases.`);
|
|
this.chibi.happyness.current = this.chibi.happyness.current - (neglectTime * sadness);
|
|
}
|
|
|
|
/*
|
|
visiting caethya will wake her up and go into lovey-dovey mode
|
|
|
|
pears energy never goes down
|
|
pear will accept fights and enjoys them
|
|
pear will accept walks and enjoys them
|
|
|
|
pear gets offended if you suggest she go to sleep
|
|
|
|
after any interaction she has a 1/4 chance of going to sleep
|
|
*/
|
|
|
|
// interaction functions
|
|
// functions which are triggered by user actions
|
|
|
|
private wakeUp(interaction: ChibiInteraction): ChibiState {
|
|
const wakeUpOutcome: RandomOutcome = this.randomService.obtainRandom(128);
|
|
const willWakeUp: boolean = wakeUpOutcome.matchesChance(1);
|
|
const willGrumble: boolean = wakeUpOutcome.matchesChance(12, 1);
|
|
if (willWakeUp) {
|
|
return STATE_IDLE;
|
|
} else if (willGrumble) {
|
|
return STATE_GRUMBLING;
|
|
}
|
|
return this.state;
|
|
}
|
|
|
|
private feedTo(interaction: ChibiInteraction<Food>): ChibiState {
|
|
console.log(`${this.chibi.name} should eat ${interaction.payload.name}`);
|
|
const foodId = interaction.payload.id;
|
|
if (this.preferredFoods.includes(foodId)) {
|
|
this.eat(interaction.payload);
|
|
return STATE_EATING;
|
|
} else if (this.lastConsumedFoods[0] === foodId && this.lastConsumedFoods[1] === foodId && this.lastConsumedFoods[2] === foodId) {
|
|
console.log(`${this.chibi.name} refuses to eat another ${interaction.payload.name}!`);
|
|
return this.state;
|
|
|
|
}
|
|
this.eat(interaction.payload);
|
|
return STATE_EATING;
|
|
}
|
|
|
|
private eat(food: Food): void {
|
|
this.addToLastEatenFoods(food.id);
|
|
this.increaseHappyness(100);
|
|
}
|
|
|
|
private addToLastEatenFoods(foodId: string): void {
|
|
if (this.lastConsumedFoods.length < 3) {
|
|
this.lastConsumedFoods.push(foodId);
|
|
} else {
|
|
this.lastConsumedFoods = this.lastConsumedFoods.slice(1, 3);
|
|
this.lastConsumedFoods.push(foodId);
|
|
}
|
|
console.log(this.lastConsumedFoods);
|
|
}
|
|
}; |