You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
2.6 KiB
TypeScript
101 lines
2.6 KiB
TypeScript
import { ObjectType, GameObject } from "./GameState"
|
|
import NounPosition from "./NounPosition"
|
|
import Verb from "./Verb"
|
|
import Game from "../Game"
|
|
|
|
export enum TokenType {
|
|
Expression = 'expression',
|
|
Literal = 'literal'
|
|
}
|
|
|
|
export class ParsedToken {
|
|
readonly type : TokenType
|
|
|
|
constructor(type : TokenType) {
|
|
this.type = type
|
|
}
|
|
}
|
|
|
|
export class ParsedTokenLiteral extends ParsedToken {
|
|
readonly word : string
|
|
|
|
constructor(word : string) {
|
|
super(TokenType.Literal)
|
|
this.word = word
|
|
}
|
|
}
|
|
|
|
export class ParsedTokenExpression extends ParsedToken {
|
|
readonly itemType : ObjectType
|
|
readonly sentencePosition : NounPosition
|
|
readonly name : string
|
|
|
|
constructor(type : ObjectType, position : NounPosition, name : string) {
|
|
super(TokenType.Expression)
|
|
this.itemType = type
|
|
this.sentencePosition = position
|
|
this.name = name
|
|
}
|
|
}
|
|
|
|
export enum ParsingErrorSeverity {
|
|
NotVisible = 0,
|
|
NoSuchObject = 1
|
|
}
|
|
|
|
export type ValidCommandDetails = {isValid: true, command: ParsedCommand, subject: GameObject | null, object: GameObject | null}
|
|
export type InvalidCommandDetails = {isValid: false, command: ParsedCommand, reason: string, severity: ParsingErrorSeverity}
|
|
|
|
export default class ParsedCommand {
|
|
readonly verb : Verb
|
|
private tokens : ParsedToken[] = []
|
|
|
|
constructor(verb : Verb) {
|
|
this.verb = verb
|
|
}
|
|
|
|
prepend(token : ParsedToken) {
|
|
const newCommand = new ParsedCommand(this.verb)
|
|
newCommand.tokens = [token, ...this.tokens]
|
|
return newCommand
|
|
}
|
|
|
|
areNounsValid(game : Game) : ValidCommandDetails | InvalidCommandDetails {
|
|
const nouns = this.tokens.filter(({type}) => type === TokenType.Expression).map(token => token as ParsedTokenExpression)
|
|
|
|
let subject : GameObject | null = null
|
|
let object : GameObject | null = null
|
|
|
|
for(const noun of nouns) {
|
|
let gameObject = game.findObjectByName(noun.name, noun.itemType)
|
|
if(!gameObject)
|
|
return {
|
|
isValid: false,
|
|
command: this,
|
|
reason: `You used the word ${noun.name} as if it was a ${noun.itemType}, but there is no such object`,
|
|
severity: ParsingErrorSeverity.NoSuchObject
|
|
}
|
|
|
|
if(!game.isVisible(gameObject))
|
|
return {
|
|
isValid: false,
|
|
command: this,
|
|
reason: `You cannot see ${noun.name}`,
|
|
severity: ParsingErrorSeverity.NotVisible
|
|
}
|
|
|
|
if(noun.sentencePosition === NounPosition.Subject)
|
|
subject = gameObject
|
|
else
|
|
object = gameObject
|
|
}
|
|
|
|
return {
|
|
isValid: true,
|
|
command: this,
|
|
subject,
|
|
object
|
|
}
|
|
}
|
|
}
|