Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**********************************************/
- /* Minesweeper (15.06.12- . . ) */
- /* [GeekBros]Siapran & Eiyeron */
- /* tristan.robin@hotmail.fr */
- /**********************************************/
- #include "fxlib.h"
- #include "ECode.h"
- #include "MonochromeLib.h"
- #include "syscall.h"
- #include "sprites.h"
- typedef struct{
- unsigned char* grid;
- unsigned char gridWidth;
- unsigned char gridHeight;
- unsigned int nbMines;
- unsigned char gameState;
- unsigned int timeStarted;
- unsigned char offsetX;
- unsigned char offsetY;
- }GameState;
- #define VIEWPORT_WIDTH 12
- #define VIEWPORT_HEIGHT 8
- // FLAGS & CASES
- #define BLANK_CASE 0x00 // 0000 0000
- #define MINE_CASE 0x0F // 0000 1111
- #define BOOM_CASE 0xDD // Dead Case
- #define FLAG_SWITCH 0x10 // 0001 0000
- #define DEFUSED_SWITCH 0x20 // 0010 0000
- #define BAD_FLAG 0x40 // 0100 0000
- #define COVERED_SWITCH 0x80 // 1000 0000
- // MASKS
- #define VALUE_PART 0x0F // 0000 1111
- #define SWITCH_PART 0xF0 // 1111 0000
- // Event returns
- #define NOT_UNCOVERED 0x00 // 0 cases unc
- #define NORMAL_UNCONVERED 0x01 // only normal cases
- #define MINE_UNCOVERED 0xFF // mine uncovered : gameover
- #define TOGGLED_FLAG 0x10 // Toggled a flag
- #define NOT_TOGGLED_FLAG 0x1F // Couldn't toggled a flag
- // MISC
- #define INCLUDE_MINES 0x01 // OPtions toinclude mines to uncover
- #define NOT_INCLUDE_MINES 0x00
- // Macros
- #define GET_CASE(g,x,y) ((g->grid)[(y)*(g->gridWidth) + (x)])
- #define min(a,b) (((a) < (b))? (a) : (b))
- #define max(a,b) (((a) > (b))? (a) : (b))
- void replaceValue(GameState* g, char origin, char target) //replaces origin with target in the grid
- {
- int i;
- for(i=0;i<(g->gridWidth*g->gridHeight);i++) //explore the whole grid
- {
- if(g->grid[i]==origin) {g->grid[i] = target;} //replace a with b
- }
- }
- void initValues(GameState* g) {
- // Init the case's values
- unsigned char x, y;
- unsigned char total;
- for(y = 0; y < g->gridHeight; ++y) {
- for(x = 0; x < g->gridWidth; ++x) {
- if( (GET_CASE(g, x, y) & VALUE_PART) == MINE_CASE ) continue;
- total = 0;
- if(x > 0) {
- if(y > 0 && (GET_CASE(g, x - 1, y - 1) & VALUE_PART) == MINE_CASE) ++total;
- if((GET_CASE(g, x - 1, y) & VALUE_PART) == MINE_CASE) ++total;
- if(y < g->gridHeight - 1 && (GET_CASE(g, x - 1, y + 1) & VALUE_PART) == MINE_CASE) ++total;
- }
- if(y > 0 && (GET_CASE(g, x, y - 1) & VALUE_PART) == MINE_CASE) ++total;
- if(y < g->gridHeight - 1 && (GET_CASE(g, x, y + 1) & VALUE_PART) == MINE_CASE) ++total;
- if(x < g->gridWidth - 1) {
- if(y > 0 && (GET_CASE(g, x + 1, y - 1) & VALUE_PART) == MINE_CASE) ++total;
- if((GET_CASE(g, x + 1, y) & VALUE_PART) == MINE_CASE) ++total;
- if(y < g->gridHeight - 1 && (GET_CASE(g, x + 1, y + 1) & VALUE_PART) == MINE_CASE) ++total;
- }
- GET_CASE(g, x, y) |= total;
- }
- }
- }
- void drawTileFromGrid(GameState* g, unsigned char x, unsigned char y, unsigned char xt, unsigned char yt) //draws tile grid indicates at pos x,y
- {
- unsigned char value;
- value = GET_CASE(g, x,y);
- if(value == BOOM_CASE)
- ML_bmp_8_or(boom, xt*8, yt*8);
- else if(value & FLAG_SWITCH) //flag
- ML_bmp_8_or(flag, xt*8, yt*8);
- else if(value & COVERED_SWITCH) //if spot closed
- ML_bmp_8_or(closed, xt*8, yt*8);
- else if(value & DEFUSED_SWITCH)
- ML_bmp_8_or(mine, xt*8, yt*8);
- else if(value == BAD_FLAG)
- ML_bmp_8_or(wrong, xt*8, yt*8);
- else {
- value &= VALUE_PART;
- if(value == MINE_CASE)
- ML_bmp_8_or(mine, xt*8, yt*8);
- else {
- ML_bmp_8_or(open, xt*8, yt*8);
- if(value)
- ML_bmp_or(chars[value], 2+xt*8, 1+yt*8, 3, 5);
- }
- }
- }
- void drawMap(GameState* g) {
- unsigned char i;
- unsigned char j;
- unsigned char minX, maxX;
- unsigned char minY, maxY;
- minX = max(0, g->offsetX);
- maxX = min(minX + VIEWPORT_WIDTH, minX + g->gridWidth);
- minY = max(0, g->offsetY);
- maxY = min(minY + VIEWPORT_HEIGHT, minY + g->gridHeight);
- for(i=minY;i<maxY;++i)
- {
- for(j=minX;j<maxX;++j)
- {
- drawTileFromGrid(g, j, i, j - minX, i - minY);
- }
- }
- }
- void createGrid(GameState* g) //creates a new grid
- {
- unsigned char mineCount;
- memset(g->grid, BLANK_CASE | COVERED_SWITCH, g->gridHeight * g->gridWidth * sizeof(char));
- for(mineCount = 0; mineCount < g->nbMines; ++mineCount) {
- unsigned char minePlaced = 0;
- while(!minePlaced) {
- unsigned char x = rand()%g->gridWidth;
- unsigned char y = rand()%g->gridHeight;
- if((GET_CASE(g, x, y) & VALUE_PART) == BLANK_CASE) {
- minePlaced = 1;
- GET_CASE(g, x, y) |= MINE_CASE;
- }
- }
- }
- initValues(g);
- }
- unsigned char searchForAdjacentBlankCases(GameState* g, unsigned char x, unsigned char y, unsigned char includeMines) {
- unsigned char *positions;
- unsigned int pos = 0;
- unsigned char xt,yt,minX,minY,maxX,maxY,i,j,hasNodes;
- positions = (unsigned char*)malloc(g->gridWidth * g->gridHeight * sizeof(unsigned char) * 2);
- ++pos;
- positions[pos * 2] = x;
- positions[pos * 2 + 1] = y;
- while(pos) {
- xt = positions[pos*2];
- yt = positions[pos*2 + 1];
- minX = xt == 0 ? 0 : xt - 1;
- maxX = xt == g->gridWidth - 1 ? g->gridWidth - 1 : xt + 1;
- minY = yt == 0 ? 0 : yt - 1;
- maxY = yt == g->gridHeight - 1 ? g->gridHeight - 1 : yt + 1;
- hasNodes = 0;
- for(i = minY; i<= maxY; ++i) {
- for(j = minX; j<= maxX; ++j) {
- unsigned char value = GET_CASE(g, j, i);
- //if(i == yt && j == xt) continue;
- if(!(value & COVERED_SWITCH) || value & FLAG_SWITCH || ((value & VALUE_PART) == MINE_CASE && includeMines == NOT_INCLUDE_MINES)) continue;
- if((value & VALUE_PART) == MINE_CASE) {
- GET_CASE(g, j, i) = BOOM_CASE;
- }
- else {
- GET_CASE(g, j, i) &= ~COVERED_SWITCH;
- }
- if((value & VALUE_PART) == 0) {
- pos++;
- positions[pos*2] = j;
- positions[pos*2 + 1] = i;
- hasNodes = 1;
- }
- }
- }
- if(!hasNodes) --pos;
- }
- free(positions);
- }
- unsigned char countNeighbourFlags(GameState* g, unsigned char x, unsigned char y) {
- unsigned char i,j;
- unsigned char minX, maxX;
- unsigned char minY, maxY;
- unsigned char total = 0;
- minX = x == 0 ? 0 : x - 1;
- maxX = x == g->gridWidth - 1 ? g->gridWidth - 1 : x + 1;
- minY = y == 0 ? 0 : y - 1;
- maxY = y == g->gridHeight - 1 ? g->gridHeight - 1 : y + 1;
- for(i = minY; i<= maxY; ++i) {
- for(j = minX; j<= maxX; ++j) {
- unsigned char value = GET_CASE(g, j, i);
- if(!(value == BOOM_CASE) && value & FLAG_SWITCH) ++total;
- }
- }
- return total;
- }
- unsigned char actionUncoverCase(GameState* g, unsigned char x, unsigned char y) {
- unsigned char value = GET_CASE(g, x, y);
- if(value & FLAG_SWITCH) return NOT_UNCOVERED;
- if((value & VALUE_PART) == MINE_CASE) {
- GET_CASE(g, x, y) = BOOM_CASE;
- return MINE_UNCOVERED;
- }
- if(!(GET_CASE(g, x, y) & COVERED_SWITCH)) {
- if(countNeighbourFlags(g, x, y) == (GET_CASE(g, x, y)&VALUE_PART)) {
- searchForAdjacentBlankCases(g, x, y, INCLUDE_MINES);
- return NORMAL_UNCONVERED;
- }
- else
- return NOT_UNCOVERED;
- }
- GET_CASE(g, x, y) &= ~COVERED_SWITCH;
- value = GET_CASE(g, x, y) & VALUE_PART;
- if(value == BLANK_CASE) {
- searchForAdjacentBlankCases(g, x, y, NOT_INCLUDE_MINES);
- }
- return NORMAL_UNCONVERED;
- }
- unsigned char actionToggleFlag(GameState* g, unsigned char x, unsigned char y) {
- unsigned char value = GET_CASE(g, x, y);
- if(!(value & COVERED_SWITCH)) return NOT_TOGGLED_FLAG;
- GET_CASE(g, x, y) ^= FLAG_SWITCH;
- return TOGGLED_FLAG;
- }
- //===================================//
- void manageEvents(GameState *g, unsigned char event) {
- switch(event) {
- case NOT_UNCOVERED:
- break;
- case NORMAL_UNCONVERED:
- break;
- case MINE_UNCOVERED:
- break;
- case TOGGLED_FLAG:
- break;
- case NOT_TOGGLED_FLAG:
- break;
- }
- }
- void allocateGrid(GameState* g) {
- g->grid = (unsigned char*)malloc(g->gridWidth * g->gridHeight * sizeof(unsigned char));
- }
- void drawPlayerCursor(unsigned char x, unsigned char y) {
- //ML_rectangle(x*8, y*8, x*8+8, y*8+8, 0, XOR, XOR);
- ML_bmp_and_cl(cursor_alpha, x*8 - 2, y*8 - 2, 12, 12);
- ML_bmp_or_cl(cursor, x*8 - 2, y*8 - 2, 12, 12);
- }
- unsigned char ergoKey(unsigned char* pDownTime, unsigned char* pressed) {
- if(!*pressed) {
- *pDownTime++;
- *pressed = 1;
- }
- if(*pDownTime == 1) {
- return 1;
- }
- if(*pDownTime == 5) {
- *pDownTime = 4;
- return 1;
- }
- }
- int AddIn_main(int isAppli, unsigned short OptionNum)
- {
- //actual int main() lol
- GameState g;
- unsigned char x, y = x = 0;
- unsigned char event = 0;
- unsigned char downTime = 0;
- unsigned char keyIsPressed = 0;
- unsigned char keyAction = 0;
- g.gridWidth = 32;
- g.gridHeight = 32;
- g.nbMines = 20;
- g.timeStarted = RTC_GetTicks();
- g.offsetX = 0;
- g.offsetY = 0;
- srand(RTC_GetTicks());
- allocateGrid(&g);
- createGrid(&g);
- ML_clear_vram();
- drawMap(&g);
- drawPlayerCursor(x, y);
- ML_display_vram();
- while(1) {
- keyIsPressed = 0;
- if(KeyDown(K_LEFT) && x > 0) {
- if(ergoKey(&downTime, &keyIsPressed)) {
- --x;
- }
- }
- if(KeyDown(K_RIGHT) && x < g.gridWidth - 1) {
- if(ergoKey(&downTime, &keyIsPressed)) {
- ++x;
- }
- }
- if(KeyDown(K_UP) && y > 0) {
- if(ergoKey(&downTime, &keyIsPressed)) {
- --y;
- }
- }
- if(KeyDown(K_DOWN) && y < g.gridHeight - 1) {
- if(ergoKey(&downTime, &keyIsPressed)) {
- ++y;
- }
- }
- if(g.gridWidth > VIEWPORT_WIDTH) {
- g.offsetX = max(0, x - VIEWPORT_WIDTH/2);
- g.offsetX = min(g.offsetX, g.gridWidth - VIEWPORT_WIDTH);
- }
- if(g.gridHeight > VIEWPORT_HEIGHT) {
- g.offsetY = max(0, y - VIEWPORT_HEIGHT/2);
- g.offsetY = min(g.offsetY, g.gridHeight - VIEWPORT_HEIGHT);
- }
- if(KeyDown(K_SHIFT)) {
- if(ergoKey(&downTime, &keyIsPressed)) {
- event = actionUncoverCase(&g, x, y);
- }
- }
- else if(KeyDown(K_ALPHA)) {
- if(ergoKey(&downTime, &keyIsPressed)) {
- event = actionToggleFlag(&g, x, y);
- }
- }
- if(!keyIsPressed) {
- downTime = 0;
- }
- manageEvents(&g, event);
- ML_clear_vram();
- drawMap(&g);
- drawPlayerCursor(x - g.offsetX, y - g.offsetY);
- ML_display_vram();
- Sleep(50);
- }
- return 1;
- }
- //========================================================================//
- #pragma section R_Size
- unsigned long BR_Size;
- #pragma section
- #pragma section _TOP
- int InitializeSystem(int isAppli, unsigned short OptionNum)
- {
- return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
- }
- #pragma section
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement