home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sunny 1,000 Collection
/
SUNNY1000.iso
/
Files
/
Dos
/
Boardak
/
G_O_LIFE.ZIP
/
LIFE.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-11-07
|
18KB
|
391 lines
(**************************************************************************\
| |
| Scott Dudley This program simulates life on a 20x20 grid. Life on |
| CS 1053 the grid obeys the following rules: |
| 9-24-94 a) a being stays alive only with two or three neigbors |
| Program 3 b) a new Begin is born with three neigbors |
| c) life cycles through 10 generations or death, wich- |
| ever happens first. |
| |
\**************************************************************************)
(**************************************************************************\
| |
| Extra stuff 1) Create, save, and load various data. |
| 2) Graphic interface. |
| 3) Setup the number of generations. 1 to 20 |
| 4) Toggle weather or not the program halts when |
| all the being are dead. |
| 5) It's user friendly also! |
| |
\**************************************************************************)
Program CSProg3; {Computer Science Program 3}
Uses Printer,Crt,Graph,Aids; {Aids is my graphic aid unit}
Type
LifeArray=Array[0..21,0..21] of boolean;
FileName1=String[12]; {My 20x20 grid is expanded in each }
FileName2=String[8]; {direction. This make it easy to count }
{neighbors. All I have to do is make }
{sure the outter area stays empty. }
{I also work with file names that can }
{only be 12 characters long, four of }
{wich must be the extention ".DAT". }
Var
Prtr,Death :Boolean; {My toggles. }
GenLoop :Word; {The number of generation it runs. }
MainGrid :LifeArray; {The main grid. }
Gr,Gd :Integer; {These integers are used in opening }
{graphics mode. }
{$I-}
Procedure ChkPrt; {Checks for printer and toggles Prtr. }
Begin {If the printer is toggled on, this will}
If Prtr then Prtr:=false else {also toggle it off. }
Begin
WriteLn(Lst,' ');
If IOResult <> 0 then Prtr:=false else prtr:=true;
End;
End;
Function Neighbors(X,Y:Word):Word; {This counts the number of neighbors a }
Var {life form has. }
Total:Word;
Begin
Total:=0;
If (X>0) and (X<21) and (Y>0) and (Y<21) then
Begin
If MainGrid[X-1,Y-1] then Total:=Total+1;
If MainGrid[X+1,Y+1] then Total:=Total+1;
If MainGrid[X+1,Y-1] then Total:=Total+1;
If MainGrid[X-1,Y+1] then Total:=Total+1;
If MainGrid[X-1,Y] then Total:=Total+1;
If MainGrid[X,Y-1] then Total:=Total+1;
If MainGrid[X+1,Y] then Total:=Total+1;
If MainGrid[X,Y+1] then Total:=Total+1;
End;
Neighbors:=Total;
End;
Procedure Generate; {Everytime this procedure is called, }
Var {one generation passes. }
BufGrid :LifeArray;
Count1,Count2 :Integer;
Begin
For Count1:=0 to 21 do
For Count2:=0 to 21 do
BufGrid[count2,count1]:=false;
For Count1:=1 to 20 do {The fate of each being is filtered }
For Count2:=1 to 20 do {into BufGrid. }
Begin
If MainGrid[count2,count1] then
Begin
If (neighbors(count2,count1)=2) or (neighbors(count2,count1)=3) then
BufGrid[count2,count1]:=True;
End
else
Begin
If neighbors(count2,count1)=3 then
BufGrid[count2,count1]:=True;
End;
End;
MainGrid:=BufGrid; {The MainGrid is set to the BufGrid }
End;
Procedure Writefile(files:FileName1);
Var {This is the physical action of writing}
Data,Count1,Count2 :Word; {a file. Also contains error checking. }
DatFile :Text;
Begin
Assign(DatFile,Files);
rewrite(DatFile);
If IOResult=0 then {This loop only runs if there are no }
Begin {I/O errors. }
For Count1:=1 to 20 do {This loop writes my boolean array to a}
Begin {file with the same binary grid as your}
For Count2:=1 to 20 do {file, LIFE.DAT. }
Begin
If MainGrid[count2,count1] then Data:=1 else Data:=0;
Write(DatFile,Data);
Write(DatFile,' '); {The spaces and lines are to keep the }
End; {same standard format as you flile. }
WriteLn(DatFile);
End;
Close(DatFile);
TextColor(LightGreen);
WriteLn('File Saved. Press any key to continue');
End
else {If there was an error, ie. an invalid }
Begin {file name, the program doesn't attempt}
TextColor(Red); {to write a file. }
WriteLn('Error saveing file!!!!');
End;
End;
Procedure Readfile(files:FileName1);
Var {This procedure is very much like the }
Data,Count1,Count2 :Word; {WriteFile procedure. }
DatFile :Text;
Begin
Assign(DatFile,Files);
Reset(DatFile);
If IOResult=0 then {The same I/O checking. }
Begin
For Count1:=1 to 20 do {This loop reads a binary file and sets }
For Count2:=1 to 20 do {up the boolean grid. }
Begin
Read(DatFile,Data);
If Data=1 then MainGrid[count2,count1]:=true else
MainGrid[count2,count1]:=false;
End;
Close(DatFile);
TextColor(LightGreen);
WriteLn('File Loaded. Press any key to continue');
End
else
Begin
TextColor(Red);
WriteLn('Error loading file!!!!');
End;
End;
Procedure LoadFile; {This procedure is the user interface }
Var {for loading a file. }
Input :FileName2;
Begin
Closegraph; {It is much easier to enter a file name }
TextColor(green); {while in Text Mode. }
WriteLn('Enter the file to load. You do not need to include the file extention.');
Write('>');
TextColor(LightGreen);
ReadLn(Input);
Readfile(Input+'.dat'); {ReadFile is the procedure to actually }
pause; {load the file. }
initgraph(gr,gd,''); {Going back into GraphMode. }
End;
Procedure SaveFile; {This procedure is the user interface }
Var {for saveing a file. }
Input :FileName2;
Begin
Closegraph; {It is much easier to enter a file name }
TextColor(Cyan); {while in Text Mode. }
WriteLn('Name the file to save. You do not need to include the file extention.');
Write('>');
TextColor(LightCyan);
ReadLn(Input);
Writefile(Input+'.dat'); {WriteFile is the procedure to actually }
pause; {save the file. }
initgraph(gr,gd,''); {Going back into GraphMode. }
End;
Procedure EditFile; {A built in option to seed the 0th }
Var {generation. }
InKey :Char;
Count1,Count2:Integer;
CurrentX,CurrentY:Word;
Begin
CurrentX:=1;
CurrentY:=1; {This procedure sets up a graphic grid. }
Drawgrid;
For Count1:=1 to 20 do {This loop just draws the beings. }
For Count2:=1 to 20 do
If MainGrid[count2,count1] then LifeForm(Count1*20+180,Count2*20+20);
SetTextStyle(2,0,5); {These are instuctions for user. }
Txtout(' Make sure the Num',10,80,Blue,black,white);
Txtout(' Lock is togled on.',10,100,Blue,black,white);
Txtout(' Press 5 to change',10,140,Blue,black,white);
TxtOut(' a square.',10,160,Blue,black,white);
Txtout(' 8-=UP=-',10,200,Blue,black,white);
Txtout('4-=LEFT=- 6-=RIGHT=-',10,220,Blue,black,white);
Txtout(' 2-=DOWN=-',10,240,Blue,black,white);
Box3D(181+CurrentX*20,21+CurrentY*20,199+CurrentX*20,39+CurrentY*20,White,Darkgray);
Repeat {This repeat-until loop won't generate an}
Inkey:=readkey; {error. }
If Inkey=('5') then {"5" changes the status. }
If MainGrid[CurrentX,CurrentY] then
Begin
MainGrid[CurrentX,CurrentY]:=false;
BlankForm(Currentx*20+180,Currenty*20+20);
End else
Begin
MainGrid[CurrentX,CurrentY]:=true;
LifeForm(Currentx*20+180,Currenty*20+20);
End;
Box3D(181+CurrentX*20,21+CurrentY*20,199+CurrentX*20,39+CurrentY*20,Darkgray,White);
If Inkey=('8') then CurrentY:=CurrentY-1; {Move up}
If Inkey=('4') then CurrentX:=CurrentX-1; {Move left}
If Inkey=('6') then CurrentX:=CurrentX+1; {Move right}
If Inkey=('2') then CurrentY:=CurrentY+1; {Move down}
If CurrentX<1 then CurrentX:=20; {I have to keep the current position}
If CurrentY<1 then CurrentY:=20; {withing the grid. }
If CurrentX>20 then CurrentX:=1;
If CurrentY>20 then CurrentY:=1;
Box3D(181+CurrentX*20,21+CurrentY*20,199+CurrentX*20,39+CurrentY*20,White,Darkgray);
until (InKey=#27); {This 3DBox is an inverse of the }
End; {normal box around a being. It lets }
{the user know where the current }
{position is. }
{BTW #27 is the escape key }
Procedure Results(FinalStage:Word); {This procedure writes the status of }
Var {MainGrid to the printer. }
InKey:Char;
Count1,Count2:integer;
Data:String;
Begin {It promps the user as well. }
Txtout('Would you like to',10,50,Blue,black,white);
Txtout('print the grid?',10,60,Blue,black,white);
InKey:=ReadKey;
setfillstyle(solidfill,lightgray);
bar(5,45,190,80);
If (Inkey=('y')) or (Inkey=('Y')) then
Begin
Str(FinalStage,Data);
If prtr then WriteLn(lst,'At generation ',Data,', the data looked as follows:');
For Count1:=1 to 3 do
If prtr then WriteLn(lst,'');
For Count1:=1 to 20 do {I have to build a string to represent}
Begin {a row before I can print it. }
Data:=('');
For Count2:=1 to 20 do
If MainGrid[count2,count1] then Data:=Data+('[@]') else Data:=Data+('[ ]');
If prtr then WriteLn(lst,Data);
End;
For Count1:=1 to 5 do
If prtr then WriteLn(lst,'');
End;
End;
Procedure RunLoop; {This is the most important loop. It }
Var {runs each generation, checks if all }
Count1,Count2,Count3:Word; {the beings are dead, and displays it }
Dead :Boolean; {all to the screen. }
Data :String;
Begin
Drawgrid; {Just the graphic grid and life forms.}
For Count2:=1 to 20 do
For Count1:=1 to 20 do
If MainGrid[count2,count1] then LifeForm(Count1*20+180,Count2*20+20);
SetTextStyle(2,0,5);
If Prtr then results(0); {Lets you print the 0th generation. }
Txtout('Press anykey to Begin.',10,80,Blue,black,white);
pause;
setfillstyle(solidfill,lightgray);
bar(5,75,190,105);
Count3:=0; {Sets the counter to 0. }
bar(105,80,150,100);
txtout('1',110,80,Blue,Black,White);
dead:=false; {Dead is set to false for the first run.}
While not (Count3>=GenLoop) and not Dead do
Begin
Generate;
If Death then Dead:=true else Dead:=false; {This looks complicated but }
For Count1:=1 to 20 do {its not. Dead is set to false before }
For Count2:=1 to 20 do {each generation if Death is toggled }
If MainGrid[count2,count1] then {off. Death is the global boolean for }
Begin {weather or not the loop ends if every-}
Dead:=false; {thing is dead. If death is on, it sets}
LifeForm(Count1*20+180,Count2*20+20){dead to false as soon as it finds}
End {a life form. }
else BlankForm(Count1*20+180,Count2*20+20);
Count3:=Count3+1;
bar(105,80,150,100);
str(Count3,Data);
txtout(Data,110,80,Blue,Black,White);
For Count1:=1 to 50 do {A short pause with some noise to }
Begin {signify a generation passed. }
sound(random(4000));
delay(2);
nosound;
delay(2);
End;
End;
If Prtr then results(Count3); {Lets you print the results. }
Txtout('Press anykey to End.',10,50,Blue,black,white);
pause;
End;
{This is the functionality of the }
Procedure MainLoop; {Main Menu. }
Var
InKey :Char;
Begin
Repeat
MenuScreen(Prtr,Death,GenLoop); {This draws the graphic Main Menu. }
Inkey:=readkey;
If Inkey=('1') then {You can load a *.DAT file. }
LoadFile;
If Inkey=('2') then {You can save a *.DAT file. }
SaveFile;
If Inkey=('3') then {You can edit MainGrid. }
EditFile;
If Inkey=('4') then {This runs the actual generation. }
RunLoop;
If Inkey=('5') then {This allows you to change the number}
Begin {of times the loop runs. }
GenLoop:=GenLoop+1;
If GenLoop>20 then GenLoop:=1;
End; {This allows you to toggle if the }
If Inkey=('6') then {loop stops when everything is dead. }
If death then death:=false else death:=true;
If Inkey=('7') then {This allows you to toggle the printer}
ChkPrt;
Until Inkey=#27; {#27 is the escape key}
End;
Procedure Default; {This procedure loads some default }
Var {values and stuff. }
Count1:integer;
Begin
SetBKColor(LightGray); {All the graphic stuff has a lightgray}
Death:=true; {background.}
Prtr:=false;
ChkPrt;
GenLoop:=10;
For Count1:=0 to 21 do {This loop assures that the outter }
Begin {bounds are empty to start with. }
MainGrid[0,Count1]:=false;
MainGrid[21,Count1]:=false;
MainGrid[Count1,0]:=false;
MainGrid[Count1,21]:=false;
End;
End;
Begin
Gr:=Detect; {This puts you in Graph Mode useing }
Initgraph(gr,gd,''); {a Borland Graphic Interface file. }
Default; {Sets the default values for the }
{program. }
TitleScreen; {Just identifies the program to the }
{user. }
MainLoop; {The loop for the Main Menu itself. }
Closegraph; {Close the graph before you exit or }
{DOS looks really goofy. <grin> }
ClrScr; {Just a little after message to the }
TextColor(Green); {user. }
Write('I hope you enjoyed ');
TextColor(LightGreen);
WriteLn('The Game of Life');
End.
{Note from the author:
I woulda used the little smiley faces when printing the data, but my printer
wouldn't support it. I ran this on tons of data cuz data is so easy to make
with my built in editor. Any of the specs in the instructions can easily be
set up from the main menu. You can force it to run with everything being dead,
one to twenty times, and save the grid as a *.DAT file.
Zaskoda
}