home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume3
/
puzzle
/
puzzle.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-02-19
|
13KB
|
522 lines
/*
* Puzzle, By Henk-Jan Visscher.
*
* compile:
* cc -O puzzle.c -o puzzle -ltermcap
* strip puzzle
*
* NB : change UID in own UID.
*/
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sgtty.h>
#include <pwd.h>
extern char *tgoto ();
#define scr_init() tputs (IS, 0, xputc)
#define clear() tputs (CL, 0, xputc)
#define rev_begin() tputs (SO, 0, xputc)
#define rev_end() tputs (SE, 0, xputc)
#define cursor(y, x) tputs (tgoto (CM, x, y), 0, xputc)
#define hi_begin() tputs (HI, 0, xputc)
#define hi_end() tputs (HE, 0, xputc)
#define home() tputs (HO, 0, xputc)
#define bell() xputc ('\007')
#define flush() fflush (stdout)
#define UID 320
#define BORDER -1
#define EMPTY 0
#define SMALL 1
#define WIDTH 2
#define HIGH 3
#define BIG 4
#define CLEAR 0
#define DRAW 1
#define ACCENT 2
char *CL, *SO, *SE, *IS, *CM, *HI, *HE, *HO, ch;
short x, y;
int moves;
struct sgttyb sg, save;
struct field {
short hx, hy, type;
} field [6] [7];
struct mem {
short nx, ny, ox, oy;
} tb [9999];
struct mem sol [] = {
{ 1, 1, 2, 1 } , { 1, 2, 1, 1 } , { 2, 3, 1, 3 } , { 3, 2, 3, 1 } ,
{ 4, 2, 3, 2 } , { 4, 1, 4, 2 } , { 3, 1, 4, 1 } , { 3, 2, 3, 1 } ,
{ 1, 3, 2, 3 } , { 2, 3, 3, 3 } , { 2, 2, 2, 3 } , { 2, 1, 2, 2 } ,
{ 2, 3, 1, 3 } , { 2, 2, 2, 3 } , { 3, 1, 2, 1 } , { 4, 2, 3, 2 } ,
{ 3, 2, 3, 1 } , { 3, 3, 3, 2 } , { 2, 3, 3, 3 } , { 3, 3, 4, 3 } ,
{ 1, 3, 2, 3 } , { 2, 3, 3, 3 } , { 1, 1, 1, 2 } , { 2, 1, 2, 2 } ,
{ 3, 1, 2, 1 } , { 2, 1, 1, 1 } , { 4, 1, 3, 1 } , { 3, 1, 2, 1 } ,
{ 3, 2, 3, 1 } , { 3, 3, 3, 2 } , { 3, 2, 4, 2 } , { 2, 2, 3, 2 } ,
{ 1, 2, 2, 2 } , { 1, 4, 1, 3 } , { 1, 3, 1, 2 } , { 2, 4, 1, 4 } ,
{ 4, 4, 3, 4 } , { 4, 3, 4, 4 } , { 4, 4, 4, 5 } , { 4, 2, 4, 3 } ,
{ 4, 3, 4, 4 } , { 3, 2, 4, 2 } , { 3, 4, 3, 3 } , { 3, 3, 3, 2 } ,
{ 1, 4, 2, 4 } , { 1, 2, 1, 3 } , { 1, 3, 1, 4 } , { 2, 2, 1, 2 } ,
{ 3, 2, 2, 2 } , { 4, 2, 3, 2 } , { 4, 4, 4, 3 } , { 4, 3, 4, 2 } ,
{ 4, 5, 4, 4 } , { 4, 4, 4, 3 } , { 2, 4, 3, 4 } , { 2, 2, 2, 3 } ,
{ 2, 3, 2, 4 } , { 3, 2, 2, 2 } , { 4, 2, 3, 2 } , { 3, 2, 3, 3 } ,
{ 3, 1, 3, 2 } , { 2, 1, 3, 1 } , { 3, 1, 4, 1 } , { 1, 1, 2, 1 } ,
{ 2, 1, 3, 1 } , { 1, 2, 1, 1 } , { 2, 2, 2, 1 } , { 3, 3, 2, 3 } ,
{ 2, 3, 1, 3 } , { 4, 3, 3, 3 } , { 3, 3, 2, 3 } , { 3, 2, 3, 3 } ,
{ 4, 1, 4, 2 } , { 3, 1, 4, 1 } , { 2, 1, 3, 1 } , { 2, 3, 2, 2 } ,
{ 2, 2, 2, 1 } , { 2, 4, 2, 3 } , { 2, 3, 2, 2 } , { 1, 4, 2, 4 } ,
{ 1, 3, 1, 4 } , { 1, 4, 1, 5 } , { 1, 1, 1, 2 } , { 1, 2, 1, 3 } ,
{ 2, 1, 1, 1 } , { 1, 1, 1, 2 } , { 2, 2, 2, 1 } , { 2, 4, 2, 3 } ,
{ 1, 5, 2, 5 } , { 1, 3, 1, 4 } , { 1, 2, 1, 3 } , { 2, 1, 1, 1 } ,
{ 2, 3, 2, 2 } , { 2, 2, 2, 1 } , { 1, 3, 2, 3 } , { 2, 3, 2, 4 } ,
{ 1, 4, 1, 3 } , { 2, 5, 1, 5 } , { 2, 4, 2, 5 } , { 2, 1, 2, 2 } ,
{ 2, 2, 2, 3 } , { 3, 1, 2, 1 } , { 4, 1, 3, 1 } , { 4, 2, 4, 1 } ,
{ 3, 3, 3, 2 } , { 3, 4, 3, 3 } , { 2, 5, 3, 5 } , { 3, 5, 4, 5 } ,
{ 1, 5, 2, 5 } , { 2, 5, 3, 5 } , { 1, 3, 1, 4 } , { 1, 1, 1, 2 } ,
{ 2, 3, 2, 4 } , { 2, 1, 2, 2 } , { 3, 1, 2, 1 } , { 2, 1, 1, 1 } ,
{ 4, 1, 3, 1 } , { 3, 1, 2, 1 } , { 3, 2, 3, 1 } , { 3, 3, 3, 2 } ,
{ 3, 5, 3, 4 } , { 3, 4, 4, 4 } , { 2, 4, 3, 4 } , { 2, 2, 2, 3 } ,
{ 2, 3, 2, 4 } , { 3, 2, 2, 2 } , { 4, 4, 4, 3 } , { 4, 3, 4, 2 } ,
{ 4, 5, 4, 4 } , { 4, 4, 4, 3 } , { 3, 4, 4, 4 } , { 2, 4, 3, 4 } ,
{ 1, 4, 2, 4 } , { 1, 2, 1, 3 } , { 1, 3, 1, 4 } , { 2, 2, 1, 2 } ,
{ 4, 2, 3, 2 } , { 3, 2, 3, 3 } , { 3, 1, 3, 2 } , { 2, 1, 3, 1 } ,
{ 3, 1, 4, 1 } , { 1, 1, 2, 1 } , { 2, 1, 3, 1 } , { 1, 2, 1, 1 } ,
{ 3, 3, 2, 3 } , { 2, 3, 1, 3 } , { 4, 3, 3, 3 } , { 3, 3, 2, 3 } ,
{ 3, 2, 3, 3 } , { 3, 1, 3, 2 } , { 3, 2, 4, 2 } , { 1, 1, 2, 1 } ,
{ 0, 0, 0, 0 }
};
main ()
{
init ();
layout ();
initfield ();
for (;;)
move ();
}
init ()
{
int leave ();
#ifdef SIGTSTP
int sigtstp();
#endif SIGTSTP
int xputc ();
char buffer [1024];
static char save_buf [100];
char *ptr = save_buf;
extern char *tgetstr ();
signal (SIGINT, leave);
signal (SIGQUIT, leave);
#ifdef SIGTSTP
signal (SIGTSTP, sigtstp);
#endif SIGTSTP
gtty (1, &sg);
save = sg;
sg.sg_flags |= CBREAK;
sg.sg_flags &= ~ECHO;
stty (1, &sg);
switch (tgetent (buffer, getenv ("TERM"))) {
case -1:
fprintf (stderr, "can't open \"termcap\" file.\n");
exit (1);
case 0:
fprintf (stderr, "can't find entry for term.type.\n");
exit (1);
}
IS = tgetstr ("is", &ptr);
CL = tgetstr ("cl", &ptr);
CM = tgetstr ("cm", &ptr);
SO = tgetstr ("so", &ptr);
SE = tgetstr ("se", &ptr);
HI = tgetstr ("hi", &ptr);
HE = tgetstr ("he", &ptr);
HO = tgetstr ("ho", &ptr);
if (!CL || !CM || !SO || !SE || !HI || !HE || !HO) {
fprintf (stderr, "not a right terminal.\n");
stty (1, &save);
exit (1);
}
if (IS != (char *) 0) scr_init ();
ch = ' ';
}
#ifdef SIGTSTP
sigtstp()
{
signal (SIGTSTP, SIG_IGN);
stty (1, &save);
cursor (23, 0);
flush ();
kill (0, SIGSTOP);
signal (SIGTSTP, sigtstp);
stty (1, &sg);
redraw ();
}
#endif SIGTSTP
leave ()
{
stty (1, &save);
cursor (23, 0);
exit (0);
}
fill (x, y, px, py, mode)
short x, y, px, py, mode;
{
short i, j;
for (i = y; i < y+py; i++)
{
cursor (i, x);
if (mode != CLEAR) rev_begin ();
if (mode == ACCENT) hi_begin ();
for (j = x; j < x+px; j++)
putchar ((mode == ACCENT) ? ch : ' ');
if (mode != CLEAR) rev_end ();
if (mode == ACCENT) hi_end ();
}
}
/* VARARGS3 */
pline (yc, xc, format, arg)
short yc, xc;
char *format;
int arg;
{
cursor (yc, xc);
printf (format, arg);
}
layout ()
{
clear ();
fill (7, 2, 34, 20, DRAW);
fill (18, 2, 12, 2, CLEAR);
fill (11, 4, 26, 16, CLEAR);
pline (3, 46, "PUZZLE (By HJ Visscher)");
pline (5, 46, "Purpose :");
pline (6, 46, "----------");
pline (7, 46, "Try to move the biggest");
pline (8, 46, "piece through the hole at");
pline (9, 46, "the top.");
pline (11, 46, "Commands :");
pline (12, 46, "------------");
pline (13, 46, "y k u \\");
pline (14, 46, " \\ | / \\");
pline (15, 46, "h - * - l |- To Move");
pline (16, 46, " / | \\ /");
pline (17, 46, "b j n /");
pline (19, 46, "Q - Quit T - Take back");
pline (20, 46, "R - Redraw ? - Solution");
pline (21, 46, "N - New Game A - Extra accent");
}
redraw ()
{
short i, j;
layout ();
for (i = 1; i < 5; i++)
for (j = 1; j < 6; j++)
if (field [i] [j]. hx == i && field [i] [j]. hy == j)
change (DRAW, i, j, field [i] [j]. type);
change (ACCENT, x, y, field [x] [y]. type);
pline (22, 20, "Moves : %04d", moves);
home ();
}
clfield ()
{
short i, j;
static struct field empty_field;
for (i = 0; i < 6; i++)
for (j = 0; j < 7; j++)
field [i] [j] = empty_field;
for (i = 0; i < 6; i++)
field [i] [0]. type = field [i] [6]. type = BORDER;
for (j = 0; j < 7; j++)
field [0] [j]. type = field [5] [j]. type = BORDER;
}
change (task, xc, yc, kind)
short task, xc, yc, kind;
{
field [xc] [yc]. hx = (task == CLEAR) ? 0 : xc;
field [xc] [yc]. hy = (task == CLEAR) ? 0 : yc;
field [xc] [yc]. type = (task == CLEAR) ? EMPTY : kind;
switch (kind) {
case SMALL:
fill (7+xc*6, 2+yc*3, 4, 2, task);
return;
case WIDTH:
field [xc+1] [yc]. hx = (task == CLEAR) ? 0 : xc;
field [xc+1] [yc]. hy = (task == CLEAR) ? 0 : yc;
fill (7+xc*6, 2+yc*3, 10, 2, task);
return;
case HIGH:
field [xc] [yc+1]. hx = (task == CLEAR) ? 0 : xc;
field [xc] [yc+1]. hy = (task == CLEAR) ? 0 : yc;
fill (7+xc*6, 2+yc*3, 4, 5, task);
return;
case BIG:
field [xc+1] [yc]. hx = field [xc] [yc+1]. hx =
field [xc+1] [yc+1]. hx =
(task == CLEAR) ? 0 : xc;
field [xc+1] [yc]. hy = field [xc] [yc+1]. hy =
field [xc+1] [yc+1]. hy =
(task == CLEAR) ? 0 : yc;
fill (7+xc*6, 2+yc*3, 10, 5, task);
return;
}
}
initfield ()
{
clfield ();
change (ACCENT, 1, 1, SMALL);
change (DRAW, 2, 2, SMALL);
change (DRAW, 3, 2, SMALL);
change (DRAW, 4, 1, SMALL);
change (DRAW, 1, 2, HIGH);
change (DRAW, 1, 4, HIGH);
change (DRAW, 4, 2, HIGH);
change (DRAW, 4, 4, HIGH);
change (DRAW, 2, 3, WIDTH);
change (DRAW, 2, 4, BIG);
x = y = 1;
moves = 0;
pline (22, 20, "Moves : %04d", moves);
home ();
}
move ()
{
char c;
short nx, ny, px, py;
short movem, kind;
c = getchar ();
px = (field [x] [y]. type == BIG||field [x] [y]. type == WIDTH) ? 2 : 1;
py = (field [x] [y]. type == BIG||field [x] [y]. type == HIGH) ? 2 : 1;
movem = 0;
switch (c) {
case 'A' : ch = (ch == ' ') ? ':' : ' ';
change (ACCENT, x, y, field [x] [y]. type);
home ();
return;
case 'Q' : clear ();
leave ();
case 'R' : redraw ();
return;
case '?' : solution ();
return;
case 'T' : takeback ();
return;
case 'N' : new ();
return;
case 'h' : nx = field [x-1] [y]. hx;
ny = field [x-1] [y]. hy;
if (nx == EMPTY && py == 2) {
nx = field [x-1] [y+1]. hx;
ny = field [x-1] [y+1]. hy;
}
movem = 1;
break;
case 'j' : nx = field [x] [y+py]. hx;
ny = field [x] [y+py]. hy;
if (nx == EMPTY && px == 2) {
nx = field [x+1] [y+py]. hx;
ny = field [x+1] [y+py]. hy;
}
movem = 1;
break;
case 'k' : nx = field [x] [y-1]. hx;
ny = field [x] [y-1]. hy;
if (nx == EMPTY && px == 2) {
nx = field [x+1] [y-1]. hx;
ny = field [x+1] [y-1]. hy;
}
movem = 1;
break;
case 'l' : nx = field [x+px] [y]. hx;
ny = field [x+px] [y]. hy;
if (nx == EMPTY && py == 2) {
nx = field [x+px] [y+1]. hx;
ny = field [x+px] [y+1]. hy;
}
movem = 1;
break;
case 'y' : nx = field [x-1] [y-1]. hx;
ny = field [x-1] [y-1]. hy;
break;
case 'u' : nx = field [x+px] [y-1]. hx;
ny = field [x+px] [y-1]. hy;
if (nx == EMPTY) {
nx = field [x+1] [y-1]. hx;
ny = field [x+1] [y-1]. hy;
}
break;
case 'b' : nx = field [x-1] [y+py]. hx;
ny = field [x-1] [y+py]. hy;
if (nx == EMPTY) {
nx = field [x-1] [y+1]. hx;
ny = field [x-1] [y+1]. hy;
}
break;
case 'n' : nx = field [x+px] [y+py]. hx;
ny = field [x+px] [y+py]. hy;
if (nx == EMPTY) {
nx = field [x+1] [y+1]. hx;
ny = field [x+1] [y+1]. hy;
}
break;
default : bell ();
return;
}
if (nx != EMPTY) {
change (DRAW, x, y, field [x] [y]. type);
change (ACCENT, nx, ny, field [nx] [ny]. type);
home ();
x = nx; y = ny;
return;
}
if (!movem) {
bell ();
return;
}
kind = field [x] [y]. type;
change (CLEAR, x, y, kind);
nx = x + (c == 'l') - (c == 'h');
ny = y + (c == 'j') - (c == 'k');
if (!space (nx, ny, kind)) {
if (c == 'k' && kind == BIG && x == 2 && y == 1) solved ();
change (ACCENT, x, y, kind);
bell ();
home ();
return;
}
change (ACCENT, nx, ny, kind);
pline (22, 20, "Moves : %04d", ++moves);
home ();
tb [moves]. ox = x;
tb [moves]. oy = y;
tb [moves]. nx = nx;
tb [moves]. ny = ny;
x = nx; y = ny;
}
space (xc, yc, kind)
short xc, yc, kind;
{
if (field [xc] [yc]. type) return (0);
switch (kind) {
case SMALL : return (1);
case WIDTH : return (field [xc+1] [yc]. type == EMPTY);
case HIGH : return (field [xc] [yc+1]. type == EMPTY);
case BIG : return (field [xc+1] [yc]. type == EMPTY &&
field [xc] [yc+1]. type == EMPTY &&
field [xc+1] [yc+1]. type == EMPTY);
}
/* NOTREACHED */
}
solved ()
{
fill (11, 4, 26, 16, CLEAR);
fill (15, 10, 18, 5, ACCENT);
fill (17, 11, 14, 3, DRAW);
pline (12, 19, "SOLVED !!!");
leave ();
}
xputc (c)
char c;
{
putchar (c);
}
solution ()
{
struct passwd *pw, *getpwuid();
short i, kind;
char *crypt ();
if ((pw = getpwuid (UID)) == (struct passwd *) 0) {
pline (22, 20, "Sorry.... ");
home ();
return;
}
cursor (22, 20);
printf ("Password: ");
flush ();
if (strcmp (crypt (getpass(""), pw->pw_passwd), pw->pw_passwd)) {
pline (22, 20, "Sorry.... ");
home ();
return;
}
new ();
pline (22, 20, "Moves : %04d ", moves);
for (i = 0; sol [i]. nx; i++) {
kind = field [sol [i]. nx] [sol [i]. ny]. type;
change (CLEAR, sol [i]. nx, sol [i]. ny, kind);
change (DRAW, (x = sol [i]. ox), (y = sol [i]. oy), kind);
pline (22, 28, "%04d", ++moves);
home ();
}
solved ();
}
takeback ()
{
int count;
short i, kind;
char buffer [BUFSIZ];
pline (22, 15, "How many moves ? ");
stty (1, &save);
gets (buffer);
count = atoi (buffer);
stty (1, &sg);
if (moves - count < 0) {
pline (22, 15, " Sorry ");
home ();
return;
}
pline (22, 15, " ");
for (i = 0; i < count; i++) {
kind = field [tb [moves]. nx] [tb [moves]. ny]. type;
change (DRAW, x, y, field [x] [y]. type);
change (CLEAR, tb [moves]. nx, tb [moves]. ny, kind);
change (ACCENT, (x = tb [moves]. ox), (y = tb [moves]. oy), kind);
pline (22, 20, "Moves : %04d", --moves);
home ();
}
}
new ()
{
fill (11, 4, 26, 16, CLEAR);
initfield ();
}