home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / corewars.zip / COREWARS.LBR / COREWARS.C < prev    next >
Text File  |  1989-03-19  |  16KB  |  796 lines

  1. /**
  2. **
  3. ** COREWARS 2.C    The game of Core Wars, as described by
  4. **            A.K. Dewdney in the May 1984 issue of
  5. **            Scientific American. 
  6. **
  7. **            Note: Output redirection will effect detailed
  8. **                  listings ONLY! (And it'll probably be a
  9. **                  BIG file.)
  10. **
  11. **    Date: 28 May 1984
  12. **    Author: Kevin A. Bjorke
  13. **
  14. **    Copyright (C) 1984 Kevin A. Bjorke
  15. **    Released to the Public Domain for Non-Commercial Use Only
  16. **
  17. **    22-Sept-1984 Harvey Lord
  18. **        Converted to Lattice C compiler, V. 2.12 and a VT-100
  19. **        terminal (DEC Rainbow 100, 100+, 100B or IBM PC running
  20. **        PC DOS V. 2.xx with the ANSI device drivers installed
  21. **        at cold boot)
  22. **
  23. **      7-June-1984 Bob Green
  24. **          Converted to MS-DOS 2.xx   -  Computer Innovations  C86
  25. **          and A TeleVideo 950 terminal from CP/M and Small-C 2.03  
  26. **
  27. **/
  28.  
  29. #include <stdio.h>
  30.  
  31. #undef abs
  32.  
  33. /**
  34.  
  35. NOTE: a bug appeared when converting to the LATTICE C compiler.
  36. LATTICE's stdio.h header contains a macro for abs, the absolute
  37. value function.  In line 703, here, abs is used as a variable
  38. and the compiler thought it was a macro with the wrong number of
  39. arguments.  Therefore, I had to undefine abs.
  40.  
  41. Harvey G. Lord
  42.  
  43. **/
  44.  
  45. #define TRUE    1
  46. #define FALSE    NULL
  47. #define ERROR    -1
  48. #define MAXSIZE 1000        /* Dewdney has 8000 - change to your taste */
  49. #define VERSION "1.01"
  50. #define INDEXED 2        /* Modes (Indexed = Indirect) */
  51. #define DIRECT    1
  52. #define IMMEDIATE 0
  53. #define CUTOFF    2000        /* Max. number of instructions executed */
  54. #define BLANK    ' '
  55. #define BEL    0x07
  56. #define CR    0x0d
  57. #define LF    0x0a
  58. #define ENQ    0x05
  59. #define FULLIST         /* List what's going where on MOV, ADD, etc */
  60.  
  61. #define CLRSCR    "\033[2J\033[H"    /* For Rainbow 100, all VT-100 terminals */
  62. #define cursor(row,column) printf("\033[%d;%dH",row,column) /* Ditto    */
  63.  
  64. /*
  65. **********************
  66. ** Global Variables **
  67.  
  68. **********************
  69. */
  70.  
  71. char proga[80];            /* names of the battle programs */
  72. char progb[80];
  73.  
  74. int pc[2];            /* Redcode program counters */
  75. char instr;            /* Current instruction */
  76. int modea, modeb;        /* Current addressing modes -- see below */
  77. int now;            /* programs 0 and 1 (pc index) */
  78. char line[12];            /* large enough to accept anything required */
  79. char show;            /* used to differentiate between showing and */
  80.                 /* executing code */
  81.  
  82. char code[MAXSIZE];        /* Redcode Instructions */
  83. int  arga[MAXSIZE];        /* Battle Prog Arguments */
  84. int  argb[MAXSIZE];        /* Total: 5 bytes per "location" */
  85.  
  86. /*
  87. ** Since the Redcode Instruction set has only 9 instruction and 3 addressing
  88. ** modes, the code is split into three fields:
  89. **
  90. **    Bit:    7 6 5 4 3 2 1 0
  91. **        a a b b i i i i
  92. **
  93. ** where a = mode of argument a
  94. **       b = mode of argument b
  95. **       i = instruction (0-8 -- 9-15 treated as 0, or invalid)
  96. **
  97. ** modes: 0 - immediate
  98. **        1 - direct
  99. **        2 - indirect
  100. */
  101.  
  102. /*
  103. *************************
  104. ** Main Program Driver **
  105. *************************
  106. */
  107.  
  108. main()    
  109. {
  110.     while (TRUE) {
  111.         logo();
  112.         clean();
  113.         prepare();
  114.         fight();
  115.         fputs("\nList Memory? ",stderr);
  116.         if (toupper(getche()) == 'Y')
  117.             showmem(0,MAXSIZE);
  118.         fputs("\n\nPlay Again (Y/N) ? ",stderr);
  119.         if (toupper(getche()) != 'Y')
  120.             break;
  121.     }
  122.     fputs("\n\n\tThththththat\'s all, folks....\n",stderr);
  123. }
  124.  
  125. /*
  126. ** Advertise the program
  127. */
  128. logo()
  129. {
  130.     fputs(CLRSCR,stderr);
  131.     fputs("\n\n\t****************************************\n",stderr);
  132.     fputs("\t**                                    **\n",stderr);
  133.     fputs("\t**         C O R E    W A R S         **\n",stderr);
  134.     fputs("\t**                                    **\n",stderr);
  135.     fputs("\t****************************************\n\n\n",stderr);
  136.     fputs("\tMARS Version ",stderr);
  137.     fputs(VERSION,stderr);
  138.     fputs("   Kevin Bjorke 5/28/84\n\n",stderr);
  139. }
  140.  
  141. /*
  142. ********************
  143. ** Input Routines **
  144. ********************
  145. */
  146.  
  147. /*
  148. ** Read in both programs
  149. */
  150. prepare()
  151. {
  152.     int top,bot; char *p;
  153.     FILE *fp;            /* possible file pointer */
  154.     fputs("\n\tEnter the name of Battle-Program A: ",stderr);
  155.     gets(proga,80,stdin);
  156.     fputs("\n\tEnter the name of Battle-Program B: ",stderr);
  157.     gets(progb,80,stdin);
  158.     for (p = &progb[0]; *p; ++p)
  159.         *p = toupper(*p);
  160.     for (p = &proga[0]; *p; ++p)
  161.         *p = toupper(*p);
  162.     bot = 0;
  163.     if ((fp = fopen(proga,"r")) == NULL) {
  164.         fputs(CLRSCR,stderr);
  165.         fputs("\n\nPlease enter code for ",stderr);
  166.         fputs(proga,stderr);
  167.         fputs(":\n\n",stderr);
  168.         top = getprog(proga,bot);
  169.     } else
  170.         top = fgetprog(fp,bot);
  171.     printf("\nNow listing Program %s:\n\n",proga);
  172.     showmem(bot,top);
  173.     pc[0] = bot;
  174.     getpc(0);
  175.     bot = MAXSIZE / 2;
  176.     if ((fp = fopen(progb,"r")) == NULL) {
  177.         fputs(CLRSCR,stderr);
  178.         fputs("\n\nNow, please enter code for ",stderr);
  179.         fputs(progb,stderr);
  180.         fputs(":\n\n",stderr);
  181.         top = getprog(progb,bot);
  182.     } else
  183.         top = fgetprog(fp,bot);
  184.     printf("\nNow listing Program %s:\n\n",progb);
  185.     showmem(bot,top);
  186.     pc[1] = bot;
  187.     getpc(1);
  188. }
  189.  
  190. /*
  191. ** get a program from the keyboard
  192. */
  193. getprog(prg,ct) char *prg; int ct;
  194. {
  195.     int i,row; 
  196.         char *pt;
  197.     row = 10;
  198.     fputs("Enter program one line at a time.\n",stderr);
  199.     fputs("Pressing RETURN between arguments.\n",stderr);
  200.     fputs("\tUse END to finish\n\n",stderr);
  201.     header(9);
  202.     while (TRUE) {
  203.         modea = modeb = DIRECT;
  204.         cursor(row,1);
  205.         stout(ct);
  206.         cursor(row,10);
  207.         gets(line,12,stdin);
  208.         for (i = 0; line[i]; ++i) {
  209.             if ((line[i] == '\t') || (line[i] == ' '))
  210.                 line[i] = '\0';
  211.             line[i] = toupper(line[i]);
  212.         }
  213.         if ((i = getinst(ct)) == NULL)
  214.             break;
  215.         if (i == ERROR) {
  216.             cursor(row,10);
  217.             fputs("\007???\n",stderr);
  218.             continue;
  219.         }
  220.         cursor(row,50);
  221.         fputs(line,stderr);
  222.         if (code[ct] != 0) {
  223.             cursor(row,20);
  224.             gets(line,12,stdin);
  225.             pt = &line[0];
  226.             cursor(row,60);
  227.             if (*pt == '@') {
  228.                 fputs("Indirect",stderr);
  229.                 modea = INDEXED;
  230.                 ++pt;
  231.             } else if (*pt == '#') {
  232.                 fputs("Immediate",stderr);
  233.                 modea = IMMEDIATE;
  234.                 ++pt;
  235.             }  else
  236.                 fputs("Direct",stderr);
  237.             i = stoi(pt);
  238.             arga[ct] = i;
  239.         }
  240.         if (code[ct] != 4) {
  241.             cursor(row,30);
  242.             gets(line,12,stdin);
  243.             pt = &line[0];
  244.             cursor(row,70);
  245.             if (*pt == '@') {
  246.                 fputs("Indirect",stderr);
  247.                 modeb = INDEXED;
  248.                 ++pt;
  249.             } else if (*pt == '#') {
  250.                 fputs("Immediate",stderr);
  251.                 modeb = IMMEDIATE;
  252.                 ++pt;
  253.             } else
  254.                 fputs("Direct",stderr);
  255.             i = stoi(pt);
  256.             argb[ct] = i;
  257.         }
  258.         modea *= 64;
  259.         modea &= 192;
  260.         modeb *= 16;
  261.         modeb &= 48;
  262.         code[ct] += (modea + modeb);
  263.         ++ct;
  264.         if ((++row) > 23) {
  265.             row = 2;
  266.             fputs(CLRSCR,stderr);
  267.             header(1);
  268.         }
  269.     }
  270.     fputs("\n\tCode for ",stderr);
  271.     fputs(prg,stderr);
  272.     fputs(" completed.\n",stderr);
  273.     return(ct);
  274. }
  275.  
  276. /*
  277. ** get a program from a file
  278. */
  279. fgetprog(prg,ct) int prg,ct;
  280. {
  281.     int i; char *pt;
  282.     fputs("\nNow reading program file...\n\n",stderr);
  283.     while (TRUE) {
  284.         modea = modeb = DIRECT;
  285.         if (nextword(prg) == FALSE)
  286.             break;
  287.         if ((i = getinst(ct)) == NULL)
  288.             break;
  289.         if (i == ERROR) {
  290.             fputs("\007\nError - file fouled up!!!\n",stderr);
  291.             exit();
  292.         }
  293.         if (code[ct] != 0) {
  294.             nextword(prg);
  295.             arga[ct] = rdarg(&modea);
  296.         }
  297.         if (code[ct] != 4) {
  298.             nextword(prg);
  299.             argb[ct] = rdarg(&modeb);
  300.         }
  301.         modea *= 64;
  302.         modea &= 192;
  303.         modeb *= 16;
  304.         modeb &= 48;
  305.         code[ct] += (modea + modeb);
  306.         ++ct;
  307.     }
  308.     fclose(prg);
  309.     return(ct);
  310. }
  311.  
  312. /*
  313. ** select an instruction from the value in line[]
  314. */
  315. getinst(indx) int indx;
  316. {
  317.     if (strcmp(line,"MOV") == NULL)
  318.         code[indx] = 1;
  319.     else if (strcmp(line,"ADD") == NULL)
  320.         code[indx] = 2;
  321.     else if (strcmp(line,"SUB") == NULL)
  322.         code[indx] = 3;
  323.     else if (strcmp(line,"JMP") == NULL)
  324.         code[indx] = 4;
  325.     else if (strcmp(line,"JMZ") == NULL)
  326.         code[indx] = 5;
  327.     else if (strcmp(line,"JMG") == NULL)
  328.         code[indx] = 6;
  329.     else if (strcmp(line,"DJZ") == NULL)
  330.         code[indx] = 7;
  331.     else if (strcmp(line,"CMP") == NULL)
  332.         code[indx] = 8;
  333.     else if (strcmp(line,"DAT") == NULL)
  334.         code[indx] = 0;
  335.     else if (strcmp(line,"END") == NULL)
  336.         return(NULL);
  337.     else 
  338.         return(ERROR);
  339.     return(TRUE);
  340. }
  341.  
  342. /*
  343. ** get an argument value from line[]
  344. */
  345. rdarg(md) char *md;
  346. {
  347.     char *pt; int i;
  348.     pt = &line[0];
  349.     if (*pt == '@') {
  350.         *md = INDEXED;
  351.         ++pt;
  352.     } else if (*pt == '#') {
  353.         *md = IMMEDIATE;
  354.         ++pt;
  355.     }
  356.     i = stoi(pt);
  357.     return(i);
  358. }
  359.  
  360. /*
  361. ** set the program counters to their initial locations
  362. */
  363. getpc(i) int i;
  364. {
  365.     fputs("\nStart execution at location: ",stderr);
  366.     gets(line,12,stdin);
  367.     pc[i] = stoi(line);
  368.     pc[i] = reladr(pc[i],0);
  369. }
  370.  
  371. /*
  372. ** print programming header on screen
  373. */
  374. header(rw) int rw;
  375. {
  376.     cursor(rw,1);
  377.     fputs("Addr",stderr);
  378.     cursor(rw,10);
  379.     fputs("Instr",stderr);
  380.     cursor(rw,20);
  381.     fputc('A',stderr);
  382.     cursor(rw,30);
  383.     fputc('B',stderr);
  384.     cursor(rw,55);
  385.     fputs("Modes:",stderr);
  386. }
  387.  
  388. /*
  389. ** Get the next word from a TEXTfile, making sure to capitalize
  390. */
  391. nextword(fil) int fil;
  392. {
  393.     char *pt, c;
  394.     pt = &line[0];
  395.     c = '\t';
  396.     while ((c == '\t') || (c == BLANK) || (c == CR) || (c == LF)) {
  397.         if ((c = toupper(fgetc(fil))) == EOF)
  398.             return (FALSE);
  399.     }
  400.     while ((c != '\t') && (c != BLANK) && (c != CR) && (c != LF)) {
  401.         *pt++ = c;
  402.         if ((c = toupper(fgetc(fil))) == EOF)
  403.             return (FALSE);
  404.     }
  405.     *pt++ = '\0';
  406.     return(TRUE);
  407. }
  408.  
  409.  
  410.  
  411. /*
  412. ** Show memory
  413. */
  414. showmem(start,finish) int start, finish;
  415. {
  416.     int ct;
  417.     printf("Addresses %4d through %4d.\n",start,(finish-1));
  418.     show = TRUE;
  419.     putchar('\n');
  420.     for (ct = start; ct < finish; ++ct) {
  421.         readloc(ct);
  422.         putchar('\n');
  423.     }
  424. }
  425.     
  426. /*
  427. ****************************
  428. ** MASTER BATTLE ROUTINES **
  429. ****************************
  430. */
  431.  
  432. /*
  433. ** Fight it out
  434. */
  435. fight()
  436. {
  437.     int ct, i;
  438.     show = FALSE;
  439.     fputs(CLRSCR,stderr);
  440.     fputs("\tPRESS ANY KEY TO BEGIN ",stderr);
  441.     while (bdos(06,0xff) == NULL);
  442.     fputs("\n\nBeginning Battle...\n\n",stderr);
  443.     fputs("\t> ^E to Abort <\n\n",stderr);
  444.     printf("\t\t%8s\t\t%8s\n\n",proga,progb);
  445.     for (ct = 0; ct < CUTOFF; ++ct) {
  446.         if ((ct % 5) == 0)
  447.             fputc('\n',stderr);
  448.         stout(ct);
  449.         now = 0;
  450.         if (readloc(pc[0]) == NULL)
  451.             break;
  452.         putchar('\t');
  453.         now = 1;
  454.         if (readloc(pc[1]) == NULL)
  455.             break;
  456.         putchar('\n');
  457.         if ((bdos(6,0xff)&0x7f) == ENQ)
  458.             break;
  459.         for (i = 0; i <2; ++i)
  460.             pc[i] = reladr(pc[i],0);
  461.     }
  462.     fputc(BEL,stderr);
  463.     printf("\nBattle Completed after %d instruction cycles!\n",ct);
  464.     if (ct == CUTOFF)
  465.         fputs("\>Draw<\n",stderr);
  466. }    
  467.  
  468. /*
  469. ** read a location, print the mnemonic, and perform it
  470. */
  471. readloc(loc) int loc;
  472. {
  473.     char ma, mb; int res;
  474.     instr = modea = modeb = code[loc];
  475.     instr &= 15;        /* or 0x0F */
  476.     modea = (modea / 64) & 3;
  477.     modeb = (modeb / 16) & 3;
  478.     res = -1;
  479.     if (instr == 1)            /* can't use switch with char arg */
  480.         mov();
  481.     else if (instr == 2)
  482.         add();
  483.     else if (instr == 3)
  484.         sub();
  485.     else if (instr == 4)
  486.         jmp();
  487.     else if (instr == 5)
  488.         jmz();
  489.     else if (instr == 6)
  490.         jmg();
  491.     else if (instr == 7)
  492.         djz();
  493.     else if (instr == 8)
  494.         cmp();
  495.     else {
  496.         puts("DAT");
  497.         res = NULL;
  498.     }
  499.     printf("\t%c%3d\t%c%3d [%3d]",mnem(modea),arga[loc],mnem(modeb),argb[loc],loc);
  500.     return(res);
  501. }
  502.  
  503. /*
  504. *********************************************
  505. ** functions to perform Redcode operations **
  506. *********************************************
  507. */
  508.  
  509. /*
  510. ** Redcode MOV instruction
  511. */
  512. mov()
  513. {
  514.     int a,b;
  515.     puts("MOV");
  516.     if (show)
  517.         return(NULL);
  518.     b = findadr(pc[now], &argb[0], modeb);
  519.     if (modea == IMMEDIATE) {
  520.         code[b] = 0;            /* make it a DAT */
  521.         argb[b] = arga[pc[now]];
  522. #ifdef FULLIST
  523.         printf("|#%6d>%3d|",arga[pc[now]],b);
  524. #endif
  525.     } else {
  526.         a = findadr(pc[now], &arga[0], modea);
  527. #ifdef FULLIST
  528.         printf("|%3d>%3d|",a,b);
  529. #endif
  530.         code[b] = code[a];
  531.         arga[b] = arga[a];
  532.         argb[b] = argb[a];
  533.     }
  534.     ++pc[now];
  535. }
  536.  
  537. /*
  538. ** Redcode ADD instruction
  539. */
  540. add()
  541. {
  542.     int a,b;
  543.     puts("ADD");
  544.     if (show)
  545.         return(NULL);
  546.     b = findadr(pc[now], &argb[0], modeb);
  547.     if (modea == IMMEDIATE) {
  548.         argb[b] += arga[pc[now]];
  549. #ifdef FULLIST
  550.         printf("|#%6d+%3d|",arga[pc[now]],b);
  551. #endif
  552.     } else {
  553.         a = findadr(pc[now], &arga[0], modea);
  554. #ifdef FULLIST
  555.         printf("|%3d+%3d|",b,a);
  556. #endif
  557.         argb[b] += arga[a];
  558.     }
  559.     ++pc[now];
  560. }
  561.  
  562. /*
  563. ** Redcode SUB instruction
  564. */
  565. sub()
  566. {
  567.     int a,b;
  568.     puts("SUB");
  569.     if (show)
  570.         return(NULL);
  571.     b = findadr(pc[now], &argb[0], modeb);
  572.     if (modea == IMMEDIATE) {
  573.         argb[b] -= arga[pc[now]];
  574. #ifdef FULLIST
  575.         printf("|%3d-#%6d|",b,arga[pc[now]]);
  576. #endif
  577.     } else {
  578.         a = findadr(pc[now], &arga[0],modea);
  579. #ifdef FULLIST
  580.         printf("|%3d-%3d|",b,a);
  581. #endif
  582.         argb[b] -= arga[a];
  583.     }
  584.     ++pc[now];
  585. }
  586.  
  587. /*
  588. ** Redcode JMP Instruction
  589. */
  590. jmp()
  591. {
  592.     int a;
  593.     puts("JMP");
  594.     if (show)
  595.         return(NULL);
  596.     pc[now] = findadr(pc[now], &arga[0], modea);
  597. }
  598.  
  599. /*
  600. ** Redcode JMZ instruction
  601. */
  602. jmz()
  603. {
  604.     int b;
  605.     puts("JMZ");
  606.     if (show)
  607.         return(NULL);
  608.     b = findadr(pc[now], &argb[0], modeb);
  609. #ifdef FULLIST
  610.     printf("|%3d|",b);
  611. #endif
  612.     if (argb[b] == 0)
  613.         pc[now] = findadr(pc[now], &arga[0], modea);
  614.     else
  615.         ++pc[now];
  616. }
  617.  
  618.  
  619. /*
  620. ** Redcode JMG Instruction
  621. */
  622. jmg()
  623. {
  624.     int b;
  625.     puts("JMG");
  626.     if (show)
  627.         return(NULL);
  628.     b = findadr(pc[now], &argb[0], modeb);
  629. #ifdef FULLIST
  630.     printf("|%3d|",b);
  631. #endif
  632.     if (argb[b] != 0)
  633.         pc[now] = findadr(pc[now], &arga[0], modea);
  634.     else
  635.         ++pc[now];
  636. }
  637.     
  638. /*
  639. ** Redcode DJZ Instruction
  640. */
  641. djz()
  642. {
  643.     int b;
  644.     puts("DJZ");
  645.     if (show)
  646.         return(NULL);
  647.     b = findadr(pc[now], &argb[0], modeb);
  648. #ifdef FULLIST
  649.     printf("|%3d|",b);
  650. #endif
  651.     if ((--argb[b]) == NULL)
  652.         pc[now] = findadr(pc[now], &arga[0], modea);
  653.     else
  654.         ++pc[now];
  655. }
  656.  
  657. /*
  658. ** Redcode CMP Instruction
  659. */
  660. cmp()
  661. {
  662.     int a,b;
  663.     puts("CMP");
  664.     if (show)
  665.         return(NULL);
  666.     if (modea != IMMEDIATE) {
  667.         a = findadr(pc[now], &arga[0], modea);
  668.         a = argb[a];
  669.     } else
  670.         a = arga[pc[now]];
  671.     if (modeb != IMMEDIATE) {
  672.         b = findadr(pc[now], &argb[0], modeb);
  673.         b = argb[b];
  674.     } else
  675.         b = argb[pc[now]];
  676.     ++pc[now];
  677.     if (a != b)
  678.         ++pc[now];
  679. }
  680.  
  681. /*
  682. *************************
  683. ** Addressing Routines **
  684. *************************
  685. */
  686.  
  687. /*
  688. ** find an address via direct or indirect
  689. */
  690. findadr(orig,pab,mod) int orig, *pab; char mod;
  691. {
  692.     int p;
  693.     if (mod == IMMEDIATE)
  694.         return(orig);
  695.     p = reladr(orig,pab[orig]);
  696.     if (mod == INDEXED)
  697.         p = reladr(p,argb[p]);
  698.     return(p);
  699. }
  700.  
  701.  
  702. /*
  703. ** return an absolute address in the circular arena from a relative one
  704. */
  705. reladr(abs,rel) int abs,rel;
  706. {
  707.     int j;
  708.     if ((j = abs + rel) >= MAXSIZE)
  709.         j = reladr((j - MAXSIZE),0);
  710.     else if (j < 0)
  711.         j = reladr((j + MAXSIZE),0);
  712.     return(j);
  713. }
  714.  
  715. /*
  716. ****************************
  717. ** Miscellaneous routines **
  718. ****************************
  719. */
  720.  
  721. /*
  722. ** Start with a "clean slate" in the battle-code arena
  723. */
  724. clean()
  725. {
  726.     int i;
  727.     for (i = 0; i < MAXSIZE; ++i) {
  728.         code[i] = '\0';
  729.         arga[i] = NULL;
  730.         argb[i] = NULL;
  731.     }
  732. }
  733.  
  734. /*
  735. ** return appropriate character for addressing modes
  736. */
  737. mnem(c) char c;
  738. {
  739.     c &= 255;
  740.     if (c == IMMEDIATE)
  741.         return('#');
  742.     else if (c == INDEXED)
  743.         return('@');
  744.     else
  745.         return('.');
  746. }
  747.  
  748. /*
  749. ** return an integer from a string
  750. */
  751. stoi(str) char *str;
  752. {
  753.     int i,s;
  754.     if (*str == '-') {
  755.         s = -1;
  756.         ++str;
  757.     } else
  758.         s = 1;
  759.     i = 0;
  760.     while ((*str >= '0') && (*str <= '9'))
  761.         i = (10 * i) + (*str++ - '0');
  762.     i *= s;
  763.     return (i);
  764. }
  765.  
  766. /*
  767. ** print a string to stderr from an integer <= 9999
  768. */
  769. stout(i) int i;
  770. {
  771.     if (i < 0)
  772.         fputc('-',stderr);
  773.     fputc((i / 1000 + '0'),stderr);
  774.     i %= 1000;
  775.     fputc((i / 100 + '0'),stderr);
  776.     i %= 100;
  777.     fputc((i / 10 + '0'),stderr);
  778.     i %= 10;
  779.     fputc((i + '0'),stderr);
  780.     fputs(":\t",stderr);
  781. }
  782.  
  783. /*
  784. ** raw console io
  785. */
  786. keypr()
  787. {
  788.     int c;
  789.         while (!((c=bdos(6, 0xff)&0x7f)))
  790.             ;
  791.     return(c);
  792. }
  793.  
  794. /* end of CORE WARS 2 */
  795.  
  796.