DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T p

⟦6e9bc7a6d⟧ TextFile

    Length: 12931 (0x3283)
    Types: TextFile
    Names: »puzzle.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Puzzle/puzzle.c« 

TextFile

	/*
	 *	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 ();
}