//This file is reflex.C. #include //for copy, random_shuffle #include "reflex.h" typedef pair pair_t; const pair_t a[] = { pair_t("me", "you"), pair_t("you", "me"), pair_t("I", "you"), pair_t("my", "your"), pair_t("your", "my"), pair_t("mine", "yours"), pair_t("yours", "mine"), pair_t("myself", "yourself"), pair_t("yourself", "myself"), pair_t("I'd", "you'd"), pair_t("you'd", "I'd"), pair_t("I'm", "you're"), pair_t("you're", "I'm"), pair_t("I've", "you've"), pair_t("you've", "I've"), pair_t("am", "are"), pair_t("are", "am"), pair_t("ain't", "aren't"), pair_t("aren't", "am not"), pair_t("was", "were"), pair_t("were", "was"), pair_t("wasn't", "weren't"), pair_t("weren't", "wasn't") }; const size_t n = sizeof a / sizeof a[0]; const mapreflex::conjugate(a, a + n); reflex::reflex(string pattern_line, const string *begin, const string *end) : pattern(chop(pattern_line)) { while (begin < end) { responses.push_back(chop(*begin++)); } random_shuffle(responses.begin(), responses.end()); current = responses.begin(); } reflex::reflex(const reflex& another) : pattern(another.pattern), responses(another.responses), current(responses.begin() + (another.current - another.responses.begin())) {} reflex& reflex::operator=(const reflex& another) { if (&another != this) { pattern = another.pattern; responses = another.responses; current = responses.begin() + (another.current - another.responses.begin()); } return *this; } string reflex::operator()(vector words) { const vector::iterator found = search(words.begin(), words.end(), pattern.begin(), pattern.end()); if (found == words.end()) { return ""; } //Only the words after the pattern should remain. words.erase(words.begin(), found + pattern.size()); //Swap "my" & "your", "I'm" & "You're", etc. for (vector::iterator it = words.begin(); it != words.end(); ++it) { const map::const_iterator i = conjugate.find(it->c_str()); if (i != conjugate.end()) { *it = i->second; } } vector reply; for (vector::const_iterator it = current->begin(); it != current->end(); ++it) { if (*it == ">") { copy(words.begin(), words.end(), back_inserter(reply)); } else { reply.push_back(*it); } } //Use a different response the next time we find this pattern. if (++current == responses.end()) { current = responses.begin(); } string s; for (vector::const_iterator it = reply.begin(); it != reply.end(); ++it) { if (it != reply.begin()) { s += " "; } s += *it; } return s; } //Chop a line into a vector of individual strings (Lippman pp. 276-280). vector reflex::chop(string line) { line += " "; vector words; for (;;) { //How many leading white space characters are there? const string::size_type n1 = line.find_first_not_of(" \t"); if (n1 == string::npos) { break; } line.erase(0, n1); //Remove the leading white space. //How long is the first word? const string::size_type n2 = line.find_first_of(" \t"); words.push_back(line.substr(0, n2)); line.erase(0, n2); //Remove the leading word. } return words; }