home *** CD-ROM | disk | FTP | other *** search
-
- /* COREWARS 2.C The game of Core Wars, as described by
- ** A.K. Dewdney in the May 1984 issue of
- ** Scientific American.
- **
- ** Note: Output redirection will effect detailed
- ** listings ONLY! (And it'll probably be a
- ** BIG file.)
- **
- ** Date: 28 May 1984
- ** Author: Kevin A. Bjorke
- **
- ** Copyright (C) 1984 Kevin A. Bjorke
- ** Released to the Public Domain for Non-Commercial Use Only
- **
- ** 7-June-1984 Bob Green
- ** Converted to MS-DOS 2.xx - Computer Innovations C86
- ** and A TeleVideo 950 terminal from CP/M and Small-C 2.03
- **
- */
-
- #include "local.h"
-
- #define MAXSIZE 1000 /* Dewdney has 8000 - change to your taste */
- #define VERSION "1.01"
- #define CLRSCR "\033*" /* For Telcon, Heath, Etc. */
- #define ADRCUR "\033=" /* Likewise */
- #define BIAS 31 /* Ditto */
- #define INDEXED 2 /* Modes (Indexed = Indirect) */
- #define DIRECT 1
- #define IMMEDIATE 0
- #define CUTOFF 2000 /* Max. number of instructions executed */
- #define BLANK ' '
- #define CR 0x0d
- #define LF 0x0a
- #define ENQ 0x05
- #define FULLIST /* List what's going where on MOV, ADD, etc */
- /*
- **********************
- ** Global Variables **
-
- **********************
- */
-
- char proga[80]; /* names of the battle programs */
- char progb[80];
-
- int pc[2]; /* Redcode program counters */
- char instr; /* Current instruction */
- int modea, modeb; /* Current addressing modes -- see below */
- int now; /* programs 0 and 1 (pc index) */
- char line[12]; /* large enough to accept anything required */
- char show; /* used to differentiate between showing and */
- /* executing code */
-
- char code[MAXSIZE]; /* Redcode Instructions */
- int arga[MAXSIZE]; /* Battle Prog Arguments */
- int argb[MAXSIZE]; /* Total: 5 bytes per ""location" */
-
- /*
- ** Since the Redcode Instruction set has only 9 instruction and 3 addressing
- ** modes, the code is split into three fields:
- **
- ** Bit: 7 6 5 4 3 2 1 0
- ** a a b b i i i i
- **
- ** where a = mode of argument a
- ** b = mode of argument b
- ** i = instruction (0-8 -- 9-15 treated as 0, or invalid)
- **
- ** modes: 0 - immediate
- ** 1 - direct
- ** 2 - indirect
- */
-
- /*
- *************************
- ** Main Program Driver **
- *************************
- */
-
- main()
- {
- while (TRUE) {
- logo();
- clean();
- prepare();
- fight();
- fputs("\nList Memory? ",stderr);
- if (toupper(flgetc()) == 'Y')
- showmem(0,MAXSIZE);
- fputs("\n\nPlay Again (Y/N) ? ",stderr);
- if (toupper(flgetc()) != 'Y')
- break;
- }
- fputs("\n\n\tThththththat\'s all, folks....\n",stderr);
- }
-
- /*
- ** Advertise the program
- */
- logo()
- {
- fputs(CLRSCR,stderr);
- fputs("\n\n\t****************************************\n",stderr);
- fputs("\t** **\n",stderr);
- fputs("\t** C O R E W A R S **\n",stderr);
- fputs("\t** **\n",stderr);
- fputs("\t****************************************\n\n\n",stderr);
- fputs("\tMARS Version ",stderr);
- fputs(VERSION,stderr);
- fputs(" Kevin Bjorke 5/28/84\n\n",stderr);
- }
-
- /*
- ********************
- ** Input Routines **
- ********************
- */
-
- /*
- ** Read in both programs
- */
- prepare()
- {
- int top,bot; char *p;
- int fp; /* possible file pointer */
- fputs("\n\tEnter the name of Battle-Program A: ",stderr);
- gets(proga,80,stdin);
- fputs("\n\tEnter the name of Battle-Program B: ",stderr);
- gets(progb,80,stdin);
- for (p = &progb[0]; *p; ++p)
- *p = toupper(*p);
- for (p = &proga[0]; *p; ++p)
- *p = toupper(*p);
- bot = 0;
- if ((fp = fopen(proga,"r")) == NULL) {
- fputs(CLRSCR,stderr);
- fputs("\n\nPlease enter code for ",stderr);
- fputs(proga,stderr);
- fputs(":\n\n",stderr);
- top = getprog(proga,bot);
- } else
- top = fgetprog(fp,bot);
- printf("\nNow listing Program %s:\n\n",proga);
- showmem(bot,top);
- pc[0] = bot;
- getpc(0);
- bot = MAXSIZE / 2;
- if ((fp = fopen(progb,"r")) == NULL) {
- fputs(CLRSCR,stderr);
- fputs("\n\nNow, please enter code for ",stderr);
- fputs(progb,stderr);
- fputs(":\n\n",stderr);
- top = getprog(progb,bot);
- } else
- top = fgetprog(fp,bot);
- printf("\nNow listing Program %s:\n\n",progb);
- showmem(bot,top);
- pc[1] = bot;
- getpc(1);
- }
-
- /*
- ** get a program from the keyboard
- */
- getprog(prg,ct) char *prg; int ct;
- {
- int i,row;
- char *pt;
- row = 10;
- fputs("Enter program one line at a time.\n",stderr);
- fputs("Pressing RETURN between arguments.\n",stderr);
- fputs("\tUse END to finish\n\n",stderr);
- header(9);
- while (TRUE) {
- modea = modeb = DIRECT;
- cursor(row,1);
- stout(ct);
- cursor(row,10);
- gets(line,12,stdin);
- for (i = 0; line[i]; ++i) {
- if ((line[i] == '\t') || (line[i] == ' '))
- line[i] = '\0';
- line[i] = toupper(line[i]);
- }
- if ((i = getinst(ct)) == NULL)
- break;
- if (i == ERROR) {
- cursor(row,10);
- fputs("\007???\n",stderr);
- continue;
- }
- cursor(row,50);
- fputs(line,stderr);
- if (code[ct] != 0) {
- cursor(row,20);
- gets(line,12,stdin);
- pt = &line[0];
- cursor(row,60);
- if (*pt == '@') {
- fputs("Indirect",stderr);
- modea = INDEXED;
- ++pt;
- } else if (*pt == '#') {
- fputs("Immediate",stderr);
- modea = IMMEDIATE;
- ++pt;
- } else
- fputs("Direct",stderr);
- i = stoi(pt);
- arga[ct] = i;
- }
- if (code[ct] != 4) {
- cursor(row,30);
- gets(line,12,stdin);
- pt = &line[0];
- cursor(row,70);
- if (*pt == '@') {
- fputs("Indirect",stderr);
- modeb = INDEXED;
- ++pt;
- } else if (*pt == '#') {
- fputs("Immediate",stderr);
- modeb = IMMEDIATE;
- ++pt;
- } else
- fputs("Direct",stderr);
- i = stoi(pt);
- argb[ct] = i;
- }
- modea *= 64;
- modea &= 192;
- modeb *= 16;
- modeb &= 48;
- code[ct] += (modea + modeb);
- ++ct;
- if ((++row) > 23) {
- row = 2;
- fputs(CLRSCR,stderr);
- header(1);
- }
- }
- fputs("\n\tCode for ",stderr);
- fputs(prg,stderr);
- fputs(" completed.\n",stderr);
- return(ct);
- }
-
- /*
- ** get a program from a file
- */
- fgetprog(prg,ct) int prg,ct;
- {
- int i; char *pt;
- fputs("\nNow reasding program file...\n\n",stderr);
- while (TRUE) {
- modea = modeb = DIRECT;
- if (nextword(prg) == FALSE)
- break;
- if ((i = getinst(ct)) == NULL)
- break;
- if (i == ERROR) {
- fputs("\007\nError - file fouled up!!!\n",stderr);
- exit();
- }
- if (code[ct] != 0) {
- nextword(prg);
- arga[ct] = rdarg(&modea);
- }
- if (code[ct] != 4) {
- nextword(prg);
- argb[ct] = rdarg(&modeb);
- }
- modea *= 64;
- modea &= 192;
- modeb *= 16;
- modeb &= 48;
- code[ct] += (modea + modeb);
- ++ct;
- }
- fclose(prg);
- return(ct);
- }
-
- /*
- ** select an instruction from the vaule in line[]
- */
- getinst(indx) int indx;
- {
- if (strcmp(line,"MOV") == NULL)
- code[indx] = 1;
- else if (strcmp(line,"ADD") == NULL)
- code[indx] = 2;
- else if (strcmp(line,"SUB") == NULL)
- code[indx] = 3;
- else if (strcmp(line,"JMP") == NULL)
- code[indx] = 4;
- else if (strcmp(line,"JMZ") == NULL)
- code[indx] = 5;
- else if (strcmp(line,"JMG") == NULL)
- code[indx] = 6;
- else if (strcmp(line,"DJZ") == NULL)
- code[indx] = 7;
- else if (strcmp(line,"CMP") == NULL)
- code[indx] = 8;
- else if (strcmp(line,"DAT") == NULL)
- code[indx] = 0;
- else if (strcmp(line,"END") == NULL)
- return(NULL);
- else
- return(ERROR);
- return(TRUE);
- }
-
- /*
- ** get an argument value from line[]
- */
- rdarg(md) char *md;
- {
- char *pt; int i;
- pt = &line[0];
- if (*pt == '@') {
- *md = INDEXED;
- ++pt;
- } else if (*pt == '#') {
- *md = IMMEDIATE;
- ++pt;
- }
- i = stoi(pt);
- return(i);
- }
-
- /*
- ** set the program counters to their initial locations
- */
- getpc(i) int i;
- {
- fputs("\nStart execution at location: ",stderr);
- gets(line,12,stdin);
- pc[i] = stoi(line);
- pc[i] = reladr(pc[i],0);
- }
-
- /*
- ** print programming header on screen
- */
- header(rw) int rw;
- {
- cursor(rw,1);
- fputs("Addr",stderr);
- cursor(rw,10);
- fputs("Instr",stderr);
- cursor(rw,20);
- fputc('A',stderr);
- cursor(rw,30);
- fputc('B',stderr);
- cursor(rw,55);
- fputs("Modes:",stderr);
- }
-
- /*
- ** Get the next word from a TEXTfile, making sure to capitalize
- */
- nextword(fil) int fil;
- {
- char *pt, c;
- pt = &line[0];
- c = '\t';
- while ((c == '\t') || (c == BLANK) || (c == CR) || (c == LF)) {
- if ((c = toupper(fgetc(fil))) == EOF)
- return (FALSE);
- }
- while ((c != '\t') && (c != BLANK) && (c != CR) && (c != LF)) {
- *pt++ = c;
- if ((c = toupper(fgetc(fil))) == EOF)
- return (FALSE);
- }
- *pt++ = '\0';
- return(TRUE);
- }
-
-
-
- /*
- ** Show memory
- */
- showmem(start,finish) int start, finish;
- {
- int ct;
- printf("Addresses %4d through %4d.\n",start,(finish-1));
- show = TRUE;
- putchar('\n');
- for (ct = start; ct < finish; ++ct) {
- readloc(ct);
- putchar('\n');
- }
- }
-
- /*
- ****************************
- ** MASTER BATTLE ROUTINES **
- ****************************
- */
-
- /*
- ** Fight it out
- */
- fight()
- {
- int ct, i;
- show = FALSE;
- fputs(CLRSCR,stderr);
- fputs("\tPRESS ANY KEY TO BEGIN ",stderr);
- while (bdos(06,0xff) == NULL);
- fputs("\n\nBeginning Battle...\n\n",stderr);
- fputs("\t> ^E to Abort <\n\n",stderr);
- printf("\t\t%8s\t\t%8s\n\n",proga,progb);
- for (ct = 0; ct < CUTOFF; ++ct) {
- if ((ct % 5) == 0)
- fputc('\n',stderr);
- stout(ct);
- now = 0;
- if (readloc(pc[0]) == NULL)
- break;
- putchar('\t');
- now = 1;
- if (readloc(pc[1]) == NULL)
- break;
- putchar('\n');
- if ((bdos(6,0xff)&0x7f) == ENQ)
- break;
- for (i = 0; i <2; ++i)
- pc[i] = reladr(pc[i],0);
- }
- fputc(BELL,stderr);
- printf("\nBattle Completed after %d instruction cycles!\n",ct);
- if (ct == CUTOFF)
- fputs("\>Draw<\n",stderr);
- }
-
- /*
- ** read a location, print the mnemonic, and perform it
- */
- readloc(loc) int loc;
- {
- char ma, mb; int res;
- instr = modea = modeb = code[loc];
- instr &= 15; /* or 0x0F */
- modea = (modea / 64) & 3;
- modeb = (modeb / 16) & 3;
- res = -1;
- if (instr == 1) /* can't use switch with char arg */
- mov();
- else if (instr == 2)
- add();
- else if (instr == 3)
- sub();
- else if (instr == 4)
- jmp();
- else if (instr == 5)
- jmz();
- else if (instr == 6)
- jmg();
- else if (instr == 7)
- djz();
- else if (instr == 8)
- cmp();
- else {
- puts("DAT");
- res = NULL;
- }
- printf("\t%c%3d\t%c%3d [%3d]",mnem(modea),arga[loc],mnem(modeb),argb[loc],loc);
- return(res);
- }
-
- /*
- *********************************************
- ** functions to perform Redcode operations **
- *********************************************
- */
-
- /*
- ** Redcode MOV instruction
- */
- mov()
- {
- int a,b;
- puts("MOV");
- if (show)
- return(NULL);
- b = findadr(pc[now], &argb[0], modeb);
- if (modea == IMMEDIATE) {
- code[b] = 0; /* make it a DAT */
- argb[b] = arga[pc[now]];
- #ifdef FULLIST
- printf("|#%6d>%3d|",arga[pc[now]],b);
- #endif
- } else {
- a = findadr(pc[now], &arga[0], modea);
- #ifdef FULLIST
- printf("|%3d>%3d|",a,b);
- #endif
- code[b] = code[a];
- arga[b] = arga[a];
- argb[b] = argb[a];
- }
- ++pc[now];
- }
-
- /*
- ** Redcode ADD instruction
- */
- add()
- {
- int a,b;
- puts("ADD");
- if (show)
- return(NULL);
- b = findadr(pc[now], &argb[0], modeb);
- if (modea == IMMEDIATE) {
- argb[b] += arga[pc[now]];
- #ifdef FULLIST
- printf("|#%6d+%3d|",arga[pc[now]],b);
- #endif
- } else {
- a = findadr(pc[now], &arga[0], modea);
- #ifdef FULLIST
- printf("|%3d+%3d|",b,a);
- #endif
- argb[b] += arga[a];
- }
- ++pc[now];
- }
-
- /*
- ** Redcode SUB instruction
- */
- sub()
- {
- int a,b;
- puts("SUB");
- if (show)
- return(NULL);
- b = findadr(pc[now], &argb[0], modeb);
- if (modea == IMMEDIATE) {
- argb[b] -= arga[pc[now]];
- #ifdef FULLIST
- printf("|%3d-#%6d|",b,arga[pc[now]]);
- #endif
- } else {
- a = findadr(pc[now], &arga[0],modea);
- #ifdef FULLIST
- printf("|%3d-%3d|",b,a);
- #endif
- argb[b] -= arga[a];
- }
- ++pc[now];
- }
-
- /*
- ** Redcode JMP Instruction
- */
- jmp()
- {
- int a;
- puts("JMP");
- if (show)
- return(NULL);
- pc[now] = findadr(pc[now], &arga[0], modea);
- }
-
- /*
- ** Redcode JMZ instruction
- */
- jmz()
- {
- int b;
- puts("JMZ");
- if (show)
- return(NULL);
- b = findadr(pc[now], &argb[0], modeb);
- #ifdef FULLIST
- printf("|%3d|",b);
- #endif
- if (argb[b] == 0)
- pc[now] = findadr(pc[now], &arga[0], modea);
- else
- ++pc[now];
- }
-
-
- /*
- ** Redcode JMG Instruction
- */
- jmg()
- {
- int b;
- puts("JMG");
- if (show)
- return(NULL);
- b = findadr(pc[now], &argb[0], modeb);
- #ifdef FULLIST
- printf("|%3d|",b);
- #endif
- if (argb[b] != 0)
- pc[now] = findadr(pc[now], &arga[0], modea);
- else
- ++pc[now];
- }
-
- /*
- ** Redcode DJZ Instruction
- */
- djz()
- {
- int b;
- puts("DJZ");
- if (show)
- return(NULL);
- b = findadr(pc[now], &argb[0], modeb);
- #ifdef FULLIST
- printf("|%3d|",b);
- #endif
- if ((--argb[b]) == NULL)
- pc[now] = findadr(pc[now], &arga[0], modea);
- else
- ++pc[now];
- }
-
- /*
- ** Redcode CMP Instruction
- */
- cmp()
- {
- int a,b;
- puts("CMP");
- if (show)
- return(NULL);
- if (modea != IMMEDIATE) {
- a = findadr(pc[now], &arga[0], modea);
- a = argb[a];
- } else
- a = arga[pc[now]];
- if (modeb != IMMEDIATE) {
- b = findadr(pc[now], &argb[0], modeb);
- b = argb[b];
- } else
- b = argb[pc[now]];
- ++pc[now];
- if (a != b)
- ++pc[now];
- }
-
- /*
- *************************
- ** Addressing Routines **
- *************************
- */
-
- /*
- ** find an address via direct or indirect
- */
- findadr(orig,pab,mod) int orig, *pab; char mod;
- {
- int p;
- if (mod == IMMEDIATE)
- return(orig);
- p = reladr(orig,pab[orig]);
- if (mod == INDEXED)
- p = reladr(p,argb[p]);
- return(p);
- }
-
-
- /*
- ** return an absolute address in the circular arena from a relative one
- */
- reladr(abs,rel) int abs,rel;
- {
- int j;
- if ((j = abs + rel) >= MAXSIZE)
- j = reladr((j - MAXSIZE),0);
- else if (j < 0)
- j = reladr((j + MAXSIZE),0);
- return(j);
- }
-
- /*
- ****************************
- ** Miscellaneous routines **
- ****************************
- */
-
- /*
- ** Start with a "clean slate" in the battle-code arena
- */
- clean()
- {
- int i;
- for (i = 0; i < MAXSIZE; ++i) {
- code[i] = '\0';
- arga[i] = NULL;
- argb[i] = NULL;
- }
- }
-
- /*
- ** return appropriate character for addressing modes
- */
- mnem(c) char c;
- {
- c &= 255;
- if (c == IMMEDIATE)
- return('#');
- else if (c == INDEXED)
- return('@');
- else
- return('.');
- }
-
- /*
- ** return an integer from a string
- */
- stoi(str) char *str;
- {
- int i,s;
- if (*str == '-') {
- s = -1;
- ++str;
- } else
- s = 1;
- i = 0;
- while ((*str >= '0') && (*str <= '9'))
- i = (10 * i) + (*str++ - '0');
- i *= s;
- return (i);
- }
-
- /*
- ** print a string to stderr from an integer <= 9999
- */
- stout(i) int i;
- {
- if (i < 0)
- fputc('-',stderr);
- fputc((i / 1000 + '0'),stderr);
- i %= 1000;
- fputc((i / 100 + '0'),stderr);
- i %= 100;
- fputc((i / 10 + '0'),stderr);
- i %= 10;
- fputc((i + '0'),stderr);
- fputs(":\t",stderr);
- }
-
- /*
- ** Address the cursor (Currently set for Heath/Telcon)
- */
- cursor(row,col) int row,col;
- {
- fputs(ADRCUR,stderr);
- fputc((row+BIAS),stderr);
- fputc((col+BIAS),stderr);
- }
-
- /*
- ** raw console io
- */
- keypr()
- {
- char c;
- while (!((c=bdos(6, 0xff)&0x7f)))
- ;
- return(c);
- }
-
- /* end of CORE WARS 2 */
-