Permalink
Browse files

Version 1.0: Initial upload

  • Loading branch information...
0 parents commit f64dea49dfe89a6e33812d631bc8033d3fb7687b Michael Kamensky committed with Oct 12, 2012
Showing with 481 additions and 0 deletions.
  1. +124 −0 README
  2. +96 −0 README.orig
  3. +261 −0 plugin/VimChatBot.vim
124 README
@@ -0,0 +1,124 @@
+This is a mirror of http://www.vim.org/scripts/script.php?script_id=4264
+
+Agetian's Vim ChatBot (C) 2012 by Michael Kamensky, all rights reserved.
+This script is distributed under Vim license.
+==============================================================================
+
+Vim ChatBot is a simple self-teaching chat bot game for Vim. It will try to
+communicate with the human and will accumulate the human's questions and answers
+over time, utilizing them later and trying to mimic human behavior. This chat
+bot is not meant to be smart, at best it resembles a talking parrot and it's far
+from being a real human-like chat robot companion. It's meant to be fun and it
+was originally intended as a little project to teach myself how to script Vim.
+
+IMPORTANT -- READ BEFORE USING OR DON'T TELL ME YOU WERE NOT WARNED:
+====================================================================
+
+Vim ChatBot will use the currently open file in the buffer as a source and as a
+target for its database of known questions and replies! It will automatically
+append new lines to the end of the current file as it learns the phrases from
+the human! Therefore, if you were working on some important document prior to
+starting the chat bot, make sure you switch to a new document or open your chat
+database before initiating a conversation.
+
+Vim ChatBot will never automatically save the file for you though, and it's
+always up to you to decide if you want to save the updated database or not. You
+should do it explicitly using the :write (or another command) to save the file.
+
+Vim ChatBot utilizes the concept of a here-document (similar to here-documents
+in bash) to be able to store its database of known questions and replies in the
+script file itself. When VimChatBot.vim is opened in Vim, the chat bot will
+automatically append new entries to the end of the script file as it learns new
+phrases from you, and it will not corrupt the script file. If you'd like to keep
+the updated database, you need to make sure you save the script file (:w or :x)
+after you're done chatting.
+
+Starting the Vim ChatBot
+========================
+
+By default, Vim ChatBot maps itself to the <Leader>Cb command in normal mode
+(<Leader> is the backslash symbol by default, so unless you've changed your
+leader, the default command to start Vim Chatbot is \Cb ).
+
+If the <Leader>Cb command is already taken by something among your scripts, feel
+free to change the mapping (just search for nnoremap in the script file and
+change the mapping to another combination of keys).
+
+Macros
+======
+
+You can use the following macros when typing answers, the bot will also utilize
+them when learning to use the phrase from you:
+
+$TIME$ - refers to the current time.
+$TIME12$ - (experimental) refers to the current time in 12-hour format.
+$DAY$ - refers to the current day.
+$WEEKDAY$ - refers to the current day of the week.
+$MONTH$ - refers to the current month.
+$YEAR$ - refers to the current year.
+
+Finishing the conversation
+==========================
+
+To finish the conversation, type /Q into the "You Say:" prompt. Unless you are
+asked something (or told something) by the bot and it's waiting for you to teach
+it how to reply to that, /Q will end the conversation immediately. If, however,
+the bot is waiting for your reply to learn something from you, /Q will merely
+inform the bot that you don't have the intention to answer the question. If you
+want to quit the conversation altogether, you will need to type /Q again.
+
+Ctrl+C can be used as the universal quit command if you want to quit chatting
+when in the middle of a bot-asked question and when you don't feel like typing
+/Q twice.
+
+Magical contexts
+================
+
+By default, Vim ChatBot treats the first two responses as special, that is, the
+bot will store a separate set of responses for the phrases you type as your
+first and as your second lines, and will respond accordingly. This is to prevent
+absolute stupidity, such as saying "Hi!" in the middle of a conversation. The
+number of "magical contexts" (responses which should be treated specially) can
+be modified and is stored in the s:MagicalContexts variable.
+
+Database Modification
+=====================
+
+You can modify the database manually by adding or removing phrases in case you
+are not satisfied with something that the bot has learned or would like to teach
+it something without having to go through the process of teaching-by-chatting.
+
+The database for Vim ChatBot is stored in the following way:
+
+<Phrase>:::[MagicalContextID]
+<Response1>
+<Response2>
+...
+<BLANK_LINE>
+
+Quirks
+======
+
+The database structure described above has an important consequence: when
+speaking to Vim ChatBot, never use a triple colon (:::) symbol in your phrases,
+they will confuse the bot and may make it behave more stupidly than normal.
+
+In the beginning of the conversation, the bot might seem not to recognize some
+of the phrases you taught it before - this is due to the magical contexts
+kicking in, the bot hasn't yet been taught to recognize that specific phrase in
+that particular position. This is normal behavior, just patiently repeat the
+lesson.
+
+If you have a Python-enabled version of Vim, ChatBot will utilize the Python
+random number generation algorithm from the "random" library. If your Vim is not
+Python-enabled, a simpler algorithm will be utilized instead, based on the idea
+suggested by Bee-9 at:
+http://vim.1045645.n5.nabble.com/simple-16-bit-random-number-generator-td2843842.html
+This algorithm is less efficient and will produce less random numbers, which may
+or may not be apparent in the actual conversation with the bot (your mileage may
+vary). At any rate, a Python-enabled Vim is recommended for more randomness, but
+not strictly required.
+
+==============================================================================
+Remember: Don't take Vim ChatBot seriously and just have fun! :)
+
96 README.orig
@@ -0,0 +1,96 @@
+Agetian's Vim ChatBot (C) 2012 by Michael Kamensky, all rights reserved.
+This script is distributed under Vim license.
+==============================================================================
+
+Vim ChatBot is a simple self-teaching chat bot game for Vim. It will try to
+communicate with the human and will accumulate the human's questions and answers
+over time, utilizing them later and trying to mimic human behavior. This chat
+bot is not meant to be smart, at best it resembles a talking parrot and it's far
+from being a real human-like chat robot companion. It's meant to be fun and it
+was originally intended as a little project to teach myself how to script Vim.
+
+IMPORTANT -- READ BEFORE USING OR DON'T TELL ME YOU WERE NOT WARNED:
+====================================================================
+
+Vim ChatBot will use the currently open file in the buffer as a source and as a
+target for its database of known questions and replies! It will automatically
+append new lines to the end of the current file as it learns the phrases from
+the human! Therefore, if you were working on some important document prior to
+starting the chat bot, make sure you switch to a new document or open your chat
+database before initiating a conversation.
+
+Vim ChatBot will never automatically save the file for you though, and it's
+always up to you to decide if you want to save the updated database or not. You
+should do it explicitly using the :write (or another command) to save the file.
+
+Vim ChatBot utilizes the concept of a here-document (similar to here-documents
+in bash) to be able to store its database of known questions and replies in the
+script file itself. When VimChatBot.vim is opened in Vim, the chat bot will
+automatically append new entries to the end of the script file as it learns new
+phrases from you, and it will not corrupt the script file. If you'd like to keep
+the updated database, you need to make sure you save the script file (:w or :x)
+after you're done chatting.
+
+Starting the Vim ChatBot
+========================
+
+By default, Vim ChatBot maps itself to the <Leader>Cb command in normal mode
+(<Leader> is the backslash symbol by default, so unless you've changed your
+leader, the default command to start Vim Chatbot is \Cb ).
+
+If the <Leader>Cb command is already taken by something among your scripts, feel
+free to change the mapping (just search for nnoremap in the script file and
+change the mapping to another combination of keys).
+
+Alternatively, you can start Vim ChatBot by typing the following command:
+:call MainChatLoop()
+
+Finishing the conversation
+==========================
+
+To finish the conversation, type /Q into the "You Say:" prompt. Unless you are
+asked something (or told something) by the bot and it's waiting for you to teach
+it how to reply to that, /Q will end the conversation immediately. If, however,
+the bot is waiting for your reply to learn something from you, /Q will merely
+inform the bot that you don't have the intention to answer the question. If you
+want to quit the conversation altogether, you will need to type /Q again.
+
+Ctrl+C can be used as the universal quit command if you want to quit chatting
+when in the middle of a bot-asked question and when you don't feel like typing
+/Q twice.
+
+Magical contexts
+================
+
+By default, Vim ChatBot treats the first two responses as special, that is, the
+bot will store a separate set of responses for the phrases you type as your
+first and as your second lines, and will respond accordingly. This is to prevent
+absolute stupidity, such as saying "Hi!" in the middle of a conversation. The
+number of "magical contexts" (responses which should be treated specially) can
+be modified and is stored in the s:MagicalContexts variable.
+
+Database Modification
+=====================
+
+You can modify the database manually by adding or removing phrases in case you
+are not satisfied with something that the bot has learned or would like to teach
+it something without having to go through the process of teaching-by-chatting.
+
+The database for Vim ChatBot is stored in the following way:
+
+<Phrase>:::[MagicalContextID]
+<Response1>
+<Response2>
+...
+<BLANK_LINE>
+
+Quirks
+======
+
+The database structure described above has an important consequence: when
+speaking to Vim ChatBot, never use a triple colon (:::) symbol in your phrases,
+they will confuse the bot and may make it behave more stupidly than normal.
+
+==============================================================================
+Remember: Don't take Vim ChatBot seriously and just have fun! :)
+
261 plugin/VimChatBot.vim
@@ -0,0 +1,261 @@
+" Self-teaching chat bot (C) 2012 by Michael Kamensky, all rights reserved.
+" This script is distributed under Vim license.
+" =========================================================================
+
+let s:ChatIteration = 1
+let s:MagicalContexts = 2
+let s:BotVersion = "1.0"
+
+function! Random(min, max)
+ if has("python")
+ python from random import randint
+ python from vim import command, eval
+ python command("return %d" % randint(int(eval("a:min")), int(eval("a:max"))))
+ else
+ let s:random_val = localtime() % 65536
+ let s:random_val = (s:random_val * 31421 + 6927) % 65536
+ let s:constrained_val = (s:random_val * a:max) / 65536 + a:min
+ return s:constrained_val
+ endif
+endfunction
+
+function! GetLineMatchingPattern(pattern)
+ let s:num_line = 1
+ let s:max_line = line("$")
+ while s:num_line != s:max_line
+ if getline(s:num_line) =~ a:pattern
+ return s:num_line
+ endif
+ let s:num_line += 1
+ endwhile
+ return -1
+endfunction
+
+function! CountResponses(start_line)
+ let s:num_responses = 0
+ let s:cur_line = a:start_line + 1
+ let s:max_line = line("$")
+ if a:start_line <= 0
+ return -1
+ endif
+ while s:cur_line < s:max_line
+ if getline(s:cur_line) =~ "^\\s*$"
+ break
+ endif
+ let s:cur_line += 1
+ let s:num_responses += 1
+ endwhile
+ return s:num_responses
+endfunction
+
+function! HasResponse(start_line, resp)
+ let s:has_response = 0
+ let s:cur_line = a:start_line + 1
+ let s:max_line = line("$")
+ if a:start_line <= 0
+ return -1
+ endif
+ while s:cur_line < s:max_line
+ if getline(s:cur_line) =~ a:resp
+ let s:has_response = 1
+ break
+ elseif getline(s:cur_line) =~ "^\\s*$"
+ break
+ endif
+ let s:cur_line += 1
+ endwhile
+ return s:has_response
+endfunction
+
+function! AI_AddResponse(pattern, new_resp, iteration)
+ let s:signature = ":::"
+ if a:iteration <= s:MagicalContexts
+ let s:signature = s:signature . a:iteration
+ endif
+ let s:resp_block = GetLineMatchingPattern(a:pattern . s:signature)
+ if s:resp_block == -1
+ call AI_Store_New_Response(a:pattern, a:new_resp, a:iteration)
+ return 0
+ endif
+ let s:has_resp = HasResponse(s:resp_block, a:new_resp)
+ if s:has_resp == 1
+ return -1
+ endif
+ execute ("normal " . s:resp_block . "gg")
+ execute ("normal o" . a:new_resp)
+ return 0
+endfunction
+
+function! AI_Decide_Response(pattern)
+ let s:resp_block = GetLineMatchingPattern(a:pattern)
+ if s:resp_block == -1
+ return -1
+ endif
+ let s:has_resp = HasResponse(s:resp_block, a:pattern)
+ if s:has_resp == -1
+ return -1
+ endif
+ let s:num_responses = CountResponses(s:resp_block)
+ return s:resp_block + Random(1, s:num_responses)
+endfunction
+
+function! AI_Store_New_Response(pattern, response, iteration)
+ execute ("normal Go")
+ if a:iteration <= s:MagicalContexts
+ execute ("normal o" . a:pattern . ":::" . a:iteration)
+ else
+ execute ("normal o" . a:pattern . ":::")
+ endif
+ execute ("normal o" . a:response)
+endfunction
+
+function! AI_Respond(pattern, iteration)
+ if a:iteration <= s:MagicalContexts
+ let s:chosen_response = AI_Decide_Response("^" . a:pattern . ":::" . a:iteration . "$")
+ let s:resp_offset = 5
+ let s:request_group = 'v:val =~ ".*:::' . a:iteration . '$"'
+ let s:request_signature = ":::" . a:iteration
+ if a:iteration == s:MagicalContexts
+ let s:next_request = 'v:val =~ ".*:::$"'
+ let s:resp_offset = 4
+ let s:request_group = 'v:val =~ ".*:::' . a:iteration . '$"'
+ let s:request_signature = ":::" . a:iteration
+ else
+ let s:next_request = 'v:val =~ ".*:::' . (a:iteration + 1) . '$"'
+ endif
+ else
+ let s:chosen_response = AI_Decide_Response("^" . a:pattern . ":::$")
+ let s:resp_offset = 4
+ let s:request_group = 'v:val =~ ".*:::$"'
+ let s:next_request = 'v:val =~ ".*:::$"'
+ let s:request_signature = ":::"
+ endif
+ if s:chosen_response != -1
+ echo "ChatBot: " . getline(s:chosen_response) . "\n"
+ else
+ echohl Comment
+ echo "ChatBot: I don't understand that. Can you please teach me what to say?\n"
+ echohl None
+ let s:suggested_response = input("You say: ")
+ if s:suggested_response == "/Q" || s:suggested_response =~ "^\\s*$"
+ echohl Comment
+ echo "ChatBot: Fine, don't teach me if you don't want to!\n"
+ echohl N
+ return
+ endif
+ echo "Human: " . s:suggested_response . "\n"
+ call AI_Store_New_Response(a:pattern, s:suggested_response, a:iteration)
+ echohl Comment
+ echo "ChatBot: Thanks, I'll remember that!\n"
+ echohl None
+ endif
+ let s:decide_to_ask_back = Random(0, 1)
+ if s:decide_to_ask_back
+ let s:lines = getline(1, line("$"))
+ let s:requests = filter(s:lines, s:next_request)
+ if len(s:requests) != 0
+ let s:decision = Random(0, len(s:requests) - 1)
+ echo "ChatBot: " . s:requests[s:decision][:-s:resp_offset] . "\n"
+ let s:taught_response = input("You say: ")
+ if s:taught_response == "/Q" || s:taught_response =~ "^\\s*$"
+ echohl Comment
+ echo "ChatBot: Fine, don't want to answer me - don't answer.\n"
+ echohl None
+ return
+ endif
+ echo "Human: " . s:taught_response . "\n"
+ let s:response_group_loc = GetLineMatchingPattern(s:requests[s:decision][:-s:resp_offset] . s:request_signature)
+ let s:already_has_resp = HasResponse(s:response_group_loc, s:taught_response)
+ if s:already_has_resp != 1
+ call AI_AddResponse(s:requests[s:decision][:-s:resp_offset], s:taught_response, a:iteration)
+ echohl Comment
+ echo "ChatBot: Oh, thanks, that's a good way to respond to that! I'll remember it!\n"
+ echohl None
+ endif
+ endif
+ endif
+endfunction
+
+function! MainChatLoop()
+ let s:ChatIteration = 1
+ let s:more_status = &more
+ setlocal nomore
+ echohl Comment
+ echo "Welcome to Agetian's ChatBot for Vim v" . s:BotVersion . "! Enjoy and have fun!\n"
+ echo "Type /Q to choose not to answer the bot's question or to end the conversation.\n"
+ echohl None
+ while 1
+ let s:HumanResponse = input("You say: ")
+ if s:HumanResponse =~ "^\\s*$"
+ continue
+ endif
+ if s:HumanResponse == "/Q"
+ echo "ChatBot: Bye-bye!\n"
+ break
+ endif
+ echo "Human: " . s:HumanResponse . "\n"
+ call AI_Respond(s:HumanResponse, s:ChatIteration)
+ let s:ChatIteration += 1
+ endwhile
+ let &more = s:more_status
+endfunction
+
+nnoremap <silent> \Cb :call MainChatLoop()<CR>
+finish
+
+------> HERE-DOCUMENT WITH THE CHAT BOT DATABASE BEGINS HERE <------
+
+
+Hi!:::1
+Hi!
+
+How's it going?:::2
+I'm doing good, thanks!
+
+What's new?:::
+Not a whole lot!
+Not much!
+
+How's it going?:::1
+Good, thanks!
+
+Are you a robot?:::2
+No, I'm an alien!
+No, of course not!
+
+What are you doing?:::
+Nothing special.
+Talking to a robot.
+Talking to you!
+
+Are you a robot?:::1
+No...
+No
+
+What about you?:::
+Same! :)
+Doing good, thanks!
+
+Are you a robot?:::
+No, of course not!
+
+Should I work today?:::
+Probably :P
+Yes, of course!
+I don't know, to be honest.
+
+What's new?:::2
+Not a whole lot!
+
+What's new?:::1
+Not much!
+
+What are you doing?:::2
+Talking to you!
+
+Are you an alien?:::
+Yes, yes I am.
+You could say so.
+
+What about you?:::2
+I'm great, thanks!

0 comments on commit f64dea4

Please sign in to comment.