[alt.sources] Video Christmas Card

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
====================================================================