Subversion Repositories Kolibri OS

Rev

Rev 1771 | Rev 3979 | Go to most recent revision | 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. int XST,             // offset of first pixel X - ñìåùåíèå ïîëÿ îò ãðàíèöû îêíà
  62.     YST,
  63.     ncx,             // number of squares in X  - ðàçìåð ïîëÿ
  64.     ncy,
  65.     cmines,          // mines discovered        - êîëè÷åñòâî íåîòêðûòûõ ìèí
  66.     initmines,       // number of initial mines - èçíà÷àëüíîå êîëè÷åñòâî ìèí
  67.     sqclosed;        // squares still closed    - êîëè÷åñòâî çàêðûòûõ êëåòîê
  68.  
  69. dword xpos = 100,    // window coordinates      - êîîðäèíàòû îêíà
  70.       ypos = 100,
  71.       xsize,         // window size
  72.       ysize;
  73.  
  74. byte stop_game = FALSE,   // game stopped - ïðèçíàê êîíöà èãðû
  75.      mouse_en = TRUE,     // mouse enabled   - ìûøü
  76.      mode = 2,            // ðåæèì èãðû 1-íîâè÷îê 2-ëþáèòåëü 3-ýêñïåðò (0 îñîáûé)
  77.      mouse_status,
  78.      firstmine;
  79.  
  80. ProcessInfo  procinfo;
  81. SystemColors colors;
  82.  
  83. /************************************** CODE **************************************/
  84.  
  85. inline void fastcall mouse_enable()
  86. {
  87.   $mov eax,40
  88.   $mov ebx,100111b
  89.   $int 0x40
  90. }
  91.  
  92.  
  93. inline void fastcall mouse_disable()
  94. {
  95.   $mov eax,40
  96.   $mov ebx,000111b
  97.   $int 0x40
  98. }
  99.  
  100.  
  101. # include "timer.h--"  // timer functions
  102. # include "draw.h--"   // drawing functions
  103. # include "access.h--" // get & set functions
  104. # include "random.h--" // random number generator
  105. //? include "uf.h--"     // user field window
  106.  
  107.  
  108. void init()
  109. // Èíèöèàëèçàöèÿ
  110. {
  111.   XST = 10; YST = 52;      // FIELD POSITION IN WINDOW
  112.  
  113.   ECX = mode;
  114.   IF (ECX != 0)
  115.   {
  116.     //ncx = stdmodes[ECX-1].x_size;
  117.     //ncy = stdmodes[ECX-1].y_size;
  118.     //cmines = initmines = stdmodes[ECX-1].nmines;
  119.  
  120.     EBX = #stdmodes;
  121.     ECX--; ECX *= 3;
  122.     EBX += ECX;
  123.  
  124.     ncx = DSBYTE[EBX]; EBX++;
  125.     ncy = DSBYTE[EBX]; EBX++;
  126.     cmines = initmines = DSBYTE[EBX];
  127.   }
  128.  
  129.   xsize = ncx * XPX + XST + XST;
  130.   ysize = ncy * YPX + YST + XST;
  131. } // init
  132.  
  133.  
  134. void clear_all()
  135. // Î÷èñòèòü ïîëå
  136. {
  137.   EAX = 0;
  138.   EDI = #massiv;
  139.   ECX = ncx * ncy;
  140.   $REP $STOSD
  141. } // clear_all
  142.  
  143.  
  144. void new_game()
  145. // Íîâàÿ èãðà
  146. {
  147.   init();            // èíèöèàëèçàöèÿ
  148.   randomize();       // ãåíåðàòîð ñëó÷àéíûõ ÷èñåë
  149.   clear_all();       // î÷èñòèòü ïîëå
  150.  
  151.   firstmine = TRUE;  // èãðà íå íà÷àòà
  152.   mouse_en = TRUE;   // ìûøü ðàçðåøåíà
  153.   stop_game = FALSE; // èãðà íå çàêîí÷åíà
  154.   stop_timer();
  155.   time = 0;          // âðåìÿ = 0
  156. } // new_game
  157.  
  158.  
  159. void set_mines(int nminas, no_x, no_y)
  160. // Ðàññòàâèòü ìèíû
  161. {
  162.   int i, x, y, a, b;
  163.  
  164.   #ifdef DEBUG
  165.   sys_debug_write_string("MINE: set_mines called\n");
  166.   #endif
  167.  
  168.   sqclosed = ncx * ncy - nminas;  // êîëè÷åñòâî ÍÅîòêðûòûõ êëåòîê = ïëîùàäü ïîëÿ - êîë-âî ìèí
  169.  
  170.   FOR (i = nminas; i > 0; i--)    // ðàññòàâèòü ìèíû
  171.   {
  172.     x = random(ncx);
  173.     y = random(ncy);
  174.     WHILE ((get_value(x, y) == MINE) || ((x == no_x) && (y == no_y)))
  175.     {
  176.       x = random(ncx);
  177.       y = random(ncy);
  178.     }
  179.     set_value(x, y, MINE);
  180.   }
  181.  
  182.   for (x = ncx-1; x >= 0; x--)    // ðàññòàâèòü öèôðû
  183.   {
  184.     for (y = ncy-1; y >= 0; y--)
  185.     {
  186.       IF (get_value(x, y) == MINE)
  187.         continue;
  188.       EDX = x * ncy + y*4 + #massiv;
  189.       a = x; b = y;
  190.       FOR (i = 0; i < 8; i++)
  191.       {
  192.          AL = matrix[i].a_inc;
  193.          $movsx eax,al
  194.          a += EAX;
  195.          AL = matrix[i].b_inc;
  196.          $movsx eax,al
  197.          b += EAX;
  198.          IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_value(a, b) == MINE))
  199.            DSBYTE[EDX]++;
  200.       }
  201.     }
  202.   }
  203. }  // set_mines
  204.  
  205.  
  206. inline void do_mouse(void)
  207. // Îáðàáîò÷èê ìûøè
  208. {
  209.   int x,y;
  210.  
  211.   EAX = sys_read_mouse(2);            // ìûøü íå íàæàòà -> âûõîä
  212.   IF (EAX == 0)
  213.   {
  214. //    sys_debug_write_string("Strange\n");
  215.     return;
  216.   }
  217.  
  218.   mouse_status = AL;
  219.  
  220.   EAX = sys_read_mouse(1);            // ìûøü âíå ïîëÿ  -> âûõîä
  221.   EBX = EAX; EAX >>= 16; EBX &= 0xffff;
  222.   ECX = ncx * XPX + XST - 1;
  223.   EDX = ncy * YPX + YST - 1;
  224.   IF ((EAX < XST) || (EBX < YST) || (EAX > ECX) || (EBX > EDX)) return;
  225.  
  226.   EAX -= XST; EAX /= XPX; x = EAX;    // âû÷èñëèòü x è y
  227.   EBX -= YST; EBX /= YPX; y = EBX;
  228.  
  229.   IF ((mouse_status == 1) && (!get_open(x, y)) && (get_mark(x, y) != 1))
  230.   {
  231.     // íà íåîòêðûòîé êëåòêå áåç ôëàæêà íàæàòà ëåâàÿ êíîïêà ìûøè
  232.     // left mouse button is pressed
  233.     IF (firstmine == TRUE)
  234.     {
  235.       firstmine = FALSE;
  236.       set_mines(initmines, x, y);
  237.       start_timer();
  238.       time = 1;
  239.       draw_time();
  240.     }
  241.     IF (get_value(x, y) == MINE)
  242.     {
  243.       end_game();
  244.       return;
  245.     }
  246.     open_square(x, y);
  247.   }
  248.   else IF ((mouse_status == 2) && (!get_open(x, y)))
  249.   {
  250.     // íà íåîòêðûòîé êëåòêå íàæàòà ïðàâàÿ êíîïêà ìûøè
  251.     // right mouse button is pressed
  252.     EBX = get_mark(x, y); EBX++;
  253.     EBX = EBX%3;
  254.     SWITCH (EBX)
  255.     {
  256.       CASE 2: cmines++; BREAK;
  257.       CASE 1: cmines--;
  258.     }
  259.  
  260.     set_mark(x, y, EBX);
  261.  
  262.     draw_minesi();
  263.     draw_square(x, y);
  264.     return;
  265.   }
  266.   ELSE IF ((mouse_status == 3) && (get_open(x, y)))
  267.   {
  268.     // íà îòêðûòîé êëåòêå íàæàòû îáå êíîïêè ìûøè
  269.     // both mouse buttons are pressed
  270.     IF (open_near_squares(x, y) == TRUE)
  271.       end_game();
  272.   }
  273.  
  274.   IF (sqclosed == 0)
  275.   {
  276.     // îòêðûòû âñå êëåòêè
  277.     // all squares are opened
  278.     mouse_en   = FALSE;  // çàïðåòèòü ìûøü
  279.     stop_timer();
  280.     stop_game  = TRUE;   // èãðà çàâåðøåíà
  281.  
  282.     // ïîñòàâèòü íåðàññòàâëåííûå ìèíû
  283.     FOR (x = 0; x < ncx; x++)
  284.       FOR (y = 0; y < ncy; y++)
  285.         IF ((get_value(x, y) == MINE) && (get_mark(x, y) != 1))
  286.         {
  287.           set_mark(x, y, 1);
  288.           cmines--;
  289.           draw_square(x, y);
  290.         }
  291.     draw_minesi();
  292.   }
  293. }  // do_mouse
  294.  
  295.  
  296. void open_square(int x, y)
  297. // Îòêðûòü êëåòêó
  298. {
  299.   int a, b, i;
  300.  
  301.   #ifdef DEBUG
  302.   sys_debug_write_string("MINE: open_square called\n");
  303.   #endif
  304.  
  305.   set_open(x, y, TRUE);
  306.   sqclosed--;
  307.  
  308.   IF (get_value(x, y) != 0)
  309.   {
  310.     draw_square(x, y);
  311.   }
  312.   else
  313.   {
  314.     draw_square(x, y);
  315.     a = x; 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_open(a, b)) && (get_mark(a, b) != 1))
  327.         open_square(a, b);
  328.     }
  329.   }
  330. }  // open_square
  331.  
  332.  
  333. int open_near_squares(int x, y)
  334. // Îòêðûòü áëèçëåæàùèå êëåòêè (îáå êíîïêè ìûøè âìåñòå)
  335. {
  336.   int a, b, i;
  337.   dword suma = 0;
  338.  
  339.   #ifdef DEBUG
  340.   sys_debug_write_string("MINE: open_near_squares called\n");
  341.   #endif
  342.  
  343.   a = x;
  344.   b = y;
  345.   FOR (i = 0; i < 8; i++)
  346.   {
  347.     //a+=matrix[i].a_inc;
  348.     //b+=matrix[i].b_inc;
  349.     AL = matrix[i].a_inc;
  350.     $movsx eax,al
  351.     a += EAX;
  352.     AL = matrix[i].b_inc;
  353.     $movsx eax,al
  354.     b += EAX;
  355.     IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (get_mark(a, b) == 1))
  356.       suma++;
  357.   }
  358.  
  359.   if (suma == get_value(x, y))
  360.   {
  361.     suma = 0;
  362.     a = x;
  363.     b = y;
  364.     for (i = 0; i < 8; i++)
  365.     {
  366.       //a+=matrix[i].a_inc;
  367.       //b+=matrix[i].b_inc;
  368.       AL = matrix[i].a_inc;
  369.       $movsx eax,al
  370.       a += EAX;
  371.       AL = matrix[i].b_inc;
  372.       $movsx eax,al
  373.       b += EAX;
  374.       IF ((a >= 0) && (b >= 0) && (a < ncx) && (b < ncy) && (!get_open(a, b)) && (get_mark(a, b) != 1))
  375.       {
  376.         IF (get_value(a, b) == MINE)
  377.           suma = 1;
  378.         open_square(a, b);
  379.       }
  380.     }
  381.     RETURN suma;
  382.   }
  383.   ELSE
  384.     RETURN 0;
  385. }  // open_near_squares
  386.  
  387.  
  388. void end_game()
  389. {
  390.   int x,y;
  391.  
  392.   #ifdef DEBUG
  393.   sys_debug_write_string("MINE: end_game called\n");
  394.   #endif
  395.  
  396.   stop_game = TRUE;
  397.   stop_timer();
  398.   for (x=0; x<ncx; x++)
  399.   {
  400.     for (y=0; y<ncy; y++)
  401.     {
  402.       IF (get_value(x, y) == MINE)
  403.       {
  404.         set_mark(x, y, FALSE); // ñíÿòü ôëàã
  405.         open_square(x, y);
  406.       }
  407.       ELSE IF (get_mark(x, y) == 1)      // åñëè ìèíû íåò, à ôëàæîê åñòü
  408.       {
  409.         EBX = XPX * x + XST;      // x left
  410.         ECX = EBX + XPX - 1;      // x right
  411.         EBX <<= 16; EBX += ECX;
  412.         $PUSH EBX
  413.  
  414.         ECX = YPX * y + YST;      // y top
  415.         $PUSH ECX
  416.         EDX = ECX + YPX - 1;      // y bottom
  417.         ECX <<= 16; ECX += EDX;
  418.         sys_draw_line(EBX, ECX, clBlack);
  419.  
  420.         $POP EDX
  421.         ECX = EDX + YPX - 1;
  422.         ECX <<= 16; ECX += EDX;
  423.         $POP EBX
  424.         sys_draw_line(EBX, ECX, clBlack);
  425.         CONTINUE;
  426.       }
  427.     }
  428.   }
  429. }  // end_game
  430.  
  431.  
  432. void main()
  433. {
  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.           window_move_size(OLD,OLD,xsize,ysize);
  467.           CONTINUE;
  468.         }
  469. //        ELSE IF (EAX == 1002)
  470. //        {
  471. //          start_uf();
  472. //        }
  473.         ELSE IF (EAX == 1)           // close window
  474.           sys_exit_process();
  475.         CONTINUE;
  476.  
  477.       case evMouse:
  478.         IF (!mouse_en) // is mouse enabled ?
  479.           CONTINUE;
  480.         do_mouse();
  481.         // wait for mouse release - æäàòü îòïóñêàíèÿ êíîïêè
  482.         WHILE (sys_read_mouse(2) == mouse_status)
  483.         {
  484.           check_timer();
  485.           sys_delay(3);
  486.           CONTINUE;
  487.         }
  488.         check_timer();
  489.         IF (stop_game)      // disable mouse if game is stopped
  490.           mouse_en = FALSE;
  491.         CONTINUE;
  492.     }
  493.     check_timer();
  494.     sys_delay(2);
  495.   }
  496. }  // main
  497.