pipe-game

Un jeu de cartes à piper les une dans les autres - retour accueil

git clone git://bebou.netlib.re/pipe-game
Log | Files | Refs | README |

interface.c (14942B)


      1 #define TB_IMPL
      2 #include "termbox2.h"
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <stdbool.h>
      6 
      7 #define LIST_SIZE 1000
      8 #define DISPLAY_SIZE 1000
      9 #define CMD_LINE_SIZE 100
     10 /* Le chiffre c'est des octets. Les caractères sont encodés sur un octet chacun ?
     11  * Donc si on met 5 la taille max serait 4 caractères ? */
     12 #define CARD_NAME_SIZE 25
     13 #define NB_PILES 6
     14 
     15 typedef struct {
     16 	int x;
     17 	int y;
     18 } coord;
     19 
     20 struct pile {
     21 	char  *name;
     22 	int    cardcount;
     23 	char **cards;
     24 	int    curline;
     25 	coord  begin;
     26 	coord  end;
     27 	struct pile *destleft;
     28 	struct pile *destright;
     29 };
     30 
     31 enum pileid { HAND, PLAYED, ARGS, PLAYEDARGS, PLAYEDENNEMY, PLAYEDENNEMYARGS };
     32 enum directions { UP, DOWN, LEFT, RIGHT };
     33 
     34 int max(int a, int b) { return a > b ? a : b; }
     35 int min(int a, int b) { return a < b ? a : b; }
     36 
     37 int nblines(char *str) {
     38 	int l=0;
     39 	for (int i = 0; str[i] != '\0'; i++)
     40 		if (str[i]=='\n') l++;
     41 	return l+1;
     42 }
     43 
     44 int hr(int coloffset, int lineoffset, int length, bool selected) {
     45 	int color=selected ? TB_DEFAULT : TB_WHITE;
     46 	for(int i=0;i<length;i++)
     47 		tb_printf(coloffset+i, lineoffset, color, TB_DEFAULT, "─");
     48 	return lineoffset+1;
     49 }
     50 
     51 void vr(int coloffset, int lineoffset, int length, bool selected) {
     52 	int color=selected ? TB_DEFAULT : TB_WHITE;
     53 	for (int i=0;i<length;i++)
     54 		tb_printf(coloffset,lineoffset+i, color, TB_DEFAULT, "│");
     55 }
     56 
     57 struct pile createpile(char *name) {
     58 	struct pile p;
     59 	p.cards=malloc(LIST_SIZE);
     60 	p.name=name;p.cardcount=0; p.curline=0;
     61 	return p;
     62 }
     63 
     64 void setpiledests(struct pile *p, struct pile *destleft, struct pile *destright) {
     65 	p->destleft=destleft;
     66 	p->destright=destright;
     67 }
     68 
     69 bool addcardtopile(char* cardname, struct pile* p, struct pile **piles) {
     70 	/*On quitte si l'argument est vide ou s'il contient un espace*/
     71 	/* strchr ne fonctionne pas avec utf-8 mais pour le moment rien
     72 	 * ne fonctionne en utf8 alors bon */
     73 	if(cardname[0]=='\0' || strchr(cardname,' ')!=NULL) return false;
     74 	if(p==piles[PLAYED]) addcardtopile("none",piles[PLAYEDARGS],piles);
     75 	if(p==piles[PLAYEDENNEMY]) addcardtopile("none",piles[PLAYEDENNEMYARGS],piles);
     76 	if( ( p==piles[PLAYEDARGS] || p==piles[PLAYEDENNEMYARGS] ) && strcmp(cardname,"none")!=0)
     77 		p->cards[p->cardcount-1]=cardname;
     78 	else {
     79 		p->cards[p->cardcount] = malloc(CARD_NAME_SIZE);
     80 		strcpy(p->cards[p->cardcount], cardname);
     81 		p->cardcount++;
     82 	}
     83 	p->curline=p->cardcount-1;
     84 	return true;
     85 }
     86 
     87 void removecardofpile(int cardposition, struct pile* p, struct pile **piles) {
     88 	if(p==piles[PLAYED]) {
     89 		if(strcmp(piles[PLAYEDARGS]->cards[cardposition],"none")!=0)
     90 			addcardtopile(piles[PLAYEDARGS]->cards[cardposition],piles[ARGS],piles);
     91 		removecardofpile(cardposition,piles[PLAYEDARGS],piles);
     92 	} else if (p==piles[PLAYEDENNEMY]) {
     93 		if(strcmp(piles[PLAYEDENNEMYARGS]->cards[cardposition],"none")!=0)
     94 			addcardtopile(piles[PLAYEDENNEMYARGS]->cards[cardposition],piles[ARGS],piles);
     95 		removecardofpile(cardposition,piles[PLAYEDENNEMYARGS],piles);
     96 	} else if( ( p==piles[PLAYEDARGS] || p==piles[PLAYEDENNEMYARGS] ) \
     97 	           && strcmp(p->cards[cardposition],"none")!=0) {
     98 		p->cards[cardposition]="none";
     99 		return;
    100 	}
    101 	p->cardcount--;
    102 	for(int i=cardposition;i<p->cardcount;i++)
    103 		p->cards[i]=p->cards[i+1];
    104 	if (p->curline>0)
    105 		p->curline--;
    106 }
    107 
    108 struct pile* mvcardup(struct pile* p, struct pile** piles, int direction, bool selection, int motion) {
    109 	int step = direction==UP ? -1 : 1 ;
    110 	if (p->curline+step >= 0 && p->curline+step < p->cardcount) {
    111 		if (selection) {
    112 			char* tmp;
    113 			tmp=p->cards[p->curline];
    114 			p->cards[p->curline]=p->cards[p->curline+step];
    115 			p->cards[p->curline+step]=tmp;
    116 		}
    117 		p->curline=p->curline+step;
    118 		return p;
    119 	}
    120 	if (motion!=TB_MOD_MOTION) {
    121 		if (p->curline+step < 0) {
    122 			if (selection) {
    123 				char* tmp;
    124 				tmp=p->cards[p->curline];
    125 				p->cards[p->curline]=p->cards[p->cardcount-1];
    126 				p->cards[p->cardcount-1]=tmp;
    127 			}
    128 			p->curline=p->cardcount-1;
    129 			return p;
    130 		}
    131 		if (p->curline+step == p->cardcount) {
    132 			if (selection) {
    133 				char* tmp;
    134 				tmp=p->cards[p->curline];
    135 				p->cards[p->curline]=p->cards[0];
    136 				p->cards[0]=tmp;
    137 			}
    138 			p->curline=0;
    139 			return p;
    140 		}
    141 	}
    142 	if (p==piles[HAND] && direction==DOWN && piles[ARGS]->cardcount>0)
    143 		return piles[ARGS];
    144 	else if (p==piles[ARGS] && direction==UP && piles[HAND]->cardcount>0)
    145 		return piles[HAND];
    146 	return p;
    147 }
    148 
    149 struct pile* mvcardlr(struct pile* p, struct pile** piles, bool selection, int direction) {
    150 	struct pile *newcurmenu=p;
    151 	newcurmenu = direction==LEFT ?  p->destleft : p->destright;
    152 	if(newcurmenu==NULL) { return p; }
    153 	if(selection) {
    154 		addcardtopile(p->cards[p->curline],newcurmenu,piles);
    155 		removecardofpile(p->curline,p,piles);
    156 	} else if ( newcurmenu->cardcount==0 ) {
    157 		newcurmenu=p;
    158 	}
    159 	if(p==piles[PLAYEDARGS] && piles[ARGS]->cardcount==0 && !selection && direction==RIGHT) { newcurmenu=piles[HAND]; }
    160 	return newcurmenu;
    161 }
    162 
    163 void updatecmd(char* cmd, struct pile p, struct pile parg) {
    164 	if (p.cardcount == 0 ) return;
    165 	strcat(cmd,"( cat ./");
    166 	strcat(cmd,p.cards[0]);
    167 	if(strcmp(parg.cards[0],"none")!=0) {
    168 		strcat(cmd," ");
    169 		strcat(cmd,parg.cards[0]);
    170 	}
    171 	for (int i=1;i<p.cardcount;i++) {
    172 		strcat(cmd," | \n./");
    173 		strcat(cmd,p.cards[i]);
    174 		if(strcmp(parg.cards[i],"none")!=0) {
    175 			strcat(cmd," ");
    176 			strcat(cmd,parg.cards[i]);
    177 		}
    178 	}
    179 	strcat(cmd," ) 2> /dev/null\n");
    180 }
    181 
    182 void updateinterncmd(char *res, const struct pile p) {
    183 	if (p.cardcount == 0 )
    184 		return;
    185 	for(int i=0;i<p.cardcount;i++) {
    186 		FILE *fp = fopen(p.cards[i], "r");
    187 		char line[CMD_LINE_SIZE];line[0]='\0';
    188 		while(fgets(line, sizeof(line), fp))
    189 			strcat(res, line);
    190 	}
    191 }
    192 
    193 void updateres(char *res, const char *cmd, FILE *fp) {
    194 	fp = popen(cmd,"r");
    195 	char line[CMD_LINE_SIZE];
    196 	while(fgets(line, sizeof(line), fp))
    197 		strcat(res, line);
    198 }
    199 
    200 void file2pile(FILE* fp, struct pile *p, struct pile **piles) {
    201 	char line[CARD_NAME_SIZE];
    202 	while (fgets(line, sizeof(line), fp)) {
    203 		/* Retire le retour à la ligne à la fin de line */
    204 		line[strcspn(line, "\n")] = '\0';
    205 		addcardtopile(line, p, piles);
    206 	}
    207 	p->curline=0;
    208 }
    209 
    210 coord displaybox(char* name, int coloffset, int lineoffset, int width, int length, bool selected) {
    211 	int color=selected ? TB_DEFAULT : TB_WHITE;
    212 	length<2 ? length=2 : length;
    213 	hr(coloffset+1,lineoffset,width-1,selected);
    214 	hr(coloffset+1,lineoffset+length,width-1,selected);
    215 	vr(coloffset,lineoffset+1,length-1,selected);
    216 	vr(coloffset+width,lineoffset+1,length-1,selected);
    217 	if(name) tb_printf(coloffset+2,lineoffset,color,TB_DEFAULT," %s ",name);
    218 	tb_print(coloffset,lineoffset,color,TB_DEFAULT,"╭");
    219 	tb_print(coloffset+width,lineoffset,color,TB_DEFAULT,"╮");
    220 	tb_print(coloffset,lineoffset+length,color,TB_DEFAULT,"╰");
    221 	tb_print(coloffset+width,lineoffset+length,color,TB_DEFAULT,"╯");
    222 	coord p; p.x=coloffset+width; p.y=lineoffset+length;
    223 	return p;
    224 }
    225 
    226 coord displaypile(struct pile *p, struct pile *curmenu, int coloffset, int lineoffset, bool selection) {
    227 	coloffset++;
    228 	int newlineoffset=lineoffset;
    229 	int maxwidth=CARD_NAME_SIZE+2; int maxlen=p->cardcount+1;
    230 	coord begin; begin.x=coloffset; begin.y=lineoffset;
    231 	coord end=displaybox(p->name, begin.x,begin.y,maxwidth,maxlen,p==curmenu);
    232 	p->begin=begin; p->end=end;
    233 	coloffset++; lineoffset++;
    234 	for (int i=0;i<p->cardcount;i++) {
    235 		char *name = strcmp(p->cards[i],"none")==0 ? " " : p->cards[i] ;
    236 		if (i==p->curline && p == curmenu ) {
    237 			int background = selection ? TB_BLUE : TB_WHITE ;
    238 			tb_printf(coloffset, lineoffset+i, TB_BLACK, background, name);
    239 		}
    240 		else
    241 			tb_printf(coloffset, lineoffset+i, TB_DEFAULT, TB_DEFAULT, name);
    242 		newlineoffset++;
    243 	}
    244 	return end;
    245 }
    246 
    247 coord displaytextblock(char* title, char *text, int coloffset, int lineoffset, int entity) {
    248 	coloffset++;lineoffset++;
    249 	coord p; int nbl=nblines(text);
    250 	int w=entity ? (CARD_NAME_SIZE+2)*2+1:CARD_NAME_SIZE+2;
    251 	p.y=nbl+lineoffset; p.x=w+coloffset;
    252 	p=displaybox(title,coloffset,lineoffset,w,nbl,false);
    253 	coloffset++; lineoffset++;
    254 	tb_printf(coloffset, lineoffset, TB_DEFAULT, TB_DEFAULT, text);
    255 	return p;
    256 }
    257 
    258 int debug(int l, struct pile curmenu,struct tb_event ev) {
    259 	tb_printf(0,l++,TB_DEFAULT,TB_DEFAULT,curmenu.name);
    260 	char str[100];sprintf(str,"%d",curmenu.cardcount);
    261 	tb_printf(0,l++,TB_DEFAULT,TB_DEFAULT,str);
    262 	char str2[100];
    263 	sprintf(str2,"%d",curmenu.curline);
    264 	tb_printf(0,l++,TB_DEFAULT,TB_DEFAULT,str2);
    265 	tb_printf(0,l++,0,0,"█");
    266 	tb_printf(0,l++,TB_DEFAULT,TB_DEFAULT,"touche█ %d, char %d, x %d, y %d\n",ev.key,ev.ch,ev.x,ev.y);
    267 	tb_printf(0,l++,TB_DEFAULT,TB_DEFAULT,"type %d, mod %d, a %d",ev.type,ev.mod,TB_MOD_MOTION);
    268 	return l;
    269 }
    270 
    271 int display(struct pile** piles, struct pile *curmenu, bool selection, char* cmd, char* res,
    272             char* intern, char* cmdennemy, char* resennemy, char* internennemy, char *player, char *ennemy) {
    273 	tb_clear();
    274 
    275 	coord pplayer=displaytextblock(NULL,player,0,0,1);
    276 	coord pennemy=displaytextblock(NULL,ennemy,pplayer.x+CARD_NAME_SIZE+3,0,1);
    277 	int y=max(pplayer.y,pennemy.y)+1;
    278 
    279 	coord p=displaypile(piles[PLAYEDARGS], curmenu, 0, y, selection);
    280 	coord p2=displaypile(piles[PLAYED], curmenu, p.x, y, selection);
    281  	coord p3=displaypile(piles[HAND], curmenu, p2.x, y, selection);
    282 	coord p4=displaypile(piles[ARGS], curmenu, p2.x, p3.y, selection);
    283 	coord p5=displaypile(piles[PLAYEDENNEMY], curmenu, p3.x, y, selection);
    284 	coord p6=displaypile(piles[PLAYEDENNEMYARGS], curmenu, p5.x, y, selection);
    285 	int m=max(max(p2.y,p4.y),p5.y);
    286 
    287 	p=displaytextblock("result",res,CARD_NAME_SIZE/2,m+2,0);
    288 	p=displaytextblock("sh commands",intern,CARD_NAME_SIZE/2,p.y,0);
    289 	p=displaytextblock("command",cmd,CARD_NAME_SIZE/2,p.y,0);
    290 
    291 	p=displaytextblock(NULL,"\
    292 * enter to select card\n\
    293 * arrows to move selection\n\
    294 * m to create arg \n\
    295 * e to end turn\n",p2.x+1,m+2,0);
    296 
    297 	coord p7=displaytextblock("result",resennemy,p3.x+CARD_NAME_SIZE/2,m+2,0);
    298 	p=displaytextblock("sh commands",internennemy,p3.x+CARD_NAME_SIZE/2,p7.y,0);
    299 	p=displaytextblock("command",cmdennemy,p3.x+CARD_NAME_SIZE/2,p.y,0);
    300 
    301 	return p.y+4;
    302 }
    303 
    304 
    305 int main(int argc, char **argv) {
    306 	tb_init();
    307 	tb_hide_cursor();
    308 	tb_set_input_mode(TB_INPUT_ESC | TB_INPUT_MOUSE);
    309 	struct tb_event ev;
    310 	coord prevpos;
    311 	struct pile *srcmenu; struct pile *destmenu;
    312 
    313 	char cmd[LIST_SIZE];    char cmdennemy[LIST_SIZE];
    314 	char res[LIST_SIZE];    char resennemy[LIST_SIZE];
    315 	char intern[LIST_SIZE]; char internennemy[LIST_SIZE];
    316 
    317 	char player[DISPLAY_SIZE]; char ennemy[DISPLAY_SIZE];
    318 
    319 	char line[100];
    320 	FILE *fp=fopen("player","r");
    321 	while (fgets(line, sizeof(line), fp)) {
    322 		strcat(player,line);
    323 	}
    324 	fp=fopen("ennemy","r");
    325 	while (fgets(line, sizeof(line), fp)) {
    326 		strcat(ennemy,line);
    327 	}
    328 
    329 	FILE *fp2, *fp3;
    330 
    331 	struct pile *piles[NB_PILES];
    332 	struct pile played=createpile("played");
    333 	struct pile hand=createpile("hand");
    334 	struct pile playedargs=createpile("playedargs");
    335 	struct pile args=createpile("args");
    336 	struct pile playedennemy=createpile("playedennemy");
    337 	struct pile playedennemyargs=createpile("playedennemyargs");
    338 	setpiledests(&hand,&played,&playedennemy);
    339 	setpiledests(&played,NULL,&hand);
    340 	setpiledests(&args,&playedargs,&playedennemyargs);
    341 	setpiledests(&playedennemy,&hand,NULL);
    342 	setpiledests(&playedennemyargs,&args,NULL);
    343 	setpiledests(&playedargs,NULL,&args);
    344 	piles[HAND]=&hand;piles[PLAYED]=&played;
    345 	piles[ARGS]=&args;piles[PLAYEDARGS]=&playedargs;
    346 	piles[PLAYEDENNEMY]=&playedennemy;
    347 	piles[PLAYEDENNEMYARGS]=&playedennemyargs;
    348 
    349 	file2pile(stdin, &hand, piles);
    350 	addcardtopile(hand.cards[0],&playedennemy,piles);
    351 
    352 	bool selection=false;
    353 	bool quit=false;
    354 	struct pile *curmenu=&hand;
    355 
    356 	while(!quit) {
    357 		cmd[0]='\0';res[0]='\0';intern[0]='\0';
    358 		cmdennemy[0]='\0';resennemy[0]='\0';internennemy[0]='\0';
    359 		updatecmd(cmd, played, playedargs);
    360 		updatecmd(cmdennemy, playedennemy, playedennemyargs);
    361 		updateres(res, cmd, fp2);
    362 		updateres(resennemy, cmdennemy, fp3);
    363 		updateinterncmd(intern, played);
    364 		updateinterncmd(internennemy, playedennemy);
    365 
    366 		int l=display(piles,curmenu,selection,cmd,res,intern,cmdennemy,resennemy,internennemy,player,ennemy);
    367 		debug(l++,*curmenu,ev);
    368 		tb_present();
    369 		tb_poll_event(&ev);
    370 		switch(ev.type) {
    371 			case 1:
    372 				switch(ev.key) {
    373 					/* up */
    374 					case 65517:
    375 						curmenu=mvcardup(curmenu,piles,UP,selection,ev.mod);
    376 						break;
    377 					/* down */
    378 					case 65516:
    379 						curmenu=mvcardup(curmenu,piles,DOWN,selection,ev.mod);
    380 						break;
    381 					/* -> */
    382 					case 65514:
    383 						curmenu=mvcardlr(curmenu, piles, selection, RIGHT);
    384 						break;
    385 					/* <- */
    386 					case 65515:
    387 						curmenu=mvcardlr(curmenu, piles, selection, LEFT);
    388 						break;
    389 					case 13:
    390 						selection=!selection;
    391 						break;
    392 					case 0:
    393 						switch(ev.ch) {
    394 							case 113: /*q*/
    395 								quit=true;
    396 								break;
    397 							case 101: /*e*/
    398 								tb_shutdown();
    399 								printf(res);
    400 								return 0;
    401 								break;
    402 							case 109: /*m*/
    403 								;bool created=false;
    404 								char *token=strtok(res,"\n");
    405 								while(token != NULL) {
    406 									if(addcardtopile(token,&args,piles)>0) created=true;
    407 									token=strtok(NULL,"\n");
    408 								}
    409 								if(created) {
    410 									for(int i=0;i<=played.cardcount;i++)
    411 										removecardofpile(i,&played,piles);
    412 									curmenu=&hand;
    413 								}
    414 								break;
    415 							default:
    416 								break;
    417 						}
    418 					default:
    419 						break;
    420 					}
    421 			break;
    422 			case 3: /*Mouse*/
    423 				switch(ev.key) {
    424 					case 65512: /*MouseLeft*/
    425 						for(int i=0;i<NB_PILES;i++) {
    426 							if( piles[i]->begin.x < ev.x && ev.x < piles[i]->end.x ) {
    427 								if(ev.mod==TB_MOD_MOTION) {
    428 									selection=true; destmenu=piles[i];
    429 									if(destmenu==piles[HAND] && piles[ARGS]->begin.y<ev.y && ev.y<piles[ARGS]->end.y)
    430 										destmenu=piles[ARGS];
    431 									if(destmenu!=srcmenu && (destmenu==srcmenu->destleft || destmenu==srcmenu->destright) ) {
    432 											if(ev.x<prevpos.x)
    433 												curmenu=mvcardlr(srcmenu, piles, selection, LEFT);
    434 											else if (ev.x>prevpos.x)
    435 												curmenu=mvcardlr(srcmenu, piles, selection, RIGHT);
    436 											srcmenu=curmenu;
    437 									} else if(ev.y>(curmenu->begin.y+curmenu->curline+1))
    438 										mvcardup(curmenu,piles,DOWN,selection,ev.mod);
    439 									else if (ev.y<(curmenu->begin.y+curmenu->curline+1))
    440 										mvcardup(curmenu,piles,UP,selection,ev.mod);
    441 								} else {
    442 									destmenu = piles[i]->cardcount>0 ? piles[i] : curmenu;
    443 									if(destmenu==piles[HAND] \
    444 										&& piles[ARGS]->begin.y < ev.y && ev.y < piles[ARGS]->end.y \
    445 										&& piles[ARGS]->cardcount>0 ) { destmenu=piles[ARGS]; }
    446 									destmenu->curline = destmenu==piles[ARGS] ? ev.y-1-piles[HAND]->end.y : min(ev.y-1,destmenu->cardcount-1);
    447 									selection=false;
    448 									curmenu=destmenu; srcmenu=destmenu;
    449 								}
    450 								break;
    451 							}
    452 						}
    453 						prevpos.x=ev.x;prevpos.y=ev.y;
    454 						break;
    455 					case 65509: /*MouseRelease*/
    456 						selection=false;
    457 						break;
    458 					case 65508: /*MouseWheelUp*/
    459 						curmenu=mvcardup(curmenu,piles,UP,selection,ev.mod);
    460 						break;
    461 					case 65507: /*MouseWheelDown*/
    462 						curmenu=mvcardup(curmenu,piles,DOWN,selection,ev.mod);
    463 						break;
    464 				}
    465 			}
    466 	}
    467 
    468 	tb_shutdown();
    469 
    470 	return 0;
    471 }