/*
*****************************************
* This is Snake 256!                    *
* Author: Tony Wasserka                 *
* Version: 0.0.3                        *
* License: GPL                          *
* See Readme.txt                        *
* Enjoy this!                           *
*****************************************
*/

#include "snake.h"

#define MENU_MAIN_MENU                 0
#define MENU_OPTIONS_MENU              1
#define MENU_OPTIONS_GFX_MENU          2
#define MENU_OPTIONS_SFX_MENU          3
#define MENU_OPTIONS_GAME_MENU         4
#define MENU_OPTIONS_GAME_PLAYERS_MENU 5

#define MENU_OPTIONS_GFX  0
#define MENU_OPTIONS_SFX  1
#define MENU_OPTIONS_GAME 2
#define MENU_OPTIONS_BACK 3

#define MENU_OPTIONS_GFX_ANTIAL   0
#define MENU_OPTIONS_GFX_RESOL    1
#define MENU_OPTIONS_GFX_COLDEPTH 2
#define MENU_OPTIONS_GFX_FPS      3
#define MENU_OPTIONS_GFX_VSYNC    4
#define MENU_OPTIONS_GFX_BACK     5

#define MENU_OPTIONS_SFX_MUSIC 0
#define MENU_OPTIONS_SFX_SOUND 1
#define MENU_OPTIONS_SFX_BACK  2

#define MENU_OPTIONS_GAME_PLAYERS 0
#define MENU_OPTIONS_GAME_BACK    1

#define MENU_OPTIONS_GAME_PLAYERS_NUM    0
#define MENU_OPTIONS_GAME_PLAYERS_PLAYER 1
#define MENU_OPTIONS_GAME_PLAYERS_ISCPU  2
#define MENU_OPTIONS_GAME_PLAYERS_COLTP  3
#define MENU_OPTIONS_GAME_PLAYERS_COLOR  4
#define MENU_OPTIONS_GAME_PLAYERS_LEFT   5
#define MENU_OPTIONS_GAME_PLAYERS_RIGHT  6
#define MENU_OPTIONS_GAME_PLAYERS_FAST   7
#define MENU_OPTIONS_GAME_PLAYERS_BACK   8

#define BUTTONCOL makecol(128, 128, 128)
#define FONTCOL makecol(255, 255, 255)

int Config::antialias;
bool Config::first_start;
int Config::card;
int Config::screenw;
int Config::screenh;
int Config::bpp;
int Config::num_gfx_mode;
bool Config::show_fps;
bool Config::do_vsync;
int Config::music_volume, Config::sound_volume;
int Config::num_snakes;
int Config::colconfig_method[8];
int Config::r[8], Config::g[8], Config::b[8];
KEY_TABLE Config::keys[8];
bool Config::is_cpu[8];

int choice = MENU_SINGLEPLAYER;
float scrolly = 0;

int predefined_cols[81];

void GetConfig()
{
 char buf[256];
 ifstream file;
 char proof[4];
 bool failure = false;

 get_executable_name(buf, sizeof(buf));
 replace_filename(buf, buf, "Config.cfg", sizeof(buf));

 file.open(buf);

 if(!exists(buf) || !file) failure = true;
 else
 {
  file >> proof;
  if(strcmp(proof, "0030") != 0)
  {
   failure = true;
   file.close();
  }
 }
 if(failure)
 {
  allegro_message("Error! Couldn't find the configuration file!\n Configuration will be set to default.");

  Config::antialias = false;
#ifdef ALLEGRO_WINDOWS
  Config::card = GFX_DIRECTX_ACCEL;
#else
  Config::card = GFX_XWINDOWS;
#endif
  Config::first_start = true;
  Config::screenw = 800;
  Config::screenh = 600;
  Config::bpp = 16;
  Config::show_fps = false;
  Config::do_vsync = false;
  Config::music_volume = 255;
  Config::sound_volume = 255;
  Config::num_snakes = 4;
  for(int a = 0;a < 8;a++)
  {
   Config::colconfig_method[a] = 3;
   Config::r[a] = rand() % 256;
   Config::g[a] = rand() % 256;
   Config::b[a] = rand() % 256;
   Config::keys[a].left = KEY_LEFT;
   Config::keys[a].right = KEY_RIGHT;
   Config::keys[a].fast = KEY_UP;
   Config::is_cpu[a] = false;
  }
  return;
 }
 file >> Config::antialias;
 file >> Config::card;
 if((Config::first_start = (Config::card == GFX_AUTODETECT)))
#ifdef ALLEGRO_WINDOWS
  Config::card = GFX_DIRECTX_ACCEL;
#else
  Config::card = GFX_XDGA2;
#endif
 file >> Config::screenw;
 file >> Config::screenh;
 file >> Config::bpp;
 file >> Config::num_gfx_mode;
 file >> Config::show_fps;
 file >> Config::do_vsync;
 file >> Config::music_volume;
 file >> Config::sound_volume;
 file >> Config::num_snakes;
 for(int a = 0;a < 8;a++)
 {
  file >> Config::colconfig_method[a];
  file >> Config::r[a];
  file >> Config::g[a];
  file >> Config::b[a];
  file >> Config::keys[a].left;
  file >> Config::keys[a].right;
  file >> Config::keys[a].fast;
  file >> Config::is_cpu[a];
 }
 file.close();
}

void SaveConfig()
{
 char buf[256];
 ofstream file;

 get_executable_name(buf, sizeof(buf));
 replace_filename(buf, buf, "Config.cfg", sizeof(buf));

 file.open(buf);

 file << "0030" << endl;
 file << Config::antialias << endl;
 file << Config::card << endl;
 file << Config::screenw << endl;
 file << Config::screenh << endl;
 file << Config::bpp << endl;
 file << Config::num_gfx_mode << endl;
 file << Config::show_fps << endl;
 file << Config::do_vsync << endl;
 file << Config::music_volume << endl;
 file << Config::sound_volume << endl;
 file << Config::num_snakes << endl;
 for(int a = 0;a < 8;a++)
 {
  file << Config::colconfig_method[a] << endl;
  file << getr(snake[a].color) << endl;
  file << getg(snake[a].color) << endl;
  file << getb(snake[a].color) << endl;
  file << Config::keys[a].left << endl;
  file << Config::keys[a].right << endl;
  file << Config::keys[a].fast << endl;
  file << Config::is_cpu[a] << endl;
 }
 file.close();
}

void DrawButton(BITMAP *bmp, int x1, int y1, int x2, int y2, char *text, bool chosen)
{
 rectfill(bmp, x1, y1, x2, y2, BUTTONCOL);
 alfont_textout_centre_ex(bmp, myfont[FONT_NORMAL], text, (x1 + x2) / 2, ((y1 + y2) >> 1) - 4, FONTCOL * chosen, -1);
}

int DoMenu()
{
 int cur_menu = MENU_MAIN_MENU;
 bool end = false;
 float counter = 0;
 char buf[64];
 int subtitlecol;
 int chosen_player = 0;
 int predef_col = 0;
 int adjusts_keys = 0;
 int configures_colors = 0;
 BITMAP *buttons = create_sub_bitmap(screenbmp, 0, 50, SCREEN_W, SCREEN_H - 100);

 clear_bitmap(buttons);

 for(int c = 0;c < 27;c++)
 {
  predefined_cols[c * 3 + 2] = (int)((c % 3) * 127.5);
  predefined_cols[c * 3 + 1] = (int)(((c / 3) % 3) * 127.5);
  predefined_cols[c * 3] = (int)((c / 9) * 127.5);
 }
 clear_keybuf();

 while(!end)
 {
  if(dtime)
#ifdef ALLEGRO_WINDOWS
   QueryPerformanceCounter((LARGE_INTEGER*)(&start_t));
#else
   gettimeofday(&start_t, NULL);
#endif

  subtitlecol = (int)((counter - 2) * 255);

  if(keypressed())
   if(!adjusts_keys)
    switch(readkey() >> 8)
    {
     case KEY_UP: if(!configures_colors) choice--;
                   else configures_colors--; counter = 0; break;
     case KEY_DOWN: if(!configures_colors) choice++;
                     else configures_colors++;
                     if(configures_colors > 3) configures_colors = 0;
                     counter = 0; break;
     case KEY_SPACE:
     case KEY_ENTER:
           switch(cur_menu)
           {
            case MENU_MAIN_MENU:
                  if(choice != MENU_OPTIONS) end = true;
                  else cur_menu = MENU_OPTIONS_MENU;
                  break;
            case MENU_OPTIONS_MENU:
                  switch(choice)
                  {
                   case MENU_OPTIONS_GFX: cur_menu = MENU_OPTIONS_GFX_MENU; break;
                   case MENU_OPTIONS_SFX: cur_menu = MENU_OPTIONS_SFX_MENU; break;
                   case MENU_OPTIONS_GAME: cur_menu = MENU_OPTIONS_GAME_MENU;break;
                   case MENU_OPTIONS_BACK: cur_menu = MENU_MAIN_MENU; break;
                  }
                  break;
            case MENU_OPTIONS_GFX_MENU:
                  switch(choice)
                  {
                   case MENU_OPTIONS_GFX_ANTIAL:
                        if(++(Config::antialias) > 4) Config::antialias = 0;

                        clear_bitmap(screen);
                        break;
                   case MENU_OPTIONS_GFX_RESOL:
                         {
                          GFX_MODE_LIST *gfx_mode_list;

                          gfx_mode_list = get_gfx_mode_list(Config::card);

                          for(int num_mode = Config::num_gfx_mode + 1;;num_mode++)
                          {
                           if(gfx_mode_list->mode[num_mode].width >= 640 && gfx_mode_list->mode[num_mode].height >= 400 &&
                              gfx_mode_list->mode[num_mode].bpp >= 15)
                           {
                            Config::screenw = gfx_mode_list->mode[num_mode].width;
                            Config::screenh = gfx_mode_list->mode[num_mode].height;
                            Config::bpp = gfx_mode_list->mode[num_mode].bpp;

                            set_color_depth(Config::bpp);
                            set_gfx_mode(Config::card, Config::screenw, Config::screenh, 0, 0);

                            destroy_bitmap(buttons);
                            destroy_bitmap(screenbmp);
                            screenbmp = create_bitmap(Config::screenw, Config::screenh);
                            clear_bitmap(screenbmp);
                            buttons = create_sub_bitmap(screenbmp, 0, 50, SCREEN_W, SCREEN_H - 100);
                            clear_bitmap(buttons);

                            Config::num_gfx_mode = num_mode;
                            break;
                           }
                           else if(gfx_mode_list->mode[num_mode].width == 0)
                            num_mode = 0;

                           Config::num_gfx_mode = num_mode;
                          }
                          destroy_gfx_mode_list(gfx_mode_list);
                         }
                         break;
                   case MENU_OPTIONS_GFX_COLDEPTH: break;
                   case MENU_OPTIONS_GFX_FPS:
                         Config::show_fps = !Config::show_fps;
                         break;
                   case MENU_OPTIONS_GFX_VSYNC:
                         Config::do_vsync = !Config::do_vsync;
                         break;
                   case MENU_OPTIONS_GFX_BACK: cur_menu = MENU_OPTIONS_MENU; break;
                 }
                 break;
            case MENU_OPTIONS_SFX_MENU:
                  switch(choice)
                  {
                   case MENU_OPTIONS_SFX_MUSIC:
                         Config::music_volume++;
                         if(Config::music_volume > 255) Config::music_volume = 0;
                         break;
                   case MENU_OPTIONS_SFX_SOUND:
                         Config::sound_volume++;
                         if(Config::sound_volume > 255) Config::sound_volume = 0;
                         break;
                   case MENU_OPTIONS_SFX_BACK: cur_menu = MENU_OPTIONS_MENU; break;
                 }
                 break;
            case MENU_OPTIONS_GAME_MENU:
                  switch(choice)
                  {
                   case MENU_OPTIONS_GAME_PLAYERS: cur_menu = MENU_OPTIONS_GAME_PLAYERS_MENU; break;
                   case MENU_OPTIONS_GAME_BACK: cur_menu = MENU_OPTIONS_MENU; break;
                  }
                  break;
            case MENU_OPTIONS_GAME_PLAYERS_MENU:
                  switch(choice)
                  {
                   case MENU_OPTIONS_GAME_PLAYERS_NUM: Config::num_snakes++; if (Config::num_snakes > 8) Config::num_snakes = 1; break;
                   case MENU_OPTIONS_GAME_PLAYERS_PLAYER: chosen_player++; if(chosen_player >= Config::num_snakes) chosen_player = 0; break;
                   case MENU_OPTIONS_GAME_PLAYERS_ISCPU: Config::is_cpu[chosen_player] = !Config::is_cpu[chosen_player]; break;
                   case MENU_OPTIONS_GAME_PLAYERS_COLTP:
                         Config::colconfig_method[chosen_player]++;
                         if(Config::colconfig_method[chosen_player] > 3) Config::colconfig_method[chosen_player] = 0;
                         else if(Config::colconfig_method[chosen_player] == 1)
                         {
                          snake[chosen_player].color = makecol(predefined_cols[0], predefined_cols[1],
                                                               predefined_cols[2]);
                          Config::r[chosen_player] = predefined_cols[0];
                          Config::g[chosen_player] = predefined_cols[1];
                          Config::b[chosen_player] = predefined_cols[2];
                         }
                   case MENU_OPTIONS_GAME_PLAYERS_COLOR:
                         switch(Config::colconfig_method[chosen_player])
                         {
                          case 0:
                                switch(configures_colors)
                                {
                                 case 0: configures_colors = 1; break;
                                 case 1: Config::r[chosen_player]++; if(Config::r[chosen_player] > 255) Config::r[chosen_player] = 0; break;
                                 case 2: Config::g[chosen_player]++; if(Config::g[chosen_player] > 255) Config::g[chosen_player] = 0; break;
                                 case 3: Config::b[chosen_player]++; if(Config::b[chosen_player] > 255) Config::b[chosen_player] = 0; break;
                                }
                                snake[chosen_player].color = makecol(Config::r[chosen_player], Config::g[chosen_player], Config::b[chosen_player]);
                                break;
                          case 1:
                                predef_col++; if(predef_col > 26) predef_col = 0;
                                snake[chosen_player].color = makecol(predefined_cols[predef_col * 3], predefined_cols[predef_col * 3 + 1],
                                                                     predefined_cols[predef_col * 3 + 2]);
                                Config::r[chosen_player] = predefined_cols[predef_col * 3];
                                Config::g[chosen_player] = predefined_cols[predef_col * 3 + 1];
                                Config::b[chosen_player] = predefined_cols[predef_col * 3 + 2];
                                break;
                          case 2:
                                Config::r[chosen_player] = rand() % 256;
                                Config::g[chosen_player] = rand() % 256;
                                Config::b[chosen_player] = rand() % 256;
                                snake[chosen_player].color = makecol(Config::r[chosen_player], Config::g[chosen_player], Config::b[chosen_player]);
                                break;
                         }
                         break;
                   case MENU_OPTIONS_GAME_PLAYERS_LEFT: adjusts_keys = 1; break;
                   case MENU_OPTIONS_GAME_PLAYERS_RIGHT: adjusts_keys = 2; break;
                   case MENU_OPTIONS_GAME_PLAYERS_FAST: adjusts_keys = 3; break;
                   case MENU_OPTIONS_GAME_PLAYERS_BACK: cur_menu = MENU_OPTIONS_GAME_MENU; break;
                  }
                  break;
           }
           break;
    }
   else
   {
    switch(adjusts_keys)
    {
     case 1: Config::keys[chosen_player].left = readkey() >> 8; break;
     case 2: Config::keys[chosen_player].right = readkey() >> 8; break;
     case 3: Config::keys[chosen_player].fast = readkey() >> 8; break;
    }
    adjusts_keys = 0;
   }

  clear_keybuf();

  switch(cur_menu)
  {
   case MENU_MAIN_MENU:
   case MENU_OPTIONS_MENU:
        if(choice > MENU_EXIT) choice = 0;
        else if(choice < 0) choice = MENU_EXIT;
        break;
   case MENU_OPTIONS_GFX_MENU:
        if(choice > MENU_OPTIONS_GFX_BACK) choice = 0;
        else if(choice < 0) choice = MENU_OPTIONS_GFX_BACK;
        break;
   case MENU_OPTIONS_SFX_MENU:
        if(choice > MENU_OPTIONS_SFX_BACK) choice = 0;
        else if(choice < 0) choice = MENU_OPTIONS_SFX_BACK;
        break;
   case MENU_OPTIONS_GAME_MENU:
        if(choice > MENU_OPTIONS_GAME_BACK) choice = 0;
        else if(choice < 0) choice = MENU_OPTIONS_GAME_BACK;
        break;
   case MENU_OPTIONS_GAME_PLAYERS_MENU:
        if(choice > MENU_OPTIONS_GAME_PLAYERS_BACK) choice = 0;
        else if(choice < 0) choice = MENU_OPTIONS_GAME_PLAYERS_BACK;
        break;
  }
  if(buttons->h * (choice + 2) * 3 / 13 + 50 > buttons->h + scrolly) scrolly += (buttons->h * (choice + 1) * 3 / 13 + 50 - buttons->h - scrolly) *
                                                                                 dtime * 2;
  if(buttons->h * choice * 3 / 13 - 50 < scrolly) scrolly -= (scrolly - buttons->h * choice * 3 / 13 + 50) * dtime * 2;
  if(scrolly < 0) scrolly = 0;

  alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SNAKE256], SCREEN_W / 2, SCREEN_H / 17 - alfont_get_font_height(myfont[FONT_SNAKE256])/2,
                       makecol(255, 255, 255), -1, "Snake 256");
  switch(cur_menu)
  {
   case MENU_MAIN_MENU:
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 3 / 13, "Singleplayer",
                   (choice == 0) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 4 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 6 / 13, "Multiplayer",
                   (choice == 1) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 7 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 9 / 13, "Options",
                   (choice == 2) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 10 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 12 / 13,  "Exit",
                   (choice == 3) ? 0 : 1);
        switch(choice)
        {
         case 0:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Start a new singleplayer game; not supported, yet");
               break;
         case 1:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Start a new multiplayer game");
               break;
         case 2:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Configure graphics, sound and the game");
               break;
         case 3:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Exit to the OS");
               break;
        }
        break;
   case MENU_OPTIONS_MENU:
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 3 / 13, "GFX",
                   (choice == 0) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 4 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 6 / 13, "SFX",
                   (choice == 1) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 7 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 9 / 13, "Game",
                   (choice == 2) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 10 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 12 / 13,  "Back",
                   (choice == 3) ? 0 : 1);
        switch(choice)
        {
         case 0:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Configure graphics");
               break;
         case 1:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Configure sound");
               break;
         case 2:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Configure the game");
               break;
         case 3:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Back to the main menu");
               break;
        }
        break;
   case MENU_OPTIONS_GFX_MENU:
        sprintf(buf, "Antialiasing: %s", (Config::antialias == 4) ? "4x" : (Config::antialias == 3) ? "3x" : (Config::antialias == 2) ? "2x" :
                                         (Config::antialias == 1) ? "1x" : "Off");
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 3 / 13 - (int)scrolly, buf,
                   (choice == 0) ? 0 : 1);
        sprintf(buf, "Resolution: %dx%dx%d", Config::screenw, Config::screenh, Config::bpp);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 4 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 6 / 13 - (int)scrolly, buf,
                   (choice == 1) ? 0 : 1);
        sprintf(buf, "Driver: %s", gfx_driver->name);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 7 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 9 / 13 - (int)scrolly, buf,
                   (choice == 2) ? 0 : 1);
        sprintf(buf, "Show FPS: %s", (Config::show_fps) ? "Yes" : "No");
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 10 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 12 / 13 - (int)scrolly, buf,
                   (choice == 3) ? 0 : 1);
        sprintf(buf, "Vsync: %s", (Config::do_vsync) ? "On" : "Off");
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 13 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 15 / 13 - (int)scrolly, buf,
                   (choice == 4) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 16 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 18 / 13 - (int)scrolly, "Back",
                   (choice == 5) ? 0 : 1);

        switch(choice)
        {
         case 0:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Adjusts antialiasing");
               break;
         case 1:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Changes the resolution");
               break;
         case 2:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "This yet does nothing");
               break;
         case 3:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Turns the FPS display on or off");
               break;
         case 4:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Turns the vertical retrace on or off");
               break;
         case 5:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Back to the options menu");
               break;
        }
        break;
   case MENU_OPTIONS_SFX_MENU:
        sprintf(buf, "Music volume: %d", Config::music_volume);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 3 / 13,  buf,
                   (choice == 0) ? 0 : 1);
        sprintf(buf, "Sound volume: %d", Config::sound_volume);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 4 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 6 / 13,  buf,
                   (choice == 1) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 7 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 9 / 13, "Back",
                   (choice == 2) ? 0 : 1);
        switch(choice)
        {
         case 0:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Adjusts the music volume");
               break;
         case 1:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Adjusts the sound effects volume");
               break;
         case 2:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Back to the options menu");
               break;
        }
        break;
   case MENU_OPTIONS_GAME_MENU:
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 3 / 13,  "Players",
                   (choice == 0) ? 0 : 1);
        DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 4 / 13,
                   (SCREEN_W >> 1) + 200, buttons->h * 6 / 13,  "Back",
                   (choice == 1) ? 0 : 1);
        switch(choice)
        {
         case 0:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Adjusts the players");
               break;
         case 1:
               alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                    (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                    "Back to the options menu");
               break;
        }
        break;
   case MENU_OPTIONS_GAME_PLAYERS_MENU:
         sprintf(buf, "Number of players: %d", Config::num_snakes);
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 3 / 13 - (int)scrolly, buf,
                   (choice == 0) ? 0 : 1);
         sprintf(buf, "Player: %d", chosen_player + 1);
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 4 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 6 / 13 - (int)scrolly,  buf,
                   (choice == 1) ? 0 : 1);
         sprintf(buf, "Player is played by %s", (Config::is_cpu[chosen_player]) ? "the computer" : "a human");
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 7 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 9 / 13 - (int)scrolly,  buf,
                   (choice == 2) ? 0 : 1);
         sprintf(buf, "Color configuration method: %s", (Config::colconfig_method[chosen_player] == 0) ? "RGB" :
                 (Config::colconfig_method[chosen_player] == 1) ? "Predefined" : (Config::colconfig_method[chosen_player] == 2) ?
                 "Generate random now" : "Always random");
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 10 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 12 / 13 - (int)scrolly,  buf,
                   (choice == 3) ? 0 : 1);
         switch(Config::colconfig_method[chosen_player])
         {
          case 0:
          case 2:
                sprintf(buf, "Snake color: (%d; %d; %d)", Config::r[chosen_player], Config::g[chosen_player],
                        Config::b[chosen_player]);
                break;
          case 1:
                sprintf(buf, "Snake color: Predefined #%d", predef_col + 1); break;
                break;
          case 3:
                sprintf(buf, "Snake color: Random");
                break;

         }
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 15 / 13 - (int)scrolly,  buf,
                   (choice == 4 && !configures_colors) ? 0 : 1);
         sprintf(buf, "Key for steering left: %s", scancode_to_name(Config::keys[chosen_player].left));
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 16 / 13 - (int)scrolly,
                   (SCREEN_W>> 1) + 200, buttons->h * 18 / 13 - (int)scrolly,  buf,
                   (choice == 5) ? 0 : 1);
         sprintf(buf, "Key for steering right: %s", scancode_to_name(Config::keys[chosen_player].right));
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 19 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 21 / 13 - (int)scrolly,  buf,
                   (choice == 6) ? 0 : 1);
         sprintf(buf, "Key for going faster: %s", scancode_to_name(Config::keys[chosen_player].fast));
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 22 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 24 / 13 - (int)scrolly,  buf,
                   (choice == 7) ? 0 : 1);
         DrawButton(buttons, (SCREEN_W >> 1) - 200, buttons->h * 25 / 13 - (int)scrolly,
                   (SCREEN_W >> 1) + 200, buttons->h * 27 / 13 - (int)scrolly,  "Back",
                   (choice == 8) ? 0 : 1);
         if(Config::colconfig_method[chosen_player] != 3)
          rectfill(buttons, (SCREEN_W >> 1 ) + 160, buttons->h - (int)scrolly + 10, (SCREEN_W >> 1 ) + 190, buttons->h * 15 / 13 - (int)scrolly - 10,
                   snake[chosen_player].color);

         switch(choice)
         {
          case 0:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Adjusts the number of players in multiplayer mode");
                break;
          case 1:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Adjusts the player you want to configure");
                break;
          case 2:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Adjusts if the player is a human or the computer");
                break;
          case 3:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Changes the color configuration method");
                break;
          case 4:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Adjusts the snake's color");
                break;
          case 5:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Adjusts the key to steer to the left");
                break;
          case 6:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Adjusts the key to steer to the right");
                break;
          case 7:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Adjusts the key to move faster");
                break;
          case 8:
                alfont_textprintf_centre_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W / 2, SCREEN_H - 30,
                                     (counter > 2) ? makecol(subtitlecol, subtitlecol, subtitlecol) : makecol(0, 0, 0), -1,
                                     "Back to the game menu");
         }
         break;
  }
  if(Config::show_fps) alfont_textprintf_right_ex(screenbmp, myfont[FONT_NORMAL], SCREEN_W - 10, 10,
                                           makecol(255, 255, 255), -1,
                                           "FPS: %.2lf", fps);

  alfont_textprintf_right_ex(screenbmp, myfont[FONT_SUBTITLE], SCREEN_W, SCREEN_H - alfont_get_font_height(myfont[FONT_SUBTITLE]),
                      makecol(255, 255, 255), -1, "(C) 2005, 2006 Tony Wasserka");

  if(key[KEY_F12]) Screenshot();

  switch(Config::bpp)
  {
   case 32: switch_antialias(32); break;
   case 16: switch_antialias(16); break;
   case 15: switch_antialias(15); break;
   default: blit(screenbmp, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
  }

  clear_bitmap(screenbmp);
  if(Config::do_vsync) vsync();

#ifdef ALLEGRO_WINDOWS
  QueryPerformanceCounter((LARGE_INTEGER*)(&end_t));
  dtime = (float)(end_t - start_t) / frequency;
#else
  gettimeofday(&end_t, NULL);
  dtime = (end_t.tv_usec - start_t.tv_usec) / 1000000. + (end_t.tv_sec - start_t.tv_sec);
#endif
  counter += dtime * 4;
  if(counter > 3) counter = 3;
 }
 SaveConfig();

 destroy_bitmap(buttons);

 return choice;
}
