[comp.sources.amiga] v02i094: evo-life - evolving life simulation

page@swan.ulowell.edu (Bob Page) (12/07/88)

Submitted-by: ain@k.cc.purdue.edu (Pat-bob White)
Posting-number: Volume 2, Issue 94
Archive-name: fun/evo-life.1

Here is an evolving life program I wrote several years ago in
AmigaBasic.  I have other (extended) versions is anybody is
interested.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	readme
#	evolving_life_140
#	tracefile
# This archive created: Tue Nov 22 11:08:37 1988
# By:	Pat-bob White (PUCC Land, USA)
cat << \SHAR_EOF > readme
   These two programs go together and were written in Amiga Basic.. first a
bit about what they are and what they do:
   Evolving Life 140 is a program I wrote about 2 years ago when I wanted to
explore the concept of genetic learning.  I abstracted real life into an
environment (sort of an electronic petri dish) and amoebe-like cells (sort of
e-amoeba).
   The environment consists of a 24x38 matrix of locations that cells can
occupy.  Each location has a food level which is incremented by one each step,
and is decrememnted when the cells eat.  The levels within the locations are
represented by a spectrum from red to blue (red = lots of food).  One step is
executed from each cell, then the environment is updated.. repeats till all
cells die or the machine crashes :-)
   The cells are represented by black dots in the locations.  They run 
"genetic programs" that have 6 different kind of steps: move, reproduce, eat,
goto, if hungry, and nop -- each step uses up internalized food.
   Move: a cell tries to move to a (randomly selected) adjacent empty location,
   Reproduce: reproduction is sexual; A cell on the make first finds a mate (a
      cell in an adjacent location), then an empty adjacent location for the
      child cell, and finally, creates the child cell's "genetic program" by
      copying half from it's own program, and half from the mate's program.
      Then, 1 random step in the new program is changed to a random value (on
      the theory that mutations are good for the soul :-)
   eat: internalize food from the environment (if there is any),
   goto: goto a new step in the program (goes back to my own theory that loops
      are essential to any programming language),
   if hungry: if internalized food level is below some amount, then go to some
      program step (same theory).. since I used bytes to represent each step,
      this put a limt of 32 steps on the size of a program (I found out that
      a cell only uses about 8 steps, but needed about 16 locations to save
      them -- the other 8 steps being spent as wasted space... when I tried to
      shorten the program to only 8 steps, I couldn't get colonies to start).
   nop: every language needs one.. and what else was I to do with the other
      3 3-bit patterns I wasn't using?
   
   There is a special cell that I used for keeping a tracefile -- cell 1.  (I
represented the cells with an array of strings, so this was the cell in the
first position of the array).  This cells is marked with a red dot in it's
center, and each time a cell that is born reuses that array location, I write a
snapshot of the current matrix, and where the cells are into the tracefile.

   The tracefile program is the other one here, and all it does is display
a tracefile on the screen.  It's comments document it fairly well, so I won't
bother to say anthing else about it.


implementation:
   Both programs are implemented in Amiga Basic, and I use the graphics
heavily.. so a bit of description about Amiga graphics is in order for those
who don't (aren't fortunate enough? :-) have an Amiga... (those who have an
Amiga may find my terminology confusing since much of it is from the meager
graphics background I have)
   The Amiga has screens and windows.  A screen is where the colors (bitplanes)
are defined, and the actual storage is attached to.  A window is a graphics
viewport onto a screen that has it's own internal coordinate system.. when
something is drawn into a window, the OS performs any necessary clipping and
coordinate translation, and then actually renders it into the screen's memory
(therefore, windows appear to have their own memory but really don't).
   Therefore, I open a new 32-color screen to get access to a whole set of 32
colors, open a window on it to render into, and then start rendering.  One
confusing call (basic's fault, not mine) is the line drawing command, which I
use to draw filled rectangles by specifying the upper left and lower right
corners of the rectangle, and adding the "bf" option to draw a box and fill it.
   PALLETTE sets a color in the pallette.
   POINT returns the color of the referenced pixel.
   LOCATE moves the cursor to the desired character position.
   CVI converts a two byte string to the integer it represents in binary
(it's much the same as "asc() * 256 + asc()").
   MKI$ is the opposite of CVI -- converts an integer into a string containing
the 2-byte binary representation.


   These are the comments from the evolving life program and it's corresponding
tracefile program:

Evolving Life 140
-----------------
max number of cells is 140
cells are kept as basic strings
there are 8 types of program steps a cell program knows: move,
reproduce, eat, goto, if hungry, and 3 nop's.  move moves a cell in
any 1 of te 8 possible directions, eat takes food from the environment,
goto unconditionally branches to another step i the program, if hungry
branches if the cell is hungry, and nop's do nothing.  All actions
cause food consumption of the internalized food (via eat).
   death is caused by falling off the end of the program, running out
of food, or executing more than the max number of steps allowed (the
lifespan).
   A trace snapshot is written to a file each time a cell is born into
cell 1's storage (the cell storage is reused since I have only a small
number of them -- so, everytime a cell is born that reuses storage
position 1, a snapshot is taken).  The snapshots files are generally
large (>200K) and are viewed through the "Tracefile" program.
   Food levels are represented by a spectrum of colors -- red is max
food, dark blue is min (somehow, purple slipped in as a high-but-not-
max color for food.. don't really know why, but I suspect it is because
I didn't want it to feel lonely :-)
   The program runs till all the cells die.. alt least it is supposed to
do that.
  The stats at the bottome are: nc = number of currently alive cells,
tc = total number of cells that have ever lived or are currently living,
ns = total number of cell-program steps have been done.
   Have fun reading the code -- it is commented but mostly consists of
mid$ accesses to get characters out of the cell storage -- the cell's
program steps are stored as characters in a basic string. 


Tracefile
---------
Tracefile -- written to display the trace files saved by
 Evolving Live 140.  Written sometime arround 6/86
Patrick White
currently (11/88) reachable at ain@k.cc.purdue.edu

displays the tracefile -- one frame at a time.  the stats at the bottom
of the picture are: which screen is being displayed, (nc) the number of
cells on the screen, (tc) the total number of cells that have ever
lived, (ns) the total number of cell-program-steps that have been
executed.
The colors on the screen indicate: red is most food, dark blue is least
food.  THe outer square is the fool level scaled on a screen-wise basis
with red being greatest amount of food.  The inner square is the food
level scaled from 0 to max possible - again red is max.  I did it this
way because I couldn't decided how to do it -- so, naturally, I did it
both ways :-)
  When finished with the data file, the program waits for a mouse-click
in the display window before closing the window/screen.  If you stop
the program in any other way, the screen and window will be left open
and take memory -- best to let it finish on it's own.
 Oh, BTW, trace snapshots are taken whenever a cell is born into cell 1
(since I have to reuse the cell locations, this makes soms sense).


   I also have a version in C for the Amiga somewhere -- I didn't submit it
because I'm not sure if it even compiles anymore -- if you want it, let me know
and I'll send it to you.



   Well, that's about it... (I think it's documented enough now :-)
If you have any questions, please ask...

-- Pat White
ARPA/UUCP: k.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM  PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906
SHAR_EOF
cat << \SHAR_EOF > evolving_life_140
REM Evolving Life 140 (140 cells max)
REM Patrick White  written -- I have no idea but somewhere around 6/86
REM currently (11/88) reachable at ain@k.cc.purdue.edu

REM max number of cells is 140
REM cells are kept as basic strings
REM there are 8 types of program steps a cell program knows: move,
REM reproduce, eat, goto, if hungry, and 3 nop's.  move moves a cell in
REM any 1 of te 8 possible directions, eat takes food from the environment,
REM goto unconditionally branches to another step i the program, if hungry
REM branches if the cell is hungry, and nop's do nothing.  All actions
REM cause food consumption of the internalized food (via eat).
REM    death is caused by falling off the end of the program, running out
REM of food, or executing more than the max number of steps allowed (the
REM lifespan).
REM    A trace snapshot is written to a file each time a cell is born into
REM cell 1's storage (the cell storage is reused since I have only a small
REM number of them -- so, everytime a cell is born that reuses storage
REM position 1, a snapshot is taken).  The snapshots files are generally
REM large (>200K) and are viewed through the "Tracefile" program.
REM    Food levels are represented by a spectrum of colors -- red is max
REM food, dark blue is min (somehow, purple slipped in as a high-but-not-
REM max color for food.. don't really know why, but I suspect it is because
REM I didn't want it to feel lonely :-)
REM    The program runs till all teh cells die.. alt least it is supposed to
REM do that.
REM   The stats at teh bottome are: nc = number of currently alive cells,
REM tc = total number of cells that have ever lived or are currently living,
REM ns = total number of cell-program steps have been done.
REM    Have fun reading the code -- it is commented but mostly consists of
REM mis$ accesses to get characters out of the cell storage -- the cell's
REM program steps are stored as characters in a basic string. 

REM   life
   CLEAR,20000,5000
   RANDOMIZE TIMER
   INPUT "filename of trace file ";filename$ : OPEN "O",#1,filename$
   ncels = 139 : nstps = 50 : clrs = 16 : alimit = 94 : ns& = 0
   nc% = 0 : tc& = 0
   DIM food%(37,23), cell$(ncels)
   
   REM   initialize screen
   SCREEN 1,300,200,4,1
   WINDOW 2,"Evolving Life Display",(0,0)-(290,180),0,1
   PALETTE 0, 0,0,0 : PALETTE 1, 0,0,1 : PALETTE 2, 0,.29,1
   PALETTE 3, 0,.57,1 : PALETTE 4, 0,.86,1 : PALETTE 5, 0,1,.86
   PALETTE 6, 0,1,.57 : PALETTE 7, 0,1,.29 : PALETTE 8, 0,1,0
   PALETTE 9, .29,1,0 : PALETTE 10,.57,1,0 : PALETTE 11,.86,1,0
   PALETTE 12,1,.86,0 : PALETTE 13,1,.57,0 : PALETTE 14,1,.29,0
   PALETTE 15,1,0,0 : CLS : mf = 8510 : stp = mf / (clrs - 2)
   FOR i = 0 TO 37
      FOR j = 0 TO 23
         food%(i,j) = i*j*10
         LINE (i*7,j*7)-(i*7+6,j*7+6),(INT(food%(i,j) / stp) + 1),bf   
      NEXT j
   NEXT i
   FOR i = 9 TO 15 : LINE (266,i*7+2)-(272,i*7+4),15,bf : NEXT i
         
   REM   initialize cells
   FOR c = 0 TO 69
      x = INT (RND * 38) : y = INT (RND * 24)
      IF POINT(x*7+3,y*7+3) > 0 THEN
         a% = INT (RND * mf) : b% = INT (RND * mf / 2)
         cell$(c) = CHR$(x) + CHR$(y) + MKI$(a%) + MKI$(b%) + MKI$(INT(RND*alimit)) + MKI$(0)
         LINE (x*7+2,y*7+2)-(x*7+4,y*7+4),0,bf 
         FOR i = 1 TO nstps : x = INT (RND * 256) : cell$(c) = cell$(c) + CHR$(x) : NEXT i
         nc% = nc% + 1
      END IF
   NEXT c
   tc& = nc%
   LOCATE 22,1 : PRINT "fre= ";FRE(0);FRE(-1);FRE(-2);
   GOSUB pic
   
   REM quit stuff
   ON ERROR GOTO e
   ON MOUSE GOSUB quit
   MOUSE ON
   
runagain:   REM   run cell programs
   REM   increment food in environment
   PALETTE 0,.2,.2,.2 : ns& = ns& + 1
   FOR i = 0 TO 37
      FOR j = 0 TO 23
         a% = food%(i,j) : food%(i,j) = a% + 1 : IF food%(i,j) > mf THEN food%(i,j) = mf
         IF INT(a% / stp) <> INT(food%(i,j) / stp) THEN
            x = POINT(i*7+3,j*7+3) : LINE (i*7,j*7)-(i*7+6,j*7+6),INT(food%(i,j) / stp) + 1,bf
            IF x = 0 THEN LINE (i*7+2,j*7+2)-(i*7+4,j*7+4),0,bf
         END IF
      NEXT j
   NEXT i
   PALETTE 0,0,0,0
   
   FOR c = 0 TO ncels
      IF cell$(c) <> "" THEN
         x = ASC( MID$( cell$(c),1,1)) : y = ASC( MID$( cell$(c),2,1))
         IF (CVI( MID$(cell$(c), 7,2)) > alimit) OR (CVI( MID$( cell$(c), 3, 2)) < 0) THEN
            LINE (x*7,y*7)-(x*7+6,y*7+6),INT(food%(x,y)/ stp)+1, bf
            cell$(c) = "" : nc% = nc% - 1
         ELSE
            MID$(cell$(c), 7,2) = MKI$( CVI( MID$(cell$(c),7,2)) + 1) 
            IF (y > 8) AND (y < 16) THEN MID$( cell$(c), 11 + INT(RND*(LEN(cell$(c))-10)), 1) = CHR$( INT(RND*256) )
            a% = CVI( MID$( cell$(c), 9, 2) ) : y = ASC( MID$( cell$(c), 11 + a%, 1) )
            a% = a% + 1
            IF a% > (LEN( cell$(c)) - 11) THEN : MID$( cell$(c), 7, 2) = MKI$( alimit + 1) : a% = 0            
            MID$( cell$(c), 9, 2) = MKI$( a% )
            ON (y AND 7)+1 GOSUB mov, repro, eat, gto, ifhung, nop, nop, nop
         END IF
      END IF
   NEXT c      
   LOCATE 22,1 : PRINT "nc="; nc%;"  tc=";tc&;"  ns=";ns&; 
   GOTO runagain

e:  WINDOW CLOSE 2 : SCREEN CLOSE 1 : CLOSE #1 : prinr ERR
    END    
   
pic:   REM store a picture of the screen   
   WRITE #1,mf;stp;ns&;tc&;nc%;cell$(0)
   FOR i = 0 TO 37
      WRITE #1,food%(i,0);food%(i,1);food%(i,2);food%(i,3);food%(i,4);food%(i,5);food%(i,6);food%(i,7);food%(i,8);food%(i,9);food%(i,10);food%(i,11)
      WRITE #1,food%(i,12);food%(i,13);food%(i,14);food%(i,15);food%(i,16);food%(i,17);food%(i,18);food%(i,19);food%(i,20);food%(i,21);food%(i,22);food%(i,23)
   NEXT i
   FOR i = 0 TO ncels : IF cell$(i) <> "" THEN WRITE #1,MID$(cell$(i),1,2)
   NEXT i
RETURN
      
quit:   REM end
   WINDOW CLOSE 2 : SCREEN CLOSE 1 : CLOSE #1
   PALETTE 0, 0,.5,1 : PALETTE 1, 1,1,1 : PALETTE 2, 0,0,0
   PALETTE 3, 1,.73,0
   END

nop:   REM no op
   MID$(cell$(c), 3, 2) = MKI$( CVI( MID$( cell$(c), 3, 2)) - 10) : RETURN   

mov:   REM move in specified direction
   MID$( cell$(c), 3, 2) = MKI$( CVI( MID$( cell$(c), 3,2) ) - 20)
   
   REM   erase old cell position
   a% = (y AND 224) / 32
   x = ASC( MID$( cell$(c), 1, 1) ) : y = ASC( MID$( cell$(c), 2, 1) ) : x1 = x : y1 = y
   LINE (x*7,y*7)-(x*7+6,y*7+6),INT( food%(x,y) / stp) + 1,bf
   
   REM   pick direction and move cell if possible   
   IF a% = 0 THEN x = x - 1: y = y - 1
   IF a% = 1 THEN y = y - 1
   IF a% = 2 THEN y = y - 1: x = x + 1
   IF a% = 3 THEN x = x + 1
   IF a% = 4 THEN x = x + 1: y = y + 1
   IF a% = 5 THEN y = y + 1
   IF a% = 6 THEN y = y + 1: x = x - 1
   IF a% = 7 THEN x = x - 1
   
   x = (x + 38) MOD 38
   y = (y + 24) MOD 24
   IF POINT( x*7 + 3, y*7 + 3) <> 0 THEN
      MID$(cell$(c), 1, 1) = CHR$( x ) : MID$(cell$(c), 2, 1) = CHR$( y )
      LINE (x*7+2, y*7+2)-(x*7+4,y*7+4),0,bf
   ELSE
      LINE (x1*7+2, y1*7+2)-(x1*7+4, y1*7+4),0,bf
   END IF
RETURN

repro:   REM reproduce if a cell nearby
   MID$( cell$(c), 3, 2) = MKI$( CVI( MID$( cell$(c), 3, 2)) - 60)
   IF nc% = ncels THEN RETURN   
   
   REM determine which cell to mate with
   a% = 0 : b% = 0 : x1 = ASC( MID$( cell$(c),1,1)) : y1 = ASC( MID$( cell$(c),2,1)) 
l1: IF (cell$(a%) <> "") AND (a% <> c) THEN
       x = ASC( MID$( cell$(a%), 1, 1) ) : y = ASC( MID$( cell$(a%), 2, 1) )
       IF ((x<x1-1) OR (x>x1+1) OR (y<y1-1) OR (y>y1+1)) AND (a% < ncels) THEN a%=a%+1 : b% = 1
    ELSE
       IF a% < ncels THEN a% = a% + 1 : b% = 1    
    END IF
   IF b% = 1 THEN b% = 0 : GOTO l1
   IF (c = a%) OR (cell$(a%) = "") OR (x<x1-1) OR (x>x1+1) OR (y<y1-1) OR (y>y1+1) THEN RETURN
   
   REM determine free cell
   b% = 0
l2: IF (cell$(b%) <> "") AND (b% < ncels) THEN b% = b% + 1 : GOTO l2
   IF cell$(b%) <> "" THEN RETURN   
   
   REM find empty spot for child cell
   c% = x1 : d% = y1
   FOR i = 1 TO 15
      x = INT(RND * 3) - 1 + x1 : y = INT(RND * 3) - 1 + y1
      IF ((POINT(x*7+3,y*7+3) > 0) AND (x > 0) AND (x < 38) AND (y > 0) AND (y < 24)) THEN c% = x : d% = y
   NEXT i 
   IF ((c% = x1) AND (d% = y1)) THEN RETURN  
   
   REM create child
   nc% = nc% + 1 : tc& = tc& + 1
   x = LEN( cell$(c) ) : y = LEN( cell$(a%) )
   cell$(b%) = MID$(cell$(c), 1, INT(x / 2) ) + MID$(cell$(a%), INT(y / 2), y - INT(y / 2) )
   MID$(cell$(b%), 1, 1) = CHR$(c%) : MID$(cell$(b%), 2, 1) = CHR$(d%)
   LINE (c%*7+2,d%*7+2)-(c%*7+4,d%*7+4),0,bf
   a% = INT( CVI( MID$( cell$(c), 3, 2) ) / 2)
   MID$( cell$(c), 3, 2) = MKI$( a% ) : MID$( cell$(b%), 3, 2)= MKI$( a% )
   MID$(cell$(b%), 7, 2) = MKI$( 0 ) : MID$(cell$(b%), 9, 2) = MKI$( 0 )
       
   REM mutate one step in child   
REM   x = LEN( cell$(b%) )
REM   a = RND : b = RND : MID$( cell$(b%), 11 + INT( a * (x - 10)), 1) = CHR$( INT( b * 256 ))
   IF b% = 0 THEN GOSUB pic
RETURN
   
eat:   REM eat food
   MID$( cell$(c), 3, 2) = MKI$( CVI( MID$( cell$(c), 3, 2)) - 20)
   x = ASC( MID$( cell$(c), 1, 1)) : y = ASC( MID$( cell$(c), 2, 1))
   IF food%(x,y) > 100 THEN
      food%(x,y) = food%(x,y) - 100
      MID$( cell$(c), 3,2) = MKI$( CVI( MID$(cell$(c),3,2)) + 100)
   ELSE
      MID$( cell$(c), 3,2) = MKI$( CVI( MID$(cell$(c),3,2)) + food%(x,y))
      food%(x,y) = 0
   END IF
   LINE (x*7,y*7)-(x*7+6,y*7+6),INT(food%(x,y)/ stp) + 1,bf
   LINE (x*7+2,y*7+2)-(x*7+4,y*7+4),0,bf  
RETURN

gto:   REM jump in program
   MID$( cell$(c), 3, 2) = MKI$( CVI( MID$( cell$(c), 3, 2)) - 20)
   a% = CVI( MID$( cell$(c), 9, 2)) : a% = ASC( MID$( cell$(c), a% + 11, 1)) MOD (LEN(cell$(c)) - 10)
   MID$( cell$(c), 9,2) = MKI$( a% )
RETURN

ifhung:   REM  if hungry then jump in program
   MID$( cell$( c), 3,2) = MKI$( CVI( MID$( cell$(c), 3,2)) -40)
   a% = CVI( MID$( cell$(c), 9, 2)) : x = ASC( MID$( cell$(c), a% + 11, 1)) MOD (LEN(cell$(c)) - 10)
   IF CVI( MID$( cell$(c), 3,2)) < CVI( MID$( cell$(c), 5,2)) THEN a% = x ELSE a% = a% + 1
   IF a% > (LEN(cell$(c)) - 11) THEN a% = 0
   MID$( cell$(c), 9, 2) = MKI$( a% )
RETURN   
SHAR_EOF
cat << \SHAR_EOF > tracefile
REM Tracefile -- written to display the trace files saved by
REM  Evolving Live 140.  Written sometime arround 6/86
REM Patrick White
REM currently (11/88) reachable at ain@k.cc.purdue.edu

REM displays the tractefile -- one frame at a time.  the stats at the bottom
REM of the picture are: which screen is being displayed, (nc) the number of
REM cells on the screen, (tc) the total number of cells that have ever
REM lived, (ns) the total number of cell-program-steps that have been
REM executed.
REM The colors on the screen indicate: red is most food, dark blue is least
REM food.  THe outer square is the fool level scaled on a screen-wise basis
REM with red being greatest amount of food.  The inner square is the food
REM level scaled from 0 to max possible - again red is max.  I did it this
REM way because I couldn't decided how to do it -- so, naturally, I did it
REM both ways :-)
REM   When finished with the data file, the program waits for a mouse-click
REM in the display window before closing the window/screen.  If you stop
REM the program in any other way, the screen and window will be left open
REM and take memory -- best to let it finish on it's own.
REM  Oh, BTW, trace snapshots are taken whenever a cell is born into cell 1
REM (since I have to reuse the cell locations, this makes soms sense).
 
REM   trace viewer
   INPUT "trace filename";filename$
   OPEN "I",#1,filename$
   DIM f%(37,23)
   sc = 0
   
   SCREEN 1,300,200,4,1
   WINDOW 2,filename$,(0,0)-(290,180),0,1
   PALETTE 0, 0,0,0 : PALETTE 1, 0,0,1 : PALETTE 2, 0,.29,1
   PALETTE 3, 0,.57,1 : PALETTE 4, 0,.86,1 : PALETTE 5, 0,1,.86
   PALETTE 6, 0,1,.57 : PALETTE 7, 0,1,.29 : PALETTE 8, 0,1,0
   PALETTE 9, .29,1,0 : PALETTE 10, .57,1,0 : PALETTE 11, .86,1,0
   PALETTE 12, 1,.86,0 : PALETTE 13, 1,.57,1 : PALETTE 14, 1,.29,0
   PALETTE 15, 1,0,0
   
nxt:
   sc = sc + 1   
   INPUT #1,mf,stp,ns&,tc&,nc%
   c$ = INPUT$ (64, #1) : c$ = MID$( c$, 3, 60)
   REM PRINT nc%;"***";c$;"***"
   FOR i = 0 TO 37
      INPUT #1,f%(i,0),f%(i,1),f%(i,2),f%(i,3),f%(i,4),f%(i,5),f%(i,6),f%(i,7),f%(i,8),f%(i,9),f%(i,10),f%(i,11)
      INPUT #1,f%(i,12),f%(i,13),f%(i,14),f%(i,15),f%(i,16),f%(i,17),f%(i,18),f%(i,19),f%(i,20),f%(i,21),f%(i,22),f%(i,23)
   NEXT i

   max = f%(0,0)
   FOR i = 0 TO 37 : FOR j = 0 TO 23
      IF f%(i,j) > max THEN max = f%(i,j)
   NEXT j : NEXT i
   mstp = max / 14
      
   FOR i = 0 TO 37
      FOR j = 0 TO 23
         LINE (i*7,j*7)-(i*7+6,j*7+6),INT(f%(i,j) / mstp) + 1,b
         LINE (i*7+1,j*7+1)-(i*7+5,j*7+5),INT(f%(i,j) / stp) + 1,bf
      NEXT j
   NEXT i
   
   FOR i = 1 TO nc%
      a$ = INPUT$ (5,#1) : x = ASC( MID$( a$, 2,1)) : y = ASC( MID$( a$, 3,1))
      REM PRINT  i;"***";a$;"***",x, y
      LINE (x*7+2,y*7+2)-(x*7+4,y*7+4),0,bf
      IF i = 1 THEN LINE (x*7+3,y*7+3)-(x*7+3,y*7+3),15,bf
   NEXT i
   
   LOCATE 22,1 : PRINT sc;"nc= ";nc%;"tc= ";tc&;"ns= ";ns&;
   
   IF EOF(1) THEN GOTO cnt ELSE GOTO nxt
   
cnt:
   BEEP   
   ON MOUSE GOSUB quit
   MOUSE ON
slp: SLEEP
   GOTO slp
   
quit:   
   CLOSE #1 : WINDOW CLOSE 2 : SCREEN CLOSE 1
   PALETTE 0, .4,.6,1 : PALETTE 1, 1,1,1 : PALETTE 2, 0,0,0
   PALETTE 3, 1,.73,0
   END
      
SHAR_EOF
#	End of shell archive
exit 0


-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.