//=========================================================================== // EVOLUTIONARY ITERATED PRISONERS DILEMMA // Revised, June, 2007 // Jackie Brosamer //=========================================================================== #include #pragma hdrstop #include "Unit1.h" // The following two lines are needed to enable the randomizer #include "stdlib.h" //#include "time.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { // Double buffering eliminates some screen flicker... DoubleBuffered = true; } //=========================================================================== // GLOBAL VARIABLES //=========================================================================== // ------------------------------------------------- your program begins here #define NO_DATA 99 // the word EMPTY will be replaced by 99 #define COOPERATE 0 #define ALWAYS_COOPERATE 0 #define DEFECT 1 #define ALWAYS_DEFECT 1 #define GRUDGER 2 #define RANDOM 3 #define TIT_FOR_TAT 4 #define TIT_FOR_TWO_TATS 5 #define KIN 6 TShape *shape[25] = {0}; // sets up an array of shapes class anAgent { // sets up an array of agents public: int strategy; int score; bool done; int rank; int tag; int lastChoice; int nextToLastChoice; int othersLastChoice[25]; // sets up local memory int othersNextToLastChoice[25]; // sets up local memory bool grudge [25]; // memory for GRUDGER strategy } agent[25]; int globalLastChoice[25]; // sets up global memory int globalNextToLastChoice[25]; // sets up global memory bool global = false; int shots = 100; int graphInterval = 1000; int evInterval = 100; class ranking { // sets up an array to rank agents by their scores public: int score; int tag; } rank[25]; int score, tag; // Other variables int chosenShape; bool aShapeWasChosen = false; int chosenCellX, chosenCellY; int cellX, cellY; int emptyE, emptyS; int fromCellX, fromCellY; bool stop = false; bool pause = false; int thisWorld[10][10]; int nextWorld[10][10]; int thisAgent, thatAgent; int thisAgentsChoice, thatAgentsChoice; int strategy; int nextAgent = 0; int lastThisAgent, lastThatAgent; int maxScore, minScore, range; int totalScore = 0; int stopAt = 5000; bool agentsAreSet = false; int east, south, relativeE, relativeS, wrappedE, wrappedS; int neighbors; int iterations=0; //=========================================================================== // FUNCTIONS //=========================================================================== //---------------------------------------------------------------- color ramp int colorRamp(int range, int value) { int pixelDistanceAlongPath = (value * 1792) / range; int red, green, blue; // Which edge of the color cube are we on? if (pixelDistanceAlongPath < 256) { // Edge 1 from BLACK to BLUE red=0; green=0; blue=pixelDistanceAlongPath; } else if (pixelDistanceAlongPath < 512) { // Edge 2 from BLUE to CYAN red =0; green=pixelDistanceAlongPath-256; blue=255; } else if (pixelDistanceAlongPath < 768) { // Edge 3 from CYAN to GREEN red =0; green =255; blue= 255-(pixelDistanceAlongPath-512); } else if (pixelDistanceAlongPath < 1024) { // Edge 4 from GREEN to YELLOW red= (pixelDistanceAlongPath-768); green =255; blue =0; } else if (pixelDistanceAlongPath <1280) { // Edge 5 from YELLOW to RED red =255; green=255-(pixelDistanceAlongPath-1024); blue =0; } else if (pixelDistanceAlongPath < 1536) { // Edge 6 from RED to MAGENTA red =255; green=0; blue=pixelDistanceAlongPath -1280; } else { // Edge 7 from MAGENTA to WHITE red =255; green=pixelDistanceAlongPath-1536; blue =255; } return (RGB(red, green, blue)); } //--------------------------------------------------------------- empty world void emptyWorld (void) { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { thisWorld[i][j]= NO_DATA; } } } //--------------------------------------------------------------------- reset void reset (void) { // initialize everything... for (int i = 0; i < 25; i++) { //agent[i].strategy = NO_DATA; agent[i].score = 0; agent[i].lastChoice = NO_DATA; agent[i].nextToLastChoice = NO_DATA; for (int j = 0; j < 25; j++) { agent[i].othersLastChoice[j] = NO_DATA; agent[i].othersNextToLastChoice[j] = NO_DATA; } shape[i]->Pen->Color = clBlack; shape[i]->Hint = IntToStr(i) + " " + Form1->ListBoxNames->Items->Strings[i] + " " + IntToStr(agent[i].score); } Form1->Chart1->Series[1]->Clear(); Form1->Chart1->Series[2]->Clear(); Form1->Chart1->Series[3]->Clear(); Form1->Chart1->Series[4]->Clear(); Form1->Chart1->Series[5]->Clear(); Form1->Chart1->Series[6]->Clear(); Form1->Chart1->Series[7]->Clear(); agentsAreSet = false; nextAgent = 0; Form1->EditNextAgent->Text = 0; totalScore = 0; Form1->EditTotalScore->Text = 0; iterations = 0; Form1->EditIterations->Text = 0; Application->ProcessMessages(); Form1->Color = clGray; // Green } //------------------------------------------------------------ set next agent void setNextAgent (int strategy) { if (nextAgent < 25) { switch (strategy) { case 0: { agent[nextAgent].strategy = ALWAYS_COOPERATE; agent[nextAgent].lastChoice = COOPERATE; agent[nextAgent].nextToLastChoice = COOPERATE; shape[nextAgent]->Pen->Color = clRed; break; } case 1: { agent[nextAgent].strategy = ALWAYS_DEFECT; agent[nextAgent].lastChoice = DEFECT; agent[nextAgent].nextToLastChoice = DEFECT; shape[nextAgent]->Pen->Color = clBlue; break; } case 2: { agent[nextAgent].strategy = GRUDGER; agent[nextAgent].lastChoice = random(2); agent[nextAgent].nextToLastChoice = random(2); shape[nextAgent]->Pen->Color = clAqua; break; } case 3: { agent[nextAgent].strategy = RANDOM; agent[nextAgent].lastChoice = random(2); agent[nextAgent].nextToLastChoice = random(2); shape[nextAgent]->Pen->Color = clLime; break; } case 4: { agent[nextAgent].strategy = TIT_FOR_TAT; agent[nextAgent].lastChoice = random(2); agent[nextAgent].nextToLastChoice = random(2); shape[nextAgent]->Pen->Color = static_cast(0x0099FF); break; } case 5: { agent[nextAgent].strategy = TIT_FOR_TWO_TATS; agent[nextAgent].lastChoice = random(2); agent[nextAgent].nextToLastChoice = random(2); shape[nextAgent]->Pen->Color = clYellow; break; } case 6: { agent[nextAgent].strategy = KIN; agent[nextAgent].lastChoice = random(2); agent[nextAgent].nextToLastChoice = random(2); shape[nextAgent]->Pen->Color = clGreen; break; } } shape[nextAgent]->Brush->Color = static_cast(colorRamp(1500, agent[nextAgent].score)); nextAgent++; } Form1->EditNextAgent->Text = nextAgent; if (nextAgent == 25) { Form1->EditNextAgent->Text = "FULL"; agentsAreSet = true; } } //--------------------------------------------------------------- render grid void renderGrid (void) { Form1->Canvas->Pen->Color = clSkyBlue; for (east=0; east<11; east++) { Form1->Canvas->MoveTo(50 * east, 0); Form1->Canvas->LineTo(50 * east, 500); } for (south=0; south<11; south++) { Form1->Canvas->MoveTo(0, 50 * south); Form1->Canvas->LineTo(500, 50 * south); } } //--------------------------------------------------- order shapes at random void orderShapesAtRandom (void) { Form1->Refresh(); emptyWorld(); Form1->EditIterations->Text = iterations; for (int i = 0; i < 25; i++) { cellX = random(10); cellY = random(10); while (thisWorld[cellX][cellY] != NO_DATA) { cellX = random(10); cellY = random(10); } thisWorld[cellX][cellY] = i; shape[i]->Left = 50 * cellX + 1; shape[i]->Top = 50 * cellY + 1; } } //------------------------------------------------------- order shapes by tag void orderShapesByTag (void) { Form1->Refresh(); Form1->EditIterations->Text = iterations; for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { shape[i * 5 + j]->Left = 50 * j + 1; shape[i * 5 + j]->Top = 50 * i + 1; } } } //----------------------------------------------------- order shapes by score void orderShapesByScore (void) { Form1->Refresh(); Form1->EditIterations->Text = iterations; // Set up an array of tags and scores for (int i = 0; i < 25; i++) { rank[i].score = agent[i].score; rank[i].tag = i; } // Bubble sort that array for (int loop = 0; loop < 25; loop++) { for (int i = 0; i < 24; i++) { if (rank[i].score < rank[i+1].score) { // switch values of i and i + 1 score = rank[i].score; tag = rank[i].tag; rank[i].score = rank[i+1].score; rank[i].tag = rank[i+1].tag; rank[i+1].score = score; rank[i+1].tag = tag; } } } for (int i = 0; i < 25; i++) { agent[rank[i].tag].rank = i; } // Order by rank for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { shape[rank[i * 5 + j].tag]->Left = 50 * j + 1; shape[rank[i * 5 + j].tag]->Top = 50 * i + 1; } } } //-------------------------------------------------------------- color shapes void colorShapes (void) { for (int i = 0; i < 25; i++) { shape[i]->Pen->Color = static_cast(colorRamp(25, 25 - shape[i]->Tag)); shape[i]->Brush->Color = static_cast(colorRamp(25, shape[i]->Tag)); } } //----------------------------------------------------------- restore shapes void restoreShapes (void) { for (int i = 0; i < 25; i++) { shape[i]->Pen->Color = clBlack; shape[i]->Brush->Color = clWhite; shape[i]->Width = 49; shape[i]->Height = 49; shape[i]->Pen->Width = 10; shape[i]->Shape = stCircle; } } //------------------------------------------------------- Cooperate or Defect, i represents number game with this player int cooperateOrDefect (int who, int other, int i) { int choice; switch (agent[who].strategy) { case ALWAYS_COOPERATE: { choice = COOPERATE; break; } case ALWAYS_DEFECT: { choice = DEFECT; break; } case GRUDGER: { if (i == 1) choice = COOPERATE; else if (agent[other].lastChoice == COOPERATE && !agent[who].grudge[other]) choice = COOPERATE; else if (agent[other].lastChoice == COOPERATE || agent[who].grudge[other]) { agent[who].grudge[other]= true; choice = DEFECT; } break; } case RANDOM: { choice = random(2); break; } case TIT_FOR_TAT: { if (i==1 && agent[who].othersLastChoice[other] == NO_DATA) choice = COOPERATE; //always cooperate on first mtg, copy every other time else if (global == false) { // if local memory if (agent[other].lastChoice == DEFECT) choice = DEFECT; if (agent[other].lastChoice == COOPERATE) choice = COOPERATE; } else { // if global memory if (globalLastChoice[other] == DEFECT) choice = DEFECT; if (globalLastChoice[other] == COOPERATE) choice = COOPERATE; } break; } case TIT_FOR_TWO_TATS: { if (i <= 2 && agent[who].othersNextToLastChoice[other] == NO_DATA) choice = COOPERATE; // if local memory if (global == false) { if (agent[other].lastChoice == DEFECT && agent[other].nextToLastChoice == DEFECT) choice = DEFECT; else choice = COOPERATE; } else { // if global memory if (globalLastChoice[other] == DEFECT && globalNextToLastChoice[other] == DEFECT) choice = DEFECT; else choice = COOPERATE; } break; } case KIN: { if (agent[other].strategy == KIN) { choice = COOPERATE; } else choice = DEFECT; break; } } return choice; } //---------------------------------------------------------------- Next Frame void nextFrame (void) { thisAgent = random(25); thatAgent = random(25); while (thisAgent == thatAgent) { thatAgent = random(25); } if ((Form1->CheckBoxRender->Checked == true) && (Form1->Chart1->Visible == false)) { Form1->Refresh(); Form1->Canvas->Pen->Width = 2; Form1->Canvas->Pen->Color = clBlack; Form1->Canvas->MoveTo(shape[thisAgent]-> Left + 25, shape[thisAgent]->Top + 25); Form1->Canvas->LineTo(shape[thatAgent]-> Left + 25, shape[thatAgent]->Top + 25); Form1->Canvas->Pen->Width = 1; Form1->Canvas->Pen->Color = clSkyBlue; } for (int i = 1; i <= shots; i ++) { thisAgentsChoice = cooperateOrDefect(thisAgent, thatAgent, i); thatAgentsChoice = cooperateOrDefect(thatAgent, thisAgent, i); if (thisAgentsChoice == COOPERATE && thatAgentsChoice == COOPERATE) { agent[thisAgent].score += 3; agent[thatAgent].score += 3; } if (thisAgentsChoice == COOPERATE && thatAgentsChoice == DEFECT) { agent[thisAgent].score += 0; agent[thatAgent].score += 5; } if (thisAgentsChoice == DEFECT && thatAgentsChoice == COOPERATE) { agent[thisAgent].score += 5; agent[thatAgent].score += 0; } if (thisAgentsChoice == DEFECT && thatAgentsChoice == DEFECT) { agent[thisAgent].score += 1; agent[thatAgent].score += 1; } // This Agent's Local Memory agent[thisAgent].nextToLastChoice = agent[thisAgent].lastChoice; agent[thisAgent].lastChoice = thisAgentsChoice; agent[thisAgent].othersNextToLastChoice[thatAgent] = agent[thisAgent].othersLastChoice[thatAgent]; agent[thisAgent].othersLastChoice[thatAgent] = thatAgentsChoice; lastThisAgent = thisAgent; // That Agent's Local Memory agent[thatAgent].nextToLastChoice = agent[thatAgent].lastChoice; agent[thatAgent].lastChoice = thatAgentsChoice; agent[thatAgent].othersNextToLastChoice[thisAgent] = agent[thatAgent].othersLastChoice[thisAgent]; agent[thatAgent].othersLastChoice[thisAgent] = thisAgentsChoice; lastThatAgent = thatAgent; // Global Memory globalNextToLastChoice[thisAgent] = globalLastChoice[thisAgent]; globalLastChoice[thisAgent] = thisAgentsChoice; globalNextToLastChoice[thatAgent] = globalLastChoice[thatAgent]; globalLastChoice[thatAgent] = thatAgentsChoice; if (Form1->CheckBoxRender->Checked == true && !(Form1->Chart1->Visible)) { shape[thisAgent]->Hint = IntToStr(thisAgent) + " " + Form1->ListBoxNames->Items->Strings[thisAgent] + " " + Form1->ListBoxStrategies->Items->Strings[agent[thisAgent].strategy] + " " + IntToStr(agent[thisAgent].score); shape[thatAgent]->Hint = IntToStr(thatAgent) + " " + Form1->ListBoxNames->Items->Strings[thatAgent] + " " + Form1->ListBoxStrategies->Items->Strings[agent[thatAgent].strategy] + " " + IntToStr(agent[thatAgent].score); maxScore = 0; minScore = 1000000; for (int i = 0; i < 25; i++) { if (agent[i].score > maxScore) maxScore = agent[i].score; if (agent[i].score < minScore) minScore = agent[i].score; } range = maxScore - minScore + 2; for (int i = 0; i < 25; i++) { shape[i]->Brush->Color = static_cast (colorRamp(range, agent[i].score - minScore)); } } } iterations ++; Form1->EditIterations->Text=iterations; Application->ProcessMessages(); } //------------------------------------------- Evolve: Randomize Worst Player void randomizeWorstPlayer (void) { orderShapesByScore(); if (Form1->CheckBoxHomo->Checked) { int randomPlayer = random(25); strategy = agent[randomPlayer].strategy; } else strategy = random(7); switch (strategy) { case 0: { agent[rank[24].tag].strategy = ALWAYS_COOPERATE; agent[rank[24].tag].lastChoice = COOPERATE; agent[rank[24].tag].nextToLastChoice = COOPERATE; shape[rank[24].tag]->Pen->Color = clRed; break; } case 1: { agent[rank[24].tag].strategy = ALWAYS_DEFECT; agent[rank[24].tag].lastChoice = DEFECT; agent[rank[24].tag].nextToLastChoice = DEFECT; shape[rank[24].tag]->Pen->Color = clBlue; break; } case 2: { agent[rank[24].tag].strategy = GRUDGER; agent[rank[24].tag].lastChoice = random(2); agent[rank[24].tag].nextToLastChoice = random(2); shape[rank[24].tag]->Pen->Color = clAqua; break; } case 3: { agent[rank[24].tag].strategy = RANDOM; agent[rank[24].tag].lastChoice = random(2); agent[rank[24].tag].nextToLastChoice = random(2); shape[rank[24].tag]->Pen->Color = clLime; break; } case 4: { agent[rank[24].tag].strategy = TIT_FOR_TAT; agent[rank[24].tag].lastChoice = random(2); agent[rank[24].tag].nextToLastChoice = random(2); shape[rank[24].tag]->Pen->Color = static_cast(0x0099FF); break; } case 5: { agent[rank[24].tag].strategy = TIT_FOR_TWO_TATS; agent[rank[24].tag].lastChoice = random(2); agent[rank[24].tag].nextToLastChoice = random(2); shape[rank[24].tag]->Pen->Color = clYellow; break; } case 6: { agent[rank[24].tag].strategy = KIN; agent[rank[24].tag].lastChoice = random(2); agent[rank[24].tag].nextToLastChoice = random(2); shape[rank[24].tag]->Pen->Color = clGreen; break; } } } //-------------------------------------------- Devolve: Randomize Best Player void randomizeBestPlayer (void) { orderShapesByScore(); if (Form1->CheckBoxHomo->Checked) { int randomPlayer = random(25); strategy = agent[randomPlayer].strategy; } else strategy = random(7); switch (strategy) { case 0: { agent[rank[0].tag].strategy = ALWAYS_COOPERATE; agent[rank[0].tag].lastChoice = COOPERATE; agent[rank[0].tag].nextToLastChoice = COOPERATE; shape[rank[0].tag]->Pen->Color = clRed; break; } case 1: { agent[rank[0].tag].strategy = ALWAYS_DEFECT; agent[rank[0].tag].lastChoice = DEFECT; agent[rank[0].tag].nextToLastChoice = DEFECT; shape[rank[0].tag]->Pen->Color = clBlue; break; } case 2: { agent[rank[0].tag].strategy = GRUDGER; agent[rank[0].tag].lastChoice = random(2); agent[rank[0].tag].nextToLastChoice = random(2); shape[rank[0].tag]->Pen->Color = clAqua; break; } case 3: { agent[rank[0].tag].strategy = RANDOM; agent[rank[0].tag].lastChoice = random(2); agent[rank[0].tag].nextToLastChoice = random(2); shape[rank[0].tag]->Pen->Color = clLime; break; } case 4: { agent[rank[0].tag].strategy = TIT_FOR_TAT; agent[rank[0].tag].lastChoice = random(2); agent[rank[0].tag].nextToLastChoice = random(2); shape[rank[0].tag]->Pen->Color = static_cast(0x0099FF); break; } case 5: { agent[rank[0].tag].strategy = TIT_FOR_TWO_TATS; agent[rank[0].tag].lastChoice = random(2); agent[rank[0].tag].nextToLastChoice = random(2); shape[rank[0].tag]->Pen->Color = clYellow; break; } case 6: { agent[rank[0].tag].strategy = KIN; agent[rank[0].tag].lastChoice = random(2); agent[rank[0].tag].nextToLastChoice = random(2); shape[rank[0].tag]->Pen->Color = clGreen; break; } } } //---------------------------------------------------------------------- Step void step (void) { nextFrame(); Application->ProcessMessages(); //....................................... Evolve or Devolve if (Form1->CheckBoxEvolve->Checked == true) { if (iterations % evInterval == 0) { randomizeWorstPlayer(); shape[24]->Hint = IntToStr(24) + " " + Form1->ListBoxNames->Items->Strings[24] + " " + Form1->ListBoxStrategies->Items-> Strings[agent[24].strategy] + " " + IntToStr(agent[24].score); if (Form1->CheckBoxSound->Checked) Beep(3000, 5); Form1->Color = 0xCCFFCC; // Green } } if (Form1->CheckBoxDevolve->Checked == true) { if (iterations % evInterval == 0) { randomizeBestPlayer(); shape[0]->Hint = IntToStr(0) + " " + Form1->ListBoxNames->Items->Strings[0] + " " + Form1->ListBoxStrategies->Items-> Strings[agent[0].strategy] + " " + IntToStr(agent[0].score); if (Form1->CheckBoxSound->Checked) Beep(2000, 5); Form1->Color = 0xFFCCFF; // Pink } } if ((Form1->Graph->Checked == true && (Form1->CheckBoxDevolve ->Checked == true || Form1->CheckBoxEvolve->Checked == true)) && iterations % graphInterval == 0) { //find number of each type int coop = 0, def = 0, grudges = 0, random = 0, tft = 0, tf2t =0, kin = 0; for (int i = 0; i < 25; i++) { if (agent [i].strategy == ALWAYS_COOPERATE) { coop ++; } else if (agent [i].strategy == ALWAYS_DEFECT) { def ++; } else if (agent [i].strategy == GRUDGER) { grudges ++; } else if (agent [i].strategy == RANDOM) { random ++; } else if (agent [i].strategy == TIT_FOR_TAT) { tft ++; } else if (agent [i].strategy == TIT_FOR_TWO_TATS) { tf2t ++; } else if (agent [i].strategy == KIN) { kin ++; } } Form1->Chart1->Series[1]->AddXY(iterations, coop, "", clRed); Form1->Chart1->Series[2]->AddXY(iterations, def, "", clBlue); Form1->Chart1->Series[3]->AddXY(iterations, grudges, "", clAqua); Form1->Chart1->Series[4]->AddXY(iterations, random, "", clLime); Form1->Chart1->Series[5]->AddXY(iterations, tft, "", static_cast(0x0099FF)); Form1->Chart1->Series[6]->AddXY(iterations, tf2t, "", clYellow); Form1->Chart1->Series[7]->AddXY(iterations, kin, "", clGreen); Form1->Chart1->Update(); } } //----------------------------------------------------------------------- Run void run (void) { // select local or global memory if (Form1->RadioGroupMemory->ItemIndex == 1) global = true; else global = false; stop = false; // figure out when to stop switch (Form1->RadioGroupStopAt->ItemIndex) { case 0: stopAt = 1000; break; case 1: stopAt = 2000; break; case 2: stopAt = 5000; break; case 3: stopAt = 10000; break; case 4: stopAt = 20000; break; case 5: stopAt = 50000; break; case 6: stopAt = 100000; break; case 7: stopAt = 200000; break; case 8: stopAt = 500000; break; } Form1->Refresh(); while (agentsAreSet && stop == false && iterations < stopAt) { step(); } // calculate statistics for (int i = 0; i < 25; i++) { totalScore += agent[i].score; } Form1->EditTotalScore->Text = totalScore; Form1->CheckBoxRender->Checked = true; nextFrame(); } //=========================================================================== // EVENT HANDLERS //=========================================================================== //------------------------------------------------------------ On Form Create void __fastcall TForm1::FormCreate(TObject *Sender) { randomize(); Form1->Shape2->Pen->Color = static_cast(0x0099FF); // defines an array of shapes with properties and events for (int i = 0; i < 25; i++) { shape[i] = new TShape(this); shape[i]->Parent = Form1; shape[i]->Visible = true; shape[i]->OnMouseDown = ShapeMouseDown; shape[i]->OnMouseMove = ShapeMouseMove; shape[i]->Height = 49; shape[i]->Width = 49; shape[i]->Shape = stCircle; shape[i]->Tag = i; shape[i]->Hint = IntToStr(i) + " " + ListBoxNames->Items->Strings[i] + " " + IntToStr(agent[i].score); shape[i]->ShowHint = true; shape[i]->Pen->Width = 10; } reset(); emptyWorld(); orderShapesAtRandom(); } //------------------------------------------------------------- On Form Paint // Redraws the grid anytime the windows is obscured and then uncovered void __fastcall TForm1::FormPaint(TObject *Sender) { renderGrid(); } //------------------------------------------------------- On Shape Mouse Down // An exception to the rule which says "Let Borland write event handlers." // This one you must type in yourself in addition to a reference to it // in Unit1.h (look at the source code in that unit). void __fastcall TForm1::ShapeMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { TShape *shape = dynamic_cast(Sender); // Captures the index number of the shape that was clicked chosenShape = shape->Tag; // Remembers that an shape was chosen aShapeWasChosen = true; } //------------------------------------------------------- On Shape Mouse Move // An exception to the rule which says "Let Borland write event handlers." // This one you must type in yourself in addition to a reference to it // in Unit1.h (look at the source code in that unit). void __fastcall TForm1::ShapeMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { int s; TShape *shape = dynamic_cast(Sender); // When the mouse moves over an agent // its index number is displayed EditTag->Text = shape->Tag; // the name associated with that agent is displayed EditName->Text = ListBoxNames->Items->Strings[shape->Tag]; // the score associated with that agent is displayed tag = shape->Tag; EditScore->Text = agent[tag].score; EditRank->Text = agent[tag].rank; if (agentsAreSet) { EditStrategy->Text = Form1->ListBoxStrategies->Items->Strings[agent[tag].strategy]; } } //-------------------------------------------------------- On Form Mouse Down void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { // Calculates the array indeces from the position of the mouse chosenCellX = X / 50; chosenCellY = Y / 50; // Only if the previous click was on an shape if (aShapeWasChosen) { // recalls the position of the shape that was previously clicked fromCellX = shape[chosenShape]->Left / 50; fromCellY = shape[chosenShape]->Top / 50; // moves the shape to the position that was just clicked shape[chosenShape]->Left = chosenCellX * 50 + 1; shape[chosenShape]->Top = chosenCellY * 50 + 1; // moves the agent in the array thisWorld[fromCellX][fromCellY] = 99; thisWorld[chosenCellX][chosenCellY] = chosenShape; // Another shape must be clicked before this will work again aShapeWasChosen = false; } } //-------------------------------------------------------- On Form Mouse Move // Calculates the array indices from the position of the mouse void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { // Captures the indices of the cell of the array cellX = X / 50; cellY = Y / 50; // Displays the indices of the cell of the array EditX->Text = cellX; EditY->Text = cellY; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ CREATE POPULATION PANEL //------------------------------------------------------ Set Cooperate Button void __fastcall TForm1::ButtonCooperateClick(TObject *Sender) { setNextAgent(ALWAYS_COOPERATE); } //--------------------------------------------------------- Set Random Button void __fastcall TForm1::ButtonRandomClick(TObject *Sender) { setNextAgent(RANDOM); } //--------------------------------------------------------- Set Defect Button void __fastcall TForm1::ButtonDefectClick(TObject *Sender) { setNextAgent(ALWAYS_DEFECT); } //---------------------------------------------------- Set Tit-for-Tat Button void __fastcall TForm1::ButtonTFTClick(TObject *Sender) { setNextAgent(TIT_FOR_TAT); } //------------------------------------------------------ Set GRUDGER Button void __fastcall TForm1::ButtonGrudgerClick(TObject *Sender) { setNextAgent(GRUDGER); } //----------------------------------------------- Set Tit-for-Two-Tats Button void __fastcall TForm1::ButtonTTTClick(TObject *Sender) { setNextAgent(TIT_FOR_TWO_TATS); } //------------------------------------------------------ Set One Each Button void __fastcall TForm1::Button1EachClick(TObject *Sender) { for (int i = 0; i < 4; i++) { setNextAgent(ALWAYS_COOPERATE); setNextAgent(RANDOM); setNextAgent(ALWAYS_DEFECT); setNextAgent(TIT_FOR_TAT); setNextAgent(GRUDGER); setNextAgent(TIT_FOR_TWO_TATS); setNextAgent (KIN); } setNextAgent(ALWAYS_DEFECT); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CONTROL PANEL //---------------------------------------------------------------- Run Button void __fastcall TForm1::ButtonRunClick(TObject *Sender) { run(); } //--------------------------------------------------------------- Step Button void __fastcall TForm1::ButtonStepClick(TObject *Sender) { stop = true; if (agentsAreSet) { step(); } } //--------------------------------------------------------------- Stop Button Order at Random Button void __fastcall TForm1::ButtonOrderAtRandomClick(TObject *Sender) { orderShapesAtRandom(); } //------------------------------------------------------- Order by Tag Button void __fastcall TForm1::ButtonOrderByTagClick(TObject *Sender) { orderShapesByTag(); } //----------------------------------------------------- Order by Score Button void __fastcall TForm1::ButtonOrderByScoreClick(TObject *Sender) { orderShapesByScore(); } //-------------------------------------------------------------- Reset Button void __fastcall TForm1::ButtonResetClick(TObject *Sender) { reset(); restoreShapes(); stop = false; } //--------------------------------------------------------------------------- void __fastcall TForm1::ShotsEditExit(TObject *Sender) { shots = StrToInt(Form1->ShotsEdit->Text); } //--------------------------------------------------------------------------- void __fastcall TForm1::KinClick(TObject *Sender) { setNextAgent (KIN); } //--------------------------------------------------------------------------- void __fastcall TForm1::GraphClick(TObject *Sender) { Form1->Chart1->Visible = Form1->Graph->Checked && (Form1->CheckBoxDevolve->Checked || Form1->CheckBoxEvolve->Checked); if (Form1->Chart1->Visible) { orderShapesByScore(); } Form1->CheckBoxRender->Checked = false; } //--------------------------------------------------------------------------- void __fastcall TForm1::ShotsEditChange(TObject *Sender) { shots = (Form1->ShotsEdit->Text).ToInt(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Edit1Change(TObject *Sender) { graphInterval = (Form1->Edit1->Text).ToInt(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Edit2Change(TObject *Sender) { evInterval = (Form1->Edit2->Text).ToInt(); } //---------------------------------------------------------------------------