Add comments throughout.

This commit is contained in:
2021-05-27 14:47:45 -07:00
parent cc306dbf87
commit e26747cc7c
12 changed files with 211 additions and 83 deletions

View File

@ -1,33 +1,42 @@
/**
* Term.ts contains the type information for parsing user sentences.
*/
import Player from "../Player.ts";
import Scene from "../Scene.ts";
// ActionFn is the signature for functions that contain the logic associated with verbs
// the player uses.
export type ActionFn = (
player: Player,
scene: Scene,
target?: string,
object?: string
) => string;
target?: string, // the target is the target of the action.
object?: string // the object is an item that is used with the action on the target.
) => string; // should return a description of the result for the player.
// Constant is a specific word that the engine knows about. If the player uses a word
// that is not a Constant, then it should be a variable that represents something that
// is defined in the writer's story files.
export interface Constant {
constant: string;
category: Category;
}
export type Category =
| "action"
| "direction"
| "compound"
| "position"
| "interaction";
// Category is a union of the different kinds of Constants.
export type Category = "action" | "direction" | "position" | "interaction";
// Term describes a known word that the player can use. It tells the parse what kinds of
// words can come after it and what it means.
export interface Term {
precedesCategories: Category[];
precedesConstants: Constant[];
category: Category;
constant: string;
canPrecedeVariable: boolean;
precedesCategories: Category[]; // categories of Constant that can follow this Term
precedesConstants: Constant[]; // Constants that can follow this Term
category: Category; // the category of this Terms Constant is part of
constant: string; // the name of the Constant that this Term describes
canPrecedeVariable: boolean; // indicates that what follows might be a variable
}
// ActionTerm extends Term, adding the function needed to execute a verb. It also
// guarentees that the category is "action".
export interface ActionTerm extends Term {
action: ActionFn;
category: "action";

View File

@ -1,15 +1,29 @@
/**
* actions.ts contains the logic for various ActionTerms. Exported should match the
* signature for "ActionFn," which is:
*
* (player: Player, scene: Scene, target?: string, object?: string) => string
*
* The returned string should be a message for the user that describes the result of the
* action.
*/
import type Scene from "../Scene.ts";
import type Player from "../Player.ts";
import type { ApplyEffectArgs, ItemAction } from "../types.ts";
const ITEM_MISSING = "You don't have that.";
const ITEM_MISSING = "I can't find that.";
const ITEM_UNUSABLE = "I don't know how to use that.";
const ITEM_ALREADY_USED = "I already did that.";
// look is what happens when a player uses the "look" verb. It gets a description of the
// scene.
export function look(player: Player, scene: Scene): string {
return scene.look(player.activeEffects, scene.activeEffects);
}
// pickUpItem is what happens when a player uses the "take" verb. It finds an item in the
// scene and, if it's there, moves it into the players inventory.
export function pickUpItem(
player: Player,
scene: Scene,
@ -19,19 +33,29 @@ export function pickUpItem(
return "What do you want me to get?";
}
// remove the item from the scene.
const item = scene.get(target);
// The item was found in the scene...
if (item !== null) {
player.put(item);
player.put(item); // put it in the players inventory.
return "Taken.";
}
return "Taken.";
return ITEM_MISSING;
}
// checkInventory is what happens when a player uses the "inventory" verb. It gets the
// description for what's in the player's inventory.
export function checkInventory(player: Player): string {
return player.look();
}
// use is what happens when a player uses the "use" verb. Different items do different
// things when they are used, so the function needs to figure out what kind of usage an
// item is written for, and then execute that logic with whatever arguments the
// storywriter has provided for that item.
export function use(player: Player, scene: Scene, target?: string): string {
if (!target) {
return "What do you want to use?";
@ -39,10 +63,12 @@ export function use(player: Player, scene: Scene, target?: string): string {
const { inventory } = player;
// if there is no inventory...
if (inventory === null) {
return ITEM_MISSING;
}
// search the inventory for the named item
const item = inventory.find((i) => i.name === target);
if (item === undefined) {
@ -51,6 +77,7 @@ export function use(player: Player, scene: Scene, target?: string): string {
const itemAction = item?.actions["use"];
// The item doesn't have action defined for "use", so it cannot be used.
if (itemAction === undefined) {
return ITEM_UNUSABLE;
}
@ -58,6 +85,8 @@ export function use(player: Player, scene: Scene, target?: string): string {
return executeItemAction(player, scene, itemAction);
}
// executeItemAction figures out what kind of action an item supports and then executes
// the logic for it.
function executeItemAction(
player: Player,
scene: Scene,
@ -71,22 +100,28 @@ function executeItemAction(
}
}
// applyEffect contains the logic for applying an effect to the player or the scene.
function applyEffect(
player: Player,
scene: Scene,
{ applyTo, effect, reverseResult, reversible, result }: ApplyEffectArgs
): string {
const target = applyTo === "player" ? player : scene;
// if true, effect is already present.
const isApplied = target.hasActiveEffect(effect);
if (!reversible && isApplied) {
// effect is present already and can't be reversed
return ITEM_ALREADY_USED;
}
if (isApplied) {
// effect is present...
target.removeEffect(effect);
return reverseResult || result;
} else {
// effect is not present...
target.addEffect(effect);
return result;
}

View File

@ -1,3 +1,8 @@
/**
* terms.ts contains the Terms that describe the Constants that the player can use.
* See Terms.ts for more information about what these terms can be.
*/
import * as actions from "./actions.ts";
import { ActionTerm } from "./Term.ts";