istvan@hhb.UUCP (Istvan Mohos) (12/20/89)
Found this while dusting off programs in a long forgotten directory... a video Christmas Card, implementing the recursive "Towers of Hanoi" algorithm (to twelve levels), disguised as tiers of a Christmas tree. What was the last time *you* used low-level termcap routines? (Incidentally, SysV versions of tgetent() seem to be hard-coded to read in /etc/termcap instead of the environment variable $TERMCAP, for your terminal description. Do tgetent(), etc. still work with termio? I don't know.) ------------------------------CUT HERE--------------------------------- /********************************************************************** * card.c --- Christmas Card From Hanoi --- by Istvan Mohos, 1984 * * Compile with "/bin/cc card.c -ltermlib -o card" * Use with ttys at 9600/4800/2400 baud; don't bother at slower speeds. * Running under SysV and BSD, on Pyramid, VAX, SUN. * SunWindows flow-control a mess, but OK on console. * * Thanks to Bill Tuthill for showing me curses... **********************************************************************/ #include <stdio.h> #define WRITENEXT tputs(tgoto(CM,HOR,VER),1,string);\ printf("%s",disk[map[from.deep][from.pole]]) #define ERASEPREV tputs(tgoto(CM,HOR,VER),1,string);\ printf("%s",disk[14]) #define PUTBLANK tputs(tgoto(CM,HOR,VER),1,string);\ printf("%s",disk[0]) string(c) register char c; { putchar(c); } static long counter = 1; struct diskpos { int ver; int hor; }; static struct diskpos level[16][3] = { 7,0, 7,28, 7,55, 8,0, 8,28, 8,55, 9,0, 9,28, 9,55, 10,0, 10,28, 10,55, 11,0, 11,28, 11,55, 12,0, 12,28, 12,55, 13,0, 13,28, 13,55, 14,0, 14,28, 14,55, 15,0, 15,28, 15,55, 16,0, 16,28, 16,55, 17,0, 17,28, 17,55, 18,0, 18,28, 18,55, 19,0, 19,28, 19,55, 20,0, 20,28, 20,55, 21,0, 21,28, 21,55, 22,0, 22,28, 22,55 }; static struct diskpos flyway[17][6] = { 7, 0, 7, 0, 7,55, 7,55, 7,28, 7,28, 6, 1, 6, 1, 6,54, 6,54, 6,29, 6,27, 5, 2, 5, 2, 5,53, 5,53, 5,30, 5,26, 4, 4, 4, 4, 4,51, 4,51, 4,32, 4,24, 3, 7, 3, 7, 3,48, 3,48, 3,35, 3,21, 2,13, 2,13, 2,42, 2,42, 2,42, 2,13, 1,19, 3,21, 1,37, 3,35, 3,48, 3, 7, 0,28, 4,24, 0,26, 4,32, 4,51, 4, 4, 1,37, 5,26, 1,19, 5,30, 5,53, 5, 2, 2,42, 6,27, 2,13, 6,29, 6,54, 6, 1, 3,48, 7,28, 3, 7, 7,28, 7,55, 7, 0, 4,51, 8,28, 4, 4, 8,28, 8,55, 8, 0, 5,53, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 6,54, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 7,55, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8,55, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0 }; /* an extra line of 0 initialized above, used for sentinel */ static char *disk[] = { " ", " may ", " every ", " falling ", " snowflake ", " bring peace ", " may every day ", " be as christmas ", " filled with quiet ", " expectant happiness ", " joy and understanding ", " our human souls shining ", "loving caring for another", "~~~~~~~~~~~~~~~~~~~~~~~~~", " | ",}; struct handle { int deep; int pole; }; int map[15][3]; int HOR, VER; char *term, entry[1024], buf[512], *area; char *getenv(), *tgetstr(), *tgoto(); char *CL, *CM; main() { int temp, i; struct handle from, to, lazy; from.pole=0; to.pole=2; lazy.pole=1; term = getenv("TERM"); if (tgetent(entry, term) != 1) perror("bad or missing termcap... but MERRY CHRISTMAS !"), exit(1); if (tgetnum("li") < 23) perror("screen too small... but MERRY CHRISTMAS !"), exit(1); if (tgetnum("co") < 80) perror("screen too small... but MERRY CHRISTMAS !"), exit(1); area = buf; CL = tgetstr("cl", &area); CM = tgetstr("cm", &area); /* initialize map matrix */ for ( i=12; i > -1; --i ) { map[i][0] = i; map[i][1] = 14; map[i][2] = 14; } map[13][0] = 13; map[13][1] = 13; map[13][2] = 13; map[0][1] = 0; map[0][2] = 0; /* print field */ tputs(CL, 1, string); for ( i=1; i<14; ++i ) { for ( temp=2; temp > -1; --temp ) { VER = level[i][temp].ver; HOR = level[i][temp].hor; tputs(tgoto(CM,HOR,VER),1,string); printf("%s",disk[map[i][temp]]); } } tputs(tgoto(CM,26,22),1,string); printf("<<*>> Merry Christmas! <<*>>"); hanoi(12,from,lazy,to); exit(0); } hanoi (high,from,lazy,to) int high; struct handle from,lazy,to; { int i; if ( high != 0 ) { hanoi(high-1,from,to,lazy); i=1; while ( map[i][from.pole] == 14 ) ++i; from.deep = i; i=1; while ( map[i][to.pole] == 14 ) ++i; to.deep = i-1; move_disk( from, to); map[to.deep][to.pole] = map[from.deep][from.pole]; map[from.deep][from.pole] = 14; ++counter; tputs(tgoto(CM,12,7),1,string); printf("*"); tputs(tgoto(CM,40,7),1,string); printf("*"); tputs(tgoto(CM,67,7),1,string); printf("*"); tputs(tgoto(CM,33,22),1,string); if (counter % 2) printf("Merry Christmas!"); else printf("Happy New Year! "); hanoi(high-1,lazy,from,to); } } down_the_pole (from, to) struct handle from, to; { int i; for ( i=2; i <= to.deep; ++i ) { VER = level[i][to.pole].ver; HOR = level[i][to.pole].hor; tputs(tgoto(CM,HOR,VER),1,string); printf("%s",disk[map[from.deep][from.pole]]); VER = level[i-1][to.pole].ver; HOR = level[i-1][to.pole].hor; tputs(tgoto(CM,HOR,VER),1,string); printf("%s",disk[14]); } } fly (from, to) struct handle from, to; { int i; switch ( from.pole + to.pole * 10 ) { case 20: for ( i=1; flyway[i][0].ver + flyway[i][0].hor; ++i ) { VER = flyway[i][0].ver; HOR = flyway[i][0].hor; WRITENEXT; VER = flyway[i-1][0].ver; HOR = flyway[i-1][0].hor; PUTBLANK; } break; case 10: for ( i=1; flyway[i][1].ver + flyway[i][1].hor; ++i ) { VER = flyway[i][1].ver; HOR = flyway[i][1].hor; WRITENEXT; VER = flyway[i-1][1].ver; HOR = flyway[i-1][1].hor; PUTBLANK; } break; case 2: for ( i=1; flyway[i][2].ver + flyway[i][2].hor; ++i ) { VER = flyway[i][2].ver; HOR = flyway[i][2].hor; WRITENEXT; VER = flyway[i-1][2].ver; HOR = flyway[i-1][2].hor; PUTBLANK; } break; case 12: for ( i=1; flyway[i][3].ver + flyway[i][3].hor; ++i ) { VER = flyway[i][3].ver; HOR = flyway[i][3].hor; WRITENEXT; VER = flyway[i-1][3].ver; HOR = flyway[i-1][3].hor; PUTBLANK; } break; case 21: for ( i=1; flyway[i][4].ver + flyway[i][4].hor; ++i ) { VER = flyway[i][4].ver; HOR = flyway[i][4].hor; WRITENEXT; VER = flyway[i-1][4].ver; HOR = flyway[i-1][4].hor; PUTBLANK; } break; case 1: for ( i=1; flyway[i][5].ver + flyway[i][5].hor; ++i ) { VER = flyway[i][5].ver; HOR = flyway[i][5].hor; WRITENEXT; VER = flyway[i-1][5].ver; HOR = flyway[i-1][5].hor; PUTBLANK; } break; default: printf("invalid case value\n"); break; } } up_the_pole (from) struct handle from; { int i; for ( i=from.deep; i; --i ) { VER = level[i-1][from.pole].ver; HOR = level[i-1][from.pole].hor; WRITENEXT; VER = level[i][from.pole].ver; HOR = level[i][from.pole].hor; ERASEPREV; } } move_disk (from, to) struct handle from, to; { up_the_pole(from); fly(from, to); down_the_pole(from, to); } ------------------------------CUT HERE--------------------------------- -- Istvan Mohos ...uunet!pyrdc!pyrnj!hhb!istvan HHB Systems 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000 ====================================================================