# This AI related code was written by Gregory Brown # In order to understand it, I had to write comments. I hoped that Ruby is more similar to Python than it actually is :( # Note that I used Python syntax highlighter, so colors may not be exactly those that you are used to in Ruby
class Conversation
def initialize(person)
@person = person # so far so good. learned what @ is for
@response_id = 0 # initial response will be from id 0 pattern match
end
attr_reader :response_id # defines getter method
def say(msg)
print "#{@person}: "
@response_id = Response[@response_id].respond_to(msg) # when this is called, responses are already defined; each new response updates current id
end
class Response # subclass
def self.responses
@responses ||= {} # is this 'OR' assignment?
end
def self.[](id) # self.[]?
responses[id] # what happens here?
end
def initialize(id)
@id = id
self.class.responses[id] = self # creates instances of subclasses for each id ?
# clears arrays for each new instance:
@matchers = [] # word patterns to recognize and to respond to ...->
@messages = [] # ...-> with these massages
end
attr_reader :id,:matchers # defines getter method
def when(pattern,id)
@matchers << [pattern,id] # add pattern to matchers array
end
def inherits(arr)
arr.each do |id|
@matchers += Response[id].matchers # add inherited patterns to matchers array
end
end
def might_say(msg,weight=1)
weight.times do
@messages << msg # add msg to messages array
end
end
def talk
puts @messages.sort_by { rand }.pop # say random message
end
def respond_to(msg)
@matchers.each do |pattern,id| # for each matchers if similar to msg, talk and return id.
if msg =~ pattern
Response[id].talk # response(id) is given, not the one where pattern was matched!
return id # update response_id in say function
end
end
return @id # otherwise, no pattern match, and remain silent
end
end
end
def response(id)
r = Conversation::Response[id] || Conversation::Response.new(id) # if doesn't exist, define new response
yield(r)
end
# Example use
c = Conversation.new("Ralph")
# define few possible responses for different pattern matches
response(0) { |r|
r.might_say "Hello" # these 2 might_say's are never really considered! responses always come from 1, 3, or 4
r.might_say "Hi"
r.when /Hello/i, 1 # if has case insensitive 'hello' in the sentence, update id to 1
}
response(1) { |r|
r.might_say "Hello"
r.might_say "Hi"
r.might_say "Howdy"
r.when /Hello/i, 4 # if has case insensitive 'hello' in the sentence, update id to 4
r.when /./, 3 # anything else, asign id 3
}
response(3) { |r|
r.might_say "Finally, something interesting"
r.inherits [1]
# or:
# r.might_say "Hello"
# r.might_say "Hi"
# r.might_say "Howdy"
# r.when /Hello/i, 4
# r.when /./, 3
}
response(4) { |r|
r.might_say "You already said that, didn't you?"
r.inherits [1]
}
# finally, execution: tracking backwards all the steps, from say -> respond_to -> talk
loop do
print "Greg: "
r = gets # user input
c.say(r) # find response with pattern match and current id (0 at begining)
end