1 | ------------------------------------------------------------------------ |
2 | -- Joseph Weizenbaum's classic Eliza ported to TinyBrain.de |
3 | -- Kein-Hong Man <khman@users.sf.net> 20060905 |
4 | -- Stefan Reich <stefan.reich.maker.of.eye@gmail.com> |
5 | -- This program is hereby placed into PUBLIC DOMAIN |
6 | ------------------------------------------------------------------------ |
7 | -- HOW TO USE |
8 | -- * This program is for recreational purposes only. :-) |
9 | -- * ClassicEliza function will open a new buffer, then type away... |
10 | -- * Eliza recognizes one line of input only (if you are typing very |
11 | -- long lines, please consider seeing a real person.) |
12 | -- * Eliza will not interfere with other buffers or handlers, and is |
13 | -- compatible with extman. |
14 | ------------------------------------------------------------------------ |
15 | -- Original ELIZA paper: |
16 | -- ELIZA--A Computer Program For the Study of Natural Language |
17 | -- Communication Between Man and Machine, |
18 | -- Joseph Weizenbaum, 1966, Communications of the ACM Volume 9, |
19 | -- Number 1 (January 1966): 36-35. |
20 | -- URL: http://i5.nyu.edu/~mm64/x52.9265/january1966.html |
21 | ------------------------------------------------------------------------ |
22 | -- A copy of the original BASIC source of this Lua version of ELIZA can |
23 | -- be found at Josep Subirana's ELIZA download page. |
24 | ------------------------------------------------------------------------ |
25 | |
26 | -- Redefine a Lua 5.0 function still used in this script |
27 | table.getn = function (t) |
28 | if t.n then |
29 | return t.n |
30 | else |
31 | local n = 0 |
32 | for i in pairs(t) do |
33 | if type(i) == "number" then |
34 | n = math.max(n, i) |
35 | end |
36 | end |
37 | return n |
38 | end |
39 | end |
40 | |
41 | ------------------------------------------------------------------------ |
42 | -- Eliza main routine, processes user input |
43 | -- * Input is case insensitive. No punctuation except apostrophes, |
44 | -- as in: don't you're i'm i've you've. |
45 | ------------------------------------------------------------------------ |
46 | local function Eliza(text) |
47 | local response = "" |
48 | local user = string.upper(text) |
49 | local userOrig = user |
50 | |
51 | -- randomly selected replies if no keywords |
52 | local randReplies = { |
53 | "WHAT DOES THAT SUGGEST TO YOU?", |
54 | "I SEE...", |
55 | "I'M NOT SURE I UNDERSTAND YOU FULLY.", |
56 | "CAN YOU ELABORATE ON THAT?", |
57 | "THAT IS QUITE INTERESTING!", |
58 | "THAT'S SO... PLEASE CONTINUE...", |
59 | "I UNDERSTAND...", |
60 | "WELL, WELL... DO GO ON", |
61 | "WHY ARE YOU SAYING THAT?", |
62 | "PLEASE EXPLAIN THE BACKGROUND TO THAT REMARK...", |
63 | "COULD YOU SAY THAT AGAIN, IN A DIFFERENT WAY?", |
64 | } |
65 | |
66 | -- keywords, replies |
67 | local replies = { |
68 | [" CAN YOU"] = "PERHAPS YOU WOULD LIKE TO BE ABLE TO", |
69 | [" DO YOU"] = "YES, I", |
70 | [" CAN I"] = "PERHAPS YOU DON'T WANT TO BE ABLE TO", |
71 | [" YOU ARE"] = "WHAT MAKES YOU THINK I AM", |
72 | [" YOU'RE"] = "WHAT IS YOUR REACTION TO ME BEING", |
73 | [" I DON'T"] = "WHY DON'T YOU", |
74 | [" I FEEL"] = "TELL ME MORE ABOUT FEELING", |
75 | [" WHY DON'T YOU"] = "WHY WOULD YOU WANT ME TO", |
76 | [" WHY CAN'T I"] = "WHAT MAKES YOU THINK YOU SHOULD BE ABLE TO", |
77 | [" ARE YOU"] = "WHY ARE YOU INTERESTED IN WHETHER OR NOT I AM", |
78 | [" I CAN'T"] = "HOW DO YOU KNOW YOU CAN'T", |
79 | [" SEX"] = "I FEEL YOU SHOULD DISCUSS THIS WITH A HUMAN.", |
80 | [" I AM"] = "HOW LONG HAVE YOU BEEN", |
81 | [" I'M"] = "WHY ARE YOU TELLING ME YOU'RE", |
82 | [" I WANT"] = "WHY DO YOU WANT", |
83 | [" WHAT"] = "WHAT DO YOU THINK?", |
84 | [" HOW"] = "WHAT ANSWER WOULD PLEASE YOU THE MOST?", |
85 | [" WHO"] = "HOW OFTEN DO YOU THINK OF SUCH QUESTIONS?", |
86 | [" WHERE"] = "WHY DID YOU THINK OF THAT?", |
87 | [" WHEN"] = "WHAT WOULD YOUR BEST FRIEND SAY TO THAT QUESTION?", |
88 | [" WHY"] = "WHAT IS IT THAT YOU REALLY WANT TO KNOW?", |
89 | [" PERHAPS"] = "YOU'RE NOT VERY FIRM ON THAT!", |
90 | [" DRINK"] = "MODERATION IN ALL THINGS SHOULD BE THE RULE.", |
91 | [" SORRY"] = "WHY ARE YOU APOLOGIZING?", |
92 | [" DREAMS"] = "WHY DID YOU BRING UP THE SUBJECT OF DREAMS?", |
93 | [" I LIKE"] = "IS IT GOOD THAT YOU LIKE", |
94 | [" MAYBE"] = "AREN'T YOU BEING A BIT TENTATIVE?", |
95 | [" NO"] = "WHY ARE YOU BEING NEGATIVE?", |
96 | [" YOUR"] = "WHY ARE YOU CONCERNED ABOUT MY", |
97 | [" ALWAYS"] = "CAN YOU THINK OF A SPECIFIC EXAMPLE?", |
98 | [" THINK"] = "DO YOU DOUBT", |
99 | [" YES"] = "YOU SEEM QUITE CERTAIN. WHY IS THIS SO?", |
100 | [" FRIEND"] = "WHY DO YOU BRING UP THE SUBJECT OF FRIENDS?", |
101 | [" COMPUTER"] = "WHY DO YOU MENTION COMPUTERS?", |
102 | [" AM I"] = "YOU ARE", |
103 | } |
104 | |
105 | -- conjugate |
106 | local conjugate = { |
107 | [" I "] = "YOU", |
108 | [" ARE "] = "AM", |
109 | [" WERE "] = "WAS", |
110 | [" YOU "] = "ME", |
111 | [" YOUR "] = "MY", |
112 | [" I'VE "] = "YOU'VE", |
113 | [" I'M "] = "YOU'RE", |
114 | [" ME "] = "YOU", |
115 | [" AM I "] = "YOU ARE", |
116 | [" AM "] = "ARE", |
117 | } |
118 | |
119 | -- random replies, no keyword |
120 | local function replyRandomly() |
121 | response = randReplies[math.random(table.getn(randReplies))].."\n" |
122 | end |
123 | |
124 | -- find keyword, phrase |
125 | local function processInput() |
126 | for keyword, reply in pairs(replies) do |
127 | local d, e = string.find(user, keyword, 1, 1) |
128 | if d then |
129 | -- process keywords |
130 | response = response..reply.." " |
131 | if string.byte(string.sub(reply, -1)) < 65 then -- "A" |
132 | response = response.."\n"; return |
133 | end |
134 | local h = string.len(user) - (d + string.len(keyword)) |
135 | if h > 0 then |
136 | user = string.sub(user, -h) |
137 | end |
138 | for cFrom, cTo in pairs(conjugate) do |
139 | local f, g = string.find(user, cFrom, 1, 1) |
140 | if f then |
141 | local j = string.sub(user, 1, f - 1).." "..cTo |
142 | local z = string.len(user) - (f - 1) - string.len(cTo) |
143 | response = response..j.."\n" |
144 | if z > 2 then |
145 | local l = string.sub(user, -(z - 2)) |
146 | if not string.find(userOrig, l) then return end |
147 | end |
148 | if z > 2 then response = response..string.sub(user, -(z - 2)).."\n" end |
149 | if z < 2 then response = response.."\n" end |
150 | return |
151 | end--if f |
152 | end--for |
153 | response = response..user.."\n" |
154 | return |
155 | end--if d |
156 | end--for |
157 | replyRandomly() |
158 | return |
159 | end |
160 | |
161 | -- main() |
162 | -- accept user input |
163 | if string.sub(user, 1, 3) == "BYE" then |
164 | response = "BYE, BYE FOR NOW.\nSEE YOU AGAIN SOME TIME.\n" |
165 | return response |
166 | end |
167 | if string.sub(user, 1, 7) == "BECAUSE" then |
168 | user = string.sub(user, 8) |
169 | end |
170 | user = " "..user.." " |
171 | -- process input, print reply |
172 | processInput() |
173 | return response |
174 | end |
175 | |
176 | if input == '' then |
177 | return "I'm Eliza, your virtual psychiatrist. Please tell me about your worries." |
178 | else |
179 | return Eliza(input):gsub('\n+$', '') |
180 | end |
chat to bot test run test run with input download show line numbers
Travelled to 12 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Recognizer | Recognition Result | Visualize | Recalc |
---|---|---|---|
#308 | 6799 | [visualize] |
Snippet ID: | #30 |
Snippet name: | Eliza, your virtual psychiatrist |
Eternal ID of this version: | #30/1 |
Text MD5: | 55d5d748317052f65c6b70894666bbb4 |
Author: | stefan |
Category: | bots |
Type: | Lua code - Chat-bot |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2013-12-21 12:49:00 |
Source code size: | 6799 bytes / 180 lines |
Pitched / IR pitched: | Yes / Yes |
Views / Downloads: | 1427913 / 2454 |
Referenced in: | [show references] |