home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
202_01
/
karel1.c
< prev
next >
Wrap
Text File
|
1979-12-31
|
22KB
|
684 lines
#include <stdio.h>
#include <ctype.h>
#define CURPOS '\033' /* ESC */
#define ERROR -1 /* error flag */
#define MAXLINE 150 /* longest input line */
#define NSECTS 8 /* number of sectors */
#define SECSIZ 128 /* sector size */
#define CPMEOF 0x1A /* end of file for op system */
#define BRACKET '['
#define LETTERH 'H'
#define SEMI ';'
#define TWO '2'
#define LETTERJ 'J'
char world[23][75]; /* array for Karel's world */
int bag; /* Karel's beeper bag */
int kst; /* Karel's street */
int kav; /* Karel's avenue */
char kdir; /* Karel's direction */
int last; /* next loc in sym table */
main(argc,argv)
int argc; /* number of arguments for main */
char **argv; /* arg vector */
{
char ans;
FILE *fileptr;
int speed;
if (argc < 3)
printf("MISSING FILENAME(S)\n");
else {
if ((fileptr = fopen(argv[2],"r")) != NULL) {
readworld(fileptr);
printworld();
} else {
initworld();
printworld();
}
fclose(fileptr);
set_curs(25,0,0,"CHANGE KAREL'S LOCATION? (Y/N)");
if ((ans = upper(getchr())) != 'N')
kareloc();
set_curs(25,0,75,"CHANGE BEEPERS IN WORLD? (Y/N)");
if ((ans = upper(getchr())) != 'N')
beeploc();
set_curs(25,0,75,"CHANGE BEEPERS IN BAG? (Y/N)");
if ((ans = upper(getchr())) != 'N')
bagloc();
set_curs(25,0,75,"CHANGE WALL LOCATIONS? (Y/N)");
if ((ans = upper(getchr())) != 'N')
wallsloc();
alterations();
set_curs(25,0,75,"EXECUTE PROGRAM? (Y/N)");
if ((ans = upper(getchr())) != 'Y') {
set_curs(25,0,75,"EXIT KAREL? (Y/N)");
if ((ans = upper(getchr())) != 'N')
exit();
}
saveworld(argv,fileptr);
do {
set_curs(25,0,75,"KAREL'S SPEED? (1,2,3)");
speed = getint();
} while (speed != 1 && speed != 2 && speed != 3);
createpgm(argv,speed);
}
}
char upper(c)
char c;
{
return islower(c) ? c-32 : c;
}
initworld() /* initialize "empty world" */
{
int i,j;
char c;
kst = 21; /* init Karel's st */
kav = 4; /* init Karel's ave */
kdir = '0'; /* init Karel's dir */
for (i = 0; i < 23; i++)
for (j = 0; j < 75; j++) /* blank out array */
world[i][j] = ' ';
for (i = 1; i < 21; i+=2)
for (j = 8; j < 75; j += 4)
world[i][j] = '.'; /* corners */
for (i = 0; i < 20; i++) {
world[i][6] = '|'; /* left edge of world */
world[i][74] = '|'; /* right edge of world */
}
for (j = 6; j < 75; j++) {
world[20][j] = '-'; /* lower edge of world */
world[0][j] = '-'; /* upper edge of world */
}
world[1][0] = 'S'; world[22][66] = 'A';
world[2][0] = 'T'; world[22][67] = 'V';
world[3][0] = 'R'; world[22][68] = 'E';
world[4][0] = 'E'; world[22][69] = 'N';
world[5][0] = 'E'; world[22][70] = 'U';
world[6][0] = 'T'; world[22][71] = 'E';
world[7][0] = 'S'; world[22][72] = 'S';
world[1][3] = '1'; world[1][4] = '0';
for (i = 3, c = '9'; i < 21; i += 2, c--)
world[i][4] = c; /* number streets */
for (j = 8, c = '1'; j < 75; j += 4, c++) {
world[21][j] = c; /* number avenues */
if (c > '9') {
world[21][--j] = '1';
world[21][++j] = c - 10;
}
}
}
readworld(fptr) /* input values from old world file */
FILE *fptr;
{
int i,j;
fscanf(fptr,"%d %d %d",&kst,&kav,&bag);
kdir = getc(fptr);
for (i = 0; i < 23; i++)
for (j = 0; j < 75; j++)
world[i][j] = getc(fptr);
}
printworld() /* output values stored in world array */
{
int i,j,kst2,kav2;
printf("%c%c%c%c",CURPOS,BRACKET,TWO,LETTERJ);
for (i = 0; i < 23; i++) {
set_curs(i+1,1,0,"");
for (j = 0; j < 75; j++) {
printf("%c",world[i][j]);
}
}
set_curs(25,37,0,"");
kst2 = (21 - kst)/2;
kav2 = (kav - 4)/4;
printf("KAREL'S ST= %d AVE= %d DIR= %c BAG= %d",
kst2,kav2,kdir,bag);
}
kareloc()/* determine street, avenue and direction for KAREL */
{
char ans,k;
k = world[kst][kav];
do {
if (kst != 0 && (k == '^' || k == 'V' ||
k == '>' || k == '<')) {
world[kst][kav] = '.';
set_curs(kst+1,kav+1,1,".");
}
do {
set_curs(25,0,75,"KAREL'S STREET?");
kst = getint();
} while (kst == 0 || kst > 10);
do {
set_curs(25,0,75,"KAREL'S AVENUE?");
kav = getint();
} while (kav == 0 || kav > 17);
kst = 21 - 2 * kst;
kav = 4 + 4 * kav;
set_curs(25,0,75,"DIRECTION? (N/S/E/W)");
kdir = upper(getchr());
storekarel();
set_curs(kst+1,kav+1,1,"");
printf("%c",kdir);
set_curs(25,0,75,"IS KAREL'S LOCATION CORRECT? (Y/N)");
if ((ans = upper(getchr())) != 'Y') {
set_curs(kst+1,kav+1,1,"");
printf("%c", world[kst][kav]);
}
} while (ans != 'Y');
if (world[kst][kav] == '.')
world[kst][kav] = kdir;
}
storekarel() /* determine KAREL's direction from console input */
{
char k;
switch(kdir) {
case 'N':
kdir = '^';
break;
case 'S':
kdir = 'V';
break;
case 'E':
kdir = '>';
break;
case 'W':
default:
kdir = '<';
}
}
beeploc() /* determine beeper locations */
{
int bst,bav,valid;
char ans;
ans = 'Y';
while (ans != 'N') {
do {
set_curs(25,0,75,"STREET?");
bst = getint();
} while (bst == 0 || bst > 10);
do {
set_curs(25,0,75,"AVENUE?");
bav = getint();
} while (bav == 0 || bav > 17);
bst = 21 - 2 * bst;
bav = 4 + 4 * bav;
set_curs(25,0,75,"TYPE A TO ADD OR D TO DELETE BEEPER");
if ((ans = upper(getchr())) != 'D') {
valid = putbeeper(bst,bav);
if (valid) {
set_curs(bst+1,bav+1,1,"");
printf("%c",world[bst][bav]);
set_curs(25,0,75,"IS BEEPER LOCATION CORRECT?(Y/N)");
if ((ans = upper(getchr())) != 'Y') {
pickbeeper(bst,bav);
set_curs(bst+1,bav+1,1,"");
printf("%c",world[bst][bav]);
}
}
} else {
pickbeeper(bst,bav);
set_curs(bst+1,bav+1,1,"");
printf("%c",world[bst][bav]);
}
set_curs(25,0,75,"OTHER BEEPER LOCATIONS? (Y/N)");
ans = upper(getchr());
}
}
bagloc() /* determine number of beepers in beeper bag */
{
char ans;
do {
set_curs(25,0,75,"HOW MANY BEEPERS IN BEEPER BAG?");
bag = getint();
set_curs(25,0,75,"");
printf("%d BEEPERS IN BAG, CORRECT? (Y/N)",bag);
} while ((ans = upper(getchr())) != 'Y');
}
putbeeper(bst,bav) /* place one beeper in the world */
int bst,bav; /* at bst street and bav avenue */
{
char k;
k = world[bst][bav];
if (k == '9') {
set_curs(25,0,75,"NO MORE THAN 9 BEEPERS ON A CORNER.");
set_curs(25,36,0,"TYPE ANY CHARACTER TO CONTINUE");
getchr();
return (0);
} else {
if (k == '.' || k == '^' || k == 'V' ||
k == '>' || k == '<')
k = '@';
else if (k == '@')
k = '2';
else ++k;
world[bst][bav] = k;
return(1);
}
}
pickbeeper(bst,bav) /* remove one beeper from the world */
int bst,bav; /* location bst street and bav avenue */
{
char k;
k = world[bst][bav];
if (k == '.' || k == '^' || k == 'V' ||
k == '<' || k == '>') {
set_curs(25,0,75,"NO BEEPER ON CORNER.");
set_curs(25,21,0,"TYPE ANY CHARACTER TO CONTINUE.");
getchr();
} else {
if (bst == kst && bav == kav && k == '@')
k = kdir;
else if (k == '2')
k = '@';
else if (k != '@')
--k;
else k = '.';
world[bst][bav] = k;
}
}
wallsloc() /* determine wall location(s) */
{
int i,j,s1,s2,st1,st2,a1,a2,av1,av2,horiz;
char ans;
do {
do {
set_curs(25,0,75,"BETWEEN WHAT STREETS?");
s1 = getint();
set_curs(25,0,40,"?");
s2 = getint();
} while (s1 < 0 || s2 < 0 || s1 > 11 || s2 > 11);
st1 = min(s1,s2);
st2 = max(s1,s2);
horiz = abs(st2 - st1);
st1 = 20 - 2 * st1;
st2 = 22 - 2 * st2;
do {
set_curs(25,0,40,"BETWEEN WHAT AVENUES?");
a1 = getint();
set_curs(25,0,40,"?");
a2 = getint();
} while (a1 < 0 || a2 < 0 || a1 > 18 || a2 > 18);
av1 = min(a1,a2);
av2 = max(a1,a2);
av1 = 6 + 4 * av1;
av2 = 2 + 4 * av2;
set_curs(25,0,75,"TYPE A TO ADD OR D TO DELETE THE WALL.");
if ((ans = upper(getchr())) != 'D') {
addwall(st1,st2,av1,av2,horiz);
set_curs(25,0,40,"IS WALL LOCATION CORRECT? (Y/N)");
if ((ans = upper(getchr())) != 'Y')
erasewall(st1,st2,av1,av2,horiz);
else {
set_curs(25,0,40,"IS THIS THE LAST WALL? (Y/N)");
ans = upper(getchr());
}
} else {
erasewall(st1,st2,av1,av2,horiz);
set_curs(25,0,40,"IS THIS THE LAST WALL? (Y/N)");
ans = upper(getchr());
}
} while (ans != 'Y');
}
addwall(st1,st2,av1,av2,horiz) /* add one wall to the world */
int st1,st2,av1,av2,horiz;
{
int i,j;
if (horiz == 1)
for (j = av1; j <= av2; j++) {
if (world[st1][j] == '|' ||
world[st1][j] == '+')
world[st1][j] = '+';
else world[st1][j] = '-';
set_curs(st1+1,j+1,1,"");
printf("%c",world[st1][j]);
}
else for (i = st2; i <= st1; i++) {
if (world[i][av1] == '-' ||
world[i][av1] == '+')
world[i][av1] = '+';
else world[i][av1] = '|';
set_curs(i+1,av1+1,1,"");
printf("%c",world[i][av1]);
}
}
erasewall(st1,st2,av1,av2,horiz) /* remove one wall from the world */
int st1,st2,av1,av2,horiz;
{
int i,j;
if (horiz == 1)
for (j = av1; j <= av2; j++) {
if (j == 6 || j ==74)
world[st1][j] = '|';
else if (world[st1][j] == '+')
world[st1][j] = '|';
else world[st1][j] = ' ';
set_curs(st1+1,j+1,1,"");
printf("%c",world[st1][j]);
}
else for (i = st2; i <= st1; i++) {
if (i == 0 || i == 20)
world[i][av1] = '-';
else if (world[i][av1] == '+')
world[i][av1] = '-';
else world[i][av1] = ' ';
set_curs(i+1,av1+1,1,"");
printf("%c",world[i][av1]);
}
}
int atoi(n)
char *n;
{
int val;
char c;
int sign;
val=0;
sign=1;
while ((c = *n) == '/t' || c== ' ') ++n;
if (c== '-') {sign = -1; n++;}
while ( isdigit(c = *n++)) val = val * 10 + c - '0';
return sign*val;
}
getint() /* determine integer input from console */
{
char str[5];
int in;
inputs(str);
in = atoi(str);
return in;
}
inputs(str) /* read string input from console */
char str[];
{
int j;
j = 0;
while ((str[j++] = getchr()) != '\r')
;
str[--j] = '\0';
}
alterations() /* additional changes to the world */
{
char ans;
set_curs(25,0,40,"ANY FURTHER CHANGES TO THE WORLD? (Y/N)");
while ((ans = upper(getchr())) != 'N') {
set_curs(25,0,40,"CHANGE KAREL'S POSITION? (Y/N)");
if ((ans = upper(getchr())) == 'Y')
kareloc();
set_curs(25,0,40,"CHANGE BEEPERS IN WORLD? (Y/N)");
if ((ans = upper(getchr())) == 'Y')
beeploc();
set_curs(25,0,40,"CHANGE BEEPERS IN BAG? (Y/N)");
if ((ans = upper(getchr())) == 'Y')
bagloc();
set_curs(25,0,40,"CHANGE WALL LOCATIONS? (Y/N)");
if ((ans = upper(getchr())) == 'Y')
wallsloc();
set_curs(25,0,40,"ANY FURTHER CHANGES TO THE WORLD? (Y/N)");
}
}
set_curs(row,col,blanks,mess) /* set cursor and print message */
int row,col,blanks;
char *mess;
{
int j;
printf("%c%c%d%c%d%c",CURPOS,BRACKET,row,SEMI,col,LETTERH);
for (j = 1; j <= blanks; j++)
printf(" "); /* blank out previous message */
printf("%c%c%d%c%d%c",CURPOS,BRACKET,row,SEMI,col,LETTERH);
printf("%s", mess); /* output current message */
}
saveworld(argv,fptr) /* save world array in second file */
char **argv;
FILE *fptr;
{
int i,j;
fptr = fopen(argv[2],"w");
fprintf(fptr,"%d %d %d",kst,kav,bag);
putc(kdir,fptr);
for (i = 0; i < 23; i++)
for (j = 0; j < 75; j++)
putc(world[i][j],fptr);
putc(CPMEOF,fptr);
fclose(fptr);
}
getchr() /* low-level character input */
{
char c;
c = getch();
putch(c);
return c;
}
createpgm(argv,speed) /* create C pgm from parse tree */
char **argv;
int speed;
{
int i,in,d,fn,fs,b,t,l,reloc[10];
char newname[10][MAXLINE],fname[12];
char *test[19],*j[9];
FILE *fileptro,*fileptri;
last = 0;
init(test);
if ((fileptri = fopen(argv[1],"r")) == NULL)
printf("CAN'T FIND TREE FILE.\n");
else {
strcpy(fname,argv[1]);
strcat(fname,".C");
if (( fileptro = fopen(fname,"w")) == NULL)
printf("CAN'T CREATE NEW FILE.\n");
else {
fprintf(fileptro,"#include <stdio.h>\n");
fprintf(fileptro,"%s%d%s","#define SPEED ",speed,"\n");
fprintf(fileptro,"#include <karel.h>\n");
setupspace(j);
fprintf(fileptro,"int j1,j2,j3,j4,j5,j6,j7,j8;\n");
fscanf(fileptri,"%d %d %d %d %d %d %d %d",&i,&in,&d,&fn,&fs,&b,&t,&l);
fscanf(fileptri,"%d %d %d %d %d %d %d %d",&i,&in,&d,&fn,&fs,&b,&t,&l);
while (i != 9) { /* translate to end of program */
createline(j,i,in,d,newname,reloc,test,fileptri,fileptro);
fscanf(fileptri,"%d %d %d %d %d %d %d %d",&i,&in,&d,&fn,&fs,&b,&t,&l);
}
fprintf(fileptro," turnoff(4);\n");
fprintf(fileptro," } \n");
putc(CPMEOF,fileptro);
fclose(fileptri);
fclose(fileptro);
}
}
}
setupspace(j) /* initialize array of ITERATE loop counters */
char *j[9];
{
char *malloc();
int i;
for (i = 0; i <= 8; i++)
j[i] = malloc(2);
j[1] = "j1"; j[2] = "j2";
j[3] = "j3"; j[4] = "j4";
j[5] = "j5"; j[6] = "j6";
j[7] = "j7"; j[8] = "j8";
}
init(test) /* initialize array with C version of tests */
char *test[19];
{
int i;
char *malloc();
for (i = 0; i < 19; i++) /* allocate space for tests */
test[i] = malloc(10);
test[0] = "nnorth";
test[1] = "!nnorth";
test[2] = "ssouth";
test[3] = "!ssouth";
test[4] = "eeast";
test[5] = "!eeast";
test[6] = "wwest";
test[7] = "!wwest";
test[8] = "ccorner";
test[9] = "!ccorner";
test[10] = "bbag";
test[11] = "!bbag";
test[12] = "ffront";
test[13] = "!ffront";
test[14] = "lleft";
test[15] = "!lleft";
test[16] = "rright";
test[17] = "!rright";
}
createline(j,i,in,d,newname,reloc,test,fptri,fptro)
int i,in,d,reloc[10];
char newname[10][MAXLINE],*test[19],*j[9];
FILE *fptri,*fptro;
{
int k,fn,fs,b,t,l;
char w[MAXLINE];
for (k = 0; k < (in - 1); k++)
fprintf(fptro," ");
if (d != 4)
switch(i) {
case 0:
fprintf(fptro,"move();\n");
break;
case 1:
fprintf(fptro,"turnleft();\n");
break;
case 2:
fprintf(fptro,"pickbeeper();\n");
break;
case 3:
fprintf(fptro,"putbeeper();\n");
break;
case 4:
fprintf(fptro,"turnoff(0);\n");
break;
case 5:
fprintf(fptro,"{ \n");
break;
case 7:
fprintf(fptro,"\nmain(argc,argv) \n");
fprintf(fptro,"int argc;\n");
fprintf(fptro,"char **argv;\n");
fprintf(fptro," { \n");
fprintf(fptro," set_up(argv);\n");
break;
case 8:
fprintf(fptro,"} \n");
break;
case 11:
fscanf(fptri,"%d %d %d %d %d %d %d %d",&i,&in,&d,&fn,&fs,&b,&t,&l); /* read test */
fprintf(fptro,"if (%s)\n",test[i]);
fscanf(fptri,"%d %d %d %d %d %d %d %d",&i,&in,&d,&fn,&fs,&b,&t,&l); /* skip THEN */
break;
case 13:
fprintf(fptro,"else\n");
break;
case 14:
fscanf(fptri,"%d %d %d %d %d %d %d %d",&i,&in,&d,&fn,&fs,&b,&t,&l);
fprintf(fptro,"for (%s = 0; %s < %d; %s++)\n",
j[in],j[in],i,j[in]);
break;
case 15:
fscanf(fptri,"%d %d %d %d %d %d %d %d",&i,&in,&d,&fn,&fs,&b,&t,&l);
fprintf(fptro,"while (%s)\n",test[i]);
break;
case 16:
fscanf(fptri,"%d %d %d %d %d %d %d %d",&i,&in,&d,&fn,&fs,&b,&t,&l);
while ((getc(fptri)) != '\n');
i = reloc[i] = last++;
k = 0;
while ((w[k++] = getc(fptri)) != '\n')
if (w[k - 1] == '-')
w[k - 1] = '_';
k -= 2;
w[k] = '\0';
strcpy(newname[i],w);
fprintf(fptro,"\n%s()\n",newname[i]);
break;
default:
;
}
else {
i = reloc[i];
fprintf(fptro,"%s();\n",newname[i]);
}
}