Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site harpo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!harpo!db From: d...@harpo.UUCP (dan becker) Newsgroups: net.games Subject: core wars Message-ID: <2279@harpo.UUCP> Date: Fri, 11-May-84 08:56:21 EDT Article-I.D.: harpo.2279 Posted: Fri May 11 08:56:21 1984 Date-Received: Sat, 12-May-84 10:42:44 EDT Organization: AT&T Bell Laboratories, Whippany Lines: 11 There was an article in the Scientific American by A. K. Dewdney recently that described a game called Core War, where two programs written by the combatting programmers try to trash each other. The last program still standing (executing valid instructions) wins. Has anybody out there seen it? Have a copy of the game running on UNIX? We plan on putting one together if nobody has one they can share, but I'd be interested in others experiences/hints/bells/whistles anyway. thanks. dan becker harpo!db or harpo!groucho!dcb ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site dartvax.UUCP Path: utzoo!watmath!clyde!akgua!mcnc!decvax!dartvax!davidk From: dav...@dartvax.UUCP (David C. Kovar) Newsgroups: net.games Subject: Re: core wars Message-ID: <1546@dartvax.UUCP> Date: Sat, 12-May-84 19:41:09 EDT Article-I.D.: dartvax.1546 Posted: Sat May 12 19:41:09 1984 Date-Received: Sun, 13-May-84 10:19:11 EDT References: <2279@harpo.UUCP> Organization: Dartmouth College Lines: 17 Sounds like machine language animals to me. The simplest one just runs up (or down) memory. This can be done with one inststruction on our Honeywell, something like jump decrement PC. Of course, they can be far more complex. With the advent of memory protection, animals died out for the most part, but before that they roamed free. I've heard stories of operating systems that took potshots at memory hoping to kill animals running loose... -- David C. Kovar USNET: {linus|decvax|cornell|astrovax}!dartvax!davidk ARPA: davidk%dartmouth@csnet-relay CSNET: davidk@dartmouth "The difficult we did yesterday, the impossible we are doing now." ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: utzoo!watmath!jsgray From: jsg...@watmath.UUCP (Jan Gray) Newsgroups: net.games Subject: Re: core wars Message-ID: <7737@watmath.UUCP> Date: Sun, 13-May-84 19:00:24 EDT Article-I.D.: watmath.7737 Posted: Sun May 13 19:00:24 1984 Date-Received: Mon, 14-May-84 01:17:31 EDT References: <2279@harpo.UUCP> Organization: U of Waterloo, Ontario Lines: 8 Perhaps some kind hearted person could post the darwin(6) manual page from version 6 UNIX (or before?)? Or a brief description? Thanks, Jan Gray (jsg...@watmath.UUCP) University of Waterloo (519) 885-1211 x2730 "I'll say, Jan Gray is not the morning's eye, 'Tis but the pale reflex of Cynthia's brow..." ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 exptools 1/6/84; site ihnss.UUCP Path: utzoo!watmath!clyde!akgua!mcnc!decvax!harpo!ulysses!mhuxl!ihnp4!ihnss!knudsen From: knud...@ihnss.UUCP Newsgroups: net.games Subject: Re: Core Wars & potshots Message-ID: <2066@ihnss.UUCP> Date: Mon, 14-May-84 13:19:27 EDT Article-I.D.: ihnss.2066 Posted: Mon May 14 13:19:27 1984 Date-Received: Wed, 16-May-84 03:07:23 EDT Organization: AT&T Bell Labs, Naperville, IL Lines: 9 "...some operating systems would take potshots in the hopes of killing animals running wild." Very interesting. Zapping random bytes in unknown code will most likely halt it, but there's always the possibility of MUTATING it into something even worse! Maybe now it eats the OS instead of other user programs. Sorta like dropping a low-yield dirty tactical nuke on the other guy's recombinant DNA germ warfare lab..... mike k ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site stat-l Path: utzoo!watmath!clyde!burl!mgnetp!ihnp4!inuxc!pur-ee!CS-Mordred!Pucc-H:Pucc-I:Stat-L:ab3 From: ab3@stat-l (Rsk the Wombat) Newsgroups: net.misc Subject: Core War Message-ID: <56@stat-l> Date: Thu, 17-May-84 16:48:20 EDT Article-I.D.: stat-l.56 Posted: Thu May 17 16:48:20 1984 Date-Received: Sat, 19-May-84 00:41:40 EDT Organization: Pucc Unix Systems Group Lines: 13 Has anyone out there implmented Core War (see the May Scientific American) on Unix? For general info: Core War is a computer game wherein two programs sharing the same memory area attempt to corrupt each other. Strategies range from the simple (write 0's every few bytes throughout memory, trying to hit the other program) to the complex (self-copying programs which check themselves for damage). -- Rsk the Wombat UUCP: { allegra, decvax, ihnp4, harpo, teklabs, ucbvax } !pur-ee!rsk { cornell, eagle, hplabs, ittvax, lanl-a, ncrday } !purdue!rsk ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site utcsstat.UUCP Path: utzoo!utcsstat!cobb From: c...@utcsstat.UUCP (Ozan Yigit) Newsgroups: net.games Subject: man (?) page for DARWIN Message-ID: <1938@utcsstat.UUCP> Date: Sun, 27-May-84 18:14:11 EDT Article-I.D.: utcsstat.1938 Posted: Sun May 27 18:14:11 1984 Date-Received: Sun, 27-May-84 20:00:18 EDT Organization: U. of Toronto, Canada Lines: 32 Gee, I think it will be difficult to find a man page for DARWIN. The article referred in core wars article was written in 1972, which was about a re-write of the game, which really was written in 1962, on a IBM 7090. It is also clear, from the description of DARWIN, that it is probably not as exciting as core wars, although it does contain some neat ideas. The significant difference between the two games is that DARWIN uses a set of "umpire" calls for examining a piece of memory, kill an organism at a particular address and obtain some more memory, namely PROBE, KILL and CLAIM. Under DARWIN, each organism has a protected code region. The game does not use a scheduler. Instead, control is only transferred from one organism to another only when a PROBE call results in a protected area of the other organism. (sort of MEMORY ACCESS VIOLATION). The critical problem with the darwin (at the time) was the loading of the organisms into the main memory in some random fashion, to obtain a UNIQUE game. There are a long list of rules for DARWIN. I could type them in if there is enough interest across the network. Commentary: DARWIN is only significant because it uses the WHOLE system as its arena. Most of its ideas are incorporated into core-wars, except that in DARWIN, one can use any programming language for the coding of an organism. OZ (wizard of something or another) Dept. of Computer Science York University decvax!utzoo!yetti!ozan decvax!utzoo!utcsstat!cobb ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site zinfandel.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxl!ihnp4!zehntel!zinfandel!berry From: be...@zinfandel.UUCP (Berry Kercheval) Newsgroups: net.sources Subject: Corewar program source Message-ID: <107@zinfandel.UUCP> Date: Thu, 28-Jun-84 17:39:55 EDT Article-I.D.: zinfande.107 Posted: Thu Jun 28 17:39:55 1984 Date-Received: Sun, 1-Jul-84 03:32:41 EDT Organization: Zehntel Inc., Walnut Creek, CA Lines: 807 Here is a program that implements 'corewar' as described in A.K.Dewdney's Scientific American column of May, 1984. I would be interested in collecting any battle programs anyone might develop. For those unfamiliar with the game , this program simulates two programs in a simple computer's memory, battling for survival. The simulator alternately executes instructions from each until a time limit expires, or an illegal instruction is encountered. Time limit implies a draw; the program with the illegal instruction loses. Berry Kercheval Zehntel Inc. (ihnp4!zehntel!zinfandel!berry) (415)932-6900 ======= Cut Here ======= #! /bin/csh -f #extract this file with csh echo extracting corewar.6 cat <<'KerchDrivOrnCo' > corewar.6 .TH COREWAR 6 .UC 4 .SH NAME corewar \- battling programs .SH SYNOPSIS .B corewar [ .B \-l ] [ .B \-t ] [ .B \-d ] prog1 prog2 .br .SH DESCRIPTION .I Corewar loads .I file1 and .I file2 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 Corewar is based on A.K Dewdeney's May 1984 column in Scientific American. .PP The .B \-l option causes a listing of the generated code to be written on the standard output while each file is loaded. .PP The option .B \-t causes an instruction execution trace to be written on the standard output. .PP The option .B \-d causes a post mortem memory dump to be writenm on the standard output. .SH AUTHOR Berry Kercheval (ihnp4!zehntel!berry) 'KerchDrivOrnCo' echo extracting corewar.c cat <<'KerchDrivOrnCo' > corewar.c /* * CoreWar * * Programs battle for supremacy in a simulated arena! Based on A.K * Dewdeney's May 1984 column in Scientific American. * * Usage: * corewar [-l][-d][-t] prog1 prog2 * prog1 and prog2 must be ascii redcode files. * -l: print listing while loading the redcode programs. * -t: print verbose execution trace * -d: print post-mortem memory dump. * * This program assumes your C compiler supports structure assignment. * * 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. */ #include #include #include "corewar.h" memword mem[MEMSIZE]; /* the simulated memory 'arena' */ char *pr_inst(); /* returns formatted string representation of a * redcode instruction suitable for %s */ int dumpflag = 0; /* TRUE --> print post-mortem dump */ int traceflag = 0; /* TRUE --> print execution trace */ int listflag = 0; /* TRUE --> print listing of loaded program */ main (argc, argv) int argc; char **argv; { char *file1 = NULL; char *file2 = NULL; address pc_1, pc_2; /* addresses of program starting points. * filled in by load() */ address load(); /* loads a file */ int winner; /* who won? */ int draw(); /* what happens if we time out */ while (*++argv && **argv == '-') switch (*++*argv) { case 'l': /* print listing at load-time */ listflag = 1; break; case 'd': /* print memory dump at end */ dumpflag = 1; break; case 't': /* print execution trace */ traceflag = 1; break; default: /* huh??? */ printf("Unknown flag '%s'\n",*argv); break; } /* now the last two arguments should be names of two redcode files */ if (*argv) { if ( access (*argv, 4) != 0) { /* check read access */ perror(*argv); exit (-1); } file1 = *argv; } else { printf ("Usage: corewar prog1 prog2\n"); exit(-1); } argv++; if (*argv) { if ( access (*argv, 4) != 0) { /* check read access */ perror(*argv); exit (-1); } file2 = *argv; } else { printf ("Usage: corewar prog1 prog2\n"); exit(-1); } srand(getpid()); clear_mem(); /* Clear the arena! Clear the arena! */ pc_1 = load( -1, file1); /* load file1 anywhere */ pc_2 = load(pc_1, file2); /* load file2 1000 away from pc_1 */ signal ( SIGALRM, draw); /* set up for timeout */ alarm (TIMEOUT); /* give up after TIMEOUT seconds */ if(traceflag) /* print trace header here because * we know the filenames here */ { printf (" %10s %10s\n", file1, file2); printf("-----------------------------------------------------------\n"); } winner = execute(pc_1, pc_2); /* run the programs */ alarm(0); /* turn off the alarm */ switch (winner) /* allocate blame */ { case 0: printf ("DRAW!\n"); break; case 1: case 2: printf ("%s(%d) wins.\n", winner==1?file1:file2,winner); break; default: printf ("Error in execute -- illegal return value\n"); } if (dumpflag) /* post-mortem dump if requested */ dump(); exit(0); /* Th-th-that's all folks */ } /* * clear_mem: clear the simulated memory */ clear_mem() { address i; for ( i=0 ; i < MEMSIZE; i++ ) { mem[i].op = 0; mem[i].a_mode = 0; mem[i].b_mode = 0; mem[i].a = 0; mem[i].b = 0; } } /* * load: * Load a redcode file. If where is not -1, place the loaded file * at a random place im mem, NOT WITHIN 'DISTANCE' of 'where' * If where IS -1, put the code anywhere. */ address load(where, filename) address where; char *filename; { address r; /* where to load current instruction */ FILE *f; /* stream pointer for input file */ char buf[256]; /* line buffer */ char *ptr; /* pointer into the line; used in parsing */ char *ip; /* pointer into the line; used in parsing */ char *index(); char error; /* error flag printed at beginning of each * listing line; currently either ' ' or 'E' */ address start; /* address of first executable instruction */ int op; /* op-code value */ int i; /* counter for for loops */ /* select starting address */ start = 0; r = (rand() >> 12) % MEMSIZE; /* 4.1 rand() sucks */ if (where != -1) { /* second program must be at least DISTANCE addresses from * first; I just make their load-points DISTANCE apart */ while ( abs (r - where) < DISTANCE ) r = (rand() >> 12) % MEMSIZE; } printf ("loading %s at %d\n", filename, r); /* now do load */ 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, 256, f) != NULL) /* for each line in the file */ { error = ' '; /* no error yet */ /* zap trailing newline to make listing generation easier */ if ( (ptr = index(buf, '\n')) != NULL ) *ptr = '\0'; /* zap comment */ if ( (ptr = index(buf, '/')) != NULL ) *ptr = '\0'; /* decode instruction */ ip = buf; /* start at the beginning of the line */ op = -1; /* Invalid op-code */ /* skip leading whitespace */ while ( *ip && (*ip == ' ' || *ip == 011)) ip++; if ( ip == ptr ) { /* it's a 'blank' line */ if ( ptr != NULL ) *ptr = '/'; /* put comment back */ if (listflag) printf ("%c '%s'\n", error, buf); break; } for ( i = 0; i <= CMP; i++) /* CMP is highest op-code */ { if ( strncmp(ip, op_str[i], 3) == 0){ op = i; break; } } if ( op == -1 ) /* didn't find it! */ { printf ("SYNTAX ERROR '%s' -- Bad opcode\n", buf); error = 'E'; } mem[r].op = op; ip += 3; /* skip over opcode mnemonic */ /* skip whitespace */ while ( *ip && (*ip == ' ' || *ip == 011)) ip++; /* figure out addressing mode for operand A */ if ( op != DAT ) { /* DAT has only B operand */ if ( *ip == '#'){ mem[r].a_mode = IMMEDIATE; ip++; } else if ( *ip == '@') { mem[r].a_mode = INDIRECT; ip++; } else { mem[r].a_mode = DIRECT; } mem[r].a = atoi ( ip ); if ( mem[r].a < 0 ) mem[r].a += MEMSIZE; while ( *ip && (*ip != ' ' && *ip != 011)) ip++; } /* skip whitespace */ while ( *ip && ( *ip == ' ' || *ip == 011)) ip++; if ( op != JMP ) { /* JMP has only A operand */ if ( *ip == '#'){ mem[r].b_mode = IMMEDIATE; ip++; } else if ( *ip == '@') { mem[r].b_mode = INDIRECT; ip++; } else { mem[r].b_mode = DIRECT; } mem[r].b = atoi ( ip ); if ( mem[r].b < 0 ) mem[r].b += MEMSIZE; } /* check for start of executable code */ if ( op != DAT && start == 0) start = r; /* DAT has zero modes... */ if ( op == DAT ) mem[r].b_mode = mem[r].a_mode = 0; /* Do listing stuff... */ if ( ptr != NULL ) *ptr = '/'; /* put comment back */ if (listflag) printf ("%c%4d %s '%s'\n", error, r, pr_inst(mem[r]), buf); r++; /* Advance to next memory location */ if ( r > MEMSIZE ) r = r % MEMSIZE; } if (listflag) fflush (stdout ); fclose (f); /* return starting address */ return start; } /* * Execute the two loaded Redcode programs starting at addresses p1 and p2 * until one executes an illegal instruction */ execute (p1, p2) address p1; address p2; { printf ("executing: p1 = %d, p2 = %d\n", p1, p2); for(;;) { if ( -1 == (p1 = do_instruction(p1))) return 1; if (p1 >= MEMSIZE) p1 = p1 % MEMSIZE; /* separate the two instruction traces */ if (traceflag) printf (" || "); if ( -1 == (p2 = do_instruction(p2))) return 1; if (p2 >= MEMSIZE) p2 = p2 % MEMSIZE; /* do_instruction prints a trace, which needs to be * 'newlined' here */ if(traceflag) printf ("\n"); } } /* * interpret one instruction at addr; return address of next instruction to * be executed, or -1 if it was an illegal instruction */ do_instruction(addr) address addr; { memword inst; if(traceflag) printf ("@ %d", addr); fflush (stdout); /* fetch instruction */ inst = mem[addr]; if (traceflag) printf (" %s %c%4d, %c%4d ", op_str[inst.op], mode_char[inst.a_mode], inst.a, mode_char[inst.b_mode], inst.b); fflush (stdout); switch ( inst.op ) { case MOV: if (do_mov(addr, inst)) return -1; else return addr + 1; case ADD: if (do_add(addr, inst)) return -1; else return addr + 1; case SUB: if (do_sub(addr, inst)) return -1; else return addr + 1; case JMP: return (addr + inst.a)%MEMSIZE; case JMZ: if ( mem[inst.b].op == DAT && mem[inst.b].b == 0 ) return (addr + inst.a)%MEMSIZE; else return (addr + 1)%MEMSIZE; case JMG: if ( mem[inst.b].op == DAT && mem[inst.b].b > 0 ) return (addr + inst.a)%MEMSIZE; else return (addr + 1) % MEMSIZE; case DJZ: mem[inst.b].b -= 1; if ( mem[inst.b].b == 0 ) return (addr + inst.a) % MEMSIZE; else return (addr + 1) % MEMSIZE; case CMP: return addr + do_cmp(addr, inst); case DAT: default: printf ("Illegal instruction %s @ %d\n", pr_inst(inst), addr); return -1; } } do_mov(addr, inst) address addr; memword inst; { address source, destination; memword data; data.op = 0; data.a_mode = data.b_mode = 0; data.a = data.b = 0; switch (inst.a_mode) { case IMMEDIATE: data.b = inst.a; break; case DIRECT: data = mem[(addr + inst.a) % MEMSIZE]; break; case INDIRECT: source = mem[(addr + inst.a) % MEMSIZE].b; data = mem[(source + addr + inst.a) % MEMSIZE]; break; default: /* ERROR */ printf ("do_mov: illegal addressing mode\n"); return 1; } switch (inst.b_mode) { case IMMEDIATE: /* error */ printf ("do_mov: illegal immediate destination\n"); return 1; case DIRECT: mem[(addr + inst.b) % MEMSIZE] = data; break; case INDIRECT: destination = mem[(addr + inst.b) % MEMSIZE].b; mem[(destination + addr + inst.b) % MEMSIZE] = data; break; default: /* ERROR */ printf ("do_mov: illegal addressing mode\n"); return 1; } return 0; } /* * CMP: compare a and b, return 1 if same, 2 if different */ do_cmp(addr, inst) address addr; memword inst; { address source, destination; memword data; data.op = 0; data.a_mode = data.b_mode = 0; data.a = data.b = 0; switch (inst.a_mode) { case IMMEDIATE: data.b = inst.a; break; case DIRECT: data = mem[(addr + inst.a) % MEMSIZE]; break; case INDIRECT: source = mem[(addr + inst.a) % MEMSIZE].b; data = mem[(source + addr + inst.a) % MEMSIZE]; break; default: /* ERROR */ printf ("do_add: illegal addressing mode\n"); return 1; } switch (inst.b_mode) { case IMMEDIATE: /* error */ if (data.a == inst.b) return 1; else return 2; case DIRECT: if ( data.a == mem[(addr + inst.b) % MEMSIZE].b) return 1; else return 2; case INDIRECT: destination = mem[(addr + inst.b) % MEMSIZE].b; if(data.b == mem[(destination+addr + inst.b)%MEMSIZE].b) return 1; else return 2; default: /* ERROR */ printf ("do_add: illegal addressing mode\n"); return 1; } } do_sub(addr, inst) address addr; memword inst; { address source, destination; memword data; data.op = 0; data.a_mode = data.b_mode = 0; data.a = data.b = 0; switch (inst.a_mode) { case IMMEDIATE: data.b = inst.a; break; case DIRECT: data = mem[(addr + inst.a) % MEMSIZE]; break; case INDIRECT: source = mem[(addr + inst.a) % MEMSIZE].b; data = mem[(source + addr + inst.a) % MEMSIZE]; break; default: /* ERROR */ printf ("do_sub: illegal addressing mode\n"); return 1; } switch (inst.b_mode) { case IMMEDIATE: /* error */ printf ("do_sub: illegal immediate destination\n"); return 1; case DIRECT: mem[(addr + inst.b) % MEMSIZE].b -= data.b; break; case INDIRECT: destination = mem[(addr + inst.b) % MEMSIZE].b; mem[(destination + addr + inst.b) % MEMSIZE].b -= data.b; break; default: /* ERROR */ printf ("do_sub: illegal addressing mode\n"); return 1; } return 0; } do_add(addr, inst) address addr; memword inst; { address source, destination; memword data; data.op = 0; data.a_mode = data.b_mode = 0; data.a = data.b = 0; switch (inst.a_mode) { case IMMEDIATE: data.b = inst.a; break; case DIRECT: data = mem[(addr + inst.a) % MEMSIZE]; break; case INDIRECT: source = mem[(addr + inst.a) % MEMSIZE].b; data = mem[(source + addr + inst.a) % MEMSIZE]; break; default: /* ERROR */ printf ("do_add: illegal addressing mode\n"); return 1; } switch (inst.b_mode) { case IMMEDIATE: /* error */ printf ("do_add: illegal immediate destination\n"); return 1; case DIRECT: mem[(addr + inst.b) % MEMSIZE].b += data.b; break; case INDIRECT: destination = mem[(addr + inst.b) % MEMSIZE].b; mem[(destination + addr + inst.b) % MEMSIZE].b += data.b; break; default: /* ERROR */ printf ("do_add: illegal addressing mode\n"); return 1; } return 0; } dump() { int r; int flag = 0; printf ("\n\n---------- MEMORY DUMP -------------\n"); for ( r = 0; r < MEMSIZE; r++) { if ( iszero(mem[r]) && flag == 0) { printf ("%5d 0:0:0:0000:0000\n", r); flag = 1; } else if (iszero(mem[r]) && flag == 1) { printf (" *\n"); flag = 2; } else if (iszero(mem[r]) && flag == 2) { /* skip it */ } else { printf ("%5d %s\n", r, pr_inst(mem[r])); flag = 0; } } } iszero(x) memword x; { if (x.op == 0 && x.a_mode == 0 && x.b_mode == 0 && x.a == 0 && x.b == 0 ) { return 1; } else { return 0; } } draw() { printf ("game is a DRAW -- timed out after %d seconds\n", TIMEOUT); if (dumpflag) dump(); exit(0); } char * pr_inst(x) memword x; { char buf[200]; sprintf(buf,"%1d:%1d:%1d:%04d:%04d",x.op,x.a_mode,x.b_mode,x.a,x.b); return buf; } 'KerchDrivOrnCo' echo extracting corewar.h cat <<'KerchDrivOrnCo' > corewar.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. */ #define TIMEOUT 120 /* only play for two minutes */ struct memword { short op; short a_mode; short b_mode; int a; int b; }; typedef struct memword memword; typedef long address; #define MEMSIZE 8000 #define DISTANCE 1000 /* programs at laest this far apart */ /* * Redcode Instruction Format: * * N N N NNNN NNNN <-- decimal digits * OP ModeA ModeB AAAA BBBB * * Max. instruction: 82279997999 = 0x1 3245 222F * Too bad it won't fit in a Long * */ /* * The redcode Op-code values */ #define MOV 1 #define ADD 2 #define SUB 3 #define JMP 4 #define JMZ 5 #define JMG 6 #define DJZ 7 #define CMP 8 #define DAT 0 char *op_str[] = { "dat", /* 0 */ "mov", /* 1 */ "add", /* 2 */ "sub", /* 3 */ "jmp", /* 4 */ "jmz", /* 5 */ "jmg", /* 6 */ "djz", /* 7 */ "cmp", /* 8 */ 0 }; /* * Operand modes */ #define IMMEDIATE 0 #define DIRECT 1 #define INDIRECT 2 char mode_char[] = { '#', ' ', '@', 0}; 'KerchDrivOrnCo' echo extracting duh cat <<'KerchDrivOrnCo' > duh jmp 0 /do nothing, ever 'KerchDrivOrnCo' echo extracting dwarf cat <<'KerchDrivOrnCo' > dwarf dat -1 add #5 -1 mov #0 @-2 jmp -2 'KerchDrivOrnCo' echo extracting gemini cat <<'KerchDrivOrnCo' > gemini 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 /otherwise, 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 'KerchDrivOrnCo' echo extracting imp cat <<'KerchDrivOrnCo' > imp mov 0 1 /copy myself one instruction ahead 'KerchDrivOrnCo' echo extracting makefile cat <<'KerchDrivOrnCo' > makefile CFLAGS = -O corewar: corewar.o cc -o corewar corewar.o corewar.o: corewar.c 'KerchDrivOrnCo' echo extracting movtest cat <<'KerchDrivOrnCo' > movtest dat 0 dat 1 dat 2 dat 3 dat -1 /indirect pointer back one dat 1 /indirect pointer ahead 1 dat 0 mov -6 -7 /mov 1 to 0 mov #77 -6 /put 77 on top of 2 mov @-5 @-4 /mov the 3 to the nearest 0 dat 0 /illegal; terminates test 'KerchDrivOrnCo' ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site oddjob.UChicago.UUCP Path: utzoo!watmath!clyde!burl!mgnetp!ihnp4!gargoyle!oddjob!matt From: m...@oddjob.UChicago.UUCP (Matt Crawford) Newsgroups: net.sources,net.games Subject: Fix to the posted corewar game Message-ID: <313@oddjob.UChicago.UUCP> Date: Fri, 29-Jun-84 15:41:59 EDT Article-I.D.: oddjob.313 Posted: Fri Jun 29 15:41:59 1984 Date-Received: Sun, 1-Jul-84 06:10:09 EDT References: <107@zinfandel.UUCP> Organization: U. Chicago: Astronomy & Astrophysics Lines: 46 Here is a fix to the subroutine do_cmp(). The "gemini" battle program was not working correctly. *** /tmp/,RCSt1008279 Fri Jun 29 14:37:01 1984 --- corewar.c Fri Jun 29 14:35:13 1984 *************** *** 444,451 } switch (inst.b_mode) { ! case IMMEDIATE: /* error */ ! if (data.a == inst.b) return 1; else return 2; case DIRECT: if ( data.a == mem[(addr + inst.b) % MEMSIZE].b) --- 444,451 ----- } switch (inst.b_mode) { ! case IMMEDIATE: ! if (data.b == inst.b) return 1; else return 2; case DIRECT: if ( data.b == mem[(addr + inst.b) % MEMSIZE].b) *************** *** 448,454 if (data.a == inst.b) return 1; else return 2; case DIRECT: ! if ( data.a == mem[(addr + inst.b) % MEMSIZE].b) return 1; else return 2; case INDIRECT: --- 448,454 ----- if (data.b == inst.b) return 1; else return 2; case DIRECT: ! if ( data.b == mem[(addr + inst.b) % MEMSIZE].b) return 1; else return 2; case INDIRECT: ___________________________________________________________ Matt University ARPA: crawf...@anl-mcs.arpa Crawford of Chicago UUCP: ihnp4!oddjob!matt ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83 (MC840302); site mcvax.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxl!ihnp4!zehntel!hplabs!hao!seismo!cmcl2!philabs!mcvax!play From: p...@mcvax.UUCP (funhouse) Newsgroups: net.sources Subject: Re: Corewar program source Message-ID: <5886@mcvax.UUCP> Date: Wed, 4-Jul-84 21:42:49 EDT Article-I.D.: mcvax.5886 Posted: Wed Jul 4 21:42:49 1984 Date-Received: Wed, 11-Jul-84 00:33:32 EDT References: <107@zinfandel.UUCP> Organization: CWI, Amsterdam Lines: 4 As we got it, the source file corewar.c contains a bug causing the first program to win whenever it is not a draw. The fix is trivial: replace in the routine execute() the first return 1 by return 2; ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83 (MC840302); site mcvax.UUCP Path: utzoo!watmath!clyde!burl!mgnetp!ihnp4!zehntel!hplabs!sdcrdcf!sdcsvax!akgua!mcnc!decvax!mcvax!play From: p...@mcvax.UUCP (funhouse) Newsgroups: net.sources Subject: Re: Corewar program source Message-ID: <5887@mcvax.UUCP> Date: Thu, 5-Jul-84 17:12:44 EDT Article-I.D.: mcvax.5887 Posted: Thu Jul 5 17:12:44 1984 Date-Received: Sun, 8-Jul-84 23:43:23 EDT References: <107@zinfandel.UUCP> Organization: CWI, Amsterdam Lines: 5 Yesterday evening I posted one small bug fix to corewar.c. In the meantime I fixed so many bugs that the diff listing is longer than the original program source. If anybody is interested in a working version of corewar he should mail me, and I'll send our current version (and some battle programs). ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site qusavx.UUCP Path: utzoo!watmath!clyde!burl!mgnetp!ihnp4!cbosgd!qusavx!ron From: r...@qusavx.UUCP (Ron Woodrum) Newsgroups: net.sources,net.games Subject: corewar request Message-ID: <201@qusavx.UUCP> Date: Tue, 17-Jul-84 16:03:08 EDT Article-I.D.: qusavx.201 Posted: Tue Jul 17 16:03:08 1984 Date-Received: Thu, 19-Jul-84 02:36:38 EDT Organization: Quantime Corp., Cincinnati, Ohio Lines: 8 A few weeks ago, someone stated they had a working version of corewar and a few programs to go with it. apparently my request for this info got lost. (Im still a rookie) could someone mail me the pgrams and a set of instructions to implement the code on a 4.1bsd (apparently what it was written for) thanqueue ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site zinfandel.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxl!ihnp4!zehntel!zinfandel!berry From: be...@zinfandel.UUCP (Berry Kercheval) Newsgroups: net.games Subject: Re: corewar request Message-ID: <119@zinfandel.UUCP> Date: Wed, 25-Jul-84 15:57:14 EDT Article-I.D.: zinfande.119 Posted: Wed Jul 25 15:57:14 1984 Date-Received: Sat, 28-Jul-84 09:24:23 EDT References: <201@qusavx.UUCP>, <133@ucsbcsl.UUCP> Organization: Zehntel Inc., Walnut Creek, CA Lines: 19 Corewar is a game in which little computer programs battle it out in a simulated computer. It derives from the game darwin somewhat but is a little easier to implement. A.K. Dewdney discussed it in the "Computer Recreations" column of Scientific American a few months ago. I wrote an implementation of it and posted it to net.sources. As soon as I get a copy of mcvax!piet's bug fixes (are you listening? Did you not get my mail?) I will post version 2 unless too many net gestapo protest. meanwhile people can send me requests for individually mailed copies, but watch out; there's a lot and intermediate site administrators might get upset. Tapes can be sent too, IFF they have return postage and a reusable mailer. tapes not meeting these crtiteria will be added to my scratch-tape collection. Berry Kercheval Zehntel Inc. (ihnp4!zehntel!zinfandel!berry) P.O. Box 8016, Walnut Creek, CA 94598 (415)932-6900 ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site zinfandel.UUCP Path: utzoo!linus!decvax!decwrl!amd!dual!zehntel!zinfandel!berry From: be...@zinfandel.UUCP (Berry Kercheval) Newsgroups: net.games Subject: Re: corewar request Message-ID: <121@zinfandel.UUCP> Date: Wed, 25-Jul-84 19:09:26 EDT Article-I.D.: zinfande.121 Posted: Wed Jul 25 19:09:26 1984 Date-Received: Sat, 28-Jul-84 05:20:58 EDT References: <119@zinfandel.UUCP> Organization: Zehntel Inc., Walnut Creek, CA Lines: 12 Well, well. That will teach me to read ALL news (gasp) before replying. I got to 'net.sources' and see that mcvax!play (not piet, sorry for any confusion my memory fault caused) has already posted his version. It seems to have some good stuff added, and made OK at my site. I won't officially bless it because I think it doesn't matter as long as people enjoy it and no one makes a million bucks selling it for apple II's. (unless mcvax!play and I get cuts) --berry ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site ucsbcsl.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxl!houxm!hogpc!houti!ariel!vax135!cornell!uw-beaver!tektronix!hplabs!sdcrdcf!trwrba!cepu!ucsbcsl!discolo From: disc...@ucsbcsl.UUCP Newsgroups: net.sources,net.games Subject: Re: corewar request Message-ID: <133@ucsbcsl.UUCP> Date: Thu, 26-Jul-84 01:40:19 EDT Article-I.D.: ucsbcsl.133 Posted: Thu Jul 26 01:40:19 1984 Date-Received: Sun, 22-Jul-84 03:54:54 EDT References: <201@qusavx.UUCP> Organization: U.C. Santa Barbara Lines: 17 > A few weeks ago, someone stated they had a working version > of corewar and a few programs to go with it. > apparently my request for this info got lost. (Im still a rookie) > could someone mail me the pgrams and a set of instructions to > implement the code on a 4.1bsd (apparently what it was written for) > thanqueue Uhh, excuse me. But what is corewar? I'm burnt out on rogue and need something new to spend 5 hours a day on. -- uucp: ucbvax!ucsbcsl!discolo arpa: ucsbcsl!discolo@berkeley csnet: discolo@ucsb USMail: Computer Systems Lab U.C. Santa Barbara Santa Barbara, CA 93106 ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdccs6.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxl!ihnp4!zehntel!hplabs!sdcrdcf!sdcsvax!sdccs6!ix269 From: ix...@sdccs6.UUCP (Jim) Newsgroups: net.sources,net.games Subject: corewars, yet another Message-ID: <1663@sdccs6.UUCP> Date: Sat, 28-Jul-84 20:23:54 EDT Article-I.D.: sdccs6.1663 Posted: Sat Jul 28 20:23:54 1984 Date-Received: Mon, 30-Jul-84 00:46:44 EDT Distribution: net.games,net.sources Organization: U.C. San Diego, Computer Center Lines: 1167 <> 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] []" /* 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 /* header file for perror */ #include #include /* header for interrupt functions */ #include /* 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 #include #include #include "cw.h" #include "machdep.h" /* * load() Load a Redcode file. load the file at a random place * in , not within 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 */ 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 */ 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 #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 , 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 #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' ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site digi-g.UUCP Path: utzoo!watmath!clyde!burl!mgnetp!ihnp4!stolaf!umn-cs!digi-g!brian From: br...@digi-g.UUCP (Brian Westley) Newsgroups: net.lang.c Subject: modulus fn with negatives Message-ID: <212@digi-g.UUCP> Date: Tue, 28-Aug-84 10:18:55 EDT Article-I.D.: digi-g.212 Posted: Tue Aug 28 10:18:55 1984 Date-Received: Thu, 30-Aug-84 00:42:38 EDT Organization: DigiGraphic Systems Corp., Mpls. MN Lines: 7 Should ((-2) % 3) equal -2 or 1? Our machine returns -2, but the posted corewars game seems to assume a%b always returns 0..b-1; is modulus for negative lefthand args well defined? What about Pascal mod function? Modula Modulus? Accepted mathematical definition of modulus? Merlyn % Leroy ------------------------------------------------------------------------------ Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 exptools 1/6/84; site ihuxn.UUCP Path: utzoo!linus!decvax!harpo!whuxlm!whuxl!houxm!ihnp4!ihuxn!kah120 From: kah...@ihuxn.UUCP (Ken Heitke) Newsgroups: net.sources Subject: Core War Request Message-ID: <856@ihuxn.UUCP> Date: Wed, 17-Oct-84 11:09:40 EDT Article-I.D.: ihuxn.856 Posted: Wed Oct 17 11:09:40 1984 Date-Received: Thu, 18-Oct-84 19:27:48 EDT Organization: AT&T Bell Labs, Naperville, IL Lines: 6 Awhile back someone posted the source for Core War. Well I wiped out the copy I had and wish to get a new copy. If someone could repost this source or send me a copy it would be greatly appreciated. Thanks, Ken Heitke ihuxn!kah120 ------------------------------------------------------------------------------