123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /// <reference path="Rulebook.ts" />
- /// <reference path="Rule.ts" />
- /// <reference path="../../Elements/Classes/Say.ts" />
- class Action {
- public static check = new Rulebook<Action>("Check any Action");
- public static carry = new Rulebook<Action>("Carry out any Action");
- public extraChecks : Array<Rulebook<Action>> = [];
- public extraCarries : Array<Rulebook<Action>> = [];
- public _actor : Thing;
- public nouns : Array<Thing> = [];
- public say : Say = new Say();
- public actingAgressively = false;
- public actingSubmissively = false;
- public requiresTurn = true;
- public requiresNoun = true;
- public requiresVisibility = true; // First noun must be visible and in the same room
- public constructor (actor : Thing, ...nouns : Array<any>) {
- this.actor = actor;
- nouns.forEach((value, index, array) => {
- this.setNoun(index, value);
- });
- }
- public async execute () : Promise<Say> {
- this.say = new Say();
- let checkRulebooks = [];
- let carryRulebooks = [];
- let cClass = this.constructor;
- while (cClass != Action) {
- if ((<typeof Action> cClass).check != undefined) {
- checkRulebooks.push((<typeof Action> cClass).check);
- }
- if ((<typeof Action> cClass).carry != undefined) {
- carryRulebooks.push((<typeof Action> cClass).carry);
- }
- cClass = Object.getPrototypeOf(cClass);
- }
- /**
- * Check if action goes through
- */
- let result = await Action.check.execute({
- noun : this
- }, ...checkRulebooks);
- // There are now multiple results! A false result means a fail Check! But it can also return a new action!
- if (result == false) {
- return;
- } else if(result instanceof Action) {
- console.debug(Rulebook.getIndentation() + "[ACTION] Instead of...");
- await result.execute();
- this.say.add(result.say);
- this.nouns = result.nouns;
- return;
- }
- /**
- * Carry Out
- */
- await Action.carry.execute({
- noun : this
- }, ...carryRulebooks);
- return this.say;
- }
- get actor(): Thing {
- return this._actor;
- }
- set actor(value: Thing) {
- this._actor = value;
- }
- public getNoun (n : number) : any {
- if (this.nouns.length > n) {
- return this.nouns[n];
- }
- return undefined;
- }
- public setNoun (n : number, noun : any) {
- while (this.nouns.length < n) {
- this.nouns.push(undefined);
- }
- this.nouns[n] = noun;
- }
- /**
- * Needs to return a string explaining what the player will do if he does this action.
- * For instance, ActionTaking should return something like return "take " + this.nouns[0].getName(),
- * which would read as "take thing".
- * remember that things implement PRINTABLE interface, so you can get their names.
- * @returns {string}
- */
- public getCommandText () {
- return "do";
- }
- /**
- * If an action is stopped, it means it failed so spectacularly that it didn't even begin.
- * Which means if the player is doing it, it'll not take a turn.
- */
- public stop () {
- this.requiresTurn = false;
- }
- }
- // Action.addCarryRule(new Rule({
- // name : "Testing say in actions rule",
- // priority : Rule.PRIORITY_LOWEST,
- // firstPriority : Rule.PRIORITY_LOWEST,
- // code : (rule, rulebook) => {
- // let action = <Action> rulebook.noun;
- // action.say.add("You do nothing all turn. What was the point, really?");
- // }
- // }))
- Action.check.addRule(
- new Rule({
- name : "Check any Action - Requires Noun",
- firstPriority : Rule.PRIORITY_HIGHEST,
- code : (rulebook : RulebookRunner<Action>) => {
- let action = <Action> rulebook.noun;
- if (action.getNoun(0) == undefined) {
- return false;
- }
- },
- conditions : runner => {
- return runner.noun.requiresNoun;
- }
- })
- );
- Action.check.addRule(
- new Rule({
- name : "Check any Action - Requires Visibility",
- code : (rulebook : RulebookRunner<Action>) => {
- let action = <Action> rulebook.noun;
- let actor = action.actor;
- if (!action.getNoun(0).isVisibleTo(actor)) {
- return false;
- }
- },
- conditions : runner => {
- return runner.noun.requiresVisibility;
- }
- })
- );
|