main.cBP\óWmain.c"%yTEXTCWIEB\óWX#include #include #include #include "pad.h" #include "sprite.h" #include "addrs.h" #include "background.h" #include "message.h" #include "bits.h" #include "card.h" #include "flipping.h" #define PAL 1 // 0 - NTSC mode, 1 - PAL mode #define PACKETMAX 4096 /* Max GPU packets */ #define PACKETMAX2 (PACKETMAX*24) #define OT_LENGTH 4 #define AnalogSpeed 20 typedef struct bui { u_char x,y; struct bui *next; } buitem; buitem *blowingup = NULL; int blowupdel; card area[12][9]; // Cards that are in the main grid. u_char orphans[12][9]; // Cards in main grid that are orphans. u_char orphaning; u_char orphanx, orphany; card hand[4]; // Cards in your current hand. u_char firsthand; u_char cardsel; // Card in you hand currently selected. u_char endmess; u_char usedcards[4][13]; // Note of cards that have been used. u_char books[13]; // Books that have been completed. typedef enum {easy, normal} difflevel; difflevel diff = normal; u_char kingstart[4][2]; static GsOT Wot[2]; /* Handler of OT */ static GsOT_TAG wtags[2][1<x][blowingup->y], 20+(blowingup->x*16), 20+(blowingup->y*24)); area[blowingup->x][blowingup->y].valid = 0; temp = blowingup; blowingup = blowingup->next; free(temp); blowupdel = 8; } else blowupdel--; } } void CheckForBooks() { int x,y; int upto = 0; int count; while (books[upto]==1) upto++; for (y=0;y<8;y++) { for (x=0;x<11;x++) { // Check if this card is the top-left card of a completed book. if (area[x][y].valid && area[x+1][y].valid && area[x+1][y+1].valid && area[x][y+1].valid && area[x][y].value==area[x+1][y].value && area[x+1][y].value==area[x+1][y+1].value && area[x+1][y+1].value==area[x][y+1].value) { if (diff==easy || upto==area[x][y].value-1) { books[area[x][y].value-1] = 1; // Blow up cards that form the book. AddBU(x,y); AddBU(x+1,y); AddBU(x+1,y+1); AddBU(x,y+1); if (diff==normal) {x=-1; y=0; upto++;} } } } } // Blow up kings if all books have been completed. count = 0; for (x=0;x<12;x++) if (books[x]) count++; if (count==12 && area[kingstart[0][0]][kingstart[0][1]].valid) { for (x=0;x<4;x++) AddBU(kingstart[x][0],kingstart[x][1]); } // Check to see if any orphans have appeared if (!orphaning) { for (y=0;y<9;y++) { for (x=0;x<12;x++) { count = 0; if (x==0) count++; else if (!area[x-1][y].valid) count++; if (y==0) count++; else if (!area[x][y-1].valid) count++; if (x==11) count++; else if (!area[x+1][y].valid) count++; if (y==8) count++; else if (!area[x][y+1].valid) count++; if (count==4 && area[x][y].valid && area[x][y].value != 13) { orphans[x][y] = 1; orphanx = x; orphany = y; orphaning = 1; } } } } } void AddBU(u_char x, u_char y) { // Add a new card onto the list of ones to be blown up. buitem *newitem; buitem *buptr = blowingup; newitem = (buitem*)(malloc(sizeof(buitem))); newitem->x = x; newitem->y = y; newitem->next = NULL; if (buptr==NULL) { blowingup = newitem; blowupdel = 0; } else { while (buptr->next!=NULL) buptr = buptr->next; buptr->next = newitem; } } void CheckPad() { u_char lr,ud; long pad; static long analogx = 0; static long analogy = 0; static long xspeed = 0; static long yspeed = 0; static u_char movecardsel = 0; static u_char xbut = 0; static u_char sbut = 0; static u_char cbut = 0; static u_char tbut = 0; static u_char diffset = 0; card c; int i,x,y; pad = PadRead(); // Change the background every now and then. if ((rand() & 4095)==128) ChangeBG(); if (diffset>0) diffset--; if (tbut) { if (!(pad & PADRup)) tbut = 0; } else { if (pad & PADRup && diffset==0) { i = 0; for (y=0;y<9;y++) { for (x=0;x<12;x++) { if (area[x][y].valid) i++; } } if (cardsel==255 && i==4) { // Change difficulty setting if (diff==easy) { diff = normal; NewMessage("Normal difficulty setting"); diffset = 64; } else { diff = easy; NewMessage("Easy difficulty setting"); diffset = 64; } } else ToggleBG(); tbut = 1; } } if (cbut) { if (!(pad & PADRright)) cbut = 0; } else { if (pad & PADRright && !Flipping()) { // Start a new game. ClearArea(); FlashBG(); cbut = 1; } } if ((cardsel!=255 || orphaning) && !Flipping()) { if (pad & PADL2) ShowPossible(); if (pad & PADR2) ShowMatching(); if (movecardsel) { if (!(pad & PADL1 || pad & PADR1)) movecardsel = 0; } else { if (pad & PADL1) { // Select card to the left of currently selected one. if (orphaning) { do { if ((orphanx--) == 0) { orphanx = 11; if ((orphany--) == 0) orphany = 8; } } while (orphans[orphanx][orphany]==0); } else { if ((cardsel--) == 0) cardsel = 3; while (!hand[cardsel].valid) if ((cardsel--) == 0) cardsel = 3; } movecardsel = 1; } if (pad & PADR1) { // Select card to the right of currently selected one. if (orphaning) { do { if ((orphanx++) == 11) { orphanx = 0; if ((orphany++) == 8) orphany = 0; } } while (orphans[orphanx][orphany]==0); } else { if ((cardsel++) == 3) cardsel = 0; while (!hand[cardsel].valid) if ((cardsel++) == 3) cardsel = 0; } movecardsel = 1; } } } if (AnalogPadRead(&lr, &ud)) { // The normal d-pad works better I think. if (ABS(lr-128)>32 || ABS(ud-128)>32) { if (lr>128) analogx+=lr-160; else analogx+=lr-96; if (ud>128) analogy+=ud-160; else analogy+=ud-96; cursorx+=analogx / AnalogSpeed; cursory+=analogy / AnalogSpeed; if (analogx>0) analogx%=AnalogSpeed; else analogx=-(-analogx % AnalogSpeed); if (analogy>0) analogy%=AnalogSpeed; else analogy=-(-analogy % AnalogSpeed); } } else { if (pad & PADLup) if ((yspeed-=3) < -16) yspeed = -16; if (pad & PADLdown) if ((yspeed+=3) > 16) yspeed = 16; if (pad & PADLleft) if ((xspeed-=3) < -16) xspeed = -16; if (pad & PADLright) if ((xspeed+=3) > 16) xspeed = 16; if (xspeed>0) xspeed-=2; if (xspeed<0) xspeed+=2; if (yspeed>0) yspeed-=2; if (yspeed<0) yspeed+=2; cursorx+=xspeed/2; cursory+=yspeed/2; if (cursorx<20) cursorx = 20; if (cursorx>211) cursorx = 211; if (cursory<20) cursory = 20; if (cursory>234) cursory = 234; } if (xbut) { if (!(pad & PADRdown)) xbut = 0; } else { if (pad & PADRdown && blowingup==NULL && !Flipping()) { if (cardsel==255 && !orphaning) { if (firsthand) firsthand = 0; // Deal new cards. for (i=0;i<4;i++) { c = NewCard(); if (c.valid) FlipCard(256, 56, 232+(i*16), 104, c, &hand[i], 0); } if (Flipping()) cardsel = 0; } else TryPlaceCard(); xbut = 1; } } if (sbut) { if (!(pad & PADRleft)) sbut = 0; } else { if (pad & PADRleft && blowingup==NULL && !Flipping() && !firsthand) { Undo(); xbut = 1; } } } void Undo() { int x,y,i; for (i=0;i<4;i++) { if (!hand[i].valid) { for (y=0;y<9;y++) { for (x=0;x<12;x++) { if (hand[i].suit==area[x][y].suit && hand[i].value==area[x][y].value && area[x][y].valid) { FlipCard2(20+x*16, 20+y*24, 232+(i*16), 104, &area[x][y], &hand[i], 1); } } } } if (Flipping()) cardsel = 0; do { if ((cardsel++) == 3) cardsel = 0; } while (!hand[cardsel].valid); } } void ShowPossible() { // Highlight all possible positions for currently selected card. int x,y; GsBOXF box; card *newcard; box.attribute = 1<<30; box.w = 16; box.h = 24; box.r = box.b = 0; box.g = 192; if (orphaning) newcard = &area[orphanx][orphany]; else newcard = &hand[cardsel]; for (y=0;y<9;y++) { for (x=0;x<12;x++) { if (CanPlace(newcard, x, y)) { box.x = 20+(x*16); box.y = 20+(y*24); GsSortBoxFill(&box, &Wot[side], 10); } } } } void ShowMatching() { // Highlight all cards that match the currently selected one in value. int x,y; GsBOXF box; card *newcard; box.attribute = 1<<30; box.w = 16; box.h = 24; box.r = 192; box.b = box.g = 0; if (orphaning) newcard = &area[orphanx][orphany]; else newcard = &hand[cardsel]; for (y=0;y<9;y++) { for (x=0;x<12;x++) { if (area[x][y].value==newcard->value && area[x][y].valid) { box.x = 20+(x*16); box.y = 20+(y*24); GsSortBoxFill(&box, &Wot[side], 10); } } } } void TryPlaceCard() { int xpos,ypos,x,y; u_char count; // Find grid x,y position from screen co-ords of cursor. xpos = (cursorx-20)/16; ypos = (cursory-20)/24; if (xpos>=0 && ypos>=0 && xpos<12 && ypos<9) { if (orphaning) { if (CanPlace(&area[orphanx][orphany],xpos,ypos)) { // Flip card into it's new position. FlipCard(20+orphanx*16, 20+orphany*24, 20+xpos*16, 20+ypos*24, area[orphanx][orphany], &area[xpos][ypos], 1); area[orphanx][orphany].valid = 0; orphans[orphanx][orphany] = 0; // Check if there are any more orphans to re-position. count = 0; for (y=0;y<9;y++) { for (x=0;x<12;x++) { if (orphans[x][y]==1) count++; } } if (count==0) orphaning = 0; else { do { if ((orphanx--) == 0) { orphanx = 11; if ((orphany--) == 0) orphany = 8; } } while (orphans[orphanx][orphany]==0); } } } else { if (CanPlace(&hand[cardsel],xpos,ypos)) { // Flip card from hand to grid position. FlipCard(232+cardsel*16, 104, 20+xpos*16, 20+ypos*24, hand[cardsel], &area[xpos][ypos], 1); hand[cardsel].valid = 0; if (!hand[0].valid && !hand[1].valid && !hand[2].valid && !hand[3].valid) cardsel = 255; else while (!hand[cardsel].valid) if ((cardsel++) == 3) cardsel = 0; } } } } u_char CanPlace(card *c, int xpos, int ypos) { // Returns true if given card can be placed in position xpos,ypos. card adj[4]; int i; if (area[xpos][ypos].valid) return 0; if (ypos==0) adj[0].valid = 0; else { adj[0] = area[xpos][ypos-1]; if (orphans[xpos][ypos-1]) adj[0].valid = 0; } if (ypos==8) adj[1].valid = 0; else { adj[1] = area[xpos][ypos+1]; if (orphans[xpos][ypos+1]) adj[1].valid = 0; } if (xpos==0) adj[2].valid = 0; else { adj[2] = area[xpos-1][ypos]; if (orphans[xpos-1][ypos]) adj[2].valid = 0; } if (xpos==11) adj[3].valid = 0; else { adj[3] = area[xpos+1][ypos]; if (orphans[xpos+1][ypos]) adj[3].valid = 0; } for (i=0;i<4;i++) { if (adj[i].valid && c->suit!=adj[i].suit && c->value!=adj[i].value) return 0; } if (!adj[0].valid && !adj[1].valid && !adj[2].valid && !adj[3].valid) return 0; return 1; } card NewCard() { u_char found = 0; card newcard; u_char count = 0; int x,y; for (y=0;y<13;y++) { for (x=0;x<4;x++) { if (usedcards[x][y]==1) count++; } } if (count==13*4) { // There are no cards left on the deck. newcard.valid = 0; return newcard; } newcard.valid = 1; // Choose a new card that hasn't already been dealt. while (!found) { newcard.suit = (esuit)(rand() & 3); newcard.value = 1+(rand() % 13); if (usedcards[newcard.suit][newcard.value-1]==0) found = 1; } usedcards[newcard.suit][newcard.value-1] = 1; return newcard; } void PlotCursor() { GsSPRITE pointer; InitSpr(&pointer); pointer.w = pointer.h = 16; CalcSprPos(pointer, 744, 24); pointer.x = cursorx; pointer.y = cursory; GsSortFastSprite(&pointer, &Wot[side], 0); } void PlotArea() { static short bounce = 0; int x,y,i,cardcount = 0; GsBOXF orphanbox; card c; orphanbox.attribute = 1<<30; orphanbox.w = 16; orphanbox.h = 24; orphanbox.r = orphanbox.b = 0; orphanbox.g = 192; // Plot cards in grid. for (x=0;x<12;x++) { for (y=0;y<9;y++) { PlotCard(&Wot[side],&area[x][y], 20+(x*16), 20+(y*24)); if (area[x][y].valid) cardcount++; if (orphans[x][y]) { orphanbox.x = 20+(x*16); orphanbox.y = 20+(y*24); GsSortBoxFill(&orphanbox, &Wot[side], 10); } } } // Plot cards in hand. for (i=0;i<4;i++) { PlotCard(&Wot[side],&hand[i], 232+(i*16), 104); if (hand[i].valid) cardcount++; } // Plot bouncy selected card symbol. if (cardsel!=255 && orphaning==0 && blowingup==NULL && !Flipping()) { PlotValue(&Wot[side],hand[cardsel].suit, hand[cardsel].value, 232+(cardsel*16), 96-(DJsin(bounce)>>8)); PlotValue(&Wot[side],hand[cardsel].suit, hand[cardsel].value, 232+(cardsel*16), 128+(DJsin(bounce)>>8)); PlotSuit(&Wot[side],hand[cardsel].suit, 240+(cardsel*16), 96-(DJsin(bounce)>>8)); PlotSuit(&Wot[side],hand[cardsel].suit, 240+(cardsel*16), 128+(DJsin(bounce)>>8)); if ((bounce+=96) >= 2048) bounce-=2048; } if (orphaning && blowingup==NULL && !Flipping()) { c = area[orphanx][orphany]; PlotValue(&Wot[side],c.suit, c.value, 20+(orphanx*16), (12+(orphany*24))-(DJsin(bounce)>>8)); PlotValue(&Wot[side],c.suit, c.value, 20+(orphanx*16), (44+(orphany*24))+(DJsin(bounce)>>8)); PlotSuit(&Wot[side],c.suit, 28+(orphanx*16), (12+(orphany*24))-(DJsin(bounce)>>8)); PlotSuit(&Wot[side],c.suit, 28+(orphanx*16), (44+(orphany*24))+(DJsin(bounce)>>8)); if ((bounce+=96) >= 2048) bounce-=2048; } // Plot deck. if (cardcount>50) { c.valid = 0; PlotCard(&Wot[side], &c, 256, 56); } else PlotBackFace(&Wot[side], 256, 56); // Plot completed books. c.suit = spade; for (y=0;y<3;y++) { for (x=0;x<4;x++) { c.valid = books[y*4+x]; c.value = (y*4+x)+1; PlotCard(&Wot[side], &c, 232+(x*16), 140+(y*24)); } } } void ClearArea() { int x,y; for (x=0;x<12;x++) { for (y=0;y<9;y++) { area[x][y].valid = 0; area[x][y].suit = (esuit)(rand() & 3); area[x][y].value = 1+(rand() % 13); orphans[x][y] = 0; } } for (x=0;x<4;x++) { area[kingstart[x][0]][kingstart[x][1]].valid = 1; area[kingstart[x][0]][kingstart[x][1]].suit = (esuit)x; area[kingstart[x][0]][kingstart[x][1]].value = 13; } orphaning = 0; firsthand = 1; cardsel = 255; endmess = 0; for (x=0;x<4;x++) { for (y=0;y<12;y++) usedcards[x][y] = 0; usedcards[x][12] = 1; } for (x=0;x<4;x++) hand[x].valid = 0; for (x=0;x<13;x++) books[x] = 0; } void InitialiseAll() { char* startupmess; if (PAL) { SetVideoMode(MODE_PAL); GsInitGraph(320,256,GsOFSGPU,0,0); GsDefDispBuff(0,0,0,256); GsDISPENV.screen.x = 5; GsDISPENV.screen.y = 20; GsDISPENV.screen.h = 256; } else { SetVideoMode(MODE_NTSC); GsInitGraph(320,240,GsOFSGPU,0,0); GsDefDispBuff(0,0,0,240); GsDISPENV.screen.x = 5; GsDISPENV.screen.y = 10; GsDISPENV.screen.h = 240; } Wot[0].length=OT_LENGTH; Wot[0].org=wtags[0]; Wot[1].length=OT_LENGTH; Wot[1].org=wtags[1]; GsClearOt(0,0,&Wot[0]); GsClearOt(0,0,&Wot[1]); // Load all sprites into VRAM InitTIM(spritesaddr); InitTIM(fontaddr); // Initialise the pad PadInit(); cursorx = 160; cursory = 128; kingstart[0][0] = 7; kingstart[0][1] = 4; kingstart[1][0] = 5; kingstart[1][1] = 4; kingstart[2][0] = 4; kingstart[2][1] = 4; kingstart[3][0] = 6; kingstart[3][1] = 4; /* kingstart[0][0] = 2; kingstart[0][1] = 2; kingstart[1][0] = 9; kingstart[1][1] = 6; kingstart[2][0] = 9; kingstart[2][1] = 2; kingstart[3][0] = 2; kingstart[3][1] = 6; */ startupmess = "Welcome to A Farewell to Kings . If you haven't already read the help file then I suggest you do, otherwise you won't know what's going on."; startupmess[11] = (char)34; startupmess[31] = (char)34; NewMessage(startupmess); } ZZRmain.critererefix.h DatantallerTEXTCWIEk\B+++++H Monaco,^,^W99>ZZRfH0RMPSRMWBB*LR