diff --git a/data/music/hiscore.mod b/data/music/hiscore.mod new file mode 100644 index 0000000..5aebbd0 Binary files /dev/null and b/data/music/hiscore.mod differ diff --git a/defs.h b/defs.h index f5f1a1e..a76469a 100644 --- a/defs.h +++ b/defs.h @@ -66,7 +66,7 @@ #define TT_HELPSHADOW 2 #define TT_GAMEOVER 3 -#define GAMEOVERWAIT 2 // # of seconds to wait before going back to title +#define GAMEOVERWAIT 3 // # of seconds to wait before going back to title // text delays #define TEXTSPEED 2 // how fast text zooms in @@ -83,8 +83,9 @@ #define DIEDELAY 80 #define HELPDELAY 80 #define LEVELDELAY 100 -//#define GAMEOVERDELAY 200 -#define GAMEOVERDELAY 20 +// TODO: put back! +#define GAMEOVERDELAY 200 +//#define GAMEOVERDELAY 20 #define POKERDELAY 170 @@ -193,6 +194,7 @@ #define MAXJOYBUTTONS 20 #define MAXHISCORES 10 +#define MAXHISCORENAME 10 // Fixed text buffer sizes #define BUFLEN 512 @@ -801,7 +803,7 @@ extern int toggletimer; extern TTF_Font *font[]; extern TTF_Font *cardfont; extern int musicplaying; -extern Mix_Music *music, *normalmusic, *fastmusic, *bossmusic; +extern Mix_Music *music, *normalmusic, *fastmusic, *bossmusic,*hiscoremusic; extern Mix_Chunk *sfx[]; extern int oldexitdir; extern int levelcomplete; diff --git a/globals.h b/globals.h index a01f868..32592c5 100644 --- a/globals.h +++ b/globals.h @@ -34,7 +34,7 @@ sprite_t *player; // pointer to the player's sprite sprite_t *boss; // point to current boss on level (normally NULL) sprite_t *mask; // point to scuba mask -Mix_Music *music, *fastmusic, *normalmusic,*bossmusic; +Mix_Music *music, *fastmusic, *normalmusic,*bossmusic,*hiscoremusic; Mix_Chunk *sfx[MAXFX]; text_t *text, *lasttext; diff --git a/rc.c b/rc.c index aab52d4..2df1c85 100644 --- a/rc.c +++ b/rc.c @@ -34,8 +34,12 @@ SDL_Surface *credittext; TTF_Font *font[MAXLETTERHEIGHT]; +char hiscoreserver[BUFLEN]; +int hiscoreport; hiscore_t hiscore[MAXHISCORES]; int numhiscores; +int wanthiscores; +int gothiscore = -1; int havejoysticks; int joybuttons; @@ -153,6 +157,10 @@ int main (int argc, char **argv) { datadir = NULL; + // default + sprintf(hiscoreserver, "photos.nethack.net"); + hiscoreport = 80; + /* handle arguments */ if (argc >= 2) { for (i = 1; i < argc; i++) { @@ -177,6 +185,41 @@ int main (int argc, char **argv) { } skipto = atoi(argv[i]); printf("Skipping to level %d.\n",skipto); + } else if (!strcmp(argv[i], "-hs")) { + if (++i >= argc) { + printf("Missing hiscore server name.\n"); + usage(); + exit(1); + } + if (strstr(argv[i], ":")) { + char *p,*p2; + // use port as well + p2 = hiscoreserver; + for (p = argv[i];p; p++) { + if (*p == ':') { + p++; + break; + } else { + *p2 = *p; + } + p2++; + } + *p2 = '\0'; + hiscoreport = atoi(p); + printf("Hiscore server set to '%s'\n",hiscoreserver); + printf("Hiscore port set to '%d'\n",hiscoreport); + } else { + sprintf(hiscoreserver, "%s",argv[i]); + printf("Hiscore server set to '%s'\n",hiscoreserver); + } + } else if (!strcmp(argv[i], "-hp")) { + if (++i >= argc) { + printf("Missing hiscore port.\n"); + usage(); + exit(1); + } + hiscoreport = atoi(argv[i]); + printf("Hiscore port set to '%d'\n",hiscoreport); } else { usage(); exit(1); @@ -263,6 +306,17 @@ int main (int argc, char **argv) { gamemode = GM_NORM; // default + + + // try to get hiscores + printf("Attepting to download hiscores from %s:%d...\n",hiscoreserver,hiscoreport); fflush(stdout); + if (gethiscores()) { + printf("Couldn't download hiscores. Disabling hiscore code.\n"); + wanthiscores = B_FALSE; + } else { + printf("Hiscores successfully downloaded.\n"); + wanthiscores = B_TRUE; + } // outside loop while (1) { @@ -655,11 +709,20 @@ int main (int argc, char **argv) { // clear screen SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format,black.r,black.g,black.b)); - // show high scores - showhiscores(); - // clear screen ready to start again... - SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format,black.r,black.g,black.b)); + if (wanthiscores) { + // check for a hiscore, if so submit it + checkhiscores(); + + // clear screen + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format,black.r,black.g,black.b)); + + // show high scores + showhiscores(); + + // clear screen ready to start again... + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format,black.r,black.g,black.b)); + } } // end outside loop return 0; @@ -5227,6 +5290,8 @@ void usage(void) { printf("usage: rc [-fs] [-l xx]\n"); printf(" -fs Start in full-screen mode.\n"); printf(" -l xx Skip to level xx.\n"); + printf(" -hs xx Set hiscore_server to http://xx.\n"); + printf(" -hp xx Connect to hiscore_server on port xx.\n"); printf("\n"); } @@ -5355,6 +5420,13 @@ int initsound(void) { return B_TRUE; } + sprintf(filename, "%s/music/hiscore.mod",datadir); + hiscoremusic = Mix_LoadMUS(filename); + if (!hiscoremusic) { + printf("can't load music\n"); + return B_TRUE; + } + return B_FALSE; } @@ -5465,9 +5537,11 @@ void dumpsprites(void) { printf("\n\n"); } -void drawoutlinetext(SDL_Surface *where,int x, int y, int size, char *msg, SDL_Color *col, SDL_Color *bgcol) { +// returns width +int drawoutlinetext(SDL_Surface *where,int x, int y, int size, char *msg, SDL_Color *col, SDL_Color *bgcol) { SDL_Surface *surf; SDL_Rect area; + int wid; area.w=0;area.h=0; @@ -5487,7 +5561,10 @@ void drawoutlinetext(SDL_Surface *where,int x, int y, int size, char *msg, SDL_C SDL_SetColors(surf, col, 1, 1); area.x = x; area.y = y; SDL_BlitSurface(surf, NULL, where, &area); + wid = surf->w; SDL_FreeSurface(surf); + + return wid; } void drawoutlinecentretext(SDL_Surface *where, int y, int size, char *msg, SDL_Color *col, SDL_Color *bgcol) { @@ -5906,6 +5983,8 @@ void initsdl(void) { havejoysticks = B_FALSE; printf("No joysticks found.\n"); } + + SDL_EnableUNICODE(1); } // player collects the given fruit @@ -6699,7 +6778,7 @@ void handleinput(void) { levelcomplete = oldlevelcomplete; } } - } else if (event.type == SDL_JOYBUTTONUP) { + } else if (havejoysticks && (event.type == SDL_JOYBUTTONUP)) { if (levelcomplete == LV_HELPFREEZE) { if (joybuttontokey(event.jbutton.button) == SDLK_z) { levelcomplete = oldlevelcomplete; @@ -6783,6 +6862,7 @@ void handleinput(void) { if (keydown(SDLK_ESCAPE)) { exit(1); } +if (cheat) { if (keydown(SDLK_q)) { gtime = nexthurryup-1; //gtime = nexthurryup+14; @@ -6849,6 +6929,7 @@ void handleinput(void) { toggletimer = 50; } } +} @@ -7216,14 +7297,6 @@ void dotitlescreen(void) { joyx = SDL_JoystickGetAxis(joy,0); joyy = SDL_JoystickGetAxis(joy,1); - /* - for (i = 0; i < 20; i++) { - joybut[i] = SDL_JoystickGetButton(joy,i); - if (joybut[i]) printf("button %d down\n",i); - } - */ - - //printf("joystick coords are: %d,%d button0=%d, button1=%d\n",joyx,joyy,joybut[0],joybut[1]); if (joyy <= -6000) handletitleinput(SDLK_UP); if (joyy >= 6000) handletitleinput(SDLK_DOWN); @@ -7375,6 +7448,8 @@ void startgame(void) { pokerpoints = 0; skiplevels = 0; + gothiscore = -1; + curfruittype = 0; curpoweruptype = 0; @@ -7550,8 +7625,7 @@ void drawcredits(void) { } -/* -int submithiscore(int score,char *name,char *rank,char *text) { +int submithiscore(int score,int level, char *name) { struct sockaddr_in serveraddress; struct hostent *server; int rv; @@ -7559,28 +7633,28 @@ int submithiscore(int score,char *name,char *rank,char *text) { char buf[1500]; char newtext[BUFLEN]; char buf2[512]; - int serverport = 80; char *p,*p2; - server = gethostbyname("www.nethack.net"); + server = gethostbyname(hiscoreserver); + + sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { + printf("Error getting socket.\n"); return B_TRUE; } //bzero((char *) &serveraddress, sizeof(serveraddress)); memset(&serveraddress, 0, sizeof(serveraddress)); - serveraddress.sin_family = AF_INET; - memcpy(&serveraddress.sin_addr.s_addr, server->h_addr, server->h_length); - serveraddress.sin_port = htons(serverport); + serveraddress.sin_port = htons(hiscoreport); - serveraddress.sin_port = htons(serverport); - // replace spaces in text with %20s + + // replace spaces in name with %20s p2 = newtext; - for (p = text ; *p != '\0'; p++) { + for (p = name ; *p != '\0'; p++) { if (*p == ' ') { *p2 = '%'; *p2++; *p2 = '2'; *p2++; @@ -7593,12 +7667,13 @@ int submithiscore(int score,char *name,char *rank,char *text) { // connect if (connect(sock,(struct sockaddr *)&serveraddress,sizeof(serveraddress)) < 0) { + printf("Error connecting to hiscore server.\n"); return B_TRUE; } // send request - sprintf(buf2, "GET HTTP://www.nethack.net/software/gala/hiscores/submitscore.php?score=%d&name=%s&rank=%s&text=%s HTTP/1.0\n\n", - score,name,rank,newtext); + sprintf(buf2, "GET HTTP://photos.nethack.net/rc/submitscore.php?score=%d&name=%s&level=%d HTTP/1.0\n\n", + score,newtext,level); write(sock,buf2,strlen(buf2)); // wait for data @@ -7611,7 +7686,6 @@ int submithiscore(int score,char *name,char *rank,char *text) { return B_FALSE; } -*/ int gethiscores(void) { struct sockaddr_in serveraddress; @@ -7621,13 +7695,12 @@ int gethiscores(void) { char buf[BUFLEN]; char buf2[512]; int state = 0; - //int serverport = 80; - int serverport = 1234; int pos; int finished; + // TODO: put back in //server = gethostbyname("photos.nethack.net"); - server = gethostbyname("localhost"); + server = gethostbyname(hiscoreserver); if (!server) { printf("can't resolve hiscore server name\n"); return B_TRUE; @@ -7643,7 +7716,7 @@ int gethiscores(void) { serveraddress.sin_family = AF_INET; memcpy(&serveraddress.sin_addr.s_addr, server->h_addr, server->h_length); - serveraddress.sin_port = htons(serverport); + serveraddress.sin_port = htons(hiscoreport); // connect @@ -7692,8 +7765,13 @@ int gethiscores(void) { p = strtok(NULL, "^"); sprintf(hiscore[pos].name,"%s", p); pos++; + if (pos >= MAXHISCORES) { + // too many - cut it off here + finished = B_TRUE; + } } } + //rv = read(sock, buf, 1500); rv = socket_readline(sock, buf); } @@ -7704,6 +7782,185 @@ int gethiscores(void) { return B_FALSE; } +void checkhiscores(void){ + int finished = B_FALSE; + int i; + char srank[BUFLEN],sscore[BUFLEN],slevel[BUFLEN],sname[BUFLEN]; + //char line[BUFLEN]; + char commascore[BUFLEN]; + int x,y,sx,sy; + char thisname[BUFLEN]; + int timer = 0; + int capital = B_TRUE; + + // contact server and read list + if (gethiscores()) { + printf("Cannot contact hiscore server!\n"); + return; + } + + // check if we are higher than any + gothiscore = -1; + for (i = 0; i < numhiscores; i++) { + if (player->score > hiscore[i].score) { + // we got a hi score + gothiscore = i; + break; + } + } + + + if (gothiscore == -1) { + // didn't get a hiscore + return; + } + + // play hiscore music + stopmusic(); + playmusic(hiscoremusic); + + // prompt user for a name + + strcpy(thisname, ""); + while (!finished) { + SDL_Color *fg, *bg; + SDL_Event event; + + // clear + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format,black.r,black.g,black.b)); + + //draw hiscore heading + sx = 110; + sy = 100; + x = sx; + y = sy; + + // headings + drawoutlinecentretext(screen, 50, TEXTSIZE_HISCORE, "New high score!", &green, &red); + + // print rank + drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, "Rank", &cyan, &blue); + x += 70; + // print score + drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, "Score", &cyan, &blue); + x += 150; + // print level + drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, "Level", &cyan, &blue); + x += 90; + // print name + drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, "Name", &cyan, &blue); + + y += 40; + x = sx; + + // player's score... + + + // generate hiscore lines + sprintf(srank, "%-2d.",gothiscore+1); + addcommas(commascore, player->score ); + sprintf(sscore, "%-14s",commascore); + sprintf(slevel, "%1d-%-2d",getworld(curlevelnum),getlevel(curlevelnum)); + if (strlen(thisname) > 0) { + sprintf(sname, "%-32s",thisname); + } + + fg = &green; + bg = &red; + + // print rank + drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, srank, fg, bg); + x += 70; + // print score + drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, sscore, fg, bg); + x += 150; + // print level + drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, slevel, fg, bg); + x += 90; + // print name + if (strlen(thisname) > 0) { + int wid; + wid = drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, thisname, fg, bg); + x += (wid + 2); + } + // print cursor + if (((timer / 10) % 2) == 0) { + drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, "_", fg, bg); + } + + if (++timer == 100) { + timer = 0; + } + + + // wait for a key... + if (SDL_PollEvent(&event)) { + int key = -1; + int keyval; + switch (event.type) { + case SDL_KEYUP: + key = event.key.keysym.sym; + keyval = event.key.keysym.unicode & 0x7F; + break; + case SDL_JOYBUTTONUP: + key = joybuttontokey(event.jbutton.button); + break; + + } + if (key != -1) { + if (key == SDLK_ESCAPE) { + // quit + exit(0); + } else if ((key == SDLK_RETURN) || (havejoysticks && (key == SDLK_z))) { + if (strlen(thisname) > 0) { + finished = B_TRUE; + } + } else { + // check for printable key + if (((keyval >= 'a') && (keyval <= 'z')) || (keyval == ' ')) { + char let[2]; + + // capital + if (capital) { + if ((keyval >= 'a') && (keyval <= 'z')) { + keyval -= 32; + capital = B_FALSE; + } + } + + let[0] = keyval; + let[1] = '\0'; + strcat(thisname, let); + // don't let name get too long + if (strlen(thisname) >= MAXHISCORENAME) { + finished = B_TRUE; + } + if (keyval == ' ') { + // next letter is a capital + capital = B_TRUE; + } + } + } + } + } + + SDL_UpdateRect(screen, 0,0,640,480); + } + + + + // submit the hiscore + if (submithiscore(player->score, curlevelnum, thisname)) { + printf("failed to submit hiscore.\n"); + } else { + // downlaod the hiscores again + gethiscores(); + } + + +} + + void showhiscores(void){ int finished = B_FALSE; int i; @@ -7712,11 +7969,13 @@ void showhiscores(void){ char commascore[BUFLEN]; int x,y,sx,sy; - // TODO: contact server and read list + // contact server and read list + /* if (gethiscores()) { printf("Cannot contact hiscore server!\n"); return; } + */ /* hiscore[0].score = 55000; hiscore[0].level = 24; @@ -7765,8 +8024,13 @@ void showhiscores(void){ sprintf(slevel, "%1d-%-2d",getworld(hiscore[i].level),getlevel(hiscore[i].level)); sprintf(sname, "%-32s",hiscore[i].name); - fg = &red; - bg = &red2; + if ((gothiscore != -1) && (i == gothiscore)) { + fg = &green; + bg = &red; + } else { + fg = &red; + bg = &red2; + } // print rank drawoutlinetext(screen, x, y, TEXTSIZE_HISCORE, srank, fg, bg); @@ -7811,6 +8075,9 @@ void showhiscores(void){ SDL_UpdateRect(screen, 0,0,640,480); } + // stop music ready for title screen again (it will only be playing if + // we got a hiscore) + stopmusic(); } int socket_readline(int sock, char* out) { diff --git a/rc.h b/rc.h index 9fe5f22..0fbad4f 100644 --- a/rc.h +++ b/rc.h @@ -88,7 +88,10 @@ void setjoymappings(void); int keytojoybutton(int key); int joybuttontokey(int buttonnum); void drawcredits(void); -void drawoutlinetext(SDL_Surface *where,int x, int y, int size, char *msg, SDL_Color *col, SDL_Color *bgcol); +int drawoutlinetext(SDL_Surface *where,int x, int y, int size, char *msg, SDL_Color *col, SDL_Color *bgcol); void drawoutlinetextcentre(SDL_Surface *where,int y, int size, char *msg, SDL_Color *col, SDL_Color *bgcol); int socket_readline(int sock, char *out); void showhiscores(void); +void checkhiscores(void); +int gethiscores(void); +int submithiscore(int score,int level, char *name);