// Projectdwator // Dave's Wator World - Births // D. Niebuhr -- 10/14/2001 //--------------------------------------------------------------------------- #include #include #include #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; // ----------------------------------- initialize bool stop=false; bool step=false; bool pause=false; bool slow=false; int ocean[80][80][2]; // first two subscripts are x,y coord.; third is: 0 = type // 1 = age (birth state) // 2 = stomach contents int e, s, east, south, emove, smove; int i,j,k,l,m,n; int maxSize=80; int iterations=0; int fishBegPop=1300; int sharkBegPop=320; int sharkType; int fishGestation=8; int sharkGestation=16; int fishPop, sharkPop; void countFishSharks(void); void renderOcean(void); // ------------ cell values: 0 dead cell (i.e., just water) (black) // 1 shark with no fish in stomach (red) // 2 " " 1 " " " (yellow) // 3 " " 2 " " " " // 4 " " 3 " " " " // 5 " " 4 " " "(i.e., full)(blue) // 6 fish (green) // // --------------- program logic // each iteration is a two step process: // first, the 'fish' move at random to a neighboring cell (unless it // already contains a fish -- then they stay put); if it's occupied // by a shark, the shark 'moves' into the fish's cell and eats // (unless the shark is full, in which case, the shark and the fish // stay put.) // secondly, the sharks then 'digest' one of the fish in their stomachs; // (actually, only about 1/4 of them do -- see the DIGEST routine) // if the stomach is empty (cell value=1), the shark automatically // 'dies' and becomes empty water (cell value=0.) // // note that the 'moves' don't occur simultaneously ... they start from the // upper left of the 'ocean' // -------------------------------- // -------------------------------- make all cells in ocean EMPTY OCEAN void makeAllCellsOcean (void) { for (east=0; eastCanvas->Pen->Color=clBlack; Form1->Canvas->Brush->Color=clBlack; Form1->Canvas->Rectangle (east*5+25,south*5+25,east*5+5+25,south*5+5+25); } } iterations=0; Form1->EditIterations->Text=iterations; } // ---------------------------------- place fish at RANDOM in ocean // set cell values to 6 for each fish void makeCellsFish (void) { for (i=1; i<=fishBegPop; i++) { east=random(maxSize); south=random(maxSize); ocean[east][south][0]=6; // randomly make them pregnant Randomize(); ocean[east][south][1] = random(fishGestation); // color the square Form1->Canvas->Pen->Color=clGreen; Form1->Canvas->Brush->Color=clGreen; Form1->Canvas->Rectangle ( east*5+25,south*5+25,east*5+5+25,south*5+5+25); } iterations=0; Form1->EditIterations->Text=iterations; countFishSharks(); } // ------------------------ place sharks at RANDOM in ocean // set cell values to 1,2,3,4 or 5 to indicate contents of stomach; // to keep it simple, sharks are distributed evenly across the five // stomach choices void makeCellsSharks(void) { for (i=1; i<=sharkBegPop; i++) { east=random(maxSize); south=random(maxSize); sharkType=random(5); ocean[east][south][0]=sharkType; // randomly make them pregnant Randomize(); ocean[east][south][1] = random(sharkGestation); // color the square switch (sharkType) { case 0: // a starving shark ocean[east][south][0]=1; Form1->Canvas->Pen->Color=clRed; Form1->Canvas->Brush->Color=clRed; Form1->Canvas->Rectangle (east*5+25,south*5+25,east*5+5+25,south*5+5+25); break; // a not full shark case 1: case 2: case 3: ocean[east][south][0]=3; // ? can i use case as a value ?? (also case+?) Form1->Canvas->Pen->Color=clYellow; Form1->Canvas->Brush->Color=clYellow; Form1->Canvas->Rectangle ( east*5+25,south*5+25,east*5+5+25,south*5+5+25); break; // a full shark case 4: ocean[east][south][0]=5; Form1->Canvas->Pen->Color=clBlue; Form1->Canvas->Brush->Color=clBlue; Form1->Canvas->Rectangle ( east*5+25,south*5+25,east*5+5+25,south*5+5+25); break; } } iterations=0; Form1->EditIterations->Text=iterations; countFishSharks(); } //================================= count fish and sharks void countFishSharks(void) { fishPop=0; sharkPop=0; float pctSharks; for (east=0; east0) { sharkPop++; // increment age (gestation) of sharks ocean[east][south][1]++; } } } Form1->EditFishPop->Text = fishPop; Form1->EditSharkPop->Text = sharkPop; pctSharks = 100*sharkPop/(fishPop+sharkPop+1); Form1->EditPctSharks->Text = pctSharks; } // ================================== MOVE the fish and FEED the sharks // ================================== BIRTH the fish if empty cell void moveAndFeed() { for (east=0; east=fishGestation) { ocean[east][south][1]=0; ocean[emove][smove][1]=-1; } else ocean[east][south][0]=0; ocean[emove][smove][0]=6; // increment age (gestation) of moved fish ocean[emove][smove][1]++; } else if (ocean[emove][smove][0]<6) // we've found a shark { switch (ocean[emove][smove][0]) { case 1: case 2: case 3: case 4: // she's hungry so she moves to the fish's cell and eats // it; if she's 'due' she gives birth // and the newborn stays in the old cell ocean[east][south][0]=ocean[emove][smove][0]+1; ocean[emove][smove][0]=0; ocean[east][south][1]=ocean[emove][smove][1]; if (ocean[emove][smove][1]>=sharkGestation) { ocean[emove][smove][0]=1; ocean[emove][smove][1]=1; // but the birthing costs her one fish ocean[east][south][0]--; } break; case 5: // she's full so no change to either cell // skip birthing for now --- add later ********* break; } } } } } } // ======================= sharks DIGEST a fish // // In order to keep sharks from dying out too soon, I've added a // random element that results in only 1/4 of them digesting // a fish each time this routine is called void sharksDigest() { for (east=0; east0) continue; else if (ocean[east][south][0]>0 && ocean[east][south][0]<6) { ocean[east][south][0]=ocean[east][south][0]-1; // if new value is 0, shark has starved } } } } // ========================= Hungry sharks SEARCH for fish void sharksSearch() { for (east=0; east0 && ocean[east][south][0]<5) { int move=random(9); // // pick at random one of the nine possible cell moves for the shark // emove and smove are the coordinates (subscripts) of the target cell switch (move) { case 0: // stay put emove=east; smove=south; break; case 1: // move NW emove=east-1; smove=south-1; break; case 2: // move W emove=east-1; smove=south; break; case 3: // move SW emove=east-1; smove=south+1; break; case 4: //move N emove=east; smove=south-1; break; case 5: // move S emove=east; smove=south+1; break; case 6: // move NE emove=east+1; smove=south-1; break; case 7: // move E emove=east+1; smove=south; break; case 8: // move SE emove=east+1; smove=south+1; break; } // // if the target cell for the move is 'outside' the ocean (i.e., // beyond its borders), we wrap it around a torus by setting the // subscripts to locations on the adjoining border. if (emove<0) emove=maxSize-1; if (emove==maxSize) emove=0; if (smove<0) smove=maxSize-1; if (smove==maxSize) smove=0; // // move if cell is empty if (ocean[emove][smove][0]==0) { ocean[emove][smove][0]=ocean[east][south][0]; ocean[east][south][0]=0; } // // check for fish if cell not empty else if (ocean[emove][smove][0]==6) // we've found a fish; move and eat it { ocean[emove][smove][0]=ocean[east][south][0]+1; ocean[east][south][0]=0; } // otherwise, cell contains a shark and we can leave it alone } } } } // --------------------------- render ocean void renderOcean() { for (east=0; eastCanvas->Pen->Color=clBlack; Form1->Canvas->Brush->Color=clBlack; Form1->Canvas->Rectangle (east*5+25,south*5+25,east*5+5+25,south*5+5+25); break; case 1: Form1->Canvas->Pen->Color=clRed; Form1->Canvas->Brush->Color=clRed; Form1->Canvas->Rectangle ( east*5+25,south*5+25,east*5+5+25,south*5+5+25); break; case 2: case 3: case 4: Form1->Canvas->Pen->Color=clYellow; Form1->Canvas->Brush->Color=clYellow; Form1->Canvas->Rectangle (east*5+25,south*5+25,east*5+5+25,south*5+5+25); break; case 5: Form1->Canvas->Pen->Color=clBlue; Form1->Canvas->Brush->Color=clBlue; Form1->Canvas->Rectangle (east*5+25,south*5+25,east*5+5+25,south*5+5+25); break; case 6: Form1->Canvas->Pen->Color=RGB(0,155,0); Form1->Canvas->Brush->Color=RGB(0,155,0); Form1->Canvas->Rectangle (east*5+25,south*5+25,east*5+5+25,south*5+5+25); break; } } } Application->ProcessMessages(); } // ----------------------------- run Dave's Wator World void run(void) { stop=false; while (stop==false) { while (pause==true) Application->ProcessMessages(); if (step==true) { pause=true; step=false; } if (slow==true) { for (int j=1; j<6000000; j++) int j1=j/j; } moveAndFeed(); sharksSearch(); sharksDigest(); renderOcean(); countFishSharks(); iterations++; Form1->EditIterations->Text=iterations; } } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonPlaceFishClick(TObject *Sender) { makeCellsFish(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonRunClick(TObject *Sender) { slow=false; step=false; pause=false; run(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonPlaceSharksClick(TObject *Sender) { makeCellsSharks(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonStopClick(TObject *Sender) { stop=true; pause=false; step=false; } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonPauseClick(TObject *Sender) { // pause button alternates as resume button pause=!pause; } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonStepClick(TObject *Sender) { step=true; pause=false; run(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonCountClick(TObject *Sender) { countFishSharks(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonResetClick(TObject *Sender) { makeAllCellsOcean(); step=false; stop=true; pause=false; Form1->EditIterations->Text=0; Form1->EditFishPop->Text = 0; Form1->EditSharkPop->Text = 0; } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarFishBegPopChange(TObject *Sender) { fishBegPop=Form1->TrackBarFishBegPop->Position; Form1->EditFishBegPop->Text=fishBegPop; Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarSharkBegPopChange(TObject *Sender) { sharkBegPop=Form1->TrackBarSharkBegPop->Position; Form1->EditSharkBegPop->Text=sharkBegPop; Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonRunSlowClick(TObject *Sender) { slow=true; step=false; pause=false; run(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonInstructionsClick(TObject *Sender) { bool view=ScrollBox1->Visible; ScrollBox1->Visible=!view; } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarFishGestationChange(TObject *Sender) { fishGestation=Form1->TrackBarFishGestation->Position; Form1->EditFishGestation->Text=fishGestation; Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarSharkGestationChange(TObject *Sender) { sharkGestation=Form1->TrackBarSharkGestation->Position; Form1->EditSharkGestation->Text=sharkGestation; Application->ProcessMessages(); } //---------------------------------------------------------------------------