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 }