patternMinor
Very basic chatbot
Viewed 0 times
chatbotbasicvery
Problem
Was the best way to implent this? For example it will only say "It's nice I know." If you first ask "hat" and then answer "yes".
This is how I'm thinking:
Functions
This is how I'm thinking:
Topic = 0
local messages = {
{"name", "I'm Bob, the owner of this little shop."},
{"job", "I sell stuff."},
{"hat|head", "You like my hat?", Topic = 1},
{Topic == 1, "yes", "It's nice I know."}}
for i, a in ipairs(messages) do
if isMsg(a[1], msg) then
makeSay(a[2])
return true
end
endFunctions
function isMsg(messages, msg)
local keys = split(messages, "|")
if getmsg(keys, msg) then
return true
end
return false
end
function table.contains(table, element)
for _, value in ipairs(table) do
if value == element then
return true
end
end
return false
end
function getmsg(t, msg)
for v, a in ipairs(t) do
if msgcontains(msg, a) then
return true
end
end
return false
end
function keyContains(t, msg)
for v, t in ipairs(t) do
if t == msg then
return true
end
end
return false
end
function split(str, pat)
local t = {} -- NOTE: use {n = 0} in Lua-5.0
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
endSolution
I see a lot of problems here...
Use Hash-Tables
Lua has a pretty fast implementation of them, so your decision code could be made a lot faster - and easier to read like this
Now for the topics. I will skip the part where you "revert" from topics, since you have to know yourself whether you need to "cancel out" or "time out" or don't allow it in general.
You could also implement random answers quite easily by just adding more integer key values and selecting one with
if there are duplicate topics, just duplicate the table. Yeah it looks like a big overhead but in most cases it doesn't really matter. An alternative is just referencing the table like
Though that might get hard to maintain. There are other options but my answer would just get longer and longer...
- are the answers selectable in the GUI? If not such predefined answers are not quite user-friendly, prone to typos etc.
- You might have to escape strings with "|" then unescape them. Yes chances are low, but that's how bugs start.
- Use closures. Do not redefine your table every time you run that function
for k,v in ipairs(tbl)is a lot slower thanfor i, #tbl do
- Is there an actual difference between
keyContainsandtable.contains?
Use Hash-Tables
Lua has a pretty fast implementation of them, so your decision code could be made a lot faster - and easier to read like this
local messages = {
["name"] = "I'm Bob, the owner of this little shop.",
["job"] = "I sell stuff.",
}
function getanswer(question)
return messages[question];
end- Since Lua hashes all strings anyway you will almost always win using hashtables.
- Your string can contain any value
- it's a lot easier to read.
Now for the topics. I will skip the part where you "revert" from topics, since you have to know yourself whether you need to "cancel out" or "time out" or don't allow it in general.
local messages = {
[1] = "Hello stranger!",
["name"] = "I'm Bob, the owner of this little shop.",
["job"] = "I sell stuff.",
["hat"] = {
[1] = "You like my hat?",
["yes"] = "It's nice I know.",
["no"] = "You ...!",
},
}
local topic = messages;
function getanswer(question)
if type(topic[question]) == "table" then
topic = topic[question];
return topic[1];
else
return topic[question];
end
endYou could also implement random answers quite easily by just adding more integer key values and selecting one with
math.random(1, #topic)if there are duplicate topics, just duplicate the table. Yeah it looks like a big overhead but in most cases it doesn't really matter. An alternative is just referencing the table like
messages.head = messages.hat;Though that might get hard to maintain. There are other options but my answer would just get longer and longer...
Code Snippets
local messages = {
["name"] = "I'm Bob, the owner of this little shop.",
["job"] = "I sell stuff.",
}
function getanswer(question)
return messages[question];
endlocal messages = {
[1] = "Hello stranger!",
["name"] = "I'm Bob, the owner of this little shop.",
["job"] = "I sell stuff.",
["hat"] = {
[1] = "You like my hat?",
["yes"] = "It's nice I know.",
["no"] = "You ...!",
},
}
local topic = messages;
function getanswer(question)
if type(topic[question]) == "table" then
topic = topic[question];
return topic[1];
else
return topic[question];
end
endmessages.head = messages.hat;Context
StackExchange Code Review Q#14236, answer score: 7
Revisions (0)
No revisions yet.