1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 static char sccsid[] = "@(#)backgammon.c	5.1 (Berkeley) 4/8/91";
36 #endif /* not lint */
37 
38 /*
39 **	The game of Backgammon
40 */
41 
42 #include	<stdio.h>
43 
44 #define	WHITE		0
45 #define	BROWN		1
46 #define	NIL		(-1)
47 #define	MAXGMOV		10
48 #define	MAXIMOVES	1000
49 #define	RULES		"/usr/games/lib/backrules"
50 
51 char	level;		/*'b'=beginner, 'i'=intermediate, 'e'=expert*/
52 
53 int	die1;
54 int	die2;
55 int	i;
56 int	j;
57 int	l;
58 int	m;
59 int	pflg = 1;
60 int	nobroll = 0;
61 int	count;
62 int	imoves;
63 int	goodmoves[MAXGMOV];
64 int	probmoves[MAXGMOV];
65 
66 int	brown[] = {		/* brown position table */
67 	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
68 	0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
69 	0, 0, 0, 0, 0, 0
70 };
71 
72 int	white[] = {		/* white position table */
73 	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
74 	0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
75 	0, 0, 0, 0, 0, 0
76 };
77 
78 int	probability[] = {
79 	0, 11, 12, 13, 14, 15, 16,
80 	06, 05, 04, 03, 02, 01
81 };
82 
83 struct	{
84 	int	pos[4];
85 	int	mov[4];
86 } moves[MAXIMOVES];
87 
main()88 main()
89 {
90 	int	go[5], tvec[2];
91 	int	k, n, pid, ret, rpid, t;
92 	char	s[100];
93 
94 	srand(time(0));
95 	go[5] = NIL;
96 	fprintf(stdout, "Instructions? ");
97 	gets(s);
98 	if(*s == 'y')
99 		instructions();
100 	putchar('\n');
101 	fprintf(stdout, "Opponent's level: b - beginner,\n");
102 	fprintf(stdout, "i - intermediate, e - expert? ");
103 	level='e';
104 	gets(s);
105 	if(*s == 'b')
106 		level = 'b';
107 	else if(*s == 'i')
108 		level = 'i';
109 	putchar('\n');
110 	fprintf(stdout, "You will play brown.\n\n");
111 	fprintf(stdout, "Would you like to roll your own dice? ");
112 	gets(s);
113 	putchar('\n');
114 	if(*s == 'y')
115 		nobroll = 1;
116 	fprintf(stdout, "Would you like to go first? ");
117 	gets(s);
118 	putchar('\n');
119 	if(*s == 'y')
120 		goto nowhmove;
121 whitesmv:
122 	roll(WHITE);
123 	fprintf(stdout, "white rolls %d, %d\n", die1, die2);
124 	fprintf(stdout, "white's move is:");
125 	if(nextmove(white, brown) == NIL)
126 		goto nowhmove;
127 	if(piececount(white, 0, 24) == 0){
128 		fprintf(stdout, "White wins");
129 		if(piececount(brown, 0, 6) != 0)
130 			fprintf(stdout, " with a Backgammon!\n");
131 		else if (piececount(brown, 0, 24) == 24)
132 			fprintf(stdout, " with a Gammon.\n");
133 		else
134 			fprintf(stdout, ".\n");
135 		exit(0);
136 	}
137 nowhmove:
138 	if(pflg)
139 		prtbrd();
140 	roll(BROWN);
141 retry:
142 	fprintf(stdout, "\nYour roll is %d  %d\n", die1, die2);
143 	fprintf(stdout, "Move? ");
144 	gets(s);
145 	switch(*s) {
146 		case '\0':			/* empty line */
147 			fprintf(stdout, "Brown's move skipped.\n");
148 			goto whitesmv;
149 
150 		case 'b':			/* how many beared off? */
151 			fprintf(stdout, "Brown:   %d\n", piececount(brown, 0, 24) - 15);
152 			fprintf(stdout, "White:   %d\n", piececount(white, 0, 24) - 15);
153 			goto retry;
154 
155 		case 'p':			/* print board */
156 			prtbrd();
157 			goto retry;
158 
159 		case 's':			/* stop auto printing of board */
160 			pflg = 0;
161 			goto retry;
162 
163 		case 'r':			/* resume auto printing */
164 			pflg = 1;
165 			goto retry;
166 
167 		case 'm':			/* print possible moves */
168 			pmoves();
169 			goto retry;
170 
171 		case 'q':			/* i give up */
172 			exit(0);
173 
174 		case '!':			/* escape to Shell */
175 			if(s[1] != '\0')
176 				system(s+1);
177 			else if((pid = fork()) == 0) {
178 				execl("/bin/sh", "sh", "-", 0);
179 				fprintf(stderr, "back: cannot exec /bin/sh!\n");
180 				exit(2);
181 			}
182 			while((rpid = wait(&ret)) != pid && rpid != -1)
183 				;
184 			goto retry;
185 
186 		case '?':			/* well, what can i do? */
187 			fprintf(stdout, "<newline>	skip this move\n");
188 			fprintf(stdout, "b		number beared off\n");
189 			fprintf(stdout, "p		print board\n");
190 			fprintf(stdout, "q		quit\n");
191 			fprintf(stdout, "r		resume auto print of board\n");
192 			fprintf(stdout, "s		stop auto print of board\n");
193 			fprintf(stdout, "!		escape to Shell\n");
194 			goto retry;
195 	}
196 	n = sscanf(s,"%d%d%d%d%d",&go[0],&go[1],&go[2],&go[3],&go[4]);
197 	if((die1 != die2 && n > 2) || n > 4){
198 		fprintf(stdout, "Too many moves.\n");
199 		goto retry;
200 	}
201 	go[n] = NIL;
202 	if(*s=='-'){
203 		go[0]= -go[0];
204 		t=die1;
205 		die1=die2;
206 		die2=t;
207 	}
208 	for(k = 0; k < n; k++){
209 		if(0 <= go[k] && go[k] <= 24)
210 			continue;
211 		else{
212 			fprintf(stdout, "Move %d illegal.\n", go[k]);
213 			goto retry;
214 		}
215 	}
216 	if(play(brown, white, go))
217 		goto retry;
218 	if(piececount(brown, 0, 24) == 0){
219 		fprintf(stdout, "Brown wins");
220 		if(piececount(white, 0, 6) != 0)
221 			fprintf(stdout, " with a Backgammon.\n");
222 		else if(piececount(white, 0, 24) == 24)
223 			fprintf(stdout, " with a gammon.\n");
224 		else
225 			fprintf(stdout, ".\n");
226 		exit(0);
227 	}
228 	goto whitesmv;
229 }
230 
play(player,playee,pos)231 play(player,playee,pos)
232 int *player,*playee,pos[];
233 {
234 	int	k, n, die, ipos;
235 
236 	for(k=0; k < player[0]; k++){  /*blots on player[0] must be moved first*/
237 		if(pos[k] == NIL)
238 			break;
239 		if(pos[k] != 0){
240 			fprintf(stdout, "Stone on bar must be moved first.\n");
241 			return(NIL);
242 		}
243 	}
244 	for(k = 0; (ipos=pos[k]) != NIL; k++){
245 		die = k?die2:die1;
246 		n = 25-ipos-die;
247 		if(player[ipos] == 0)
248 			goto badmove;
249 		if(n > 0 && playee[n] >= 2)
250 			goto badmove;
251 		if(n <= 0){
252 			if(piececount(player,0,18) != 0)
253 				goto badmove;
254 			if((ipos+die) != 25 && piececount(player,19,24-die)!=0)
255 				goto badmove;
256 		}
257 		player[ipos]--;
258 		player[ipos+die]++;
259 	}
260 	for(k = 0; pos[k] != NIL; k++){
261 		die = k?die2:die1;
262 		n = 25-pos[k]-die;
263 		if(n>0 && playee[n]==1){
264 			playee[n]=0;
265 			playee[0]++;
266 		}
267 	}
268 	return(0);
269 
270 badmove:
271 	fprintf(stdout, "Move %d illegal.\n", ipos);
272 	while(k--){
273 		die=k?die2:die1;
274 		player[pos[k]]++;
275 		player[pos[k]+die]--;
276 	}
277 	return(NIL);
278 }
nextmove(player,playee)279 nextmove(player,playee)
280 int *player,*playee;
281 {
282 	int	k;
283 
284 	imoves=0;
285 	movegen(player,playee);
286 	if(die1!=die2){
287 		k=die1;
288 		die1=die2;
289 		die2=k;
290 		movegen(player,playee);
291 	}
292 	if(imoves==0){
293 		fprintf(stdout, "no move possible.\n");
294 		return(NIL);
295 	}
296 	k=strategy(player,playee);		/*select kth possible move*/
297 	prtmov(k);
298 	update(player,playee,k);
299 	return(0);
300 }
prtmov(k)301 prtmov(k)
302 int k;
303 {
304 	int	n;
305 
306 	if(k == NIL)
307 		fprintf(stdout, "No move possible\n");
308 	else for(n = 0; n < 4; n++){
309 		if(moves[k].pos[n] == NIL)
310 			break;
311 		fprintf(stdout, "    %d, %d",25-moves[k].pos[n],moves[k].mov[n]);
312 	}
313 	fprintf(stdout, "\n");
314 }
update(player,playee,k)315 update(player,playee,k)
316 int *player,*playee,k;
317 {
318 	int	n,t;
319 
320 	for(n = 0; n < 4; n++){
321 		if(moves[k].pos[n] == NIL)
322 			break;
323 		player[moves[k].pos[n]]--;
324 		player[moves[k].pos[n]+moves[k].mov[n]]++;
325 		t=25-moves[k].pos[n]-moves[k].mov[n];
326 		if(t>0 && playee[t]==1){
327 			playee[0]++;
328 			playee[t]--;
329 		}
330 	}
331 }
piececount(player,startrow,endrow)332 piececount(player,startrow,endrow)
333 int *player,startrow,endrow;
334 {
335 	int	sum;
336 
337 	sum=0;
338 	while(startrow <= endrow)
339 		sum += player[startrow++];
340 	return(sum);
341 }
pmoves()342 pmoves()
343 {
344 	int	i1, i2;
345 
346 	fprintf(stdout, "Possible moves are:\n");
347 	for(i1 = 0; i1 < imoves; i1++){
348 		fprintf(stdout, "\n%d",i1);
349 		 for (i2 = 0; i2<4; i2++){
350 			if(moves[i1].pos[i2] == NIL)
351 				break;
352 			fprintf(stdout, "%d, %d",moves[i1].pos[i2],moves[i1].mov[i2]);
353 		}
354 	}
355 	fprintf(stdout, "\n");
356 }
357 
roll(who)358 roll(who)
359 {
360 	register n;
361 	char	 s[10];
362 
363 	if(who == BROWN && nobroll) {
364 		fprintf(stdout, "Roll? ");
365 		gets(s);
366 		n = sscanf(s, "%d%d", &die1, &die2);
367 		if(n != 2 || die1 < 1 || die1 > 6 || die2 < 1 || die2 > 6)
368 			fprintf(stdout, "Illegal - I'll do it!\n");
369 		else
370 			return;
371 	}
372 	die1 = ((rand()>>8) % 6) + 1;
373 	die2 = ((rand()>>8) % 6) + 1;
374 }
375 
movegen(mover,movee)376 movegen(mover,movee)
377 int *mover,*movee;
378 {
379 	int	k;
380 
381 	for(i = 0; i <= 24; i++){
382 		count = 0;
383 		if(mover[i] == 0)
384 			continue;
385 		if((k=25-i-die1) > 0 && movee[k] >= 2)
386 			if(mover[0] > 0)
387 				break;
388 		else
389 			continue;
390 		if(k <= 0){
391 			if(piececount(mover, 0, 18) != 0)
392 				break;
393 			if((i+die1) != 25 && piececount(mover,19,i-1) != 0)
394 				break;
395 		}
396 		mover[i]--;
397 		mover[i+die1]++;
398 		count = 1;
399 		for(j = 0; j <= 24; j++){
400 			if(mover[j]==0)
401 				continue;
402 			if((k=25-j-die2) > 0 && movee[k] >= 2)
403 				if(mover[0] > 0)
404 					break;
405 			else
406 				continue;
407 			if(k <= 0){
408 				if(piececount(mover,0,18) != 0)
409 					break;
410 				if((j+die2) != 25 && piececount(mover,19,j-1) != 0)
411 					break;
412 			}
413 			mover[j]--;
414 			mover[j+die2]++;
415 			count = 2;
416 			if(die1 != die2){
417 				moverecord(mover);
418 				if(mover[0] > 0)
419 					break;
420 				else
421 					continue;
422 			}
423 			for(l = 0; l <= 24; l++){
424 				if(mover[l] == 0)
425 					continue;
426 				if((k=25-l-die1) > 0 && movee[k] >= 2)
427 					if(mover[0] > 0)
428 						break;
429 				else
430 					continue;
431 				if(k <= 0){
432 					if(piececount(mover, 0, 18) != 0)
433 						break;
434 					if((l+die2) != 25 && piececount(mover,19,l-1) != 0)
435 						break;
436 				}
437 				mover[l]--;
438 				mover[l+die1]++;
439 				count=3;
440 				for(m=0;m<=24;m++){
441 					if(mover[m]==0)
442 						continue;
443 					if((k=25-m-die1) >= 0 && movee[k] >= 2)
444 						if(mover[0] > 0)
445 							break;
446 					else
447 						continue;
448 					if(k <= 0){
449 						if(piececount(mover,0,18) != 0)
450 							break;
451 						if((m+die2) != 25 && piececount(mover,19,m-1) != 0)
452 							break;
453 					}
454 					count=4;
455 					moverecord(mover);
456 					if(mover[0] > 0)
457 						break;
458 				}
459 				if(count == 3)
460 					moverecord(mover);
461 				else{
462 					mover[l]++;
463 					mover[l+die1]--;
464 				}
465 				if(mover[0] > 0)
466 					break;
467 			}
468 			if(count == 2)
469 				moverecord(mover);
470 			else{
471 				mover[j]++;
472 				mover[j+die1]--;
473 			}
474 			if(mover[0] > 0)
475 				break;
476 		}
477 		if(count == 1)
478 			moverecord(mover);
479 		else{
480 			mover[i]++;
481 			mover[i+die1]--;
482 		}
483 		if(mover[0] > 0)
484 			break;
485 	}
486 }
moverecord(mover)487 moverecord(mover)
488 int *mover;
489 {
490 	int	t;
491 
492 	if(imoves < MAXIMOVES) {
493 		for(t = 0; t <= 3; t++)
494 			moves[imoves].pos[t] = NIL;
495 		switch(count) {
496 		case 4:
497 			moves[imoves].pos[3]=m;
498 			moves[imoves].mov[3]=die1;
499 
500 		case 3:
501 			moves[imoves].pos[2]=l;
502 			moves[imoves].mov[2]=die1;
503 
504 		case 2:
505 			moves[imoves].pos[1]=j;
506 			moves[imoves].mov[1]=die2;
507 
508 		case 1:
509 			moves[imoves].pos[0]=i;
510 			moves[imoves].mov[0]=die1;
511 			imoves++;
512 		}
513 	}
514 	switch(count) {
515 	case 4:
516 		break;
517 
518 	case 3:
519 		mover[l]++;
520 		mover[l+die1]--;
521 		break;
522 
523 	case 2:
524 		mover[j]++;
525 		mover[j+die2]--;
526 		break;
527 
528 	case 1:
529 		mover[i]++;
530 		mover[i+die1]--;
531 	}
532 }
533 
strategy(player,playee)534 strategy(player,playee)
535 int *player,*playee;
536 {
537 	int	k, n, nn, bestval, moveval, prob;
538 
539 	n = 0;
540 	if(imoves == 0)
541 		return(NIL);
542 	goodmoves[0] = NIL;
543 	bestval = -32000;
544 	for(k = 0; k < imoves; k++){
545 		if((moveval=eval(player,playee,k,&prob)) < bestval)
546 			continue;
547 		if(moveval > bestval){
548 			bestval = moveval;
549 			n = 0;
550 		}
551 		if(n<MAXGMOV){
552 			goodmoves[n]=k;
553 			probmoves[n++]=prob;
554 		}
555 	}
556 	if(level=='e' && n>1){
557 		nn=n;
558 		n=0;
559 		prob=32000;
560 		for(k = 0; k < nn; k++){
561 			if((moveval=probmoves[k]) > prob)
562 				continue;
563 			if(moveval<prob){
564 				prob=moveval;
565 				n=0;
566 			}
567 			goodmoves[n]=goodmoves[k];
568 			probmoves[n++]=probmoves[k];
569 		}
570 	}
571 	return(goodmoves[(rand()>>4)%n]);
572 }
573 
eval(player,playee,k,prob)574 eval(player,playee,k,prob)
575 int *player,*playee,k,*prob;
576 {
577 	int	newtry[31], newother[31], *r, *q, *p, n, sum, first;
578 	int	ii, lastwhite, lastbrown;
579 
580 	*prob = sum = 0;
581 	r = player+25;
582 	p = newtry;
583 	q = newother;
584 	while(player<r){
585 		*p++= *player++;
586 		*q++= *playee++;
587 	}
588 	q=newtry+31;
589 	for(p = newtry+25; p < q; p++)		/* zero out spaces for hit pieces */
590 		*p = 0;
591 	for(n = 0; n < 4; n++){
592 		if(moves[k].pos[n] == NIL)
593 			break;
594 		newtry[moves[k].pos[n]]--;
595 		newtry[ii=moves[k].pos[n]+moves[k].mov[n]]++;
596 		if(ii<25 && newother[25-ii]==1){
597 			newother[25-ii]=0;
598 			newother[0]++;
599 			if(ii<=15 && level=='e')		/* hit if near other's home */
600 				sum++;
601 		}
602 	}
603 	for(lastbrown = 0; newother[lastbrown] == 0; lastbrown++);
604 		;
605 	for(lastwhite = 0; newtry[lastwhite] == 0; lastwhite++)
606 		;
607 	lastwhite = 25-lastwhite;
608 	if(lastwhite<=6 && lastwhite<lastbrown)
609 		sum=1000;
610 									/* experts running game. */
611 									/* first priority is to */
612 									/* get all pieces into */
613 									/* white's home */
614 	if(lastwhite<lastbrown && level=='e' && lastwhite>6) {
615 		for(sum = 1000; lastwhite > 6; lastwhite--)
616 			sum = sum-lastwhite*newtry[25-lastwhite];
617 	}
618 	for(first = 0; first < 25; first++)
619 		if(newother[first] != 0)		/*find other's first piece*/
620 			break;
621 	q = newtry+25;
622 	for(p = newtry+1; p < q;)			/* blocked points are good */
623 		if(*p++ > 1)
624 			sum++;
625 	if(first > 5) {					/* only stress removing pieces if */
626 							/* homeboard cannot be hit */
627 		q = newtry+31;
628 		p=newtry+25;
629 		for(n = 6; p < q; n--)
630 			sum += *p++ * n;			/*remove pieces, but just barely*/
631 	}
632 	if(level != 'b'){
633 		r = newtry+25-first;	/*singles past this point can't be hit*/
634 		for(p = newtry+7; p < r; )
635 			if(*p++ == 1)		/*singles are bad after 1st 6 points if they can be hit*/
636 				sum--;
637 		q = newtry+3;
638 		for(p = newtry; p < q; )	   /*bad to be on 1st three points*/
639 			sum -= *p++;
640 	}
641 
642 	for(n = 1; n <= 4; n++)
643 		*prob += n*getprob(newtry,newother,6*n-5,6*n);
644 	return(sum);
645 }
instructions()646 instructions()
647 {
648 	register fd, r;
649 	char	 buf[BUFSIZ];
650 
651 	if((fd = open(RULES, 0)) < 0) {
652 		fprintf(stderr, "back: cannot open %s\n", RULES);
653 		return;
654 	}
655 	while(r = read(fd, buf, BUFSIZ))
656 		write(1, buf, r);
657 }
658 
getprob(player,playee,start,finish)659 getprob(player,playee,start,finish)
660 int *player,*playee,start,finish;
661 {			/*returns the probability (times 102) that any
662 			  pieces belonging to 'player' and lying between
663 			  his points 'start' and 'finish' will be hit
664 			  by a piece belonging to playee
665 			*/
666 	int	k, n, sum;
667 
668 	sum = 0;
669 	for(; start <= finish; start++){
670 		if(player[start] == 1){
671 			for(k = 1; k <= 12; k++){
672 				if((n=25-start-k) < 0)
673 					break;
674 				if(playee[n] != 0)
675 					sum += probability[k];
676 			}
677 		}
678 	}
679 	return(sum);
680 }
prtbrd()681 prtbrd()
682 {
683 	int	k;
684 	static char undersc[]="______________________________________________________";
685 
686 	fprintf(stdout, "White's Home\n%s\r",undersc);
687 	for(k = 1; k <= 6; k++)
688 		fprintf(stdout, "%4d",k);
689 	fprintf(stdout, "    ");
690 	for(k = 7; k <= 12; k++)
691 		fprintf(stdout, "%4d",k);
692 	putchar('\n');
693 	numline(brown, white, 1, 6);
694 	fprintf(stdout, "    ");
695 	numline(brown, white, 7, 12);
696 	putchar('\n');
697 	colorline(brown, 'B', white, 'W', 1, 6);
698 	fprintf(stdout, "    ");
699 	colorline(brown, 'B', white, 'W', 7, 12);
700 	putchar('\n');
701 	if(white[0] != 0)
702 		fprintf(stdout, "%28dW\n",white[0]);
703 	else
704 		putchar('\n');
705 	if(brown[0] != 0)
706 		fprintf(stdout, "%28dB\n", brown[0]);
707 	else
708 		putchar('\n');
709 	colorline(white, 'W', brown, 'B', 1, 6);
710 	fprintf(stdout, "    ");
711 	colorline(white, 'W', brown, 'B', 7, 12);
712 	fprintf(stdout, "\n%s\r",undersc);
713 	numline(white, brown, 1, 6);
714 	fprintf(stdout, "    ");
715 	numline(white, brown, 7, 12);
716 	putchar('\n');
717 	for(k = 24; k >= 19; k--)
718 		fprintf(stdout, "%4d",k);
719 	fprintf(stdout, "    ");
720 	for(k = 18; k >= 13; k--)
721 		fprintf(stdout, "%4d",k);
722 	fprintf(stdout, "\nBrown's Home\n\n\n\n\n");
723 }
numline(upcol,downcol,start,fin)724 numline(upcol,downcol,start,fin)
725 int *upcol,*downcol,start,fin;
726 {
727 	int	k, n;
728 
729 	for(k = start; k <= fin; k++){
730 		if((n = upcol[k]) != 0 || (n = downcol[25-k]) != 0)
731 			fprintf(stdout, "%4d", n);
732 		else
733 			fprintf(stdout, "    ");
734 	}
735 }
colorline(upcol,c1,downcol,c2,start,fin)736 colorline(upcol,c1,downcol,c2,start,fin)
737 int *upcol,*downcol,start,fin;
738 char c1,c2;
739 {
740 	int	k;
741 	char 	c;
742 
743 	for(k = start; k <= fin; k++){
744 		c = ' ';
745 		if(upcol[k] != 0)
746 			c = c1;
747 		if(downcol[25-k] != 0)
748 			c = c2;
749 		fprintf(stdout, "   %c",c);
750 	}
751 }
752