auto resolve existance
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export const CHIBIS: Chibi[] = [
|
|||||||
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,
|
id: '238df3e7-3003-4471-91f5-a7ecf3151e18' as ChibiId,
|
||||||
@@ -48,6 +48,6 @@ export const CHIBIS: Chibi[] = [
|
|||||||
constitution: 1000,
|
constitution: 1000,
|
||||||
power: 1000,
|
power: 1000,
|
||||||
maintenanceCals: 0,
|
maintenanceCals: 0,
|
||||||
state: EChibiStateName.Idle
|
currentStateName: EChibiStateName.Idle
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -13,8 +13,11 @@ export type ChibiInteraction<T = null> = {
|
|||||||
payload: T;
|
payload: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResolutionFunction = (interaction: ChibiInteraction<any>) => ChibiState;
|
type InteractionResolutionFunction = (interaction: ChibiInteraction<any>) => ChibiState;
|
||||||
type InteractionRecord = Partial<Record<EChibiInteraction, ResolutionFunction>>;
|
type InteractionRecord = Partial<Record<EChibiInteraction, InteractionResolutionFunction>>;
|
||||||
|
|
||||||
|
type ResolutionFunction = () => ChibiState | undefined;
|
||||||
|
type ResolutionMap = { [key in EChibiStateName]: ResolutionFunction | undefined }
|
||||||
|
|
||||||
const MAX_TIME_AWAKE: number = 10;
|
const MAX_TIME_AWAKE: number = 10;
|
||||||
|
|
||||||
@@ -38,7 +41,6 @@ export class Aperio implements IBrain {
|
|||||||
private lastConsumedFoods: string[] = [];
|
private lastConsumedFoods: string[] = [];
|
||||||
private preferredFoods: string[] = [];
|
private preferredFoods: string[] = [];
|
||||||
|
|
||||||
private state: ChibiState = STATES[this.defaultState];
|
|
||||||
private interactionMap: InteractionMap = {
|
private interactionMap: InteractionMap = {
|
||||||
[EChibiStateName.Sleeping]: {
|
[EChibiStateName.Sleeping]: {
|
||||||
[EChibiInteraction.WakeUp]: (interaction: ChibiInteraction): ChibiState => this.wakeUp(interaction),
|
[EChibiInteraction.WakeUp]: (interaction: ChibiInteraction): ChibiState => this.wakeUp(interaction),
|
||||||
@@ -58,27 +60,45 @@ export class Aperio implements IBrain {
|
|||||||
[EChibiStateName.Depressed]: undefined,
|
[EChibiStateName.Depressed]: undefined,
|
||||||
[EChibiStateName.Tired]: undefined
|
[EChibiStateName.Tired]: undefined
|
||||||
}
|
}
|
||||||
|
private 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
|
||||||
|
}
|
||||||
|
|
||||||
|
get state(): ChibiState {
|
||||||
|
return STATES[this.chibi.currentStateName];
|
||||||
|
}
|
||||||
|
|
||||||
init(chibi: Chibi, randomService: RandomService): void {
|
init(chibi: Chibi, randomService: RandomService): void {
|
||||||
this.randomService = randomService;
|
this.randomService = randomService;
|
||||||
this.chibi = chibi;
|
this.chibi = chibi;
|
||||||
this.state = STATES[chibi.state];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exist(): void {
|
exist(): void {
|
||||||
this.timeInCurrentState++;
|
this.timeInCurrentState++;
|
||||||
//this sucks, resolve should be generic
|
const resolution = this.matchResolution(this.resolutionMap, STATES[this.chibi.currentStateName]);
|
||||||
//stuff into an existMap which contains the resolve functions
|
if (resolution) {
|
||||||
//then find correct function to execute the same way we do for interactions
|
const newState = resolution();
|
||||||
this.resolveAwake();
|
if (newState && newState != STATES[this.chibi.currentStateName]) {
|
||||||
this.resolveSleeping();
|
this.changeState(newState);
|
||||||
this.resolveGrumbling();
|
}
|
||||||
this.resolveEating();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveInteraction(interaction: ChibiInteraction): void {
|
resolveInteraction(interaction: ChibiInteraction): void {
|
||||||
this.timeSinceLastInteraction = 0;
|
this.timeSinceLastInteraction = 0;
|
||||||
const resolution = this.matchInteraction(this.interactionMap, interaction.name, STATES[this.chibi.state]);
|
const resolution = this.matchInteraction(this.interactionMap, interaction.name, STATES[this.chibi.currentStateName]);
|
||||||
console.log('resolution', resolution);
|
console.log('resolution', resolution);
|
||||||
console.log(`${this.chibi.name} should ${interaction.name} with payload: ${interaction.payload}`);
|
console.log(`${this.chibi.name} should ${interaction.name} with payload: ${interaction.payload}`);
|
||||||
if (resolution) {
|
if (resolution) {
|
||||||
@@ -90,7 +110,7 @@ export class Aperio implements IBrain {
|
|||||||
return isState(this.state, EChibiStateName.Awake);
|
return isState(this.state, EChibiStateName.Awake);
|
||||||
}
|
}
|
||||||
|
|
||||||
matchInteraction(map: InteractionMap, interaction: EChibiInteraction, state: ChibiState): ResolutionFunction | undefined {
|
matchInteraction(map: InteractionMap, interaction: EChibiInteraction, state: ChibiState): InteractionResolutionFunction | undefined {
|
||||||
const directMatch = map?.[state.name]?.[interaction];
|
const directMatch = map?.[state.name]?.[interaction];
|
||||||
if (directMatch) {
|
if (directMatch) {
|
||||||
return directMatch;
|
return directMatch;
|
||||||
@@ -101,53 +121,61 @@ export class Aperio implements IBrain {
|
|||||||
return undefined;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// 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++;
|
|
||||||
|
|
||||||
if (this.timeInCurrentState % 10 === 0) {
|
if (this.timeInCurrentState % 10 === 0) {
|
||||||
this.saddenedByNeglect(this.timeSinceLastInteraction, SADNESS_FROM_NEGLECT);
|
this.saddenedByNeglect(this.timeSinceLastInteraction, SADNESS_FROM_NEGLECT);
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hasBeenAwakeFor > MAX_TIME_AWAKE) {
|
|
||||||
this.changeState(STATE_SLEEPING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.hasBeenAwakeFor > MAX_TIME_AWAKE) {
|
||||||
|
return STATE_SLEEPING;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveSleeping(): void {
|
resolveSleeping(): ChibiState | undefined {
|
||||||
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)) {
|
return STATE_AWAKE;
|
||||||
this.changeState(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) {
|
return STATE_SLEEPING;
|
||||||
this.changeState(STATE_SLEEPING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveEating(): void {
|
resolveEating(): ChibiState | undefined {
|
||||||
if (isState(this.state, EChibiStateName.Eating)) {
|
console.log(`${this.chibi.name} is eating. ${this.timeInCurrentState}`);
|
||||||
console.log(`${this.chibi.name} is eating.`);
|
if (this.timeInCurrentState > MAX_DURATION_EATING) {
|
||||||
if (this.timeInCurrentState > MAX_DURATION_EATING) {
|
return STATE_IDLE;
|
||||||
this.changeState(STATES[this.previousState]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -163,8 +191,7 @@ export class Aperio implements IBrain {
|
|||||||
|
|
||||||
private changeState(state: ChibiState): void {
|
private changeState(state: ChibiState): void {
|
||||||
this.previousState = this.state.name;
|
this.previousState = this.state.name;
|
||||||
this.state = state;
|
this.chibi.currentStateName = state.name;
|
||||||
this.chibi.state = this.state.name;
|
|
||||||
this.timeInCurrentState = 0;
|
this.timeInCurrentState = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,7 +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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ 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 = {
|
||||||
|
|||||||
Reference in New Issue
Block a user