ix269@sdccs6.UUCP (Jim) (07/29/84)
<> Here is an updated version of corewars, I am working to soon ingest the funhouse version into this so that everyone can have everything, so to speak. cut along the dotted line and extract with csh. cheers-- Jim --------------------------------------------------------------------- echo Extracting Makefile cat <<'poobahfig' > Makefile # # Makefile for "Core Wars" by Berry Kercheval (CopyRight 1984) # # based on A.K. Dewdeney's Game May 1984 SciAm # # ( UNIX is a trademark of AT&T ) HDRS= cw.h global.h machdep.h # std header, globals, Machine dependencies CFILES= main.c load.c do.c misc.c OBJS= main.o load.o do.o misc.o CFLAGS= -O -DUNIX_4_2 LFLAGS= -bchx -DUNIX_4_2 PRINT= lpr -Pexpress # this weeks print command, and flags corewars: $(HDRS) $(OBJS) @$(CC) $(CFLAGS) $(OBJS) -o corewars lint: lint $(LFLAGS) $(CFILES) > linterr count: wc -l $(CFILES) $(HDRS) print: $(PRINT) $(HDRS) $(CFILES) & 'poobahfig' echo Extracting cw.h cat <<'poobahfig' > cw.h /* * General defines for CoreWar, based on A.K. Dewdney's May 1984 * column in Scientific American. * * Copyright 1984, Berry Kercheval. All rights reserved. Permission * for distribution is granted provided no direct commercial * advantage is gained, and that this copyright notice appears * on all copies. * * many changes and amenditures by Jim of HCDE */ #define PROGRAM "corewars" /* the name of the program */ #define USAGE "[-cdlot] <prog1> [<prog2>]" /* Game variables */ #define BUFSIZE 256 /* program line size */ #define COMCHAR ';' /* comment character was a '/' */ #define DISTANCE 1000 /* programs at least this far apart */ #define MAXPROGSIZE 1000 /* maximum number of executable lines */ #define MEMSIZE 8000 /* the arena size */ #define TIMEOUT 120 /* playtime before 'DRAW', 120 cpu sec. */ /* Convenience defines */ #define EVER ;; /* for(EVER) */ #define FALSE 0 /* basic boolean value */ #define TRUE 1 /* basic boolean value */ #define TWENDASH "--------------------" /* 20 dashes */ #define iszero(m) (m.op == 0 && m.mode[A] == 0 && m.mode[B] == 0 \ && m.arg[A] == 0 && m.arg[B] == 0) /* determines if a memword is zeroed */ #define iswhite(c) (c == ' ' || c == '\t' || c == ',') /* white space, space which can be ignored in parsing */ /* * The Redcode Op-code values */ #define DAT 0 /* one operand, nonexecutable */ #define MOV 1 /* move contents of SRC to DST, A ==> B */ #define ADD 2 /* add contents of SRC to DST, A+B ==> B */ #define SUB 3 /* subtract contents of SRC from DST, A-B ==> B */ #define JMP 4 /* transfer control to DST, A ==> PC */ #define JMZ 5 /* JMP A if contents of B == 0 */ #define JMG 6 /* JMP A if contents of B > 0 */ #define DJZ 7 /* decrement B, JMP A if B == 0 */ #define CMP 8 /* if A != B skip next instruction */ #define TOPOP CMP /* the highest value opcode */ /* * Operand addressing mode values */ #define DIRECT 0 /* ' ' */ #define IMMEDIATE 1 /* '#' */ #define INDIRECT 2 /* '@' */ /* operand defines */ #define A 0 /* operand and mode A are the first array elements */ #define B 1 /* operand and mode B are the second array elements */ #define MAXOPERANDS 2 /* current limitation */ /* * Redcode Instruction Format: * * # # # #### #### <-- decimal digits * OP ModeA ModeB AAAA BBBB * * Max. instruction: 82,279,997,999 = 0x1 3245 222F * Too bad it won't fit in an unsigned long (2,147,483,648) * * TODO NOTE: OP and Modes could be packed into an unsigned int */ struct memword{ short op; /* the opcode */ short mode[MAXOPERANDS]; /* the addressing mode of operands */ int arg[MAXOPERANDS]; /* operands */ }; typedef struct memword memword; typedef long address; extern int errno, /* global error flag for perror */ error, /* global loadtime syntax error flag */ dumpflag, /* TRUE --> print post-mortem dump */ traceflag, /* TRUE --> print execution trace */ listflag, /* TRUE --> print listing of loaded program */ draw(), /* handle the timeout draw condition */ do_instruction(), /* do an instruction of Redcode */ do_add(), /* basic instructions */ do_cmp(), do_mov(), do_sub(); extern char *op_str[], /* string representations of opcodes */ mode_char[], /* addressing mode characters */ *pr_inst(); /* returns formatted string rep. of a pointer */ /* to a Redcode instruction suitable for %s */ extern address load(), /* Redcode program loader */ do_jmp(); /* do JMP operation */ extern memword mem[MEMSIZE]; /* the simulated memory 'arena' */ extern void clear_mem(), /* clear the game stack */ dump(), /* do a memory dump on the game stack */ usage(); /* print usage message andd exit */ 'poobahfig' echo Extracting global.h cat <<'poobahfig' > global.h /* * Globals for Core Wars a program for waring programs * * copyrights in main body * * Global values and initializations at beginning of main * program. */ char *op_str[] = /* strings for opcodes */ { "dat", /* 0 */ "mov", /* 1 */ "add", /* 2 */ "sub", /* 3 */ "jmp", /* 4 */ "jmz", /* 5 */ "jmg", /* 6 */ "djz", /* 7 */ "cmp", /* 8 */ 0 }; char mode_char[] = { ' ', '#', '@', 0 }; /* addressing mode char's */ int dumpflag = FALSE, /* TRUE --> print post-mortem dump */ traceflag = FALSE, /* TRUE --> print execution trace */ listflag = FALSE, /* TRUE --> print listing of loaded program */ error = FALSE; /* SYNTAX error during load */ char *pr_inst(); /* returns formatted string rep. of a pointer to a redcode instruction suitable for %s */ address load(); /* Redcode program loader */ memword mem[MEMSIZE]; /* the simulated memory 'arena' */ 'poobahfig' echo Extracting machdep.h cat <<'poobahfig' > machdep.h /* * copyright stuff in main program * * altered by: Jim of HCDE * * Unix is a trademark of AT&T */ #ifdef UNIX_4_2 /* 4.2 Unix C library */ # define RANDOM() random() /* a better version of rand() */ # define SRANDOM(x) srandom(x) /* the seed function accompli */ long random(); #else /* 4.1 Unix C library */ # define RANDOM() rand() /* use the lib or right your own */ # define SRANDOM(x) srand(x) /* the seed function companion */ int rand(); #endif /* alter SHIFT def to suit */ 'poobahfig' echo Extracting main.c cat <<'poobahfig' > main.c /* * "Core Wars" version 2.0 * * Programs battle for supremacy in a simulated arena! Based on A.K * Dewdeney's May 1984 column in Scientific American. * * Usage: * corewars [-cdlot] [prog1] [prog2] * * prog1 and prog2 must be ascii Redcode files. * * -c: Check mode, like a syntax checker. * * -d: print post-mortem memory Dump. * * -l: print Listings while loading the Redcode programs. * * -o: inform corewars that you have only one program * * -t: print verbose execution Trace * * This program assumes your C compiler supports structure assignment, * as well as many other goodies. * * Copyright 1984, Berry Kercheval. All rights reserved. Permission * for distribution is granted provided no direct commercial * advantage is gained, and that this copyright notice appears * on all copies. * * Revision and maintenance by Jim of HCDE * */ #include <errno.h> /* header file for perror */ #include <stdio.h> #include <signal.h> /* header for interrupt functions */ #include <sys/file.h> /* header for access() and c. */ #include "cw.h" /* program group header file */ #include "global.h" /* main program header file for globals */ #include "machdep.h" /* header file of machine or system dependencies */ main(argc, argv) int argc; char *argv[]; { register int j; /* utility index */ register char *pv; /* utility pointer */ int check, /* check flag for debug mode */ winner, /* who won? */ numfiles, /* number of files to load */ tmp; /* tmp variable */ char *file[2]; /* the two ascii Redcode program files */ register address pc_1, /* addresses of program starting points. */ pc_2; /* filled in by load() */ check = FALSE; numfiles = 2; while ( --argc > 0 && (*++argv)[0] == '-') for (pv = argv[0] + 1; *pv != NULL ;pv++) switch (*pv){ case 'c': check = TRUE; /* check but do not execute */ continue; case 'd': /* print memory dump at end */ dumpflag = TRUE; continue; case 'l': /* print listing at load-time */ listflag = TRUE; continue; case 'o': /* only one file */ check = TRUE; /* suppress execution */ numfiles = 1; continue; case 't': /* print execution trace */ traceflag = TRUE; continue; default: /* flag not yet implimented */ fprintf(stderr, "Unknown flag '-%c'\n", *pv); usage(); }; /* last two arguments should * be names of two redcode files */ if (argc < numfiles) /* usage file error, complain and exit */ usage(); if (argc > numfiles) { /* perhaps to many heros to let user in */ fprintf(stderr,"Error: extra unused command line arguments\n"); usage(); } SRANDOM(getpid()); /* set the seed for RANDOM() */ if (numfiles == 2) tmp = (int)(RANDOM()&01); /* random choice of first */ else tmp = 0; for (j = 0; j < numfiles ;j++) { if (access(*argv, R_OK) != NULL) { /* check read access */ perror(*argv); exit(-1); } file[abs(j - tmp)] = *(argv++); /* random first/second */ } clear_mem(); /* Clear the arena! Clear the arena! */ pc_1 = load(file[0]); /* load up program 1 */ if (numfiles == 2) pc_2 = load(file[1]); /* load up program 2 */ if (error) { /* no execution if there was an error */ printf("\n\nNot Executable, errors.\n"); exit(1); } if (check) { printf("\n\nLooks good to me.\n"); exit(0); } if (traceflag) { /* print trace header here, after possible */ /* load() listing */ printf("\n\t%-33.20s%-20s\n", file[0], file[1]); printf("%s%s%s%s\n",TWENDASH,TWENDASH,TWENDASH,TWENDASH); } (void)signal(SIGALRM, draw); /* set up for timeout, draw */ (void)alarm(TIMEOUT); /* give up after TIMEOUT seconds */ winner = execute(pc_1, pc_2); /* run the programs */ (void)alarm(0); /* turn off the alarm */ if (winner == 1 || winner == 2) {/* allocate blame */ printf("%s(%d) wins.\n", winner == 1 ? file[0] : file[1], winner); } else fprintf(stderr,"Error in execute -- bad value returned (%d)\n",winner); if (dumpflag) /* post-mortem dump if requested */ dump(); exit(0); /* Th-th-that's all folks */ } 'poobahfig' echo Extracting load.c cat <<'poobahfig' > load.c /* * load.c load the programs into the stack */ #include <ctype.h> #include <errno.h> #include <stdio.h> #include "cw.h" #include "machdep.h" /* * load() Load a Redcode file. load the file at a random place * in <mem>, not within <DISTANCE> of the other program. */ address load(filename) char *filename; { register int op, /* op-code value */ i; /* loop index */ register char *ptr, /* pointer within the line; used in parsing */ *ip; /* pointer within the line; used in parsing */ static address sp = 0; /* stack pointer for last program */ register address r; /* where to load current instruction */ char buf[BUFSIZE], /* line buffer */ *index(); address start; /* the returned start pc */ FILE *f; /* stream pointer to the input file */ if (sp != 0L) {/* if not the first */ r = sp + (address)(RANDOM() % (long)(abs((int)sp - MEMSIZE))); /* random spot in <mem> */ while (abs((int)(r - sp)) < DISTANCE) while(abs((int)(r - sp)) >= (MEMSIZE - MAXPROGSIZE)) r = sp + (address)(RANDOM() % (long)(abs((int)sp - MEMSIZE))); } else r = 0; sp = r; /* point to load start for this program */ start = 0; printf("\nloading %s at %d\n\n", filename, r); /* now load the file */ f = fopen(filename, "r"); if (f == NULL) { perror(filename); exit(-1); } /* * There now follows a moderately crufty ad-hoc redcode assembler. * It's not modular or very structured, but it seems to work, and * redcode was so simple I didn't want to use YACC or LEX or SSL */ while ( fgets(buf, BUFSIZE, f) != NULL ) {/* for each line in the file */ if (r > MEMSIZE) /* scroll around */ r %= MEMSIZE; if ((ptr = index(buf, COMCHAR)) != NULL)/* zap comment */ *ptr = '\0'; else if ((ptr = index(buf, '\n')) != NULL)/* zap trailing newline */ *ptr = '\0'; /* decode instruction */ ip = buf; /* start at the beginning of the line */ op = -1; /* Invalid op-code */ while (*ip && iswhite(*ip))/* skip leading whitespace */ ip++; if (ip == ptr || *ip == '\0') { /* it's a 'blank' line */ if (ptr != NULL) *ptr = COMCHAR; /* put comment back */ if (listflag) printf("%04d %s",r,buf); continue; /* go to next line */ } for (op = TOPOP; op >= 0 && strncmp(ip,op_str[op],3) != 0 ; op--) ; /* find that opcode */ if (op == -1) { /* opcode not yet implimented! */ fprintf(stderr,"SYNTAX ERROR: Bad opcode %s", buf); error = TRUE; } mem[r].op = op; /* load the operator into <mem> */ ip += 3; /* skip over mnemonic to rest of line */ while (*ip && iswhite(*ip))/* skip whitespace */ ip++; /* figure out addressing mode for operand A */ switch (op) { case JMP: if (*ip == '#') { fprintf(stderr,"ERROR: JMP, immediate mode operand\n"); error = TRUE; break; } if (*ip == '@') { ip++; mem[r].mode[A] = INDIRECT; } /* DIRECT mode is the initial condition */ mem[r].arg[A] = atoi(ip); while (mem[r].arg[A] < 0) /* scroll up */ mem[r].arg[A] += MEMSIZE; break; case DAT: if (*ip == '@') { fprintf(stderr,"ERROR: DAT, indirect mode operand\n"); error = TRUE; break; } if (*ip == '#') ip++; /* ignore this mode, argue later */ mem[r].arg[B] = atoi(ip); while (mem[r].arg[B] < 0) /* scroll up */ mem[r].arg[B] += MEMSIZE; break; default: for (i = A; i<= B ; i++) { if (!*ip) { fprintf(stderr,"ERROR: Two Arguments Required\n"); error = TRUE; break; /* break out of the loop */ } if (*ip == '#') { mem[r].mode[i] = IMMEDIATE; ip++; } else if (*ip == '@') { mem[r].mode[i] = INDIRECT; ip++; }; /* DIRECT mode is the default */ mem[r].arg[i] = atoi(ip); while (mem[r].arg[i] < 0) mem[r].arg[i] += MEMSIZE; while (*ip && !(iswhite(*ip))) ip++; while (*ip && iswhite(*ip)) ip++; }/* for */ break; }/* switch */ if (op != DAT && start == 0) start = r; /* first executable statement */ /* Do listing stuff... */ if (ptr != NULL) *ptr = COMCHAR; /* put comment back */ if (listflag) printf("%04d %s %s", r, pr_inst(mem[r]), buf); if (++r >= (sp + MAXPROGSIZE)){/* increment and check scroll */ fprintf(stderr,"Program %s hogged too much stack",filename); (void)exit(3); } } sp = r; if (listflag) (void)fflush(stdout); (void)fclose(f); return(start);/* return starting address */ } 'poobahfig' echo Extracting do.c cat <<'poobahfig' > do.c /* * do.c this module executes the opcodes */ #include <stdio.h> #include "cw.h" /* * execute() Execute the two loaded Redcode programs starting at * addresses pc1 and pc2 until one executes an illegal * instruction. Return the winner. */ execute(pc1, pc2) register address pc1, pc2; { printf("executing: pc1 = %d, pc2 = %d\n\n", pc1, pc2); for (EVER){ if ((pc1 = do_instruction(pc1)) < 0)/* Execution error */ return(2); if (pc1 >= MEMSIZE) /* scroll around */ pc1 %= MEMSIZE; if (traceflag) /* separate the two instruction traces */ printf("\t||\t"); if ((pc2 = do_instruction(pc2)) < 0)/* Execution error */ return(1); if (pc2 >= MEMSIZE) pc2 %= MEMSIZE; /* do_instruction prints a trace, which needs to have a newline here */ if (traceflag) putchar('\n'); } } /* * do_instruction() interprets one instruction at <addr>, and * returns the address of next instruction to * be executed or -1 if illegal instruction. */ do_instruction(addr) register address addr; { if (traceflag) printf("@ %04d", addr); (void)fflush(stdout); if (traceflag) /* a little different than pr_inst */ printf(" %s %c%-4d, %c%-4d", op_str[mem[addr].op], mode_char[mem[addr].mode[A]], mem[addr].arg[A], mode_char[mem[addr].mode[B]], mem[addr].arg[B]); (void)fflush(stdout); switch (mem[addr].op) { case MOV: if (do_mov(addr) == 0) return(++addr); else return(-1); case ADD: if (do_add(addr) == 0) return(++addr); else return(-1); case SUB: if (do_sub(addr) == 0) return(++addr); else return(-1); case JMP: return(do_jmp(addr)); case JMZ: switch (mem[addr].mode[B]) { case INDIRECT: if (mem[mem[addr].arg[B]].arg[B] == 0) return(do_jmp(addr)); else return(++addr); case DIRECT: if (mem[addr + mem[addr].arg[B]].arg[B] == 0) return(do_jmp(addr)); else return(++addr); default: /* IMMEDIATE */ if (mem[addr].arg[B] == 0) return(do_jmp(addr)); else return(++addr); } case JMG: switch (mem[addr].mode[B]) { case INDIRECT: if (mem[mem[addr].arg[B]].arg[B] > 0) return(do_jmp(addr)); else return(++addr); case DIRECT: if (mem[addr + mem[addr].arg[B]].arg[B] > 0) return(do_jmp(addr)); else return(++addr); default: /* IMMEDIATE */ if (mem[addr].arg[B] > 0) return(do_jmp(addr)); else return(++addr); } case DJZ: switch (mem[addr].mode[B]) { case INDIRECT: if (--mem[mem[addr].arg[B]].arg[B] == 0) return(do_jmp(addr)); else return(++addr); case DIRECT: if (--mem[addr + mem[addr].arg[B]].arg[B] == 0) return(do_jmp(addr)); else return(++addr); default: /* IMMEDIATE */ if (--mem[addr].arg[B] == 0) return(do_jmp(addr)); else return(++addr); } case CMP: return(addr + do_cmp(addr)); case DAT: default: printf("\nIllegal instruction %s @ %d\n", pr_inst(mem[addr]), addr); return(-1); } } /* * do_add() adds to operands, returns 0 on success, * 1 on error. */ do_add(addr) register address addr; { register address src, dest; memword data; data.op = 0; data.mode[A] = data.mode[B] = 0; data.arg[A] = data.arg[B] = 0; switch (mem[addr].mode[A]) { case IMMEDIATE: data.arg[B] = mem[addr].arg[A]; break; case DIRECT: data = mem[(addr + mem[addr].arg[A]) % MEMSIZE]; break; case INDIRECT: src = mem[(addr + mem[addr].arg[A]) % MEMSIZE].arg[B]; data = mem[(src + addr + mem[addr].arg[A]) % MEMSIZE]; break; default: /* ERROR */ fprintf(stderr,"do_add: illegal addressing mode\n"); return(1); } switch (mem[addr].mode[B]) { case IMMEDIATE: /* error */ fprintf(stderr,"do_add: illegal immediate destination\n"); return(1); case DIRECT: mem[(addr + mem[addr].arg[B]) % MEMSIZE].arg[B] += data.arg[B]; break; case INDIRECT: dest = mem[(addr + mem[addr].arg[B]) % MEMSIZE].arg[B]; mem[(dest + addr + mem[addr].arg[B]) % MEMSIZE].arg[B] += data.arg[B]; break; default: /* ERROR */ fprintf(stderr,"do_add: illegal addressing mode\n"); return(1); } return(0); /* sucessful execution */ } /* * do_cmp() compare a and b, return 1 if same, 2 if different */ do_cmp(addr) register address addr; { register address src, dest; memword data; data.op = 0; data.mode[A] = data.mode[B] = 0; data.arg[A] = data.arg[B] = 0; switch (mem[addr].mode[A]) { case IMMEDIATE: data.arg[B] = mem[addr].arg[A]; break; case DIRECT: data = mem[(addr + mem[addr].arg[A]) % MEMSIZE]; break; case INDIRECT: src = mem[(addr + mem[addr].arg[A]) % MEMSIZE].arg[B]; data = mem[(src + addr + mem[addr].arg[A]) % MEMSIZE]; break; default: /* ERROR */ fprintf(stderr,"do_cmp: illegal addressing mode\n"); return(1); } switch (mem[addr].mode[B]) { case IMMEDIATE: /* error */ if (data.arg[B] == mem[addr].arg[B]) return(1); else return(2); case DIRECT: if (data.arg[B] == mem[(addr + mem[addr].arg[B]) % MEMSIZE].arg[B]) return(1); else return(2); case INDIRECT: dest = mem[(addr + mem[addr].arg[B]) % MEMSIZE].arg[B]; if (data.arg[B] == mem[(dest+addr+mem[addr].arg[B]) % MEMSIZE].arg[B]) return(1); else return(2); default: /* ERROR */ fprintf(stderr,"do_cmp: illegal addressing mode\n"); return(1); } } /* * do_jmp() returns the address jumped to */ address do_jmp(addr) address addr; { switch (mem[addr].mode[A]) { case DIRECT: return(addr + mem[addr].arg[A]); default: /* INDIRECT */ return(addr + mem[mem[addr].arg[A]].arg[B]); } } /* * do_mov() moves operand A to operand B returning * 0 on success or 1 on error. */ do_mov(addr) register address addr; { register address src, dest; memword data; data.op = 0; data.mode[A] = data.mode[B] = 0; data.arg[A] = data.arg[B] = 0; switch (mem[addr].mode[A]) { case IMMEDIATE: data.arg[B] = mem[addr].arg[A]; break; case DIRECT: data = mem[(addr + mem[addr].arg[A]) % MEMSIZE]; break; case INDIRECT: src = mem[(addr + mem[addr].arg[A]) % MEMSIZE].arg[B]; data = mem[(src + addr + mem[addr].arg[A]) % MEMSIZE]; break; default: /* ERROR */ fprintf(stderr,"do_mov: illegal addressing mode\n"); return(1); } switch (mem[addr].mode[B]) { case IMMEDIATE: /* error */ fprintf(stderr,"do_mov: illegal immediate destination\n"); return(1); case DIRECT: mem[(addr + mem[addr].arg[B]) % MEMSIZE] = data; break; case INDIRECT: dest = mem[(addr + mem[addr].arg[B]) % MEMSIZE].arg[B]; mem[(dest + addr + mem[addr].arg[B]) % MEMSIZE] = data; break; default: /* ERROR */ fprintf(stderr,"do_mov: illegal addressing mode\n"); return(1); } return(0); /* sucessful execution */ } /* * do_sub() subtracts operand A from B putting the * result in B. returning 0 on success or * 1 on error. */ do_sub(addr) register address addr; { register address src, dest; memword data; data.op = 0; data.mode[A] = data.mode[B] = 0; data.arg[A] = data.arg[B] = 0; switch (mem[addr].mode[A]) { case IMMEDIATE: data.arg[B] = mem[addr].arg[A]; break; case DIRECT: data = mem[(addr + mem[addr].arg[A]) % MEMSIZE]; break; case INDIRECT: src = mem[(addr + mem[addr].arg[A]) % MEMSIZE].arg[B]; data = mem[(src + addr + mem[addr].arg[A]) % MEMSIZE]; break; default: /* ERROR */ fprintf(stderr,"do_sub: illegal addressing mode\n"); return(1); } switch (mem[addr].mode[B]) { case IMMEDIATE: /* error */ fprintf(stderr,"do_sub: illegal immediate destination\n"); return(1); case DIRECT: mem[(addr + mem[addr].arg[B]) % MEMSIZE].arg[B] -= data.arg[B]; break; case INDIRECT: dest = mem[(addr + mem[addr].arg[B]) % MEMSIZE].arg[B]; mem[(dest + addr + mem[addr].arg[B]) % MEMSIZE].arg[B] -= data.arg[B]; break; default: /* ERROR */ fprintf(stderr,"do_sub: illegal addressing mode\n"); return(1); } return(0); /* sucessful execution */ } 'poobahfig' echo Extracting misc.c cat <<'poobahfig' > misc.c /* * Misc.c all sorts of miscellaneus goodies */ #include <stdio.h> #include "cw.h" /* * clear_mem() clear the simulated arena */ void clear_mem() { register address i; for (i = 0; i < MEMSIZE; i++) { mem[i].op = 0; mem[i].mode[A] = 0; mem[i].mode[B] = 0; mem[i].arg[A] = 0; mem[i].arg[B] = 0; } } /* * dump() dumps the stack without dumping thousands of 0's */ void dump() { register address r; register int flag = 0; printf("\n\n---------- MEMORY DUMP -------------\n"); for (r = 0; r < MEMSIZE; r++) { if (iszero(mem[r])) { switch (flag) { case 0: continue; /* next r, don't dump thousands of 0's */ case 1: printf(" *\n"); flag = 0; break; default: printf("%05d 000 0000 0000\n", r); flag = 1; } } else { printf("%05d %s\n", r, pr_inst(mem[r])); flag = 2; } } } /* * draw() take care of tie conditions, timeing out */ int draw() { printf("\nBattle is a DRAW -- timed out after %d seconds\n", TIMEOUT); if (dumpflag) dump(); (void)exit(0); } /* * *pr_inst() returns a formatted character buffer representing * the corewar memory element x */ char *pr_inst(x) memword x; { char buf[128]; (void)sprintf(buf, "%3s %1c%04d %c%04d", op_str[x.op], mode_char[x.mode[A]], x.arg[A], mode_char[x.mode[B]], x.arg[B]); return(buf); } /* * usage() usage message */ void usage() { fprintf(stderr,"Usage: %s %s\n", PROGRAM, USAGE); exit(-1); } 'poobahfig' echo Extracting dwarf cat <<'poobahfig' > dwarf dat -1 ; target for dwarf's little 0 rocks add #5, -1 ; increase the target mov #0, @-2 ; bombs away! jmp -2 ; loop back 'poobahfig' echo Extracting gemini cat <<'poobahfig' > gemini ; Gemini ; copies itself ahead ; dat 0 ; pointer to source address dat 99 ; pointer to destination address mov @-2, @-1 ; copy source to destination cmp -3, #9 ; if all 10 lines have been copied jmp 4 ; then leave the loop add #1, -5 ; else, increment the source address add #1, -5 ; and the destination address jmp -5 ; and return to the loop mov #99, 93 ; restore the starting destination address jmp 93 ; jump to the new copy 'poobahfig' echo Extracting imp cat <<'poobahfig' > imp mov 0, 1 ; copy myself one instruction ahead 'poobahfig' echo Extracting wcount cat <<'poobahfig' > wcount wc -l main.c load.c do.c misc.c cw.h global.h machdep.h 154 main.c 193 load.c 361 do.c 96 misc.c 120 cw.h 37 global.h 18 machdep.h 979 total 'poobahfig' echo Extracting backz cat <<'poobahfig' > backz dat -1 mov 1 @-1 djz 0 -2 jmp -2 'poobahfig' echo Extracting bigfoot cat <<'poobahfig' > bigfoot dat 0 ;pointer to source address dat 1752 ;pointer to destination address mov @-2, @-1 ;copy source to destination cmp -3, #9 ;if all 10 lines have been copied... jmp 4 ;...then leave the loop add #1, -5 ;otherwise, increment the source address add #1, -5 ;...and the destination address jmp -5 ;...and return to the loop mov #1752,1746 ;restore the starting destination address jmp 1746 ;jump to the new copy 'poobahfig' echo Extracting doc.6 cat <<'poobahfig' > doc.6 .TH COREWARS 6 .UC 4 .SH NAME corewars \- battling programs .SH SYNOPSIS .B corewars [ .B \-cdlot ] prog1 [prog2] .br .SH DESCRIPTION .I Corewar loads .I prog1 and .I prog2 into the simulated memory arena and executes instructions for each in turn until one encounters an illegal instruction, at which point the other is declared the winner. If neither has won in two minutes, the match is declared a draw. .PP .I Corewars is based on A.K Dewdeney's May 1984 column in Scientific American. .PP .B Options .PP .B \-c suppress execution of the programs, allowing the loader to check for syntax errors. .PP .B \-d causes a post mortem memory dump to be written on the standard output. .PP .B \-l causes a listing of the generated code to be written on the standard output when each file is loaded. .PP .B \-o informs corewars that only one program will be loaded, this sets the .B \-c flag. .PP .B \-t causes an instruction execution trace to be written on the standard output. .SH AUTHORS Berry Kercheval (ihnp4!zehntel!berry) tailor: Jim of HCDE .PP .SH FILES /usr/games/corewars Default save file .SH BUGS .PP None yet known 'poobahfig'