parent
b01bea67f4
commit
64cda38606
@ -0,0 +1,536 @@ |
|||||||
|
import grammar from "./grammar.ohm-bundle"; |
||||||
|
import { |
||||||
|
Affinity, |
||||||
|
ElementalType, |
||||||
|
MarkdownContext, |
||||||
|
MarkdownOutput, |
||||||
|
MeteredResource, |
||||||
|
NumberSign, |
||||||
|
Operands, |
||||||
|
ParseContext, |
||||||
|
Resource, |
||||||
|
UnmeteredResource, |
||||||
|
} from "../model/Messages"; |
||||||
|
import {IterationNode, Node, NonterminalNode, TerminalNode} from "ohm-js"; |
||||||
|
import {CharacterPrivacy, CharacterSide} from "../model/Character"; |
||||||
|
import {ClockMode} from "../model/GameState"; |
||||||
|
|
||||||
|
export const parser = grammar.createSemantics() |
||||||
|
|
||||||
|
export interface ParserNode extends Node { |
||||||
|
element: ElementalType|null |
||||||
|
affinity: Affinity |
||||||
|
sign: NumberSign |
||||||
|
numberValue: number |
||||||
|
identifier: string |
||||||
|
resource: Resource|null |
||||||
|
|
||||||
|
// TODO: Implement all of the things listed below.
|
||||||
|
operands: Operands |
||||||
|
blockTargets: Operands |
||||||
|
blockSources: Operands |
||||||
|
currentValue: number|null |
||||||
|
maxValue: number|null |
||||||
|
textValue: string |
||||||
|
silenced: boolean |
||||||
|
failReason: unknown // TODO: create an enum for this
|
||||||
|
// TODO: create rules for these to describe clocks/timers/items/statuses/characters and implement them
|
||||||
|
nameText: string |
||||||
|
descriptionText: string |
||||||
|
side: CharacterSide |
||||||
|
privacy: CharacterPrivacy |
||||||
|
clockMode: ClockMode |
||||||
|
timerDirection: unknown // TODO: create an enum for this
|
||||||
|
timerDurationMs: number |
||||||
|
|
||||||
|
// TODO: make sure that FP and UP spent gets saved in the appropriate counters
|
||||||
|
evaluate(ctx: ParseContext): ParseContext |
||||||
|
renderMarkdown(ctx: MarkdownContext): MarkdownOutput |
||||||
|
} |
||||||
|
|
||||||
|
parser.addAttribute<ElementalType|null>("element", { |
||||||
|
fireElement(): ElementalType.Fire { |
||||||
|
return ElementalType.Fire |
||||||
|
}, |
||||||
|
waterElement(): ElementalType.Water { |
||||||
|
return ElementalType.Water |
||||||
|
}, |
||||||
|
lightningElement(): ElementalType.Lightning { |
||||||
|
return ElementalType.Lightning |
||||||
|
}, |
||||||
|
iceElement(): ElementalType.Ice { |
||||||
|
return ElementalType.Ice |
||||||
|
}, |
||||||
|
earthElement(): ElementalType.Earth { |
||||||
|
return ElementalType.Earth |
||||||
|
}, |
||||||
|
windElement(): ElementalType.Wind { |
||||||
|
return ElementalType.Wind |
||||||
|
}, |
||||||
|
lightElement(): ElementalType.Light { |
||||||
|
return ElementalType.Light |
||||||
|
}, |
||||||
|
darkElement(): ElementalType.Dark { |
||||||
|
return ElementalType.Dark |
||||||
|
}, |
||||||
|
physicalElement(): ElementalType.Physical { |
||||||
|
return ElementalType.Physical |
||||||
|
}, |
||||||
|
nonElement(): ElementalType.Nonelemental { |
||||||
|
return ElementalType.Nonelemental |
||||||
|
}, |
||||||
|
healingElement(): ElementalType.Healing { |
||||||
|
return ElementalType.Healing |
||||||
|
}, |
||||||
|
elementalType(elementNode: NonterminalNode): ElementalType { |
||||||
|
const element = (elementNode as ParserNode).element |
||||||
|
if (element === null) { |
||||||
|
throw Error("Unexpectedly null element when an element was specified") |
||||||
|
} |
||||||
|
return element |
||||||
|
}, |
||||||
|
DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): ElementalType | null { |
||||||
|
return (elementalType as ParserNode).element |
||||||
|
}, |
||||||
|
DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, elementalType: IterationNode): ElementalType | null { |
||||||
|
return (elementalType as ParserNode).element |
||||||
|
}, |
||||||
|
DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): ElementalType | null { |
||||||
|
return (elementalType as ParserNode).element |
||||||
|
}, |
||||||
|
_iter(...children: Node[]): ElementalType|null { |
||||||
|
if (this.isOptional() && children.length === 0) { |
||||||
|
return null |
||||||
|
} else if (this.isOptional() && children.length === 1) { |
||||||
|
return (children[0] as ParserNode).element |
||||||
|
} else { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} iteration node's element is when there are multiple children`) |
||||||
|
} |
||||||
|
}, |
||||||
|
_nonterminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} nonterminal node's element is`) |
||||||
|
}, |
||||||
|
_terminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} terminal node's element is`) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
parser.addAttribute<Affinity>("affinity", { |
||||||
|
absorbAffinity(): Affinity.Absorbs { |
||||||
|
return Affinity.Absorbs |
||||||
|
}, |
||||||
|
immuneAffinity(): Affinity.Immune { |
||||||
|
return Affinity.Immune |
||||||
|
}, |
||||||
|
resistAffinity(): Affinity.Resistant { |
||||||
|
return Affinity.Resistant |
||||||
|
}, |
||||||
|
vulnerableAffinity(): Affinity.Vulnerable { |
||||||
|
return Affinity.Vulnerable |
||||||
|
}, |
||||||
|
normalAffinity(): Affinity.Normal { |
||||||
|
return Affinity.Normal |
||||||
|
}, |
||||||
|
affinity(affinityNode: NonterminalNode): Affinity { |
||||||
|
return (affinityNode as ParserNode).affinity |
||||||
|
}, |
||||||
|
DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): Affinity { |
||||||
|
return (affinity as ParserNode).affinity |
||||||
|
}, |
||||||
|
DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, elementalType: IterationNode): Affinity { |
||||||
|
return (affinity as ParserNode).affinity |
||||||
|
}, |
||||||
|
DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): Affinity { |
||||||
|
return (affinity as ParserNode).affinity |
||||||
|
}, |
||||||
|
_iter(...children: Node[]): Affinity { |
||||||
|
if (this.isOptional() && children.length === 0) { |
||||||
|
return Affinity.Normal |
||||||
|
} else if (this.isOptional() && children.length === 1) { |
||||||
|
return (children[0] as ParserNode).affinity |
||||||
|
} else { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} iteration node's affinity is when there are multiple children`) |
||||||
|
} |
||||||
|
}, |
||||||
|
_nonterminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} nonterminal node's affinity is`) |
||||||
|
}, |
||||||
|
_terminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} terminal node's affinity is`) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
parser.addAttribute<NumberSign>("sign", { |
||||||
|
deltaOperator(oper: NonterminalNode): NumberSign { |
||||||
|
return (oper as ParserNode).sign |
||||||
|
}, |
||||||
|
plus(): NumberSign.Positive { |
||||||
|
return NumberSign.Positive |
||||||
|
}, |
||||||
|
minus(): NumberSign.Negative { |
||||||
|
return NumberSign.Negative |
||||||
|
}, |
||||||
|
StatusOrItemDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, deltaOperator: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): NumberSign { |
||||||
|
return (deltaOperator as ParserNode).sign |
||||||
|
}, |
||||||
|
StatusOrItemCounterDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, delta: NonterminalNode): NumberSign { |
||||||
|
return (delta as ParserNode).sign |
||||||
|
}, |
||||||
|
_iter(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} iteration node's number sign is`) |
||||||
|
}, |
||||||
|
_nonterminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} nonterminal node's number sign is`) |
||||||
|
}, |
||||||
|
_terminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} terminal node's number sign is`) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
parser.addAttribute<number>("numberValue", { |
||||||
|
integer(digits: IterationNode): number { |
||||||
|
return parseInt(digits.sourceString) |
||||||
|
}, |
||||||
|
Delta(sign: NonterminalNode, integer: NonterminalNode): number { |
||||||
|
const number = (integer as ParserNode).numberValue |
||||||
|
switch ((sign as ParserNode).sign) { |
||||||
|
case NumberSign.Negative: |
||||||
|
return -number |
||||||
|
case NumberSign.Positive: |
||||||
|
return number |
||||||
|
} |
||||||
|
}, |
||||||
|
DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): number { |
||||||
|
return (delta as ParserNode).numberValue |
||||||
|
}, |
||||||
|
DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, elementalType: IterationNode): number { |
||||||
|
return (delta as ParserNode).numberValue |
||||||
|
}, |
||||||
|
DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): number { |
||||||
|
return (delta as ParserNode).numberValue |
||||||
|
}, |
||||||
|
MaxValue(separator: NonterminalNode, integer: NonterminalNode): number { |
||||||
|
return (integer as ParserNode).numberValue; |
||||||
|
}, |
||||||
|
SetValueOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode): number { |
||||||
|
return (integer as ParserNode).numberValue; |
||||||
|
}, |
||||||
|
SetValueOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode, resource: NonterminalNode): number { |
||||||
|
return (integer as ParserNode).numberValue; |
||||||
|
}, |
||||||
|
SetValueOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, integer: NonterminalNode): number { |
||||||
|
return (integer as ParserNode).numberValue; |
||||||
|
}, |
||||||
|
SetMaxOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode): number { |
||||||
|
return (maxvalue as ParserNode).numberValue; |
||||||
|
}, |
||||||
|
SetMaxOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode, resource: NonterminalNode): number { |
||||||
|
return (maxvalue as ParserNode).numberValue; |
||||||
|
}, |
||||||
|
SetMaxOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, maxvalue: NonterminalNode): number { |
||||||
|
return (maxvalue as ParserNode).numberValue; |
||||||
|
}, |
||||||
|
StatusOrItemCounterUnwrapped(x: IterationNode, integer: NonterminalNode): number { |
||||||
|
return (integer as ParserNode).numberValue |
||||||
|
}, |
||||||
|
StatusOrItemCounterWrapped(lParen: TerminalNode, counter: NonterminalNode, rParen: TerminalNode): number { |
||||||
|
return (counter as ParserNode).numberValue |
||||||
|
}, |
||||||
|
StatusOrItemDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, deltaOperator: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): number { |
||||||
|
return (counter as ParserNode).numberValue |
||||||
|
}, |
||||||
|
StatusOrItemCounterDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, delta: NonterminalNode): number { |
||||||
|
return (delta as ParserNode).numberValue |
||||||
|
}, |
||||||
|
StatusOrItemCounterSetOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): number { |
||||||
|
return (counter as ParserNode).numberValue |
||||||
|
}, |
||||||
|
_iter(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} iteration node's number value is`) |
||||||
|
}, |
||||||
|
_nonterminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} nonterminal node's number value is`) |
||||||
|
}, |
||||||
|
_terminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} terminal node's number value is`) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
parser.addAttribute<string>("identifier", { |
||||||
|
identifier(): string { |
||||||
|
return this.sourceString |
||||||
|
}, |
||||||
|
StatusOrItemDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, deltaOperator: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): string { |
||||||
|
return (identifier as ParserNode).identifier |
||||||
|
}, |
||||||
|
StatusOrItemCounterDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, delta: NonterminalNode): string { |
||||||
|
return (identifier as ParserNode).identifier |
||||||
|
}, |
||||||
|
StatusOrItemCounterSetOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): string { |
||||||
|
return (identifier as ParserNode).identifier |
||||||
|
}, |
||||||
|
_iter(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} iteration node's identifier value is`) |
||||||
|
}, |
||||||
|
_nonterminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} nonterminal node's identifier value is`) |
||||||
|
}, |
||||||
|
_terminal(): never { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} terminal node's identifier value is`) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
parser.addAttribute<Resource|null>("resource", { |
||||||
|
BpResource(): MeteredResource.Blood { |
||||||
|
return MeteredResource.Blood |
||||||
|
}, |
||||||
|
FabulaResource(): UnmeteredResource.Fabula { |
||||||
|
return UnmeteredResource.Fabula; |
||||||
|
}, |
||||||
|
HpResource(): MeteredResource.Health { |
||||||
|
return MeteredResource.Health; |
||||||
|
}, |
||||||
|
IpResource(): MeteredResource.Items { |
||||||
|
return MeteredResource.Items; |
||||||
|
}, |
||||||
|
LevelResource(): UnmeteredResource.Level { |
||||||
|
return UnmeteredResource.Level; |
||||||
|
}, |
||||||
|
MaterialsResource(): UnmeteredResource.Materials { |
||||||
|
return UnmeteredResource.Materials; |
||||||
|
}, |
||||||
|
MeteredResource(res: NonterminalNode): MeteredResource { |
||||||
|
const r = (res as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case MeteredResource.Health: |
||||||
|
case MeteredResource.Magic: |
||||||
|
case MeteredResource.Items: |
||||||
|
case MeteredResource.Experience: |
||||||
|
case MeteredResource.Zero: |
||||||
|
case MeteredResource.Turns: |
||||||
|
case MeteredResource.Segments: |
||||||
|
case MeteredResource.Blood: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected unmetered resource in metered resource node") |
||||||
|
} |
||||||
|
}, |
||||||
|
MoneyResource(): UnmeteredResource.Zenit { |
||||||
|
return UnmeteredResource.Zenit; |
||||||
|
}, |
||||||
|
MpResource(): MeteredResource.Magic { |
||||||
|
return MeteredResource.Magic; |
||||||
|
}, |
||||||
|
Resource(res: NonterminalNode): Resource { |
||||||
|
const r = (res as ParserNode).resource; |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
SpResource(type: NonterminalNode): UnmeteredResource.Special|UnmeteredResource.Fabula|UnmeteredResource.Ultima { |
||||||
|
const r = (type as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case UnmeteredResource.Special: |
||||||
|
case UnmeteredResource.Fabula: |
||||||
|
case UnmeteredResource.Ultima: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected non-SP resources in an SP node") |
||||||
|
} |
||||||
|
}, |
||||||
|
SpecialResource(): UnmeteredResource.Special { |
||||||
|
return UnmeteredResource.Special; |
||||||
|
}, |
||||||
|
TpResource(): MeteredResource.Turns { |
||||||
|
return MeteredResource.Turns; |
||||||
|
}, |
||||||
|
UltimaResource(): Resource { |
||||||
|
return UnmeteredResource.Ultima; |
||||||
|
}, |
||||||
|
UnmeteredResource(res: NonterminalNode): UnmeteredResource { |
||||||
|
const r = (res as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case UnmeteredResource.Fabula: |
||||||
|
case UnmeteredResource.Ultima: |
||||||
|
case UnmeteredResource.Zenit: |
||||||
|
case UnmeteredResource.Materials: |
||||||
|
case UnmeteredResource.Special: |
||||||
|
case UnmeteredResource.Level: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected metered resource in unmetered resource node") |
||||||
|
} |
||||||
|
}, |
||||||
|
XpResource(): MeteredResource.Experience { |
||||||
|
return MeteredResource.Experience; |
||||||
|
}, |
||||||
|
ZpResource(): MeteredResource.Zero { |
||||||
|
return MeteredResource.Zero; |
||||||
|
}, |
||||||
|
DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): Resource { |
||||||
|
const r = (resource as ParserNode).resource |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in required resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, elementalType: IterationNode): Resource|null { |
||||||
|
return (resource as ParserNode).resource |
||||||
|
}, |
||||||
|
DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): Resource { |
||||||
|
const r = (resource as ParserNode).resource |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in required resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
SetValueOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode): Resource { |
||||||
|
const r = (resource as ParserNode).resource |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in required resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
SetValueOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode, resource: NonterminalNode): Resource { |
||||||
|
const r = (resource as ParserNode).resource |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in required resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
SetValueOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, integer: NonterminalNode): Resource { |
||||||
|
const r = (resource as ParserNode).resource |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in required resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
SetMaxOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode): MeteredResource { |
||||||
|
const r = (resource as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case MeteredResource.Health: |
||||||
|
case MeteredResource.Magic: |
||||||
|
case MeteredResource.Items: |
||||||
|
case MeteredResource.Experience: |
||||||
|
case MeteredResource.Zero: |
||||||
|
case MeteredResource.Turns: |
||||||
|
case MeteredResource.Segments: |
||||||
|
case MeteredResource.Blood: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected unmetered resource in metered resource node") |
||||||
|
} |
||||||
|
}, |
||||||
|
SetMaxOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode, resource: NonterminalNode): MeteredResource { |
||||||
|
const r = (resource as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case MeteredResource.Health: |
||||||
|
case MeteredResource.Magic: |
||||||
|
case MeteredResource.Items: |
||||||
|
case MeteredResource.Experience: |
||||||
|
case MeteredResource.Zero: |
||||||
|
case MeteredResource.Turns: |
||||||
|
case MeteredResource.Segments: |
||||||
|
case MeteredResource.Blood: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected unmetered resource in metered resource node") |
||||||
|
} |
||||||
|
}, |
||||||
|
SetMaxOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, maxvalue: NonterminalNode): MeteredResource { |
||||||
|
const r = (resource as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case MeteredResource.Health: |
||||||
|
case MeteredResource.Magic: |
||||||
|
case MeteredResource.Items: |
||||||
|
case MeteredResource.Experience: |
||||||
|
case MeteredResource.Zero: |
||||||
|
case MeteredResource.Turns: |
||||||
|
case MeteredResource.Segments: |
||||||
|
case MeteredResource.Blood: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected unmetered resource in metered resource node") |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
_iter(...children: Node[]): Resource|null { |
||||||
|
if (this.isOptional() && children.length === 0) { |
||||||
|
return null |
||||||
|
} else if (this.isOptional() && children.length === 1) { |
||||||
|
return (children[0] as ParserNode).resource |
||||||
|
} else { |
||||||
|
throw Error(`No idea what to say ${this.ctorName} iteration node's resource is when there are multiple children`) |
||||||
|
} |
||||||
|
}, |
||||||
|
SetMeteredOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, value: NonterminalNode): MeteredResource { |
||||||
|
const r = (resource as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case MeteredResource.Health: |
||||||
|
case MeteredResource.Magic: |
||||||
|
case MeteredResource.Items: |
||||||
|
case MeteredResource.Experience: |
||||||
|
case MeteredResource.Zero: |
||||||
|
case MeteredResource.Turns: |
||||||
|
case MeteredResource.Segments: |
||||||
|
case MeteredResource.Blood: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected unmetered resource in metered resource node") |
||||||
|
} |
||||||
|
}, |
||||||
|
SetMeteredOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, value: NonterminalNode, resource: NonterminalNode): MeteredResource { |
||||||
|
const r = (resource as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case MeteredResource.Health: |
||||||
|
case MeteredResource.Magic: |
||||||
|
case MeteredResource.Items: |
||||||
|
case MeteredResource.Experience: |
||||||
|
case MeteredResource.Zero: |
||||||
|
case MeteredResource.Turns: |
||||||
|
case MeteredResource.Segments: |
||||||
|
case MeteredResource.Blood: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected unmetered resource in metered resource node") |
||||||
|
} |
||||||
|
}, |
||||||
|
SetMeteredOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, value: NonterminalNode): MeteredResource { |
||||||
|
const r = (resource as ParserNode).resource; |
||||||
|
switch (r) { |
||||||
|
case MeteredResource.Health: |
||||||
|
case MeteredResource.Magic: |
||||||
|
case MeteredResource.Items: |
||||||
|
case MeteredResource.Experience: |
||||||
|
case MeteredResource.Zero: |
||||||
|
case MeteredResource.Turns: |
||||||
|
case MeteredResource.Segments: |
||||||
|
case MeteredResource.Blood: |
||||||
|
return r |
||||||
|
default: |
||||||
|
throw Error("unexpected unmetered resource in metered resource node") |
||||||
|
} |
||||||
|
}, |
||||||
|
ClearOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, nul: NonterminalNode): Resource { |
||||||
|
const r = (resource as ParserNode).resource |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in required resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
ClearOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, nul: NonterminalNode, resource: NonterminalNode): Resource { |
||||||
|
const r = (resource as ParserNode).resource |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in required resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
ClearOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, nul: NonterminalNode): Resource { |
||||||
|
const r = (resource as ParserNode).resource |
||||||
|
if (r === null) { |
||||||
|
throw Error("unexpected null resource in required resource node") |
||||||
|
} |
||||||
|
return r |
||||||
|
}, |
||||||
|
}) |
@ -0,0 +1,66 @@ |
|||||||
|
import {GameState} from "./GameState"; |
||||||
|
|
||||||
|
export enum ElementalType { |
||||||
|
Fire = "fire", |
||||||
|
Water = "water", |
||||||
|
Lightning = "lightning", |
||||||
|
Ice = "ice", |
||||||
|
Earth = "earth", |
||||||
|
Wind = "wind", |
||||||
|
Light = "light", |
||||||
|
Dark = "dark", |
||||||
|
Physical = "physical", |
||||||
|
Nonelemental = "non-elemental", |
||||||
|
Healing = "healing", |
||||||
|
} |
||||||
|
|
||||||
|
export enum Affinity { |
||||||
|
Absorbs = "absorbs", |
||||||
|
Immune = "immune", |
||||||
|
Resistant = "resistant", |
||||||
|
Normal = "normal", |
||||||
|
Vulnerable = "vulnerable", |
||||||
|
} |
||||||
|
|
||||||
|
export enum NumberSign { |
||||||
|
Positive = "+", |
||||||
|
Negative = "-", |
||||||
|
} |
||||||
|
|
||||||
|
export enum MeteredResource { |
||||||
|
Experience = "EXP", |
||||||
|
Health = "HP", |
||||||
|
Magic = "MP", |
||||||
|
Items = "IP", |
||||||
|
Zero = "ZP", |
||||||
|
Blood = "BP", |
||||||
|
Turns = "TP", |
||||||
|
Segments = "Segments", |
||||||
|
} |
||||||
|
export enum UnmeteredResource { |
||||||
|
Fabula = "FP", |
||||||
|
Ultima = "UP", |
||||||
|
Special = "SP", |
||||||
|
Level = "Level", |
||||||
|
Materials = "Materials", |
||||||
|
Zenit = "Zenit", |
||||||
|
} |
||||||
|
|
||||||
|
export type Resource = MeteredResource|UnmeteredResource |
||||||
|
|
||||||
|
export const Target = Symbol("target"); |
||||||
|
export const Source = Symbol("source"); |
||||||
|
|
||||||
|
export type Operands = Set<string|typeof Target|typeof Source> |
||||||
|
|
||||||
|
export interface ParseContext { |
||||||
|
readonly source: readonly string[] |
||||||
|
readonly target: readonly string[] |
||||||
|
readonly game: GameState |
||||||
|
} |
||||||
|
|
||||||
|
export interface MarkdownContext extends ParseContext {} |
||||||
|
|
||||||
|
export interface MarkdownOutput extends MarkdownContext { |
||||||
|
readonly output: string |
||||||
|
} |
Loading…
Reference in new issue