| @@ -1,6 +1,6 @@ | |||||
| import { Creature, POV, Entity } from './entity' | import { Creature, POV, Entity } from './entity' | ||||
| import { POVPair, POVPairArgs, TextLike, DynText, LiveText } from './language' | import { POVPair, POVPairArgs, TextLike, DynText, LiveText } from './language' | ||||
| import { Container } from './vore' | |||||
| import { VoreContainer } from './vore' | |||||
| import { LogEntry, LogLines, CompositeLog, FAElem, LogLine, FormatEntry, FormatOpt, PropElem } from './interface' | import { LogEntry, LogLines, CompositeLog, FAElem, LogLine, FormatEntry, FormatOpt, PropElem } from './interface' | ||||
| import { StatTest, StatVigorTest } from './combat/tests' | import { StatTest, StatVigorTest } from './combat/tests' | ||||
| @@ -3,7 +3,7 @@ import { POVPairArgs, POVPair, DynText, LiveText, TextLike } from '../language' | |||||
| import { Entity, POV, Creature } from '../entity' | import { Entity, POV, Creature } from '../entity' | ||||
| import { Damage, DamageFormula, Stat, Vigor, TogetherAction, PairAction, SelfAction } from '../combat' | import { Damage, DamageFormula, Stat, Vigor, TogetherAction, PairAction, SelfAction } from '../combat' | ||||
| import { LogLine, LogLines, LogEntry, CompositeLog } from '../interface' | import { LogLine, LogLines, LogEntry, CompositeLog } from '../interface' | ||||
| import { Container } from '../vore' | |||||
| import { VoreContainer, Container } from '../vore' | |||||
| import { CapableCondition, DrainedVigorCondition } from './conditions' | import { CapableCondition, DrainedVigorCondition } from './conditions' | ||||
| export class AttackAction extends TogetherAction { | export class AttackAction extends TogetherAction { | ||||
| @@ -73,7 +73,7 @@ export class DevourAction extends TogetherAction { | |||||
| } | } | ||||
| constructor (protected container: Container) { | constructor (protected container: Container) { | ||||
| super(new DynText('Devour (', new LiveText(container, x => x.name.all), ')'), 'Try to consume your foe', [new CapableCondition()]) | |||||
| super(new DynText(new LiveText(container, x => x.consumeVerb.capital), ' (', new LiveText(container, x => x.name.all), ')'), 'Try to consume your foe', [new CapableCondition()]) | |||||
| this.test = new StatVigorTest(Stat.Power) | this.test = new StatVigorTest(Stat.Power) | ||||
| } | } | ||||
| @@ -132,7 +132,7 @@ export class StruggleAction extends PairAction { | |||||
| protected failLines: POVPair<Entity, Entity> = new POVPair([ | protected failLines: POVPair<Entity, Entity> = new POVPair([ | ||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You fail to escape from ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLine(`You fail to escape from ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} tries to escape from you, but fails`)], | [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} tries to escape from you, but fails`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} unsuccessfully struggles within ${target.name}`)] | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} unsuccessfully struggles against ${target.name}`)] | |||||
| ]) | ]) | ||||
| allowed (user: Creature, target: Creature) { | allowed (user: Creature, target: Creature) { | ||||
| @@ -176,7 +176,7 @@ export abstract class EatenAction extends PairAction { | |||||
| } | } | ||||
| } | } | ||||
| constructor (public container: Container, name: TextLike, desc: string) { | |||||
| constructor (public container: VoreContainer, name: TextLike, desc: string) { | |||||
| super(new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'), desc, [new CapableCondition()]) | super(new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'), desc, [new CapableCondition()]) | ||||
| } | } | ||||
| } | } | ||||
| @@ -191,7 +191,7 @@ export class DigestAction extends SelfAction { | |||||
| } | } | ||||
| } | } | ||||
| constructor (protected container: Container) { | |||||
| constructor (protected container: VoreContainer) { | |||||
| super(new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition()]) | super(new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition()]) | ||||
| } | } | ||||
| @@ -231,7 +231,7 @@ export class TransferAction extends PairAction { | |||||
| lines: POVPairArgs<Entity, Entity, { from: Container; to: Container }> = new POVPairArgs([ | lines: POVPairArgs<Entity, Entity, { from: Container; to: Container }> = new POVPairArgs([ | ||||
| [[POV.First, POV.Third], (user, target, args) => new LogLine(`You squeeze ${target.name} from your ${args.from.name} to your ${args.to.name}`)], | [[POV.First, POV.Third], (user, target, args) => new LogLine(`You squeeze ${target.name} from your ${args.from.name} to your ${args.to.name}`)], | ||||
| [[POV.Third, POV.First], (user, target, args) => new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)], | [[POV.Third, POV.First], (user, target, args) => new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)], | ||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name} squeezes ${target.name} from ${user.pronouns.possessive} ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)] | |||||
| [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name} squeezes ${target.name} from ${user.pronouns.possessive} ${args.from.name.all} to ${user.pronouns.possessive} ${args.to.name.all}`)] | |||||
| ]) | ]) | ||||
| allowed (user: Creature, target: Creature) { | allowed (user: Creature, target: Creature) { | ||||
| @@ -242,8 +242,8 @@ export class TransferAction extends PairAction { | |||||
| } | } | ||||
| } | } | ||||
| constructor (protected from: Container, protected to: Container) { | |||||
| super('Transfer', `Move from your ${from.name} to your ${to.name}`, [new CapableCondition()]) | |||||
| constructor (protected from: Container, protected to: Container, name = 'Transfer') { | |||||
| super(name, `${from.name.all.capital} to ${to.name.all}`, [new CapableCondition()]) | |||||
| } | } | ||||
| execute (user: Creature, target: Creature): LogEntry { | execute (user: Creature, target: Creature): LogEntry { | ||||
| @@ -1,7 +1,7 @@ | |||||
| import { Creature, POV, Entity } from '../entity' | import { Creature, POV, Entity } from '../entity' | ||||
| import { Stat, Damage, DamageType, Vigor, ConstantDamageFormula } from '../combat' | import { Stat, Damage, DamageType, Vigor, ConstantDamageFormula } from '../combat' | ||||
| import { ProperNoun, TheyPronouns, ImproperNoun, POVPair, FemalePronouns, POVPairArgs } from '../language' | import { ProperNoun, TheyPronouns, ImproperNoun, POVPair, FemalePronouns, POVPairArgs } from '../language' | ||||
| import { VoreType, Stomach, InnerStomach, Container } from '../vore' | |||||
| import { VoreType, Stomach, InnerStomach, VoreContainer, NormalContainer, Vore } from '../vore' | |||||
| import { LogLine, LogLines, LogEntry, FAElem, CompositeLog, ImgElem } from '../interface' | import { LogLine, LogLines, LogEntry, FAElem, CompositeLog, ImgElem } from '../interface' | ||||
| import { AttackAction, EatenAction, TransferAction, FeedAction } from '../combat/actions' | import { AttackAction, EatenAction, TransferAction, FeedAction } from '../combat/actions' | ||||
| import { InstantKill } from '../combat/effects' | import { InstantKill } from '../combat/effects' | ||||
| @@ -66,7 +66,7 @@ class CrushAction extends EatenAction { | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} crushes ${target.name}; ${user.pronouns.subjective} ${user.pronouns.isPlural ? 'belch' : 'belches'} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `)] | [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} crushes ${target.name}; ${user.pronouns.subjective} ${user.pronouns.isPlural ? 'belch' : 'belches'} as ${user.pronouns.possessive} gut lets out a fatal CRUNCH `)] | ||||
| ]) | ]) | ||||
| constructor (container: Container) { | |||||
| constructor (container: VoreContainer) { | |||||
| super(container, "Crush", "Crush 'em!") | super(container, "Crush", "Crush 'em!") | ||||
| this.desc = "Crush somebody in your gut" | this.desc = "Crush somebody in your gut" | ||||
| } | } | ||||
| @@ -1,13 +1,43 @@ | |||||
| import { Creature, POV } from '../entity' | import { Creature, POV } from '../entity' | ||||
| import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction } from '../combat' | import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction } from '../combat' | ||||
| import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs, POVSoloArgs } from '../language' | |||||
| import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs, POVSoloArgs, Verb } from '../language' | |||||
| import { LogLine, LogLines, LogEntry, Newline } from '../interface' | import { LogLine, LogLines, LogEntry, Newline } from '../interface' | ||||
| import { VoreType, Stomach, Container, Vore } from '../vore' | |||||
| import { AttackAction, FeedAction } from '../combat/actions' | |||||
| import { VoreType, Stomach, VoreContainer, Vore, NormalContainer } from '../vore' | |||||
| import { AttackAction, FeedAction, TransferAction } from '../combat/actions' | |||||
| import { TogetherCondition } from '../combat/conditions' | import { TogetherCondition } from '../combat/conditions' | ||||
| import { InstantKill } from '../combat/effects' | import { InstantKill } from '../combat/effects' | ||||
| import * as Words from '../words' | import * as Words from '../words' | ||||
| class MawContainer extends NormalContainer { | |||||
| consumeVerb = new Verb('grab') | |||||
| releaseVerb = new Verb('release') | |||||
| struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled') | |||||
| consumeLines = new POVPair<Vore, Vore>([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You snatch ${target.name} up in your jaws`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} snatches you up in ${user.pronouns.possessive} maw`)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} snatches ${target.name} up in ${user.pronouns.possessive} maw`)] | |||||
| ]) | |||||
| releaseLines = new POVPair([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You let out ${target.name}`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} lets you out `)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} lets out ${target.name}`)] | |||||
| ]) | |||||
| struggleLines = new POVPair([ | |||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`You claw your way free of ${target.name}`)], | |||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital} forces ${user.pronouns.possessive} way free!`)], | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${user.name.capital} escapes from ${target.name}`)] | |||||
| ]) | |||||
| constructor (owner: Vore, stomach: VoreContainer) { | |||||
| super(new ImproperNoun('maw'), owner, new Set([VoreType.Oral]), 50) | |||||
| this.actions.push(new TransferAction(this, stomach)) | |||||
| } | |||||
| } | |||||
| const huge = new RandomWord([ | const huge = new RandomWord([ | ||||
| new Adjective('massive'), | new Adjective('massive'), | ||||
| new Adjective('colossal'), | new Adjective('colossal'), | ||||
| @@ -84,7 +114,7 @@ class DevourAllAction extends GroupAction { | |||||
| return new LogLine('Eat all ', targets.length.toString(), ' of \'em!') | return new LogLine('Eat all ', targets.length.toString(), ' of \'em!') | ||||
| } | } | ||||
| constructor (private container: Container) { | |||||
| constructor (private container: VoreContainer) { | |||||
| super('Devour All', 'GULP!', [ | super('Devour All', 'GULP!', [ | ||||
| new TogetherCondition() | new TogetherCondition() | ||||
| ]) | ]) | ||||
| @@ -122,12 +152,16 @@ export class Withers extends Creature { | |||||
| stomach.digestLines = new POVPair<Vore, Vore>([ | stomach.digestLines = new POVPair<Vore, Vore>([ | ||||
| [[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach ${Words.Digests.singular} ${target.name}`)], | [[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach ${Words.Digests.singular} ${target.name}`)], | ||||
| [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach ${Words.Digests.singular} you`)], | [[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach ${Words.Digests.singular} you`)], | ||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade as the ${target.kind.all} is ${Words.Digests.past} by the ${user.kind}'s ${stomach.name}.`)] | |||||
| [[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s ${Words.Struggles.present} fades as the ${target.kind.all} is ${Words.Digests.past} by the ${user.kind.all}'s ${stomach.name}.`)] | |||||
| ]) | ]) | ||||
| this.containers.push(stomach) | this.containers.push(stomach) | ||||
| this.otherActions.push(new FeedAction(stomach)) | this.otherActions.push(new FeedAction(stomach)) | ||||
| this.groupActions.push(new DevourAllAction(stomach)) | this.groupActions.push(new DevourAllAction(stomach)) | ||||
| const grapple = new MawContainer(this, stomach) | |||||
| this.otherContainers.push(grapple) | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| import { DamageType, Damage, Combatant, Stats, Action, Vigor, VoreStats, VoreStat, Stat, Side, GroupAction } from './combat' | import { DamageType, Damage, Combatant, Stats, Action, Vigor, VoreStats, VoreStat, Stat, Side, GroupAction } from './combat' | ||||
| import { Noun, Pronoun, Adjective, ImproperNoun } from './language' | import { Noun, Pronoun, Adjective, ImproperNoun } from './language' | ||||
| import { LogEntry, LogLine } from './interface' | import { LogEntry, LogLine } from './interface' | ||||
| import { Vore, Container, VoreType } from './vore' | |||||
| import { Vore, VoreContainer, VoreType, Container } from './vore' | |||||
| export enum POV {First, Third} | export enum POV {First, Third} | ||||
| @@ -47,16 +47,17 @@ export class Creature extends Vore implements Combatant { | |||||
| resistances: Map<DamageType, number> = new Map() | resistances: Map<DamageType, number> = new Map() | ||||
| perspective: POV = POV.Third | perspective: POV = POV.Third | ||||
| containers: Array<Container> = [] | |||||
| actions: Array<Action> = []; | |||||
| groupActions: Array<GroupAction> = []; | |||||
| otherActions: Array<Action> = []; | |||||
| containers: Array<VoreContainer> = [] | |||||
| otherContainers: Array<Container> = [] | |||||
| actions: Array<Action> = [] | |||||
| groupActions: Array<GroupAction> = [] | |||||
| otherActions: Array<Action> = [] | |||||
| get bulk (): number { | get bulk (): number { | ||||
| return this.voreStats.Mass + this.containers.reduce((total, conatiner) => { return total + conatiner.contents.reduce((total, prey) => total + prey.voreStats.Bulk, 0) }, 0) | return this.voreStats.Mass + this.containers.reduce((total, conatiner) => { return total + conatiner.contents.reduce((total, prey) => total + prey.voreStats.Bulk, 0) }, 0) | ||||
| } | } | ||||
| containedIn: Container|null = null; | |||||
| containedIn: VoreContainer|null = null; | |||||
| constructor (public name: Noun, public kind: Noun, public pronouns: Pronoun, public stats: Stats, public preyPrefs: Set<VoreType>, public predPrefs: Set<VoreType>, mass: number) { | constructor (public name: Noun, public kind: Noun, public pronouns: Pronoun, public stats: Stats, public preyPrefs: Set<VoreType>, public predPrefs: Set<VoreType>, mass: number) { | ||||
| super() | super() | ||||
| @@ -67,7 +68,7 @@ export class Creature extends Vore implements Combatant { | |||||
| get [VoreStat.Bulk] () { | get [VoreStat.Bulk] () { | ||||
| console.log(containers) | console.log(containers) | ||||
| return containers.reduce( | return containers.reduce( | ||||
| (total: number, container: Container) => { | |||||
| (total: number, container: VoreContainer) => { | |||||
| return total + container.contents.reduce( | return total + container.contents.reduce( | ||||
| (total: number, prey: Vore) => { | (total: number, prey: Vore) => { | ||||
| return total + prey.voreStats.Bulk | return total + prey.voreStats.Bulk | ||||
| @@ -86,7 +87,7 @@ export class Creature extends Vore implements Combatant { | |||||
| [VoreStat.Mass]: mass, | [VoreStat.Mass]: mass, | ||||
| get [VoreStat.PreyCount] () { | get [VoreStat.PreyCount] () { | ||||
| return containers.reduce( | return containers.reduce( | ||||
| (total: number, container: Container) => { | |||||
| (total: number, container: VoreContainer) => { | |||||
| return total + container.contents.reduce( | return total + container.contents.reduce( | ||||
| (total: number, prey: Vore) => { | (total: number, prey: Vore) => { | ||||
| return total + 1 + prey.voreStats[VoreStat.PreyCount] | return total + 1 + prey.voreStats[VoreStat.PreyCount] | ||||
| @@ -140,14 +141,19 @@ export class Creature extends Vore implements Combatant { | |||||
| return "Broken" | return "Broken" | ||||
| } | } | ||||
| if (this.containedIn !== null) { | if (this.containedIn !== null) { | ||||
| return `Devoured by ${this.containedIn.owner.name}` | |||||
| return `${this.containedIn.consumeVerb.past.capital} by ${this.containedIn.owner.name}` | |||||
| } | } | ||||
| return "Normal" | return "Normal" | ||||
| } | } | ||||
| validActions (target: Creature): Array<Action> { | validActions (target: Creature): Array<Action> { | ||||
| let choices = this.actions.concat(this.containers.flatMap(container => container.actions)).concat(target.otherActions) | |||||
| let choices = this.actions.concat( | |||||
| this.containers.flatMap(container => container.actions)).concat( | |||||
| target.otherActions.concat( | |||||
| this.otherContainers.flatMap(container => container.actions) | |||||
| ) | |||||
| ) | |||||
| if (this.containedIn !== null) { | if (this.containedIn !== null) { | ||||
| choices = choices.concat(this.containedIn.actions) | choices = choices.concat(this.containedIn.actions) | ||||
| @@ -130,6 +130,7 @@ export class DynText { | |||||
| } | } | ||||
| toString (): string { | toString (): string { | ||||
| console.log(this.parts) | |||||
| return (this.parts.map(part => part.toString())).join('') | return (this.parts.map(part => part.toString())).join('') | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| import { Entity, Mortal, POV, Creature } from './entity' | import { Entity, Mortal, POV, Creature } from './entity' | ||||
| import { Damage, DamageType, Stats, Actionable, Action, Vigor, VoreStats } from './combat' | import { Damage, DamageType, Stats, Actionable, Action, Vigor, VoreStats } from './combat' | ||||
| import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | ||||
| import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun, POVSolo } from './language' | |||||
| import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun, POVSolo, TextLike, Verb, Word } from './language' | |||||
| import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions' | import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions' | ||||
| export enum VoreType { | export enum VoreType { | ||||
| @@ -29,7 +29,8 @@ export abstract class Vore implements Mortal { | |||||
| abstract voreStats: VoreStats; | abstract voreStats: VoreStats; | ||||
| abstract containedIn: Container | null; | abstract containedIn: Container | null; | ||||
| abstract predPrefs: Set<VoreType>; | abstract predPrefs: Set<VoreType>; | ||||
| abstract containers: Array<Container>; | |||||
| abstract containers: Array<VoreContainer>; | |||||
| abstract otherContainers: Array<Container>; | |||||
| destroy (): LogEntry { | destroy (): LogEntry { | ||||
| const lines = new POVSolo<Vore>([ | const lines = new POVSolo<Vore>([ | ||||
| [[POV.First], (target: Vore) => new LogLine('You die!')], | [[POV.First], (target: Vore) => new LogLine('You die!')], | ||||
| @@ -53,66 +54,101 @@ export interface Container extends Actionable { | |||||
| owner: Vore; | owner: Vore; | ||||
| voreTypes: Set<VoreType>; | voreTypes: Set<VoreType>; | ||||
| contents: Array<Vore>; | contents: Array<Vore>; | ||||
| digested: Array<Vore>; | |||||
| capacity: number; | capacity: number; | ||||
| fullness: number; | fullness: number; | ||||
| canTake: (prey: Vore) => boolean; | canTake: (prey: Vore) => boolean; | ||||
| consume: (prey: Vore) => LogEntry; | consume: (prey: Vore) => LogEntry; | ||||
| release: (prey: Vore) => LogEntry; | release: (prey: Vore) => LogEntry; | ||||
| struggle: (prey: Vore) => LogEntry; | struggle: (prey: Vore) => LogEntry; | ||||
| tick: (dt: number) => LogEntry; | |||||
| describe: () => LogEntry; | describe: () => LogEntry; | ||||
| digest: (prey: Vore) => LogEntry; | |||||
| absorb: (prey: Vore) => LogEntry; | |||||
| dispose: (preys: Vore[]) => LogEntry; | |||||
| actions: Array<Action>; | |||||
| consumeVerb: Verb; | |||||
| releaseVerb: Verb; | |||||
| struggleVerb: Verb; | |||||
| } | } | ||||
| abstract class NormalContainer implements Container { | |||||
| contents: Array<Vore> | |||||
| digested: Array<Vore> | |||||
| export abstract class NormalContainer implements Container { | |||||
| contents: Array<Vore> = [] | |||||
| actions: Array<Action> = [] | |||||
| abstract consumeLines: POVPair<Vore, Vore> | |||||
| abstract releaseLines: POVPair<Vore, Vore> | |||||
| abstract struggleLines: POVPair<Vore, Vore> | |||||
| abstract tickLines: POVPairArgs<Vore, Vore, { damage: Damage }> | |||||
| abstract digestLines: POVPair<Vore, Vore> | |||||
| abstract absorbLines: POVPair<Vore, Vore> | |||||
| abstract disposeLines: POVPair<Vore, Vore> | |||||
| abstract consumeLines: POVPair<Vore, Vore> | |||||
| abstract releaseLines: POVPair<Vore, Vore> | |||||
| abstract struggleLines: POVPair<Vore, Vore> | |||||
| get fullness (): number { | |||||
| return Array.from(this.contents.values()).reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0) | |||||
| } | |||||
| abstract consumeVerb: Verb | |||||
| abstract releaseVerb: Verb | |||||
| abstract struggleVerb: Verb | |||||
| canTake (prey: Vore): boolean { | |||||
| const fits = this.capacity - this.fullness >= prey.voreStats.Bulk | |||||
| get fullness (): number { | |||||
| return Array.from(this.contents.values()).reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0) | |||||
| } | |||||
| const permitted = Array.from(this.voreTypes).every(voreType => { | |||||
| return prey.preyPrefs.has(voreType) | |||||
| }) | |||||
| canTake (prey: Vore): boolean { | |||||
| const fits = this.capacity - this.fullness >= prey.voreStats.Bulk | |||||
| return fits && permitted | |||||
| } | |||||
| const permitted = Array.from(this.voreTypes).every(voreType => { | |||||
| return prey.preyPrefs.has(voreType) | |||||
| }) | |||||
| consume (prey: Vore): LogEntry { | |||||
| this.contents.push(prey) | |||||
| prey.containedIn = this | |||||
| return this.consumeLines.run(this.owner, prey) | |||||
| } | |||||
| return fits && permitted | |||||
| } | |||||
| release (prey: Vore): LogEntry { | |||||
| prey.containedIn = this.owner.containedIn | |||||
| this.contents = this.contents.filter(victim => victim !== prey) | |||||
| consume (prey: Vore): LogEntry { | |||||
| this.contents.push(prey) | |||||
| prey.containedIn = this | |||||
| return this.consumeLines.run(this.owner, prey) | |||||
| } | |||||
| if (this.owner.containedIn !== null) { | |||||
| this.owner.containedIn.contents.push(prey) | |||||
| } | |||||
| return this.releaseLines.run(this.owner, prey) | |||||
| } | |||||
| release (prey: Vore): LogEntry { | |||||
| prey.containedIn = this.owner.containedIn | |||||
| this.contents = this.contents.filter(victim => victim !== prey) | |||||
| struggle (prey: Vore): LogEntry { | |||||
| return this.struggleLines.run(prey, this.owner) | |||||
| if (this.owner.containedIn !== null) { | |||||
| this.owner.containedIn.contents.push(prey) | |||||
| } | } | ||||
| return this.releaseLines.run(this.owner, prey) | |||||
| } | |||||
| struggle (prey: Vore): LogEntry { | |||||
| return this.struggleLines.run(prey, this.owner) | |||||
| } | |||||
| describe (): LogEntry { | |||||
| const lines: Array<string> = [] | |||||
| this.contents.forEach(prey => { | |||||
| lines.push(prey.toString()) | |||||
| }) | |||||
| return new LogLine(...lines) | |||||
| } | |||||
| constructor (public name: Noun, public owner: Vore, public voreTypes: Set<VoreType>, public capacity: number) { | |||||
| this.actions.push(new DevourAction(this)) | |||||
| this.actions.push(new ReleaseAction(this)) | |||||
| this.actions.push(new StruggleAction(this)) | |||||
| } | |||||
| } | |||||
| export interface VoreContainer extends Container { | |||||
| digested: Array<Vore>; | |||||
| tick: (dt: number) => LogEntry; | |||||
| digest: (prey: Vore) => LogEntry; | |||||
| absorb: (prey: Vore) => LogEntry; | |||||
| dispose: (preys: Vore[]) => LogEntry; | |||||
| } | |||||
| export abstract class NormalVoreContainer extends NormalContainer implements VoreContainer { | |||||
| digested: Array<Vore> = [] | |||||
| abstract tickLines: POVPairArgs<Vore, Vore, { damage: Damage }> | |||||
| abstract digestLines: POVPair<Vore, Vore> | |||||
| abstract absorbLines: POVPair<Vore, Vore> | |||||
| abstract disposeLines: POVPair<Vore, Vore> | |||||
| consumeVerb = new Verb('devour') | |||||
| releaseVerb = new Verb('release', 'releases', 'releasing', 'released') | |||||
| struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled') | |||||
| tick (dt: number): LogEntry { | tick (dt: number): LogEntry { | ||||
| const justDigested: Array<Vore> = [] | const justDigested: Array<Vore> = [] | ||||
| @@ -140,16 +176,6 @@ abstract class NormalContainer implements Container { | |||||
| return new LogLines(tickedEntries, new LogLines(...damageResults), digestedEntries) | return new LogLines(tickedEntries, new LogLines(...damageResults), digestedEntries) | ||||
| } | } | ||||
| describe (): LogEntry { | |||||
| const lines: Array<string> = [] | |||||
| this.contents.forEach(prey => { | |||||
| lines.push(prey.toString()) | |||||
| }) | |||||
| return new LogLine(...lines) | |||||
| } | |||||
| digest (prey: Vore): LogEntry { | digest (prey: Vore): LogEntry { | ||||
| return this.digestLines.run(this.owner, prey) | return this.digestLines.run(this.owner, prey) | ||||
| } | } | ||||
| @@ -162,31 +188,23 @@ abstract class NormalContainer implements Container { | |||||
| return new CompositeLog(...preys.map(prey => this.disposeLines.run(this.owner, prey))) | return new CompositeLog(...preys.map(prey => this.disposeLines.run(this.owner, prey))) | ||||
| } | } | ||||
| actions: Array<Action> | |||||
| constructor (public name: Noun, public owner: Vore, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) { | |||||
| this.contents = [] | |||||
| this.digested = [] | |||||
| this.actions = [] | |||||
| constructor (name: Noun, owner: Vore, voreTypes: Set<VoreType>, capacity: number, private damage: Damage) { | |||||
| super(name, owner, voreTypes, capacity) | |||||
| this.name = name | this.name = name | ||||
| this.actions.push(new DevourAction(this)) | |||||
| this.actions.push(new DigestAction(this)) | this.actions.push(new DigestAction(this)) | ||||
| this.actions.push(new ReleaseAction(this)) | |||||
| this.actions.push(new StruggleAction(this)) | |||||
| } | } | ||||
| } | } | ||||
| abstract class InnerContainer extends NormalContainer { | |||||
| abstract class InnerContainer extends NormalVoreContainer { | |||||
| release (prey: Vore): LogEntry { | release (prey: Vore): LogEntry { | ||||
| prey.containedIn = this.escape | prey.containedIn = this.escape | ||||
| this.contents = this.contents.filter(victim => victim !== prey) | this.contents = this.contents.filter(victim => victim !== prey) | ||||
| return this.releaseLines.run(this.owner, prey) | return this.releaseLines.run(this.owner, prey) | ||||
| } | } | ||||
| constructor (name: Noun, owner: Vore, voreTypes: Set<VoreType>, capacity: number, damage: Damage, private escape: Container) { | |||||
| constructor (name: Noun, owner: Vore, voreTypes: Set<VoreType>, capacity: number, damage: Damage, private escape: VoreContainer) { | |||||
| super(name, owner, voreTypes, capacity, damage) | super(name, owner, voreTypes, capacity, damage) | ||||
| this.actions = [] | this.actions = [] | ||||
| @@ -196,7 +214,7 @@ abstract class InnerContainer extends NormalContainer { | |||||
| } | } | ||||
| } | } | ||||
| export class Stomach extends NormalContainer { | |||||
| export class Stomach extends NormalVoreContainer { | |||||
| constructor (owner: Vore, capacity: number, damage: Damage) { | constructor (owner: Vore, capacity: number, damage: Damage) { | ||||
| super(new ImproperNoun('stomach', 'stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage) | super(new ImproperNoun('stomach', 'stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage) | ||||
| } | } | ||||
| @@ -245,7 +263,7 @@ export class Stomach extends NormalContainer { | |||||
| } | } | ||||
| export class InnerStomach extends InnerContainer { | export class InnerStomach extends InnerContainer { | ||||
| constructor (owner: Vore, capacity: number, damage: Damage, escape: Container) { | |||||
| constructor (owner: Vore, capacity: number, damage: Damage, escape: VoreContainer) { | |||||
| super(new ImproperNoun('inner stomach', 'inner stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage, escape) | super(new ImproperNoun('inner stomach', 'inner stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage, escape) | ||||
| } | } | ||||
| @@ -292,7 +310,7 @@ export class InnerStomach extends InnerContainer { | |||||
| ]) | ]) | ||||
| } | } | ||||
| export class Bowels extends NormalContainer { | |||||
| export class Bowels extends NormalVoreContainer { | |||||
| constructor (owner: Vore, capacity: number, damage: Damage) { | constructor (owner: Vore, capacity: number, damage: Damage) { | ||||
| super(new ImproperNoun('bowel', 'bowels').plural, owner, new Set([VoreType.Anal]), capacity, damage) | super(new ImproperNoun('bowel', 'bowels').plural, owner, new Set([VoreType.Anal]), capacity, damage) | ||||
| } | } | ||||
| @@ -30,3 +30,15 @@ export const Digests = new RandomWord([ | |||||
| new Verb("melt"), | new Verb("melt"), | ||||
| new Verb("dissolve", "dissolves", "dissolving", "dissolved") | new Verb("dissolve", "dissolves", "dissolving", "dissolved") | ||||
| ]) | ]) | ||||
| export const Struggles = new RandomWord([ | |||||
| new Verb("squirm"), | |||||
| new Verb("struggle", "struggles", "struggling", "struggled"), | |||||
| new Verb("thrash", "thrashes") | |||||
| ]) | |||||
| export const Bulge = new RandomWord([ | |||||
| new ImproperNoun("bulge", "bulges"), | |||||
| new ImproperNoun("outline", "outlines"), | |||||
| new ImproperNoun("imprint", "imprints") | |||||
| ]) | |||||