xref: /csrg-svn/lib/libcurses/PSD.doc/life.c (revision 62780)
162779Sbostic .\" Copyright (c) 1980, 1993
262779Sbostic .\"	 The Regents of the University of California.  All rights reserved.
348164Sbostic .\"
448164Sbostic .\" %sccs.include.redist.roff%
548164Sbostic .\"
6*62780Sbostic .\"	@(#)life.c	8.1 (Berkeley) 06/08/93
748164Sbostic .\"
827331Smckusick # include	<curses.h>
927331Smckusick # include	<signal.h>
1027331Smckusick 
1127331Smckusick /*
1227331Smckusick  *	Run a life game.  This is a demonstration program for
1327331Smckusick  * the Screen Updating section of the -lcurses cursor package.
1427331Smckusick  */
1527331Smckusick 
1627333Smckusick typedef struct lst_st {			/* linked list element */
1727331Smckusick 	int		y, x;		/* (y, x) position of piece */
1827331Smckusick 	struct lst_st	*next, *last;	/* doubly linked */
1927333Smckusick } LIST;
2027331Smckusick 
2127331Smckusick LIST	*Head;			/* head of linked list */
2227331Smckusick 
2327333Smckusick int	die();
2427333Smckusick 
2527331Smckusick main(ac, av)
2627331Smckusick int	ac;
2727333Smckusick char	*av[];
2827333Smckusick {
2927331Smckusick 	evalargs(ac, av);		/* evaluate arguments */
3027331Smckusick 
3127331Smckusick 	initscr();			/* initialize screen package */
3227331Smckusick 	signal(SIGINT, die);		/* set to restore tty stats */
3327333Smckusick 	cbreak();			/* set for char-by-char */
3427331Smckusick 	noecho();			/*	input */
3527331Smckusick 	nonl();				/* for optimization */
3627331Smckusick 
3727331Smckusick 	getstart();			/* get starting position */
3827331Smckusick 	for (;;) {
3927331Smckusick 		prboard();		/* print out current board */
4027331Smckusick 		update();		/* update board position */
4127331Smckusick 	}
4227331Smckusick }
4327331Smckusick 
4427331Smckusick /*
4527331Smckusick  * This is the routine which is called when rubout is hit.
4627331Smckusick  * It resets the tty stats to their original values.  This
4727331Smckusick  * is the normal way of leaving the program.
4827331Smckusick  */
4927333Smckusick die()
5027333Smckusick {
5127333Smckusick 	signal(SIGINT, SIG_IGN);		/* ignore rubouts */
5227333Smckusick 	mvcur(0, COLS - 1, LINES - 1, 0);	/* go to bottom of screen */
5327333Smckusick 	endwin();				/* set terminal to good state */
5427331Smckusick 	exit(0);
5527331Smckusick }
5627331Smckusick 
5727331Smckusick /*
5827331Smckusick  * Get the starting position from the user.  They keys u, i, o, j, l,
5927331Smckusick  * m, ,, and . are used for moving their relative directions from the
6027331Smckusick  * k key.  Thus, u move diagonally up to the left, , moves directly down,
6127331Smckusick  * etc.  x places a piece at the current position, " " takes it away.
6227331Smckusick  * The input can also be from a file.  The list is built after the
6327331Smckusick  * board setup is ready.
6427331Smckusick  */
6527333Smckusick getstart()
6627333Smckusick {
6727331Smckusick 	reg char	c;
6827331Smckusick 	reg int		x, y;
6927333Smckusick 	auto char	buf[100];
7027331Smckusick 
7127331Smckusick 	box(stdscr, '|', '_');		/* box in the screen */
7227331Smckusick 	move(1, 1);			/* move to upper left corner */
7327331Smckusick 
7427333Smckusick 	for (;;) {
7527331Smckusick 		refresh();		/* print current position */
7627333Smckusick 		if ((c = getch()) == 'q')
7727331Smckusick 			break;
7827331Smckusick 		switch (c) {
7927331Smckusick 		  case 'u':
8027331Smckusick 		  case 'i':
8127331Smckusick 		  case 'o':
8227331Smckusick 		  case 'j':
8327331Smckusick 		  case 'l':
8427331Smckusick 		  case 'm':
8527331Smckusick 		  case ',':
8627331Smckusick 		  case '.':
8727331Smckusick 			adjustyx(c);
8827331Smckusick 			break;
8927331Smckusick 		  case 'f':
9027331Smckusick 			mvaddstr(0, 0, "File name: ");
9127331Smckusick 			getstr(buf);
9227331Smckusick 			readfile(buf);
9327331Smckusick 			break;
9427331Smckusick 		  case 'x':
9527331Smckusick 			addch('X');
9627331Smckusick 			break;
9727331Smckusick 		  case ' ':
9827331Smckusick 			addch(' ');
9927331Smckusick 			break;
10027331Smckusick 		}
10127331Smckusick 	}
10227331Smckusick 
10327331Smckusick 	if (Head != NULL)			/* start new list */
10427331Smckusick 		dellist(Head);
10527331Smckusick 	Head = malloc(sizeof (LIST));
10627331Smckusick 
10727331Smckusick 	/*
10827331Smckusick 	 * loop through the screen looking for 'x's, and add a list
10927331Smckusick 	 * element for each one
11027331Smckusick 	 */
11127331Smckusick 	for (y = 1; y < LINES - 1; y++)
11227331Smckusick 		for (x = 1; x < COLS - 1; x++) {
11327331Smckusick 			move(y, x);
11427331Smckusick 			if (inch() == 'x')
11527331Smckusick 				addlist(y, x);
11627331Smckusick 		}
11727331Smckusick }
11827331Smckusick 
11927331Smckusick /*
12027331Smckusick  * Print out the current board position from the linked list
12127331Smckusick  */
12227331Smckusick prboard() {
12327331Smckusick 
12427331Smckusick 	reg LIST	*hp;
12527331Smckusick 
12627331Smckusick 	erase();			/* clear out last position */
12727331Smckusick 	box(stdscr, '|', '_');		/* box in the screen */
12827331Smckusick 
12927331Smckusick 	/*
13027331Smckusick 	 * go through the list adding each piece to the newly
13127331Smckusick 	 * blank board
13227331Smckusick 	 */
13327331Smckusick 	for (hp = Head; hp; hp = hp->next)
13427331Smckusick 		mvaddch(hp->y, hp->x, 'X');
13527331Smckusick 
13627331Smckusick 	refresh();
13727331Smckusick }
138