Skip to content

Instantly share code, notes, and snippets.

@DataKinds
Last active August 29, 2015 14:25
Show Gist options
  • Save DataKinds/f9189a29d3f9702448af to your computer and use it in GitHub Desktop.
Save DataKinds/f9189a29d3f9702448af to your computer and use it in GitHub Desktop.
cinch markov bot
require 'cinch'
require 'cinch/plugins/identify'
require 'json'
LOOKFORWARD = 2 #how many words forward it generates from a seed word
BOTNAME = "MarkovBot"
def prepareString(str)
#return str.downcase.split(/(\W)+/).map{|word| word.gsub(/\s+/, "")}.reject{|word| word == ""} to remind you what it was
return str.split(/\s+/)
end
def addArrayToChain(strArray, chain)
strArray.each_with_index do |currentStr, index|
doneWithString = false
LOOKFORWARD.times do |t|
if strArray[index + t + 1].nil?
doneWithString = true
end
end #break if no more strings can be found up ahead
break if doneWithString
nextStringsArray = [] #make an array of the next strings
LOOKFORWARD.times do |t| nextStringsArray << strArray[index + t + 1] end
nextStrings = nextStringsArray.join(" ")
if !chain.key?(currentStr)
chain[currentStr] = {}
end
if !chain[currentStr].key?(nextStrings)
chain[currentStr][nextStrings] = 0
end
chain[currentStr][nextStrings] += 1
end
File.open("markovbackup.rson", "w") { |file| file.write(JSON.generate(chain)) }
return chain
end
def generateWords(chain, length, topic)
topicWords = topic.split(/\s+/).reject{|word| word.include? BOTNAME}.sort_by(&:length).select{|word| word.length > 2} #select suitable-looking words for the bot to talk about
topicWord = chain.keys.sample #fallback to a random topic
topicWords.each do |word| #try to make the bot talk about them
if !chain[word].nil?
topicWord = word
break
end
end
outputString = []
outputString << topicWord #put the first seed word in
length.times do |currentLength|
lastWord = outputString.last.split(" ").last #this is gross, splits the last phrase to get the last word to use as the next seed
break if chain[lastWord].nil? #if there aren't words to complete the phrase
chanceTable = chain[lastWord]
cdf = 0 #calculating the weighted random, warning: gross
chanceTable.each do |weight|
cdf += weight[1]
end
randomInt = rand(cdf)
runningSum = 0
chanceTable.each_pair do |word, weight|
runningSum += weight
if runningSum > randomInt
outputString << word
break
end
end
end
return outputString.join(" ")
end
class MarkovIRC
include Cinch::Plugin
match /.+/, use_prefix: false #run on anything said
def execute(m)
@@permChain = addArrayToChain(prepareString(m.message), @@permChain)
if m.message.include? BOTNAME
if m.channel.name != "#roblox-bots"
Target(m.user.nick).send("#{generateWords(@@permChain, rand(5)+20, m.message)}")
else
m.reply("#{m.user.nick}: #{generateWords(@@permChain, rand(5)+20, m.message)}")
#m.reply("NotBoringAces: #{generateWords(@@permChain, rand(5)+20, m.message)}")
end
end
end
end
bot = Cinch::Bot.new do
configure do |c|
c.server = "irc.freenode.org"
c.nick = BOTNAME
c.channels = ["#roblox-bots", "#roblox"]
c.delay_joins = :identified
c.plugins.plugins = [MarkovIRC, Cinch::Plugins::Identify]
c.plugins.options[Cinch::Plugins::Identify] = {
:username => "Aearnus",
:password => <dfnsdikfnsdk>,
:type => :nickserv
}
end
end
@@permChain = JSON.parse(File.read("markovbackup.rson"))
sampleText = File.read("sampletext")
@@permChain = addArrayToChain(prepareString(sampleText), @@permChain)
bot.start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment