Subversion Repositories Kolibri OS

Rev

Rev 109 | Rev 963 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*******************************************************************************
  2.  
  3.     MenuetOS MineSweeper
  4.     Copyright (C) 2003, 2004  Ivan Poddubny
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20. *******************************************************************************/
  21.  
  22. ? pragma option LST    // generate ASM listing file - ñîçäàòü àññåìáëåðíûé ëèñòèíã
  23. ? warning    TRUE      // âêëþ÷èòü ðåæèì âûâîäà ïðåäóïðåæäåíèé
  24. ? jumptomain NONE
  25. ? include "msys.h--"     // MenuetOS system functions - ñèñòåìíûå ôóíêöèè MenuetOS
  26. //? define DEBUG 1
  27.  
  28. ? print "\nÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"
  29. ? print "\n³          MenuetOS MineSweeper v0.4           ³"
  30. ? print "\n³ (C) Ivan Poddubny (ivan-yar@bk.ru) 2003,2004 ³"
  31. ? print "\nÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\n\n"
  32.  
  33. /************************************** DATA **************************************/
  34.  
  35. ? define XPX 16      // X pixels by square - ðàçìåð êëåòêè â ïèêñåëÿõ
  36. ? define YPX 16      // Y pixels by square
  37. ? define MINE 255    // â êëåòêå ìèíà, åñëè value = MINE
  38.  
  39. struct
  40. {
  41.   byte value;        // number of mines   - êîëè÷åñòâî ìèí â îêðóæàþùèõ êëåòêàõ
  42.   byte open;         // square is open    - êëåòêà îòêðûòà
  43.   byte press;        // reserved          - çàðåçåðâèðîâàíî
  44.   byte mark;         // square is marked  - êëåòêà ïîìå÷åíà
  45. } massiv[30*30];
  46.  
  47. struct
  48. {
  49.   byte a_inc;
  50.   byte b_inc;
  51. } matrix[8] = {-1,-1,1,0,1,0,0,1,-2,0,0,1,1,0,1,0};
  52.  
  53. struct
  54. {
  55.   byte   x_size;
  56.   byte   y_size;
  57.   byte   nmines;
  58. } stdmodes[3] = {9,9,10, 16,16,40, 30,16,99}; // {x,y,m}
  59.  
  60. int XST,             // offset of first pixel X - ñìåùåíèå ïîëÿ îò ãðàíèöû îêíà
  61.     YST,
  62.     ncx,             // number of squares in X  - ðàçìåð ïîëÿ
  63.     ncy,
  64.     cmines,          // mines discovered        - êîëè÷åñòâî íåîòêðûòûõ ìèí
  65.     initmines,       // number of initial mines - èçíà÷àëüíîå êîëè÷åñòâî ìèí
  66.     sqclosed;        // squares still closed    - êîëè÷åñòâî çàêðûòûõ êëåòîê
  67.  
  68. dword xpos = 100,    // window coordinates      - êîîðäèíàòû îêíà
  69.       ypos = 100,
  70.       xsize,         // window size
  71.       ysize;
  72.  
  73. byte stop_game = FALSE,   // game stopped - ïðèçíàê êîíöà èãðû
  74.      mouse_en = TRUE,     // mouse enabled   - ìûøü
  75.      mode = 3,            // ðåæèì èãðû 1-íîâè÷îê 2-ëþáèòåëü 3-ýêñïåðò (0 îñîáûé)
  76.      mouse_status,
  77.      firstmine;
  78.  
  79. ProcessInfo  procinfo;
  80. SystemColors colors;
  81.  
  82. /************************************** CODE **************************************/
  83.  
  84. inline void fastcall mouse_enable()
  85. {
  86.   $mov eax,40
  87.   $mov ebx,100111b
  88.   $int 0x40
  89. }
  90.  
  91.  
  92. inline void fastcall mouse_disable()
  93. {
  94.   $mov eax,40
  95.   $mov ebx,000111b
  96.   $int 0x40
  97. }
  98.  
  99.  
  100. ? include "timer.h--"  // timer functions
  101. ? include "draw.h--"   // drawing functions
  102. ? include "access.h--" // get & set functions
  103. ? include "random.h--" // random number generator
  104. //? include "uf.h--"     // user field window
  105.  
  106.  
  107. void init()
  108. // Èíèöèàëèçàöèÿ
  109. {
  110.   XST = 10; YST = 52;      // FIELD POSITION IN WINDOW
  111.  
  112.   ECX = mode;
  113.   IF (ECX != 0)
  114.   {
  115.     //ncx = stdmodes[ECX-1].x_size;
  116.     //ncy = stdmodes[ECX-1].y_size;
  117.     //cmines = initmines = stdmodes[ECX-1].nmines;
  118.  
  119.     EBX = #stdmodes;
  120.     ECX--; ECX *= 3;
  121.     EBX += ECX;
  122.  
  123.     ncx = DSBYTE[EBX]; EBX++;
  124.     ncy = DSBYTE[EBX]; EBX++;
  125.     cmines = initmines = DSBYTE[EBX];
  126.   }
  127.  
  128.   xsize = ncx * XPX + XST + XST;
  129.   ysize = ncy * YPX + YST + XST;
  130. } // init
  131.  
  132.  
  133. void clear_all()
  134. // Î÷èñòèòü ïîëå
  135. {
  136.   EAX = 0;
  137.   EDI = #massiv;
  138.   ECX = ncx * ncy;
  139.   $REP $STOSD
  140. } // clear_all
  141.  
  142.  
  143. void new_game()
  144. // Íîâàÿ èãðà
  145. {
  146.   init();            // èíèöèàëèçàöèÿ
  147.   randomize();       // ãåíåðàòîð ñëó÷àéíûõ ÷èñåë
  148.   clear_all();       // î÷èñòèòü ïîëå
  149.  
  150.   firstmine = TRUE;  // èãðà íå íà÷àòà
  151.   mouse_en = TRUE;   // ìûøü ðàçðåøåíà
  152.   stop_game = FALSE; // èãðà íå çàêîí÷åíà
  153.   stop_timer();
  154.   time = 0;          // âðåìÿ = 0
  155. } // new_game
  156.  
  157.  
  158. void set_mines(int nminas, no_x, no_y)
  159. // Ðàññòàâèòü ìèíû
  160. {
  161.   int i, x, y, a, b;
  162.  
  163.   #ifdef DEBUG
  164.   sys_debug_write_string("MINE: set_mines called\n");
  165.   #endif
  166.  
  167.   sqclosed = ncx * ncy - nminas;  // êîëè÷åñòâî ÍÅîòêðûòûõ êëåòîê = ïëîùàäü ïîëÿ - êîë-âî ìèí
  168.  
  169.   FOR (i = nminas; i > 0; i--)    // ðàññòàâèòü ìèíû
  170.   {
  171.     x = random(ncx);
  172.     y = random(ncy);
  173.     WHILE ((get_value(x, y) == MINE) || ((x == no_x) && (y == no_y)))
  174.     {
  175.       x = random(ncx);
  176.       y = random(ncy);
  177.     }
  178.     set_value(x, y, MINE);
  179.   }
  180.  
  181.   for (x = ncx-1; x >= 0; x--)    // ðàññòàâèòü öèôðû
  182.   {
  183.     for (y = ncy-1; y >= 0; y--)
  184.     {
  185.       IF (get_value(x, y) == MINE)
  186.         continue;
  187.       EDX = x * ncy + y*4 + #massiv;
  188.       a = x; b = y;
  189.       FOR (i = 0; i < 8; i++)
  190.       {
  191.          AL = matrix[i].a_inc;
  192.          $movsx eax,al
  193.          a += EAX;
  194.          AL = matrix[i].b_inc;
  195.          $movsx eax,al
  196.          b += EAX;
  197.          IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_value(a, b) == MINE))
  198.            DSBYTE[EDX]++;
  199.       }
  200.     }
  201.   }
  202. }  // set_mines
  203.  
  204.  
  205. inline void do_mouse(void)
  206. // Îáðàáîò÷èê ìûøè
  207. {
  208.   int x,y;
  209.  
  210.   EAX = sys_read_mouse(2);            // ìûøü íå íàæàòà -> âûõîä
  211.   IF (EAX == 0)
  212.   {
  213. //    sys_debug_write_string("Strange\n");
  214.     return;
  215.   }
  216.  
  217.   mouse_status = AL;
  218.  
  219.   EAX = sys_read_mouse(1);            // ìûøü âíå ïîëÿ  -> âûõîä
  220.   EBX = EAX; EAX >>= 16; EBX &= 0xffff;
  221.   ECX = ncx * XPX + XST - 1;
  222.   EDX = ncy * YPX + YST - 1;
  223.   IF ((EAX < XST) || (EBX < YST) || (EAX > ECX) || (EBX > EDX)) return;
  224.  
  225.   EAX -= XST; EAX /= XPX; x = EAX;    // âû÷èñëèòü x è y
  226.   EBX -= YST; EBX /= YPX; y = EBX;
  227.  
  228.   IF ((mouse_status == 1) && (!get_open(x, y)) && (get_mark(x, y) != 1))
  229.   {
  230.     // íà íåîòêðûòîé êëåòêå áåç ôëàæêà íàæàòà ëåâàÿ êíîïêà ìûøè
  231.     // left mouse button is pressed
  232.     IF (firstmine == TRUE)
  233.     {
  234.       firstmine = FALSE;
  235.       set_mines(initmines, x, y);
  236.       start_timer();
  237.       time = 1;
  238.       draw_time();
  239.     }
  240.     IF (get_value(x, y) == MINE)
  241.     {
  242.       end_game();
  243.       return;
  244.     }
  245.     open_square(x, y);
  246.   }
  247.   else IF ((mouse_status == 2) && (!get_open(x, y)))
  248.   {
  249.     // íà íåîòêðûòîé êëåòêå íàæàòà ïðàâàÿ êíîïêà ìûøè
  250.     // right mouse button is pressed
  251.     EBX = get_mark(x, y); EBX++;
  252.     EBX = EBX%3;
  253.     SWITCH (EBX)
  254.     {
  255.       CASE 2: cmines++; BREAK;
  256.       CASE 1: cmines--;
  257.     }
  258.  
  259.     set_mark(x, y, EBX);
  260.  
  261.     draw_minesi();
  262.     draw_square(x, y);
  263.     return;
  264.   }
  265.   ELSE IF ((mouse_status == 3) && (get_open(x, y)))
  266.   {
  267.     // íà îòêðûòîé êëåòêå íàæàòû îáå êíîïêè ìûøè
  268.     // both mouse buttons are pressed
  269.     IF (open_near_squares(x, y) == TRUE)
  270.       end_game();
  271.   }
  272.  
  273.   IF (sqclosed == 0)
  274.   {
  275.     // îòêðûòû âñå êëåòêè
  276.     // all squares are opened
  277.     mouse_en   = FALSE;  // çàïðåòèòü ìûøü
  278.     stop_timer();
  279.     stop_game  = TRUE;   // èãðà çàâåðøåíà
  280.  
  281.     // ïîñòàâèòü íåðàññòàâëåííûå ìèíû
  282.     FOR (x = 0; x < ncx; x++)
  283.       FOR (y = 0; y < ncy; y++)
  284.         IF ((get_value(x, y) == MINE) && (get_mark(x, y) != 1))
  285.         {
  286.           set_mark(x, y, 1);
  287.           cmines--;
  288.           draw_square(x, y);
  289.         }
  290.     draw_minesi();
  291.   }
  292. }  // do_mouse
  293.  
  294.  
  295. void open_square(int x, y)
  296. // Îòêðûòü êëåòêó
  297. {
  298.   int a, b, i;
  299.  
  300.   #ifdef DEBUG
  301.   sys_debug_write_string("MINE: open_square called\n");
  302.   #endif
  303.  
  304.   set_open(x, y, TRUE);
  305.   sqclosed--;
  306.  
  307.   IF (get_value(x, y) != 0)
  308.   {
  309.     draw_square(x, y);
  310.   }
  311.   else
  312.   {
  313.     draw_square(x, y);
  314.     a = x; b = y;
  315.     FOR (i = 0; i < 8; i++)
  316.     {
  317.       //a += matrix[i].a_inc;
  318.       //b += matrix[i].b_inc;
  319.       AL = matrix[i].a_inc;
  320.       $movsx eax,al
  321.       a += EAX;
  322.       AL = matrix[i].b_inc;
  323.       $movsx eax,al
  324.       b += EAX;
  325.       IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1))
  326.         open_square(a, b);
  327.     }
  328.   }
  329. }  // open_square
  330.  
  331.  
  332. int open_near_squares(int x, y)
  333. // Îòêðûòü áëèçëåæàùèå êëåòêè (îáå êíîïêè ìûøè âìåñòå)
  334. {
  335.   int a, b, i;
  336.   dword suma = 0;
  337.  
  338.   #ifdef DEBUG
  339.   sys_debug_write_string("MINE: open_near_squares called\n");
  340.   #endif
  341.  
  342.   a = x;
  343.   b = y;
  344.   FOR (i = 0; i < 8; i++)
  345.   {
  346.     //a+=matrix[i].a_inc;
  347.     //b+=matrix[i].b_inc;
  348.     AL = matrix[i].a_inc;
  349.     $movsx eax,al
  350.     a += EAX;
  351.     AL = matrix[i].b_inc;
  352.     $movsx eax,al
  353.     b += EAX;
  354.     IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_mark(a, b) == 1))
  355.       suma++;
  356.   }
  357.  
  358.   if (suma == get_value(x, y))
  359.   {
  360.     suma = 0;
  361.     a = x;
  362.     b = y;
  363.     for (i = 0; i < 8; i++)
  364.     {
  365.       //a+=matrix[i].a_inc;
  366.       //b+=matrix[i].b_inc;
  367.       AL = matrix[i].a_inc;
  368.       $movsx eax,al
  369.       a += EAX;
  370.       AL = matrix[i].b_inc;
  371.       $movsx eax,al
  372.       b += EAX;
  373.       IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1))
  374.       {
  375.         IF (get_value(a, b) == MINE)
  376.           suma = 1;
  377.         open_square(a, b);
  378.       }
  379.     }
  380.     return suma;
  381.   }
  382.   ELSE
  383.     return 0;
  384. }  // open_near_squares
  385.  
  386.  
  387. void end_game()
  388. {
  389.   int x,y;
  390.  
  391.   #ifdef DEBUG
  392.   sys_debug_write_string("MINE: end_game called\n");
  393.   #endif
  394.  
  395.   stop_game = TRUE;
  396.   stop_timer();
  397.   for (x=0; x<ncx; x++)
  398.   {
  399.     for (y=0; y<ncy; y++)
  400.     {
  401.       IF (get_value(x, y) == MINE)
  402.       {
  403.         set_mark(x, y, FALSE); // ñíÿòü ôëàã
  404.         open_square(x, y);
  405.       }
  406.       ELSE IF (get_mark(x, y) == 1)      // åñëè ìèíû íåò, à ôëàæîê åñòü
  407.       {
  408.         EBX = XPX * x + XST;      // x left
  409.         ECX = EBX + XPX - 1;      // x right
  410.         EBX <<= 16; EBX += ECX;
  411.         $PUSH EBX
  412.  
  413.         ECX = YPX * y + YST;      // y top
  414.         $PUSH ECX
  415.         EDX = ECX + YPX - 1;      // y bottom
  416.         ECX <<= 16; ECX += EDX;
  417.         sys_draw_line(EBX, ECX, clBlack);
  418.  
  419.         $POP EDX
  420.         ECX = EDX + YPX - 1;
  421.         ECX <<= 16; ECX += EDX;
  422.         $POP EBX
  423.         sys_draw_line(EBX, ECX, clBlack);
  424.         CONTINUE;
  425.       }
  426.     }
  427.   }
  428. }  // end_game
  429.  
  430.  
  431. void main()
  432. {
  433.   //sys_delay(5);   // for old kernel only!
  434.   new_game();
  435.   draw_window();
  436.  
  437.   mouse_enable();
  438.   while()
  439.   {
  440.     switch (sys_wait_event_timeout(100))  // wait for 1 second
  441.     {
  442.       case evReDraw:
  443.         draw_window();
  444.         continue;
  445.  
  446.       case evKey:
  447.         IF (sys_get_key() == 27)
  448.           sys_exit_process();
  449.         continue;
  450.  
  451.       case evButton:
  452.         EAX = sys_get_button_id();
  453.         IF (EAX == 911)              // new game
  454.         {
  455.           new_game();
  456.           draw_squares();
  457.           draw_time();
  458.           draw_minesi();
  459.         }
  460.         ELSE IF (EAX == 1001)        // change mode
  461.         {
  462.           // mode++; mode%=3; mode++;
  463.           EAX = mode; EAX++; EAX = EAX%3; EAX++; mode = AL;
  464.  
  465.           new_game();
  466.           EBX = ECX = -1;
  467.           EDX = xsize;
  468.           ESI = ysize;
  469.           EAX = 67;
  470.           $int 0x40
  471.           continue;
  472.         }
  473. //        ELSE IF (EAX == 1002)
  474. //        {
  475. //          start_uf();
  476. //        }
  477.         ELSE IF (EAX == 1)           // close window
  478.           sys_exit_process();
  479.         continue;
  480.  
  481.       case evMouse:
  482.         IF (!mouse_en) // is mouse enabled ?
  483.           continue;
  484.         do_mouse();
  485.         // wait for mouse release - æäàòü îòïóñêàíèÿ êíîïêè
  486.         WHILE (sys_read_mouse(2) == mouse_status)
  487.         {
  488.           check_timer();
  489.           sys_delay(3);
  490.           CONTINUE;
  491.         }
  492.         check_timer();
  493.         IF (stop_game)      // disable mouse if game is stopped
  494.           mouse_en = FALSE;
  495.         CONTINUE;
  496.     }
  497.     check_timer();
  498.     sys_delay(2);
  499.   }
  500. }  // main