home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume14
/
mine
/
part01
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-31
|
14KB
|
778 lines
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <termio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include <pwd.h>
static char copyright[] = "@(#) Copyright (c) O. Thery 1992";
#define VERSION "1.4"
#define X_SCORE 60
#define Y_SCORE 7
extern int errno;
char *basename();
char *getenv();
char *shell;
extern char *logname;
extern int logfile;
char *k_lft = "h"; /* left key */
char *k_rgt = "l"; /* right key */
char *k_up = "k"; /* up key */
char *k_dwn = "j"; /* down key */
int l_lft = 1;
int l_rgt = 1;
int l_up = 1;
int l_dwn = 1;
static ocount;
static oremain;
int found; /* Found bomds */
int remain; /* Posed bomb */
int good_found;
int max_found;
int best_count = 10000;
int counter;
int counter0;
#define F_L 58
#define F_H 22
#define F_X 32
#define F_Y 16
unsigned char field[F_L * F_H];
int f_x = F_X;
int f_y = F_Y;
int f_x0; /* Left corner of the field */
int f_y0;
int bomb;
int pos_x;
int pos_y;
int pos_n;
char ibuf[128];
#define BOOM 128
#define FLAG 64
#define DONE 32
#define MASK 31
struct termio tinit;
struct w {
char n[14];
short t;
};
struct w *score;
struct w *get_score();
myexit(i)
{
s_pc(0, 23, 0);
sleep(1);
ioctl(0, TCSETA, &tinit);
s_term();
if(i == 5)
abort();
exit(i);
}
sigalr()
{
myexit(5);
}
main(argc, argv)
int argc;
char *argv[];
{
struct fd_set ibits;
struct timeval tim;
int i = 0;
int k;
signal(SIGALRM, sigalr);
argc--, argv++;
while (argc > 0) {
switch (argv[0][0]) {
case '-':
if(argv[0][1] == 'n' && argv[0][2] == 0) {
argv++;
argc--;
bomb = atoi(*argv);
} else if(argv[0][1] == 'f' && argv[0][2] == 0) {
bomb = 10;
f_x = 8;
f_y = 8;
} else if(!strcmp(&argv[0][1], "score")) {
char *n;
int t;
int chk;
argv++;
argc--;
chk = f_x = atoi(*argv);
argv++;
argc--;
chk ^= f_y = atoi(*argv);
argv++;
argc--;
chk ^= bomb = atoi(*argv);
argv++;
argc--;
n = *argv;
t = 0;
for(i = 0; n[i]; i++)
t += n[i]<<i;
chk ^= t;
argv++;
argc--;
chk ^= t = atoi(*argv);
argv++;
argc--;
if(atoi(*argv) != chk)
exit(1);
set_score(f_x, f_y, bomb, n, t);
exit(0);
} else
usage();
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if(!i++) {
k = atoi(*argv);
if(k < 3)
break;
if(k > F_L)
k = F_L;
f_x = k;
} else {
k = atoi(*argv);
if(k < 3)
break;
if(k > F_H)
k = F_H;
f_y = k;
}
break;
default:
usage();
}
argc--;
argv++;
}
tim.tv_sec = 0;
tim.tv_usec = 0;
FD_ZERO(&ibits);
while(1) {
char tmp[256];
char c;
init();
if(mloop())
continue;
FD_SET(0, &ibits);
i = select(2, &ibits, (fd_set *)0, (fd_set *)0, &tim);
if(i)
read(0, tmp, 250);
while(1) {
FD_SET(0, &ibits);
i = select(2, &ibits, (fd_set *)0, (fd_set *)0, 0);
read(0, &c, 1);
if(c == 'q' || c == 'Q')
myexit(0);
else if(c == 'n' || c == 'N')
break;
else if(c == 'c' || c == 'C') {
chief();
break;
}
}
}
}
mloop()
{
int i, k, rc, l = 0;
struct fd_set ibits;
struct timeval tim;
tim.tv_sec = 1;
tim.tv_usec = 0;
FD_ZERO(&ibits);
for (; ; ) {
FD_SET(0, &ibits);
upd_counter();
switch (select(2, &ibits, (fd_set *)0, (fd_set *)0, &tim)) {
case -1:
if (errno == EINTR)
continue;
myexit(1);
case 0:
break;
case 1:
rc = read(0, ibuf + l, sizeof(ibuf) - 1 - l);
rc += l;
l = 0;
ibuf[rc] = 0;
for(i = 0; i < rc;) {
if(!strncmp(&ibuf[i], k_up, l_up)) {
if(pos_y) {
pos_y--;
pos_n -= f_x;
s_pc(f_x0 + pos_x, f_y0 + pos_y, 0);
}
i += l_up;
} else if(!strncmp(&ibuf[i], k_dwn, l_dwn)) {
if(pos_y < f_y - 1) {
pos_y++;
pos_n += f_x;
s_pc(f_x0 + pos_x, f_y0 + pos_y, 0);
}
i += l_dwn;
} else if(!strncmp(&ibuf[i], k_lft, l_lft)) {
if(pos_x) {
pos_x--;
pos_n -= 1;
s_pc(f_x0 + pos_x, f_y0 + pos_y, 0);
}
i += l_lft;
} else if(!strncmp(&ibuf[i], k_rgt, l_rgt)) {
if(pos_x < f_x - 1) {
pos_x++;
pos_n += 1;
s_pc(f_x0 + pos_x, f_y0 + pos_y, 0);
}
i += l_rgt;
} else if(ibuf[i] == 'F' || ibuf[i] == 'f') {
if(field[pos_n] & FLAG) {
s_pc(f_x0 + pos_x, f_y0 + pos_y, ' ');
field[pos_n] &= ~FLAG;
if(field[pos_n] & BOOM) {
found--;
}
remain++;
} else if(!(field[pos_n] & DONE)){
s_bold();
s_pc(f_x0 + pos_x, f_y0 + pos_y, 'F');
s_rmso();
field[pos_n] |= FLAG;
if(field[pos_n] & BOOM) {
found++;
}
remain--;
}
i = rc;
upd_counter();
} else if (ibuf[i] == ' ') {
if(!counter0){
fill_field(pos_n);
}
if((field[pos_n] & BOOM) && !(field[pos_n] & FLAG)) {
sleep(1);
s_bold();
s_pc(f_x0 + pos_x, f_y0 + pos_y, '@');
s_rmso();
field[pos_n] |= FLAG;
bad_exit();
return(0);
} else if (!(field[pos_n]&(FLAG|DONE))) {
make_move(pos_n, pos_x, pos_y);
upd_counter();
if(good_found == max_found) {
return(good_exit());
}
}
i = rc;
} else if (ibuf[i] == 'q' || ibuf[i] == 'Q') {
myexit(0);
} else if(ibuf[i] == 'n' || ibuf[i] == 'N') {
return(1);
} else if(ibuf[i] == 'r' || ibuf[i] == 'R') {
redraw();
i = rc;
} else if(ibuf[i] == 'c' || ibuf[i] == 'C') {
chief();
i = rc;
} else if(ibuf[i] == 'p' || ibuf[i] == 'P') {
pausing();
i = rc;
} else {
l = rc - i;
if(!strncmp(&ibuf[i], k_rgt, l) || !strncmp(&ibuf[i], k_lft, l) ||
!strncmp(&ibuf[i],
k_dwn, l) || !strncmp(&ibuf[i], k_up, l)) {
for(k = 0; k < l; k++)
ibuf[k] = ibuf[k+i];
i = rc;
} else {
l = 0;
i++;
}
}
}
}
}
}
make_move(n, x, y)
int n;
int x;
int y;
{
if(field[n]&~MASK)
return;
field[n] |= DONE;
good_found++;
s_pc(f_x0 + x, f_y0 + y, '0' + (field[n]&MASK));
if(field[n]&MASK)
return;
if(x > 0) {
make_move(n - 1, x - 1, y);
if(y > 0) {
make_move(n - 1 - f_x, x - 1, y - 1);
}
}
if(y > 0) {
make_move(n - f_x, x, y - 1);
if(x < f_x - 1) {
make_move(n + 1 - f_x, x + 1, y - 1);
}
}
if(x < f_x - 1) {
make_move(n + 1, x + 1, y);
if(y < f_y - 1) {
make_move(n + f_x + 1, x + 1, y + 1);
}
}
if(y < f_y - 1) {
make_move(n + f_x, x, y + 1);
if(x > 0) {
make_move(n - 1 + f_x, x - 1, y + 1);
}
}
}
good_exit()
{
char n[14];
int i;
char c;
FILE *fd;
s_pr(X_SCORE + 3, Y_SCORE - 1, "Won !!!");
if(counter >= best_count)
return(0);
sleep(1);
for(i = 0; i < 14; i++)
n[i] = 0;
#define X_NAME 30
#define Y_NAME 11
s_box(X_NAME, Y_NAME, 15, 2);
s_pr(X_NAME + 1, Y_NAME + 1, " ");
s_pc(X_NAME + 1, Y_NAME + 1, 0);
i = 0;
while(1) {
read(0, &c, 1);
switch(c) {
case 8:
if(i == 0)
break;
i--;
s_pc(X_NAME + 1 + i, Y_NAME + 1, ' ');
s_pc(X_NAME + 1 + i, Y_NAME + 1, 0);
break;
case '\n':
case '\r':
set_score(f_x, f_y, bomb, n, counter);
fd = fopen("/etc/mine.score", "r");
if(fd) {
char cmd[256];
char tmp[256];
int chk = f_x ^ f_y ^ bomb ^ counter;
int j;
for(j = i = 0; n[i]; i++)
j += n[i] << i;
chk ^= j;
while(fgets(tmp, 255, fd)) {
tmp[strlen(tmp) - 1] = 0;
sprintf(cmd, "rshell %s mine -score %d %d %d \"\\\"%s\\\"\" %d %d&\n", tmp, f_x,
f_y, bomb, n, counter, chk);
system(cmd);
}
fclose(fd);
}
return(1);
break;
default:
if(c < 32 || c > 126)
break;
n[i] = c;
s_pc(X_NAME + 1 + i, Y_NAME + 1, c);
if(i < 14)
i++;
s_pc(X_NAME + 1 + i, Y_NAME + 1, 0);
break;
}
}
}
bad_exit()
{
int i;
int x, y;
sleep(1);
s_pr(X_SCORE + 3, Y_SCORE -1, "Lost !!!");
s_bold();
for(i = y = 0; y < f_y; y++) {
for(x = 0; x < f_x; x++, i++) {
if(field[i] & BOOM) {
if(!(field[i] & FLAG))
s_pc(f_x0 +x, f_y0 + y, '*');
} else if(field[i] & FLAG) {
s_pc(f_x0 +x, f_y0 + y, '#');
}
}
}
s_rmso();
return;
}
usage()
{
fprintf(stderr, "usage:\n mine [-f] [-n <bombs>] [<x>] [<y>]\n");
exit(1);
}
init()
{
struct termio tem;
static ft = 1;
int i;
if(ft) {
struct passwd *getpwnam();
struct passwd *p;
p = getpwnam("mine");
if(p)
setreuid(p->pw_uid, p->pw_uid);
ioctl(0, TCGETA, &tinit);
/* Mise du tty en mode raw */
tem = tinit;
tem.c_oflag = 0;
tem.c_lflag = 0;
tem.c_iflag = 0;
tem.c_cc[VMIN] = 1;
tem.c_cc[VTIME] = 1;
ioctl(0, TCSETA, &tem);
s_init();
ft = 0;
}
s_clear();
for(i = 0; i < F_H * F_L; i++)
field[i] = 0;
ocount = -1;
oremain = -1;
counter0 = 0;
counter = 0;
if(!bomb || bomb > f_x * f_y / 2) {
bomb = 3 * f_x + 3;
if(bomb > f_x * f_y / 2)
bomb = (f_x * f_y) / 2;
}
remain = bomb;
good_found = 0;
max_found = f_x * f_y - bomb;
pos_x = f_x / 2;
pos_y = f_y / 2;
pos_n = pos_x + pos_y * f_x;
f_x0 = (F_L - f_x) / 2 + 1;
f_y0 = (F_H - f_y) / 2 + 1;
s_box(f_x0 - 1, f_y0 - 1, f_x + 1, f_y + 1);
score = get_score(f_x, f_y, bomb);
if(score) {
best_count = score[4].t ? score[4].t : 10000;
}
draw_screen();
}
draw_screen()
{
int i;
s_bold();
s_pr(X_SCORE + 3 , 1, "MineSweeper %s", VERSION);
s_rmso();
s_box(X_SCORE, Y_SCORE, 19, 8);
s_bold();
s_pr(X_SCORE + 1, Y_SCORE + 1, " Top scores ");
s_pr(X_SCORE + 1, Y_SCORE + 2, "------------------");
if(score) {
for(i = 0; i < 5; i++) {
if(!score[i].n[0])
break;
s_pr(X_SCORE + 1, Y_SCORE + 3 + i, "%.14s", score[i].n);
s_pr(X_SCORE + 16, Y_SCORE + 3 + i, "%.3d", score[i].t);
}
}
s_rmso();
s_pr(X_SCORE, Y_SCORE + 10, " f : (un)mark");
s_pr(X_SCORE, Y_SCORE + 11, " <SPACE> : discover");
s_pr(X_SCORE, Y_SCORE + 12, " n : new game");
s_pr(X_SCORE, Y_SCORE + 13, " q : quit");
s_pr(X_SCORE, Y_SCORE + 14, " r : redraw");
s_pr(X_SCORE, Y_SCORE + 15, " p : pause");
s_pr(X_SCORE, Y_SCORE + 16, " c : boss");
s_box(63, 3, 6, 2);
s_box(71, 3, 6, 2);
}
fill_field(n)
int n;
{
int i;
int s = f_x * f_y;
counter0 = time(0);
memset(field, 0, sizeof(field));
found = 0;
remain = 0;
do {
int x, y;
i = aleat(s);
if(field[i] & BOOM || i == n)
continue;
field[i] |= BOOM;
if(field[i]&FLAG)
found++;
x = i % f_x;
y = i / f_x;
if(x > 0)
field[i - 1]++;
if(y > 0) {
field[i - f_x]++;
if(x > 0)
field[i - 1 - f_x]++;
if(x < f_x - 1)
field[i + 1 - f_x]++;
}
if(y < f_y - 1) {
field[i + f_x]++;
if(x < f_x - 1)
field[i + 1 + f_x]++;
if(x > 0)
field[i - 1 + f_x]++;
}
if(x < f_x - 1)
field[i + 1]++;
remain++;
} while(remain != bomb);
}
aleat(s)
unsigned int s;
{
static unsigned int ft;
if(!ft) {
ft = time(0);
}
ft *= 3793;
ft ^= 49834897;
ft >>= 2;
return(ft % s);
}
upd_counter()
{
if(counter0) {
counter = time(0) - counter0;
if(counter > 999)
counter = 999;
}
if(oremain == remain && ocount == counter) {
s_pc(f_x0 + pos_x, f_y0 + pos_y, 0);
return;
}
s_civis();
if(ocount != counter) {
s_pr(64, 4, " %3.3d", counter);
ocount = counter;
}
if(remain != oremain) {
if(remain < 0)
s_pr(72, 4, "%3.3d", remain);
else
s_pr(72, 4, " %3.3d", remain);
oremain = remain;
}
s_cnorm();
s_pc(f_x0 + pos_x, f_y0 + pos_y, 0);
}
redraw() {
int i;
int j;
int k;
int l;
int p;
char tmp[256];
s_clear();
s_civis();
s_box(f_x0 - 1, f_y0 - 1, f_x + 1, f_y + 1);
for(i = 0, k = 0; i < f_y; i++) {
for(j = 0, l = 0, p = 0; j < f_x; j++, k++) {
if(field[k] & FLAG) {
if(l) {
tmp[l] = 0;
s_pr(f_x0 + p, f_y0 + i, "%s", tmp);
l = 0;
}
s_bold();
s_pc(f_x0 + j, f_y0 + i, 'F');
s_rmso();
p = j+1;
} else {
tmp[l++] = (field[k] & DONE) ? (field[k] & MASK) + '0' : ' ';
}
}
if(l) {
tmp[l] = 0;
s_pr(f_x0 + p, f_y0 + i, "%s", tmp);
}
}
draw_screen();
s_pr(64, 4, " %3.3d", counter);
if(remain < 0)
s_pr(72, 4, "%3.3d", remain);
else
s_pr(72, 4, " %3.3d", remain);
s_pc(f_x0 + pos_x, f_y0 + pos_y, 0);
s_cnorm();
}
#define LENGTH 35
#define FORMAT "%35.35s"
#define X_MIDLE ((80 - LENGTH) / 2 - 1)
#define Y_MIDLE 11
pausing() {
int i;
int j;
char tmp[256];
int pos;
int len;
struct fd_set ibits;
struct timeval tim;
int t;
s_civis();
for(j = 0; j < f_x; j++) {
tmp[j] = ' ';
}
tmp[j] = 0;
for(i = 0; i < f_y; i++) {
s_pr(f_x0, f_y0 + i, "%s", tmp);
}
s_box(X_MIDLE, Y_MIDLE, LENGTH + 1, 2);
t = time(0);
strftime(tmp, 256, "Local time is %R, press a key to continue. ", localtime(&t));
len = strlen(tmp);
tim.tv_sec = 0;
tim.tv_usec = 450000;
FD_ZERO(&ibits);
pos = 0;
while(1) {
FD_SET(0, &ibits);
i = select(2, &ibits, (fd_set *)0, (fd_set *)0, &tim);
if(i) {
read(0, tmp, 250);
redraw();
if(counter0)
counter0 = time(0) - counter;
return;
} else {
s_pr(X_MIDLE + 1, Y_MIDLE + 1, FORMAT, tmp+pos++);
if(pos + LENGTH == len) {
t = time(0);
strftime(tmp + len, 256 - len, "Local time is %R, press a key to continue. ", localtime(&t));
} else if(pos == len) {
strcpy(tmp, tmp+len);
len = strlen(tmp);
pos = 0;
}
}
}
}
chief() {
char *n = getenv("CHIEFCMD");
struct fd_set ibits;
int i;
char b[250];
struct termio nterm;
s_clear();
if(n) {
ioctl(0, TCGETA, &nterm);
ioctl(0, TCSETA, &tinit);
system(n);
ioctl(0, TCSETA, &nterm);
} else {
printf("$ ");
fflush(stdout);
}
FD_ZERO(&ibits);
while(1) {
FD_SET(0, &ibits);
i = select(2, &ibits, (fd_set *)0, (fd_set *)0, 0);
if(i) {
read(0, b, 250);
redraw();
if(counter0)
counter0 = time(0) - counter;
return;
}
}
}