home *** CD-ROM | disk | FTP | other *** search
- /* tierra.c 28-10-91 main module of Tierra Synthetic Life Simulator */
- /** Tierra Simulator V3.0: Copyright (c) 1991 Thomas S. Ray **/
-
- #include "license.h"
-
- #ifndef lint
- static char sccsid[] = "%W% %G%";
- #endif
-
- #include "tierra.h"
- #include "declare.h"
- #include "soup_in.h"
- #include <sys/types.h>
- #include <fcntl.h>
- #include <signal.h>
- #ifdef unix
- #include <unistd.h>
- #endif
-
- I32s FindCell;
- I32s itime, mtime;
- struct event FindTime;
- int run_flag; /* NEW GLOBAL */
-
- #define _DBGMainModule
- #include "debug.h" /* some useful debugging stuff */
- #undef _DBGMainModule
-
- #ifdef SOCKETS
-
- #include "alreques.h" /* request constants, ids, etc. */
- #include "allayer.h" /* public header for AL Layer */
- #include "tlayer.h" /* public header for T layer */
- #include "tlayerp.h"
-
- static void _t_memory_stats P_(( unsigned char which, void *indata,
- int inlen, void **outdata, int *outdatalen ));
- static void _t_sim_runcontrol P_(( unsigned char which, void *data,
- int datalen ));
-
- static void _t_init_birthdeath P_(( ALtCLink *clink ));
-
- static TtMonInitRoutine _t_myinitroutines[] = {
- { ALrdBirthDeath, _t_init_birthdeath }
- };
-
- static void _t_init_birthdeath( clink )
- ALtCLink *clink;
- {
- Pcells ce;
- I32s i;
-
- TRepBirthDeathInit( clink, 1 );
- for ( i = 0; i < CellsSize; i++ ) {
- ce = cells + i;
- if ( ce->ld ) {
- if ( ce->mm.s )
- TRepBirthDirect( clink, ce->mm.p, ce->mm.s );
- if ( ce->md.s )
- TRepBirthDirect( clink, ce->md.p, ce->md.s );
- }
- }
- TRepBirthDeathInit( clink, 0 );
- }
-
- static void _t_memory_stats( which, indata, inlen, outdata, outdatalen )
- u_char which;
- void *indata;
- int inlen;
- void **outdata;
- int *outdatalen;
- { ALrtMemStats *ms;
-
- if (( ms = (ALrtMemStats *)ALMalloc(sizeof(ALrtMemStats))) ==
- (ALrtMemStats *)NULL)
- { sprintf(mes[0], "_t_memory_stats: can't malloc");
- FEError(1);
- exit(1);
- }
- ms->memsize = SoupSize;
- *outdata = ms;
- *outdatalen = sizeof(ALrtMemStats);
- }
- /*-----------------------------------------------------------------------*/
- static void
- _t_query_org( which, indata, inlen, outdata, outdatalen )
- u_char which;
- void *indata;
- int inlen;
- void **outdata;
- int *outdatalen;
- {
- ALrtQueryOrg *qo;
- ALrtOrgInfo *oi;
-
- FILE *dan_fp;
- I32s tpci;
- I8s tmd;
- I8s tstr[200];
- Pgl g;
- I32s tl=1;
- I32s dan_fd, tsz;
-
- qo = (ALrtQueryOrg *)indata;
- fprintf( stderr, "QueryOrg: received query for [ %d : %d ]\n",
- qo->start, qo->length );
-
- if ((IsFree(ad(qo->start))))
- {
- if (( oi = (ALrtOrgInfo *)ALMalloc( 1 )
- ) == (ALrtOrgInfo *)NULL ) {
- fprintf( stderr, "_t_query_org: can't malloc\n" );
- exit( 1 );
- }
- *oi = '@';
- *outdata = oi;
- *outdatalen = 1;
- }
- else {
- WhichCell(ad(qo->start),&tpci,&tmd);
- if (tmd == 'm')
- {
- extract(tpci);
- sprintf(tstr,"arg x %s%4.4d.gen %s\n",GenebankPath,
- (cells+tpci)->d.gen.size, (cells+tpci)->d.gen.label);
- system(tstr);
-
- sprintf(tstr,"%4.4d%s",(cells+tpci)->d.gen.size,
- (cells+tpci)->d.gen.label);
-
- dan_fd = open(tstr,O_RDONLY);
- if( dan_fd < 0 ) {
- fprintf(stderr,"temp gene file can't read");
- perror("moo");
- exit(-666);
- }
- tsz = (int)lseek(dan_fd,0L,SEEK_END);
- lseek(dan_fd,0L,SEEK_SET);
- if (( oi = (ALrtOrgInfo *)ALMalloc( (tsz ) + 20)
- ) == (ALrtOrgInfo *)NULL ) {
- fprintf( stderr, "_t_query_org: can't malloc\n" );
- exit( 1 );
- }
- *oi = ' ';
- tl = read(dan_fd,oi,tsz) ;
- if (tl < 0){
- fprintf(stderr,"temp gene file can't read");
- perror("moo");
- exit(-666);
- }
- close(dan_fd);
- sprintf(tstr,"rm %4.4d%s\n",(cells+tpci)->d.gen.size,
- (cells+tpci)->d.gen.label);
- system(tstr);
- *outdata = oi;
- *outdatalen = tsz +1;
- }
- else
- {
- if (( oi = (ALrtOrgInfo *)ALMalloc(100)
- ) == (ALrtOrgInfo *)NULL ) {
- fprintf( stderr, "_t_query_org: can't malloc\n" );
- exit( 1 );
- }
- sprintf(oi,"\nchild data: yet yet able to display\n\n");
- *outdata = oi;
- *outdatalen = 100;
- }
-
- }
- }
-
-
-
- /*-----------------------------------------------------------------------*/
- /* this routine is nto finished, but helps in monitoring runs
- till the tty version of ov is ready */
- static void
- _t_query_size(size_class)
- I32s size_class;
- {
- I32s top_buf,tc,tl,c,t,thit;
- typedef struct size_buf {
- I32s count;
- I8s *gene;
- I32s moves;
- I32s flags;
- I32s bits;
- } bf;
- bf buf[10];
-
- if((size_class < 1) || (size_class > 20000)) return;
-
- thit = 0;
- top_buf = -1;
-
- for(t=0; t< 10; t++)
- {
- buf[t].count=0;
- buf[t].moves=0;
- buf[t].gene=NULL;
- buf[t].bits=0;
- buf[t].flags=0;
- }
-
- for(c = 2; c < CellsSize; c++)
- {
- if (
- ((cells+c)->ld) &&
- ((cells+c)->mm.s == size_class))
- {
- for(t = 0; t < 10; t++)
- {
- if (buf[t].gene == NULL ) { thit = 0; t = 500; break;}
- if (strcmp((cells+c)->d.gen.label,buf[t].gene)== 0 )
- {
- thit = 1;
- buf[t].count++;
- buf[t].flags += (cells+c)->d.flags - (cells+c)->d.d1.flags;
- buf[t].moves += (cells+c)->d.mov_daught;
- /* buf[t].bits |= (cells+c)->d.bits; */
- t = 500;
-
- }
- }
- if (thit== 0)
- {
- thit =1;
- top_buf += (top_buf < 11) ? 1 : 0;
- if (top_buf > 10) break;
- buf[top_buf].gene = (cells+c)->d.gen.label;
- buf[top_buf].count++;
- /* buf[top_buf].bits |= (cells+c)->d.bits; */
- buf[top_buf].flags += (cells+c)->d.flags - (cells+c)->d.d1.flags;
- buf[top_buf].moves += (cells+c)->d.mov_daught;
- }
-
- }
- }
- sprintf(mes[0],"==========================================================");
- sprintf(mes[1],"TIERRA: Size Class %d (first 10)",size_class);
- sprintf(mes[2],"==========================================================");
- sprintf(mes[3],"Gene:\t#\t%% Mem\tErrs\tMove\tBits");
- FEError(4);
-
- for(t= 0; t < 10; t++)
- {
- if (buf[t].count < 1) break;
- sprintf(mes[0],"%3.3s\t%d\t%d\t%d\t%d\t%d",
- buf[t].gene,
- buf[t].count,
- (int) (100.0 * buf[t].count * size_class / SoupSize),
- (int) (buf[t].flags / buf[t].count),
- (int) (buf[t].moves / buf[t].count),
- buf[t].bits
- );
- FEError(1);
- }
- }
- /*-----------------------------------------------------------------------*/
-
- static void _t_sim_runcontrol( which, data, datalen )
- u_char which;
- void *data;
- int datalen;
- { switch (which)
- { case ALrsPauseSim: run_flag = 0; break;
- case ALrsResumeSim: run_flag = 1; break;
- default:
- { sprintf(mes[0], "_t_sim_runcontrol: unknown state request: %d",
- which);
- FEError(1);
- }
- break;
- }
- }
-
- #endif /* SOCKETS */
-
- /* THE CODE IN SHUTD IS NOT IS NOT FINISHED ,
- when I get acces to a pc, i will fully test it out ... */
-
- void shutd(sig,code,scp,addr)
- I32s sig,code;
- /* struct sigcontext *scp; */
- I32s *scp; /* DO NOT USE !!!!! */
- I8s *addr;
- {
- I8s answer;
- I32s tsz;
- I8s data[85];
-
- sprintf(mes[0],"\tTIERRA: trapped a signal! # %d @ %d",sig, InstExe.i);
- FEMessage(1);
- #ifdef SOCKETS
- sprintf(mes[0],"\tTIERRA: port %d",TS.port);
- FEMessage(1);
- #endif
- sprintf(mes[0],"\tTIERRA: trapped a signal! # %d @ %d",sig, InstExe.i);
- FEError(1);
- #ifdef SOCKETS
- sprintf(mes[0],"\tTIERRA: port %d",TS.port);
- FEError(1);
- #endif
- sprintf(mes[0],"Variable | siZe info | Save soup | save & Quit | ");
- sprintf(mes[1],"Exit | Continue | {v,z,s,q,e,c}");
- FEError(2);
- fgets(data,84,stdin);
- sscanf(data,"%c", &answer);
- if (answer == 'e') exit(-666);
- if (answer == 'v')
- {
- sprintf(mes[0],"To alter any global variable from soup_in, type\n");
- sprintf(mes[1],"the variable name (using proper case), a space,\n");
- sprintf(mes[2],"an equal sign, a space, and the new value.\n");
- sprintf(mes[3],"Use no space at start of line. Some examples:\n");
- sprintf(mes[4],"alive = 0");
- sprintf(mes[5],"DistProp = .6");
- sprintf(mes[6],"GenebankPath = newpath/");
- FEError(7);
- fgets(data,84,stdin);
- if (!GetAVar(data))
- { sprintf(mes[0],"Not a valid soup_in variable: %s", data);
- FEError(1);
- }
- }
-
- if (answer == 'z')
- {
- sprintf(mes[0],"Enter a size class ( eg: 80 ) to examine ");
- FEError(1);
- fgets(data,84,stdin);
- sscanf(data,"%d", &tsz);
- /* _t_query_size(tsz); */
- }
-
- if (answer == 's')
- { WriteSoup(1);
- sprintf(mes[0],"TIERRA Soup Written ...");
- FEError(1);
- }
- if (answer == 'q')
- { WriteSoup(1);
- sprintf(mes[0],"TIERRA Soup Written ...");
- FEError(1);
- exit(-333);
- }
- sprintf(mes[0],"Continuing from interupt...");
- FEError(1);
- }
-
- int main(argc,argv)
- int argc;
- char *argv[];
- {
-
- signal(SIGINT, shutd);
-
- if (argc > 1)
- { sprintf(soup_fn,"%s", argv[1]);
- }
- else
- {
- #ifdef IBM3090
- strcpy(soup_fn,"soup_in.io.d");
- #else
- strcpy(soup_fn,"soup_in");
- #endif
- }
- #ifdef SOCKETS
- setpgrp( 0, getpid() ); /* SHOULD BE DONE AS PART OF SV!!! */
-
- TInitialise( _t_myinitroutines, 1, argc, argv );
-
- TRegisterQueryhandler( ALrqMemStats, _t_memory_stats );
- TRegisterQueryhandler( ALrqQueryOrg, _t_query_org );
- /* TRegisterQueryhandler( ALrqQueryOrg, _t_query_size ); */
-
- TRegisterStatehandler( ALrsPauseSim, _t_sim_runcontrol );
- TRegisterStatehandler( ALrsResumeSim, _t_sim_runcontrol );
-
- #endif
-
- run_flag = 1;
- GetSoup();
- life();
- WriteSoup(1);
- return 0;
- }
-
- void life() /* doles out time slices and death */
- { while(InstExe.m < alive)
- { if ( run_flag == 1 )
- { (*slicer)();
- ReapCheck();
- }
- else
- sleep( 1 );
- #ifdef SOCKETS
- TCheckRequestQueue();
- #endif
- }
- }
-
- void TimeSlice(ci, size_slice)
- I32s ci, size_slice;
- { Pcells ce = cells + ci;
- I16s di; /* decoded instruction */
-
- ce->d.ib += size_slice;
- for(is.ts = ce->d.ib; is.ts > 0; )
- { di = FetchDecode(ci);
- (*id[di].execute)(ci);
- ce = cells + ci;
- IncrementIp(ci);
- SystemWork(ci);
- }
- }
-
- I16s FetchDecode(ci)
- I32s ci;
- { Pcells ce = cells + ci;
- I16s di;
-
- di = soup[ce->c.ip][ce->c.tr].inst;
- is.oip = ce->c.ip;
- (*id[di].parse)(ci);
- return di;
- }
-
- void IncrementIp(ci)
- I32s ci;
- { Pcells ce = cells + ci;
-
- ce->c.ip += is.iip;
- ce->c.ip = ad(ce->c.ip);
- ce->d.ib -= is.dib;
- is.ts -= is.dib;
- if (WatchExe)
- GenExExe(ci, is.oip);
- }
-
- void SystemWork(ci)
- I32s ci;
- {
- (cells + ci)->d.inst++;
- if((cells + ci)->c.fl)
- { (cells + ci)->d.flags++;
- if(!(cells + ci)->d.dm)
- UpRprIf(ci);
- }
- CountMutRate++;
- if(CountMutRate >= RateMut && RateMut)
- { mutate();
- TotMut++;
- CountMutRate = tlrand() % RateMut;
- }
- if(isolate) extract(extr);
- InstExe.i++;
- if(InstExe.i > 1000000L)
- { InstExe.i %= 1000000L; InstExe.m++;
- if(DropDead && (InstExe.m > LastDiv.m + DropDead))
- { sprintf(mes[0],
- "SystemWork: soup has died, saving system to disk");
- FEMessage(1);
- WriteSoup(1);
- exit(0);
- }
- if(!(InstExe.m % SaveFreq)) WriteSoup(0);
- plan();
- }
- }
-
- void mutate()
- { Ind i;
-
- i = tlrand() % SoupSize;
- mut_site(soup + i, tcrand() % 2);
- MutBookeep(i);
- }
-
- void mut_site(s, t)
- HpInst s;
- I8s t;
- { s[0][t].inst ^= (1 << (tirand() % (I16s) INSTBITNUM)); }
-
- void ReapCheck() /* kill some cells if necessary */
- { I32s i, t, dtime;
- struct event result;
-
- if(DistFreq < 0 || !reaped || (!DistNext.m && !DistNext.i)) return;
- dtime = SubEvent(&InstExe, &DistNext, &result);
- if(dtime > 0)
- { Disturb = InstExe;
- DistNext.m = DistNext.i = 0L;
- t = (I32s) (DistProp * (float) NumCells);
- if(t == NumCells)
- t--;
- for(i = 0; i < t; i++)
- reaper(0);
- }
- }
-
- void reaper(ex)
- I8s ex; /* is a creature executing now ? */
- { Pcells ce; /* cell to be reaped */
- I32s l_top, rtime; /* local TopReap */
- struct event result;
- Pcells nc; /* daughter of cell to be reaped */
- FpInst in;
- I32s i, j;
-
- if(ex && TopReap == ThisSlice)
- DownReaper(TopReap);
- if(ex && DistFreq > 0 && !DistNext.m && !DistNext.i)
- { rtime = SubEvent(&InstExe, &Disturb, &result);
- rtime = (I32s) (DistFreq * (float) rtime);
- DistNext = Disturb = InstExe;
- DistNext.m += rtime / 1000000L;
- DistNext.i += rtime % 1000000L;
- DistNext.m += DistNext.i / 1000000L;
- DistNext.i %= 1000000L;
- }
- if(NumCells == 1)
- { sprintf(mes[0],
- "Tierra reaper error 0, attempt to reap last creature");
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"core being saved");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- ce = cells + TopReap; l_top = TopReap;
- #ifdef ERROR
- if(!ce->ld || !NumCells || (!ce->mm.s && !ce->md.s))
- { sprintf(mes[0],
- "Tierra reaper error 1, attempt to reap non-existant cell");
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"core being saved");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- #endif
- if(ce->mm.s)
- {
- #ifdef ERROR
- if(ce->mm.p < 0 || ce->mm.p >= SoupSize)
- { sprintf(mes[0],
- "Tierra reaper error 2: attemp to deallocate main memory not in soup");
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"core being saved");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- #endif
- for(i = 0; i < ce->mm.s; i++)
- { in = soup + ad(ce->mm.p + i);
- for (j = 0; j < PLOIDY; j++)
- in[0][j].write = in[0][j].read = in[0][j].exec = 0;
- }
- MemDealloc(ce->mm.p,ce->mm.s);
- }
- if(ce->md.s)
- {
- #ifdef ERROR
- if(ce->md.p < 0 || ce->md.p >= SoupSize)
- { sprintf(mes[0],"Tierra reaper error 3: attemp to deallocate \
- daughter memory not in soup");
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"core being saved");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- #endif
- for(i = 0; i < ce->mm.s; i++)
- { in = soup + ad(ce->mm.p + i);
- for (j = 0; j < PLOIDY; j++)
- in[0][j].write = in[0][j].read = in[0][j].exec = 0;
- }
- if(ce->d.ni > -1) /* cleanup daughter cpu */
- { nc = cells + ce->d.ni;
- if(nc->d.is) /* cleanup daughter instruction pointer */
- RmvFrmSlicer(ce->d.ni);
- NumCells--;
- InitCell(ce->d.ni);
- }
- MemDealloc(ce->md.p,ce->md.s);
- }
- RmvFrmSlicer(l_top);
- RmvFrmReaper(l_top);
- ReapBookeep(l_top);
- /* InitCell(ci); done in ReapBookeep(ci); */
- }
-
- I32s SubEvent(event1, event2, result) /* subtract e2 from e1 */
- struct event *event1, *event2, *result;
- { result->m = event1->m - event2->m;
- result->m += (event1->i - event2->i) / 1000000L;
- result->i = (event1->i - event2->i) % 1000000L;
- if(result->m <= 0)
- return result->i + (result->m * 1000000L);
- if(result->i < 0)
- { --result->m;
- result->i += 1000000L;
- }
- return result->i + (result->m * 1000000L);
- }
-