Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*******************************************************************************
  2.  
  3.     MenuetOS MineSweeper
  4.     Copyright (C) 2003  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. ? pragma option meos
  25. ? jumptomain NONE
  26. ? include "msys.h--"   // MenuetOS system functions - ñèñòåìíûå ôóíêöèè MenuetOS
  27.  
  28. ? print "\nÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"
  29. ? print "\n³          MeOS MineSweeper v0.3          ³"
  30. ? print "\n³ (C) Ivan Poddubny (ivan-yar@bk.ru) 2003 ³"
  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
  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. inline void fastcall mouse_disable()
  92. {
  93.   $mov eax,40
  94.   $mov ebx,000111b
  95.   $int 0x40
  96. }
  97.  
  98. ? include "timer.h--"  // timer functions
  99. ? include "draw.h--"   // drawing functions
  100. ? include "access.h--" // get & set functions
  101. ? include "random.h--" // random number generator
  102. //? include "uf.h--"     // user field window
  103.  
  104. void init()
  105. // Èíèöèàëèçàöè
  106. {
  107.   XST = 10; YST = 52;      // FIELD POSITION IN WINDOW
  108.  
  109.   ECX = mode;
  110.   IF (ECX != 0)
  111.   {
  112.     //ncx = stdmodes[ECX-1].x_size;
  113.     //ncy = stdmodes[ECX-1].y_size;
  114.     //cmines = initmines = stdmodes[ECX-1].nmines;
  115.  
  116.     EBX = #stdmodes;
  117.     ECX--; ECX *= 3;
  118.     EBX += ECX;
  119.  
  120.     ncx = DSBYTE[EBX]; EBX++;
  121.     ncy = DSBYTE[EBX]; EBX++;
  122.     cmines = initmines = DSBYTE[EBX];
  123.   }
  124.  
  125.   xsize = ncx * XPX + XST + XST;
  126.   ysize = ncy * YPX + YST + XST;
  127. } // init
  128.  
  129. void clear_all()
  130. // Î÷èñòèòü ïîëå
  131. {
  132.   EAX = 0;
  133.   EDI = #massiv;
  134.   ECX = ncx * ncy;
  135.   $REP $STOSD
  136. } // clear_all
  137.  
  138. void new_game()
  139. // Íîâàÿ èãðà
  140. {
  141.   init();            // èíèöèàëèçàöè
  142.   randomize();       // ãåíåðàòîð ñëó÷àéíûõ ÷èñåë
  143.   clear_all();       // î÷èñòèòü ïîëå
  144.  
  145.   firstmine = TRUE;  // èãðà íå íà÷àòà
  146.   mouse_en = TRUE;   // ìûøü ðàçðåøåíà
  147.   stop_game = FALSE; // èãðà íå çàêîí÷åíà
  148.   stop_timer();
  149.   time = 0;          // âðåìÿ = 0
  150. } // new_game
  151.  
  152. void set_mines(int nminas, no_x, no_y)
  153. // Ðàññòàâèòü ìèíû
  154. {
  155.   int i, x, y, a, b;
  156.  
  157.   sqclosed = ncx * ncy - nminas;  // êîëè÷åñòâî ÍÅîòêðûòûõ êëåòîê = ïëîùàäü ïîëÿ - êîë-âî ìèí
  158.  
  159.   FOR (i = nminas; i > 0; i--)    // ðàññòàâèòü ìèíû
  160.   {
  161.     x = random(ncx); y = random(ncy);
  162.     WHILE ((get_value(x, y) == MINE) || ((x == no_x) && (y == no_y)))
  163.     {
  164.       x = random(ncx);
  165.       y = random(ncy);
  166.     }
  167.     set_value(x, y, MINE);
  168.   }
  169.  
  170.   for (x = ncx-1; x >= 0; x--)    // ðàññòàâèòü öèôðû
  171.   {
  172.     for (y = ncy-1; y >= 0; y--)
  173.     {
  174.       IF (get_value(x, y) == MINE)
  175.         continue;
  176.       EDX = x * ncy + y*4 + #massiv;
  177.       a = x; b = y;
  178.       FOR (i = 0; i < 8; i++)
  179.       {
  180.          AL = matrix[i].a_inc;
  181.          $movsx eax,al
  182.          a += EAX;
  183.          AL = matrix[i].b_inc;
  184.          $movsx eax,al
  185.          b += EAX;
  186.          IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_value(a, b) == MINE))
  187.            DSBYTE[EDX]++;
  188.       }
  189.     }
  190.   }
  191. }  // set_mines
  192.  
  193. inline void do_mouse(void)
  194. // Îáðàáîò÷èê ìûøè
  195. {
  196.   int x,y;
  197.  
  198.   EAX = sys_read_mouse(2);            // ìûøü íå íàæàòà -> âûõîä
  199.   IF (EAX == 0) return;
  200.  
  201.   mouse_status = AL;
  202.  
  203.   EAX = sys_read_mouse(1);            // ìûøü âíå ïîëÿ  -> âûõîä
  204.   EBX = EAX; EAX >>= 16; EBX &= 0xffff;
  205.   ECX = ncx * XPX + XST - 1;
  206.   EDX = ncy * YPX + YST - 1;
  207.   IF ((EAX < XST) || (EBX < YST) || (EAX > ECX) || (EBX > EDX)) return;
  208.  
  209.   EAX -= XST; EAX /= XPX; x = EAX;    // âû÷èñëèòü x è y
  210.   EBX -= YST; EBX /= YPX; y = EBX;
  211.  
  212.   IF ((mouse_status == 1) && (!get_open(x, y)) && (get_mark(x, y) != 1))
  213.   {
  214.     // íà íåîòêðûòîé êëåòêå áåç ôëàæêà íàæàòà ëåâàÿ êíîïêà ìûøè
  215.     // left mouse button is pressed
  216.     IF (firstmine == TRUE)
  217.     {
  218.       firstmine = FALSE;
  219.       set_mines(cmines, x, y);
  220.       start_timer();
  221.     }
  222.     IF (get_value(x, y) == MINE)
  223.     {
  224.       end_game();
  225.       return;
  226.     }
  227.     open_square(x, y);
  228.   }
  229.   else IF ((mouse_status == 2) && (!get_open(x, y)))
  230.   {
  231.     // íà íåîòêðûòîé êëåòêå íàæàòà ïðàâàÿ êíîïêà ìûøè
  232.     // right mouse button is pressed
  233.     EBX = get_mark(x, y); EBX++;
  234.     EBX = EBX%3;
  235.     SWITCH (EBX)
  236.     {
  237.       CASE 2: cmines++; BREAK;
  238.       CASE 1: cmines--;
  239.     }
  240.  
  241.     set_mark(x, y, EBX);
  242.  
  243.     draw_minesi();
  244.     draw_square(x, y);
  245.     return;
  246.   }
  247.   ELSE IF ((mouse_status == 3) && (get_open(x, y)))
  248.   {
  249.     // íà îòêðûòîé êëåòêå íàæàòû îáå êíîïêè ìûøè
  250.     // both mouse buttons are pressed
  251.     IF (open_near_squares(x, y) == TRUE)
  252.       end_game();
  253.   }
  254.  
  255.   if (sqclosed == 0)
  256.   // îòêðûòû âñå êëåòêè
  257.   // all squares are opened
  258.   {
  259.     mouse_en   = FALSE;  // çàïðåòèòü ìûøü
  260.     stop_timer();
  261.     stop_game  = TRUE;   // èãðà çàâåðøåíà
  262.  
  263.     // ïîñòàâèòü íåðàññòàâëåííûå ìèíû
  264.     FOR (x = 0; x < ncx; x++)
  265.       FOR (y = 0; y < ncy; y++)
  266.         IF ((get_value(x, y) == MINE) && (get_mark(x, y) != 1))
  267.         {
  268.           set_mark(x, y, 1);
  269.           cmines--;
  270.           draw_square(x, y);
  271.         }
  272.     draw_minesi();
  273.   }
  274. }  // do_mouse
  275.  
  276. void open_square(int x, y)
  277. // Îòêðûòü êëåòêó
  278. {
  279.   int a, b, i;
  280.  
  281.   set_open(x, y, TRUE);
  282.   sqclosed--;
  283.  
  284.   IF (get_value(x, y) != 0)
  285.   {
  286.     draw_square(x, y);
  287.   }
  288.   else
  289.   {
  290.     draw_square(x, y);
  291.     a = x; b = y;
  292.     FOR (i = 0; i < 8; i++)
  293.     {
  294.       //a += matrix[i].a_inc;
  295.       //b += matrix[i].b_inc;
  296.       AL = matrix[i].a_inc;
  297.       $movsx eax,al
  298.       a += EAX;
  299.       AL = matrix[i].b_inc;
  300.       $movsx eax,al
  301.       b += EAX;
  302.       IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1))
  303.         open_square(a, b);
  304.     }
  305.   }
  306. }  // open_square
  307.  
  308. int open_near_squares(int x, y)
  309. // Îòêðûòü áëèçëåæàùèå êëåòêè (îáå êíîïêè ìûøè âìåñòå)
  310. {
  311.   int a, b, i;
  312.   dword suma = 0;
  313.  
  314.   a = x;
  315.   b = y;
  316.   FOR (i = 0; i < 8; i++)
  317.   {
  318.     //a+=matrix[i].a_inc;
  319.     //b+=matrix[i].b_inc;
  320.     AL = matrix[i].a_inc;
  321.     $movsx eax,al
  322.     a += EAX;
  323.     AL = matrix[i].b_inc;
  324.     $movsx eax,al
  325.     b += EAX;
  326.     IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_mark(a, b) == 1))
  327.       suma++;
  328.   }
  329.  
  330.   if (suma == get_value(x, y))
  331.   {
  332.     suma = 0;
  333.     a = x;
  334.     b = y;
  335.     for (i = 0; i < 8; i++)
  336.     {
  337.       //a+=matrix[i].a_inc;
  338.       //b+=matrix[i].b_inc;
  339.       AL = matrix[i].a_inc;
  340.       $movsx eax,al
  341.       a += EAX;
  342.       AL = matrix[i].b_inc;
  343.       $movsx eax,al
  344.       b += EAX;
  345.       IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1))
  346.       {
  347.         IF (get_value(a, b) == MINE)
  348.           suma = 1;
  349.         open_square(a, b);
  350.       }
  351.     }
  352.     RETURN suma;
  353.   }
  354.   ELSE
  355.     RETURN 0;
  356. }  // open_near_squares
  357.  
  358. void end_game()
  359. {
  360.   int x,y;
  361.  
  362.   stop_game = TRUE;
  363.   stop_timer();
  364.   for (x=0; x<ncx; x++)
  365.   {
  366.     for (y=0; y<ncy; y++)
  367.     {
  368.       IF (get_value(x, y) == MINE)
  369.       {
  370.         set_mark(x, y, FALSE); // ñíÿòü ôëàã
  371.         open_square(x, y);
  372.       }
  373.       ELSE IF (get_mark(x, y) == 1)      // åñëè ìèíû íåò, à ôëàæîê åñòü
  374.       {
  375.         EBX = XPX * x + XST;      // x left
  376.         ECX = EBX + XPX - 1;      // x right
  377.         EBX <<= 16; EBX += ECX;
  378.         $PUSH EBX
  379.  
  380.         ECX = YPX * y + YST;      // y top
  381.         $PUSH ECX
  382.         EDX = ECX + YPX - 1;      // y bottom
  383.         ECX <<= 16; ECX += EDX;
  384.         sys_draw_line(EBX, ECX, clBlack);
  385.  
  386.         $POP EDX
  387.         ECX = EDX + YPX - 1;
  388.         ECX <<= 16; ECX += EDX;
  389.         $POP EBX
  390.         sys_draw_line(EBX, ECX, clBlack);
  391.         CONTINUE;
  392.       }
  393.     }
  394.   }
  395. }  // end_game
  396.  
  397.  
  398. void main()
  399. {
  400.   sys_delay(5);   // for old kernel only!
  401.   new_game();
  402.   draw_window();
  403.  
  404.   mouse_enable();
  405.   while()
  406.   {
  407.     switch (sys_wait_event_timeout(100))  // wait for 1 second
  408.     {
  409.       CASE evReDraw:
  410.         draw_window();
  411.         continue;
  412.  
  413.       CASE evKey:
  414.         IF (sys_get_key() == 27)
  415.           sys_exit_process();
  416.         continue;
  417.  
  418.       CASE evButton:
  419.         EAX = sys_get_button_id();
  420.         IF (EAX == 911)              // new game
  421.         {
  422.           new_game();
  423.           draw_squares();
  424.           draw_time();
  425.           draw_minesi();
  426.         }
  427.         ELSE IF (EAX == 1001)        // change mode
  428.         {
  429.           // mode++; mode%=3; mode++;
  430.           EAX = mode; EAX++; EAX = EAX%3; EAX++; mode = AL;
  431.  
  432.           // get window position - ïîëó÷èòü êîîðäèíàòû îêíà
  433.           sys_process_info(#procinfo, -1);
  434.           xpos = procinfo.xstart;
  435.           ypos = procinfo.ystart;
  436.  
  437.           // start a new process and terminate this one
  438.           sys_create_thread(#main, ESP);
  439.           sys_exit_process();
  440.         }
  441.         //ELSE IF (EAX == 1002)
  442.         //{
  443.         //  start_uf();
  444.         //}
  445.         ELSE IF (EAX == 1)           // close window
  446.           sys_exit_process();
  447.         CONTINUE;
  448.  
  449.       case evMouse:
  450.         IF (!mouse_en) // is mouse enabled ?
  451.           CONTINUE;
  452.         do_mouse();
  453.         // wait for mouse release - æäàòü îòïóñêàíèÿ êíîïêè
  454.         WHILE (sys_read_mouse(2) == mouse_status)
  455.         {
  456.           check_timer();
  457.           sys_delay(6);
  458.           CONTINUE;
  459.         }
  460.         check_timer();
  461.         IF (stop_game)      // disable mouse if game is stopped
  462.           mouse_en = FALSE;
  463.         CONTINUE;
  464.     }
  465.     check_timer();
  466.     sys_delay(2);
  467.   }
  468. }  // main
  469.