/* --- elizabot.js v.1.1 - ELIZA JS library (N.Landsteiner 2005) https://www.masswerk.at/elizabot/ Free Software © Norbert Landsteiner 2005 --- Modified by Cadence Ember in 2025 for v1.2 (unofficial) * Changed to class structure * Load from local file and instance instead of global variables * Remove memory * Remove xnone * Remove initials * Remove finals * Allow substitutions in rule keys --- Eliza is a mock Rogerian psychotherapist. Original program by Joseph Weizenbaum in MAD-SLIP for "Project MAC" at MIT. cf: Weizenbaum, Joseph "ELIZA - A Computer Program For the Study of Natural Language Communication Between Man and Machine" in: Communications of the ACM; Volume 9 , Issue 1 (January 1966): p 36-45. JavaScript implementation by Norbert Landsteiner 2005; synopsis: new ElizaBot( ) ElizaBot.prototype.transform( ) ElizaBot.prototype.reset() usage: var eliza = new ElizaBot(); var reply = eliza.transform(inputstring); // to reproduce the example conversation given by J. Weizenbaum // initialize with the optional random-choice-disable flag var originalEliza = new ElizaBot(true); `ElizaBot' is also a general chatbot engine that can be supplied with any rule set. (for required data structures cf. "elizadata.js" and/or see the documentation.) data is parsed and transformed for internal use at the creation time of the first instance of the `ElizaBot' constructor. vers 1.1: lambda functions in RegExps are currently a problem with too many browsers. changed code to work around. */ // @ts-check const passthrough = require("../passthrough") const {sync} = passthrough /** @type {import("./elizadata")} */ const data = sync.require("./elizadata") class ElizaBot { /** @type {any} */ elizaKeywords = [['###',0,[['###',[]]]]]; pres={}; preExp = /####/; posts={}; postExp = /####/; /** * @param {boolean} noRandomFlag */ constructor(noRandomFlag) { this.noRandom= !!noRandomFlag; this.capitalizeFirstLetter=true; this.debug=false; this.version="1.2"; this._init(); this.reset(); } reset() { this.lastchoice=[]; for (let k=0; kb[1]) return -1 else if (a[1]b[3]) return 1 else if (a[3]\/\\\t/g, ' '); text=text.replace(/\s+-+\s+/g, '.'); text=text.replace(/\s*[,\.\?!;]+\s*/g, '.'); text=text.replace(/\s*\bbut\b\s*/g, '.'); text=text.replace(/\s{2,}/g, ' '); // split text in part sentences and loop through them var parts=text.split('.'); for (let i=0; i=0) { rpl = this._execRule(k); } if (rpl!='') return rpl; } } } // return reply or default string return rpl || undefined } _execRule(k) { var rule=this.elizaKeywords[k]; var decomps=rule[2]; var paramre=/\(([0-9]+)\)/; for (let i=0; iri)) || (this.lastchoice[k][i]==ri)) { ri= ++this.lastchoice[k][i]; if (ri>=reasmbs.length) { ri=0; this.lastchoice[k][i]=-1; } } else { this.lastchoice[k][i]=ri; } var rpl=reasmbs[ri]; if (this.debug) alert('match:\nkey: '+this.elizaKeywords[k][0]+ '\nrank: '+this.elizaKeywords[k][1]+ '\ndecomp: '+decomps[i][0]+ '\nreasmb: '+rpl); if (rpl.search('^goto ', 'i')==0) { ki=this._getRuleIndexByKey(rpl.substring(5)); if (ki>=0) return this._execRule(ki); } // substitute positional params (v.1.1: work around lambda function) var m1=paramre.exec(rpl); if (m1) { var lp=''; var rp=rpl; while (m1) { var param = m[parseInt(m1[1])]; // postprocess param var m2=this.postExp.exec(param); if (m2) { var lp2=''; var rp2=param; while (m2) { lp2+=rp2.substring(0,m2.index)+this.posts[m2[1]]; rp2=rp2.substring(m2.index+m2[0].length); m2=this.postExp.exec(rp2); } param=lp2+rp2; } lp+=rp.substring(0,m1.index)+param; rp=rp.substring(m1.index+m1[0].length); m1=paramre.exec(rp); } rpl=lp+rp; } rpl=this._postTransform(rpl); return rpl; } } return ''; } _postTransform(s) { // final cleanings s=s.replace(/\s{2,}/g, ' '); s=s.replace(/\s+\./g, '.'); if ((data.elizaPostTransforms) && (data.elizaPostTransforms.length)) { for (let i=0; i