home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume15 / xdemineur / part01 / main.c next >
C/C++ Source or Header  |  1993-01-27  |  18KB  |  484 lines

  1. /* ********************************************************************** */
  2. /*                                                                        */
  3. /* xdemineur - Jeu de reflexion sous X, version 1.0                       */
  4. /*                                                                        */
  5. /* Copyright : Marc Baudoin (baudoin@ensta.fr)                            */
  6. /*                                                                        */
  7. /*            |\                                                          */
  8. /*          |\| \                                                         */
  9. /*          |//  )                                                        */
  10. /*        |\ /  /        /\/\_                                            */
  11. /*        |//  /        /. . /                                            */
  12. /*      |\ /  /     ___/    |_                                            */
  13. /*      |//  /     (____/    /_/\_                                        */
  14. /*       |__|      (_____/ __     >                                       */
  15. /*     /| ___  ________ _< \ \__  >                                       */
  16. /*     \|| __\| _|_   _/ \\ \___\/                                        */
  17. /*       | __\____ | |/ _ \\    >                                         */
  18. /*     /||___\_____|___/ \_\\  _>                                         */
  19. /*     \|____           ____ \|                                           */
  20. /*       \   \_________/   /                                              */
  21. /*        \   _    _      /                                               */
  22. /*         \_//   //_____/                                                */
  23. /*           (_   \ (_  _\                                                */
  24. /*             |/\|   \/                                                  */
  25. /*                                                                        */
  26. /* Ecole Nationale Superieure de Techniques Avancees (ENSTA)              */
  27. /* 32, boulevard Victor - 75015 Paris - France                            */
  28. /*                                                                        */
  29. /* Vous avez le droit d'utiliser et de distribuer xdemineur et sa         */
  30. /* documentation pourvu que cette notice de copyright apparaisse sur      */
  31. /* toutes les copies et que vous ne tiriez aucun profit de mon programme. */
  32. /*                                                                        */
  33. /* ********************************************************************** */
  34.  
  35.  
  36.  
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <sys/time.h>
  40. #include <X11/Xlib.h>
  41. #include <X11/Xutil.h>
  42.  
  43. #include "demineur.h"
  44. #include "xdemineur.h"
  45.  
  46. #include "bitmaps/xdemineur.bm"
  47.  
  48. extern struct jeu    **tableau ;
  49. extern int             nb_lig , nb_col , nb_mines ;
  50. extern time_t          temps ;
  51. extern BOOLEAN         perdu , gagne , jeu , ouvre ;
  52.  
  53. Display   *display ;
  54. int        screen ;
  55. Window     window ;
  56. GC         gc ;
  57.  
  58. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Programme principal ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  59.  
  60. main ( argc , argv )
  61. int   argc ;
  62. char *argv [ ] ;
  63. {
  64.    int             i ;
  65.    char           *display_name = NULL ;
  66.    Bool            option_m = False ;
  67.  
  68.    char           *window_title = "Demineur" , *icon_title = "Demineur" ;
  69.    XTextProperty   window_name , icon_name ;
  70.    Pixmap          icon_bitmap ;
  71.    XSizeHints      size_hints ;
  72.    XWMHints        wm_hints ;
  73.    XClassHint      class_hint ;
  74.    Atom            protocol [ 1 ] ;
  75.  
  76.    time_t          ref , courant , ancien ;
  77.  
  78.    XEvent          event ;
  79.    int             lig , col , l , c , bouton = 0 ;
  80.    enum { CASE , DOUBLE_CLIC , ICONE , RIEN } quoi ;
  81.    Bool            focus = False ;
  82.    Region          region ;
  83.    XRectangle      rectangle ;
  84.  
  85.    nb_mines = NB_MINES ;
  86.  
  87.    /* arguments de la ligne de commande */
  88.  
  89.    for ( i = 1 ; i < argc ; i ++ )
  90.    {
  91.       if ( strcmp ( argv [ i ] , "-display" ) == 0 )
  92.       {
  93.          display_name = argv [ ++ i ] ;
  94.       }
  95.       else if ( strcmp ( argv [ i ] , "-l" ) == 0 )
  96.       {
  97.          nb_lig = atoi ( argv [ ++ i ] ) ;
  98.          if ( nb_lig < 5 )
  99.          {
  100.             nb_lig = 5 ;
  101.          }
  102.          if ( ! option_m )
  103.          {
  104.             nb_mines = NB_MINES ;
  105.          }
  106.       }
  107.       else if ( strcmp ( argv [ i ] , "-c" ) == 0 )
  108.       {
  109.          nb_col = atoi ( argv [ ++ i ] ) ;
  110.          if ( nb_col < 10 )
  111.          {
  112.             nb_col = 10 ;
  113.          }
  114.          if ( ! option_m )
  115.          {
  116.             nb_mines = NB_MINES ;
  117.          }
  118.       }
  119.       else if ( strcmp ( argv [ i ] , "-m" ) == 0 )
  120.       {
  121.          option_m = True ;
  122.          nb_mines = atoi ( argv [ ++ i ] ) ;
  123.          if ( nb_mines >= nb_lig * nb_col )
  124.          {
  125.             nb_mines = NB_MINES ;
  126.          }
  127.       }
  128.       else if ( strcmp ( argv [ i ] , "-ouvre" ) == 0 )
  129.       {
  130.          ouvre = TRUE ;
  131.       }
  132.       else
  133.       {
  134.          fprintf ( stderr ,
  135. "Usage: xdemineur [-display display] [-l lignes] [-c colonnes] [-m mines]\n" ) ;
  136.          fprintf ( stderr ,
  137. "                 [-ouvre]\n" ) ;
  138.          exit ( 1 ) ;
  139.       }
  140.    }
  141.  
  142.    /* initialisation de X */
  143.  
  144.    if ( ( display = XOpenDisplay ( display_name ) ) == NULL )
  145.    {
  146.       fprintf ( stderr , "%s : impossible de se connecter au serveur X.\n" ,
  147.                          argv [ 0 ] ) ;
  148.       exit ( 1 ) ;
  149.    }
  150.  
  151.    screen = DefaultScreen ( display ) ;
  152.  
  153.    while ( HAUTEUR_FEN > DisplayHeight ( display , screen ) )
  154.    {
  155.       nb_lig -- ;
  156.       if ( ! option_m )
  157.       {
  158.          nb_mines = NB_MINES ;
  159.       }
  160.    }
  161.    while ( LARGEUR_FEN > DisplayWidth ( display , screen ) )
  162.    {
  163.       nb_col -- ;
  164.       if ( ! option_m )
  165.       {
  166.          nb_mines = NB_MINES ;
  167.       }
  168.    }
  169.  
  170.    window = XCreateSimpleWindow ( display , RootWindow ( display , screen ) ,
  171.                                   X_FEN , Y_FEN , LARGEUR_FEN , HAUTEUR_FEN , 2 ,
  172.                                   BlackPixel ( display , screen ) ,
  173.                                   WhitePixel ( display , screen ) ) ;
  174.    XSelectInput ( display , window , ButtonPressMask | ButtonReleaseMask |
  175.                                      FocusChangeMask | ExposureMask ) ;
  176.  
  177.    XStringListToTextProperty ( &window_title , 1 , &window_name ) ;
  178.    XStringListToTextProperty ( &icon_title   , 1 , &icon_name   ) ;
  179.  
  180.    icon_bitmap = XCreateBitmapFromData ( display , RootWindow ( display , screen ) ,
  181.                                          xdemineur_bits ,
  182.                                          xdemineur_width , xdemineur_height ) ;
  183.  
  184.    size_hints . flags         = USPosition | PSize | PMinSize | PMaxSize ;
  185.    size_hints . min_width     = size_hints . max_width  = LARGEUR_FEN ;
  186.    size_hints . min_height    = size_hints . max_height = HAUTEUR_FEN ;
  187.  
  188.    wm_hints   . flags         = InputHint | StateHint | IconPixmapHint ;
  189.    wm_hints   . input         = True ;
  190.    wm_hints   . initial_state = NormalState ;
  191.    wm_hints   . icon_pixmap   = icon_bitmap ;
  192.  
  193.    class_hint . res_name      = argv [ 0 ] ;
  194.    class_hint . res_class     = "XDemineur" ;
  195.  
  196.    XSetWMProperties ( display , window ,
  197.                       &window_name , &icon_name ,
  198.                       argv , argc ,
  199.                       &size_hints , &wm_hints , &class_hint ) ;
  200.  
  201.    protocol [ 0 ] = XInternAtom ( display , "WM_DELETE_WINDOW" , False ) ;
  202.    XSetWMProtocols ( display , window , protocol , 1 ) ;
  203.  
  204.    gc = XCreateGC ( display , window , 0 , NULL ) ;
  205.    XSetForeground ( display , gc , BlackPixel ( display , screen ) ) ;
  206.    XSetBackground ( display , gc , WhitePixel ( display , screen ) ) ;
  207.  
  208.    cree_pixmaps ( ) ;
  209.  
  210.    XMapWindow ( display , window ) ;
  211.  
  212.    /* initialisation du jeu */
  213.    
  214.    /* on rajoute deux rangees supplementaires pour ne pas avoir a s'occuper *
  215.     * des effets de bord lors du comptage du nombre de mines adjacentes     */
  216.  
  217.    tableau = ( struct jeu ** ) malloc ( ( nb_lig + 2 ) *
  218.                                         sizeof ( struct jeu * ) ) ;
  219.    for ( i = 0 ; i < nb_lig + 2 ; i ++ )
  220.    {
  221.       tableau [ i ] = ( struct jeu * ) malloc ( ( nb_col + 2 ) *
  222.                                                 sizeof ( struct jeu ) );
  223.    }
  224.  
  225.    remplis_et_compte ( ) ;
  226.  
  227.    /* le jeu */
  228.  
  229.    region = XCreateRegion ( ) ;
  230.    while ( True )
  231.    {
  232.       while ( XPending ( display ) )
  233.       {
  234.          XNextEvent ( display , &event ) ;
  235.          switch ( event . type )
  236.          {
  237.          case ButtonPress :
  238.             bouton ++ ;
  239.  
  240.             if ( event . xbutton . y >= Y_ICONE              &&
  241.                  event . xbutton . y <= Y_ICONE + HAUT_ICONE &&
  242.                  event . xbutton . x >= X_ICONE              &&
  243.                  event . xbutton . x <= X_ICONE + LARG_ICONE &&
  244.                  event . xbutton . button == Button1         &&
  245.                  bouton == 1 )   /* nouveau jeu */
  246.             {
  247.                quoi = ICONE ;
  248.                icone_activee ( ) ;
  249.             }
  250.             else if ( event . xbutton . x > X_JEU            &&
  251.                       event . xbutton . x < X_JEU + LARG_JEU &&
  252.                       event . xbutton . y > Y_JEU            &&
  253.                       event . xbutton . y < Y_JEU + HAUT_JEU &&
  254.                       ! perdu && ! gagne )
  255.             {
  256.                if ( ( event . xbutton . x - X_JEU ) % ( LARG_CASE + 1 ) == 0 ||
  257.                     ( event . xbutton . y - Y_JEU ) % ( HAUT_CASE + 1 ) == 0 )
  258.                {
  259.                   quoi = RIEN ;   /* on a clique sur une ligne donc on ne fait rien */
  260.                }
  261.                else
  262.                {
  263.                   icone_joue ( ) ;
  264.  
  265.                   lig = 1 + ( event . xbutton . y - Y_JEU ) / ( HAUT_CASE + 1 ) ;
  266.                   col = 1 + ( event . xbutton . x - X_JEU ) / ( LARG_CASE + 1 ) ;
  267.  
  268.                   if ( event . xbutton . button == Button1          &&
  269.                        tableau [ lig ] [ col ] . etat != DECOUVERTE &&
  270.                        tableau [ lig ] [ col ] . etat != MARQUEE    &&
  271.                        bouton == 1 )
  272.                   {
  273.                      quoi = CASE ;
  274.                      case_vide ( lig , col ) ;
  275.                   }
  276.                   else if ( tableau [ lig ] [ col ] . etat == DECOUVERTE &&
  277.                             bouton == 2 )
  278.                   {
  279.                      quoi = DOUBLE_CLIC ;
  280.                      cases_vides ( lig , col ) ;
  281.                   }
  282.                   else if ( event . xbutton . button == Button3          &&
  283.                             tableau [ lig ] [ col ] . etat != DECOUVERTE &&
  284.                             bouton == 1 )
  285.                   {
  286.                      quoi = CASE ;
  287.                      marque ( lig , col ) ;
  288.  
  289.                      if ( ! jeu && ! gagne && ! perdu )
  290.                      {
  291.                         jeu = TRUE ;
  292.                         ancien = ref = time ( 0 ) ;
  293.                      }
  294.                   }
  295.                   else
  296.                   {
  297.                      quoi = RIEN ;
  298.                   }
  299.                }
  300.             }
  301.             else
  302.             {
  303.                quoi = RIEN ;
  304.             }
  305.             break ;
  306.          case ButtonRelease :
  307.             bouton -- ;
  308.             if ( bouton != 0 )
  309.             {
  310.                break ;
  311.             }
  312.  
  313.             if ( event . xbutton . y >= Y_ICONE              &&
  314.                  event . xbutton . y <= Y_ICONE + HAUT_ICONE &&
  315.                  event . xbutton . x >= X_ICONE              &&
  316.                  event . xbutton . x <= X_ICONE + LARG_ICONE &&
  317.                  event . xbutton . button == Button1         &&
  318.                  quoi == ICONE )   /* nouveau jeu */
  319.             {
  320.                remplis_et_compte ( ) ;
  321.                affiche_jeu ( ) ;
  322.             }
  323.             else if ( quoi == ICONE )
  324.             {
  325.                icone_perdu_gagne ( ) ;
  326.             }
  327.             if ( ( event . xbutton . y < Y_JEU            ||
  328.                    event . xbutton . y > Y_JEU + HAUT_JEU ||
  329.                    event . xbutton . x < X_JEU            ||
  330.                    event . xbutton . x > X_JEU + LARG_JEU ) &&
  331.                  quoi == CASE )
  332.             {
  333.                affiche_case ( lig , col ) ;
  334.             }
  335.             else if ( event . xbutton . x > X_JEU            &&
  336.                       event . xbutton . x < X_JEU + LARG_JEU &&
  337.                       event . xbutton . y > Y_JEU            &&
  338.                       event . xbutton . y < Y_JEU + HAUT_JEU &&
  339.                       ! perdu && ! gagne                     &&
  340.                       event . xbutton . button == Button1    &&
  341.                       quoi == CASE )
  342.             {
  343.                if ( ( event . xbutton . y - Y_JEU ) % ( HAUT_CASE + 1 ) == 0 ||
  344.                     ( event . xbutton . x - X_JEU ) % ( LARG_CASE + 1 ) == 0 )
  345.                {
  346.                   affiche_case ( lig , col ) ;   /* on a clique sur une ligne donc on ne fait rien */
  347.                }
  348.                else
  349.                {
  350.                   l = 1 + ( event . xbutton . y - Y_JEU ) / ( HAUT_CASE + 1 ) ;
  351.                   c = 1 + ( event . xbutton . x - X_JEU ) / ( LARG_CASE + 1 ) ;
  352.  
  353.                   if ( tableau [ lig ] [ col ] . etat != DECOUVERTE &&
  354.                        tableau [ lig ] [ col ] . etat != MARQUEE    &&
  355.                        lig == l && col == c )
  356.                   {
  357.                      joue ( lig , col ) ;
  358.  
  359.                      if ( ! jeu && !gagne && ! perdu )
  360.                      {
  361.                         jeu = TRUE ;
  362.                         ancien = ref = time ( 0 ) ;
  363.                      }
  364.                   }
  365.                   else
  366.                   {
  367.                      affiche_case ( lig , col ) ;
  368.                   }
  369.                }
  370.             }
  371.             else if ( ( event . xbutton . y < Y_JEU            ||
  372.                         event . xbutton . y > Y_JEU + HAUT_JEU ||
  373.                         event . xbutton . x < X_JEU            ||
  374.                         event . xbutton . x > X_JEU + LARG_JEU ) &&
  375.                         quoi == DOUBLE_CLIC )
  376.             {
  377.                affiche_bloc ( lig , col ) ;
  378.             }
  379.             else if ( event . xbutton . x > X_JEU            &&
  380.                       event . xbutton . x < X_JEU + LARG_JEU &&
  381.                       event . xbutton . y > Y_JEU            &&
  382.                       event . xbutton . y < Y_JEU + HAUT_JEU &&
  383.                       ! perdu && ! gagne                     &&
  384.                       quoi == DOUBLE_CLIC )
  385.             {
  386.                if ( ( event . xbutton . y - Y_JEU ) % ( HAUT_CASE + 1 ) == 0 ||
  387.                     ( event . xbutton . x - X_JEU ) % ( LARG_CASE + 1 ) == 0 )
  388.                {
  389.                   affiche_bloc ( lig , col ) ;   /* on a clique sur une ligne donc on ne fait rien */
  390.                }
  391.                else
  392.                {
  393.                   l = 1 + ( event . xbutton . y - Y_JEU ) / ( HAUT_CASE + 1 ) ;
  394.                   c = 1 + ( event . xbutton . x - X_JEU ) / ( LARG_CASE + 1 ) ;
  395.  
  396.                   if ( tableau [ lig ] [ col ] . etat == DECOUVERTE &&
  397.                        tableau [ lig ] [ col ] . nombre ==
  398.                           nombre_de_drapeaux ( lig , col )          &&
  399.                        lig == l && col == c )
  400.                   {
  401.                      double_clic ( lig , col ) ;
  402.                   }
  403.                   else
  404.                   {
  405.                      affiche_bloc ( lig , col ) ;
  406.                   }
  407.                }
  408.             }
  409.             icone_perdu_gagne ( ) ;
  410.             break ;
  411.          case FocusIn :
  412.             focus = True ;
  413.             ref = time ( 0 ) - temps ;
  414.             break ;
  415.          case FocusOut :
  416.             focus = False ;
  417.             break ;
  418.          case Expose :
  419.             rectangle . x      = ( short )          event . xexpose . x ;
  420.             rectangle . y      = ( short )          event . xexpose . y ;
  421.             rectangle . width  = ( unsigned short ) event . xexpose . width ;
  422.             rectangle . height = ( unsigned short ) event . xexpose . height ;
  423.             XUnionRectWithRegion ( &rectangle , region , region ) ;
  424.             if ( event . xexpose . count == 0 )
  425.             {
  426.                XSetRegion ( display , gc , region ) ;
  427.                affiche_jeu ( ) ;
  428.                XSetClipMask ( display , gc , None ) ;
  429.                XDestroyRegion ( region ) ;
  430.                region = XCreateRegion ( ) ;
  431.             }
  432.             break ;
  433.          case ClientMessage :
  434.             if ( event . xclient . data . l [ 0 ] == protocol [ 0 ] )
  435.             {
  436.                for ( i = 0 ; i < nb_lig + 2 ; i ++ )
  437.                {
  438.                   free ( tableau [ i ] ) ;
  439.                }
  440.                free ( tableau ) ;
  441.                detruit_pixmaps ( ) ;
  442.                XDestroyWindow ( display , window ) ;
  443.                XCloseDisplay ( display ) ;
  444.                exit ( 0 ) ;
  445.             }
  446.             break ;
  447.          }
  448.       }
  449.       if ( jeu && focus )
  450.       {
  451.          courant = time ( 0 ) ;
  452.          if ( ancien != courant )
  453.          {
  454.             ancien = courant ;
  455.             temps = courant - ref ;
  456.             if ( temps > 999 )
  457.             {
  458.                temps %= 1000 ;
  459.             }
  460.             chronometre ( ) ;
  461.          }
  462.       }
  463.    }
  464. }
  465.  
  466. int nombre_de_drapeaux ( lig , col )
  467. int lig , col ;
  468. {
  469.    return ( drapeau01 ( lig - 1 , col - 1 ) +
  470.             drapeau01 ( lig - 1 , col     ) +
  471.             drapeau01 ( lig - 1 , col + 1 ) +
  472.             drapeau01 ( lig     , col - 1 ) +
  473.             drapeau01 ( lig     , col + 1 ) +
  474.             drapeau01 ( lig + 1 , col - 1 ) +
  475.             drapeau01 ( lig + 1 , col     ) +
  476.             drapeau01 ( lig + 1 , col + 1 ) ) ;
  477. }
  478.  
  479. int drapeau01 ( lig , col )
  480. int lig , col ;
  481. {
  482.    return ( ( tableau [ lig ] [ col ] . etat == MARQUEE ) ? 1 : 0 ) ;
  483. }
  484.