Files
CharacterGardenStack/charactergarden/app/src/world/applyActions.ts
spencer 998635f542 feat: implement processTurn function to handle turn processing and world state updates
refactor: remove legacy types.ts file and update frontend to use new contracts

feat: add applyActions function to manage action application and world state mutation

chore: remove empty .gitkeep file from sqlite data directory

refactor: update frontend App component to align with new API contracts and improve UX

docs: revise project.md to reflect updated architecture and system requirements

docs: update thoughts.md with current status, architecture decisions, and remaining checks
2026-04-24 01:04:17 -04:00

74 lines
1.7 KiB
TypeScript

import { randomUUID } from "node:crypto";
import type { Action } from "../contracts/action";
import type { ValidationResult } from "../contracts/validation";
import type { Entity } from "../contracts/entity";
import type { WorldState } from "../contracts/world";
function cloneWorldState(worldState: WorldState): WorldState {
const entities: Record<string, Entity> = {};
for (const [id, entity] of Object.entries(worldState.entities)) {
entities[id] = {
...entity,
attributes: { ...entity.attributes },
};
}
return {
...worldState,
entities,
metadata: { ...worldState.metadata },
};
}
export function applyActions(
actions: Action[],
results: ValidationResult[],
worldState: WorldState
): WorldState {
const nextState = cloneWorldState(worldState);
for (const result of results) {
if (!result.success) {
continue;
}
const action = actions[result.actionIndex];
if (!action) {
continue;
}
const actor = nextState.entities[action.actorId];
const target = action.targetId ? nextState.entities[action.targetId] : undefined;
switch (action.type) {
case "move":
if (actor && action.targetId) {
actor.attributes.location = action.targetId;
}
break;
case "take":
if (actor && target) {
target.attributes.location = `inventory:${actor.id}`;
if (target.id === "key_1") {
actor.attributes.has_key_1 = true;
}
}
break;
case "open":
if (target) {
target.attributes.open = true;
}
break;
case "inspect":
default:
break;
}
}
nextState.id = randomUUID();
nextState.createdAt = Date.now();
return nextState;
}