FROM:	INTERNET:A.Fraser@eee.salford.ac.uk, INTERNET:A.Fraser@eee.salford.ac.uk
TO:	Mitch Allen, 76040,2757
	(unknown), 100010,2243
DATE:	05/11/93 11:26 AM

Re:	Virtual Ants in C

Sender: cellular-automata-request@Think.COM
Received: from Mail.Think.COM by ihc.compuserve.com (5.65/5.930129sam)
	id AA08046; Tue, 11 May 93 11:25:23 -0400
Received: by mail.think.com; Tue, 11 May 93 11:21:11 -0400
Return-Path: <A.Fraser@eee.salford.ac.uk>
Received: from Think.COM by mail.think.com; Tue, 11 May 93 11:21:03 -0400
Received: from europa.salford.ac.uk ([146.87.3.2]) by Early-Bird.Think.COM; Tue, 11 May 93 11:20:39 EDT
Message-Id: <9305111520.AA09872@Early-Bird.Think.COM>
Received: from mailgate-0.salford.ac.uk by europa.salford.ac.uk with SMTP (PP);
          Tue, 11 May 1993 15:47:45 +0100
From: A.Fraser@eee.salford.ac.uk
Date: 11 May 93 10:27
To: ca@Think.COM
Subject: Virtual Ants in C
X-Mailer: University of Salford cc:Mail/SMTP gateway 1.35
Encoding: 306 TEXT

Hi,

     Continuing in the longest messages known to man here is a C
implementation/port of the Virtual Ant program runs in Borland C but should be
simply portable to other compilers/systems. If you do make a port please send
me a copy, a Unix derivation would be nice.

     Also there is a new function which has 8 possible movement directions. The
emergent function of this is like a pulsating protoplasm, very unusual!!!?

     This C port runs about 3/4 times faster than the Qbasic version and it is
worthwhile to leave it for half an hour.

     Multiple Virtual Ants coming soon....

     Bugs and enhancements welcome.....

Ta ra
     Adam P.Fraser

 code follows.....

/* *************************************************************************
         **** Virtual Ant Code Version 1.0 10-11 May 1993 by Adam P.Fraser....**
**
         ***********************************************************************
**/


/* Compiled with Borland 3.1 but should be easily portable......... */

/*  This is a (near) direct port of a QBasic program written by Charles Wells
                Department of Mathematics, Case Western Reserve University.
                 His notes follow....

                        "This program implements Chris Langton's cellular automa
ton
                described in the Mathematical Intelligencer, volume 15, number 2
                (Spring 1993), page 54.  It describes the path of an ant who
                starts pointing in a certain direction.  If the ant is on a
                non-white square it turns the square red, rotates 90 degrees
                clockwise and moves one pixel in the direction it is pointing.
                If it is on a red square it turns the square white, rotates 90
                degrees counterclockwise and moves one pixel in the direction it
                is pointing.  In this implementation the path of the ant wraps
                around when it reaches the edge of the screen.  Most amazingly
                these simple rules produce behavior which looks chaotic for
                THOUSANDS of moves, then goes into a steady state during which
                it runs off the screen."


                Now my bit, actually this is more than a port there are a few mo
re bells
                and whistles and it will (fingers crossed) run on a CGA monitor.
                On a 486dx33 it goes like a bat out of hell and is really quite 
beautiful.

                Try it on its own, just compile and run and watch.. the steady s
tate
                quickly collides and a sort of 'rust' breaks out....

                Try running Virtual_Ant2 instead of Virtual_Ant that is very une
xpected
                you get something like a pulsating amoeba...

                All the random lines and dots will produce wierd and wonderful e
ffects.
                Try them and experiment.....

                To finish just press any key....

                Enjoy........


                All bugs and enhancements will be lovingly treated by me. (I wou
ld love
                to see some really exciting new virtual ant code. How about the 
turmite
                code Chris Langton wherever you are.....)

                Coming soon MULTIPLE VIRTUAL ANTS !!!!.....

                        ta ra,
                                                        Adam P. Fraser
                                Snail:Postgraduate Section         Email:a.frase
r@eee.salford.ac.uk
                                                        Maxwell Building
                                                        University Of Salford
                                                        M5 4WT
                                                        England
                                                                                
                                                                                
                                                                                
                                                         */

#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>

/* #define CGA    1  */                 /* Choose one and only one, thanks */
/* #define EGA    3  */     /*  Note no SuperVGA mode yet   */
#define VGA    9

#ifdef CGA
        #define HORIZONTAL 320
        #define VERTICAL   200
        #define BACKGROUND BLACK
        #define FOREGROUND CGA_RED
        #define GRAPHICS   1
        #define GMODE   CGAC2
#endif

#ifdef EGA
        #define HORIZONTAL 640
        #define VERTICAL   350
        #define BACKGROUND BLACK
        #define FOREGROUND YELLOW
        #define GRAPHICS   EGA
        #define GMODE      EGAHI
#endif

#ifdef VGA
        #define HORIZONTAL 640
        #define VERTICAL   480
        #define BACKGROUND BLACK
        #define FOREGROUND YELLOW
        #define GRAPHICS    9
        #define GMODE   VGAHI
#endif


/* Function Prototypes....................................................*/

void Random_Dots(int);
void Random_Lines(int);
void Random_Circles(int);
double Virtual_Ant(void);
double Virtual_Ant2(void);


/* Yes its the main block of code */

void main()
{
/* The graphics drivers nicked straight from borland C example */
        int gdriver = GRAPHICS, gmode=GMODE, errorcode;
        double count;

        initgraph(&gdriver, &gmode, "");
        errorcode = graphresult();
        if (errorcode != grOk)           /* an error occurred */
        {
                printf("Graphics error: %s\n", grapherrormsg(errorcode));
                printf("Press any key to halt:");
                getch();
                exit(1);                      /* return with error code */
        }

/*      Random_Dots(100);     */        /* Any of these will give further fun */
/*      Random_Lines(100);    */
/*      Random_Circles(20);   */

        count=Virtual_Ant();             /* Main block of code */
/*      count=Virtual_Ant2();  */     /* A new function takes place of above */

        printf("Iterations: %g\n",count);
        printf("Please press a key");
        {char c=getch();}               /* Buffer for chars will give an warning
 */
        while (!(kbhit()));
        closegraph();
}



void Random_Dots(int number_of_dots)
{
        int i,u,v;
        randomize();      /* necessary to really mess up the pot */
        for (i=0; i<=number_of_dots; i++)
        {
                u=random(HORIZONTAL);
                v=random(VERTICAL);
                putpixel(u,v,FOREGROUND);
        }
}

void Random_Lines(int number_of_lines)
{
        int i,u,v,w,z;
        randomize();             /* necessary to really mess up the pot */
        setcolor(FOREGROUND);
        for (i=0; i<=number_of_lines; i++)
        {
                u=random(HORIZONTAL);
                v=random(VERTICAL);
                w=random(HORIZONTAL);
                z=random(VERTICAL);
                line(u,v,w,z);
        }
}


void Random_Circles(int number_of_circles)
{
        int i,u,v,size;
        randomize();            /* necessary to really mess up the pot */
        setcolor(FOREGROUND);
        for (i=0; i<=number_of_circles; i++)
        {
                u=random(HORIZONTAL);
                v=random(VERTICAL);
                size=random(20);
                circle(u,v,size);
        }
}

/* The main ported code (not hacked, just got it to work) see initial note
         to see what is going on....................                    APF 10/0
5/93       */

double Virtual_Ant(void)
{
        int vector=0,ht=VERTICAL,wdth=HORIZONTAL,y=ht/2,x=wdth/2;
        int xdirs[4],ydirs[4];
        double count=0;

        xdirs[0]=-1;xdirs[1]=0;xdirs[2]=1;xdirs[3]=0;
        ydirs[0]=0;ydirs[1]=1;ydirs[2]=0;ydirs[3]=-1;

        while (!(kbhit()))
        {
                if (x < 0) x=wdth-1;
                if (x > wdth-1) x=0;
                if (y < 0) y=ht-1;
                if (y > ht-1) y=0;

                count++;

                if ( getpixel(x,y) == BACKGROUND)
                {
                        putpixel(x,y,FOREGROUND);
                        vector=(vector+1)%4;      // rotation direction clockwis
e
                        x=x+xdirs[vector];
                        y=y+ydirs[vector];
                }
                else
                {
                        putpixel(x,y,BACKGROUND);
                        vector=(vector+3)%4;      // rotation direction anti-clo
ckwise
                        x=x+xdirs[vector];
                        y=y+ydirs[vector];
                }
        }
        return count;
}

/* Basically the only difference between this and Virtual_Ant() is that
         this can move in 8 directions NE,SW etc (in Cellular Automata terms
         instead if having 5 neighbourhood states we have nine). The change to
         the program though is quite amazing........... APF 11/05/93   */

double Virtual_Ant2(void)
{
        int vector=0,ht=VERTICAL,wdth=HORIZONTAL,y=ht/2,x=wdth/2;
        int xdirs[8],ydirs[8];
        double count=0;

        xdirs[0]=-1;xdirs[1]=-1;xdirs[2]=0;xdirs[3]=1;
        xdirs[4]=1;xdirs[5]=1;xdirs[6]=0;xdirs[7]=-1;

        ydirs[0]=0;ydirs[1]=1;ydirs[2]=1;ydirs[3]=1;
        ydirs[4]=0;ydirs[5]=-1;ydirs[6]=-1;ydirs[7]=-1;

        while (!(kbhit()))
        {
                if (x < 0) x=wdth-1;
                if (x > wdth-1) x=0;
                if (y < 0) y=ht-1;
                if (y > ht-1) y=0;

                count++;

                if ( getpixel(x,y) == BACKGROUND)
                {
                        putpixel(x,y,FOREGROUND);
                        vector=(vector+1)%8;      // rotation direction clockwis
e
                        x=x+xdirs[vector];
                        y=y+ydirs[vector];
                }
                else
                {
                        putpixel(x,y,BACKGROUND);
                        vector=(vector+7)%8;      // rotation direction anti-clo
ckwise
                        x=x+xdirs[vector];
                        y=y+ydirs[vector];
                }
        }
        return count;
}


