diff --git a/defs.h b/defs.h index 0ad643a..d5e34e2 100644 --- a/defs.h +++ b/defs.h @@ -49,6 +49,7 @@ #define TEXTSIZE_LEVEL 32 #define TEXTSIZE_LIFE 36 #define TEXTSIZE_BOMB 36 +#define TEXTSIZE_POKER 40 #define TEXTSIZE_HURRY 50 #define TEXTSIZE_PAUSED 50 #define TEXTSIZE_GAMEOVER 50 @@ -62,11 +63,13 @@ #define MULTIDELAY 50 #define HURRYDELAY 50 #define LIFEDELAY 50 +#define POKERMSGDELAY 80 #define LEVELWINDELAY 80 #define DIEDELAY 80 #define HELPDELAY 80 #define LEVELDELAY 100 #define GAMEOVERDELAY 200 +#define POKERDELAY 150 @@ -109,6 +112,8 @@ #define MASKOFFSETSLAMX 1 #define MASKOFFSETSLAMY -17 +#define POKERWAITTIME 150 // how long to display poker msg + #define CANNONSIZE 10 @@ -165,6 +170,8 @@ #define MAXHELP 5 #define MAXTILEFRAMES 10 // max number of frames for animated tiles +#define MAXCARDS 5 // how many cards a player can have + // Fixed text buffer sizes #define BUFLEN 512 #define MIDBUFLEN 64 @@ -180,7 +187,8 @@ #define FT_PERM 2 #define FT_TEMP 3 #define FT_GEM 4 -#define FT_OTHER 5 +#define FT_CARD 5 +#define FT_OTHER 6 // monster types #define MT_MONSTER 1 @@ -235,13 +243,31 @@ #define FX_ENGAGED 38 #define FX_FLOOD 39 +// card suits +#define CS_HEART 1 +#define CS_DIAMOND 2 +#define CS_SPADE 3 +#define CS_CLUB 4 + +// poker effects +#define PE_HIGHCARD 1 +#define PE_PAIR 2 +#define PE_TWOPAIR 3 +#define PE_TRIPLE 4 +#define PE_STRAIGHT 5 +#define PE_FLUSH 6 +#define PE_FULLHOUSE 7 +#define PE_FOUR 8 +#define PE_STRAIGHTFLUSH 9 +#define PE_ROYALFLUSH 10 + // Slope types #define S_NOTSOLID 0 #define S_SOLID 1 #define S_SLOPE 2 // Sprite types -#define MAXPTYPES 116 +#define MAXPTYPES 118 #define P_PLAYER 0 #define P_RAT 1 #define P_CHEESE 2 @@ -363,12 +389,27 @@ #define P_CARDCJ 113 #define P_CARDCQ 114 #define P_CARDCK 115 +#define P_MOVINGCARD 116 +#define P_FIVECARDS 117 // cards #define CARDFONTX 4 #define CARDFONTY 6 #define CARDFONTSIZE 10 +// card display (in top left of main screen) +#define CARDX 20 +#define CARDY 55 + +// how fast cards move towards the corner +#define CARDSPEED 8 +#define FIVECARDSPEED 8 + +// how many cards in a deck +#define DECKSIZE 52 + +#define SHUFFLEQUALITY 100 + // powerups #define PW_NONE 0 #define PW_BOXING 1 // boxing glove @@ -416,6 +457,7 @@ #define LV_CLOUDLOOP 6 // cloud looping #define LV_NEXTLEV 7 // cloud done , nextlevel() in 5 seconds #define LV_GAMEOVER 8 // No lives left. +#define LV_DOPOKER 9 // Got a full set of cards! // movement types #define MV_NONE 0 // didn't move @@ -595,10 +637,14 @@ typedef struct sprite_s { int powerup; // what temp powerup does the player have? int permspeed; // got the permenant speed powerup? + int permnumnets; // got the permenant numnets powerup? + int permbignet; // got the permenant bignets powerup? + int permsticky; // got the permenant sticky net powerup? int ontramp; // on a trampoline? int trampx; // x,y coords for trampoline we are/were on int trampy; // + // player permenant powerups int armour; // does the player have armour? int gemboost; // how many extra gems do you get in a bonus @@ -606,6 +652,11 @@ typedef struct sprite_s { int hasbell; // got a bell ? int hasmask; // got scuba mask? + // player cards + int numcards; + int card[MAXCARDS]; + int usedcard[MAXCARDS]; + // monster only int iced; // turned to ice? SDL_Surface *iceimg; // Image to blit for ice @@ -707,6 +758,9 @@ extern char *deathtext[]; extern char *bifftext[]; extern spriteinfo_t spriteinfo[]; +extern int curcard; +extern int deck[]; + extern char *datadir; #endif diff --git a/edit.c b/edit.c index a3e4b5f..4234308 100644 --- a/edit.c +++ b/edit.c @@ -1044,6 +1044,8 @@ int isplacablesprite(int sid) { case P_METEOR: case P_LIFE: case P_BIGSPEED: + case P_MOVINGCARD: + case P_FIVECARDS: return B_FALSE; } diff --git a/globals.h b/globals.h index 1f8f066..b65ec1e 100644 --- a/globals.h +++ b/globals.h @@ -13,6 +13,9 @@ spriteinfo_t spriteinfo[MAXPTYPES]; char *datadir; +int curcard; +int deck[DECKSIZE]; + SDL_Surface *levelbg; // level background image SDL_Surface *temps; // temporary surface diff --git a/rc.c b/rc.c index 12c4d6c..78231a8 100644 --- a/rc.c +++ b/rc.c @@ -36,8 +36,11 @@ int sprayalpha; // for spray effect SDL_Surface *pausedtext, *pausedshadow; int paused; + //tiletype_t fakeblock; +int skiplevels = 0; + /* the order in which fruit will appear */ int fruittypes[] = { @@ -78,6 +81,8 @@ int skipto = -1; // which level to skip to level_t *curlevel; int levelcompletetime = -1; +int oldlevelcomplete = -1; + sprite_t *sprite = NULL; /* main sprite list */ sprite_t *player; sprite_t *lastsprite; @@ -85,6 +90,9 @@ sprite_t *lastsprite; sprite_t *lastmet; +int pokereffect = -1; +int pokerpoints = 0; + SDL_Color red = {255, 0, 0, 0}; SDL_Color orange = {255, 167, 88, 1}; @@ -228,6 +236,8 @@ int main (int argc, char **argv) { exit(1); } + shufflecards(); + playmusic(normalmusic); if (loadlevel(curworld,curlevelnum, B_TRUE)) { return 1; @@ -248,10 +258,6 @@ int main (int argc, char **argv) { - - - - /* generate images for "PAUSED" text */ pausedtext = TTF_RenderText_Solid(font[TEXTSIZE_PAUSED], "PAUSED", yellow); pausedshadow = TTF_RenderText_Solid(font[TEXTSIZE_PAUSED], "PAUSED", black); @@ -339,11 +345,25 @@ int main (int argc, char **argv) { } - if (!paused) { + if ((!paused) && (!levelcomplete != LV_DOPOKER)) { if (keys[SDLK_q]) { gtime = nexthurryup-1; //gtime = nexthurryup+14; } + if (keys[SDLK_i]) { + if (player->numcards == 0) { + gaincard(player, getrandomcard()); + gaincard(player, getrandomcard()); + gaincard(player, getrandomcard()); + gaincard(player, getrandomcard()); + /* + gaincard(player, P_CARDD4); + gaincard(player, P_CARDD5); + gaincard(player, P_CARDS8); + gaincard(player, P_CARDH8); + */ + } + } if (keys[SDLK_l]) { if (toggletimer == 0) { addscore(player, 100001); @@ -623,8 +643,18 @@ int main (int argc, char **argv) { } } - // move sprites - moveallsprites(); + if (levelcomplete == LV_DOPOKER) { + // only fivecards sprite can move + sprite_t *this; + for (this = sprite; this ; this = this->next) { + if (this->id == P_FIVECARDS) { + movesprite(this); + } + } + } else { // all other states... + // move sprites + moveallsprites(); + } // animate text movetext(); @@ -661,6 +691,8 @@ int main (int argc, char **argv) { checkwrap(s); } break; + case LV_DOPOKER: // do nothing + break; } } @@ -691,14 +723,18 @@ int main (int argc, char **argv) { } } - checkcollideall(); + if (levelcomplete != LV_DOPOKER) { + checkcollideall(); + } } - drawnetting(player); + if (levelcomplete != LV_DOPOKER) { + drawnetting(player); + } - if (player->powerup == PW_CANNONFIRE) { // cannon firing + if ((levelcomplete != LV_DOPOKER) && (player->powerup == PW_CANNONFIRE)) { // cannon firing if (timer % 2 == 0) { int found; sprite_t *s; @@ -770,13 +806,34 @@ int main (int argc, char **argv) { } } - } + } // end cannon effect // draw sprites - drawallsprites(); + if (levelcomplete != LV_DOPOKER) { + drawallsprites(); + } + + if (levelcomplete == LV_DOPOKER) { + SDL_Rect area; + sprite_t *this; + + area.x = 0; + area.y = 0; + area.w = 640; + area.h = 480; + // clear screen + SDL_FillRect(screen, &area, SDL_MapRGB(screen->format,black.r,black.g,black.b)); + + // only fivecards sprite is drawn + for (this = sprite; this ; this = this->next) { + if (this->id == P_FIVECARDS) { + drawsprite(this); + } + } + } /* draw text */ drawtext(); @@ -802,6 +859,7 @@ int main (int argc, char **argv) { } if (!paused) { + /* is screen shaking? */ if (player->powerup == PW_BOMB) { if (timer % 5 == 0) { @@ -1093,7 +1151,17 @@ void nextlevel(void) { player->slamming = B_FALSE; player->jumping = B_FALSE; player->netcaught = 0; - player->powerup = B_FALSE; + + // remove powerup, phone is a special case + if (player->powerup == PW_PHONE) { + skiplevels--; +printf("%d levels left to skip\n",skiplevels); + if (skiplevels <= 0) { + player->powerup = B_FALSE; + } + } else { + player->powerup = B_FALSE; + } // add initial fading cloud @@ -1397,6 +1465,8 @@ void checkcollide(sprite_t *s) { else if (s->caughtby) continue; else if (s2->caughtby) continue; else if (s2->teleporting) continue; + else if (iseffect(s2->id)) continue; + keepchecking = B_TRUE; @@ -1822,6 +1892,31 @@ if (s->id == P_PUFF) printf("PUFF WITH DOOMCOUNT!\n"); if (s->id == P_PUFF) { if (s->timer3 >= 0) { sprite_t *newsp; + + // if player already has this, and no cards already on screen, + // we get a card instead + if ((isfruit(s->timer3) == FT_PERM) && haspowerup(player, s->timer3)) { + sprite_t *search; + int found; + found = B_FALSE; + + for (search = sprite; search ; search = search->next) { + if (iscard(search->id)) { + found = B_TRUE; + break; + } + // if it's a puff that will become a card... + if ((search->id == P_PUFF) && (iscard(search->timer3))) { + found = B_TRUE; + break; + } + } + + if (!found) { + s->timer3 = getrandomcard(); + } + } + newsp = addsprite(s->timer3, s->x,s->y,s->name ); // is it a boss? if so update boss pointer switch (s->timer3) { @@ -1862,6 +1957,87 @@ if (s->id == P_PUFF) printf("PUFF WITH DOOMCOUNT!\n"); } } } + } else if (s->id == P_MOVINGCARD) { + // timer1 is the actual cardid + // timer2 is the target x position + // timer3 is the target y position + // + // move towards end position + movetostart(s, s->timer2, s->timer3, CARDSPEED, CARDSPEED); + + // are we there yet? + if ((s->x == s->timer2) && (s->y == s->timer3)) { + gaincard(player, s->timer1); + s->dead = D_FINAL; + } + } else if (s->id == P_FIVECARDS) { + // are we there yet? + if ((s->x == 320) && (s->y == 240 )) { + if (s->timer2 == 0) { + int i; + SDL_Surface *blackness, *cardimg; + SDL_Rect area; + + s->timer2 = -1; //this means we are counting down + s->timer1 = POKERWAITTIME; + + + // hide non-used cards + cardimg = imageset[P_FIRSTCARD].img[F_WALK1]; + area.x = 0; + area.y = 0; + area.w = cardimg->w; + area.h = cardimg->h; + + // create semi-transparent black surface the size of a card + blackness = SDL_CreateRGBSurface(SDL_SWSURFACE, + cardimg->w, cardimg->h, + screen->format->BitsPerPixel, screen->format->Rmask, + screen->format->Gmask,screen->format->Bmask, + screen->format->Amask); + SDL_FillRect(blackness, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); + SDL_SetAlpha(blackness, SDL_SRCALPHA, 200); + + + for (i = 0; i < player->numcards; i++) { + if (player->usedcard[i] == B_FALSE) { + // hide it + //SDL_FillRect(s->img, &area, SDL_MapRGB(screen->format, 0, 0, 0)); + SDL_BlitSurface(blackness, NULL, s->img, &area); + } + + area.x += (cardimg->w + 2); + } + SDL_FreeSurface(blackness); + + + } else { + s->timer1--; + if (s->timer1 == 0) { + int i; + // die + s->dead = D_FINAL; + // restore state + levelcomplete = oldlevelcomplete; + + // do effect! + dopokereffect(player,pokereffect); + + // clear player cards + for (i = 0; i < MAXCARDS; i++) { + player->card[i] = -1; + } + player->numcards = 0; + + // shuffle cards + shufflecards(); + + } + } + } else { + // move towards centre of the screen + movetostart(s, 320, 240, FIVECARDSPEED, FIVECARDSPEED); + } } else if (s->id == P_MASK) { // mask effect if (player->slamming) { s->y = player->y + MASKOFFSETSLAMY; @@ -3522,7 +3698,7 @@ void drawscore(void) { area.h = 0; SDL_BlitSurface(score, NULL, screen, &area); SDL_FreeSurface(score); - /* score */ + /* text */ score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], tempm, white); area.x = 320-(score->w/2); area.y = 5; @@ -3530,6 +3706,22 @@ void drawscore(void) { area.h = 0; SDL_BlitSurface(score, NULL, screen, &area); SDL_FreeSurface(score); + + + // cards + if (levelcomplete != LV_DOPOKER) { + area.x = 20; + area.y = 55; + area.w = 0; + area.h = 0; + for (i = 0; i < player->numcards; i++) { + SDL_Surface *cardimg; + cardimg = imageset[player->card[i]].img[F_WALK1]; + SDL_BlitSurface(cardimg, NULL, screen, &area); + area.x += (cardimg->w + 2); + } + } + } void drawtext(void) { @@ -4379,10 +4571,6 @@ void dogravity(sprite_t *s) { } } - // if player already has this, we get a card instead - if (haspowerup(player, s2->willbecome)) { - s2->willbecome = getrandomcard(); - } } } else if (player->powerup == PW_MACE) { s2->willbecome = P_DIAMOND; @@ -4823,6 +5011,7 @@ int dofruiteffect(sprite_t *s) { addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY); // set powerup player->powerup = PW_PHONE; + skiplevels = 1; // kill all enemies for (s2 = sprite; s2 ; s2 = nexts) { nexts = s2->next; @@ -4931,10 +5120,35 @@ int dofruiteffect(sprite_t *s) { addoutlinetext(320,240,TEXTSIZE_HELP, s->name, &white,&black,HELPDELAY); return B_TRUE; } else if (iscard(s->id)) { - // TODO: handle cards - sprintf(tempm, getcardname(s->id)); - addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY); - // TODO: add a "card" effect, move it slowly towards the corner. + if (player->numcards < MAXCARDS) { + sprite_t *newc; + int cardwidth,cardheight; + + // TODO: play sound + + + // show text + sprintf(tempm, getcardname(s->id)); + addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY); + + // add a "card" effect. it will move slowly towards the corner. + newc = addsprite(P_MOVINGCARD,s->x, s->y, "moving_card"); + + // timer1 is the actual cardid + // timer2 is the target x position + // timer3 is the target y position + cardwidth = imageset[P_FIRSTCARD].img[F_WALK1]->w; + cardheight = imageset[P_FIRSTCARD].img[F_WALK1]->h; + newc->timer1 = s->id; + newc->timer2 = CARDX + (player->numcards * (cardwidth+2)) + (cardwidth/2); + newc->timer3 = CARDY + cardheight; + + // set image + newc->img = imageset[s->timer1].img[F_WALK1]; + } else { + // is this possible?! + addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, "Full cards!",&red,&black,POINTSDELAY); + } return B_TRUE; } else if (isflower(s->id)) { int xx; @@ -5167,20 +5381,26 @@ void channeldone(int channel) { // move player towards new position void movetostart(sprite_t *p, int dstx, int dsty, double xspeed, double yspeed) { + double ang,xs,ys; + // figure out angle to player + ang = atan2(dsty - p->y, dstx - p->x); + xs = (cos(ang) * xspeed); + ys = (sin(ang) * yspeed); + if (p->x < dstx) { - p->x += xspeed; + p->x += xs; if (p->x > dstx) p->x = dstx; } if (p->x > dstx) { - p->x -= xspeed; + p->x += xs; if (p->x < dstx) p->x = dstx; } if (p->y < dsty) { - p->y += yspeed; + p->y += ys; if (p->y > dsty) p->y = dsty; } if (p->y > dsty) { - p->y -= yspeed; + p->y += ys; if (p->y < dsty) p->y = dsty; } } @@ -5723,3 +5943,588 @@ int haspowerup(sprite_t *s, int pid) { } return B_FALSE; } + +void gaincard(sprite_t *s, int cardid) { + int i; + + // just in case + if (s->numcards >= MAXCARDS) return; + + // gain the card + s->card[s->numcards] = cardid; + s->numcards++; + + + // check for a full hand of cards + if (s->numcards == MAXCARDS) { + int cardwidth,cardheight; + SDL_Rect area; + sprite_t *newsp; + + cardwidth = imageset[P_FIRSTCARD].img[F_WALK1]->w; + cardheight = imageset[P_FIRSTCARD].img[F_WALK1]->h; + + // remember old level state + oldlevelcomplete = levelcomplete; + // change state to LV_CARDCOMPLETE + // (in this state, everything is frozen ) + levelcomplete = LV_DOPOKER; + + + // generate FIVECARDS sprite + newsp = addsprite(P_FIVECARDS, CARDX, CARDY, "fivecards"); + + // create blank image + newsp->img = SDL_CreateRGBSurface(SDL_SWSURFACE, + (cardwidth+2)*MAXCARDS, cardheight, + screen->format->BitsPerPixel, screen->format->Rmask, + screen->format->Gmask,screen->format->Bmask, + screen->format->Amask); + SDL_FillRect(newsp->img, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); + // fill in the cards + area.x = 0; + area.y = 0; + area.w = 0; + area.h = 0; + for (i = 0; i < player->numcards; i++) { + SDL_Surface *cardimg; + cardimg = imageset[player->card[i]].img[F_WALK1]; + if (cardimg == NULL){ + printf("ERROR! Card image is null!!\n"); + fflush(stdout); + } + SDL_BlitSurface(cardimg, NULL, newsp->img, &area); + area.x += (cardimg->w + 2); + } + + + + // adjust x value so we can use drawsprite() + newsp->x += (newsp->img->w / 2); + newsp->y += (newsp->img->h); + + // figure out what happened + pokereffect = getpokereffect(player); + + // display BIG message + addoutlinetext(320,190,TEXTSIZE_POKER,getpokermsg(pokereffect),&green, &black, POKERDELAY); + + } +} + + +// figure out what poker effect to apply and set variables +// also record which cards were used in pl->usedcards +int getpokereffect(sprite_t *pl) { + int i, c, count, curval, val, suit, found; + // default + pokerpoints = 0; + + /// mark all player cards as unused + for (c = 0; c < MAXCARDS; c++) { + pl->usedcard[c] = B_FALSE; + } + + + // * check for royal straight flush (perm trophy) + // for each card, count up from here + for (i = 0; i < MAXCARDS; i++) { + count = 1; + val = getcardvalue(pl->card[i]); + suit = getcardsuit(pl->card[i]); + curval = val; + found = B_TRUE; + // start at this card + while (found && count < 5) { + found = B_FALSE; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardsuit(pl->card[c]) == suit) { // same suit? + if (getcardvalue(pl->card[c]) == curval + 1) { + curval++; + count++; + found = B_TRUE; + } + } + } + } + } + // got it? + if (count >= 5) { + if (curval == 13) { // last card was a king + // GOT IT! + /// mark all player cards as USED + for (c = 0; c < MAXCARDS; c++) { + pl->usedcard[c] = B_TRUE; + } + return PE_ROYALFLUSH; + } + } + } + + + // * check for straight flush (skip 7 levels) + + for (i = 0; i < MAXCARDS; i++) { + count = 1; + val = getcardvalue(pl->card[i]); + suit = getcardsuit(pl->card[i]); + curval = val; + found = B_TRUE; + // start at this card + while (found && count < 5) { + found = B_FALSE; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardsuit(pl->card[c]) == suit) { // same suit? + if (getcardvalue(pl->card[c]) == curval + 1) { + curval++; + count++; + found = B_TRUE; + } + } + } + } + } + // got it? + if (count >= 5) { + // GOT IT! + /// mark all player cards as USED + for (c = 0; c < MAXCARDS; c++) { + pl->usedcard[c] = B_TRUE; + } + return PE_STRAIGHTFLUSH; + } + } + + + + // * check for four of a kind (perm 4 nets ) + for (i = 0; i < MAXCARDS; i++) { + val = getcardvalue(pl->card[i]); + count = 1; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardvalue(pl->card[c]) == val ) { + count++; + } + } + } + // got it? + if (count >= 4) { + // GOT IT! + /// mark all player cards with correct value as USED + for (c = 0; c < MAXCARDS; c++) { + if (getcardvalue(pl->card[c]) == val) { + pl->usedcard[c] = B_TRUE; + } + } + return PE_FOUR; + } + } + + + // * check for full house (perm bignet ) + for (i = 0; i < MAXCARDS; i++) { + val = getcardvalue(pl->card[i]); + count = 1; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardvalue(pl->card[c]) == val ) { + count++; + } + } + } + // got it? + if (count >= 3) { + int ii, val2,cc,count2; + // got a triple with this card - now look for doubles + + for (ii = 0; ii < MAXCARDS; ii++) { + val2 = getcardvalue(pl->card[ii]); + if (val2 != val) { // must be a DIFFERENT value! + count2 = 1; + for (cc = 0; cc < MAXCARDS; cc++) { + if (cc != ii) { + if (getcardvalue(pl->card[cc]) == val2 ) { + count2++; + } + } + } + // got it? + if (count2 >= 2) { + // GOT IT! - double with this one + /// mark all player cards as USED + for (c = 0; c < MAXCARDS; c++) { + pl->usedcard[c] = B_TRUE; + } + return PE_FULLHOUSE; + + } + } + } + } + } + + + + // * check for flush (skip 5 levels ) + for (i = 0; i < MAXCARDS; i++) { + suit = getcardsuit(pl->card[i]); + count = 1; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardsuit(pl->card[c]) == suit ) { + count++; + } + } + } + // got it? + if (count >= 5) { + // GOT IT! + /// mark all player cards as USED + for (c = 0; c < MAXCARDS; c++) { + pl->usedcard[c] = B_TRUE; + } + return PE_FLUSH; + } + } + + + + // * check for straight (perm honey) + for (i = 0; i < MAXCARDS; i++) { + count = 1; + val = getcardvalue(pl->card[i]); + suit = getcardsuit(pl->card[i]); + curval = val; + found = B_TRUE; + // start at this card + while (found && count < 5) { + found = B_FALSE; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardvalue(pl->card[c]) == curval + 1) { + curval++; + count++; + found = B_TRUE; + } + } + } + } + // got it? + if (count >= 5) { + // GOT IT! + /// mark all player cards as USED + for (c = 0; c < MAXCARDS; c++) { + pl->usedcard[c] = B_TRUE; + } + return PE_STRAIGHT; + } + } + + + // * check for triple (skip 3 levels ) + for (i = 0; i < MAXCARDS; i++) { + val = getcardvalue(pl->card[i]); + count = 1; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardvalue(pl->card[c]) == val ) { + count++; + } + } + } + // got it? + if (count >= 3) { + // GOT IT! + /// mark all player cards with correct value as USED + for (c = 0; c < MAXCARDS; c++) { + if (getcardvalue(pl->card[c]) == val) { + pl->usedcard[c] = B_TRUE; + } + } + return PE_TRIPLE; + } + } + + + // * check for two pair (value * 2000 for each card in pair ) + for (i = 0; i < MAXCARDS; i++) { + val = getcardvalue(pl->card[i]); + count = 1; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardvalue(pl->card[c]) == val ) { + count++; + } + } + } + // got it? + if (count >= 2) { + int ii, val2,cc,count2; + // got a pair with this card - now look for another one + + for (ii = 0; ii < MAXCARDS; ii++) { + val2 = getcardvalue(pl->card[ii]); + if (val2 != val) { // must be a DIFFERENT value! + count2 = 1; + for (cc = 0; cc < MAXCARDS; cc++) { + if (cc != ii) { + if (getcardvalue(pl->card[cc]) == val2 ) { + count2++; + } + } + } + // got it? + if (count2 >= 2) { + // GOT IT! - double with this one + /// mark all player cards as USED and assign points + pokerpoints = 0; + for (c = 0; c < MAXCARDS; c++) { + int thisval; + thisval = getcardvalue(pl->card[c]); + if ((thisval == val) || (thisval == val2)) { + pokerpoints += (thisval * 2000); + pl->usedcard[c] = B_TRUE; + } + } + return PE_TWOPAIR; + + } + } + } + } + } + + + // * check for pair (value * 2000 for each card in pair ) + for (i = 0; i < MAXCARDS; i++) { + val = getcardvalue(pl->card[i]); + count = 1; + for (c = 0; c < MAXCARDS; c++) { + if (c != i) { + if (getcardvalue(pl->card[c]) == val ) { + count++; + } + } + } + // got it? + if (count >= 2) { + // GOT IT! + // assign points and + // mark all player cards with correct value as USED + pokerpoints = 0; + for (c = 0; c < MAXCARDS; c++) { + int thisval; + thisval = getcardvalue(pl->card[c]); + if (thisval == val) { + pokerpoints += (thisval * 2000); + pl->usedcard[c] = B_TRUE; + } + } + return PE_PAIR; + } + } + + + + // * default is high card (value * 1000) + // find highest card + count = -1;// use this to track highest card index + curval = -1; + for (i = 0; i < MAXCARDS; i++) { + val = getcardvalue(pl->card[i]); + if (val > curval) { + curval = val; + count = i; + } + } + // assign points + pokerpoints = curval * 1000; + + // mark used card + for (c = 0; c < MAXCARDS; c++) { + if (c == count) { + pl->usedcard[c] = B_TRUE; + } else { + pl->usedcard[c] = B_FALSE; + } + } + return PE_HIGHCARD; +} + +// actually apply the current poker effect (in global "pokereffect") +void dopokereffect(sprite_t *pl, int effect) { + char tempmsg[BUFLEN]; + sprite_t *s2, *nexts; + + switch (effect) { + case PE_HIGHCARD: + case PE_TWOPAIR: + case PE_PAIR: + // points + addscore(pl, pokerpoints); + sprintf(tempmsg, "%d",pokerpoints); + addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY); + break; + case PE_TRIPLE: + // skip 3 levels + sprintf(tempmsg, "Skip 3 levels!"); + addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY); + // set powerup + player->powerup = PW_PHONE; + skiplevels = 2; + // kill all enemies + for (s2 = sprite; s2 ; s2 = nexts) { + nexts = s2->next; + if (isbullet(s2->id) || ismonster(s2->id)) { + s2->dead = D_FINAL; + + if (s2->caughtby) { + s2->caughtby = NULL; + player->netcaught--; + } + } + } + // call in cloud immediately + levelcomplete = LV_FINAL; + break; + case PE_STRAIGHT: + // permenant sticky nets + pl->permsticky = B_TRUE; + pl->netsticky = B_TRUE; + sprintf(tempmsg, "Permenant sticky net!"); + addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY); + break; + case PE_FLUSH: + // skip 5 levels + sprintf(tempmsg, "Skip 5 levels!"); + addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY); + // set powerup + player->powerup = PW_PHONE; + skiplevels = 4; + // kill all enemies + for (s2 = sprite; s2 ; s2 = nexts) { + nexts = s2->next; + if (isbullet(s2->id) || ismonster(s2->id)) { + s2->dead = D_FINAL; + + if (s2->caughtby) { + s2->caughtby = NULL; + player->netcaught--; + } + } + } + // call in cloud immediately + levelcomplete = LV_FINAL; + break; + case PE_FULLHOUSE: + // permenant big net + pl->permbignet = B_TRUE; + pl->netbig = B_TRUE; + sprintf(tempmsg, "Permenant Big Nets!"); + addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY); + break; + case PE_FOUR: + // permenant max nets + pl->permnumnets = B_TRUE; + pl->netmax = 4; + sprintf(tempmsg, "Permenant Max Nets!"); + addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY); + break; + case PE_STRAIGHTFLUSH: + // skip 7 levels + sprintf(tempmsg, "Skip 7 levels!"); + addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY); + // set powerup + player->powerup = PW_PHONE; + skiplevels = 6; + // kill all enemies + for (s2 = sprite; s2 ; s2 = nexts) { + nexts = s2->next; + if (isbullet(s2->id) || ismonster(s2->id)) { + s2->dead = D_FINAL; + + if (s2->caughtby) { + s2->caughtby = NULL; + player->netcaught--; + } + } + } + // call in cloud immediately + levelcomplete = LV_FINAL; + break; + case PE_ROYALFLUSH: + // permenant trophy + pl->permspeed = B_TRUE; + pl->permbignet = B_TRUE; + pl->permnumnets = B_TRUE; + pl->speed = 2; + pl->netbig = B_TRUE; + pl->netmax = 4; + sprintf(tempmsg, "Permenant full power!"); + addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY); + break; + } +} + +char *getpokermsg(int effect) { + switch (effect) { + case PE_HIGHCARD: + return "High Card"; + case PE_PAIR: + return "Pair!"; + case PE_TWOPAIR: + return "Two Pairs!"; + case PE_TRIPLE: + return "Triple!"; + case PE_STRAIGHT: + return "Straight!"; + case PE_FLUSH: + return "Flush!"; + case PE_FULLHOUSE: + return "Full House!"; + case PE_FOUR: + return "Four of a Kind!"; + case PE_STRAIGHTFLUSH: + return "Straight Flush!"; + case PE_ROYALFLUSH: + return "ROYAL FLUSH!"; + } + return "unknown"; +} + +int getcardsuit(int cardid) { + if ((cardid >= P_FIRSTHEART) && (cardid <= (P_FIRSTHEART + 12))) { + return CS_HEART; + } else if ((cardid >= P_FIRSTDIAMOND) && (cardid <= (P_FIRSTDIAMOND + 12))) { + return CS_DIAMOND; + } else if ((cardid >= P_FIRSTSPADE) && (cardid <= (P_FIRSTSPADE + 12))) { + return CS_SPADE; + } else { + return CS_CLUB; + } +} +int getcardvalue(int cardid) { + int points; + points = cardid; + switch (getcardsuit(cardid)) { + case CS_HEART: + points -= P_FIRSTHEART; + break; + case CS_DIAMOND: + points -= P_FIRSTDIAMOND; + break; + case CS_SPADE: + points -= P_FIRSTSPADE; + break; + case CS_CLUB: + default: + points -= P_FIRSTCLUB; + break; + } + + return (points+1); +} + diff --git a/rc.h b/rc.h index 3a1bf74..da9d9db 100644 --- a/rc.h +++ b/rc.h @@ -68,3 +68,9 @@ void togglefullscreen(void); void initsdl(void); void getfruit(sprite_t *giveto, sprite_t *fruit, int multiplier); int haspowerup(sprite_t *s, int pid); +void gaincard(sprite_t *s, int cardid); +int getpokereffect(sprite_t *pl); +void dopokereffect(sprite_t *pl, int effect); +char *getpokermsg(int effect); +int getcardvalue(int cardid); +int getcardsuit(int cardid); diff --git a/shared.c b/shared.c index b09fec9..44d64c8 100644 --- a/shared.c +++ b/shared.c @@ -568,6 +568,22 @@ void setdefaults(sprite_t *s) { } else { s->speed = 1; } + if (s->permbignet) { + s->netbig = B_TRUE; + } else { + s->netbig = B_FALSE; + } + + if (s->permnumnets) { + s->netmax = 4; + } else { + s->netmax = 1; + } + if (s->permsticky) { + s->netsticky = B_TRUE; + } else { + s->netsticky = B_FALSE; + } s->frame = 0; @@ -576,11 +592,8 @@ void setdefaults(sprite_t *s) { s->armour = B_FALSE; s->gemboost = 1; s->powerup = 0; - s->netbig = 0; - s->netsticky = B_FALSE; // player-only states s->netting = 0; - s->netmax = 1; s->netcaught = 0; s->slamming = 0; s->invuln = 0; @@ -677,6 +690,7 @@ void setdefaults(sprite_t *s) { /* initial is TRUE if we are populating the level for the first time */ sprite_t *addsprite(int id, int x, int y, char *name ) { sprite_t *s; + int c; if (sprite == NULL) { sprite = malloc(sizeof(sprite_t)); @@ -717,8 +731,19 @@ sprite_t *addsprite(int id, int x, int y, char *name ) { } s->iceimg = NULL; - // don't set this in setdefaults as it is called after player death + // don't set these in setdefaults() as setdefaults() is called after each player death s->permspeed = B_FALSE; + s->permbignet = B_FALSE; + s->permnumnets = B_FALSE; + s->permsticky = B_FALSE; + + // don't set this in setdefaults() as setdefaults() is called after each player death + s->numcards = 0; + for (c = 0; c < MAXCARDS; c++) { + s->card[c] = -1; + s->usedcard[c] = 0; + } + setdefaults(s); @@ -1179,6 +1204,8 @@ int loadimagesets(void) { loadspriteimage(P_STARPOWERUP,F_WALK1, "sprites/star.png"); imageset[P_STARPOWERUP].numimages = 1; + // Don't load image for P_MOVINGCARD or P_FIVECARDS + for (i = 0; i < STARFRAMES; i++) { char name[SMALLBUFLEN]; @@ -1497,6 +1524,12 @@ void drawsprite(sprite_t *s) { } else { return; } + } else if (s->id == P_MOVINGCARD) { + // not really needed but included here for neatness + frame = F_WALK1; + } else if (s->id == P_FIVECARDS) { + // not really needed but included here for neatness + frame = F_WALK1; } } else if (s->dead) { @@ -1593,7 +1626,13 @@ void drawsprite(sprite_t *s) { frame += (MAXFRAMES*2); } - if ((s->id != P_BLACKCLOUD) && (s->id != P_PINKCLOUD) && (!s->teleporting)) { + if (s->id == P_MOVINGCARD) { + // image comes from timer1 + s->img = imageset[s->timer1].img[F_WALK1]; + } else if (s->id == P_FIVECARDS) { + // do nothing - img already there! + } else if ((s->id != P_BLACKCLOUD) && (s->id != P_PINKCLOUD) && (!s->teleporting)) { + // select image based on sprite id s->img = imageset[s->id].img[frame]; } @@ -1722,6 +1761,12 @@ void killsprite(sprite_t *s) { // cards? // etc + if (s->id == P_FIVECARDS) { + if (s->img) { + SDL_FreeSurface(s->img); + } + } + nextone = s->next; if (nextone != NULL) { nextone->prev = s->prev; @@ -1850,7 +1895,7 @@ int isfruit(int id) { } - if (iscard(id)) return FT_FRUIT; + if (iscard(id)) return FT_CARD; return B_FALSE; } @@ -1875,6 +1920,8 @@ int iseffect(int id) { case P_STAR: case P_METEOR: case P_MASK: + case P_MOVINGCARD: + case P_FIVECARDS: return B_TRUE; } @@ -2441,7 +2488,7 @@ int loadlevellist(void) { int randompowerup(void) { int num; - num = rand() % 26; + num = rand() % 27; switch (num) { case 0: @@ -2497,6 +2544,8 @@ int randompowerup(void) { return P_TAP; case 25: return P_MASKPOWERUP; + case 26: + return getrandomcard(); } } @@ -2776,9 +2825,35 @@ char *getcardletter(int num) { // returns a random card sprite id int getrandomcard(void) { + int i; int cardid; - // TODO: change to 52 - cardid = P_FIRSTCARD + (rand() % 52); + int gotit; + //cardid = P_FIRSTCARD + (rand() % 52); + + + gotit = B_TRUE; + while (gotit) { + // give current card + cardid = deck[curcard]; + // move to next card + curcard++; + if (curcard >= DECKSIZE) { + shufflecards(); + curcard = 0; + } + // make sure the player doesn't have it! + gotit = B_FALSE; + if (player) { + for (i = 0; i < player->numcards; i++) { + if (player->card[i] == cardid) { + gotit = B_TRUE; + } + } + } + } + +printf("returning cardid %d\n",cardid); + return cardid; } @@ -2892,3 +2967,29 @@ char *getcardname(int id) { } return "Unknown Card"; } + +void shufflecards(void) { + int ii,i,n,thiscard; + + // generate initial list of cards + for (i = 0; i < DECKSIZE; i++) { + deck[i] = P_FIRSTCARD + i; + } + + // shuffle them + for (ii = 0; ii < SHUFFLEQUALITY; ii++) { + for (i = 0; i < DECKSIZE; i++) { + // 50% chance of moving to the end + if (rand() % 2) { + thiscard = deck[i]; + for (n = i; n < (DECKSIZE-1); n++) { + deck[n] = deck[n+1]; + } + deck[DECKSIZE-1] = thiscard; + } + } + } + + curcard = 0; +} + diff --git a/shared.h b/shared.h index c1170ef..c895bb9 100644 --- a/shared.h +++ b/shared.h @@ -55,6 +55,7 @@ void doblit(SDL_Surface *src, SDL_Surface *dst, SDL_Rect *dstarea); char *getcardletter(int num); int getrandomcard(void); char *getcardname(int id); +void shufflecards(void); // for doco void setfruitinfo(void); void setinfo(int id, char *name, char *desc, char *file);