Advertisement
Siapran

MINES.c

Aug 8th, 2013
347
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.33 KB | None | 0 0
  1. /**********************************************/
  2. /* Minesweeper (15.06.12-  .  .  )            */
  3. /* [GeekBros]Siapran & Eiyeron                */
  4. /* tristan.robin@hotmail.fr                   */
  5. /**********************************************/
  6. #include "fxlib.h"
  7. #include "ECode.h"
  8. #include "MonochromeLib.h"
  9. #include "syscall.h"
  10. #include "sprites.h"
  11.  
  12. typedef struct{
  13.     unsigned char* grid;
  14.     unsigned char gridWidth;
  15.     unsigned char gridHeight;
  16.     unsigned int nbMines;
  17.     unsigned char gameState;
  18.     unsigned int timeStarted;
  19.     unsigned char offsetX;
  20.     unsigned char offsetY;
  21.  
  22. }GameState;
  23.  
  24.  
  25. #define VIEWPORT_WIDTH 12
  26. #define VIEWPORT_HEIGHT 8
  27.  
  28. // FLAGS & CASES
  29. #define BLANK_CASE          0x00 // 0000 0000
  30. #define MINE_CASE           0x0F // 0000 1111
  31. #define BOOM_CASE           0xDD // Dead Case
  32. #define FLAG_SWITCH         0x10 // 0001 0000
  33. #define DEFUSED_SWITCH      0x20 // 0010 0000
  34. #define BAD_FLAG            0x40 // 0100 0000
  35. #define COVERED_SWITCH      0x80 // 1000 0000
  36.  
  37. // MASKS
  38. #define VALUE_PART          0x0F // 0000 1111
  39. #define SWITCH_PART         0xF0 // 1111 0000
  40.  
  41. // Event returns
  42.  
  43. #define NOT_UNCOVERED       0x00 // 0 cases unc
  44. #define NORMAL_UNCONVERED   0x01 // only normal cases
  45. #define MINE_UNCOVERED      0xFF // mine uncovered : gameover
  46.  
  47. #define TOGGLED_FLAG        0x10 // Toggled a flag
  48. #define NOT_TOGGLED_FLAG    0x1F // Couldn't toggled a flag
  49.  
  50. // MISC
  51.  
  52. #define INCLUDE_MINES       0x01 // OPtions toinclude mines to uncover
  53. #define NOT_INCLUDE_MINES   0x00
  54.  
  55. // Macros
  56.  
  57. #define GET_CASE(g,x,y) ((g->grid)[(y)*(g->gridWidth) + (x)])
  58.  
  59. #define min(a,b) (((a) < (b))? (a) : (b))
  60.  
  61. #define max(a,b) (((a) > (b))? (a) : (b))
  62.  
  63. void replaceValue(GameState* g, char origin, char target) //replaces origin with target in the grid
  64. {
  65.     int i;
  66.     for(i=0;i<(g->gridWidth*g->gridHeight);i++) //explore the whole grid
  67.     {
  68.         if(g->grid[i]==origin) {g->grid[i] = target;} //replace a with b
  69.     }
  70. }
  71.  
  72. void initValues(GameState* g) {
  73. // Init the case's values
  74.     unsigned char x, y;
  75.     unsigned char total;
  76.     for(y = 0; y < g->gridHeight; ++y) {
  77.         for(x = 0; x < g->gridWidth; ++x) {
  78.  
  79.             if( (GET_CASE(g, x, y) & VALUE_PART) == MINE_CASE ) continue;
  80.  
  81.             total = 0;
  82.             if(x > 0) {
  83.                 if(y > 0 && (GET_CASE(g, x - 1, y - 1) & VALUE_PART) == MINE_CASE)  ++total;
  84.                 if((GET_CASE(g, x - 1, y) & VALUE_PART) == MINE_CASE)  ++total;
  85.                 if(y < g->gridHeight - 1 && (GET_CASE(g, x - 1, y + 1) & VALUE_PART) == MINE_CASE)  ++total;
  86.             }
  87.             if(y > 0 && (GET_CASE(g, x, y - 1) & VALUE_PART) == MINE_CASE)  ++total;
  88.             if(y < g->gridHeight - 1 && (GET_CASE(g, x, y + 1) & VALUE_PART) == MINE_CASE)  ++total;
  89.             if(x < g->gridWidth - 1) {
  90.                 if(y > 0 && (GET_CASE(g, x + 1, y - 1) & VALUE_PART) == MINE_CASE)  ++total;
  91.                 if((GET_CASE(g, x + 1, y) & VALUE_PART) == MINE_CASE)  ++total;
  92.                 if(y < g->gridHeight - 1 && (GET_CASE(g, x + 1, y + 1) & VALUE_PART) == MINE_CASE)  ++total;
  93.             }
  94.  
  95.             GET_CASE(g, x, y) |= total;
  96.         }
  97.     }
  98. }
  99.  
  100. void drawTileFromGrid(GameState* g, unsigned char x, unsigned char y, unsigned char xt, unsigned char yt) //draws tile grid indicates at pos x,y
  101. {
  102.     unsigned char value;
  103.     value = GET_CASE(g, x,y);
  104.     if(value == BOOM_CASE)
  105.         ML_bmp_8_or(boom, xt*8, yt*8);
  106.     else if(value & FLAG_SWITCH) //flag
  107.         ML_bmp_8_or(flag, xt*8, yt*8);
  108.     else if(value & COVERED_SWITCH) //if spot closed
  109.         ML_bmp_8_or(closed, xt*8, yt*8);
  110.     else if(value & DEFUSED_SWITCH)
  111.         ML_bmp_8_or(mine, xt*8, yt*8);
  112.     else if(value == BAD_FLAG)
  113.         ML_bmp_8_or(wrong, xt*8, yt*8);
  114.     else {
  115.         value &= VALUE_PART;
  116.         if(value == MINE_CASE)
  117.             ML_bmp_8_or(mine, xt*8, yt*8);
  118.         else {
  119.             ML_bmp_8_or(open, xt*8, yt*8);
  120.             if(value)
  121.                 ML_bmp_or(chars[value], 2+xt*8, 1+yt*8, 3, 5);
  122.         }
  123.     }
  124. }
  125.  
  126. void drawMap(GameState* g) {
  127.     unsigned char i;
  128.     unsigned char j;
  129.     unsigned char minX, maxX;
  130.     unsigned char minY, maxY;
  131.     minX = max(0, g->offsetX);
  132.     maxX = min(minX + VIEWPORT_WIDTH, minX + g->gridWidth);
  133.     minY = max(0, g->offsetY);
  134.     maxY = min(minY + VIEWPORT_HEIGHT, minY + g->gridHeight);
  135.  
  136.     for(i=minY;i<maxY;++i)
  137.     {
  138.         for(j=minX;j<maxX;++j)
  139.         {
  140.             drawTileFromGrid(g, j, i, j - minX, i - minY);
  141.         }
  142.     }
  143. }
  144.  
  145.  
  146. void createGrid(GameState* g) //creates a new grid
  147. {
  148.     unsigned char mineCount;
  149.     memset(g->grid, BLANK_CASE | COVERED_SWITCH, g->gridHeight * g->gridWidth * sizeof(char));
  150.     for(mineCount = 0; mineCount < g->nbMines; ++mineCount) {
  151.         unsigned char minePlaced = 0;
  152.         while(!minePlaced) {
  153.             unsigned char x = rand()%g->gridWidth;
  154.             unsigned char y = rand()%g->gridHeight;
  155.             if((GET_CASE(g, x, y) & VALUE_PART) == BLANK_CASE) {
  156.                 minePlaced = 1;
  157.                 GET_CASE(g, x, y) |= MINE_CASE;
  158.             }
  159.         }
  160.     }
  161.     initValues(g);
  162. }
  163.  
  164.  
  165. unsigned char searchForAdjacentBlankCases(GameState* g, unsigned char x, unsigned char y, unsigned char includeMines) {
  166.     unsigned char *positions;
  167.     unsigned int pos = 0;
  168.     unsigned char xt,yt,minX,minY,maxX,maxY,i,j,hasNodes;
  169.  
  170.     positions = (unsigned char*)malloc(g->gridWidth * g->gridHeight * sizeof(unsigned char) * 2);
  171.     ++pos;
  172.     positions[pos * 2] = x;
  173.     positions[pos * 2 + 1] = y;
  174.     while(pos) {
  175.         xt = positions[pos*2];
  176.         yt = positions[pos*2 + 1];
  177.         minX = xt == 0 ? 0 : xt - 1;
  178.         maxX = xt == g->gridWidth - 1 ? g->gridWidth - 1 : xt + 1;
  179.         minY = yt == 0 ? 0 : yt - 1;
  180.         maxY = yt == g->gridHeight - 1 ? g->gridHeight - 1 : yt + 1;
  181.         hasNodes = 0;
  182.  
  183.         for(i = minY; i<= maxY; ++i) {
  184.             for(j = minX; j<= maxX; ++j) {
  185.                 unsigned char value = GET_CASE(g, j, i);
  186.  
  187.                 //if(i == yt && j == xt) continue;
  188.                 if(!(value & COVERED_SWITCH) || value & FLAG_SWITCH || ((value & VALUE_PART) == MINE_CASE && includeMines == NOT_INCLUDE_MINES)) continue;
  189.  
  190.                 if((value & VALUE_PART) == MINE_CASE) {
  191.                     GET_CASE(g, j, i) = BOOM_CASE;
  192.                 }
  193.                 else {                 
  194.                     GET_CASE(g, j, i) &= ~COVERED_SWITCH;
  195.                 }
  196.                 if((value & VALUE_PART) == 0) {
  197.                     pos++;
  198.                     positions[pos*2] = j;
  199.                     positions[pos*2 + 1] = i;
  200.                     hasNodes = 1;
  201.                 }
  202.             }
  203.         }
  204.         if(!hasNodes) --pos;
  205.  
  206.     }
  207.  
  208.     free(positions);
  209. }
  210.  
  211. unsigned char countNeighbourFlags(GameState* g, unsigned char x, unsigned char y) {
  212.     unsigned char i,j;
  213.     unsigned char minX, maxX;
  214.     unsigned char minY, maxY;
  215.     unsigned char total = 0;
  216.     minX = x == 0 ? 0 : x - 1;
  217.     maxX = x == g->gridWidth - 1 ? g->gridWidth - 1 : x + 1;
  218.     minY = y == 0 ? 0 : y - 1;
  219.     maxY = y == g->gridHeight - 1 ? g->gridHeight - 1 : y + 1;
  220.  
  221.     for(i = minY; i<= maxY; ++i) {
  222.         for(j = minX; j<= maxX; ++j) {
  223.             unsigned char value = GET_CASE(g, j, i);
  224.            
  225.             if(!(value == BOOM_CASE) && value & FLAG_SWITCH) ++total;
  226.            
  227.         }
  228.     }
  229.  
  230.     return total;
  231. }
  232.  
  233. unsigned char actionUncoverCase(GameState* g, unsigned char x, unsigned char y) {
  234.     unsigned char value = GET_CASE(g, x, y);
  235.  
  236.     if(value & FLAG_SWITCH) return NOT_UNCOVERED;
  237.     if((value & VALUE_PART) == MINE_CASE) {
  238.         GET_CASE(g, x, y) = BOOM_CASE;
  239.         return MINE_UNCOVERED; 
  240.     }
  241.  
  242.     if(!(GET_CASE(g, x, y) & COVERED_SWITCH)) {
  243.         if(countNeighbourFlags(g, x, y) == (GET_CASE(g, x, y)&VALUE_PART)) {
  244.             searchForAdjacentBlankCases(g, x, y, INCLUDE_MINES);
  245.             return NORMAL_UNCONVERED;
  246.         }
  247.         else
  248.             return NOT_UNCOVERED;
  249.     }
  250.  
  251.     GET_CASE(g, x, y) &= ~COVERED_SWITCH;
  252.     value = GET_CASE(g, x, y) & VALUE_PART;
  253.  
  254.     if(value == BLANK_CASE) {
  255.         searchForAdjacentBlankCases(g, x, y, NOT_INCLUDE_MINES);
  256.     }
  257.  
  258.     return NORMAL_UNCONVERED;
  259. }
  260.  
  261. unsigned char actionToggleFlag(GameState* g, unsigned char x, unsigned char y) {
  262.     unsigned char value = GET_CASE(g, x, y);
  263.  
  264.     if(!(value & COVERED_SWITCH)) return NOT_TOGGLED_FLAG;
  265.     GET_CASE(g, x, y) ^= FLAG_SWITCH;
  266.     return TOGGLED_FLAG;
  267. }
  268.  
  269. //===================================//
  270.  
  271.  
  272. void manageEvents(GameState *g, unsigned char event) {
  273.     switch(event) {
  274.         case NOT_UNCOVERED:
  275.         break;
  276.         case NORMAL_UNCONVERED:
  277.         break;
  278.         case MINE_UNCOVERED:
  279.         break;
  280.         case TOGGLED_FLAG:
  281.         break;
  282.         case NOT_TOGGLED_FLAG:
  283.         break;
  284.     }
  285. }
  286.  
  287. void allocateGrid(GameState* g) {
  288.     g->grid = (unsigned char*)malloc(g->gridWidth * g->gridHeight * sizeof(unsigned char));
  289. }
  290.  
  291. void drawPlayerCursor(unsigned char x, unsigned char y) {
  292.     //ML_rectangle(x*8, y*8, x*8+8, y*8+8, 0, XOR, XOR);
  293.     ML_bmp_and_cl(cursor_alpha, x*8 - 2, y*8 - 2, 12, 12);
  294.     ML_bmp_or_cl(cursor, x*8 - 2, y*8 - 2, 12, 12);
  295. }
  296.  
  297. unsigned char ergoKey(unsigned char* pDownTime, unsigned char* pressed) {
  298.     if(!*pressed) {
  299.         *pDownTime++;
  300.         *pressed = 1;
  301.     }
  302.     if(*pDownTime == 1) {
  303.         return 1;
  304.     }
  305.     if(*pDownTime == 5) {
  306.         *pDownTime = 4;
  307.         return 1;
  308.     }
  309. }
  310.  
  311. int AddIn_main(int isAppli, unsigned short OptionNum)
  312. {
  313.  
  314. //actual int main() lol
  315.     GameState g;
  316.     unsigned char x, y = x = 0;
  317.     unsigned char event = 0;
  318.     unsigned char downTime = 0;
  319.     unsigned char keyIsPressed = 0;
  320.     unsigned char keyAction = 0;
  321.  
  322.     g.gridWidth = 32;
  323.     g.gridHeight = 32;
  324.     g.nbMines = 20;
  325.     g.timeStarted = RTC_GetTicks();
  326.     g.offsetX = 0;
  327.     g.offsetY = 0;
  328.  
  329.  
  330.     srand(RTC_GetTicks());
  331.     allocateGrid(&g);
  332.     createGrid(&g);
  333.    
  334.     ML_clear_vram();
  335.     drawMap(&g);
  336.     drawPlayerCursor(x, y);
  337.     ML_display_vram();
  338.  
  339.    
  340.  
  341.     while(1) {
  342.  
  343.         keyIsPressed = 0;
  344.  
  345.         if(KeyDown(K_LEFT) && x > 0) {
  346.             if(ergoKey(&downTime, &keyIsPressed)) {
  347.                 --x;
  348.             }
  349.         }
  350.         if(KeyDown(K_RIGHT) && x < g.gridWidth - 1) {
  351.             if(ergoKey(&downTime, &keyIsPressed)) {
  352.                 ++x;
  353.             }
  354.         }
  355.         if(KeyDown(K_UP) && y > 0) {
  356.             if(ergoKey(&downTime, &keyIsPressed)) {
  357.                 --y;
  358.             }
  359.         }
  360.         if(KeyDown(K_DOWN) && y < g.gridHeight - 1) {
  361.             if(ergoKey(&downTime, &keyIsPressed)) {
  362.                 ++y;
  363.             }
  364.         }
  365.  
  366.         if(g.gridWidth > VIEWPORT_WIDTH) {
  367.             g.offsetX = max(0, x - VIEWPORT_WIDTH/2);
  368.             g.offsetX = min(g.offsetX, g.gridWidth - VIEWPORT_WIDTH);
  369.         }
  370.         if(g.gridHeight > VIEWPORT_HEIGHT) {
  371.             g.offsetY = max(0, y - VIEWPORT_HEIGHT/2);
  372.             g.offsetY = min(g.offsetY, g.gridHeight - VIEWPORT_HEIGHT);
  373.         }
  374.  
  375.         if(KeyDown(K_SHIFT)) {
  376.             if(ergoKey(&downTime, &keyIsPressed)) {
  377.                 event = actionUncoverCase(&g, x, y);
  378.             }
  379.         }
  380.         else if(KeyDown(K_ALPHA)) {
  381.             if(ergoKey(&downTime, &keyIsPressed)) {
  382.                 event = actionToggleFlag(&g, x, y);
  383.             }
  384.         }
  385.  
  386.         if(!keyIsPressed) {
  387.             downTime = 0;
  388.         }
  389.  
  390.         manageEvents(&g, event);
  391.  
  392.         ML_clear_vram();
  393.         drawMap(&g);
  394.         drawPlayerCursor(x - g.offsetX, y - g.offsetY);
  395.         ML_display_vram();
  396.         Sleep(50);
  397.     }
  398.     return 1;
  399. }
  400.  
  401. //========================================================================//
  402.  
  403. #pragma section R_Size
  404. unsigned long BR_Size;
  405. #pragma section
  406.  
  407.  
  408. #pragma section _TOP
  409.  
  410. int InitializeSystem(int isAppli, unsigned short OptionNum)
  411. {
  412.     return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
  413. }
  414.  
  415.  
  416. #pragma section
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement