#include "menu.h" #include "announce.h" #include "bomber.h" #include "draw.h" #include "game.h" #include "gfx.h" #include "network.h" #include "sound.h" #include "utils.h" GameOptions configopts = {2, 1, 0, 2}; /* Generic menu */ typedef enum { MENU_ANY = -1, MENU_MAIN = 0, MENU_CONFIG = 2, MENU_JOIN = 3 } menuname; #define MENU_SELECT(x) ((menuname)(-x - 1)) static int menuhistory[32] = {0}; static char menustring[1024]; static char *menuput, *menuitems[40], *menutitle; static int menunum, menuexit; static int menudelta; static void drawmenu(int selected) { int i, j; int tx, ty; clear(); j = strlen(menutitle) * bigfontxsize; drawbigstring((IXSIZE - j) >> 1, 20, menutitle); ty = ((IYSIZE - (bigfontysize * menunum)) >> 1) - (IYSIZE >> 3); for (i = 0; i < menunum; ++i) { j = strlen(menuitems[i]) * bigfontxsize; tx = (IXSIZE - j) >> 1; if (i == selected) { greyrect(0, ty - 1, tx - 5, bigfontysize); greyrect(tx + j + 3, ty - 1, IXSIZE - (tx + j + 3), bigfontysize); } drawbigstring(tx, ty, menuitems[i]); ty += bigfontyspace; } } static int domenu(menuname whichmenu, int (*pause)(void)) { char redraw; int selected; int mcount = 0; if (whichmenu >= 0) selected = menuhistory[whichmenu]; else selected = -whichmenu - 1; if (!pause) pause = mypause; redraw = 1; clearspritelist(); while (!exitflag) { if (redraw) { drawmenu(selected); redraw = 0; } if (!pause()) return -1; scaninput(); ++mcount; clearsprites(); clearspritelist(); addsprite(IXSIZE / 2 - 50 - 20, IYSIZE - 80, walking[2] + (30 + mcount % 15)); addsprite(IXSIZE / 2 + 50 - 20, IYSIZE - 80, walking[3] + (30 + (mcount + 7) % 15)); plotsprites(); copyup(); if (anydown()) playsound(3); while (anydown()) { switch (takedown()) { case MYLEFT: menudelta = -1; return selected; case MYRIGHT: case ' ': case 13: menudelta = 1; return selected; case 'k': case MYUP: if (selected) --selected; else selected = menunum - 1; if (whichmenu >= 0) menuhistory[whichmenu] = selected; redraw = 1; break; case 'j': case MYDOWN: ++selected; if (selected == menunum) selected = 0; if (whichmenu >= 0) menuhistory[whichmenu] = selected; redraw = 1; break; case 0x1b: if (MENU_MAIN == whichmenu && menuexit != selected) { selected = menuexit; redraw = 1; break; } menudelta = 1; return menuexit; } } } menudelta = 0; return menuexit; } static void menustart() { menunum = -1; menuput = menustring; *menuput = 0; menuexit = 0; } static void additem_s(char* item, int len) { if (len < 0 || (menustring + sizeof(menustring) - menuput <= len)) return; if (menunum < 0) menutitle = menuput; else menuitems[menunum] = menuput; ++menunum; memcpy(menuput, item, len + 1); menuput += len + 1; } static void additem(char* item, ...) { char output[256]; va_list ap; int len; va_start(ap, item); len = vsnprintf(output, sizeof(output), item, ap); if (len >= 256) len = 255; /* truncated string */ additem_s(output, len); } static void addexit(char* item, ...) { char output[256]; va_list ap; int len; va_start(ap, item); len = vsnprintf(output, sizeof(output), item, ap); if (len >= 256) len = 255; /* truncated string */ menuexit = menunum; additem_s(output, len); } /* end generic menu */ /* game menues */ static const char* densities[] = {"PACKED", "HIGH", "MEDIUM", "LOW"}; static const char* generosities[] = {"LOW", "MEDIUM", "HIGH", "RIDICULOUS"}; static const char* dis_en_abled[] = {"DISABLED", "ENABLED"}; static void config_menu(void) { int sel; while (!exitflag) { menustart(); additem("GAME OPTIONS"); additem("RETURN TO MAIN MENU"); additem("DENSITY: %s", densities[configopts.density]); additem("GENEROSITY: %s", generosities[configopts.generosity]); additem("INITIAL FLAME LENGTH: %d", configopts.flames + 1); additem("INITIAL NUMBER OF BOMBS: %d", configopts.bombs + 1); additem("SOUND: %s", dis_en_abled[sound_enabled]); sel = domenu(MENU_CONFIG, NULL); switch (sel) { case 0: return; case 1: configopts.density += menudelta; configopts.density &= 3; break; case 2: configopts.generosity += menudelta; configopts.generosity &= 3; break; case 3: configopts.flames += menudelta; configopts.flames &= 7; break; case 4: configopts.bombs += menudelta; configopts.bombs &= 7; break; case 5: sound_enabled = 1 - sound_enabled; break; } } } static void draw_host_game(void) { int i; char* name; char temp[64]; #define M3X (IXSIZE / 3) #define M3Y (IYSIZE / 4) clear(); centerbig(20, "HOST NETWORK GAME"); drawbigstring(M3X, M3Y, "SLOT NAME"); for (i = 0; i < MAXNETNODES; ++i) { if (!netnodes[i].used) continue; name = netnodes[i].name; snprintf(temp, sizeof(temp), " %d %s", i + 1, name); drawbigstring(M3X, M3Y + (i + 2) * bigfontyspace, temp); } copyup(); } static void host_game(void) { create_seed_unique(); if (!start_network_game()) { failure("COULD NOT REGISTER GAME"); return; } draw_host_game(); for (;;) { scaninput(); while (anydown()) { switch (takedown()) { case 0x1b: unregistergame(); cancel_network_game(); return; case ' ': case 13: unregistergame(); if (begin_network_game()) { run_network_game(); return; } send_invites(); draw_host_game(); } } if (!handle_joins()) continue; send_invites(); draw_host_game(); } } static void drawjoinscreen(void) { int i; char name[17]; char temp[64]; #define JX (IXSIZE / 3) #define JY (IYSIZE / 4) clear(); centerbig(20, "JOIN NETWORK GAME"); drawbigstring(JX, JY, "SLOT NAME"); for (i = 0; i < MAXNETNODES; ++i) { if (!netnodes[i].used) continue; memmove(name, netnodes[i].name, 16); name[16] = 0; snprintf(temp, sizeof(temp), " %d %s", i + 1, name); drawbigstring(JX, JY + (i + 1) * bigfontyspace, temp); } } static int tryjoin(int which) { int res; if (0 == (res = send_join(&gamelistentries[which].netname, playername))) { return 0; } while (!exitflag) { switch (res) { case 1: failure("Game closed"); return 0; case 2: drawjoinscreen(); copyup(); break; case 3: return 1; default: break; } scaninput(); while (anydown()) { switch (takedown()) { case 0x1b: send_quit(); return 0; } } res = scaninvite(200); } return 0; } static int join_game_pause(void) { if (find_more_games()) return 0; mypause(); return 1; } static void join_game(void) { int i; int sel = -1; if (!searchgames()) { return; } menuhistory[MENU_JOIN] = 0; while (-1 == sel) { menustart(); if (gamelistsize == 0) { additem("JOIN NETWORK GAME - NO GAMES AVAILABLE"); addexit("EXIT"); } else { additem("JOIN NETWORK GAME"); for (i = 0; i < gamelistsize; i++) { additem(gamelistentries[i].name); } addexit("EXIT"); } sel = domenu(MENU_JOIN, join_game_pause); if (menudelta < 0) sel = -1; } stop_search(); if (menuexit == sel || !gamelistsize) { return; } if (!tryjoin(sel)) { return; } run_network_game(); } void mainloop(void) { int sel; exitflag = 0; while (!exitflag) { menustart(); additem("BOMBER MAIN MENU"); additem("EXIT GAME"); additem("START SINGLE PLAYER GAME"); additem("OPTIONS"); // additem("REMAP MOVEMENT KEYS"); additem("START NETWORK GAME"); additem("JOIN NETWORK GAME"); sel = domenu(MENU_MAIN, NULL); if (menudelta < 0) sel = -1; switch (sel) { case 0: return; case 1: run_single_player(); break; case 2: config_menu(); break; case 3: host_game(); break; case 4: join_game(); break; } } }