--[[
BDA: Brain Damaged Algorithm
A natural language parsing and attempting to creating program
Written by: BigSHinyToys
Modified by: NitrogenFingers 28/8/2012 (12:20am)
--]]
local winX, winY = term.getSize()
--Add your stop word lists here- they can be common subjects, participles, or any other grammatical
--feature you'd like to capture. Denote it with a single, lowercase character- this indicates it is a
--terminating symbol
local stopWords = {
["s"] = {"I", "you", "he", "she", "they", "we"};
["v"] = {"is", "are", "am", "can be", "like", "hate", "often", "will", "must", "should", "might"};
["a"] = {"and", "or", ", also", ", but", ", however", "like"};
}
--This list is of words that aren't stop words- they'll be added as you type them
local vocab = {}
local vcLength = 0
local savefile = "Grammerwords"
local convofile = "Grammerconvo"
local function saveTalk(sentence)
local f = fs.open(convofile, "a")
f.write(sentence.."n")
f.close()
end
local function save()
local f = fs.open(savefile, "w")
f.write(textutils.serialize(vocab))
f.close()
end
if fs.exists(savefile) then
local f = fs.open(savefile, "r")
local save = textutils.unserialize(f.readAll())
f.close()
vocab = save
end
--Here you should have tables with capital letters, your non-terminating characters, that include
--all possible rules for your grammar. These tokens will in turn be selected and randomly replaced
--with one of the contents of the table.
--Note: AVOID INFINITE LOOPS: make sure every possible grammar has a terminating-only character string.
local grammar = {
["S"] = {"svW"},
["W"] = {"waW", "wasW", "w"}
}
function readWords()
while true do
local arg1, arg2 = os.pullEvent("new_line")
if arg1 == "new_line" then
local lastMatch = ""
for match in string.gmatch(arg2, "[^ t]+") do
local stop = false
for _,list in pairs(stopWords) do
for _,stopword in pairs(list) do
--If you want to be supersmart you can try to detect stop words and add them
--to your list here- try looking for "ly" for adverbs, "ing" for present tense verbs
--etc.
if match == stopword then
stop = true
break
end
end
end
if not stop then
--We handle linkages here
if not vocab[match] then
--I must admit I'm unsure how to get just the key in a table (there must be a way)
--Anyway I just include the word itself as the first value in the value table. Cheap and dusty.
vocab[match] = {match, ""}
--And of course because it's a string indexed value now it's not included in the array, or the length!
vcLength = vcLength+1
end
if lastMatch ~= "" then
table.insert(vocab[lastMatch], match)
end
lastMatch = match
else
lastMatch = ""
end
end
end
local newGrammar = "S"
local found = false
--This randomly creates your grammar
repeat
found = false
for k,v in pairs(grammar) do
local f = string.find(newGrammar, k)
if f then
newGrammar = string.gsub(newGrammar, k, v[math.random(1, #v)], 1)
found = true
end
end
until not found
--This then randomly replaces your grammar with actual words
local newSentence = ""
for i=1,#newGrammar do
local token = string.sub(newGrammar, i, i)
if token == "w" then
--This is horribly messy- will fix when less tired!
local chosenWord = math.random(1,vcLength)
local i=1
for k,_ in pairs(vocab) do
if i==chosenWord then
chosenWord = k
break
end
i=i+1
end
local chosenLink = vocab[chosenWord][math.random(2,#vocab[chosenWord])]
if chosenLink ~= "" then chosenLink = chosenLink.." " end
--Again cheap and dusty here, the extra space will make sentences look a bit ugly. Requires a little tweaking, but I'm to tired to fix right now.
newSentence=newSentence..vocab[chosenWord][1].." "..chosenLink
else
local newstop = stopWords[token][math.random(1,#stopWords[token])]
--Cheap and dusty (lots of it in this program!) to get rid of extra space
if string.sub(newstop, 1, 1)=="," then newSentence = string.sub(newSentence, 1, #newSentence-1) end
newSentence=newSentence..newstop.." "
end
end
term.scroll(1)
term.setCursorPos(1,winY - 1)
term.clearLine()
save()
local talk = "AI> "..string.sub(newSentence, 1, #newSentence-1).."."
saveTalk(talk)
print(talk)
end
end
function getInput()
while true do
term.setCursorPos(1,winY)
term.clearLine()
local input = read()
saveTalk(input)
os.queueEvent("new_line",input)
end
end
term.clear()
parallel.waitForAny(getInput, readWords)