Subversion Repositories Kolibri OS

Rev

Rev 6166 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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