/// /// /// /// interface LiquidOptions extends ThingOptions { taste? : OneOf; } interface LiquidContainer { liquidContents : Array; } interface LiquidMixture { quantities : Map; result : Liquid; quantityMultiplier? : number; firstPriority : number; priority : number; } class Liquid extends Thing { public taste : OneOf; public constructor (options? : LiquidOptions) { super(options); options = options == undefined ? {} : options; if (options.taste != undefined) { this.taste = options.taste; } else { this.taste = new OneOf( OneOf.ROTATING_RANDOM, "It goes easily through your throat with no particular taste.", "You taste nothing as it softly slides through your tongue." ); } } /** * This rulebook will return a LiquidMixture * @type {Rulebook} */ public static rulebookMixing = new Rulebook("Mixing the liquid contents of something"); // noun = LiquidContainer public static mixtures : Array = []; public static sortedMixtures = false; public static async mix (container : LiquidContainer) { let result = await Liquid.rulebookMixing.execute({noun : container}); // Did we find a liquid? if (result != undefined) { let finalQuantity = result.quantityMultiplier != undefined ? (result.quantityMultiplier * container.liquidContents.length) : (container.liquidContents.length); container.liquidContents = new Array(finalQuantity); for (let i = 0; i < finalQuantity; i++) { container.liquidContents[i] = result.result; } } } public static getMixtures () { if (Liquid.sortedMixtures) { return Liquid.mixtures; } Liquid.mixtures.sort((a, b) => { if (b.firstPriority < a.firstPriority) return -1; if (a.firstPriority < b.firstPriority) return 1; if (b.priority < a.priority) return -1; if (a.priority < b.priority) return 1; return 0; }); Liquid.sortedMixtures = true; return Liquid.mixtures; } public static addMixture(mixture : LiquidMixture) { Liquid.mixtures.push(mixture); Liquid.sortedMixtures = false; } public static ruleDefaultMixing = Liquid.rulebookMixing.createAndAddRule({ name : "Mixing through Mixtures", code : runner => { if (runner.noun.liquidContents.length == 0) { return; } let mixture : LiquidMixture; for (let i = 0; i < Liquid.mixtures.length; i++) { mixture = Liquid.mixtures[i]; let proportions = []; let mixtureIterator = mixture.quantities.entries(); for (let mixtureLiquid = mixtureIterator.next(); !mixtureLiquid.done; mixtureLiquid = mixtureIterator.next()) { let mixtureType = mixtureLiquid.value[0]; let mixtureQuantity = mixtureLiquid.value[1]; let matchedQuantity = 0; runner.noun.liquidContents.forEach((liquidType) => { try { if (liquidType == mixtureType || (typeof mixtureType == "function" && (liquidType instanceof mixtureType || mixtureType(liquidType)) ) ) { matchedQuantity++; } // mixtureType is not always callable } catch (e) {} }); proportions.push(matchedQuantity / mixtureQuantity); } // If this is a valid mix, then every part of the recipe is represented proportionally if (proportions.every(function(element, index, array) { return element === array[0]; })) { return mixture; } } } }); } // class Semen extends Liquid {} // class OrcSemen extends Semen {} // class MinotaurSemen extends Semen {} // class PowerfulDrink extends Liquid {} // // let powerfulDrinkQuantities = new Map(); // powerfulDrinkQuantities.set(OrcSemen, 2); // powerfulDrinkQuantities.set(MinotaurSemen, 1); // Liquid.addMixture({ // firstPriority : Rule.PRIORITY_HIGHEST, // priority : Rule.PRIORITY_MEDIUM, // quantityMultiplier : 0.5, // result : new PowerfulDrink("Powerful Drink"), // quantities : powerfulDrinkQuantities // }); // let recipient = new Recipient("Cup"); // recipient.liquidContents.push(new OrcSemen("Semen of the Chief")); // recipient.liquidContents.push(new OrcSemen("Semen of the Chief")); // recipient.liquidContents.push(new OrcSemen("Semen of the Chief")); // recipient.liquidContents.push(new OrcSemen("Semen of the Chief")); // recipient.liquidContents.push(new MinotaurSemen("Semen of Harold")); // recipient.liquidContents.push(new MinotaurSemen("Semen of Harold")); // // { // Settings.setDebug(false); // let t1 = performance.now(); // let t0 = performance.now(); // Liquid.mix(recipient); // t1 = performance.now(); // console.log(t1 - t0); // }