You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

menu.c 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #include "bomber.h"
  2. #include "menu.h"
  3. #include "draw.h"
  4. #include "gfx.h"
  5. #include "utils.h"
  6. #include "sound.h"
  7. #include "network.h"
  8. #include "announce.h"
  9. #include "game.h"
  10. GameOptions configopts = { 2, 1, 0, 2 };
  11. /* Generic menu */
  12. typedef enum {
  13. MENU_ANY = -1,
  14. MENU_MAIN = 0,
  15. MENU_CONFIG = 2,
  16. MENU_JOIN = 3
  17. } menuname;
  18. #define MENU_SELECT(x) ((menuname) (-x-1))
  19. static int menuhistory[32]={0};
  20. static char menustring[1024];
  21. static char *menuput,*menuitems[40],*menutitle;
  22. static int menunum, menuexit;
  23. static int menudelta;
  24. static void drawmenu(int selected) {
  25. int i,j;
  26. int tx,ty;
  27. clear();
  28. j=strlen(menutitle)*bigfontxsize;
  29. drawbigstring((IXSIZE-j) >> 1,20,menutitle);
  30. ty=((IYSIZE-(bigfontysize*menunum))>>1)-(IYSIZE>>3);
  31. for(i=0;i<menunum;++i)
  32. {
  33. j=strlen(menuitems[i])*bigfontxsize;
  34. tx=(IXSIZE-j) >> 1;
  35. if(i==selected)
  36. {
  37. greyrect(0,ty-1,tx-5,bigfontysize);
  38. greyrect(tx+j+3,ty-1,IXSIZE-(tx+j+3),bigfontysize);
  39. }
  40. drawbigstring(tx,ty,menuitems[i]);
  41. ty+=bigfontyspace;
  42. }
  43. }
  44. static int domenu(menuname whichmenu, int (*pause)(void)) {
  45. char redraw;
  46. int selected;
  47. int mcount=0;
  48. if(whichmenu>=0)
  49. selected=menuhistory[whichmenu];
  50. else
  51. selected=-whichmenu-1;
  52. if (!pause) pause=mypause;
  53. redraw=1;
  54. clearspritelist();
  55. while(!exitflag) {
  56. if(redraw) {
  57. drawmenu(selected);
  58. redraw=0;
  59. }
  60. if (!pause()) return -1;
  61. scaninput();
  62. ++mcount;
  63. clearsprites();
  64. clearspritelist();
  65. addsprite(IXSIZE/2-50-20,IYSIZE-80,walking[2]+(30+mcount%15));
  66. addsprite(IXSIZE/2+50-20,IYSIZE-80,walking[3]+(30+(mcount+7)%15));
  67. plotsprites();
  68. copyup();
  69. if(anydown()) playsound(3);
  70. while(anydown()) {
  71. switch(takedown()) {
  72. case MYLEFT:
  73. menudelta=-1;
  74. return selected;
  75. case MYRIGHT:
  76. case ' ':
  77. case 13:
  78. menudelta=1;
  79. return selected;
  80. case 'k':
  81. case MYUP:
  82. if (selected) --selected;
  83. else selected=menunum-1;
  84. if (whichmenu>=0)
  85. menuhistory[whichmenu]=selected;
  86. redraw=1;
  87. break;
  88. case 'j':
  89. case MYDOWN:
  90. ++selected;
  91. if (selected==menunum) selected=0;
  92. if (whichmenu>=0)
  93. menuhistory[whichmenu]=selected;
  94. redraw=1;
  95. break;
  96. case 0x1b:
  97. if (MENU_MAIN == whichmenu && menuexit != selected) {
  98. selected = menuexit;
  99. redraw = 1;
  100. break;
  101. }
  102. menudelta = 1;
  103. return menuexit;
  104. }
  105. }
  106. }
  107. menudelta = 0;
  108. return menuexit;
  109. }
  110. static void menustart() {
  111. menunum=-1;
  112. menuput=menustring;
  113. *menuput=0;
  114. menuexit = 0;
  115. }
  116. static void additem_s(char *item, int len) {
  117. if (len < 0 || (menustring+sizeof(menustring)-menuput <= len)) return;
  118. if(menunum<0)
  119. menutitle=menuput;
  120. else
  121. menuitems[menunum]=menuput;
  122. ++menunum;
  123. memcpy(menuput,item,len+1);
  124. menuput += len+1;
  125. }
  126. static void additem(char *item,...) {
  127. char output[256];
  128. va_list ap;
  129. int len;
  130. va_start(ap, item);
  131. len = vsnprintf(output,sizeof(output),item,ap);
  132. if (len >= 256) len = 255; /* truncated string */
  133. additem_s(output, len);
  134. }
  135. static void addexit(char *item,...) {
  136. char output[256];
  137. va_list ap;
  138. int len;
  139. va_start(ap, item);
  140. len = vsnprintf(output,sizeof(output),item,ap);
  141. if (len >= 256) len = 255; /* truncated string */
  142. menuexit = menunum;
  143. additem_s(output, len);
  144. }
  145. /* end generic menu */
  146. /* game menues */
  147. static const char *densities[]={"PACKED","HIGH","MEDIUM","LOW"};
  148. static const char *generosities[]={"LOW","MEDIUM","HIGH","RIDICULOUS"};
  149. static const char *dis_en_abled[]={"DISABLED","ENABLED"};
  150. static void config_menu(void) {
  151. int sel;
  152. while (!exitflag) {
  153. menustart();
  154. additem("GAME OPTIONS");
  155. additem("RETURN TO MAIN MENU");
  156. additem("DENSITY: %s",densities[configopts.density]);
  157. additem("GENEROSITY: %s",generosities[configopts.generosity]);
  158. additem("INITIAL FLAME LENGTH: %d",configopts.flames+1);
  159. additem("INITIAL NUMBER OF BOMBS: %d",configopts.bombs+1);
  160. additem("SOUND: %s", dis_en_abled[sound_enabled]);
  161. sel=domenu(MENU_CONFIG, NULL);
  162. switch (sel) {
  163. case 0:
  164. return;
  165. case 1:
  166. configopts.density+=menudelta;
  167. configopts.density&=3;
  168. break;
  169. case 2:
  170. configopts.generosity+=menudelta;
  171. configopts.generosity&=3;
  172. break;
  173. case 3:
  174. configopts.flames+=menudelta;
  175. configopts.flames&=7;
  176. break;
  177. case 4:
  178. configopts.bombs+=menudelta;
  179. configopts.bombs&=7;
  180. break;
  181. case 5:
  182. sound_enabled = 1 - sound_enabled;
  183. break;
  184. }
  185. }
  186. }
  187. static void draw_host_game(void) {
  188. int i;
  189. char *name;
  190. char temp[64];
  191. #define M3X (IXSIZE/3)
  192. #define M3Y (IYSIZE/4)
  193. clear();
  194. centerbig(20,"HOST NETWORK GAME");
  195. drawbigstring(M3X,M3Y,"SLOT NAME");
  196. for(i=0;i<MAXNETNODES;++i) {
  197. if(!netnodes[i].used) continue;
  198. name=netnodes[i].name;
  199. sprintf(temp," %d %s",i+1,name);
  200. drawbigstring(M3X,M3Y+(i+2)*bigfontyspace,temp);
  201. }
  202. copyup();
  203. }
  204. static void host_game(void) {
  205. create_seed_unique();
  206. if (!start_network_game()) {
  207. failure("COULD NOT REGISTER GAME");
  208. return;
  209. }
  210. draw_host_game();
  211. for(;;) {
  212. scaninput();
  213. while(anydown()) {
  214. switch(takedown()) {
  215. case 0x1b:
  216. unregistergame();
  217. cancel_network_game();
  218. return;
  219. case ' ':
  220. case 13:
  221. unregistergame();
  222. if (begin_network_game()) {
  223. run_network_game();
  224. return;
  225. }
  226. send_invites();
  227. draw_host_game();
  228. }
  229. }
  230. if (!handle_joins()) continue;
  231. send_invites();
  232. draw_host_game();
  233. }
  234. }
  235. static void drawjoinscreen(void) {
  236. int i;
  237. char name[17];
  238. char temp[64];
  239. #define JX (IXSIZE/3)
  240. #define JY (IYSIZE/4)
  241. clear();
  242. centerbig(20,"JOIN NETWORK GAME");
  243. drawbigstring(JX,JY,"SLOT NAME");
  244. for (i = 0; i < MAXNETNODES; ++i) {
  245. if(!netnodes[i].used) continue;
  246. memmove(name,netnodes[i].name,16);
  247. name[16]=0;
  248. sprintf(temp," %d %s",i+1,name);
  249. drawbigstring(JX,JY+(i+1)*bigfontyspace,temp);
  250. }
  251. }
  252. static int tryjoin(int which) {
  253. int res;
  254. if (0 == (res = send_join(&gamelistentries[which].netname, playername))) {
  255. return 0;
  256. }
  257. while (!exitflag) {
  258. switch (res) {
  259. case 1:
  260. failure("Game closed");
  261. return 0;
  262. case 2:
  263. drawjoinscreen();
  264. copyup();
  265. break;
  266. case 3: return 1;
  267. default: break;
  268. }
  269. scaninput();
  270. while(anydown()) {
  271. switch(takedown()) {
  272. case 0x1b:
  273. send_quit();
  274. return 0;
  275. }
  276. }
  277. res=scaninvite(200);
  278. }
  279. return 0;
  280. }
  281. static int join_game_pause(void) {
  282. if (find_more_games()) return 0;
  283. mypause();
  284. return 1;
  285. }
  286. static void join_game(void) {
  287. int i;
  288. int sel = -1;
  289. if (!searchgames()) {
  290. return;
  291. }
  292. menuhistory[MENU_JOIN] = 0;
  293. while (-1 == sel) {
  294. menustart();
  295. if (gamelistsize == 0) {
  296. additem("JOIN NETWORK GAME - NO GAMES AVAILABLE");
  297. addexit("EXIT");
  298. } else {
  299. additem("JOIN NETWORK GAME");
  300. for (i = 0; i < gamelistsize; i++) {
  301. additem(gamelistentries[i].name);
  302. }
  303. addexit("EXIT");
  304. }
  305. sel = domenu(MENU_JOIN, join_game_pause);
  306. if (menudelta < 0) sel = -1;
  307. }
  308. stop_search();
  309. if(menuexit == sel || !gamelistsize) {
  310. return;
  311. }
  312. if(!tryjoin(sel)) {
  313. return;
  314. }
  315. run_network_game();
  316. }
  317. void mainloop(void) {
  318. int sel;
  319. exitflag = 0;
  320. while(!exitflag) {
  321. menustart();
  322. additem("BOMBER MAIN MENU");
  323. additem("EXIT GAME");
  324. additem("START SINGLE PLAYER GAME");
  325. additem("OPTIONS");
  326. // additem("REMAP MOVEMENT KEYS");
  327. additem("START NETWORK GAME");
  328. additem("JOIN NETWORK GAME");
  329. sel=domenu(MENU_MAIN, NULL);
  330. if (menudelta < 0) sel = -1;
  331. switch (sel) {
  332. case 0:
  333. return;
  334. case 1:
  335. run_single_player();
  336. break;
  337. case 2:
  338. config_menu();
  339. break;
  340. case 3:
  341. host_game();
  342. break;
  343. case 4:
  344. join_game();
  345. break;
  346. }
  347. }
  348. }