home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
pascal
/
corwar.zip
/
CORWAR.C
next >
Wrap
Text File
|
1992-03-15
|
15KB
|
783 lines
/* 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 */
END OF TRANSFER - PRESS ENTER TO RETURN TO MENU
0xff)&0x7f)))