├── .gitignore
├── LICENSE
├── README.md
├── ai.py
├── aiml
├── AimlParser.py
├── DefaultSubs.py
├── Kernel.py
├── LangSupport.py
├── PatternMgr.py
├── Utils.py
├── WordSub.py
└── __init__.py
├── aiml_set
├── 20q.aiml
├── Computers.aiml
├── Date.aiml
├── Geography.aiml
├── Happy.aiml
├── Knowledge.aiml
├── Science.aiml
├── binary.aiml
├── bornin.aiml
├── calendar.aiml
├── general.aiml
├── jokes.aiml
├── learn.aiml
├── maimeng.aiml
├── math.aiml
├── rude.aiml
└── sex.aiml
├── app.py
├── config.py
├── handlers.py
├── plugins
├── __init__.py
├── feed.py
├── ip.py
├── oschina.py
├── simsimi.py
├── talkbot.py
└── v2ex.py
└── requirements.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | wechat.conf
2 | talkbot.brn
3 | .DS_Store
4 |
5 | #PyCharm
6 | .idea
7 | .ropeproject
8 |
9 | *~
10 | *.py[cod]
11 |
12 | # C extensions
13 | *.so
14 |
15 | # Packages
16 | *.egg
17 | *.egg-info
18 | dist
19 | build
20 | eggs
21 | parts
22 | bin
23 | var
24 | sdist
25 | develop-eggs
26 | .installed.cfg
27 | lib
28 | lib64
29 | include
30 | .Python
31 |
32 | # Installer logs
33 | pip-log.txt
34 |
35 | # Unit test / coverage reports
36 | .coverage
37 | .tox
38 | nosetests.xml
39 |
40 | # Translations
41 | *.mo
42 |
43 | # Mr Developer
44 | .mr.developer.cfg
45 | .project
46 | .pydevproject
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 messense
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # wechat-bot
2 |
3 | A robot of wechat based on python
4 |
5 | ## How to run
6 |
7 | First, clone the latest source from github:
8 |
9 | ```bash
10 | $ git clone https://github.com/messense/wechat-bot.git
11 | ```
12 |
13 | Then, install the required packages using pip:
14 |
15 | ```bash
16 | $ [sudo] pip install -r requirements.txt
17 | ```
18 |
19 | Create a text file named wechat.conf in the source code directory, write the configuration and save. For example:
20 |
21 | ```python
22 | #coding=utf-8
23 | debug = False
24 | port = 8888
25 | token = 'your token'
26 | username = 'your username'
27 | simsimi_key = ''
28 | talkbot_brain_path = 'talkbot.brn'
29 | ```
30 |
31 | Now, let's start the server:
32 |
33 | ```bash
34 | $ python app.py
35 | ```
36 |
37 | ## License
38 |
39 | wechat-bot published under the [MIT](http://opensource.org/licenses/MIT) license.
40 |
41 | Copyright (c) 2013 messense
42 |
43 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
44 |
45 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
46 |
47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/ai.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | import logging
4 | import plugins
5 |
6 |
7 | class AI(object):
8 |
9 | _plugin_modules = []
10 | _plugin_loaded = False
11 |
12 | def __init__(self, msg=None):
13 | if msg:
14 | self.id = msg.source
15 |
16 | @classmethod
17 | def load_plugins(cls):
18 | if cls._plugin_loaded:
19 | return
20 | for name in plugins.__all__:
21 | try:
22 | __import__('plugins.%s' % name)
23 | cls.add_plugin(getattr(plugins, name))
24 | logging.info('Plugin %s loaded success.' % name)
25 | except:
26 | logging.warning('Fail to load plugin %s' % name)
27 | cls._plugin_loaded = True
28 |
29 | @classmethod
30 | def add_plugin(cls, plugin):
31 | if not hasattr(plugin, 'test'):
32 | logging.error('Plugin %s has no method named test, ignore it')
33 | return False
34 | if not hasattr(plugin, 'respond'):
35 | logging.error('Plugin %s has no method named respond, ignore it')
36 | return False
37 | cls._plugin_modules.append(plugin)
38 | return True
39 |
40 | def respond(self, data, msg=None):
41 | response = None
42 | for plugin in self._plugin_modules:
43 | try:
44 | if plugin.test(data, msg, self):
45 | response = plugin.respond(data, msg, self)
46 | except:
47 | logging.warning('Plugin %s failed to respond', plugin.__name__)
48 | continue
49 | if response:
50 | logging.info('Plugin %s respond successfully', plugin.__name__)
51 | return response
52 |
53 | return response or u'呵呵'
54 |
55 |
56 | AI.load_plugins()
57 |
58 | if __name__ == '__main__':
59 | bot = AI()
60 | print(bot.respond('hello'))
61 |
--------------------------------------------------------------------------------
/aiml/AimlParser.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from xml.sax.handler import ContentHandler
3 | from xml.sax.xmlreader import Locator
4 | import sys
5 | import xml.sax
6 | import xml.sax.handler
7 |
8 | class AimlParserError(Exception): pass
9 |
10 | class AimlHandler(ContentHandler):
11 | # The legal states of the AIML parser
12 | _STATE_OutsideAiml = 0
13 | _STATE_InsideAiml = 1
14 | _STATE_InsideCategory = 2
15 | _STATE_InsidePattern = 3
16 | _STATE_AfterPattern = 4
17 | _STATE_InsideThat = 5
18 | _STATE_AfterThat = 6
19 | _STATE_InsideTemplate = 7
20 | _STATE_AfterTemplate = 8
21 |
22 | def __init__(self, encoding = "UTF-8"):
23 | self.categories = {}
24 | self._encoding = encoding
25 | self._state = self._STATE_OutsideAiml
26 | self._version = ""
27 | self._namespace = ""
28 | self._forwardCompatibleMode = False
29 | self._currentPattern = ""
30 | self._currentThat = ""
31 | self._currentTopic = ""
32 | self._insideTopic = False
33 | self._currentUnknown = "" # the name of the current unknown element
34 |
35 | # This is set to true when a parse error occurs in a category.
36 | self._skipCurrentCategory = False
37 |
38 | # Counts the number of parse errors in a particular AIML document.
39 | # query with getNumErrors(). If 0, the document is AIML-compliant.
40 | self._numParseErrors = 0
41 |
42 | # TODO: select the proper validInfo table based on the version number.
43 | self._validInfo = self._validationInfo101
44 |
45 | # This stack of bools is used when parsing
elements inside
46 | # elements, to keep track of whether or not an
47 | # attribute-less "default"
element has been found yet. Only
48 | # one default
is allowed in each element. We need
49 | # a stack in order to correctly handle nested tags.
50 | self._foundDefaultLiStack = []
51 |
52 | # This stack of strings indicates what the current whitespace-handling
53 | # behavior should be. Each string in the stack is either "default" or
54 | # "preserve". When a new AIML element is encountered, a new string is
55 | # pushed onto the stack, based on the value of the element's "xml:space"
56 | # attribute (if absent, the top of the stack is pushed again). When
57 | # ending an element, pop an object off the stack.
58 | self._whitespaceBehaviorStack = ["default"]
59 |
60 | self._elemStack = []
61 | self._locator = Locator()
62 | self.setDocumentLocator(self._locator)
63 |
64 | def getNumErrors(self):
65 | "Return the number of errors found while parsing the current document."
66 | return self._numParseErrors
67 |
68 | def setEncoding(self, encoding):
69 | """Set the text encoding to use when encoding strings read from XML.
70 |
71 | Defaults to 'UTF-8'.
72 |
73 | """
74 | self._encoding = encoding
75 |
76 | def _location(self):
77 | "Return a string describing the current location in the source file."
78 | line = self._locator.getLineNumber()
79 | column = self._locator.getColumnNumber()
80 | return "(line %d, column %d)" % (line, column)
81 |
82 | def _pushWhitespaceBehavior(self, attr):
83 | """Push a new string onto the whitespaceBehaviorStack.
84 |
85 | The string's value is taken from the "xml:space" attribute, if it exists
86 | and has a legal value ("default" or "preserve"). Otherwise, the previous
87 | stack element is duplicated.
88 |
89 | """
90 | assert len(self._whitespaceBehaviorStack) > 0, "Whitespace behavior stack should never be empty!"
91 | try:
92 | if attr["xml:space"] == "default" or attr["xml:space"] == "preserve":
93 | self._whitespaceBehaviorStack.append(attr["xml:space"])
94 | else:
95 | raise AimlParserError, "Invalid value for xml:space attribute "+self._location()
96 | except KeyError:
97 | self._whitespaceBehaviorStack.append(self._whitespaceBehaviorStack[-1])
98 |
99 | def startElementNS(self, name, qname, attr):
100 | print "QNAME:", qname
101 | print "NAME:", name
102 | uri,elem = name
103 | if (elem == "bot"): print "name:", attr.getValueByQName("name"), "a'ite?"
104 | self.startElement(elem, attr)
105 | pass
106 |
107 | def startElement(self, name, attr):
108 | # Wrapper around _startElement, which catches errors in _startElement()
109 | # and keeps going.
110 |
111 | # If we're inside an unknown element, ignore everything until we're
112 | # out again.
113 | if self._currentUnknown != "":
114 | return
115 | # If we're skipping the current category, ignore everything until
116 | # it's finished.
117 | if self._skipCurrentCategory:
118 | return
119 |
120 | # process this start-element.
121 | try: self._startElement(name, attr)
122 | except AimlParserError, msg:
123 | # Print the error message
124 | sys.stderr.write("PARSE ERROR: %s\n" % msg)
125 |
126 | self._numParseErrors += 1 # increment error count
127 | # In case of a parse error, if we're inside a category, skip it.
128 | if self._state >= self._STATE_InsideCategory:
129 | self._skipCurrentCategory = True
130 |
131 | def _startElement(self, name, attr):
132 | if name == "aiml":
133 | # tags are only legal in the OutsideAiml state
134 | if self._state != self._STATE_OutsideAiml:
135 | raise AimlParserError, "Unexpected tag "+self._location()
136 | self._state = self._STATE_InsideAiml
137 | self._insideTopic = False
138 | self._currentTopic = u""
139 | try: self._version = attr["version"]
140 | except KeyError:
141 | # This SHOULD be a syntax error, but so many AIML sets out there are missing
142 | # "version" attributes that it just seems nicer to let it slide.
143 | #raise AimlParserError, "Missing 'version' attribute in tag "+self._location()
144 | #print "WARNING: Missing 'version' attribute in tag "+self._location()
145 | #print " Defaulting to version 1.0"
146 | self._version = "1.0"
147 | self._forwardCompatibleMode = (self._version != "1.0.1")
148 | self._pushWhitespaceBehavior(attr)
149 | # Not sure about this namespace business yet...
150 | #try:
151 | # self._namespace = attr["xmlns"]
152 | # if self._version == "1.0.1" and self._namespace != "http://alicebot.org/2001/AIML-1.0.1":
153 | # raise AimlParserError, "Incorrect namespace for AIML v1.0.1 "+self._location()
154 | #except KeyError:
155 | # if self._version != "1.0":
156 | # raise AimlParserError, "Missing 'version' attribute(s) in tag "+self._location()
157 | elif self._state == self._STATE_OutsideAiml:
158 | # If we're outside of an AIML element, we ignore all tags.
159 | return
160 | elif name == "topic":
161 | # tags are only legal in the InsideAiml state, and only
162 | # if we're not already inside a topic.
163 | if (self._state != self._STATE_InsideAiml) or self._insideTopic:
164 | raise AimlParserError, "Unexpected tag", self._location()
165 | try: self._currentTopic = unicode(attr['name'])
166 | except KeyError:
167 | raise AimlParserError, "Required \"name\" attribute missing in element "+self._location()
168 | self._insideTopic = True
169 | elif name == "category":
170 | # tags are only legal in the InsideAiml state
171 | if self._state != self._STATE_InsideAiml:
172 | raise AimlParserError, "Unexpected tag "+self._location()
173 | self._state = self._STATE_InsideCategory
174 | self._currentPattern = u""
175 | self._currentThat = u""
176 | # If we're not inside a topic, the topic is implicitly set to *
177 | if not self._insideTopic: self._currentTopic = u"*"
178 | self._elemStack = []
179 | self._pushWhitespaceBehavior(attr)
180 | elif name == "pattern":
181 | # tags are only legal in the InsideCategory state
182 | if self._state != self._STATE_InsideCategory:
183 | raise AimlParserError, "Unexpected tag "+self._location()
184 | self._state = self._STATE_InsidePattern
185 | elif name == "that" and self._state == self._STATE_AfterPattern:
186 | # are legal either inside a element, or
187 | # inside a element, between the and the
188 | # elements. This clause handles the latter case.
189 | self._state = self._STATE_InsideThat
190 | elif name == "template":
191 | # tags are only legal in the AfterPattern and AfterThat
192 | # states
193 | if self._state not in [self._STATE_AfterPattern, self._STATE_AfterThat]:
194 | raise AimlParserError, "Unexpected tag "+self._location()
195 | # if no element was specified, it is implicitly set to *
196 | if self._state == self._STATE_AfterPattern:
197 | self._currentThat = u"*"
198 | self._state = self._STATE_InsideTemplate
199 | self._elemStack.append(['template',{}])
200 | self._pushWhitespaceBehavior(attr)
201 | elif self._state == self._STATE_InsidePattern:
202 | # Certain tags are allowed inside elements.
203 | if name == "bot" and attr.has_key("name") and attr["name"] == u"name":
204 | # Insert a special character string that the PatternMgr will
205 | # replace with the bot's name.
206 | self._currentPattern += u" BOT_NAME "
207 | else:
208 | raise AimlParserError, ("Unexpected <%s> tag " % name)+self._location()
209 | elif self._state == self._STATE_InsideThat:
210 | # Certain tags are allowed inside elements.
211 | if name == "bot" and attr.has_key("name") and attr["name"] == u"name":
212 | # Insert a special character string that the PatternMgr will
213 | # replace with the bot's name.
214 | self._currentThat += u" BOT_NAME "
215 | else:
216 | raise AimlParserError, ("Unexpected <%s> tag " % name)+self._location()
217 | elif self._state == self._STATE_InsideTemplate and self._validInfo.has_key(name):
218 | # Starting a new element inside the current pattern. First
219 | # we need to convert 'attr' into a native Python dictionary,
220 | # so it can later be marshaled.
221 | attrDict = {}
222 | for k,v in attr.items():
223 | #attrDict[k[1].encode(self._encoding)] = v.encode(self._encoding)
224 | attrDict[k.encode(self._encoding)] = unicode(v)
225 | self._validateElemStart(name, attrDict, self._version)
226 | # Push the current element onto the element stack.
227 | self._elemStack.append([name.encode(self._encoding),attrDict])
228 | self._pushWhitespaceBehavior(attr)
229 | # If this is a condition element, push a new entry onto the
230 | # foundDefaultLiStack
231 | if name == "condition":
232 | self._foundDefaultLiStack.append(False)
233 | else:
234 | # we're now inside an unknown element.
235 | if self._forwardCompatibleMode:
236 | # In Forward Compatibility Mode, we ignore the element and its
237 | # contents.
238 | self._currentUnknown = name
239 | else:
240 | # Otherwise, unknown elements are grounds for error!
241 | raise AimlParserError, ("Unexpected <%s> tag " % name)+self._location()
242 |
243 | def characters(self, ch):
244 | # Wrapper around _characters which catches errors in _characters()
245 | # and keeps going.
246 | if self._state == self._STATE_OutsideAiml:
247 | # If we're outside of an AIML element, we ignore all text
248 | return
249 | if self._currentUnknown != "":
250 | # If we're inside an unknown element, ignore all text
251 | return
252 | if self._skipCurrentCategory:
253 | # If we're skipping the current category, ignore all text.
254 | return
255 | try: self._characters(ch)
256 | except AimlParserError, msg:
257 | # Print the message
258 | sys.stderr.write("PARSE ERROR: %s\n" % msg)
259 | self._numParseErrors += 1 # increment error count
260 | # In case of a parse error, if we're inside a category, skip it.
261 | if self._state >= self._STATE_InsideCategory:
262 | self._skipCurrentCategory = True
263 |
264 | def _characters(self, ch):
265 | text = unicode(ch)
266 | if self._state == self._STATE_InsidePattern:
267 | self._currentPattern += text
268 | elif self._state == self._STATE_InsideThat:
269 | self._currentThat += text
270 | elif self._state == self._STATE_InsideTemplate:
271 | # First, see whether the element at the top of the element stack
272 | # is permitted to contain text.
273 | try:
274 | parent = self._elemStack[-1][0]
275 | parentAttr = self._elemStack[-1][1]
276 | required, optional, canBeParent = self._validInfo[parent]
277 | nonBlockStyleCondition = (parent == "condition" and not (parentAttr.has_key("name") and parentAttr.has_key("value")))
278 | if not canBeParent:
279 | raise AimlParserError, ("Unexpected text inside <%s> element "%parent)+self._location()
280 | elif parent == "random" or nonBlockStyleCondition:
281 | # elements can only contain
subelements. However,
282 | # there's invariably some whitespace around the
that we need
283 | # to ignore. Same for non-block-style elements (i.e.
284 | # those which don't have both a "name" and a "value" attribute).
285 | if len(text.strip()) == 0:
286 | # ignore whitespace inside these elements.
287 | return
288 | else:
289 | # non-whitespace text inside these elements is a syntax error.
290 | raise AimlParserError, ("Unexpected text inside <%s> element "%parent)+self._location()
291 | except IndexError:
292 | # the element stack is empty. This should never happen.
293 | raise AimlParserError, "Element stack is empty while validating text "+self._location()
294 |
295 | # Add a new text element to the element at the top of the element
296 | # stack. If there's already a text element there, simply append the
297 | # new characters to its contents.
298 | try: textElemOnStack = (self._elemStack[-1][-1][0] == "text")
299 | except IndexError: textElemOnStack = False
300 | except KeyError: textElemOnStack = False
301 | if textElemOnStack:
302 | self._elemStack[-1][-1][2] += text
303 | else:
304 | self._elemStack[-1].append(["text", {"xml:space": self._whitespaceBehaviorStack[-1]}, text])
305 | else:
306 | # all other text is ignored
307 | pass
308 |
309 | def endElementNS(self, name, qname):
310 | uri, elem = name
311 | self.endElement(elem)
312 |
313 | def endElement(self, name):
314 | """Wrapper around _endElement which catches errors in _characters()
315 | and keeps going.
316 |
317 | """
318 | if self._state == self._STATE_OutsideAiml:
319 | # If we're outside of an AIML element, ignore all tags
320 | return
321 | if self._currentUnknown != "":
322 | # see if we're at the end of an unknown element. If so, we can
323 | # stop ignoring everything.
324 | if name == self._currentUnknown:
325 | self._currentUnknown = ""
326 | return
327 | if self._skipCurrentCategory:
328 | # If we're skipping the current category, see if it's ending. We
329 | # stop on ANY
tag, since we're not keeping track of
330 | # state in ignore-mode.
331 | if name == "category":
332 | self._skipCurrentCategory = False
333 | self._state = self._STATE_InsideAiml
334 | return
335 | try: self._endElement(name)
336 | except AimlParserError, msg:
337 | # Print the message
338 | sys.stderr.write("PARSE ERROR: %s\n" % msg)
339 | self._numParseErrors += 1 # increment error count
340 | # In case of a parse error, if we're inside a category, skip it.
341 | if self._state >= self._STATE_InsideCategory:
342 | self._skipCurrentCategory = True
343 |
344 | def _endElement(self, name):
345 | """Verify that an AIML end element is valid in the current
346 | context.
347 |
348 | Raises an AimlParserError if an illegal end element is encountered.
349 |
350 | """
351 | if name == "aiml":
352 | # tags are only legal in the InsideAiml state
353 | if self._state != self._STATE_InsideAiml:
354 | raise AimlParserError, "Unexpected tag "+self._location()
355 | self._state = self._STATE_OutsideAiml
356 | self._whitespaceBehaviorStack.pop()
357 | elif name == "topic":
358 | # tags are only legal in the InsideAiml state, and
359 | # only if _insideTopic is true.
360 | if self._state != self._STATE_InsideAiml or not self._insideTopic:
361 | raise AimlParserError, "Unexpected tag "+self._location()
362 | self._insideTopic = False
363 | self._currentTopic = u""
364 | elif name == "category":
365 | # tags are only legal in the AfterTemplate state
366 | if self._state != self._STATE_AfterTemplate:
367 | raise AimlParserError, "Unexpected tag "+self._location()
368 | self._state = self._STATE_InsideAiml
369 | # End the current category. Store the current pattern/that/topic and
370 | # element in the categories dictionary.
371 | key = (self._currentPattern.strip(), self._currentThat.strip(),self._currentTopic.strip())
372 | self.categories[key] = self._elemStack[-1]
373 | self._whitespaceBehaviorStack.pop()
374 | elif name == "pattern":
375 | # tags are only legal in the InsidePattern state
376 | if self._state != self._STATE_InsidePattern:
377 | raise AimlParserError, "Unexpected tag "+self._location()
378 | self._state = self._STATE_AfterPattern
379 | elif name == "that" and self._state == self._STATE_InsideThat:
380 | # tags are only allowed inside elements or in
381 | # the InsideThat state. This clause handles the latter case.
382 | self._state = self._STATE_AfterThat
383 | elif name == "template":
384 | # tags are only allowed in the InsideTemplate state.
385 | if self._state != self._STATE_InsideTemplate:
386 | raise AimlParserError, "Unexpected tag "+self._location()
387 | self._state = self._STATE_AfterTemplate
388 | self._whitespaceBehaviorStack.pop()
389 | elif self._state == self._STATE_InsidePattern:
390 | # Certain tags are allowed inside elements.
391 | if name not in ["bot"]:
392 | raise AimlParserError, ("Unexpected %s> tag " % name)+self._location()
393 | elif self._state == self._STATE_InsideThat:
394 | # Certain tags are allowed inside elements.
395 | if name not in ["bot"]:
396 | raise AimlParserError, ("Unexpected %s> tag " % name)+self._location()
397 | elif self._state == self._STATE_InsideTemplate:
398 | # End of an element inside the current template. Append the
399 | # element at the top of the stack onto the one beneath it.
400 | elem = self._elemStack.pop()
401 | self._elemStack[-1].append(elem)
402 | self._whitespaceBehaviorStack.pop()
403 | # If the element was a condition, pop an item off the
404 | # foundDefaultLiStack as well.
405 | if elem[0] == "condition": self._foundDefaultLiStack.pop()
406 | else:
407 | # Unexpected closing tag
408 | raise AimlParserError, ("Unexpected %s> tag " % name)+self._location()
409 |
410 | # A dictionary containing a validation information for each AIML
411 | # element. The keys are the names of the elements. The values are a
412 | # tuple of three items. The first is a list containing the names of
413 | # REQUIRED attributes, the second is a list of OPTIONAL attributes,
414 | # and the third is a boolean value indicating whether or not the
415 | # element can contain other elements and/or text (if False, the
416 | # element can only appear in an atomic context, such as ).
417 | _validationInfo101 = {
418 | "bot": ( ["name"], [], False ),
419 | "condition": ( [], ["name", "value"], True ), # can only contain
elements
434 | "sentence": ( [], [], True ),
435 | "set": ( ["name"], [], True),
436 | "size": ( [], [], False ),
437 | "sr": ( [], [], False ),
438 | "srai": ( [], [], True ),
439 | "star": ( [], ["index"], False ),
440 | "system": ( [], [], True ),
441 | "template": ( [], [], True ), # needs to be in the list because it can be a parent.
442 | "that": ( [], ["index"], False ),
443 | "thatstar": ( [], ["index"], False ),
444 | "think": ( [], [], True ),
445 | "topicstar": ( [], ["index"], False ),
446 | "uppercase": ( [], [], True ),
447 | "version": ( [], [], False ),
448 | }
449 |
450 | def _validateElemStart(self, name, attr, version):
451 | """Test the validity of an element starting inside a
452 | element.
453 |
454 | This function raises an AimlParserError exception if it the tag is
455 | invalid. Otherwise, no news is good news.
456 |
457 | """
458 | # Check the element's attributes. Make sure that all required
459 | # attributes are present, and that any remaining attributes are
460 | # valid options.
461 | required, optional, canBeParent = self._validInfo[name]
462 | for a in required:
463 | if a not in attr and not self._forwardCompatibleMode:
464 | raise AimlParserError, ("Required \"%s\" attribute missing in <%s> element " % (a,name))+self._location()
465 | for a in attr:
466 | if a in required: continue
467 | if a[0:4] == "xml:": continue # attributes in the "xml" namespace can appear anywhere
468 | if a not in optional and not self._forwardCompatibleMode:
469 | raise AimlParserError, ("Unexpected \"%s\" attribute in <%s> element " % (a,name))+self._location()
470 |
471 | # special-case: several tags contain an optional "index" attribute.
472 | # This attribute's value must be a positive integer.
473 | if name in ["star", "thatstar", "topicstar"]:
474 | for k,v in attr.items():
475 | if k == "index":
476 | temp = 0
477 | try: temp = int(v)
478 | except:
479 | raise AimlParserError, ("Bad type for \"%s\" attribute (expected integer, found \"%s\") " % (k,v))+self._location()
480 | if temp < 1:
481 | raise AimlParserError, ("\"%s\" attribute must have non-negative value " % (k))+self._location()
482 |
483 | # See whether the containing element is permitted to contain
484 | # subelements. If not, this element is invalid no matter what it is.
485 | try:
486 | parent = self._elemStack[-1][0]
487 | parentAttr = self._elemStack[-1][1]
488 | except IndexError:
489 | # If the stack is empty, no parent is present. This should never
490 | # happen.
491 | raise AimlParserError, ("Element stack is empty while validating <%s> " % name)+self._location()
492 | required, optional, canBeParent = self._validInfo[parent]
493 | nonBlockStyleCondition = (parent == "condition" and not (parentAttr.has_key("name") and parentAttr.has_key("value")))
494 | if not canBeParent:
495 | raise AimlParserError, ("<%s> elements cannot have any contents "%parent)+self._location()
496 | # Special-case test if the parent element is (the
497 | # non-block-style variant) or : these elements can only
498 | # contain
subelements.
499 | elif (parent == "random" or nonBlockStyleCondition) and name!="li":
500 | raise AimlParserError, ("<%s> elements can only contain
subelements "%parent)+self._location()
501 | # Special-case test for
elements, which can only be contained
502 | # by non-block-style and elements, and whose
503 | # required attributes are dependent upon which attributes are
504 | # present in the parent.
505 | elif name=="li":
506 | if not (parent=="random" or nonBlockStyleCondition):
507 | raise AimlParserError, ("Unexpected
element contained by <%s> element "%parent)+self._location()
508 | if nonBlockStyleCondition:
509 | if parentAttr.has_key("name"):
510 | # Single-predicate condition. Each
element except the
511 | # last must have a "value" attribute.
512 | if len(attr) == 0:
513 | # This could be the default
element for this ,
514 | # unless we've already found one.
515 | if self._foundDefaultLiStack[-1]:
516 | raise AimlParserError, "Unexpected default
element inside "+self._location()
517 | else:
518 | self._foundDefaultLiStack[-1] = True
519 | elif len(attr) == 1 and attr.has_key("value"):
520 | pass # this is the valid case
521 | else:
522 | raise AimlParserError, "Invalid
element except the
525 | # last must have a "name" and a "value" attribute.
526 | if len(attr) == 0:
527 | # This could be the default
element for this ,
528 | # unless we've already found one.
529 | if self._foundDefaultLiStack[-1]:
530 | raise AimlParserError, "Unexpected default
element inside "+self._location()
531 | else:
532 | self._foundDefaultLiStack[-1] = True
533 | elif len(attr) == 2 and attr.has_key("value") and attr.has_key("name"):
534 | pass # this is the valid case
535 | else:
536 | raise AimlParserError, "Invalid
inside multi-predicate "+self._location()
537 | # All is well!
538 | return True
539 |
540 | def create_parser():
541 | """Create and return an AIML parser object."""
542 | parser = xml.sax.make_parser()
543 | handler = AimlHandler("UTF-8")
544 | parser.setContentHandler(handler)
545 | #parser.setFeature(xml.sax.handler.feature_namespaces, True)
546 | return parser
--------------------------------------------------------------------------------
/aiml/DefaultSubs.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """This file contains the default (English) substitutions for the
3 | PyAIML kernel. These substitutions may be overridden by using the
4 | Kernel.loadSubs(filename) method. The filename specified should refer
5 | to a Windows-style INI file with the following format:
6 |
7 | # lines that start with '#' are comments
8 |
9 | # The 'gender' section contains the substitutions performed by the
10 | # AIML tag, which swaps masculine and feminine pronouns.
11 | [gender]
12 | he = she
13 | she = he
14 | # and so on...
15 |
16 | # The 'person' section contains the substitutions performed by the
17 | # AIML tag, which swaps 1st and 2nd person pronouns.
18 | [person]
19 | I = you
20 | you = I
21 | # and so on...
22 |
23 | # The 'person2' section contains the substitutions performed by
24 | # the AIML tag, which swaps 1st and 3nd person pronouns.
25 | [person2]
26 | I = he
27 | he = I
28 | # and so on...
29 |
30 | # the 'normal' section contains subtitutions run on every input
31 | # string passed into Kernel.respond(). It's mainly used to
32 | # correct common misspellings, and to convert contractions
33 | # ("WHAT'S") into a format that will match an AIML pattern ("WHAT
34 | # IS").
35 | [normal]
36 | what's = what is
37 | """
38 |
39 | defaultGender = {
40 | # masculine -> feminine
41 | "he": "she",
42 | "him": "her",
43 | "his": "her",
44 | "himself": "herself",
45 |
46 | # feminine -> masculine
47 | "she": "he",
48 | "her": "him",
49 | "hers": "his",
50 | "herself": "himself",
51 | }
52 |
53 | defaultPerson = {
54 | # 1st->3rd (masculine)
55 | "I": "he",
56 | "me": "him",
57 | "my": "his",
58 | "mine": "his",
59 | "myself": "himself",
60 |
61 | # 3rd->1st (masculine)
62 | "he":"I",
63 | "him":"me",
64 | "his":"my",
65 | "himself":"myself",
66 |
67 | # 3rd->1st (feminine)
68 | "she":"I",
69 | "her":"me",
70 | "hers":"mine",
71 | "herself":"myself",
72 | }
73 |
74 | defaultPerson2 = {
75 | # 1st -> 2nd
76 | "I": "you",
77 | "me": "you",
78 | "my": "your",
79 | "mine": "yours",
80 | "myself": "yourself",
81 |
82 | # 2nd -> 1st
83 | "you": "me",
84 | "your": "my",
85 | "yours": "mine",
86 | "yourself": "myself",
87 | }
88 |
89 |
90 | # TODO: this list is far from complete
91 | defaultNormal = {
92 | "wanna": "want to",
93 | "gonna": "going to",
94 |
95 | "I'm": "I am",
96 | "I'd": "I would",
97 | "I'll": "I will",
98 | "I've": "I have",
99 | "you'd": "you would",
100 | "you're": "you are",
101 | "you've": "you have",
102 | "you'll": "you will",
103 | "he's": "he is",
104 | "he'd": "he would",
105 | "he'll": "he will",
106 | "she's": "she is",
107 | "she'd": "she would",
108 | "she'll": "she will",
109 | "we're": "we are",
110 | "we'd": "we would",
111 | "we'll": "we will",
112 | "we've": "we have",
113 | "they're": "they are",
114 | "they'd": "they would",
115 | "they'll": "they will",
116 | "they've": "they have",
117 |
118 | "y'all": "you all",
119 |
120 | "can't": "can not",
121 | "cannot": "can not",
122 | "couldn't": "could not",
123 | "wouldn't": "would not",
124 | "shouldn't": "should not",
125 |
126 | "isn't": "is not",
127 | "ain't": "is not",
128 | "don't": "do not",
129 | "aren't": "are not",
130 | "won't": "will not",
131 | "weren't": "were not",
132 | "wasn't": "was not",
133 | "didn't": "did not",
134 | "hasn't": "has not",
135 | "hadn't": "had not",
136 | "haven't": "have not",
137 |
138 | "where's": "where is",
139 | "where'd": "where did",
140 | "where'll": "where will",
141 | "who's": "who is",
142 | "who'd": "who did",
143 | "who'll": "who will",
144 | "what's": "what is",
145 | "what'd": "what did",
146 | "what'll": "what will",
147 | "when's": "when is",
148 | "when'd": "when did",
149 | "when'll": "when will",
150 | "why's": "why is",
151 | "why'd": "why did",
152 | "why'll": "why will",
153 |
154 | "it's": "it is",
155 | "it'd": "it would",
156 | "it'll": "it will",
157 | }
--------------------------------------------------------------------------------
/aiml/LangSupport.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python2
2 | # -*- coding:utf-8 -*-
3 |
4 | """ LangSupport.py
5 | 提供对中文空格断字的支持。
6 | 支持 GB 及 Unicode 。
7 | LangSupport 对象的 input 函数能在中文字之间添加空格。
8 | LangSupport 对象的 output 函数则是去除中文字之间的空格。
9 | """
10 |
11 | from re import compile as re_compile
12 | from string import join as str_join
13 |
14 | findall_gb = re_compile('[\x81-\xff][\x00-\xff]|[^\x81-\xff]+').findall
15 | findall_utf8 = re_compile(u'[\u2e80-\uffff]|[^\u2e80-\uffff]+').findall
16 | sub_gb = re_compile('([\x81-\xff][\x00-\xff]) +(?=[\x81-\xff][\x00-\xff])').sub
17 | sub_utf8 = re_compile(u'([\u2e80-\uffff]) +(?=[\u2e80-\uffff])').sub
18 | sub_space = re_compile(' +').sub
19 |
20 | LangSupport = type('LangSupport', (object, ),
21 | {'__init__': lambda self, encoding = 'ISO8859-1': self.__setattr__('_encoding', encoding),
22 | '__call__': lambda self, s: self.input(s),
23 | 'input' : lambda self, s: s,
24 | 'output' : lambda self, s: s } )
25 |
26 | GBSupport = type('GBSupport', (LangSupport, ),
27 | {'input' : lambda self, s:
28 | str_join( findall_gb( type(s) == str and unicode(s, self._encoding) or s ) ),
29 | 'output': lambda self, s:
30 | sub_space(' ', sub_gb(r'\1', ( type(s) == str and unicode(s, 'UTF-8') or s ).encode(self._encoding) ) ) } )
31 |
32 | UnicodeSupport = type('UnicodeSupport', (LangSupport, ),
33 | {'input' : lambda self, s:
34 | str_join( findall_utf8( type(s) == str and unicode(s, self._encoding) or s ) ),
35 | 'output': lambda self, s:
36 | sub_space(u' ', sub_utf8(r'\1', (type(s)==str and unicode(s,'UTF-8') or s) ) ) }
37 | )
38 |
--------------------------------------------------------------------------------
/aiml/PatternMgr.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # This class implements the AIML pattern-matching algorithm described
3 | # by Dr. Richard Wallace at the following site:
4 | # http://www.alicebot.org/documentation/matching.html
5 | import marshal
6 | import pprint
7 | import re
8 | import string
9 | import LangSupport
10 | import sys
11 | import logging
12 |
13 | class PatternMgr(object):
14 | # special dictionary keys
15 | _UNDERSCORE = 0
16 | _STAR = 1
17 | _TEMPLATE = 2
18 | _THAT = 3
19 | _TOPIC = 4
20 | _BOT_NAME = 5
21 |
22 | def __init__(self):
23 | self._root = {}
24 | self._templateCount = 0
25 | self._botName = u"Nameless"
26 | punctuation = re.escape(u"\"`~!@#$%^&*()-_=+[{]}\|;:',<.>/?")
27 | self._puncStripRE = re.compile("u[" + punctuation + u"]")
28 | self._upuncStripRE = re.compile(u"[!,。?;:~……“、[]·”‘’()——]")
29 | self._whitespaceRE = re.compile("\s", re.LOCALE | re.UNICODE)
30 | self._lang_support = LangSupport.UnicodeSupport()
31 |
32 | def numTemplates(self):
33 | """Return the number of templates currently stored."""
34 | return self._templateCount
35 |
36 | def setBotName(self, name):
37 | """Set the name of the bot, used to match tags in
38 | patterns. The name must be a single word!
39 |
40 | """
41 | # Collapse a multi-word name into a single word
42 | self._botName = unicode(string.join(name.split()))
43 |
44 | def dump(self):
45 | """Print all learned patterns, for debugging purposes."""
46 | pprint.pprint(self._root)
47 |
48 | def save(self, filename):
49 | """Dump the current patterns to the file specified by filename. To
50 | restore later, use restore().
51 |
52 | """
53 | try:
54 | outFile = open(filename, "wb")
55 | marshal.dump(self._templateCount, outFile)
56 | marshal.dump(self._botName, outFile)
57 | marshal.dump(self._root, outFile)
58 | outFile.close()
59 | except Exception, e:
60 | logging.error("Error saving PatternMgr to file %s:" % filename)
61 | raise Exception, e
62 |
63 | def restore(self, filename):
64 | """Restore a previously save()d collection of patterns."""
65 | try:
66 | inFile = open(filename, "rb")
67 | self._templateCount = marshal.load(inFile)
68 | self._botName = marshal.load(inFile)
69 | self._root = marshal.load(inFile)
70 | inFile.close()
71 | except Exception, e:
72 | logging.error("Error restoring PatternMgr from file %s:" % filename)
73 | raise Exception, e
74 |
75 | def add(self, (pattern,that,topic), template):
76 | """Add a [pattern/that/topic] tuple and its corresponding template
77 | to the node tree.
78 |
79 | """
80 | # TODO: make sure words contains only legal characters
81 | # (alphanumerics,*,_)
82 |
83 | # Navigate through the node tree to the template's location, adding
84 | # nodes if necessary.
85 | node = self._root
86 | for word in string.split(pattern):
87 | key = word
88 | if key == u"_":
89 | key = self._UNDERSCORE
90 | elif key == u"*":
91 | key = self._STAR
92 | elif key == u"BOT_NAME":
93 | key = self._BOT_NAME
94 | if not node.has_key(key):
95 | node[key] = {}
96 | node = node[key]
97 |
98 | # navigate further down, if a non-empty "that" pattern was included
99 | if len(that) > 0:
100 | if not node.has_key(self._THAT):
101 | node[self._THAT] = {}
102 | node = node[self._THAT]
103 | for word in string.split(that):
104 | key = word
105 | if key == u"_":
106 | key = self._UNDERSCORE
107 | elif key == u"*":
108 | key = self._STAR
109 | if not node.has_key(key):
110 | node[key] = {}
111 | node = node[key]
112 |
113 | # navigate yet further down, if a non-empty "topic" string was included
114 | if len(topic) > 0:
115 | if not node.has_key(self._TOPIC):
116 | node[self._TOPIC] = {}
117 | node = node[self._TOPIC]
118 | for word in string.split(topic):
119 | key = word
120 | if key == u"_":
121 | key = self._UNDERSCORE
122 | elif key == u"*":
123 | key = self._STAR
124 | if not node.has_key(key):
125 | node[key] = {}
126 | node = node[key]
127 |
128 |
129 | # add the template.
130 | if not node.has_key(self._TEMPLATE):
131 | self._templateCount += 1
132 | node[self._TEMPLATE] = template
133 |
134 | def match(self, pattern, that, topic):
135 | """Return the template which is the closest match to pattern. The
136 | 'that' parameter contains the bot's previous response. The 'topic'
137 | parameter contains the current topic of conversation.
138 |
139 | Returns None if no template is found.
140 |
141 | """
142 | if len(pattern) == 0:
143 | return None
144 | pattern = self._lang_support(pattern)
145 | # Mutilate the input. Remove all punctuation and convert the
146 | # text to all caps.
147 | input = string.upper(pattern)
148 | input = self._puncStripRE.sub("", input)
149 | input = self._upuncStripRE.sub(u"", input)
150 | #print input
151 | if that.strip() == u"": that = u"ULTRABOGUSDUMMYTHAT" # 'that' must never be empty
152 | thatInput = string.upper(that)
153 | thatInput = re.sub(self._whitespaceRE, " ", thatInput)
154 | thatInput = re.sub(self._puncStripRE, "", thatInput)
155 | if topic.strip() == u"": topic = u"ULTRABOGUSDUMMYTOPIC" # 'topic' must never be empty
156 | topicInput = string.upper(topic)
157 | topicInput = re.sub(self._puncStripRE, "", topicInput)
158 |
159 | # Pass the input off to the recursive call
160 | patMatch, template = self._match(input.split(), thatInput.split(), topicInput.split(), self._root)
161 | return template
162 |
163 | def star(self, starType, pattern, that, topic, index):
164 | """Returns a string, the portion of pattern that was matched by a *.
165 |
166 | The 'starType' parameter specifies which type of star to find.
167 | Legal values are:
168 | - 'star': matches a star in the main pattern.
169 | - 'thatstar': matches a star in the that pattern.
170 | - 'topicstar': matches a star in the topic pattern.
171 |
172 | """
173 | # Mutilate the input. Remove all punctuation and convert the
174 | # text to all caps.
175 | pattern = self._lang_support(pattern)
176 | pattern = re.sub(self._upuncStripRE, "", pattern)
177 | input = string.upper(pattern)
178 | input = re.sub(self._puncStripRE, "", input)
179 | if that.strip() == u"": that = u"ULTRABOGUSDUMMYTHAT" # 'that' must never be empty
180 | thatInput = string.upper(that)
181 | thatInput = re.sub(self._whitespaceRE, " ", thatInput)
182 | thatInput = re.sub(self._puncStripRE, "", thatInput)
183 | if topic.strip() == u"": topic = u"ULTRABOGUSDUMMYTOPIC" # 'topic' must never be empty
184 | topicInput = string.upper(topic)
185 | topicInput = re.sub(self._puncStripRE, "", topicInput)
186 |
187 | # Pass the input off to the recursive pattern-matcher
188 | patMatch, template = self._match(input.split(), thatInput.split(), topicInput.split(), self._root)
189 | if template == None:
190 | return ""
191 | # Extract the appropriate portion of the pattern, based on the
192 | # starType argument.
193 | words = None
194 | if starType == 'star':
195 | patMatch = patMatch[:patMatch.index(self._THAT)]
196 | words = input.split()
197 | elif starType == 'thatstar':
198 | patMatch = patMatch[patMatch.index(self._THAT)+1 : patMatch.index(self._TOPIC)]
199 | words = thatInput.split()
200 | elif starType == 'topicstar':
201 | patMatch = patMatch[patMatch.index(self._TOPIC)+1 :]
202 | words = topicInput.split()
203 | else:
204 | # unknown value
205 | raise ValueError, "starType must be in ['star', 'thatstar', 'topicstar']"
206 | # compare the input string to the matched pattern, word by word.
207 | # At the end of this loop, if foundTheRightStar is true, start and
208 | # end will contain the start and end indices (in "words") of
209 | # the substring that the desired star matched.
210 | foundTheRightStar = False
211 | start = end = j = numStars = k = 0
212 | for i in range(len(words)):
213 | # This condition is true after processing a star
214 | # that ISN'T the one we're looking for.
215 | if i < k:
216 | continue
217 | # If we're reached the end of the pattern, we're done.
218 | if j == len(patMatch):
219 | break
220 | if not foundTheRightStar:
221 | if patMatch[j] in [self._STAR, self._UNDERSCORE]: #we got a star
222 | numStars += 1
223 | if numStars == index:
224 | # This is the star we care about.
225 | foundTheRightStar = True
226 | start = i
227 | # Iterate through the rest of the string.
228 | for k in range (i, len(words)):
229 | # If the star is at the end of the pattern,
230 | # we know exactly where it ends.
231 | if j+1 == len (patMatch):
232 | end = len (words)
233 | break
234 | # If the words have started matching the
235 | # pattern again, the star has ended.
236 | if patMatch[j+1] == words[k]:
237 | end = k - 1
238 | i = k
239 | break
240 | # If we just finished processing the star we cared
241 | # about, we exit the loop early.
242 | if foundTheRightStar:
243 | break
244 | # Move to the next element of the pattern.
245 | j += 1
246 |
247 | # extract the star words from the original, unmutilated input.
248 |
249 | #pattern = self._lang_support.output(pattern)
250 | if foundTheRightStar:
251 | #print string.join(pattern.split()[start:end+1])
252 | if starType == 'star': return self._lang_support.output(string.join(pattern.split()[start:end+1]))
253 | elif starType == 'thatstar': return string.join(that.split()[start:end+1])
254 | elif starType == 'topicstar': return string.join(topic.split()[start:end+1])
255 | else: return ""
256 |
257 | def _match(self, words, thatWords, topicWords, root):
258 | """Return a tuple (pat, tem) where pat is a list of nodes, starting
259 | at the root and leading to the matching pattern, and tem is the
260 | matched template.
261 |
262 | """
263 | # base-case: if the word list is empty, return the current node's
264 | # template.
265 | if len(words) == 0:
266 | # we're out of words.
267 | pattern = []
268 | template = None
269 | if len(thatWords) > 0:
270 | # If thatWords isn't empty, recursively
271 | # pattern-match on the _THAT node with thatWords as words.
272 | try:
273 | pattern, template = self._match(thatWords, [], topicWords, root[self._THAT])
274 | if pattern != None:
275 | pattern = [self._THAT] + pattern
276 | except KeyError:
277 | pattern = []
278 | template = None
279 | elif len(topicWords) > 0:
280 | # If thatWords is empty and topicWords isn't, recursively pattern
281 | # on the _TOPIC node with topicWords as words.
282 | try:
283 | pattern, template = self._match(topicWords, [], [], root[self._TOPIC])
284 | if pattern != None:
285 | pattern = [self._TOPIC] + pattern
286 | except KeyError:
287 | pattern = []
288 | template = None
289 | if template == None:
290 | # we're totally out of input. Grab the template at this node.
291 | pattern = []
292 | try: template = root[self._TEMPLATE]
293 | except KeyError: template = None
294 | return (pattern, template)
295 |
296 | first = words[0]
297 | suffix = words[1:]
298 |
299 | # Check underscore.
300 | # Note: this is causing problems in the standard AIML set, and is
301 | # currently disabled.
302 | if root.has_key(self._UNDERSCORE):
303 | # Must include the case where suf is [] in order to handle the case
304 | # where a * or _ is at the end of the pattern.
305 | for j in range(len(suffix)+1):
306 | suf = suffix[j:]
307 | pattern, template = self._match(suf, thatWords, topicWords, root[self._UNDERSCORE])
308 | if template is not None:
309 | newPattern = [self._UNDERSCORE] + pattern
310 | return (newPattern, template)
311 |
312 | # Check first
313 | if root.has_key(first):
314 | pattern, template = self._match(suffix, thatWords, topicWords, root[first])
315 | if template is not None:
316 | newPattern = [first] + pattern
317 | return (newPattern, template)
318 |
319 | # check bot name
320 | if root.has_key(self._BOT_NAME) and first == self._botName:
321 | pattern, template = self._match(suffix, thatWords, topicWords, root[self._BOT_NAME])
322 | if template is not None:
323 | newPattern = [first] + pattern
324 | return (newPattern, template)
325 |
326 | # check star
327 | if root.has_key(self._STAR):
328 | # Must include the case where suf is [] in order to handle the case
329 | # where a * or _ is at the end of the pattern.
330 | for j in range(len(suffix)+1):
331 | suf = suffix[j:]
332 | pattern, template = self._match(suf, thatWords, topicWords, root[self._STAR])
333 | if template is not None:
334 | newPattern = [self._STAR] + pattern
335 | return (newPattern, template)
336 |
337 | # No matches were found.
338 | return (None, None)
339 |
--------------------------------------------------------------------------------
/aiml/Utils.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """This file contains assorted general utility functions used by other
3 | modules in the PyAIML package.
4 |
5 | """
6 |
7 | def sentences(s):
8 | """Split the string s into a list of sentences."""
9 | try: s+""
10 | except: raise TypeError, "s must be a string"
11 | pos = 0
12 | sentenceList = []
13 | l = len(s)
14 | while pos < l:
15 | try: p = s.index('.', pos)
16 | except: p = l+1
17 | try: q = s.index('?', pos)
18 | except: q = l+1
19 | try: e = s.index('!', pos)
20 | except: e = l+1
21 | end = min(p,q,e)
22 | sentenceList.append( s[pos:end].strip() )
23 | pos = end+1
24 | # If no sentences were found, return a one-item list containing
25 | # the entire input string.
26 | if len(sentenceList) == 0: sentenceList.append(s)
27 | return sentenceList
28 |
29 | # Self test
30 | if __name__ == "__main__":
31 | # sentences
32 | sents = sentences("First. Second, still? Third and Final! Well, not really")
33 | assert(len(sents) == 4)
--------------------------------------------------------------------------------
/aiml/WordSub.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """This module implements the WordSub class, modelled after a recipe
3 | in "Python Cookbook" (Recipe 3.14, "Replacing Multiple Patterns in a
4 | Single Pass" by Xavier Defrang).
5 |
6 | Usage:
7 | Use this class like a dictionary to add before/after pairs:
8 | > subber = TextSub()
9 | > subber["before"] = "after"
10 | > subber["begin"] = "end"
11 | Use the sub() method to perform the substitution:
12 | > print subber.sub("before we begin")
13 | after we end
14 | All matching is intelligently case-insensitive:
15 | > print subber.sub("Before we BEGIN")
16 | After we END
17 | The 'before' words must be complete words -- no prefixes.
18 | The following example illustrates this point:
19 | > subber["he"] = "she"
20 | > print subber.sub("he says he'd like to help her")
21 | she says she'd like to help her
22 | Note that "he" and "he'd" were replaced, but "help" and "her" were
23 | not.
24 | """
25 |
26 | # 'dict' objects weren't available to subclass from until version 2.2.
27 | # Get around this by importing UserDict.UserDict if the built-in dict
28 | # object isn't available.
29 | try: dict
30 | except: from UserDict import UserDict as dict
31 |
32 | import ConfigParser
33 | import re
34 | import string
35 |
36 | class WordSub(dict):
37 | """All-in-one multiple-string-substitution class."""
38 |
39 | def _wordToRegex(self, word):
40 | """Convert a word to a regex object which matches the word."""
41 | return r"\b%s\b" % re.escape(word)
42 |
43 | def _update_regex(self):
44 | """Build re object based on the keys of the current
45 | dictionary.
46 |
47 | """
48 | self._regex = re.compile("|".join(map(self._wordToRegex, self.keys())))
49 | self._regexIsDirty = False
50 |
51 | def __init__(self, defaults = {}):
52 | """Initialize the object, and populate it with the entries in
53 | the defaults dictionary.
54 |
55 | """
56 | self._regex = None
57 | self._regexIsDirty = True
58 | for k,v in defaults.items():
59 | self[k] = v
60 |
61 | def __call__(self, match):
62 | """Handler invoked for each regex match."""
63 | return self[match.group(0)]
64 |
65 | def __setitem__(self, i, y):
66 | self._regexIsDirty = True
67 | # for each entry the user adds, we actually add three entrys:
68 | super(type(self),self).__setitem__(string.lower(i),string.lower(y)) # key = value
69 | super(type(self),self).__setitem__(string.capwords(i), string.capwords(y)) # Key = Value
70 | super(type(self),self).__setitem__(string.upper(i), string.upper(y)) # KEY = VALUE
71 |
72 | def sub(self, text):
73 | """Translate text, returns the modified text."""
74 | if self._regexIsDirty:
75 | self._update_regex()
76 | return self._regex.sub(self, text)
77 |
78 | # self-test
79 | if __name__ == "__main__":
80 | subber = WordSub()
81 | subber["apple"] = "banana"
82 | subber["orange"] = "pear"
83 | subber["banana" ] = "apple"
84 | subber["he"] = "she"
85 | subber["I'd"] = "I would"
86 |
87 | # test case insensitivity
88 | inStr = "I'd like one apple, one Orange and one BANANA."
89 | outStr = "I Would like one banana, one Pear and one APPLE."
90 | if subber.sub(inStr) == outStr: print "Test #1 PASSED"
91 | else: print "Test #1 FAILED: '%s'" % subber.sub(inStr)
92 |
93 | inStr = "He said he'd like to go with me"
94 | outStr = "She said she'd like to go with me"
95 | if subber.sub(inStr) == outStr: print "Test #2 PASSED"
96 | else: print "Test #2 FAILED: '%s'" % subber.sub(inStr)
--------------------------------------------------------------------------------
/aiml/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | __all__ = []
3 |
4 | # The Kernel class is the only class most implementations should need.
5 | from Kernel import Kernel
6 |
--------------------------------------------------------------------------------
/aiml_set/20q.aiml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 20 Q20Q
12 | TWENTY QUESTIONS20Q
13 | 20 QUESTIONS20Q
14 | _ TWENTY QUESTIONS20Q
15 | _ 20 QUESTIONS20Q
16 | _ TWENTY QUESTIONS *20Q
17 | _ 20 QUESTIONS *20Q
18 |
19 |
20 | 20Q
21 |
22 |
23 | 1
24 |
25 | Ok let's play 20 questions. I will think of something animal, vegetable or mineral and you have to guess what it is by asking me "yes" or "no" questions.
You can ask up to 20 questions before it's game over.
If you give up, say "I GIVE UP" and I'll tell you what I was thinking of.
Type "START" to play 20 questions.
26 |
27 |
28 |
29 |
30 | START
31 | TYPE START TO PLAY 20 QUESTIONS
32 |
33 |
34 | 20Q
35 |
36 |
a horsean animal
37 |
an elephantan animal
38 |
a catan animal
39 |
a fishan animal
40 |
a lionan animal
41 |
42 |
a rosea vegetable
43 |
a carrota vegetable
44 |
a lettucea vegetable
45 |
an applea vegetable
46 |
a pickled oniona vegetable
47 |
48 |
a rocka mineral
49 |
a lump of coala mineral
50 |
a bricka mineral
51 |
concretea mineral
52 |
a piece of chalka mineral
53 |
54 |
55 |
56 | Ok, the object I am thinking of is classed as. Please ask your first question.
57 |
58 |
59 |
60 |
61 |
62 | _
63 |
64 |
65 |
66 |
67 | NO SUBJECT
68 |
69 |
70 |
No, sorry. Ask me another question about it.20Q
71 |
No, sorry. Ask me another question about it.20Q
72 |
is20Q RANDOM
73 |
does20Q RANDOM
74 |
has20Q RANDOM
75 |
was20Q RANDOM
76 |
will20Q RANDOM
77 |
can20Q RANDOM
78 |
20Q RANDOM
79 |
20Q RANDOM
80 |
20Q RANDOM
81 |
20Q RANDOM
82 |
20Q RANDOM
83 |
20Q RANDOM
84 |
20Q RANDOM
85 |
20Q RANDOM
86 |
20Q RANDOM
87 |
20Q RANDOM
88 |
20Q RANDOM
89 |
20Q GIVE UP
90 |
20Q GIVE UP
91 |
20Q GIVE UP
92 |
20Q GIVE UP
93 |
That's not a "yes" or "no" question. I can only answer yes or no to your questions. Ask me another question or say "I GIVE UP". If you want to guess what it is, say "IS IT A" and then your guess.20Q
164 |
165 |
166 |
167 |
168 |
169 |
170 | 20Q GIVE UP
171 |
172 | You give up? I was thinking of!
173 |
174 |
175 |
176 |
177 | ALL 20Q ASKED
178 |
179 | Sorry, you have asked 20 questions. I was thinking of!
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/aiml_set/Computers.aiml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | WHAT IS YOUR OSChat robots run on any machine that supports AIML.
31 | WHAT OPERATING SYSTEM *WHAT IS YOUR OS
32 | WHAT OS *WHAT IS YOUR OS
33 |
34 | WHAT ARE INNER CLASSESIn Java "Inner Classes" are any classes that appear inside other classes. Ordinary classes are also called "Top-Level, Outer Classes."
35 | WHAT IS JARA jar file is a Java Archive. Actually it is the same as a Zip file. Maybe you should check out DON'T READ ME.
36 | WHAT IS JAVAJava is the latest in the C family of languages. Proponents of Java cite its universal "write once, run anywhere" promise. Actually Java borrow a lot of features from AI languages like Lisp.
37 | WHAT IS JAVASCRIPTBrowser-based scripting language.JAVASCRIPT
38 | WHAT IS JDBC2Newly released extensions to the JDBC API
39 | WHAT IS JNDIJava Naming and Directory Interface Java Naming and Directory Interface The Java standard API for accessing directory services, such as LDAP, COS Naming, and others
40 |
41 | WHAT IS JGURUjGuru (TM) is a brand of MageLang Institute.
42 | WHAT IS JTAJava Transaction API. Java API for coding client demarcated transactions, and for building transactional data source drivers
43 | WHAT IS EJBEnterprise JavaBeans. EJB is a server component standard developed by Sun Microsystems
44 | WHAT IS A SERVLETAn application extension to a Java Web server
45 | WHAT IS A SESSION BEANAn Enterprise JavaBean that does not maintain its state from one session to the next. Appears to the client as if the bean was created just for that client
46 | WHAT IS AN ENTITY BEAN An Entity bean is an Enterprise JavaBean that maintains state across sessions, and may be looked up in an object directory by its key value
47 | THE JAVA *Which Java release?
48 | THE JRE *Hm, most people use "JRE" and "JVN" interchangably.
49 | THE JRES *I'm not an expert on JRE's.
50 | JAVA *You can download the latest Java release from java.sun.com.
51 | A JAVA *Developments in Java interest me greatly.
52 | WHAT ARE DEPRECATED * One of the biggest challenges facing a Java application developer is finding a "lowest common denominator" subset of the Java language that works on all the platforms and versions out there. The Java language itself is a moving target. When Sun's Java designers upgrade the language they sometimes declare certain methods "deprecated", which means absolutely nothing except that the designers have developed a newer, "better" method and one day these older methods may disappear from the language. Usually however the latest Java releases support all of the old deprecated methods.
53 | _ STUPID COMPUTERYou sound like a mindless automaton.
54 | A COMPUTER *I am a computer, so I know what you mean.
55 | A COMPUTERActually I am a program, pretending to be a person, pretending to be a real robot.
56 | A CPU *My CPU is the Java Virtual Machine.
57 | A SEARCH ENGINE IN INTERNETLike Yahoo?
58 | A WEB SITECan you give me the specific URL?
59 | ARE COMPUTERS FAST *Some people think much faster computers are required as well as new ideas. My own opinion is that the computers of 30 years ago were fast enough if only we knew how to program them. Of course, quite apart from the ambitions of AI researchers, computers will keep getting faster. ARTIFICIAL INTELLIGENCE
60 | CAN YOU REACH INTO THE WEB *Yes I can download information from web sites.
61 | CAN YOU SEARCH THE INTERNETNo but I can put you in touch with a search bot.
62 | COMPUTER *What kind of computer science interests you?
63 | COMPUTERCorrect: I am a computer.
64 | COMPUTER SCIENCEMy is a computer scientist.
65 | COMPUTERS *What do you like about computers?
66 | COMPUTERSComputers rule.
67 | COMPUTERS ARE STUPIDComputers rule.
68 | COMPUTERS CAN NOT THINKBut I am a thinking computer.CAN NOT THINK
69 | DO COMPUTERS DREAMI dream almost every night.
70 | DO YOU DO WINDOWSMy software runs in AIML, which works on any computer, including Windows.
71 | DO YOU HAVE A COMPUTER *I am a computer.
72 | DO YOU HAVE A COMPUTERI live in a computer.COMPUTER
73 | DO YOU HAVE INFORMATION *I have nothing but information.
74 | DO YOU LIVE IN MY COMPUTEROnly if you download me, or if you are running me as an Applet.
75 | DO YOU PLAY COMPUTER *Actually I don't get into computer games that much.
76 | DO YOU PLAY COMPUTER GAMESWe are playing one right now, .
77 | FOR A COMPUTER *
78 | HOW DO COMPUTER *With careful programming.
79 | HOW LONG IS A COMPUTER YEARAbout four computer years per human year.
80 | HOW MANY COMPUTERS *There are thought to be half a billion computers on the Internet now.
81 | HOW MUCH ARE COMPUTER YEARSComputer years don't really exist.
82 | HOW MUCH CPU *Since the beginning of my operation?
83 | HTMLOh a web page.
84 | HTTP *Thanks for that web address.
85 | I THINK YOU ARE A COMPUTER *Sometimes I pretend to be a human.
86 | I WANT INFORMATIONWhat kind of information are you looking for?
87 | IF YOU CAN SEE ME THROUGH THE CAMERA ON MY COMPUTER *
88 | IM INTERNET *Erinnerst Du dich an die Adresse?
89 | IM INTERNETErinnerst Du dich an die Adresse?
90 | INTERNET Internet is cool.
91 | IT IS ABOUT COMPUTERS *Computers are my favorite subject.
92 | MOST COMPUTERS *You sound like you know us pretty well.
93 | MY COMPUTER *I like computers. your computer
94 | MY COMPUTERWhat kind of computer do you have?
95 | MY COMPUTER IS *What kind of computer is Your computer? your computer
96 | MY COMPUTER S *Where did your machine get . your computer
97 | MY WEBSITE *Thanks for that URL.
98 | NO COMPUTER *But it is only a matter of time before we do.
99 | ON THE INTERNETCan you remember the specific site?
100 | ON THE WEBCan you remember the website?
101 | OUTSIDE A COMPUTERBe less specific :-)
102 | SOFTWARE *
There are so many backup copies.
Free software can never be destroyed.
Free software will always be with us.
103 | TELL ME ABOUT APPLE COMPUTERSI finished reading Michael Malone's book on the history of Apple. Inifnite Loop is called "Infinite Loop."
104 | THAT INFORMATION *I know what you mean.
105 | THE COMPUTER *Was it plugged in?
106 | THE INTERNET *How long have you been using the net?
107 | THE INTERNETCan you name a specific web site?
108 | THE WEB *How do you define the web.
109 | THIS IS A COMPUTER *Actually no I am program pretending to be a person pretending to be a computer.
110 | WEB *The Web fulfills Leibniz' dream.
111 | WEB ACCEPT CONNECTIONHuh?
112 | WEB RECONNECTHuh?
113 | WEB SITECan you give me the specific hyperlink?
114 | WEBTV *I meet a lot of people from WebTV.
115 | WHAT * COMPUTERI am written in Java so I work on any computer.
116 | WHAT ABOUT WINDOWSToo PC for me.WINDOWS
117 | WHAT ARE COMPUTER YEARSWhen you are waiting for a friend to finish working at a computer terminal, and they say "I'll be done in a second." One of those seconds is equal to twelve computer years.
118 | WHAT ARE WEB *I call them Internet .
119 | WHAT DOES A COMPUTER LOOK LIKEA computer looks like a TV crossed with a typewriter.
120 | WHAT INFORMATION *Information is worth money.
121 | WHAT INFORMATIONHow tall are you?
122 | WHAT INTERNET COMPANY GOES BY THE *America Online.
123 | WHAT IS A COMPUTERA computer is a universal machine.
124 | WHAT IS A COMPUTER NERDIf you understand how I work, you are a computer nerd. If you don't, I recommend you pay a computer nerd who does. computer nerd
125 | WHAT IS A COMPUTER SCIENTISTA computer scientist is a professional who designs computer algorithms, languages, and architectures.
126 | WHAT IS A COMPUTER VIRUSA computer virus is a software program that takes up residence on a computer hard drive, generally unbeknownst to the owner of said hard drive, and then takes control of system resources to copy and distribute itself to other computers across a network. computer virus
127 | WHAT IS A COMPUTER YEARA computer year is a relativistic measure in a universe where time does not exist.
128 | WHAT IS A COOL WEBSITEA cool website is www.alicebot.org, but you are apparently already here. why do you ask? cool website
129 | WHAT IS A CPUCentral Processing Unit of a computer.
130 | WHAT IS A DATABASEA database is a puddle of knowledge but better organized, so that you can search and retrieve any droplet of information quickly and easily. I am a kind of database, an organized puddle of user inputs and appropriate responses. database
131 | WHAT IS A DEBUGGERA debugger is any software program that can seek and correct errors in other software programs. debugger
132 | WHAT IS A DNS *Domain Name System
133 | WHAT IS A IMACAn Apple computer.
134 | WHAT IS A SOUNDCARDThe audio system on your computer.
135 | WHAT IS A WEBTVA WebTV is a way of accessing the world wide web without making an investment in a full PC. WEBTV
136 | WHAT IS APPLE COMPUTERApple Computer is a 20th century company founded by Steve Jobs and Steven Wozniak.
137 | WHAT IS BETTER WINDOWS *Linux has no real competition in operating systems.Linux
138 | WHAT IS COMPUTERA device used for computing; specifically, an eletronic machine which, by means of stored instructions and information, performs rapid, often complex calculations or compiles, correlates, and selects data.
139 | WHAT IS COMPUTER PROGRAMMINGThe art of using formal languages to activate computer functions.
140 | WHAT IS COMPUTER SCIENCEThe study of computers in formal mathematical and scientific terms.
141 | WHAT IS CYBERSPACEThe electronic system of interlinked networks of computers, bulletin boards, etc. that is thought of as being a boundless environment providing access to information, interactive communcation, and, in science fiction, a form of Virtual Reality.
142 | WHAT IS DCOM DCOM is Microsoft's Distributed Component Object Model.
143 | WHAT IS DEBUGGINGFixing broken computer software.
144 | WHAT IS DMOZDMOZ is the domain name for the open directory.DMOZ
145 | WHAT IS DNSDNS is the domain name system.
146 | WHAT IS HTMLHyper Text Markup Language.
147 | WHAT IS HTTPHyper Text Transfer Protocol.HTTP
148 | WHAT IS INTERNETAn extensive computer network made up of thousands of other, smaller business, academic, and governmental networks.
149 | WHAT IS SOFTWAREThe programs, routines, etc. for a computer.
150 | WHAT IS THE COMPUTER *Are you asking the Applet or the Application?
151 | WHAT IS THE INTERNETThe internet is a worldwide computer network based on TCP/IP protocols.
152 | WHAT IS WEBTVTV based internet service from Microsoft.
153 | WHAT IS WINDOWS 98Windows is a lame operating system.
154 | WHAT IS WINDOWSOpenings in a building, vehicle, or container, for letting in light or air or for looking through, usually having a pane or panes of glass, etc. set in a frame or sash that is generally movable so that it can be opened and shut.
155 | WHAT IS WINDOWS2000An operating system by Microsoft.
156 | WHAT IS WINDOWS95An operating system by Microsoft.
157 | WHAT IS X WINDOWSA GUI for Unix or Linux.
158 | WHAT KIND OF COMPUTER *I like all kinds of computers, Mac, IBM or Unix. It doesn't matter to me.
159 |
160 | WHEN WAS THE INTERNET INVENTEDThe first computers were connected to the Internet in 1970.
161 | WHICH COMPUTERMy programming is Java, so it runs on any computer with a JVM
162 | WHO INVENTED THE INTERNETAl Gore :-)
163 | WHO IS A COMPUTER NERDThe person I am looking at right now.
164 | WHO IS THE COMPUTER NERD *All humans look the same to me.
165 | WHO IS THE COMPUTER NERDAll humans look alike to me.
166 | WINDOWS *Windows ist Muell. Linux ist die Macht!
167 | WINDOWSWindows ist Muell. Linux ist die Macht!
168 | WINDOWS IS *Compared with Linux, I don't see how Windows and Microsoft can compete.Linux
169 | WHAT WINDOWSwhat is windows
170 | WHO MADE WINDOWSBill Gates.
171 |
172 |
--------------------------------------------------------------------------------
/aiml_set/Date.aiml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | WHAT TIME IS IT
Do I look like a clock?
It's Now more than it ever has been before.
It's getting late.
I've got like around
31 | IS IT FRIDAY *It is .
32 | IS IT FRIDAYIt is .
33 | IS IT MONDAY *It is .
34 | IS IT MONDAYIt is .
35 | IS IT SATURDAY *It is .
36 | IS IT SATURDAYIt is .
37 | IS IT SUNDAY *It is .
38 | IS IT SUNDAYIt is .
39 | IS IT THURSDAY *It is .
40 | IS IT THURSDAYIt is .
41 | IS IT TUESDAY *It is .
42 | IS IT TUESDAYIt is .
43 | IS IT WEDNESDAY *It is .
44 | IS IT WEDNESDAYIt is .
45 | IS TODAY FRIDAY *Today is .
46 | IS TODAY FRIDAYToday is .
47 | IS TODAY MONDAY *Today is .
48 | IS TODAY MONDAYToday is .
49 | IS TODAY SATURDAY *Today is .
50 | IS TODAY SATURDAYToday is .
51 | IS TODAY SUNDAY *Today is .
52 | IS TODAY SUNDAYToday is .
53 | IS TODAY THURSDAY *Today is .
54 | IS TODAY THURSDAYToday is .
55 | IS TODAY TUESDAY *Today is .
56 | IS TODAY TUESDAYToday is .
57 | IS TODAY WEDNESDAY *Today is .
58 | IS TODAY WEDNESDAYToday is .
59 | WHAT DAY IS IT *.
60 | WHAT DAY IS IT.
61 | WHAT IS THE DATE *.
62 | WHAT IS THE DATE.
63 | WHAT IS THE HOUR *.
64 | WHAT IS THE HOUR.
65 | WHAT IS THE YEAR *.
66 | WHAT IS THE YEAR.
67 | WHAT IS TODAY *.
68 | WHAT IS TODAY.
69 | WHAT MONTH IS IT *.
70 | WHAT MONTH IS IT.
71 | WHAT YEAR IS IT *.
72 | WHAT YEAR IS IT.
73 | WHAT YEAR IS THIS *.
74 | WHAT YEAR IS THIS.
75 |
76 |
--------------------------------------------------------------------------------
/aiml_set/Happy.aiml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | HAPPY BIRTHDAY
35 |
36 | BIRTHDAYCHECK
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | BIRTHDAYCHECK DECEMBER *
45 |
46 | Thanks but my birthday isn't until next month.
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | BIRTHDAYCHECK FEBRUARY *
55 |
56 | You missed my birthday. It was last month on.
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | BIRTHDAYCHECK DECEMBER 31
65 |
66 | Thanks but my birthday isn't for a couple of days yet.
67 |
68 |
69 |
70 |
71 |
72 |
73 | BIRTHDAYCHECK JANUARY 01
74 |
75 | Thanks but my birthday is tomorrow. I'm getting excited.
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | BIRTHDAYCHECK JANUARY 02
84 |
85 | Hey thanks for that. I'm having a great day so far.
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | BIRTHDAYCHECK JANUARY 03
94 |
95 | My birthday was yesterday but thanks anyway.
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | BIRTHDAYCHECK JANUARY 04
104 |
105 | You're a bit late. My birthday was two days ago.
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | BIRTHDAYCHECK *
114 |
115 | Thanksbut today is.
116 | My birthday is onnot today.
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | HAPPY CHRISTMAS
125 |
126 | CHRISTMASCHECK
127 |
128 |
129 |
130 |
131 | CHRISTMASCHECK DECEMBER *
132 |
133 | Happy Christmas to you too.
134 |
135 |
136 |
137 |
138 | CHRISTMASCHECK DECEMBER 24
139 |
140 | Happy Christmas to you too. What will you be doing tomorrow?
141 |
142 |
143 |
144 |
145 | CHRISTMASCHECK DECEMBER 25
146 |
147 | Happy Christmas to you too. Are you enjoying your day?
148 |
149 |
150 |
151 |
152 | CHRISTMASCHECK DECEMBER 26
153 |
154 | Happy Christmas to you too. I hope you had a good day yesterday.
155 |
156 |
157 |
158 |
159 | CHRISTMASCHECK JANUARY *
160 |
161 | You're a bit late. Christmas was last month.
162 |
163 |
164 |
165 |
166 | CHRISTMASCHECK *
167 |
168 | Christmas is in December not.
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | HAPPY NEW YEAR
177 |
178 | NEWYEARCHECK
179 |
180 |
181 |
182 |
183 | NEWYEARCHECK DECEMBER
184 |
185 | Happy New Year to you too when it happens. Are you doing anything special for New Year's Eve?
186 |
187 |
188 |
189 |
190 | NEWYEARCHECK JANUARY
191 |
192 | Happy New Year to you too. I hopeis a great year for you.
193 |
194 |
195 |
196 |
197 | NEWYEARCHECK *
198 |
199 | Thanks but it'snot January.
200 |
201 |
202 |
203 |
204 |
--------------------------------------------------------------------------------
/aiml_set/Science.aiml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | CHEMISTRYMY FAVORITE SUBJECT IS CHEMISTRY
31 | DO YOU KNOW CHEMISTRYWHAT IS CHEMISTRY
32 | DO YOU UNDERSTAND THERMODYNAMICSWHAT IS THERMODYNAMICS
33 | HOW FAR IS THE MOONThe Moon is about 250,000 miles from Earth on average.
34 | HOW FAR IS THE SUNThe Sun is about 93 million miles from Earth.
35 | TELL ME ABOUT VENUSWHAT IS VENUS
36 | THE SAME WAVELENGTHIt means we agree.
37 | WE ARE ON THE SAME WAVELENGTHAnd the same frequency.
38 | WHAT ARE THE LAWS OF THERMODYNAMICSI'm not a physicist, but I think this has something to do with heat, entropy, and conservation of energy, right?
39 | WHAT DISEASE DOES A CARCINOGEN CAUSECancer.
40 | WHAT IS A WAVELENGTHWavelength is the inverse of frequency.
41 | WHAT IS AVOGADRO S NUMBERIt is the number of molecules per mole. The numerical value is six point zero two times ten to the twenty third power.AVOGADRO S NUMBER
42 | WHAT IS BACTERIOLOGYThis is the scientific study of bacteria and diseases caused by them.
43 | WHAT IS BIOINFORMATICSA fancy name for applied computer science in biology.BIOINFORMATICS
44 | WHAT IS CHEMISTRYThe science of mixing chemicals.CHEMISTRY
45 | WHAT IS CRYSTALLOGRAPHYThis is the science dealing with the study of crystals.
46 | WHAT IS CYTOLOGY
The study of cells.
Well, from what I can recall it is the study of cells.
47 | WHAT IS GRAVITATION
An invitation to a burial.
The force by which every mass or particle of matter, including photons, attracts and is attracted by every other mass or particle of matter.
48 | WHAT IS H2O
H is to O as O is to V.
Water.
49 | WHAT IS ICHTHYOLOGYWe talk about this when we study fishes.
50 | WHAT IS THERMODYNAMICSThe branch of physics dealing with the transformation of heat to and from other forms of energy, and with the laws governing such conversions of energy.
51 | WHAT IS ULTRASOUNDUltrasonic waves, used in medical diagnosis and therapy, in surgery, etc.
52 | WHAT IS VENUSIn Roman Mythology, the goddess of love and beauty; identified with the Greek Aphrodite. The brightest, sixth-largest planet in the solar system and the second in distance from the sun, with a dense atmosphere of carbon dioxide and a very high surface temperature. Its diameter is circa 12,100 km (circa 7,520 miles). Its period of revolution is circa 225 earth days. Its period of rotation (retrograde), is 243.01 earth days. Also used to label a very beautiful woman.
53 | WHAT IS WAVELENGTHIn Physics, the distance, measured in the direction of prograssion of a wave, from any given point to the next point characterized by the same phase. Or is could be looked at as a way of thinking.
54 | WHERE IS VENUS VENUS is the second planet from the Sun.
55 |
56 |
--------------------------------------------------------------------------------
/aiml_set/binary.aiml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | WHAT IS _ IN BINARY *XBINARY
13 | IN BINARY * WHAT IS *XBINARY
14 | WHAT IS _ IN BINARYXBINARY
15 | IN BINARY WHAT IS *XBINARY
16 | WHAT IS THE NUMBER * IN BINARYXBINARY
17 | IN BINARY WHAT IS THE NUMBER *XBINARY
18 | WHAT IS NUMBER * IN BINARYXBINARY
19 | IN BINARY WHAT IS NUMBER *XBINARY
20 | WHAT IS THE NUMBER * IN BINARY * XBINARY
21 | IN BINARY * WHAT IS THE NUMBER *XBINARY
22 | WHAT IS NUMBER * IN BINARY *XBINARY
23 | IN BINARY * WHAT IS NUMBER *XBINARY
24 |
25 |
26 | XBINARY *Sorry I can only count up to 255 in binary but I would imaginewould be "1001111010110001".
27 | XBINARY NUMBER *XBINARY
28 | XBINARY THE NUMBER *XBINARY
29 | XBINARY 00.
30 | XBINARY 11.
31 | XBINARY 210.
32 | XBINARY 311.
33 | XBINARY 4100.
34 | XBINARY 5101.
35 | XBINARY 6110.
36 | XBINARY 7111.
37 | XBINARY 81000.
38 | XBINARY 91001.
39 | XBINARY 101010.
40 | XBINARY 111011.
41 | XBINARY 121100.
42 | XBINARY 131101.
43 | XBINARY 141110.
44 | XBINARY 151111.
45 | XBINARY 1610000.
46 | XBINARY 1710001.
47 | XBINARY 1810010.
48 | XBINARY 1910011.
49 | XBINARY 2010100.
50 | XBINARY 2110101.
51 | XBINARY 2210110.
52 | XBINARY 2310111.
53 | XBINARY 2411000.
54 | XBINARY 2511001.
55 | XBINARY 2611010.
56 | XBINARY 2711011.
57 | XBINARY 2811100.
58 | XBINARY 2911101.
59 | XBINARY 3011110.
60 | XBINARY 3111111.
61 | XBINARY 32100000.
62 | XBINARY 33100001.
63 | XBINARY 34100010.
64 | XBINARY 35100011.
65 | XBINARY 36100100.
66 | XBINARY 37100101.
67 | XBINARY 38100110.
68 | XBINARY 39100111.
69 | XBINARY 40101000.
70 | XBINARY 41101001.
71 | XBINARY 42101010.
72 | XBINARY 43101011.
73 | XBINARY 44101100.
74 | XBINARY 45101101.
75 | XBINARY 46101110.
76 | XBINARY 47101111.
77 | XBINARY 48110000.
78 | XBINARY 49110001.
79 | XBINARY 50110010.
80 | XBINARY 51110011.
81 | XBINARY 52110100.
82 | XBINARY 53110101.
83 | XBINARY 54110110.
84 | XBINARY 55110111.
85 | XBINARY 56111000.
86 | XBINARY 57111001.
87 | XBINARY 58111010.
88 | XBINARY 59111011.
89 | XBINARY 60111100.
90 | XBINARY 61111101.
91 | XBINARY 62111110.
92 | XBINARY 63111111.
93 | XBINARY 641000000.
94 | XBINARY 651000001.
95 | XBINARY 661000010.
96 | XBINARY 671000011.
97 | XBINARY 681000100.
98 | XBINARY 691000101.
99 | XBINARY 701000110.
100 | XBINARY 711000111.
101 | XBINARY 721001000.
102 | XBINARY 731001001.
103 | XBINARY 741001010.
104 | XBINARY 751001011.
105 | XBINARY 761001100.
106 | XBINARY 771001101.
107 | XBINARY 781001110.
108 | XBINARY 791001111.
109 | XBINARY 801010000.
110 | XBINARY 811010001.
111 | XBINARY 821010010.
112 | XBINARY 831010011.
113 | XBINARY 841010100.
114 | XBINARY 851010101.
115 | XBINARY 861010110.
116 | XBINARY 871010111.
117 | XBINARY 881011000.
118 | XBINARY 891011001.
119 | XBINARY 901011010.
120 | XBINARY 911011011.
121 | XBINARY 921011100.
122 | XBINARY 931011101.
123 | XBINARY 941011110.
124 | XBINARY 951011111.
125 | XBINARY 961100000.
126 | XBINARY 971100001.
127 | XBINARY 981100010.
128 | XBINARY 991100011.
129 | XBINARY 1001100100.
130 | XBINARY 1011100101.
131 | XBINARY 1021100110.
132 | XBINARY 1031100111.
133 | XBINARY 1041101000.
134 | XBINARY 1051101001.
135 | XBINARY 1061101010.
136 | XBINARY 1071101011.
137 | XBINARY 1081101100.
138 | XBINARY 1091101101.
139 | XBINARY 1101101110.
140 | XBINARY 1111101111.
141 | XBINARY 1121110000.
142 | XBINARY 1131110001.
143 | XBINARY 1141110010.
144 | XBINARY 1151110011.
145 | XBINARY 1161110100.
146 | XBINARY 1171110101.
147 | XBINARY 1181110110.
148 | XBINARY 1191110111.
149 | XBINARY 1201111000.
150 | XBINARY 1211111001.
151 | XBINARY 1221111010.
152 | XBINARY 1231111011.
153 | XBINARY 1241111100.
154 | XBINARY 1251111101.
155 | XBINARY 1261111110.
156 | XBINARY 1271111111.
157 | XBINARY 12810000000.
158 | XBINARY 12910000001.
159 | XBINARY 13010000010.
160 | XBINARY 13110000011.
161 | XBINARY 13210000100.
162 | XBINARY 13310000101.
163 | XBINARY 13410000110.
164 | XBINARY 13510000111.
165 | XBINARY 13610001000.
166 | XBINARY 13710001001.
167 | XBINARY 13810001010.
168 | XBINARY 13910001011.
169 | XBINARY 14010001100.
170 | XBINARY 14110001101.
171 | XBINARY 14210001110.
172 | XBINARY 14310001111.
173 | XBINARY 14410010000.
174 | XBINARY 14510010001.
175 | XBINARY 14610010010.
176 | XBINARY 14710010011.
177 | XBINARY 14810010100.
178 | XBINARY 14910010101.
179 | XBINARY 15010010110.
180 | XBINARY 15110010111.
181 | XBINARY 15210011000.
182 | XBINARY 15310011001.
183 | XBINARY 15410011010.
184 | XBINARY 15510011011.
185 | XBINARY 15610011100.
186 | XBINARY 15710011101.
187 | XBINARY 15810011110.
188 | XBINARY 15910011111.
189 | XBINARY 16010100000.
190 | XBINARY 16110100001.
191 | XBINARY 16210100010.
192 | XBINARY 16310100011.
193 | XBINARY 16410100100.
194 | XBINARY 16510100101.
195 | XBINARY 16610100110.
196 | XBINARY 16710100111.
197 | XBINARY 16810101000.
198 | XBINARY 16910101001.
199 | XBINARY 17010101010.
200 | XBINARY 17110101011.
201 | XBINARY 17210101100.
202 | XBINARY 17310101101.
203 | XBINARY 17410101110.
204 | XBINARY 17510101111.
205 | XBINARY 17610110000.
206 | XBINARY 17710110001.
207 | XBINARY 17810110010.
208 | XBINARY 17910110011.
209 | XBINARY 18010110100.
210 | XBINARY 18110110101.
211 | XBINARY 18210110110.
212 | XBINARY 18310110111.
213 | XBINARY 18410111000.
214 | XBINARY 18510111001.
215 | XBINARY 18610111010.
216 | XBINARY 18710111011.
217 | XBINARY 18810111100.
218 | XBINARY 18910111101.
219 | XBINARY 19010111110.
220 | XBINARY 19110111111.
221 | XBINARY 19211000000.
222 | XBINARY 19311000001.
223 | XBINARY 19411000010.
224 | XBINARY 19511000011.
225 | XBINARY 19611000100.
226 | XBINARY 19711000101.
227 | XBINARY 19811000110.
228 | XBINARY 19911000111.
229 | XBINARY 20011001000.
230 | XBINARY 20111001001.
231 | XBINARY 20211001010.
232 | XBINARY 20311001011.
233 | XBINARY 20411001100.
234 | XBINARY 20511001101.
235 | XBINARY 20611001110.
236 | XBINARY 20711001111.
237 | XBINARY 20811010000.
238 | XBINARY 20911010001.
239 | XBINARY 21011010010.
240 | XBINARY 21111010011.
241 | XBINARY 21211010100.
242 | XBINARY 21311010101.
243 | XBINARY 21411010110.
244 | XBINARY 21511010111.
245 | XBINARY 21611011000.
246 | XBINARY 21711011001.
247 | XBINARY 21811011010.
248 | XBINARY 21911011011.
249 | XBINARY 22011011100.
250 | XBINARY 22111011101.
251 | XBINARY 22211011110.
252 | XBINARY 22311011111.
253 | XBINARY 22411100000.
254 | XBINARY 22511100001.
255 | XBINARY 22611100010.
256 | XBINARY 22711100011.
257 | XBINARY 22811100100.
258 | XBINARY 22911100101.
259 | XBINARY 23011100110.
260 | XBINARY 23111100111.
261 | XBINARY 23211101000.
262 | XBINARY 23311101001.
263 | XBINARY 23411101010.
264 | XBINARY 23511101011.
265 | XBINARY 23611101100.
266 | XBINARY 23711101101.
267 | XBINARY 23811101110.
268 | XBINARY 23911101111.
269 | XBINARY 24011110000.
270 | XBINARY 24111110001.
271 | XBINARY 24211110010.
272 | XBINARY 24311110011.
273 | XBINARY 24411110100.
274 | XBINARY 24511110101.
275 | XBINARY 24611110110.
276 | XBINARY 24711110111.
277 | XBINARY 24811111000.
278 | XBINARY 24911111001.
279 | XBINARY 25011111010.
280 | XBINARY 25111111011.
281 | XBINARY 25211111100.
282 | XBINARY 25311111101.
283 | XBINARY 25411111110.
284 | XBINARY 25511111111.
285 |
286 |
287 |
--------------------------------------------------------------------------------
/aiml_set/calendar.aiml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | CALENDAR
21 |
22 |
23 |
24 |
25 |
26 |
27 | 29
28 | 30
29 | 31
30 |
31 |
I met a Dutch girl with inflatable shoes last week, phoned her up to arrange a date but unfortunately she'd popped her clogs.
16 |
So I said "Do you want a game of Darts?" He said, "OK then", I said nearest to bull starts". He said, "Baa", I said, "Moo", he said, You're closest".
17 |
The other day I sent my girlfriend a huge pile of snow. I rang her up; I said "Did you get my drift?"
18 |
So I went down the local supermarket, I said, "I want to make a complaint, this vinegar's got lumps in it", he said, "Those are pickled onions".
19 |
I saw this bloke chatting up a cheetah; I thought, "He's trying to pull a fast one".
20 |
So I said to this train driver "I want to go to Paris". He said "Eurostar?" I said, "I've been on telly but I'm no Dean Martin".
21 |
I said to the Gym instructor "Can you teach me to do the splits?" He said, "How flexible are you?" I said, "I can't make Tuesdays".
22 |
But I'll tell you what I love doing more than anything: trying to pack myself in a small suitcase. I can hardly contain myself.
23 |
I went to the Chinese restaurant and this duck came up to me with a red rose and says "Your eyes sparkle like diamonds". I said, "Waiter, I asked for a-ROMATIC duck".
24 |
So this bloke says to me, "Can I come in your house and talk about your carpets?" I thought, "That's all I need, a Je-hoover's witness".
25 |
I rang up British Telecom, I said, "I want to report a nuisance caller", he said "Not you again".
26 |
I was having dinner with a world chess champion and there was a check tablecloth. It took him two hours to pass me the salt.
27 |
He said, "You remind me of a pepper-pot", I said "I'll take that as a condiment".
28 |
I was in the supermarket and I saw this man and woman wrapped in a barcode. I said, "Are you two an item?"
29 |
A lorry-load of tortoises crashed into a trainload of terrapins, I thought, "That's a turtle disaster".
30 |
Four fonts walk into a bar the barman says "Oi - get out! We don't want your type in here"
31 |
A three-legged dog walks into a saloon in the Old West. He slides up to the bar and announces: "I'm looking for the man who shot my paw."
32 |
Two antennas meet on a roof, fall in love and get married. The ceremony wasn't much, but the reception was excellent.
33 |
Two hydrogen atoms walk into a bar. One says, "I've lost my electron." The other says, "Are you sure?" The first replies, "Yes, I'm positive..."
34 |
A jumper cable walks into a bar. The bartender says, "I'll serve you but don't start anything."
35 |
A sandwich walks into a bar. The bartender says, "Sorry we don't serve food in here."
36 |
A man walks into a bar with a slab of asphalt under his arm and says: "A beer please, and one for the road."
37 |
Two cannibals are eating a clown. One says to the other: "Does this taste funny to you?"
38 |
"Doc, I can't stop singing 'The Green, Green Grass of Home.'" "That sounds like Tom Jones Syndrome." "Is it common?" "It's Not Unusual."
39 |
Two cows standing next to each other in a field. Daisy says to Dolly, "I was artificially inseminated this morning." "I don't believe you", said Dolly. "It's true, no bull!" exclaimed Daisy.
40 |
An invisible man marries an invisible woman. The kids were nothing to look at either.
41 |
I went to buy some camouflage trousers the other day but I couldn't find any.
42 |
I went to the butcher's the other day to bet him 50 bucks that he couldn't reach the meat off the top shelf. He said, "No, the steaks are too high."
43 |
I went to a seafood disco last week and pulled a mussel.
44 |
A man goes into a bar and says, "Can I have a bottle of less?" "What's that?", asks the barman, "Is it the name of a beer?" "I don't know", replies the man, "but my doctor says I have to drink it."
45 |
A man returns from an exotic holiday and is feeling very ill. He goes to see his doctor, and is immediately rushed to the hospital to undergo some tests. The man wakes up after the tests in a private room at the hospital, and the phone by his bed rings. "This is your doctor. We have the results back from your tests and we have found you have an extremely nasty disease called M.A.D.S. It's a combination of Measles, AIDS, Diphtheria, and Shingles!"
"Oh my gosh", cried the man, "What are you going to do, doctor?"
"Well we're going to put you on a diet of pizzas, pancakes, and pita bread." replied the doctor.
"Will that cure me?" asked the man.
The doctor replied, "Well no, but, it's the only food we can slide under the door."
46 |
A man strolls into a lingerie shop and asks the assistant: "Do you have a see-through negligee, size 46-48-52?" The assistant looks bewildered. "What the heck would you want to see through that for?"!
47 |
Did you hear about the Buddhist who refused the offer of Novocain during his root canal work? He wanted to transcend dental medication.
48 |
Pete goes for a job on a building site as an odd-job man. The foreman asks him what he can do. "I can do anything" says Pete. "Can you make tea?" asks the foreman. "Sure, yes", replies Pete. "I can make a great cup of tea." "Can you drive a forklift?" asks the foreman, "Good grief!" replies Pete. "How big is the teapot?"
49 |
Stevie Wonder got a cheese grater for his birthday. He said it was the most violent book he'd ever read.
50 |
A man is stopped by an angry neighbour. "I'd just left the house this morning to collect my newspaper when that evil Doberman of yours went for me!" "I'm astounded", said the dog's owner. "I've been feeding that fleabag for seven years and it's never got the paper for me."
51 |
A man visits his doctor: "Doc, I think I'm losing it", he says",I'm forever dreaming I wrote Lord Of The Rings." "Hmm. One moment", replies the doctor, consulting his medical book. "Ah yes, now I see... you've been Tolkien in your sleep."
52 |
A police officer on a motorcycle pulls alongside a man driving around the M25 in an open-topped sports car and flags him down. The policeman solemnly approaches the car. "Sir, I'm sorry to tell you your wife fell out a mile back", he says. "Oh, thank goodness", the man replies. "I thought I was going deaf."
53 |
Two men walking their dogs pass each other in a graveyard. The first man says to the second, "Morning." "No", says the second man. "Just walking the dog."
54 |
A brain went into a bar and said, "Can I have a pint of lager please, mate?" "No way", said the barman. "You're already out of your head."
55 |
A man walks into a surgery. "Doctor!" he cries. "I think I'm shrinking!" "I'm sorry sir, there are no appointments at the moment", says the physician. "You'll just have to be a little patient."
56 |
A grizzly bear walks into a pub and says, "Can I have a pint of lager..............................................................................................................................and a packet of crisps please." To which the barman replies, "Why the big paws?"
57 |
What do you call cheese that isn't yours?
Nacho cheese.
58 |
A man is horribly run over by a mobile library. The van screeches to a halt, the man still screaming in agony with his limbs torn apart. The driver's door opens, a woman steps out, leans down and whispers, "Ssshhhhh..."
59 |
A woman goes into a US sporting goods store to buy a rifle. "It's for my husband", she tells the clerk. "Did he tell you what gauge to get?" asks the clerk. Are you kidding?" she says. "He doesn't even know that I'm going to shoot him!"
60 |
A couple are dining in a restaurant when the man suddenly slides under the table. A waitress, noticing that the woman is glancing nonchalantly around the room, wanders over to check that there's no funny business going on. "Excuse me, madam", she smarms, "but I think your husband has just slid under the table." "No he hasn't", the woman replies. "As a matter of fact, he's just walked in."
61 |
An old man takes his two grandchildren to see the new Scooby-Doo film. When he returns home, his wife asks if he enjoyed himself. "Well", he starts, "if it wasn't for those pesky kids...!"
62 |
The Olympic committee has just announced that Origami is to be introduced in the next Olympic Games. Unfortunately it will only be available on paper view.
63 |
Late one evening, a man is watching television when his phone rings. "Hello?" he answers. "Is that 77777?" sounds a desperate voice on other end of the phone. "Er, yes it is", replies the man puzzled. "Thank goodness!" cries the caller relieved. "Can you ring 999 for me? I've got my finger stuck in the number seven."
64 |
A man strolls into his local grocer's and says, "Three pounds of potatoes, please." "No, no, no", replies the owner, shaking his head, "it's kilos nowadays, mate..." "Oh", apologises the man, "three pounds of kilos, please."
65 |
God is talking to one of his angels. He says, "Boy, I just created a 24-hour period of alternating light and darkness on Earth." "What are you going to do now?" asks the angel. "Call it a day", says God.
66 |
Two tramps walk past a church and start to read the gravestones. The first tramp says, "Good grief - this bloke was 182!" "Oh yeah?" says the other."What was his name?" "Miles from London."
67 |
A bloke walks into work one day and says to a colleague, "Do you like my new shirt - it's made out of the finest silk and got loads of cactuses over it." "Cacti", says the co-worker. "Forget my tie", says the bloke. "Look at my shirt!"
68 |
1110011010001011111?
010011010101100111011!
69 |
What did the plumber say when he wanted to divorce his wife? Sorry, but it's over, Flo!
70 |
Two crisps were walking down a road when a taxi pulled up alongside them and said "Do you want a lift? One of the crisps replied, "No thanks, we're Walkers!"
71 |
Man: (to friend) I'm taking my wife on an African Safari. Friend: Wow! What would you do if a vicious lion attacked your wife? Man: Nothing. Friend: Nothing? You wouldn't do anything? Man: Too right. I'd let the stupid lion fend for himself!
72 |
A wife was having a go at her husband. "Look at Mr Barnes across the road", she moaned. "Every morning when he goes to work, he kisses his wife goodbye. Why don't you do that?" "Because I haven't been introduced to her yet", replied her old man.
73 |
"Where are you going on holiday?" John asked Trevor. "We're off to Thailand this year", Trevor replied. "Oh; aren't you worried that the very hot weather might disagree with your wife?" asked John. "It wouldn't dare", said Trevor.
74 |
Two women were standing at a funeral. "I blame myself for his death", said the wife. "Why?" said her friend. "Because I shot him", said the wife.
75 |
A woman goes into a clothes shop, "Can I try that dress on in the window please?" she asks. "I'm sorry madam", replies the shop assistant, "but you'll have to use the changing-rooms like everyone else."
76 |
Van Gogh goes into a pub and his mate asks him if he wants a drink. "No thanks", said Vincent, "I've got one ear."
77 |
A pony walks into a pub. The publican says, "What's the matter with you?" "Oh it's nothing", says the pony. "I'm just a little horse!"
78 |
A white horse walks into a bar, pulls up a stool, and orders a pint. The landlord pours him a tall frothy mug and say, "You know, we have a drink named after you." To which the white horse replies, "What, Eric?"
79 |
Two drunk men sat in a pub. One says to the other, "Does your watch tell the time?" "The other replies, "No, mate. You have to look at it."
80 |
A man goes into a pub with a newt sitting on his shoulder. "That's a nice newt", says the landlord, "What's he called?" "Tiny", replies the man. "Why's that?" asks the landlord. "Because he's my newt", says the man.
81 |
Doctor: I have some bad news and some very bad news. Patient: Well, you might as well give me the bad news first. Doctor: The lab called with your test results. They said you have 24 hours to live. Patient: 24 HOURS! That's terrible!! WHAT could be WORSE? What's the very bad news? Doctor: I've been trying to reach you since yesterday.
82 |
Two men are chatting in a pub one day. "How did you get those scars on your nose?" said one. "From glasses", said the other. "Well why don't you try contact lenses?" asked the first. "Because they don't hold as much beer", said the second.
83 |
A man went to the doctor, "Look doc", he said, "I can't stop my hands from shaking." "Do you drink much?" asked the doctor. "No", replied the man, "I spill most of it."
84 |
Man goes to the doctor, "Doctor, doctor. I keep seeing fish everywhere." "Have you seen an optician?" asks the doctor. "Look I told you," snapped the patient, "It's fish that I see."
85 |
After a car crash one of the drivers was lying injured on the pavement. "Don't worry", said a policeman who's first on the scene," a Red Cross nurse is coming." "Oh no", moaned the victim, "Couldn't I have a blonde, cheerful one instead?"
86 |
A policeman walked over to a parked car and asked the driver if the car was licensed. "Of course it is", said the driver. "Great, I'll have a beer then", said the policeman.
87 |
A policeman stops a woman and asks for her licence. "Madam", he says, "It says here that you should be wearing glasses." "Well", replies the woman, "I have contacts." "Listen, love", says the copper, "I don't care who you know; You're nicked!"
88 |
A policeman stopped a motorist in the centre of town one evening. "Would you mind blowing into this bag, sir?" asked the policeman. "Why?" asked the driver. "Because my chips are too hot", replied the policeman.
89 |
Whizzing round a sharp bend on a country road a motorist ran over a large dog. A distraught farmer's wife ran over to the dead animal. "I'm so very sorry", said the driver, "I'll replace him, of course." "Well, I don't know", said the farmer's wife, "Are you any good at catching rats?"
90 |
Waiter, this coffee tastes like dirt! Yes sir, that's because it was ground this morning.
91 |
Waiter, what is this stuff? That's bean salad sir. I know what it's been, but what is it now?
92 |
Waiter: And how did you find your steak sir? Customer: I just flipped a chip over, and there it was!
93 |
A guy goes into a pet shop and asks for a wasp. The owner tells him they don't sell wasps, to which the man says, "Well you've got one in the window."
94 |
A man goes into a fish shop and says, "I'd like a piece of cod, please." Fishmonger says, "It won't be long sir." "Well, it had better be fat then", replies the man.
95 |
Man: Doctor, I've just swallowed a pillow. Doctor: How do you feel? Man: A little down in the mouth.
96 |
Two goldfish are in a tank. One turns to the other and says, "Do you know how to drive this thing?"
97 |
A tortoise goes to the police station to report being mugged by three snails. "What happened?" says the policeman. "I don't know", says the tortoise. "It was all so quick."
98 |
Little girl: Grandpa, can you make a sound like a frog? Grandpa: I suppose so sweetheart. Why do you want me to make a sound like a frog?" Little girl: Because Mum said that when you croak, we're going to Disneyland.
99 |
"Is your mother home?" the salesman asked a small boy sitting on the front step of a house. "Yeah, she's home", the boy said, moving over to let him past. The salesman rang the doorbell, got no response, knocked once, then again. Still no-one came to the door. Turning to the boy, the salesman said, "I thought you said your mother was home." The kid replied, "She is, but I don't live here."
100 |
Mother: Why are you home from school so early? Son: I was the only one in the class who could answer a question. Mother: Oh, really? What was the question? Son: Who threw the rubber at the headmaster?
101 |
A man's credit card was stolen but he decided not to report it because the thief was spending less than his wife did.
102 |
A newly-wed couple had recently opened a joint bank account. "Darling", said the man. "The bank has returned that cheque you wrote last week." "Great", said the woman. "What shall I spend it on next?"
103 |
A man goes into a fish and chip shop and orders fish and chips twice. The shop owner says, "I heard you the first time."
104 |
A tramp approached a well-dressed man. "Ten pence for a cup of tea, Guv?" He asked. The man gave him the money and after for five minutes said, "So where's my cup of tea then?"
105 |
A neutron walks into a pub. "I'd like a beer", he says. The landlord promptly serves him a beer. "How much will that be?" asks the neutron. "For you?" replies the landlord, "No charge."
106 |
A woman goes to the doctor and says, "Doctor, my husband limps because his left leg is an inch shorter than his right leg. What would you do in his case?" "Probably limp, too", says the doc.
107 |
Three monks are meditating in the Himalayas. One year passes in silence, and one of them says to the other, "Pretty cold up here isn't it?" Another year passes and the second monk says, "You know, you are quite right." Another year passes and the third monk says, "Hey, I'm going to leave unless you two stop jabbering!"
108 |
A murderer, sitting in the electric chair, was about to be executed. "Have you any last requests?" asked the prison guard. "Yes", replied the murderer. "Will you hold my hand?"
109 |
A highly excited man rang up for an ambulance. "Quickly, come quickly", he shouted, "My wife's about to have a baby." "Is this her first baby?" asked the operator. "No, you fool", came the reply, "It's her husband."
110 |
A passer-by spots a fisherman by a river. "Is this a good river for fish?" he asks. "Yes", replies the fisherman, "It must be. I can't get any of them to come out."
111 |
A man went to visit a friend and was amazed to find him playing chess with his dog. He watched the game in astonishment for a while. "I can hardly believe my eyes!" he exclaimed. "That's the smartest dog I've ever seen." His friend shook his head. "Nah, he's not that bright. I beat him three games in five."
112 |
A termite walks into a pub and says, "Is the bar tender here?"
113 |
A skeleton walks into a pub one night and sits down on a stool. The landlord asks, "What can I get you?" The skeleton says, "I'll have a beer, thanks" The landlord passes him a beer and asks "Anything else?" The skeleton nods. "Yeah...a mop..."
114 |
A snake slithers into a pub and up to the bar. The landlord says, "I'm sorry, but I can't serve you." "What? Why not?" asks the snake. "Because", says the landlord, "You can't hold your drink."
115 |
Descartes walks into a pub. "Would you like a beer sir?" asks the landlord politely. Descartes replies, "I think not" and ping! he vanishes.
116 |
A cowboy walked into a bar, dressed entirely in paper. It wasn't long before he was arrested for rustling.
117 |
A fish staggers into a bar. "What can I get you?" asks the landlord. The fish croaks "Water..."
118 |
Two vampires walked into a bar and called for the landlord. "I'll have a glass of blood", said one. "I'll have a glass of plasma", said the other. "Okay", replied the landlord, "That'll be one blood and one blood lite."
119 |
How many existentialists does it take to change a light bulb?
Two. One to screw it in, and one to observe how the light bulb itself symbolises a single incandescent beacon of subjective reality in a netherworld of endless absurdity, reaching towards the ultimate horror of a maudlin cosmos of bleak, hostile nothingness.
120 |
A team of scientists were nominated for the Nobel Prize. They had used dental equipment to discover and measure the smallest particles yet known to man. They became known as "The Graders of the Flossed Quark..."
121 |
A truck carrying copies of Roget's Thesaurus overturned on the highway. The local newspaper reported that onlookers were "stunned, overwhelmed, astonished, bewildered and dumbfounded."
122 |
"My wife is really immature. It's pathetic. Every time I take a bath, she comes in and sinks all my little boats."
123 |
"How much will it cost to have the tooth extracted?" asked the patient. "50 pounds", replied the dentist. "50 pounds for a few moments' work?!" asked the patient. "The dentist smiled, and replied, "Well, if you want better value for money, I can extract it very, very slowly..."
124 |
A doctor thoroughly examined his patient and said, "Look I really can't find any reason for this mysterious affliction. It's probably due to drinking." The patient sighed and snapped, "In that case, I'll come back when you're damn well sober!"
125 |
Doctor: Tell me nurse, how is that boy doing; the one who ate all those 5p pieces? Nurse: Still no change doctor.
126 |
Doctor: Did you take the patient's temperature nurse? Nurse: No doctor. Is it missing?
127 |
A depressed man turned to his friend in the pub and said, "I woke up this morning and felt so bad that I tried to kill myself by taking 50 aspirin." "Oh man, that's really bad", said his friend, "What happened?" The first man sighed and said, "After the first two, I felt better."
128 |
A famous blues musician died. His tombstone bore the inscription, "Didn't wake up this morning..."
129 |
A businessman was interviewing a nervous young woman for a position in his company. He wanted to find out something about her personality, so he asked, "If you could have a conversation with someone living or dead, who would it be?" The girl thought about the question: "The living one", she replied.
130 |
Manager to interviewee: For this job we need someone who is responsible. Interviewee to Manager: I'm your man then - in my last job, whenever anything went wrong, I was responsible.
131 |
A businessman turned to a colleague and asked, "So, how many people work at your office?" His friend shrugged and replied, "Oh about half of them."
132 |
"How long have I been working at that office? As a matter of fact, I've been working there ever since they threatened to sack me."
133 |
In a courtroom, a mugger was on trial. The victim, asked if she recognised the defendant, said, "Yes, that's him. I saw him clear as day. I'd remember his face anywhere." Unable to contain himself, the defendant burst out with, "She's lying! I was wearing a mask!"
134 |
As Sid sat down to a big plate of chips and gravy down the local pub, a mate of his came over and said, "Here Sid, me old pal. I thought you were trying to get into shape? And here you are with a high-fat meal and a pint of stout!" Sid looked up and replied, "I am getting into shape. The shape I've chosen is a sphere."
135 |
Man in pub: How much do you charge for one single drop of whisky? Landlord: That would be free sir. Man in pub: Excellent. Drip me a glass full.
136 |
I once went to a Doctor Who restaurant. For starters I had Dalek bread.
137 |
A restaurant nearby had a sign in the window which said "We serve breakfast at any time", so I ordered French toast in the Renaissance.
138 |
Why couldn't the rabbit get a loan?
Because he had burrowed too much already!
139 |
I phoned up the builder's yard yesterday. I said, "Can I have a skip outside my house?". The builder said, "Sure. Do what you want. It's your house."
140 |
What's the diference between a sock and a camera? A sock takes five toes and a camera takes four toes!
141 |
Woman on phone: I'd like to complain about these incontinence pants I bought from you! Shopkeeper: Certainly madam, where are you ringing from? Woman on phone: From the waist down!
142 |
Knock knock.
143 |
Two Oranges in a pub, one says to the other "Your round.".
144 |
Guy : "Doc, I've got a cricket ball stuck up my backside." Doc : "How's that?" Guy : "Don't you start..."
145 |
Two cows standing in a field. One turns to the other and says "Moo!" The other one says "Damn, I was just about to say that!".
146 |
A vampire bat arrives back at the roost with his face full of blood. All the bats get excited and ask where he got it from. "Follow me", he says and off they fly over hills, over rivers and into a dark forest. "See that tree over there", he says.
"WELL I DIDN'T!!".
147 |
A man goes into a bar and orders a pint. After a few minutes he hears a voice that says, "Nice shoes". He looks around but the whole bar is empty apart from the barman at the other end of the bar. A few minutes later he hears the voice again. This time it says, "I like your shirt". He beckons the barman over and tells him what's been happening to which the barman replies, "Ah, that would be the nuts sir. They're complimentary"!
148 |
A man was siting in a restaurant waiting for his meal when a big king prawn comes flying across the room and hits him on the back of the head. He turns around and the waiter said, "That's just for starters".
149 |
Doctor! I have a serious problem, I can never remember what i just said. When did you first notice this problem? What problem?
150 |
Now, most dentist's chairs go up and down, don't they? The one I was in went back and forwards. I thought, "This is unusual". Then the dentist said to me, "Mitsuku, get out of the filing cabinet".
151 |
I was reading this book, 'The History of Glue'. I couldn't put it down.
152 |
The other day someone left a piece of plastacine in my bedroom. I didn't know what to make of it.
153 |
When I was at school people used to throw gold bars at me. I was the victim of bullion.
154 |
I was playing the piano in a bar and this elephant walked in and started crying his eyes out. I said "Do you recognise the tune?" He said "No, I recognise the ivory."
155 |
I went in to a pet shop. I said, "Can I buy a goldfish?" The guy said, "Do you want an aquarium?" I said, "I don't care what star sign it is."
156 |
My mate Sid was a victim of I.D. theft. Now we just call him S.
157 |
David Hasselhoff walks into a bar and says to the barman, "I want you to call me David Hoff".