#include <dos.h>
#include <conio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <alloc.h>
#include <graphics.h>
#define EXTCDECL extern
#include "goh.c"
/* screen and keyboard functions */
/* most operating system calls are in ibm.c */
unsigned solkey() /* return zero if no key waiting */
{
unsigned key, shift, test;
key = bioskey(1);
if (key) key = bioskey(0);
if (key == 0x0e08) key &= 0xff00; /* separate Backspace and Ctrl-H */
if (key == 0x0f09) key &= 0xff00; /* separate Tab and Ctrl-I */
if (key == 0x1c0d) key &= 0xff00; /* separate CR and Ctrl-M */
test = key & 0xff;
if (test) key = test;
shift = bioskey(2);
shift &= 3; /* either left or right shift */
if (shift) {
if (key == LEFT) key = SLEFT;
if (key == RIGHT) key = SRIGHT;
if (key == UP) key = SUP;
if (key == DOWN) key = SDOWN;
}
return(key);
}
unsigned getkey() /* wait for a key ... negative is IBM code */
{
unsigned key;
do {
key = solkey();
} while (!key);
return(key);
}
void flushkey()
{
unsigned key;
do {
key = solkey();
} while (key);
}
int iscanf(int dflt) /* scan keyboard for an integer (dflt if null) */
{
int value;
char buf[128];
unsigned c;
unsigned key;
int i;
i = 0;
do {
key = getkey();
if (key == BACKSP) { /* backspace detect */
if (i) {
putch(8);
putch(' ');
putch(8);
}
if (i > 0) --i;
key = 0;
}
if (key == LEFT) { /* back cursor */
if (i) {
putch(8);
putch(' ');
putch(8);
}
if (i > 0) --i;
key = 0;
}
if (key) {
c = key & 255;
if (c) putch(c);
buf[i] = c;
++i;
}
} while (key != CR);
buf[i-1] = 0;
if (i != 1) value = atoi(buf);
else value = dflt;
return(value);
}
int bscanf(char *buf, int max) /* scan keyboard for char string + CR */
{
int value; /* return 0 if null line bufsize otherwise */
unsigned c;
unsigned key;
int i;
value = 0;
i = 0;
do {
key = getkey();
c = key & 255;
if (key == BACKSP) { /* intercept backspace */
if (i) {
putch(8);
putch(' ');
putch(8);
}
if (i > 0) --i;
key = 0;
}
if (key == LEFT) { /* back cursor */
if (i) {
putch(8);
putch(' ');
putch(8);
}
if (i > 0) --i;
key = 0;
}
if (key) {
buf[i] = c;
if (i < max) {
if (c) putch(c);
++i;
}
}
} while (key != CR);
buf[i-1] = 0;
if (i == 1) value = 0;
else value = i;
return(value);
}
unsigned cput(flag)
unsigned flag; /* 0 to reset ... 1 to return elapsed time */
{
struct time now;
unsigned hunds;
long elapsed;
hunds = 0;
elapsed = 0;
gettime(&now);
if (!flag) {
thour = now.ti_hour;
tmin = now.ti_min;
tsec = now.ti_sec;
thund = now.ti_hund;
}
else {
elapsed += now.ti_hour - thour;
elapsed *= 60;
elapsed += now.ti_min - tmin;
elapsed *= 60;
elapsed += now.ti_sec - tsec;
elapsed *= 100;
elapsed += now.ti_hund - thund;
}
if ((elapsed > 0) && (elapsed <= 30000)) hunds = elapsed;
return(hunds);
}
void hundelay(hundsec)
unsigned hundsec;
{
unsigned hunds;
if (hundsec) {
hunds = cput(0);
do {
hunds = cput(1);
} while (hunds < hundsec);
}
}
void locatec(index)
unsigned index;
{
int inline, inchar;
char nline, nchar;
#if DDD
unsigned z;
z = ((index-1) / nsize) / nsize + 1;
index -= (z-1) * nsize * nsize;
#endif
inline = (index - 1) / nsize;
inchar = index - nsize * inline;
#if DONUT
inline += ydonut;
inchar += xdonut;
if (inline < 0) inline += nsize;
if (inline >= nsize) inline -= nsize;
if (inchar < 1) inchar += nsize;
if (inchar > nsize) inchar -= nsize;
#endif
inline += ((19 - nsize) / 2);
inchar += ((19 - nsize) / 2);
inchar += inchar;
nline = inline;
nchar = inchar;
scr_rowcol(nline, nchar);
}
void mocatec(index)
unsigned index;
{
int inline, inchar;
char nline, nchar;
#if DDD
unsigned z;
z = ((index-1) / nsize) / nsize + 1;
index -= (z-1) * nsize * nsize;
#endif
inline = (index - 1) / nsize;
inchar = index - nsize * inline;
#if DONUT
inline += ydonut;
inchar += xdonut;
if (inline < 0) inline += nsize;
if (inline >= nsize) inline -= nsize;
if (inchar < 1) inchar += nsize;
if (inchar > nsize) inchar -= nsize;
#endif
inline += ((19 - nsize) / 2);
inchar += ((19 - nsize) / 2);
inchar += inchar;
nline = inline;
nchar = inchar + 1;
scr_rowcol(nline, nchar);
}
unsigned twist(unsigned index)
{
unsigned newx, newy;
unsigned x, y;
#if DDD
unsigned z;
z = ((index-1) / nsize) / nsize + 1;
index -= (z-1) * nsize * nsize;
#endif
xy(index, &x, &y);
newx = x;
newy = y;
if (twister == 1) {
newx = y;
newy = nsize -x + 1;
}
else if (twister == 2) {
newx = nsize - x + 1;
newy = nsize - y + 1;
}
else if (twister == 3) {
newx = nsize - y + 1;
newy = x;
}
x = newx;
y = newy;
index = fxy(x, y);
#if DDD
index += (z-1) * nsize * nsize;
#endif
return(index);
}
unsigned xgboard(unsigned index)
{
unsigned xc;
int x, y, z;
z = ((index-1) / nsize) / nsize + 1;
index -= (z-1) * nsize * nsize;
xy(index, &x, &y);
#if DONUT
x += ydonut;
if (x < 1) x += nsize;
if (x > nsize) x -= nsize;
y += xdonut;
if (y < 1) y += nsize;
if (y > nsize) y -= nsize;
#endif
xc = 360; /* Hercules center */
xc += (xrad+xrad) * (y-(nsize+1)/2) + ((nsize+1)-x*2) * persp;
return(xc);
}
unsigned ygboard(unsigned index)
{
unsigned yc;
int x, y, z;
z = ((index-1) / nsize) / nsize + 1;
index -= (z-1) * nsize * nsize;
xy(index, &x, &y);
#if DONUT
x += ydonut;
if (x < 1) x += nsize;
if (x > nsize) x -= nsize;
y += xdonut;
if (y < 1) y += nsize;
if (y > nsize) y -= nsize;
#endif
#if DDD
yc = 125;
yc += (z-1) * zinc;
#else
yc = 174; /* Hercules center */
#endif
yc += (yrad+yrad) * ((nsize+1)/2-x) + ((int)((nsize+1)-y*2)/2) * persp;
return(yc);
}
unsigned handipt(unsigned index)
{
unsigned handi;
unsigned xhand, yhand;
int x, y;
xy(index, &x, &y);
xhand = 0;
if (x == 4) xhand = 1;
if (x == 10) xhand = 1;
if (x == 16) xhand = 1;
yhand = 0;
if (y == 4) yhand = 1;
if (y == 10) yhand = 1;
if (y == 16) yhand = 1;
if (xhand && yhand) handi = 1;
else handi = 0;
return(handi);
}
void curof(index)
unsigned index;
{
unsigned x, y, xc, yc, xhand, yhand;
struct root *rootp;
char c;
if (index) {
rootp = dir[index];
invid[index] = 0;
if (col80) {
mocatec(index);
scr_mark(' ', 7);
locatec(index);
c = scr_sinp();
scr_mark(c, 7);
}
else {
setcolor(BLACK);
if (rootp) {
if (rootp->clr == WHT) setcolor(WHITE);
}
index = twist(index);
xy(index, &x, &y);
xc = xgboard(index);
yc = ygboard(index);
if (north(index)) {
zline(xc, yc, xc+persp/2, yc+yrad/2);
}
if (west(index)) {
zline(xc, yc, xc-xrad/2, yc+persp/4);
}
if (east(index)) {
zline(xc, yc, xc+xrad/2, yc-persp/4);
}
if (south(index)) {
zline(xc, yc, xc-persp/2, yc-yrad/2);
}
if (1) {
xhand = 0;
if (x == 4) xhand = 1;
if (x == 10) xhand = 1;
if (x == 16) xhand = 1;
yhand = 0;
if (y == 4) yhand = 1;
if (y == 10) yhand = 1;
if (y == 16) yhand = 1;
if (xhand && yhand && !dir[index]) {
setcolor(WHITE);
blackfill();
zfillellipse(xc, yc, 2, 2);
}
}
}
}
}
void curon(index)
unsigned index;
{
unsigned x, y, xc, yc;
struct root *rootp;
char c;
if (index) {
invid[index] = 1;
if (col80) {
mocatec(index);
scr_mark(' ', 112);
locatec(index);
c = scr_sinp();
scr_mark(c, 112);
}
else {
setcolor(WHITE);
rootp = dir[index];
if (rootp) {
if (rootp->clr == WHT) setcolor(BLACK);
}
index = twist(index);
xc = xgboard(index);
yc = ygboard(index);
if (north(index)) {
zline(xc, yc, xc+persp/2, yc+yrad/2);
}
if (west(index)) {
zline(xc, yc, xc-xrad/2, yc+persp/4);
}
if (east(index)) {
zline(xc, yc, xc+xrad/2, yc-persp/4);
}
if (south(index)) {
zline(xc, yc, xc-persp/2, yc-yrad/2);
}
}
}
}
unsigned strtscrl()
{
unsigned line;
line = 1;
return (line);
}
unsigned stopscrl()
{
unsigned line;
line = 18;
if (col80) line = 23;
return (line);
}
unsigned xscrl()
{
unsigned column;
column = 23;
if (col80) column = 43;
return (column);
}
void typeset(i, j)
unsigned i, j;
{
unsigned ichar;
char ci, cj;
ci = i;
cj = j;
scr_rowcol(ci, cj); /* set cursor to i,j */
}
void clearline()
{
if (col80) {
printf(" ");
}
}
void subline()
{
unsigned nextline;
if (linum < strtscrl()) linum = strtscrl();
nextline = linum + 1;
if (nextline > stopscrl()) nextline = strtscrl();
typeset(nextline, xscrl());
clearline();
typeset(nextline, xscrl());
printf("...");
typeset(linum, xscrl());
clearline();
typeset(linum, xscrl());
linum = nextline;
}
void newline()
{
if (!col80) switchscreen();
keybreak(0);
subline();
}
void turnon(indexes)
struct link *indexes;
{
struct link *linkp;
unsigned jndex;
linkp = indexes;
if (linkp) {
do {
jndex = linkp->loc;
if (jndex) {
curon(jndex);
/*
newline();
coords(jndex);
*/
}
linkp = linkp->nextl;
} while (linkp);
}
}
void xtturnon(indexes)
unsigned indexes;
{
unsigned linkp;
unsigned jndex;
linkp = indexes;
if (linkp) {
do {
jndex = peek(linkp, LOC);
if (jndex) curon(jndex);
linkp = peek(linkp, NEXTL);
} while (linkp);
}
}
void xtturnof(indexes)
unsigned indexes;
{
unsigned linkp;
unsigned jndex;
linkp = indexes;
if (linkp) {
do {
jndex = peek(linkp, LOC);
if (jndex) curof(jndex);
linkp = peek(linkp, NEXTL);
} while (linkp);
}
}
void xtboxes(indexes)
unsigned indexes;
{
unsigned linkp;
unsigned jndex;
linkp = indexes;
if (linkp) {
do {
jndex = peek(linkp, LOC);
if (jndex) {
locatec(jndex);
scr_co(0xb0);
}
linkp = peek(linkp, NEXTL);
} while (linkp);
}
}
unsigned flip(bw)
unsigned bw;
{
if (bw == BLK) bw = WHT;
else bw = BLK;
return(bw);
}
unsigned tranctl(key)
unsigned key;
{
unsigned result;
result = key;
if (key) {
if (key == 72) result = 30; /* cursor arrow keys */
if (key == 80) result = 31;
if (key == 75) result = 29;
if (key == 77) result = 28;
if (key == 71) result = 200;
if (key == 79) result = 201;
if (key == 73) result = 202;
if (key == 81) result = 203;
if (key == 0x77) result = 204;
if (key == 0x75) result = 205;
}
return (result);
}
unsigned odd(number)
unsigned number;
{
unsigned result;
result = number & 1;
return (result);
}
unsigned even(number)
unsigned number;
{
unsigned result;
result = !odd(number);
return (result);
}
void agstone(index, x, y)
unsigned index;
unsigned x, y;
{
int i;
unsigned j[11] = {7,7,7,7,7,7,6,5,4,3,2};
unsigned k[11] = {7,7,7,7,7,6,5,4,3,2,1};
unsigned m[11] = {7,7,7,7,6,5,4,3,2,1,0};
/*unsigned n[11] = {7,7,7,7,6,5,4,3,2,1,0};*/
unsigned usej, usek, usem, iswhite, iseven;
struct root *rootp;
rootp = dir[index];
iswhite = rootp->clr == WHT;
setlinestyle(0,0,1);
if (!iswhite) {
for (i=0; i<=10; ++i) zline(x+i, y-j[i], x+i, y+k[i]);
for (i=0; i<=10; ++i) zline(x-i-1, y-k[i], x-i-1, y+m[i]);
}
else {
for (i=0; i<=10; ++i) zline(x+i, y-k[i]-1, x+i, y+j[i]);
for (i=0; i<=10; ++i) zline(x-i-1, y-m[i]-1, x-i-1, y+k[i]);
}
}
void showlink(jndex, kndex, bw)
unsigned jndex;
unsigned kndex;
unsigned bw;
{
int i, j;
unsigned x1, y1, x2, y2;
x1 = xgboard(jndex);
y1 = ygboard(jndex);
x2 = xgboard(kndex);
y2 = ygboard(kndex);
if (bw == BLK) setcolor(BLACK);
else setcolor(WHITE);
for (i=-1; i<=1; ++i) {
for (j=-1; j<=1; ++j) {
zplt(x1+i, y1+j, 0);
zplt(x2+i, y2+j, 1);
}
}
setcolor(WHITE);
}
int yltf(x, y, xi, yi, xj, yj)
int x;
int y;
int xi;
int yi;
int xj;
int yj;
{
int allow; /* return 1 if y < line(i,j) given x */
int newy;
allow = 0;
if (xj != xi) {
newy = yi + ((long) (x-xi) * (yj - yi)) / (xj - xi);
if (y < newy) allow = 1;
}
return(allow);
}
int ygtf(x, y, xi, yi, xj, yj)
int x;
int y;
int xi;
int yi;
int xj;
int yj;
{
int allow; /* return 1 if y < line(i,j) given x */
int newy;
allow = 0;
if (xj != xi) {
newy = yi + ((long) (x-xi) * (yj - yi)) / (xj - xi);
if (y > newy) allow = 1;
}
return(allow);
}
void showarea(index, jndex, kndex, bw)
unsigned index;
unsigned jndex;
unsigned kndex;
unsigned bw;
{
int x, y, allow, area;
int xi, yi, xj, yj, xk, yk;
int xmin, xmax, ymin, ymax;
xi = xgboard(index);
yi = ygboard(index);
xj = xgboard(jndex);
yj = ygboard(jndex);
xk = xgboard(kndex);
yk = ygboard(kndex);
xmin = min(min(xi, xj), min(xj, xk));
xmax = max(max(xi, xj), max(xj, xk));
ymin = min(min(yi, yj), min(yj, yk));
ymax = max(max(yi, yj), max(yj, yk));
/*
newline();
printf(" showarea");
coords(index);
coords(jndex);
coords(kndex);
newline();
printf(" xmn:%d xmx:%d ymn:%d ymx:%d", xmin, xmax, ymin, ymax);
*/
if (bw == BLK) setcolor(BLACK);
else setcolor(WHITE);
for (y=ymin; y<=ymax; ++y) {
for (x=xmin; x<=xmax; ++x) {
allow = 1;
if (xi == xj) {
if (!yltf(x, y, xi, yi, xk, yk)) allow = 0;
if (!ygtf(x, y, xj, yj, xk, yk)) allow = 0;
}
else if (xi == xk) {
if (!yltf(x, y, xi, yi, xj, yj)) allow = 0;
if (!ygtf(x, y, xj, yj, xk, yk)) allow = 0;
}
else if (xj == xk) {
if (!yltf(x, y, xi, yi, xj, yj)) allow = 0;
if (!ygtf(x, y, xi, yi, xk, yk)) allow = 0;
}
else {
area = howbig(index, jndex, kndex);
if (area > 0) {
if (xj < xi) {
if (!yltf(x, y, xi, yi, xj, yj)) allow = 0;
if (xk > xj) {
if (!ygtf(x, y, xj, yj, xk, yk)) allow = 0;
}
if (xk < xj) {
if (!yltf(x, y, xj, yj, xk, yk)) allow = 0;
}
if (xi > xk) {
if (!ygtf(x, y, xi, yi, xk, yk)) allow = 0;
}
if (xi < xk) {
if (!yltf(x, y, xi, yi, xk, yk)) allow = 0;
}
}
if (xj > xi) {
if (!yltf(x, y, xi, yi, xk, yk)) allow = 0;
if (!ygtf(x, y, xj, yj, xk, yk)) allow = 0;
if (!ygtf(x, y, xi, yi, xj, yj)) allow = 0;
}
}
if (area < 0) {
if (xj > xi) {
if (!yltf(x, y, xi, yi, xj, yj)) allow = 0;
if (xj > xk) {
if (!ygtf(x, y, xj, yj, xk, yk)) allow = 0;
}
if (xj < xk) {
if (!yltf(x, y, xj, yj, xk, yk)) allow = 0;
}
if (xk > xi) {
if (!ygtf(x, y, xi, yi, xk, yk)) allow = 0;
}
if (xk < xi) {
if (!yltf(x, y, xi, yi, xk, yk)) allow = 0;
}
}
if (xj < xi) {
if (!yltf(x, y, xi, yi, xk, yk)) allow = 0;
if (!ygtf(x, y, xj, yj, xk, yk)) allow = 0;
if (!ygtf(x, y, xi, yi, xj, yj)) allow = 0;
}
}
}
if (allow) {
if ((rand()&4) && (rand()&4)) {
zplt(x, y, 0);
zplt(x, y, 1);
}
}
}
}
setcolor(WHITE);
}
void showdead()
{
unsigned index;
struct link *rootlp;
struct root *rootp;
struct link *stonep;
rootlp = rootlist->nextl;
if (rootlp) {
do {
rootp = rootlp->loc;
stonep = rootp->neighbs->nextl;
do {
index = stonep->loc;
if (!rootp->reallive && !rootp->realdead) {
if (col80) {
locatec(index);
if (rootp->clr == BLK) scr_co(BSEKI);
if (rootp->clr == WHT) scr_co(WSEKI);
}
if (!col80) {
}
}
if (rootp->realdead) {
if (col80) {
locatec(index);
if (rootp->clr == BLK) scr_co(BDEAD);
if (rootp->clr == WHT) scr_co(WDEAD);
}
if (!col80) {
}
}
stonep = stonep->nextl;
} while (stonep);
rootlp = rootlp->nextl;
} while (rootlp);
}
}
int isqrt(x2)
int x2;
{
int x;
int i;
x = x2 / 2;
for (i=1; i<=7; ++i) {
if (x) x -= (x*x-x2) / (x+x);
}
return(x);
}
/*
void zfillgem(xc, yc, dx, dy)
int xc, yc, dx, dy;
{
int x, y, i;
int a2, b2, y2;
int buffer[100], npoly;
long test;
a2 = dx * dx + dx;
b2 = dy * dy;
npoly = 0;
for (i=0; i<=1; ++i) {
x = dx;
if (i == 1) x = 0;
y = dy / 3;
if (i == 1) y = dy;
buffer[npoly+npoly] = xc + x;
test = y * persp + persp;
test /= yrad;
/*printf("\natest %d: %d %d %d ", test, y, persp, yrad);*/
buffer[npoly+npoly] += test;
buffer[npoly+npoly+1] = yc + y;
++npoly;
}
for (i=1; i<=1; ++i) {
x = -dx;
y = dy / 3;
buffer[npoly+npoly] = xc + x;
test = y * persp + persp;
test /= yrad;
/*printf("\natest %d: %d %d %d ", test, y, persp, yrad);*/
buffer[npoly+npoly] += test;
buffer[npoly+npoly+1] = yc + y;
++npoly;
}
for (i=0; i<=1; ++i) {
x = -dx;
if (i == 1) x = 0;
y = -dy/3;
if (i == 1) y = -dy;
buffer[npoly+npoly] = xc + x;
test = y * persp + persp;
test /= yrad;
/*printf("\natest %d: %d %d %d ", test, y, persp, yrad);*/
buffer[npoly+npoly] += test;
buffer[npoly+npoly+1] = yc + y;
++npoly;
}
for (i=0; i<=1; ++i) {
x = dx;
y = -dy / 3;
if (i == 1) x = dx;
if (i == 1) y = dy / 2;
buffer[npoly+npoly] = xc + x;
test = y * persp + persp;
test /= yrad;
/*printf("\natest %d: %d %d %d ", test, y, persp, yrad);*/
buffer[npoly+npoly] += test;
buffer[npoly+npoly+1] = yc + y;
++npoly;
}
zfillpoly(npoly, buffer);
}
*/
void zfillips(xc, yc, dx, dy)
int xc, yc, dx, dy;
{
dx *= 30 + abs(persp);
dx /= 30;
dy *= 30 + abs(persp);
dy /= 30;
zfillellipse(xc, yc, dx, dy);
/*
int x, y;
int a2, b2, y2;
int buffer[100], npoly;
long test;
a2 = dx * dx + dx;
b2 = dy * dy;
npoly = 0;
for (y=0; y<=dy; ++y) {
y2 = y * y;
x = isqrt(a2 - (a2 * y2) / b2);
buffer[npoly+npoly] = xc + x;
test = y * persp + persp;
test /= yrad;
/*printf("\natest %d: %d %d %d ", test, y, persp, yrad);*/
buffer[npoly+npoly] += test;
buffer[npoly+npoly+1] = yc + y;
++npoly;
}
for (y=dy-1; y>=0; --y) {
y2 = y * y;
x = isqrt(a2 - (a2 * y2) / b2);
buffer[npoly+npoly] = xc - x;
test = y *