//=========================================================================== // SHELLING'S SEGREGATION - WINDOW ONE // A "simple" introduction to multiagent simulation programming // 5 April 2004 //=========================================================================== #include #pragma hdrstop #include "Unit1.h" #include "Unit2.h" #include "Unit3.h" #include "time.h" // you must type this in to enable randomize() //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------- your program begins here //=========================================================================== // VARIABLES //=========================================================================== int world[400][400]; int e, s; int fromE, fromS; int toE, toS; int rawE, rawS; int validE, validS; int ego; int neighbors[4]; int folksLikeEgo; int rollDice; int moves; int opportunities; bool stop = true; //=========================================================================== // FUNCTIONS //=========================================================================== //---------------------------------------------------------------- render all void renderAll (void) { for (int e = 0; e < 400; e++) { for (int s = 0; s < 400; s++) { switch (world[e][s]) { case 0: { // empty Form1->Canvas->Pixels[e][s]=clBlack; break; } case 1: { // cyan folk Form1->Canvas->Pixels[e][s]=clAqua; break; } case 2: { // magenta folk Form1->Canvas->Pixels[e][s]=clFuchsia; break; } case 3: { // yellow folk Form1->Canvas->Pixels[e][s]=clYellow; break; } } } } } //---------------------------------------------------------------------- fill void fill (void) { moves = 0; opportunities = 0; Form1->EditMoves->Text = moves; Form1->EditOpportunities->Text = opportunities; for (int e = 0; e < 400; e++) { for (int s = 0; s < 400; s++) { rollDice = random(4); switch (rollDice) { case 0: { // empty Form1->Canvas->Pixels[e][s]=clBlack; world[e][s] = 0; break; } case 1: { // cyan folk Form1->Canvas->Pixels[e][s]=clAqua; world[e][s] = 1; break; } case 2: { // magenta folk Form1->Canvas->Pixels[e][s]=clFuchsia; world[e][s] = 2; break; } case 3: { // yellow folk Form1->Canvas->Pixels[e][s]=clYellow; world[e][s] = 3; break; } } } } } //----------------------------------------------------------- count neighbors void countNeighbors (void) { neighbors[0] = 0; // set empty neighbors to zero neighbors[1] = 0; // set cyan neighbors to zero neighbors[2] = 0; // set magenta neighbors to zero neighbors[3] = 0; // set yellow neighbors to zero // check out the neighborhood for (rawE = toE - 1; rawE <= toE + 1; rawE++) { validE = rawE; if (rawE < 0) validE = 399; // don't go out of bounds if (rawE > 399) validE = 0; // don't go out of bounds for (rawS = toS - 1; rawS <= toS + 1; rawS++) { validS = rawS; if (rawS < 0) validS = 399; // don't go out of bounds if (rawS > 399) validS = 0; // don't go out of bounds // ignore ego's cell if (!(validE == toE && validS == toS)) { neighbors[world[validE][validS]]++; } } } } //---------------------------------------------------------------------- move void move (void) { // update the visualization Form1->Canvas->Pixels[fromE][fromS] = clBlack; // black if (ego == 1) Form1->Canvas->Pixels[toE][toS] = clAqua; // cyan if (ego == 2) Form1->Canvas->Pixels[toE][toS] = clFuchsia; // magenta if (ego == 3) Form1->Canvas->Pixels[toE][toS] = clYellow; // yellow // update the array world[fromE][fromS] = 0; world[toE][toS] = ego; moves++; Form1->EditMoves->Text = moves; } //----------------------------------------------------- choose to move or not void chooseToMoveOrNot (void) { ego = world[fromE][fromS]; // here the preference is only for folksLikeEgo if (neighbors[ego] >= folksLikeEgo) move(); // but you can replace this with any criteria you like } //----------------------------------------------------------------- next step void nextStep (void) { opportunities++; Form1->EditOpportunities->Text = opportunities; fromE = random(400); // pick a random place to move FROM fromS = random(400); toE = random(400); // pick a random place to move TO toS = random(400); // if FROM is not empty and TO is empty if (world[fromE][fromS]!=0 && world[toE][toS]==0) { countNeighbors(); chooseToMoveOrNot(); } } //=========================================================================== // EVENT HANDLERS //=========================================================================== //------------------------------------------------------------- on Form Paint void __fastcall TForm1::FormPaint(TObject *Sender) { renderAll(); } //--------------------------------------------------------------- fill button void __fastcall TForm1::ButtonFillClick(TObject *Sender) { fill(); } //---------------------------------------------------------------- run button void __fastcall TForm1::ButtonRunClick(TObject *Sender) { stop = false; while (stop == false) { nextStep(); Application->ProcessMessages(); } } //--------------------------------------------------------------- step button void __fastcall TForm1::ButtonStepClick(TObject *Sender) { stop = true; nextStep(); } //--------------------------------------------------------------- stop button void __fastcall TForm1::ButtonStopClick(TObject *Sender) { stop = !stop; } //------------------------------------------------ when the window is created void __fastcall TForm1::FormCreate(TObject *Sender) { randomize(); // randomly initializes the random number generator } //----------------------------------------------------- FolksLikeEgo trackbar void __fastcall TForm1::TrackBarFolksLikeEgoChange(TObject *Sender) { folksLikeEgo = TrackBarFolksLikeEgo->Position; Form1->EditFolksLikeEgo->Text = folksLikeEgo; } //---------------------------------------------------------- that's all folks