require 'yaml' require 'wordnet' class MyAgent def initialize @MY_NAME = "(?i)wnbot" @score = 1 @DEFAULT_SCORE = 1 @filename = File.expand_path(File.dirname(__FILE__)) << "/patterns.yaml" load_message = load_synonyms if load_message == false @patterns = [ [/^(.*?) is a synonym for (.*)/, :add_synonym], [/^save syn/, :save_synonyms], [/^load syn/, :load_synonyms] ] save_synonyms else puts load_message end @method_def = '' @wordnet = Wordnet.new end def define_method method_def file = IO.read(__FILE__.to_s) return "Doesn't have 'end # class'" unless file =~ /(.*)end # class(.*)if \$0 == __FILE__(.*)/m grp1 = $1.to_s grp2 = $2.to_s grp3 = $3.to_s new_filename = get_new_filename File.open(new_filename, "w+") { |f| f.puts grp1 << method_def << "\nend # class\n\nif $0 == __FILE__" << grp3 } @patterns.push( [@new_regexp, @new_symbol] ) save_synonyms exec "ruby #{new_filename}" end def get_new_filename old_filename = __FILE__.to_s if old_filename =~ /(.*)\.(\d+)\.rb$/ incr = $2.to_s.to_i + 1 return new_filename = $1.to_s << "." << incr.to_s << ".rb" end #return "temp.0.rb" return old_filename # Dangerous! end def getResponse input r = "Default response." # In input is addressed to us, increment score. if input =~ /^(?:#{@MY_NAME}[:,!]* )(.*)/ input = $1.to_s #puts "[wnbot.getResponse]: $1=" << $1 @score += 1 end @patterns.each { |pattern| if input =~ /^add pattern (.*), (.*)/ # preprocess new_pattern to remove obvious delimeters, etc. @new_regexp = $1.to_s @new_symbol = $2.to_s @new_regexp.gsub!(/\//, '') @new_regexp = %r{#{@new_regexp}} method_def = " def #{@new_symbol}(pattern=nil, input=nil)\n return 'Default response from " << @new_symbol << "'\n end # method_def" return define_method(method_def) end if input =~ /define method: (.*) \nend #method_def$/m return define_method($1.to_s) end if input =~ /^>:q$/ or input =~ /^>$/ #puts "OK STOPPING RECORDING METHOD_DEF" if @method_def =~ /^ *; *def(.*)/ @method_def = "def" << $1.to_s end return define_method(@method_def) end if input =~ /^>(.*)/ #puts "OK RECORDING METHOD_DEF" @method_def << "\n " << $1.to_s if @method_def =~ /end # method_def/ # No longer necessary? #if @method_def =~ /^ *; *def(.*)/ # @method_def = "def" + $1.to_s #end # return define_method(@method_def) end return '' end if input =~ pattern[0] return self.send(pattern[1], pattern[0], input) end } if r =~ /^Default response/; @score -= 1; end return r end def load_synonyms(pattern=nil, input=nil) if File.exist?(@filename) @patterns = YAML.load_file(@filename) return "I have loaded #{@filename}." end return false end def save_synonyms(pattern=nil, input=nil) r = "Eep! error saving synonyms! " begin File.open(@filename, 'w') do |out| YAML.dump(@patterns, out) end return "OK I have saved the synonyms to disk." rescue => error return r << error end end def add_synonym(pattern, input) return "Problem matching pattern." unless input =~ pattern grp1 = %r{^#{$1}} grp2 = %r{^#{$2}} method ='' @patterns.each { |p| if p[0] == grp2 method = p[1] break end } return unless method.to_s != nil @patterns.push( [grp1, method] ) save_synonyms return "OK, #{grp1} has been added, and will now call #{method}." end def method_missing input return getResponse(input.to_s) end def preprocess input input.strip! input.gsub!(/\?$/, '') input.gsub!(/^"/, '') input.gsub!(/"$/, '') return input end def process input input = input.to_s input.strip! input.sub!(/(\, *)*$/, '') input.sub!(/^(\, *)*/, '') return input end def getScore r = @score @score = @DEFAULT_SCORE return r end def syns(pattern=nil, input=nil) r = '' if input =~ pattern input = $1.to_s input = preprocess(input) else return "#{input} doesn't match #{pattern}." end syns_opts = [ "n", "v", "a", "r" ] begin syns_opts.each { |opt| r << @wordnet.getResponse("wn " << input << " -syns#{opt}") << ", " } @score += 1 rescue => error r = "Eep! Problem starting wordnet: #{error}" end return process(r) end # method_def def over(pattern=nil, input=nil) r = "" if input =~ pattern input = $1.to_s input = preprocess input else return "Eep! #{pattern} does not match #{input}." end begin r = @wordnet.getResponse("wn " << input << " -over") @score += 1 rescue => error r = "Eep! I can't access wordnet. #{error}" end if r == nil or r == '' return "I don't have an entry for #{input}." end return process(r) end # method_def def wn_raw_command(pattern=nil, input=nil) r = "" if input =~ pattern grp1 = $1.to_s else return "#{pattern} does not match #{input}." end begin r = @wordnet.getResponse(grp1) @score += 1 rescue => error r = "Problem submitting #{grp1} to Wordnet: #{error}" end return process(r) end # method_def def wn_help(pattern=nil, input=nil) r = "" if input =~ pattern else return "#{pattern} does not match #{input}." end begin r = @wordnet.getResponse("wn help") @score += 1 r.gsub!(/\t/, ' ') rescue => error r = "Problem submitting 'wn help' to Wordnet: #{error}" end return r end # method_def def restart(pattern=nil, input=nil) exec("ruby myagent.rb") end # method_def end # class if $0 == __FILE__ bot = MyAgent.new print "\n> "; $stdout.flush quitwords = [":q", "quit", "exit", "bye"] while (line = gets) !~ /^#{quitwords.join('|')}$/ and line !~ /^$/ print bot.send(line.to_s) << "\n\n" print "> "; $stdout.flush end end # of file