learningBot = {}-- Choose what dictionary that should be used at startuplearningBot.startingDictionary = "default.lua"-- Some default settings in case loading the dictionary failslearningBot.options = {}learningBot.options.name = "Failed"learningBot.options.dictionary = "default.lua"learningBot.options.acceptNewWords = truelearningBot.options.maxWords = 1000learningBot.options.replaceWords = truelearningBot.options.maxOccurancesForReplace = 10learningBot.options.acceptInput = truelearningBot.data = {}learningBot.data.numWords = 0learningBot.dictionary = {}-- Handle text and update the dictionarylearningBot.handleInput = function(sentence) if learningBot.options.acceptInput == false then return end -- Lowercase the sentence sentence = string.lower(sentence) -- Remove all punctuations sentence = string.gsub(sentence, "%p", "") -- Trim the string (remove spaces at the begining and the end) sentence = string.sub(sentence, string.find(sentence, "[^%s]"), -1) while string.char(string.byte(sentence, -1)) == " " do sentence = string.sub(sentence, 1, -2) end -- Remove all double, triple etc, spaces sentence = string.gsub(sentence, "%s%s+", " ") local words = learningBot.explode(" ", sentence) for k,v in pairs(words) do -- If it's a new word, create a base template if learningBot.dictionary[v] == nil then if learningBot.options.acceptNewWords == true and learningBot.data.numWords < learningBot.options.maxWords then -- Create space for the new word learningBot.dictionary[v] = {} learningBot.dictionary[v][1] = 0 learningBot.dictionary[v][2] = 0 learningBot.data.numWords = learningBot.data.numWords + 1 elseif learningBot.options.replaceWords == true then -- Replace the most rarely used word local tmpLowestOccurances = 9999 local tmpLowestKey = 1 local tmptmpOccurances = 0 for k2,v2 in pairs(learningBot.dictionary) do tmptmpOccurances = 0 for k3,v3 in pairs(v2) do tmptmpOccurances = tmptmpOccurances + v3 end if tmptmpOccurances < tmpLowestOccurances then tmpLowestOccurances = tmptmpOccurances tmpLowestKey = k2 end end -- Only replace if we have a well established dictionary if tmpLowestOccurances < learningBot.options.maxOccurancesForReplace then -- Remove all occurances of tmpLowestKey learningBot.dictionary[tmpLowestKey] = nil for k2,v2 in pairs(learningBot.dictionary) do if v2[tmpLowestKey] ~= nil then v2[tmpLowestKey] = nil end end -- Create space for the new word learningBot.dictionary[v] = {} learningBot.dictionary[v][1] = 0 learningBot.dictionary[v][2] = 0 end end end if learningBot.dictionary[v] ~= nil then -- Check if next word exists or not (sentence end) if k ~= table.getn(words) then if learningBot.dictionary[v][words[k+1]] == nil then learningBot.dictionary[v][words[k+1]] = 0 end -- Increase number of occurances of the next word following this one learningBot.dictionary[v][words[k+1]] = learningBot.dictionary[v][words[k+1]] + 1 else if learningBot.dictionary[v][2] == nil then learningBot.dictionary[v][2] = 0 end -- Increase number of occurances of "" following this one learningBot.dictionary[v][2] = learningBot.dictionary[v][2] + 1 end end end -- Increase number of sentence starter occurances for the first word if learningBot.dictionary[words[1]] ~= nil then if learningBot.dictionary[words[1]][1] == nil then learningBot.dictionary[words[1]][1] = 0 end learningBot.dictionary[words[1]][1] = learningBot.dictionary[words[1]][1] + 1 endend-- Return a sentence constructed from the dictionary. Start with 'word' if it is declaredlearningBot.createSentence = function(word) if word == nil then -- max_random is used to pick a word with higher probability to get a more commonly used one (as a sentence starter) local max_random = 0 for k,v in pairs(learningBot.dictionary) do max_random = max_random + learningBot.dictionary[k][1] end random = math.random(0, max_random) word = 1 local wordOccurance = 0 -- Get the first word for k,v in pairs(learningBot.dictionary) do wordOccurance = wordOccurance + learningBot.dictionary[k][1] -- We found the word if wordOccurance >= random then word = k break end end end -- Print the words until nil is returned local sentence = "" while word ~= nil do sentence = sentence..word.." " word = learningBot.pickNextWord(word) end sentence = string.upper(string.sub(sentence, 0, 1))..string.sub(sentence, 2, -2).."." return sentenceend-- Return a word suited to follow 'word'. Returns nil if end of sentence is suitablelearningBot.pickNextWord = function(word) if learningBot.dictionary[word] == nil then return end local max_random = 0 for k,v in pairs(learningBot.dictionary[word]) do if k ~= 1 then max_random = max_random + v end end local random = math.random(max_random) local wordOccurance = 0 for k,v in pairs(learningBot.dictionary[word]) do if k ~= 1 then wordOccurance = wordOccurance + v if wordOccurance >= random then if k == 2 then return nil end return k end end endend-- Saves the dictionary in a seperate file and select it for further inputlearningBot.saveDictionary = function(filename) if filename == nil then filename = learningBot.options.dictionary end if string.find(filename, "..") or string.find(filename, ":") then _Msg("Suspected attempt to overwrite system files. Aborting.\n") return end local fileString = "learningBot.options = {}\n\n" -- Save options learningBot.options.dictionary = filename for k,v in pairs(learningBot.options) do if type(v) ~= "string" then fileString = fileString.."learningBot.options."..k.." = "..tostring(v).."\n" else fileString = fileString.."learningBot.options."..k.." = \""..tostring(v).."\"\n" end end fileString = fileString.."\n\nlearningBot.dictionary = {}\n\n" -- Save the dictionary, word table declaration for k,v in pairs(learningBot.dictionary) do fileString = fileString.."learningBot.dictionary[\""..k.."\"] = {}\n" end fileString = fileString.."\n\n" -- Save dictionary, word table elements for k,v in pairs(learningBot.dictionary) do for k2,v2 in pairs(v) do if type(k2) == "string" then fileString = fileString.."learningBot.dictionary[\""..k.."\"][\""..k2.."\"] = "..v2.."\n" else fileString = fileString.."learningBot.dictionary[\""..k.."\"]["..k2.."] = "..v2.."\n" end end fileString = fileString.."\n" end --local file = io.open(filename, "w+") --file:write(fileString) --file:close() _file.Write("lua/lbdict/"..filename, fileString) _Msg("Learning-Bot Dictionary ("..filename..") has been saved!\n")endlearningBot.loadDictionary = function(filename) if filename == nil then filename = learningBot.options.dictionary end --dofile(filename) _OpenScript("lua/lbdict/"..filename) -- Calculate the number of words in the dictionary learningBot.data.numWords = 0 for k,v in pairs(learningBot.dictionary) do learningBot.data.numWords = learningBot.data.numWords + 1 end _Msg("Learning-Bot Dictionary ("..filename..") has been loaded!\n")endlearningBot.explode = function(d,p) local t,ll,l t={} ll=0 while true do l=string.find(p,d,ll+1,true) -- find the next d in the string if l~=nil then -- if "not not" found then.. table.insert(t, string.sub(p,ll,l-1)) -- Save it in our array. ll=l+1 -- save just after where we found it for searching next time. else table.insert(t, string.sub(p,ll)) -- Save what's left in our array. break -- Break at end, as it should be, according to the lua manual. end end return tend-- **********GMOD SPECIFIC CODE FOLLOWS HERE, keep above code as Lua universal as possible*************-- Load the default dictionary immediatelylearningBot.loadDictionary(learningBot.startingDictionary)learningBot.startingDictionary = nil-- Talks with chosen output methodlearningBot.talk = function(word) _PrintMessageAll(HUD_PRINTTALK, learningBot.options.name..": "..learningBot.createSentence(word))end-- Talk "locally". Which means another output methodlearningBot.talkLocal = function(propid) if _EntExists(propid) then _GModText_Start("Default") _GModText_SetColor(255, 255, 255, 255) _GModText_SetTime(4, 0.25, 0.5) _GModText_SetEntityOffset(vector3(0, 0, 48)) _GModText_SetEntity(propid) _GModText_SetText(learningBot.options.name..": "..learningBot.createSentence()) _GModText_Send(0, 3100+propid)--[[ _GModText_Start("Default") _GModText_SetEntity(propid) _GModText_SetTime(4, 1, 1) _GModText_SetText(learningBot.options.name..": "..learningBot.createSentence()) _GModText_SetEntityOffset(vector3(0, 0, 32)) _GModText_Send(0, propid + 31000) -- Paranoia]] endend-- Handles input from console command 'learnbot'learningBot.handleCommand = function(userid, arg) if arg == nil then _PrintMessage(userid, HUD_PRINTCONSOLE, learningBot.options.name..":\nDictionary size: "..learningBot.data.numWords.."\nAccepts input: "..tostring(learningBot.options.acceptInput).."\nAccepts new words: "..tostring(learningBot.options.acceptNewWords).."\nMax number of words allowed in dictionary: "..tostring(learningBot.options.maxWords).."\nReplaces words when dictionary is full: "..tostring(learningBot.options.replaceWords).."\nMax frequency of word to allow it being replaced: "..tostring(learningBot.options.maxOccurancesForReplace).."\n\n--Commands".."\nlearnbot spawn".."\nlearnbot save <filename(optional)>".."\nlearnbot load <filename(optional)>") return end local args = learningBot.explode(" ", arg) if args[1] == "spawn" then _TraceLine(_PlayerGetShootPos(userid), _PlayerGetShootAng(userid), 9999, userid) learningBot.data.entity = _EntCreate("npc_dog") _EntSetPos(learningBot.data.entity, vecAdd(_TraceEndPos(), vector3(0,0,64))) _EntSetName(learningBot.data.entity, "learnbot") _EntSpawn(learningBot.data.entity) end if args[1] == "save" then learningBot.saveDictionary(args[2]) elseif args[1] == "load" then learningBot.loadDictionary(args[2]) endendCONCOMMAND("learnbot", learningBot.handleCommand)-- Speak every 4 minutesAddTimer(240, 0, learningBot.talk)-- Speak locally every 200 secondsAddTimer(200, 0, learningBot.talkLocal)-- Save the dictionary every 2 minutesAddTimer(120, 0, learningBot.saveDictionary)-- Talk when a player someone is killedHookEvent("eventPlayerKilled", function(userid, attacker, weapon) learningBot.talk() end)-- Talk when the bot's name is mentioned. Respond in some cases. Othervise, input the text into the dictionaryHookEvent("eventPlayerSay", function(userid, strText, bTeam) -- Remove the "PlayerName: " in the string strText = string.sub(strText, string.len(_PlayerInfo(userid, "name")) + 3) -- Check if the bot's name is mentioned if string.find(string.lower(strText), string.lower(learningBot.options.name)) then words = learningBot.explode(" ", string.lower(strText)) -- Check if there's two words and the last one ends with "?" if table.getn(words) == 2 and string.char(string.byte(words[2], -1)) == "?" then -- Remove the "?" words[2] = string.sub(words[2], 1, -2) if string.find(words[1], string.lower(learningBot.options.name)) then learningBot.talk(words[2]) else learningBot.talk(words[1]) end else learningBot.talk() end else learningBot.handleInput(strText) endend)-- Check if the bot has been "used" and speak "locally" if that is the case.HookEvent("eventPlayerUseEntity", function(userid, propid) if _EntGetName(propid) == "learnbot" then learningBot.talkLocal(propid) endend)