home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume3 / puzzle / puzzle.c < prev    next >
C/C++ Source or Header  |  1988-02-19  |  13KB  |  522 lines

  1.     /*
  2.      *    Puzzle,  By Henk-Jan Visscher.
  3.      * 
  4.      *    compile:
  5.      *        cc -O puzzle.c -o puzzle -ltermcap
  6.      *        strip puzzle
  7.      *
  8.      *    NB : change UID in own UID.
  9.      */
  10.  
  11. #include    <stdio.h>
  12. #include    <signal.h>
  13. #include    <sys/types.h>
  14. #include    <sgtty.h>
  15. #include    <pwd.h>
  16.  
  17. extern    char    *tgoto ();
  18.  
  19. #define        scr_init()    tputs (IS, 0, xputc)
  20. #define        clear()        tputs (CL, 0, xputc)
  21. #define     rev_begin()    tputs (SO, 0, xputc)
  22. #define     rev_end()    tputs (SE, 0, xputc)
  23. #define        cursor(y, x)    tputs (tgoto (CM, x, y), 0, xputc)
  24. #define        hi_begin()    tputs (HI, 0, xputc)
  25. #define        hi_end()    tputs (HE, 0, xputc)
  26. #define        home()        tputs (HO, 0, xputc)
  27. #define        bell()        xputc ('\007')
  28. #define        flush()        fflush (stdout)
  29.  
  30. #define        UID        320
  31.  
  32. #define        BORDER        -1
  33. #define        EMPTY        0
  34. #define        SMALL        1
  35. #define        WIDTH        2
  36. #define        HIGH        3
  37. #define        BIG        4
  38.  
  39. #define        CLEAR        0
  40. #define        DRAW        1
  41. #define        ACCENT        2
  42.  
  43. char    *CL, *SO, *SE, *IS, *CM, *HI, *HE, *HO, ch;
  44. short    x, y;
  45. int    moves;
  46.  
  47. struct    sgttyb    sg, save;
  48.  
  49. struct field {
  50.     short    hx, hy, type;
  51. } field [6] [7];
  52.  
  53. struct mem {
  54.     short   nx, ny, ox, oy;
  55. } tb [9999];
  56.  
  57. struct mem sol [] = {
  58.     { 1, 1, 2, 1 } , { 1, 2, 1, 1 } , { 2, 3, 1, 3 } , { 3, 2, 3, 1 } ,
  59.     { 4, 2, 3, 2 } , { 4, 1, 4, 2 } , { 3, 1, 4, 1 } , { 3, 2, 3, 1 } ,
  60.     { 1, 3, 2, 3 } , { 2, 3, 3, 3 } , { 2, 2, 2, 3 } , { 2, 1, 2, 2 } , 
  61.     { 2, 3, 1, 3 } , { 2, 2, 2, 3 } , { 3, 1, 2, 1 } , { 4, 2, 3, 2 } ,
  62.     { 3, 2, 3, 1 } , { 3, 3, 3, 2 } , { 2, 3, 3, 3 } , { 3, 3, 4, 3 } ,
  63.     { 1, 3, 2, 3 } , { 2, 3, 3, 3 } , { 1, 1, 1, 2 } , { 2, 1, 2, 2 } ,
  64.     { 3, 1, 2, 1 } , { 2, 1, 1, 1 } , { 4, 1, 3, 1 } , { 3, 1, 2, 1 } ,
  65.     { 3, 2, 3, 1 } , { 3, 3, 3, 2 } , { 3, 2, 4, 2 } , { 2, 2, 3, 2 } ,
  66.     { 1, 2, 2, 2 } , { 1, 4, 1, 3 } , { 1, 3, 1, 2 } , { 2, 4, 1, 4 } ,
  67.     { 4, 4, 3, 4 } , { 4, 3, 4, 4 } , { 4, 4, 4, 5 } , { 4, 2, 4, 3 } ,
  68.     { 4, 3, 4, 4 } , { 3, 2, 4, 2 } , { 3, 4, 3, 3 } , { 3, 3, 3, 2 } ,
  69.     { 1, 4, 2, 4 } , { 1, 2, 1, 3 } , { 1, 3, 1, 4 } , { 2, 2, 1, 2 } ,
  70.     { 3, 2, 2, 2 } , { 4, 2, 3, 2 } , { 4, 4, 4, 3 } , { 4, 3, 4, 2 } ,
  71.     { 4, 5, 4, 4 } , { 4, 4, 4, 3 } , { 2, 4, 3, 4 } , { 2, 2, 2, 3 } ,
  72.     { 2, 3, 2, 4 } , { 3, 2, 2, 2 } , { 4, 2, 3, 2 } , { 3, 2, 3, 3 } ,
  73.     { 3, 1, 3, 2 } , { 2, 1, 3, 1 } , { 3, 1, 4, 1 } , { 1, 1, 2, 1 } , 
  74.     { 2, 1, 3, 1 } , { 1, 2, 1, 1 } , { 2, 2, 2, 1 } , { 3, 3, 2, 3 } ,
  75.     { 2, 3, 1, 3 } , { 4, 3, 3, 3 } , { 3, 3, 2, 3 } , { 3, 2, 3, 3 } ,
  76.     { 4, 1, 4, 2 } , { 3, 1, 4, 1 } , { 2, 1, 3, 1 } , { 2, 3, 2, 2 } , 
  77.     { 2, 2, 2, 1 } , { 2, 4, 2, 3 } , { 2, 3, 2, 2 } , { 1, 4, 2, 4 } ,
  78.     { 1, 3, 1, 4 } , { 1, 4, 1, 5 } , { 1, 1, 1, 2 } , { 1, 2, 1, 3 } ,
  79.     { 2, 1, 1, 1 } , { 1, 1, 1, 2 } , { 2, 2, 2, 1 } , { 2, 4, 2, 3 } ,
  80.     { 1, 5, 2, 5 } , { 1, 3, 1, 4 } , { 1, 2, 1, 3 } , { 2, 1, 1, 1 } ,
  81.     { 2, 3, 2, 2 } , { 2, 2, 2, 1 } , { 1, 3, 2, 3 } , { 2, 3, 2, 4 } ,
  82.     { 1, 4, 1, 3 } , { 2, 5, 1, 5 } , { 2, 4, 2, 5 } , { 2, 1, 2, 2 } ,
  83.     { 2, 2, 2, 3 } , { 3, 1, 2, 1 } , { 4, 1, 3, 1 } , { 4, 2, 4, 1 } , 
  84.     { 3, 3, 3, 2 } , { 3, 4, 3, 3 } , { 2, 5, 3, 5 } , { 3, 5, 4, 5 } ,
  85.     { 1, 5, 2, 5 } , { 2, 5, 3, 5 } , { 1, 3, 1, 4 } , { 1, 1, 1, 2 } ,
  86.     { 2, 3, 2, 4 } , { 2, 1, 2, 2 } , { 3, 1, 2, 1 } , { 2, 1, 1, 1 } ,
  87.     { 4, 1, 3, 1 } , { 3, 1, 2, 1 } , { 3, 2, 3, 1 } , { 3, 3, 3, 2 } ,
  88.     { 3, 5, 3, 4 } , { 3, 4, 4, 4 } , { 2, 4, 3, 4 } , { 2, 2, 2, 3 } ,
  89.     { 2, 3, 2, 4 } , { 3, 2, 2, 2 } , { 4, 4, 4, 3 } , { 4, 3, 4, 2 } ,
  90.     { 4, 5, 4, 4 } , { 4, 4, 4, 3 } , { 3, 4, 4, 4 } , { 2, 4, 3, 4 } ,
  91.     { 1, 4, 2, 4 } , { 1, 2, 1, 3 } , { 1, 3, 1, 4 } , { 2, 2, 1, 2 } ,
  92.     { 4, 2, 3, 2 } , { 3, 2, 3, 3 } , { 3, 1, 3, 2 } , { 2, 1, 3, 1 } ,
  93.     { 3, 1, 4, 1 } , { 1, 1, 2, 1 } , { 2, 1, 3, 1 } , { 1, 2, 1, 1 } , 
  94.     { 3, 3, 2, 3 } , { 2, 3, 1, 3 } , { 4, 3, 3, 3 } , { 3, 3, 2, 3 } ,
  95.     { 3, 2, 3, 3 } , { 3, 1, 3, 2 } , { 3, 2, 4, 2 } , { 1, 1, 2, 1 } ,
  96.     { 0, 0, 0, 0 }
  97. };
  98.  
  99. main ()
  100. {
  101.     init ();
  102.     layout ();
  103.     initfield (); 
  104.     for (;;)
  105.         move ();
  106. }
  107.  
  108. init ()
  109. {
  110.     int    leave ();
  111. #ifdef    SIGTSTP
  112.     int    sigtstp();
  113. #endif    SIGTSTP
  114.     int    xputc ();
  115.     char    buffer [1024];
  116.     static  char    save_buf [100];
  117.     char    *ptr  = save_buf;
  118.     extern     char    *tgetstr ();
  119.  
  120.     signal (SIGINT, leave);
  121.     signal (SIGQUIT, leave);
  122. #ifdef    SIGTSTP
  123.     signal (SIGTSTP, sigtstp);
  124. #endif  SIGTSTP
  125.  
  126.     gtty (1, &sg);
  127.     save = sg;
  128.     sg.sg_flags |= CBREAK;
  129.     sg.sg_flags &= ~ECHO;
  130.     stty (1, &sg);
  131.  
  132.     switch (tgetent (buffer, getenv ("TERM"))) {
  133.         case -1:
  134.             fprintf (stderr, "can't open \"termcap\" file.\n");
  135.             exit (1);
  136.         case 0:
  137.             fprintf (stderr, "can't find entry for term.type.\n");
  138.             exit (1);
  139.     }
  140.  
  141.     IS = tgetstr ("is", &ptr);
  142.     CL = tgetstr ("cl", &ptr);
  143.     CM = tgetstr ("cm", &ptr);
  144.     SO = tgetstr ("so", &ptr);
  145.     SE = tgetstr ("se", &ptr);
  146.     HI = tgetstr ("hi", &ptr);
  147.     HE = tgetstr ("he", &ptr);
  148.     HO = tgetstr ("ho", &ptr);
  149.     if (!CL || !CM || !SO || !SE || !HI || !HE || !HO) {
  150.         fprintf (stderr, "not a right terminal.\n");
  151.         stty (1, &save);
  152.         exit (1);
  153.     }
  154.     if (IS != (char *) 0)    scr_init ();
  155.     ch = ' ';
  156. }
  157.  
  158. #ifdef    SIGTSTP
  159. sigtstp()
  160. {
  161.     signal (SIGTSTP, SIG_IGN);
  162.     stty (1, &save);
  163.     cursor (23, 0);
  164.     flush ();
  165.     kill (0, SIGSTOP);
  166.     signal (SIGTSTP, sigtstp);
  167.     stty (1, &sg);
  168.     redraw ();
  169. }
  170. #endif    SIGTSTP
  171.  
  172. leave ()
  173. {
  174.     stty (1, &save);
  175.     cursor (23, 0);
  176.     exit (0);
  177. }
  178.  
  179. fill (x, y, px, py, mode)
  180. short    x, y, px, py, mode;
  181. {
  182.     short    i, j;
  183.  
  184.     for (i = y; i < y+py; i++)
  185.     {
  186.         cursor (i, x);
  187.         if (mode != CLEAR) rev_begin ();
  188.         if (mode == ACCENT) hi_begin ();
  189.         for (j = x; j < x+px; j++)
  190.             putchar ((mode == ACCENT) ? ch : ' ');
  191.         if (mode != CLEAR) rev_end ();
  192.         if (mode == ACCENT) hi_end ();
  193.     }
  194. }
  195.  
  196. /* VARARGS3 */
  197. pline (yc, xc, format, arg)
  198. short    yc, xc;
  199. char    *format;
  200. int    arg;
  201. {
  202.     cursor (yc, xc);
  203.     printf (format, arg);
  204. }
  205.  
  206. layout ()
  207. {
  208.     clear ();
  209.     fill (7, 2, 34, 20, DRAW);
  210.     fill (18, 2, 12, 2, CLEAR);
  211.     fill (11, 4, 26, 16, CLEAR);
  212.     pline (3, 46, "PUZZLE   (By HJ Visscher)");
  213.     pline (5, 46, "Purpose  :");
  214.     pline (6, 46, "----------");
  215.     pline (7, 46, "Try to move the biggest");
  216.     pline (8, 46, "piece through the hole at");
  217.     pline (9, 46, "the top.");
  218.     pline (11, 46, "Commands  :");
  219.     pline (12, 46, "------------");
  220.     pline (13, 46, "y   k   u  \\");
  221.     pline (14, 46, "  \\ | /     \\");
  222.     pline (15, 46, "h - * - l    |- To Move");
  223.     pline (16, 46, "  / | \\     /");
  224.     pline (17, 46, "b   j   n  /");
  225.     pline (19, 46, "Q - Quit      T - Take back");
  226.     pline (20, 46, "R - Redraw    ? - Solution");
  227.     pline (21, 46, "N - New Game  A - Extra accent");
  228. }
  229.  
  230. redraw ()
  231. {
  232.     short    i, j;
  233.  
  234.     layout ();
  235.     for (i = 1; i < 5; i++)
  236.         for (j = 1; j < 6; j++)
  237.             if (field [i] [j]. hx == i && field [i] [j]. hy == j)
  238.                 change (DRAW, i, j, field [i] [j]. type);
  239.     change (ACCENT, x, y, field [x] [y]. type);
  240.     pline (22, 20, "Moves : %04d", moves);
  241.     home ();
  242. }
  243.  
  244. clfield ()
  245. {
  246.     short i, j;
  247.     static struct field empty_field;
  248.  
  249.     for (i = 0; i < 6; i++)
  250.         for (j = 0; j < 7; j++)
  251.             field [i] [j] = empty_field;
  252.     for (i = 0; i < 6; i++)
  253.         field [i] [0]. type = field [i] [6]. type = BORDER;
  254.     for (j = 0; j < 7; j++)
  255.         field [0] [j]. type = field [5] [j]. type = BORDER;
  256. }
  257.  
  258. change (task, xc, yc, kind)
  259. short    task, xc, yc, kind;
  260. {
  261.     field [xc] [yc]. hx = (task == CLEAR) ? 0 : xc;
  262.     field [xc] [yc]. hy = (task == CLEAR) ? 0 : yc;
  263.     field [xc] [yc]. type = (task == CLEAR) ? EMPTY : kind;
  264.     switch (kind) {
  265.         case SMALL:
  266.             fill (7+xc*6, 2+yc*3, 4, 2, task);
  267.             return;
  268.         case WIDTH:
  269.             field [xc+1] [yc]. hx = (task == CLEAR) ? 0 : xc;
  270.             field [xc+1] [yc]. hy = (task == CLEAR) ? 0 : yc;
  271.             fill (7+xc*6, 2+yc*3, 10, 2, task);
  272.             return;
  273.         case HIGH:
  274.             field [xc] [yc+1]. hx = (task == CLEAR) ? 0 : xc;
  275.             field [xc] [yc+1]. hy = (task == CLEAR) ? 0 : yc;
  276.             fill (7+xc*6, 2+yc*3, 4, 5, task);
  277.             return;
  278.         case BIG:
  279.             field [xc+1] [yc]. hx = field [xc] [yc+1]. hx =
  280.                 field [xc+1] [yc+1]. hx = 
  281.                 (task == CLEAR) ? 0 : xc;
  282.             field [xc+1] [yc]. hy = field [xc] [yc+1]. hy =
  283.                 field [xc+1] [yc+1]. hy = 
  284.                 (task == CLEAR) ? 0 : yc;
  285.             fill (7+xc*6, 2+yc*3, 10, 5, task);
  286.             return;
  287.     }
  288. }
  289.  
  290. initfield ()
  291. {
  292.     clfield ();
  293.     change (ACCENT, 1, 1, SMALL);
  294.     change (DRAW, 2, 2, SMALL);
  295.     change (DRAW, 3, 2, SMALL);
  296.     change (DRAW, 4, 1, SMALL);
  297.     change (DRAW, 1, 2, HIGH);
  298.     change (DRAW, 1, 4, HIGH);
  299.     change (DRAW, 4, 2, HIGH);
  300.     change (DRAW, 4, 4, HIGH);
  301.     change (DRAW, 2, 3, WIDTH);
  302.     change (DRAW, 2, 4, BIG);
  303.     x = y = 1;
  304.     moves = 0;
  305.     pline (22, 20, "Moves : %04d", moves);
  306.     home ();
  307. }
  308.  
  309. move ()
  310. {
  311.     char    c;
  312.     short    nx, ny, px, py;
  313.     short    movem, kind;
  314.  
  315.     c = getchar ();
  316.  
  317.     px = (field [x] [y]. type == BIG||field [x] [y]. type == WIDTH) ? 2 : 1;
  318.     py = (field [x] [y]. type == BIG||field [x] [y]. type == HIGH) ? 2 : 1;
  319.     movem = 0;
  320.     switch (c) {
  321.         case 'A' : ch = (ch == ' ') ? ':' : ' ';
  322.                change (ACCENT, x, y, field [x] [y]. type);
  323.                home ();
  324.                return;
  325.         case 'Q' : clear ();
  326.                leave ();
  327.         case 'R' : redraw ();
  328.                return;
  329.         case '?' : solution ();
  330.                return;
  331.         case 'T' : takeback ();
  332.                return;
  333.         case 'N' : new ();
  334.                return;
  335.         case 'h' : nx = field [x-1] [y]. hx;
  336.                ny = field [x-1] [y]. hy;
  337.                if (nx == EMPTY && py == 2) {
  338.                 nx = field [x-1] [y+1]. hx;
  339.                 ny = field [x-1] [y+1]. hy;
  340.                }
  341.                movem = 1;
  342.                break;
  343.         case 'j' : nx = field [x] [y+py]. hx;
  344.                ny = field [x] [y+py]. hy;
  345.                if (nx == EMPTY && px == 2) {
  346.                 nx = field [x+1] [y+py]. hx;
  347.                 ny = field [x+1] [y+py]. hy;
  348.                }
  349.                movem = 1;
  350.                break;
  351.         case 'k' : nx = field [x] [y-1]. hx;
  352.                ny = field [x] [y-1]. hy;
  353.                if (nx == EMPTY && px == 2) {
  354.                 nx = field [x+1] [y-1]. hx;
  355.                 ny = field [x+1] [y-1]. hy;
  356.                }
  357.                movem = 1;
  358.                break;
  359.         case 'l' : nx = field [x+px] [y]. hx;
  360.                ny = field [x+px] [y]. hy;
  361.                if (nx == EMPTY && py == 2) {
  362.                 nx = field [x+px] [y+1]. hx;
  363.                 ny = field [x+px] [y+1]. hy;
  364.                }
  365.                movem = 1;
  366.                break;
  367.         case 'y' : nx = field [x-1] [y-1]. hx;
  368.                ny = field [x-1] [y-1]. hy;
  369.                break;
  370.         case 'u' : nx = field [x+px] [y-1]. hx;
  371.                ny = field [x+px] [y-1]. hy;
  372.                if (nx == EMPTY) {
  373.                 nx = field [x+1] [y-1]. hx;
  374.                    ny = field [x+1] [y-1]. hy;
  375.                }
  376.                break;
  377.         case 'b' : nx = field [x-1] [y+py]. hx;
  378.                ny = field [x-1] [y+py]. hy;
  379.                if (nx == EMPTY) {
  380.                 nx = field [x-1] [y+1]. hx;
  381.                    ny = field [x-1] [y+1]. hy;
  382.                }
  383.                break;
  384.         case 'n' : nx = field [x+px] [y+py]. hx;
  385.                ny = field [x+px] [y+py]. hy;
  386.                if (nx == EMPTY) {
  387.                 nx = field [x+1] [y+1]. hx;
  388.                    ny = field [x+1] [y+1]. hy;
  389.                }
  390.                break;
  391.         default  : bell ();
  392.                return;
  393.     }
  394.  
  395.     if (nx != EMPTY) {
  396.         change (DRAW, x, y, field [x] [y]. type);
  397.         change (ACCENT, nx, ny, field [nx] [ny]. type);
  398.         home ();
  399.         x = nx; y = ny;
  400.         return;
  401.     }
  402.  
  403.     if (!movem) {
  404.         bell ();
  405.         return;
  406.     }
  407.  
  408.     kind = field [x] [y]. type;
  409.     change (CLEAR, x, y, kind);
  410.     nx = x + (c == 'l') - (c == 'h');
  411.     ny = y + (c == 'j') - (c == 'k');
  412.     if (!space (nx, ny, kind)) {
  413.         if (c == 'k' && kind == BIG && x == 2 && y == 1) solved ();
  414.         change (ACCENT, x, y, kind);
  415.         bell ();
  416.         home ();
  417.         return;
  418.     }
  419.     change (ACCENT, nx, ny, kind);
  420.     pline (22, 20, "Moves : %04d", ++moves);
  421.     home ();
  422.     tb [moves]. ox = x; 
  423.     tb [moves]. oy = y;
  424.     tb [moves]. nx = nx; 
  425.     tb [moves]. ny = ny;
  426.     x = nx; y = ny;
  427. }
  428.  
  429. space (xc, yc, kind)
  430. short     xc, yc, kind;
  431. {
  432.     if (field [xc] [yc]. type) return (0);
  433.     switch (kind) {
  434.         case SMALL : return (1);
  435.         case WIDTH : return (field [xc+1] [yc]. type == EMPTY);
  436.         case HIGH  : return (field [xc] [yc+1]. type == EMPTY);
  437.         case BIG : return (field [xc+1] [yc]. type == EMPTY && 
  438.                      field [xc] [yc+1]. type == EMPTY &&
  439.                      field [xc+1] [yc+1]. type == EMPTY);
  440.     }
  441.     /* NOTREACHED */
  442. }
  443.  
  444. solved ()
  445. {
  446.     fill (11, 4, 26, 16, CLEAR);
  447.     fill (15, 10, 18, 5, ACCENT);
  448.     fill (17, 11, 14, 3, DRAW);
  449.     pline (12, 19, "SOLVED !!!");
  450.     leave ();
  451. }
  452.  
  453. xputc (c)
  454. char    c;
  455. {
  456.     putchar (c);
  457. }
  458.  
  459. solution ()
  460. {
  461.     struct    passwd    *pw, *getpwuid();
  462.     short    i, kind;
  463.     char    *crypt ();
  464.  
  465.     if ((pw = getpwuid (UID)) == (struct passwd *) 0) {
  466.         pline (22, 20, "Sorry....       ");
  467.         home ();
  468.         return;
  469.     }
  470.     cursor (22, 20);
  471.     printf ("Password:   ");
  472.     flush ();
  473.     if (strcmp (crypt (getpass(""), pw->pw_passwd), pw->pw_passwd)) {
  474.         pline (22, 20, "Sorry....       ");
  475.         home ();
  476.         return;
  477.     }
  478.     new ();
  479.     pline (22, 20, "Moves : %04d         ", moves);
  480.     for (i = 0; sol [i]. nx; i++) {
  481.         kind = field [sol [i]. nx] [sol [i]. ny]. type;
  482.         change (CLEAR, sol [i]. nx, sol [i]. ny, kind);
  483.         change (DRAW, (x = sol [i]. ox), (y = sol [i]. oy), kind);
  484.         pline (22, 28, "%04d", ++moves);
  485.         home ();
  486.     }
  487.     solved ();
  488. }
  489.  
  490. takeback ()
  491. {
  492.     int    count;
  493.     short    i, kind;
  494.     char    buffer [BUFSIZ];
  495.  
  496.     pline (22, 15, "How many moves ? ");
  497.     stty (1, &save);
  498.     gets (buffer);
  499.     count = atoi (buffer);
  500.     stty (1, &sg);
  501.     if (moves - count < 0) {
  502.         pline (22, 15, "     Sorry         ");
  503.         home ();
  504.         return;
  505.     }
  506.     pline (22, 15, "                   ");
  507.     for (i = 0; i < count; i++) {
  508.         kind = field [tb [moves]. nx] [tb [moves]. ny]. type;
  509.         change (DRAW, x, y, field [x] [y]. type);
  510.         change (CLEAR, tb [moves]. nx, tb [moves]. ny, kind);
  511.         change (ACCENT, (x = tb [moves]. ox), (y = tb [moves]. oy), kind);
  512.         pline (22, 20, "Moves : %04d", --moves);
  513.         home ();
  514.     }
  515. }
  516.  
  517. new ()
  518. {
  519.     fill (11, 4, 26, 16, CLEAR);
  520.     initfield ();
  521. }
  522.