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: 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 #include #include #include #include /* #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; }