Simple Socialising Chat Bots
Hi,
I started programming in C++ a few months ago, and I'm also really interested in psychology (hence I'm doing a degree in it). So I've recently started this simple program that relates to human dominance hierarchies, status, insults/ compliments, that kind of thing.
Basically at present all the program does is generate 4 ridiculously simple chat bots. I call them cretins. Each cretin can either insult or compliment the other cretins. The cretins perceive the status of the other 3 cretins in integer form, so that if cretin 1 insults cretin 2, cretin 2 lowers it's perception of cretin 1's status by 5 points. And the opposite for compliments. Cretins can also laugh at insults- if they see a cretin insult another cretin, they reduce their perception of the insult receiver's status by 1 point.
At present this might seem like a ludicrously simple way of trying to simulate human behaviour, but as the program gets more complicated, it should hopefully get more convincing. I intend to eventually add in a vast array of social rules and instincts, such as cretins being able to set other cretins as enemies or friends, only talking to other cretins if that cretin is popular enough, considering certain words fashionable ("get lost" or "I like you" will be replaced by banks of pre-set phrases), all kinds of stuff. And obviously, it'll end up like a proper chat room, with cretins speaking to other cretins in private rooms etc.
Here's the stuff I need help with currently:
a) Streamlining the code. This program is a LOT longer than it needs to be, I'm sure. I think it could be made shorter by having arrays instead of loads of different functions and variables such as move1, move2 etc.
b)What do you think the best way of adding in a memory for each cretin would be? I want to make it so that each cretin can remember whether it was insulted by another cretin and then respond. This way cretins will each be able to have proper strategies e.g. tit for tat. A pretty simple but cool thing would be to have escalating insult matches so that they start off with insults of weight 1 but get progressively more as the insults get more aggressive.
If anyone could help me with these I'd be really grateful. I'd also really appreciate it if you could keep your solutions as simple as possible because like I said I'm a beginner to C++.
Thanks.
Code:
// Cretinpolitics by Ben Greenwood [email protected] 27/11/07
#include <iostream>
#include <string>
#include <list>
using namespace std;
int movecounter = 1;
class cretin {
private:
std::string name;
int id;
int status1; // How this cretin perceives the status of
int status2; // the 4 cretins including itself- Arnold is always
int status3; // 1, Barry is always 2, Colin is always 3 and
int status4; // Dave is 4, whoever pereives who.
int move1; // Each cretin just has a strategy of
int move2; // 3 preset moves at present.
int move3;
public:
cretin(const std::string& nm, int i,
int s1, int s2, int s3, int s4,
int m1, int m2, int m3)
{
name = nm;
id = i;
status1 = s1;
status2 = s2;
status3 = s3;
status4 = s4;
move1 = m1;
move2 = m2;
move3 = m3;
}
std::string getname () { return name; };
int getid() { return id; };
int getstatus1() { return status1; };
int getstatus2() { return status2; };
int getstatus3() { return status3; };
int getstatus4() { return status4; };
int getmove1() {return move1; };
int getmove2() {return move2; };
int getmove3() {return move3; };
void display()
{
std::cout << id << ": " << name << "\n"
<< getstatus1() << "\n"
<< getstatus2() << "\n"
<< getstatus3() << "\n"
<< getstatus4() << "\n";
}
void setstatus1(int s1){status1 = s1;}
void setstatus2(int s2){status2 = s2;}
void setstatus3(int s3){status3 = s3;}
void setstatus4(int s4){status4 = s4;}
};
void cretinthink(std::list<cretin>& cretinlist);
int main() {
int cretinscore1; // These are the final scores that determine who
int cretinscore2; // was the most or least popular
int cretinscore3; // at the end of the session.
int cretinscore4;
std::list<cretin> cretinlist;
cretinlist.push_back(cretin("Arnold",1,0,0,0,0, 5,-5,-5)); // Each insult or compliment gets
cretinlist.push_back(cretin("Barry", 2,0,0,0,0,-5, 5, 5)); // the sayer plus or minus 5 points
cretinlist.push_back(cretin("Colin", 3,0,0,0,0,-5,-5,-5)); // in the receiver's eyes.
cretinlist.push_back(cretin("Dave" , 4,0,0,0,0, 5, 5, 5));
int choice;
while(1)
{
cout << "\nEnter 1 for next round.\n";
cin >> choice;
if (choice != 1)
break;
cretinthink(cretinlist);
if (movecounter < 3)
movecounter++;
else
movecounter = 1;
}
// The following deals with outputting each cretin's final status ratings
// for each of the other cretins in it's opinion.
std::list<cretin>::iterator iter = cretinlist.begin();
while (iter != cretinlist.end())
{
iter->display();
iter++;
};
// The following deals with outputting each cretin's total popularity score, based
// on the opinions held of it by all the other cretins. This is not the final picture because
// in reality people have allies/ enemies etc. Ultimately the aim of the game will, in the
// future, be to have as many allies who are willing to defer to you. So there will be some
// kind of thing like this because something like this will kind of describe how willing others
// are to defer to you e.g. who among your allies you can insult without them responding or
// becoming an enemy.
std::list<cretin>::iterator iter2 = cretinlist.begin();
iter = cretinlist.begin();
cretinscore1 = 0;
//iter2++;
while (iter->getid() <= 4)
{
if (iter->getid() == 1)
{ while (iter2 != cretinlist.end())
{ cretinscore1 = cretinscore1 + iter2->getstatus1();
iter2++; }
}
if (iter->getid() == 2)
{ while (iter2 != cretinlist.end())
{ cretinscore1 = cretinscore1 + iter2->getstatus2();
iter2++; }
}
if (iter->getid() == 3)
{ while (iter2 != cretinlist.end())
{ cretinscore1 = cretinscore1 + iter2->getstatus3();
iter2++; }
}
if (iter->getid() == 4)
{ while (iter2 != cretinlist.end())
{ cretinscore1 = cretinscore1 + iter2->getstatus4();
iter2++; }
}
cout << endl << iter->getname() << " ended with a popularity of score of: " << cretinscore1 << endl;
cretinscore1 = 0;
iter2 = cretinlist.begin();
if (iter->getid() == 4) // These 2 lines stop it trying to make iter
break; // go past the last cretin and cause an error.
iter++;
cretinscore1 = 0;
}
return 0;
}
void cretinthink(std::list<cretin>& cretinlist)
{
int tempinsult;
int targetcretin = 1;
cout << "Round 1" << endl << endl;
std::list<cretin>::iterator iter;
std::list<cretin>::iterator iter2;
std::list<cretin>::iterator iter3;
while (targetcretin < 5)
{
iter = cretinlist.begin(); // iter deals with the cretin complimenting/ insulting
iter2 = cretinlist.begin(); // iter2 deals with the cretin receiving that stuff
iter3 = cretinlist.begin(); // iter3 deals with the cretins observing stuff
while (iter2->getid() != targetcretin) // This just sets observer 2 to targetcretin
{
iter2++;
}
while (iter != cretinlist.end())
{
if (movecounter == 1)
tempinsult = iter->getmove1();
if (movecounter == 2)
tempinsult = iter->getmove2();
if (movecounter == 3)
tempinsult = iter->getmove3();
// The following checks if an insult or a compliment has been given
// and that the sayer and receiver of said insult are not the same cretin
if ( (tempinsult == -5 || tempinsult == 5) && (iter != iter2) )
{
if (tempinsult == -5)
{ cout << iter->getname() << ": Get lost, "
<< iter2->getname() << endl; }
if (tempinsult == 5)
{ cout << iter->getname() << ": I like you, "
<< iter2->getname() << endl; }
// The following deals with increasing or decreasing the receiver cretin's
// perceived status of each of the other cretins in status slots 1-4.
// This is based on whether the sayer gives that receiver an insult or compliment.
if (iter->getid() == 1)
{ iter2->setstatus1( iter2->getstatus1() + tempinsult ); }
if (iter->getid() == 2)
{ iter2->setstatus2( iter2->getstatus2() + tempinsult ); }
if (iter->getid() == 3)
{ iter2->setstatus3( iter2->getstatus3() + tempinsult ); }
if (iter->getid() == 4)
{ iter2->setstatus4( iter2->getstatus4() + tempinsult ); }
// LAUGHTER CODE.
// The following code deals with how each of the other cretins in the
// room perceive the receiver of an insult, to give insults some kind of
// benefit to the sayer of them. Basically they laugh at the receiver
// and this decreases the receiver's status in their eyes.
if (tempinsult == -5)
{
iter3 = cretinlist.begin();
// The following line checks if the observer cretin pointed to by
// iter3 is not the last one.
while ( (iter3->getid() <= 4) )
{
// The following cannot be part of the while loop because if it is
// then as soon as iter3->getid() = iter2->getid() the loop will
// stop even if iter2->getid() is not the last id number.
if (
( iter3->getid() != iter2->getid() )
&& (iter3->getid() != iter->getid() )
)
{
cout << iter3->getname() << ": lol." << endl;
// The following 8 lines decrease the status of the insult
// receiver in the eyes of the current observer.
if (iter2->getid() == 1)
{ iter3->setstatus1( iter3->getstatus1()-1 ); }
if (iter2->getid() == 2)
{ iter3->setstatus2( iter3->getstatus2()-1 ); }
if (iter2->getid() == 3)
{ iter3->setstatus3( iter3->getstatus3()-1 ); }
if (iter2->getid() == 4)
{ iter3->setstatus4( iter3->getstatus4()-1 ); }
}
if (iter3->getid() == 4)
break;
iter3++;
}
}
}
iter++;
}
targetcretin++;
}
}