textadv
Version:
Text Adventures generator from Markdown files
102 lines • 3.46 kB
JavaScript
import { Project } from "./types.js";
import { generateInputVariations, removeDiacritics } from "./utils.js";
export class Engine {
constructor(project) {
this.project = project;
}
static fromJSON(jsonProject) {
const project = Project.fromJSON(jsonProject);
return new Engine(project);
}
start() {
return {
roomIndex: this.project.initialRoomIndex,
output: [],
flags: {},
gameover: false
};
}
getRoomIntro(roomIndex) {
const room = this.project.getChild(roomIndex);
return [`[${room.name.trim()}]`, ...room.intro];
}
input(str, state) {
const newState = Object.assign({}, state);
newState.output = [];
const room = this.project.getChild(state.roomIndex);
if (!room) {
throw new Error(`invalid room ${state.roomIndex}`);
}
const codes = room.onInput.concat(this.project.onInput);
for (const code of codes) {
if (this.matchesOn(str, code.on)) {
let done = true;
for (const op of code.ops) {
const success = this.runOp(op, newState);
if (!success) {
done = false;
break;
}
}
if (done) {
break;
}
}
}
return newState;
}
matchesOn(str, on) {
str = removeDiacritics(str).trim().replace(/ +/g, ' ').toLocaleLowerCase();
on = removeDiacritics(on).trim().replace(/ +/g, ' ').toLocaleLowerCase();
const variations = generateInputVariations(on);
for (const variation of variations) {
if (variation.endsWith('*')) {
if (variation === '*') {
return true;
}
const codeOnStart = variation.replace('*', '').trim();
if (str.substring(0, codeOnStart.length) === codeOnStart) {
return true;
}
}
if (str === variation) {
return true;
}
}
return false;
}
runOp(op, state) {
var _a;
switch (op.cmd) {
case "print":
state.output.push(String(op.params[0]));
break;
case "check-room":
state.output.push(...this.getRoomIntro(state.roomIndex));
break;
case "goto":
const roomIndex = (_a = this.project.getChildById(String(op.params[0]))) === null || _a === void 0 ? void 0 : _a.index;
if (roomIndex === undefined) {
throw new Error(`could not find room "${op.params[0]}"`);
}
state.roomIndex = roomIndex;
break;
case "set":
state.flags[op.params[0]] = 1;
break;
case "clear":
state.flags[op.params[0]] = 0;
break;
case "zero":
return !state.flags[op.params[0]];
case "notzero":
return !!state.flags[op.params[0]];
case "continue":
return false;
default:
throw new Error(`invalid op ${op.cmd}`);
}
return true;
}
}
//# sourceMappingURL=engine.js.map