|  |  | @@ -1,4 +1,4 @@ | 
		
	
		
			
			|  |  |  | import { Entity, Mortal, POV } from './entity' | 
		
	
		
			
			|  |  |  | import { Entity, Mortal, POV, Creature } from './entity' | 
		
	
		
			
			|  |  |  | import { Damage, Actionable, Action, DevourAction, FeedAction, DigestAction, ReleaseAction, StruggleAction, Vigor } from './combat' | 
		
	
		
			
			|  |  |  | import { LogLines, LogEntry, CompositeLog, LogLine } from './interface' | 
		
	
		
			
			|  |  |  | import { Noun, POVPair, POVPairArgs, ImproperNoun } from './language' | 
		
	
	
		
			
				|  |  | @@ -10,52 +10,49 @@ export enum VoreType { | 
		
	
		
			
			|  |  |  | Unbirth = "Unbirthing" | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | export interface Prey extends Mortal { | 
		
	
		
			
			|  |  |  | export interface Vore extends Mortal { | 
		
	
		
			
			|  |  |  | preyPrefs: Set<VoreType>; | 
		
	
		
			
			|  |  |  | bulk: number; | 
		
	
		
			
			|  |  |  | containedIn: Container | null; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | export interface Pred extends Entity { | 
		
	
		
			
			|  |  |  | predPrefs: Set<VoreType>; | 
		
	
		
			
			|  |  |  | containers: Array<Container>; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | export interface Container extends Actionable { | 
		
	
		
			
			|  |  |  | name: Noun; | 
		
	
		
			
			|  |  |  | owner: Pred; | 
		
	
		
			
			|  |  |  | owner: Vore; | 
		
	
		
			
			|  |  |  | voreTypes: Set<VoreType>; | 
		
	
		
			
			|  |  |  | contents: Array<Prey>; | 
		
	
		
			
			|  |  |  | contents: Array<Vore>; | 
		
	
		
			
			|  |  |  | capacity: number; | 
		
	
		
			
			|  |  |  | fullness: number; | 
		
	
		
			
			|  |  |  | canTake: (prey: Prey) => boolean; | 
		
	
		
			
			|  |  |  | consume: (prey: Prey) => LogEntry; | 
		
	
		
			
			|  |  |  | release: (prey: Prey) => LogEntry; | 
		
	
		
			
			|  |  |  | struggle: (prey: Prey) => LogEntry; | 
		
	
		
			
			|  |  |  | canTake: (prey: Vore) => boolean; | 
		
	
		
			
			|  |  |  | consume: (prey: Vore) => LogEntry; | 
		
	
		
			
			|  |  |  | release: (prey: Vore) => LogEntry; | 
		
	
		
			
			|  |  |  | struggle: (prey: Vore) => LogEntry; | 
		
	
		
			
			|  |  |  | tick: (dt: number) => LogEntry; | 
		
	
		
			
			|  |  |  | describe: () => LogEntry; | 
		
	
		
			
			|  |  |  | digest: (prey: Prey) => LogEntry; | 
		
	
		
			
			|  |  |  | absorb: (prey: Prey) => LogEntry; | 
		
	
		
			
			|  |  |  | dispose: (preys: Prey[]) => LogEntry; | 
		
	
		
			
			|  |  |  | digest: (prey: Vore) => LogEntry; | 
		
	
		
			
			|  |  |  | absorb: (prey: Vore) => LogEntry; | 
		
	
		
			
			|  |  |  | dispose: (preys: Vore[]) => LogEntry; | 
		
	
		
			
			|  |  |  | actions: Array<Action>; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | abstract class NormalContainer implements Container { | 
		
	
		
			
			|  |  |  | contents: Array<Prey> | 
		
	
		
			
			|  |  |  | contents: Array<Vore> | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | abstract consumeLines: POVPair<Pred, Prey> | 
		
	
		
			
			|  |  |  | abstract releaseLines: POVPair<Pred, Prey> | 
		
	
		
			
			|  |  |  | abstract struggleLines: POVPair<Prey, Pred> | 
		
	
		
			
			|  |  |  | abstract tickLines: POVPairArgs<Pred, Prey, { damage: Damage }> | 
		
	
		
			
			|  |  |  | abstract digestLines: POVPair<Pred, Prey> | 
		
	
		
			
			|  |  |  | abstract absorbLines: POVPair<Pred, Prey> | 
		
	
		
			
			|  |  |  | abstract disposeLines: POVPair<Pred, Prey> | 
		
	
		
			
			|  |  |  | 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> | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | get fullness (): number { | 
		
	
		
			
			|  |  |  | return Array.from(this.contents.values()).reduce((total: number, prey: Prey) => total + prey.bulk, 0) | 
		
	
		
			
			|  |  |  | return Array.from(this.contents.values()).reduce((total: number, prey: Vore) => total + prey.bulk, 0) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | canTake (prey: Prey): boolean { | 
		
	
		
			
			|  |  |  | canTake (prey: Vore): boolean { | 
		
	
		
			
			|  |  |  | const fits = this.capacity - this.fullness >= prey.bulk | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | const permitted = Array.from(this.voreTypes).every(voreType => { | 
		
	
	
		
			
				|  |  | @@ -65,25 +62,29 @@ abstract class NormalContainer implements Container { | 
		
	
		
			
			|  |  |  | return fits && permitted | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | consume (prey: Prey): LogEntry { | 
		
	
		
			
			|  |  |  | consume (prey: Vore): LogEntry { | 
		
	
		
			
			|  |  |  | this.contents.push(prey) | 
		
	
		
			
			|  |  |  | prey.containedIn = this | 
		
	
		
			
			|  |  |  | return this.consumeLines.run(this.owner, prey) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | release (prey: Prey): LogEntry { | 
		
	
		
			
			|  |  |  | prey.containedIn = null | 
		
	
		
			
			|  |  |  | release (prey: Vore): LogEntry { | 
		
	
		
			
			|  |  |  | prey.containedIn = this.owner.containedIn | 
		
	
		
			
			|  |  |  | this.contents = this.contents.filter(victim => victim !== prey) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (this.owner.containedIn !== null) { | 
		
	
		
			
			|  |  |  | this.owner.containedIn.contents.push(prey) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return this.releaseLines.run(this.owner, prey) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | struggle (prey: Prey): LogEntry { | 
		
	
		
			
			|  |  |  | struggle (prey: Vore): LogEntry { | 
		
	
		
			
			|  |  |  | return this.struggleLines.run(prey, this.owner) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | tick (dt: number): LogEntry { | 
		
	
		
			
			|  |  |  | const digested: Array<Prey> = [] | 
		
	
		
			
			|  |  |  | const absorbed: Array<Prey> = [] | 
		
	
		
			
			|  |  |  | const digested: Array<Vore> = [] | 
		
	
		
			
			|  |  |  | const absorbed: Array<Vore> = [] | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | const scaled = this.damage.scale(dt / 60) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
	
		
			
				|  |  | @@ -122,21 +123,21 @@ abstract class NormalContainer implements Container { | 
		
	
		
			
			|  |  |  | return new LogLines(...lines) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | digest (prey: Prey): LogEntry { | 
		
	
		
			
			|  |  |  | digest (prey: Vore): LogEntry { | 
		
	
		
			
			|  |  |  | return this.digestLines.run(this.owner, prey) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | absorb (prey: Prey): LogEntry { | 
		
	
		
			
			|  |  |  | absorb (prey: Vore): LogEntry { | 
		
	
		
			
			|  |  |  | return this.absorbLines.run(this.owner, prey) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | dispose (preys: Prey[]): LogEntry { | 
		
	
		
			
			|  |  |  | dispose (preys: Vore[]): LogEntry { | 
		
	
		
			
			|  |  |  | return new CompositeLog(...preys.map(prey => this.disposeLines.run(this.owner, prey))) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | actions: Array<Action> | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | constructor (public name: Noun, public owner: Pred, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) { | 
		
	
		
			
			|  |  |  | constructor (public name: Noun, public owner: Vore, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) { | 
		
	
		
			
			|  |  |  | this.contents = [] | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | this.actions = [] | 
		
	
	
		
			
				|  |  | @@ -151,13 +152,13 @@ abstract class NormalContainer implements Container { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | abstract class InnerContainer extends NormalContainer { | 
		
	
		
			
			|  |  |  | release (prey: Prey): LogEntry { | 
		
	
		
			
			|  |  |  | release (prey: Vore): LogEntry { | 
		
	
		
			
			|  |  |  | prey.containedIn = this.escape | 
		
	
		
			
			|  |  |  | this.contents = this.contents.filter(victim => victim !== prey) | 
		
	
		
			
			|  |  |  | return this.releaseLines.run(this.owner, prey) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | constructor (name: Noun, owner: Pred, voreTypes: Set<VoreType>, capacity: number, damage: Damage, private escape: Container) { | 
		
	
		
			
			|  |  |  | constructor (name: Noun, owner: Vore, voreTypes: Set<VoreType>, capacity: number, damage: Damage, private escape: Container) { | 
		
	
		
			
			|  |  |  | super(name, owner, voreTypes, capacity, damage) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | this.actions = [] | 
		
	
	
		
			
				|  |  | @@ -168,7 +169,7 @@ abstract class InnerContainer extends NormalContainer { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | export class Stomach extends NormalContainer { | 
		
	
		
			
			|  |  |  | constructor (owner: Pred, capacity: number, damage: Damage) { | 
		
	
		
			
			|  |  |  | constructor (owner: Vore, capacity: number, damage: Damage) { | 
		
	
		
			
			|  |  |  | super(new ImproperNoun('stomach', 'stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
	
		
			
				|  |  | @@ -190,7 +191,7 @@ export class Stomach extends NormalContainer { | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} escapes from the gut of ${target.name}`)] | 
		
	
		
			
			|  |  |  | ]) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | tickLines = new POVPairArgs<Pred, Prey, { damage: Damage }>([ | 
		
	
		
			
			|  |  |  | tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([ | 
		
	
		
			
			|  |  |  | [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())], | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you for `, args.damage.renderShort())], | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} churns ${target.name} for `, args.damage.renderShort())] | 
		
	
	
		
			
				|  |  | @@ -216,7 +217,7 @@ export class Stomach extends NormalContainer { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | export class InnerStomach extends InnerContainer { | 
		
	
		
			
			|  |  |  | constructor (owner: Pred, capacity: number, damage: Damage, escape: Container) { | 
		
	
		
			
			|  |  |  | constructor (owner: Vore, capacity: number, damage: Damage, escape: Container) { | 
		
	
		
			
			|  |  |  | super(new ImproperNoun('inner stomach', 'inner stomachs').all, owner, new Set([VoreType.Oral]), capacity, damage, escape) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
	
		
			
				|  |  | @@ -238,7 +239,7 @@ export class InnerStomach extends InnerContainer { | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} escapes from the gut of ${target.name}`)] | 
		
	
		
			
			|  |  |  | ]) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | tickLines = new POVPairArgs<Pred, Prey, { damage: Damage }>([ | 
		
	
		
			
			|  |  |  | tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([ | 
		
	
		
			
			|  |  |  | [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())], | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you for `, args.damage.renderShort())], | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} churns ${target.name} for `, args.damage.renderShort())] | 
		
	
	
		
			
				|  |  | @@ -264,7 +265,7 @@ export class InnerStomach extends InnerContainer { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | export class Bowels extends NormalContainer { | 
		
	
		
			
			|  |  |  | constructor (owner: Pred, capacity: number, damage: Damage) { | 
		
	
		
			
			|  |  |  | constructor (owner: Vore, capacity: number, damage: Damage) { | 
		
	
		
			
			|  |  |  | super(new ImproperNoun('bowel', 'bowels').plural, owner, new Set([VoreType.Anal]), capacity, damage) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
	
		
			
				|  |  | @@ -286,7 +287,7 @@ export class Bowels extends NormalContainer { | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.Third], (user, target) => new LogLines(`${user.name.capital} escapes from the bowels of ${target.name}`)] | 
		
	
		
			
			|  |  |  | ]) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | tickLines = new POVPairArgs<Pred, Prey, { damage: Damage }>([ | 
		
	
		
			
			|  |  |  | tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([ | 
		
	
		
			
			|  |  |  | [[POV.First, POV.Third], (user, target, args) => new LogLine(`Your bowels gurgle ${target.name} for `, args.damage.renderShort())], | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s bowels churn you for `, args.damage.renderShort())], | 
		
	
		
			
			|  |  |  | [[POV.Third, POV.Third], (user, target, args) => new LogLine(`${target.name.capital} churns ${user.name} for `, args.damage.renderShort())] | 
		
	
	
		
			
				|  |  | 
 |