1
0
mirror of https://github.com/abakh/nbsdgames.git synced 2024-11-02 16:27:18 -04:00
nbsdgames/sources/memoblocks.c

270 lines
5.8 KiB
C
Raw Normal View History

2019-05-13 09:58:19 -04:00
#include <curses.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <time.h>
#include <signal.h>
/*
. . _
|\/| |_)
| |EMORY|_)LOCKS
Authored by Hossein Bakhtiarifar <abakh@tuta.io>
No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law.
compile with -lncurses
*/
/* The Plan9 compiler can not handle VLAs */
#ifdef Plan9
#define size 8
#define size2 16
#endif
2019-05-13 09:58:19 -04:00
typedef signed char byte;
typedef unsigned char ubyte;
byte size,size2;//size2 is there to avoid a lot of multiplications
byte py,px;
byte fy,fx; //the first tile
chtype colors[6]={0};
void rectangle(byte sy,byte sx){
for(byte y=0;y<=size+1;y++){
mvaddch(sy+y,sx,ACS_VLINE);
mvaddch(sy+y,sx+size2+1,ACS_VLINE);
}
for(byte x=0;x<=size2+1;x++){
mvaddch(sy,sx+x,ACS_HLINE);
mvaddch(sy+size+1,sx+x,ACS_HLINE);
}
mvaddch(sy,sx,ACS_ULCORNER);
mvaddch(sy+size+1,sx,ACS_LLCORNER);
mvaddch(sy,sx+size2+1,ACS_URCORNER);
mvaddch(sy+size+1,sx+size2+1,ACS_LRCORNER);
}
void logo(byte sy,byte sx){
mvaddstr(sy,sx, ". . _");
mvaddstr(sy+1,sx,"|\\/| |_)");
mvaddstr(sy+2,sx,"| |EMORY|_)LOCKS");
}
//convert integer to representing sign
char int2sgn(byte num){
2020-05-18 14:59:29 -04:00
if(0< num && num <= 9)
return num+'0';
else if(10<=num && num <=35)
return num-10+'a';
else if(36<=num && num <=51)
return num-36+'A';
2019-05-13 09:58:19 -04:00
else if(52<=num && num<=64)
return num-52+'!';
2020-05-18 14:59:29 -04:00
return 0;
2019-05-13 09:58:19 -04:00
}
//display
void draw(byte sy,byte sx,chtype board[size][size2],bool show[size][size2]){
rectangle(sy,sx);
byte y,x;
chtype prnt;
for(y=0;y<size;y++){
for(x=0;x<size2;x++){
if(show[y][x] || (y==fy && x==fx) )
prnt=board[y][x];
else
prnt='.';
if(y==py && x==px)
prnt|=A_STANDOUT;
mvaddch(sy+1+y,sx+1+x,prnt);
}
}
}
void fill(chtype board[size][size2]){
ubyte y,x,m;
int n;
for(y=0;y<size;y++){
for(x=0;x<size2;x++){
n=(y*size2+x)/2;
if(size*size<193) //(1+0*64)%6 == (1+3*64)%6 so this won't work in n=193 and above
m=n%6;
else //this for default wouldn't be colorful enough blow n=193
m=(n/64)%6;
board[y][x]=int2sgn((n%64)+1)|colors[m];
//fills with 1,1,2,2,.. with colored pairs
}
}
}
bool issolved(bool show[size][size2]){
byte y,x;
for(y=0;y<size;y++){
for(x=0;x<size2;x++){
if(!show[y][x])
return 0;
}
}
return 1;
}
void shuffle(chtype board[size][size2]){
int n=size*size*3;
chtype a;
byte ay,ax,by,bx;
for(int m=0;m<n;m++){
2019-07-30 14:13:10 -04:00
ay=rand()%size;
ax=rand()%(size2);
by=rand()%size;
bx=rand()%(size2);
2019-05-13 09:58:19 -04:00
a=board[ay][ax];
board[ay][ax]=board[by][bx];
board[by][bx]=a;
}
}
//peacefully close when ^C is pressed
void sigint_handler(int x){
endwin();
puts("Quit.");
exit(x);
}
void mouseinput(void){
MEVENT minput;
2019-07-30 15:50:57 -04:00
#ifdef PDCURSES
nc_getmouse(&minput);
#else
2019-05-13 09:58:19 -04:00
getmouse(&minput);
2019-07-30 15:50:57 -04:00
#endif
2019-05-13 09:58:19 -04:00
if( minput.y-4<size && minput.x-1<size2){
py=minput.y-4;
px=(minput.x-1);
}
else
return;
if(minput.bstate & BUTTON1_CLICKED)
ungetch('\n');
}
void help(void){
2020-05-18 14:59:29 -04:00
erase();
2019-05-13 09:58:19 -04:00
logo(0,0);
2020-05-18 14:59:29 -04:00
attron(A_BOLD);
mvprintw(3,0," **** THE CONTROLS ****");
2019-05-13 09:58:19 -04:00
mvprintw(8,0,"YOU CAN ALSO USE THE MOUSE!");
2020-05-18 14:59:29 -04:00
attroff(A_BOLD);
2019-05-13 09:58:19 -04:00
mvprintw(4,0,"RETURN/ENTER : Reveal");
2020-05-18 14:59:29 -04:00
mvprintw(5,0,"hjkl/ARROW KEYS : Move cursor");
mvprintw(6,0,"q : Quit");
2019-05-13 09:58:19 -04:00
mvprintw(7,0,"F1 & F2 : Help on controls & gameplay");
2020-05-18 14:59:29 -04:00
mvprintw(10,0,"Press a key to continue");
2019-05-13 09:58:19 -04:00
refresh();
2020-05-18 14:59:29 -04:00
getch();
2019-05-13 09:58:19 -04:00
erase();
}
void gameplay(void){
2020-05-18 14:59:29 -04:00
erase();
2019-05-13 09:58:19 -04:00
logo(0,0);
2020-05-18 14:59:29 -04:00
attron(A_BOLD);
mvprintw(3,0," **** THE GAMEPLAY ****");
attroff(A_BOLD);
2019-05-13 09:58:19 -04:00
mvprintw(4,0,"Click on a tile to see the gylph it contains,\n");
printw( "then try to find a matching gylph the same way.\n");
printw( "They form a pair only when you click a tile\n");
printw( "directly after the match. The game ends when \n");
printw( "you have found all the matching pairs.\n");
2020-05-18 14:59:29 -04:00
refresh();
getch();
erase();
2019-05-13 09:58:19 -04:00
}
int main(int argc, char** argv){
#ifndef Plan9
size=8;
#endif
2019-05-13 09:58:19 -04:00
if(argc>=2){
2020-05-18 14:59:29 -04:00
size=atoi(argv[1]);
if(size<3 || size>19){
fprintf(stderr,"3<=size<=19\n");
return EXIT_FAILURE;
}
if(!strcmp("help",argv[1])){
printf("Usage: %s [size]\n",argv[0]);
2019-05-13 09:58:19 -04:00
return EXIT_SUCCESS;
}
2020-05-18 14:59:29 -04:00
}
2019-05-13 09:58:19 -04:00
signal(SIGINT,sigint_handler);
2019-07-30 14:13:10 -04:00
srand(time(NULL)%UINT_MAX);
2019-05-13 09:58:19 -04:00
initscr();
2020-05-18 14:59:29 -04:00
mousemask(ALL_MOUSE_EVENTS,NULL);
noecho();
cbreak();
keypad(stdscr,1);
if(has_colors()){
start_color();
use_default_colors();
2019-05-13 09:58:19 -04:00
if( has_colors() ){
2020-05-18 14:59:29 -04:00
start_color();
use_default_colors();
init_pair(1,COLOR_YELLOW,-1);
init_pair(2,COLOR_GREEN,-1);
init_pair(3,COLOR_BLUE,-1);
init_pair(4,COLOR_CYAN,-1);
init_pair(5,COLOR_MAGENTA,-1);
init_pair(6,COLOR_RED,-1);
for(byte b=0;b<6;b++){
colors[b]=COLOR_PAIR(b+1);
}
2019-05-13 09:58:19 -04:00
}
2020-05-18 14:59:29 -04:00
}
2019-05-13 09:58:19 -04:00
else if(size>8)//big sizes depend on color display
#ifndef Plan9
2019-05-13 09:58:19 -04:00
size=8;
size2=size*2;
#endif
chtype board[size][size2];
2019-05-13 09:58:19 -04:00
bool show[size][size2];
2020-05-18 14:59:29 -04:00
int input;
2019-05-13 09:58:19 -04:00
time_t tstart,now;
Start:
tstart=time(NULL);
py=px=0;
fy=fx=-1;
curs_set(0);
memset(show,0,size*size2);
fill(board);
shuffle(board);
while(1){
erase();
logo(0,0);
draw(3,0,board,show);
refresh();
if(issolved(show))
break;
input = getch();
if( input==KEY_F(1) || input=='?' )
help();
if( input==KEY_F(2) )
gameplay();
if( input==KEY_MOUSE )
mouseinput();
if( (input=='k' || input==KEY_UP) && py>0)
py--;
if( (input=='j' || input==KEY_DOWN) && py<size-1)
py++;
if( (input=='h' || input==KEY_LEFT) && px>0)
px--;
if( (input=='l' || input==KEY_RIGHT) && px<size2-1)
px++;
if( input=='q')
sigint_handler(0);
if(input=='\n'){
if(fy!=-1 && board[py][px]==board[fy][fx] && !(fy==py && fx==px) )
show[py][px]=show[fy][fx]=1;
else{
fy=py;
fx=px;
}
}
}
now=time(NULL)-tstart;
mvprintw(size+7,0,"Time spent: %d:%2d:%2d",now/3600,(now%3600)/60,now%60);
mvprintw(size+5,0,"You solved it! Wanna play again?(y/n)");
curs_set(1);
input=getch();
if(input != 'N' && input != 'n' && input != 'q')
goto Start;
endwin();
return EXIT_SUCCESS;
}