/* MINEHUNT A port of the famous easter egg on the HP-48 Series calculators. Jonathan Tao. */ #include #include #include #include #include "curses.h" #define CHK(x) (mines[x/32]&(1<<(x%32))) #define CHKV(x) (visit[x/32]&(1<<(x%32))) static const char* title="MINEHUNT"; void find_near(short* near, uint32_t* mines, short posx, short posy) { short j; *near=0; j=(posy-1)*16+(posx-1); /*Upper Left*/ if(posy!=0 && posx!=0 && CHK(j)) (*near)++; j=(posy-1)*16+posx; /*Up*/ if(posy!=0 && CHK(j)) (*near)++; j=(posy-1)*16+(posx+1); /*Upper Right*/ if(posy!=0 && posx!=15 && CHK(j)) (*near)++; j=posy*16+(posx+1); /*Right*/ if(posx!=15 && CHK(j)) (*near)++; j=(posy+1)*16+(posx+1); /*Lower Right*/ if(posy!=7 && posx!=15 && CHK(j)) (*near)++; j=(posy+1)*16+posx; /*Down*/ if(posy!=7 && CHK(j)) (*near)++; j=(posy+1)*16+(posx-1); /*Lower Left*/ if(posy!=7 && posx!=0 && CHK(j)) (*near)++; j=posy*16+(posx-1); /*Left*/ if(posx!=0 && CHK(j)) (*near)++; } /*find_near()*/ int main(int argc, char** argv) { short i,j,near,score,posx,posy; char key,state; uint32_t mines[4],visit[4],seed; memset(mines,0,32); memset(visit,0,32); posx=posy=near=0; key=state=0; score=1; /*Generate*/ if(argc>1) { seed=atoi(argv[1]); srand(seed); printf("Seed:\t%d",seed); } /*if a seed is provided*/ else { srand((unsigned)(long)&seed); printf("Seed:\t%d",(unsigned)(long)&seed); } /*else create seed from seed via "random" memory address*/ for(i=0;i<20;i++) { do {j=rand()&0X7F;} while(j==0 || j==127 || CHK(j)); mines[j/32]|=(1<<(j%32)); } /* 20 mines to place*/ visit[0]=1; /*First space taken*/ /* Init ncurses*/ initscr(); noecho(); curs_set(0); mvaddch(0,0,ACS_LEQUAL); for(i=0;i<8;i++) mvaddch(i+2,0,*(title+i)); mvaddch(10,0,164|A_ALTCHARSET); mvaddch(0,21,ACS_GEQUAL); for(i=0;i<8;i++) mvaddch(i+2,21,*(title+i)); mvaddch(10,21,164|A_ALTCHARSET); mvaddch(1,2,ACS_ULCORNER); mvaddch(1,19,ACS_URCORNER); mvaddch(10,2,ACS_LLCORNER); mvaddch(10,19,ACS_LRCORNER); mvhline(1,3,ACS_HLINE,16); mvhline(10,3,ACS_HLINE,16); mvvline(2,2,ACS_VLINE,8); mvvline(2,19,ACS_VLINE,8); for(i=0;i<8;i++) mvhline(i+2,3,' '|A_STANDOUT,16); mvaddch(9,18,ACS_CKBOARD); find_near(&near,mines,posx,posy); mvprintw(0,3,"Near %d",near); mvprintw(0,11,"Score %d",score); mvaddch(2,3,ACS_DIAMOND); refresh(); while(state==0) { key=getch(); mvaddch(posy+2,posx+3,'.'); repoll: switch(key) { case '4': case 'h': if(posx!=0) posx--; break; case '2': case 'j': if(posy!=7) posy++; break; case '8': case 'k': if(posy!=0) posy--; break; case '6': case 'l': if(posx!=15) posx++; break; case '7': case 'y': if(posx!=0 && posy!=0) {posx--; posy--;} break; case '9': case 'u': if(posx!=15 && posy!=0) {posx++; posy--;} break; case '1': case 'b': if(posx!=0 && posy!=7) {posx--; posy++;} break; case '3': case 'n': if(posx!=15 && posy!=7) {posx++; posy++;} break; case 'q': case 27: state=1; break; default: mvaddch(posy+2,posx+3,ACS_DIAMOND); key = getch(); goto repoll; }; /*switch key*/ mvaddch(posy+2,posx+3,ACS_DIAMOND); j = posy*16+posx; if(!CHKV(j)) { visit[j/32]|=(1<<(j%32)); score++; } /*Score increases when square is cleared*/ if(state || mines[j/32]&(1<<(j%32))) { score--; for(i=0;i<128;i++) if(CHK(i)) mvaddch((i/16)+2,(i%16)+3,164|A_ALTCHARSET); mvprintw(0,11,"Score %d",score); mvprintw(0,3,"YOU BLEW UP!!"); mvaddch(posy+2,posx+3,'X'); state=1; getch(); } /*if lose*/ else if(posx==15 && posy==7) { for(i=0;i<128;i++) if(CHK(i)) mvaddch((i/16)+2,(i%16)+3,164|A_ALTCHARSET); mvprintw(0,11,"Score %d",score); mvprintw(0,3,"YOU MADE IT!!"); mvaddch(posy+2,posx+3,'@'); state=1; getch(); } /*if win*/ else { find_near(&near,mines,posx,posy); mvprintw(0,3,"Near %d",near); mvprintw(0,11,"Score %d",score); } /*else continue play*/ } /*while continue*/ endwin(); printf("\nScore:\t%d\n",score); return 0; } /* main() */