/* * Biloba * Copyright (C) 2004-2005 Guillaume Demougeot, Colin Leroy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** * Biloba - Q1 2005 * Game by Guillaume Demougeot * Code by Colin Leroy * * This file contains the options code used at startup. */ #include #include #include #include #include #include #include #include #include "utils.h" #include "arrow.h" #include "font.h" #include "player.h" #include "keyboard.h" #include "net.h" #include "game.h" #include "help.h" #include "msg.h" #define IS_DEMO 0 #define MAX_AGE (3600 * 24 * 30) static SDL_Surface *i_num_players = NULL; static SDL_Surface *i_players[5] = {NULL, NULL, NULL, NULL, NULL}; static SDL_Surface *i_highlighter = NULL; static SDL_Surface *i_create_game = NULL; static SDL_Surface *i_join_game = NULL; static SDL_Surface *i_start = NULL; static SDL_Surface *i_biloba_title = NULL; static SDL_Surface *i_local = NULL; static SDL_Surface *i_reseau = NULL; static SDL_Surface *i_computer = NULL; static SDL_Surface *i_empty_20040 = NULL; static SDL_Surface *i_empty_20050 = NULL; static SDL_Surface *i_empty_4040 = NULL; static SDL_Surface *i_game_name = NULL; static SDL_Surface *i_network_games = NULL; static SDL_Surface *i_help = NULL; static SDL_Surface *i_pawn[5] = {NULL, NULL, NULL, NULL, NULL}; static SDL_Surface *i_lfr = NULL, *i_len = NULL, *i_les = NULL; #define BILOBA_MIN_X (300) #define BILOBA_MAX_X (BILOBA_MIN_X+200) #define BILOBA_MIN_Y (20) #define BILOBA_MAX_Y (BILOBA_MIN_Y+50) #define IN_BILOBA(x,y) is_in_box(x,y,BILOBA_MIN_X,BILOBA_MIN_Y,BILOBA_MAX_X,BILOBA_MAX_Y) #define PLAYERS_MIN_X (50) #define PLAYERS_MAX_X (PLAYERS_MIN_X+400) #define PLAYERS_MIN_Y (100) #define PLAYERS_MAX_Y (PLAYERS_MIN_Y+50) #define IN_PLAYERS(x,y) is_in_box(x,y,PLAYERS_MIN_X,PLAYERS_MIN_Y,PLAYERS_MAX_X,PLAYERS_MAX_Y) #define NETGAMES_MIN_X (500) #define NETGAMES_MAX_X (NETGAMES_MIN_X+200) #define NETGAMES_MIN_Y (100) #define NETGAMES_MAX_Y (NETGAMES_MIN_Y+50) #define IN_NETGAMES(x,y) is_in_box(x,y,NETGAMES_MIN_X,NETGAMES_MIN_Y,NETGAMES_MAX_X,NETGAMES_MAX_Y) #define GAMENAME_MIN_X (50) #define GAMENAME_MAX_X (GAMENAME_MIN_X+350) #define GAMENAME_MIN_Y (400) #define GAMENAME_MAX_Y (GAMENAME_MIN_Y+50) #define IN_GAMENAME(x,y) is_in_box(x,y,GAMENAME_MIN_X,GAMENAME_MIN_Y,GAMENAME_MAX_X,GAMENAME_MAX_Y) #define CREATEGAME_MIN_X (50) #define CREATEGAME_MAX_X (CREATEGAME_MIN_X+200) #define CREATEGAME_MIN_Y (500) #define CREATEGAME_MAX_Y (CREATEGAME_MIN_Y+50) #define IN_CREATEGAME(x,y) is_in_box(x,y,CREATEGAME_MIN_X,CREATEGAME_MIN_Y,CREATEGAME_MAX_X,CREATEGAME_MAX_Y) #define JOINGAME_MIN_X (300) #define JOINGAME_MAX_X (JOINGAME_MIN_X+200) #define JOINGAME_MIN_Y (500) #define JOINGAME_MAX_Y (JOINGAME_MIN_Y+50) #define IN_JOINGAME(x,y) is_in_box(x,y,JOINGAME_MIN_X,JOINGAME_MIN_Y,JOINGAME_MAX_X,JOINGAME_MAX_Y) #define START_MIN_X (550) #define START_MAX_X (START_MIN_X+200) #define START_MIN_Y (500) #define START_MAX_Y (START_MIN_Y+50) #define IN_START(x,y) is_in_box(x,y,START_MIN_X,START_MIN_Y,START_MAX_X,START_MAX_Y) #define HELP_MIN_X (720) #define HELP_MAX_X (HELP_MIN_X+30) #define HELP_MIN_Y (40) #define HELP_MAX_Y (HELP_MIN_Y+30) #define IN_HELP(x,y) is_in_box(x,y,HELP_MIN_X,HELP_MIN_Y,HELP_MAX_X,HELP_MAX_Y) #define LANG_MIN_X (688) #define LANG_MAX_X (LANG_MIN_X+30) #define LANG_MIN_Y (40) #define LANG_MAX_Y (LANG_MIN_Y+30) #define IN_LANG(x,y) is_in_box(x,y,LANG_MIN_X,LANG_MIN_Y,LANG_MAX_X,LANG_MAX_Y) #define PLAYERPAWN_MIN_X(i) (100) #define PLAYERPAWN_MAX_X(i) (PLAYERPAWN_MIN_X(i)+40) #define PLAYERPAWN_MIN_Y(i) (200 + (40*(i-2))) #define PLAYERPAWN_MAX_Y(i) (PLAYERPAWN_MIN_Y(i)+40) #define IN_PLAYERPAWN(i,x,y) is_in_box(x,y,PLAYERPAWN_MIN_X(i),PLAYERPAWN_MIN_Y(i),PLAYERPAWN_MAX_X(i),PLAYERPAWN_MAX_Y(i)) #define PLAYERNAME_MIN_X(i) (140) #define PLAYERNAME_MAX_X(i) (PLAYERNAME_MIN_X(i)+200) #define PLAYERNAME_MIN_Y(i) (200 + (40*(i-2))) #define PLAYERNAME_MAX_Y(i) (PLAYERNAME_MIN_Y(i)+40) #define IN_PLAYERNAME(i,x,y) is_in_box(x,y,PLAYERNAME_MIN_X(i),PLAYERNAME_MIN_Y(i),PLAYERNAME_MAX_X(i),PLAYERNAME_MAX_Y(i)) #define PLAYERTYPE_MIN_X(i) (340) #define PLAYERTYPE_MAX_X(i) (PLAYERTYPE_MIN_X(i)+110) #define PLAYERTYPE_MIN_Y(i) (200 + (40*(i-2))) #define PLAYERTYPE_MAX_Y(i) (PLAYERTYPE_MIN_Y(i)+40) #define IN_PLAYERTYPE(i,x,y) is_in_box(x,y,PLAYERTYPE_MIN_X(i),PLAYERTYPE_MIN_Y(i),PLAYERTYPE_MAX_X(i),PLAYERTYPE_MAX_Y(i)) #define GAMELIST_MIN_X(i) (500) #define GAMELIST_MAX_X(i) (GAMELIST_MIN_X(i)+200) #define GAMELIST_MIN_Y(i) (200 + (40*(i))) #define GAMELIST_MAX_Y(i) (GAMELIST_MIN_Y(i)+40) #define IN_GAMELIST(i,x,y) is_in_box(x,y,GAMELIST_MIN_X(i),GAMELIST_MIN_Y(i),GAMELIST_MAX_X(i),GAMELIST_MAX_Y(i)) #if IS_DEMO static int get_file_age(const char *prefix, const char *name) { int age = -1; char *path = malloc(strlen(prefix)+ strlen (DIR_SEP) + strlen(name) + 1); struct stat stats; strcpy(path, prefix); strcat(path, DIR_SEP); strcat(path, name); if (stat(path, &stats) == 0 && S_ISREG(stats.st_mode)) age = time(NULL) - stats.st_ctime; free(path); return age; } int check_install_expiration(void) { int age = 0; age = get_file_age(PREFIX DIR_SEP "res", "nplay.png"); if (age < 0) age = get_file_age(PREFIX, "nplay.png"); return (age > MAX_AGE); } #endif void options_free_images(void) { SDL_FreeSurface(i_num_players); SDL_FreeSurface(i_players[2]); SDL_FreeSurface(i_players[3]); SDL_FreeSurface(i_players[4]); SDL_FreeSurface(i_highlighter); SDL_FreeSurface(i_start); SDL_FreeSurface(i_help); SDL_FreeSurface(i_lfr); SDL_FreeSurface(i_len); SDL_FreeSurface(i_les); SDL_FreeSurface(i_biloba_title); SDL_FreeSurface(i_computer); SDL_FreeSurface(i_create_game); SDL_FreeSurface(i_empty_20040); SDL_FreeSurface(i_empty_20050); SDL_FreeSurface(i_empty_4040); SDL_FreeSurface(i_game_name); SDL_FreeSurface(i_join_game); SDL_FreeSurface(i_local); SDL_FreeSurface(i_network_games); SDL_FreeSurface(i_reseau); SDL_FreeSurface(i_pawn[0]); SDL_FreeSurface(i_pawn[1]); SDL_FreeSurface(i_pawn[2]); SDL_FreeSurface(i_pawn[3]); } void options_load_images(void) { if (i_num_players != NULL) options_free_images(); i_num_players = biloba_load_image("nplay.png"); assert(i_num_players != NULL); i_players[2] = biloba_load_image("2play.png"); assert(i_players[2] != NULL); i_players[3] = biloba_load_image("3play.png"); assert(i_players[3] != NULL); i_players[4] = biloba_load_image("4play.png"); assert(i_players[4] != NULL); i_highlighter = biloba_load_image("black-highlighter.png"); assert(i_highlighter != NULL); i_start = biloba_load_image("start.png"); assert(i_start != NULL); i_help = biloba_load_image("help.png"); assert(i_help != NULL); i_lfr = biloba_load_image("fr.png"); assert(i_lfr != NULL); i_len = biloba_load_image("en.png"); assert(i_len != NULL); i_les = biloba_load_image("es.png"); assert(i_les != NULL); i_biloba_title = biloba_load_image("biloba-title.png"); assert(i_biloba_title != NULL); i_computer = biloba_load_image("computer.png"); assert(i_computer != NULL); i_create_game = biloba_load_image("create-game.png"); assert(i_create_game != NULL); i_empty_20040 = biloba_load_image("empty_200_40.png"); assert(i_empty_20040 != NULL); i_empty_20050 = biloba_load_image("empty_200_50.png"); assert(i_empty_20050 != NULL); i_empty_4040 = biloba_load_image("empty_40_40.png"); assert(i_empty_4040 != NULL); i_game_name = biloba_load_image("game-name.png"); assert(i_game_name != NULL); i_join_game = biloba_load_image("join-game.png"); assert(i_join_game != NULL); i_local = biloba_load_image("local.png"); assert(i_local != NULL); i_network_games = biloba_load_image("network-games.png"); assert(i_network_games != NULL); i_reseau = biloba_load_image("reseau.png"); assert(i_reseau != NULL); i_pawn[0] = biloba_load_image("pawn-orange.png"); assert(i_pawn[0] != NULL); i_pawn[1] = biloba_load_image("pawn-blue.png"); assert(i_pawn[1] != NULL); i_pawn[2] = biloba_load_image("pawn-red.png"); assert(i_pawn[2] != NULL); i_pawn[3] = biloba_load_image("pawn-green.png"); assert(i_pawn[3] != NULL); } static int player_edit = 0; static char *player_name[4] = {NULL,NULL,NULL,NULL}; static InputSystemMethod player_type[4] = {INPUT_LOCAL,INPUT_LOCAL,INPUT_LOCAL,INPUT_LOCAL}; static int network_create = FALSE, network_join = FALSE; static char *gamename = NULL; static int gamename_edit = FALSE; static int game_number = -1; static LList *netgames = NULL; static int netgames_ids[6] = {0, 0, 0, 0, 0, 0}; static char *mynetname = NULL; static int my_local_player = -1; static int my_game_id = -1; int get_options(void) { static int nump = 2; int num_players = 0; int x, y; int use_net = FALSE; if (!i_num_players) options_load_images(); SDL_FillRect(screen, NULL, 0x00000000); SDL_UpdateRect(screen, 0, 0, 0, 0); #if IS_DEMO if (check_install_expiration()) { static SDL_Surface *demo_surface = NULL; if (demo_surface == NULL) { demo_surface = biloba_load_image("demo.png"); assert(demo_surface != NULL); } put_image(demo_surface, 150, 150); SDL_UpdateRect(screen, 0, 0, 0, 0); SDL_Delay(20000); SDL_FillRect(screen, NULL, 0x00000000); SDL_UpdateRect(screen, 0, 0, 0, 0); return -1; } #endif /* init num_players from nump */ num_players = nump - 2; choose_again: do { SDL_Event event; int i = 0; int focus_changed = FALSE; SDL_FillRect(screen, NULL, 0x00000000); put_image(i_num_players, PLAYERS_MIN_X + 50, PLAYERS_MIN_Y); put_image(i_players[nump], PLAYERS_MIN_X, PLAYERS_MIN_Y); put_image(i_biloba_title, BILOBA_MIN_X, BILOBA_MIN_Y); for (i = 1; i <= nump; i++) { put_image(i_empty_4040, PLAYERPAWN_MIN_X(i), PLAYERPAWN_MIN_Y(i)); put_image(i_pawn[i-1], PLAYERPAWN_MIN_X(i)+5, PLAYERPAWN_MIN_Y(i)+5); put_image(i_empty_20040, PLAYERNAME_MIN_X(i), PLAYERNAME_MIN_Y(i)); if (!network_create && !network_join && player_type[i-1] == INPUT_NETWORK) player_type[i-1] = INPUT_LOCAL; switch (player_type[i-1]) { case INPUT_LOCAL: put_image(i_local, PLAYERTYPE_MIN_X(i), PLAYERTYPE_MIN_Y(i)); break; case INPUT_NETWORK: put_image(i_reseau, PLAYERTYPE_MIN_X(i), PLAYERTYPE_MIN_Y(i)); break; case INPUT_AI: put_image(i_computer, PLAYERTYPE_MIN_X(i), PLAYERTYPE_MIN_Y(i)); break; default: assert(FALSE); } if (player_name[i-1] == NULL) { char s_nump[2]= {i+'0', 0}; player_name[i-1] = malloc(10); memset(player_name[i-1], 0, 10); strcpy(player_name[i-1], get_msg(M_PLAYER)); strcat(player_name[i-1], s_nump); } draw_message_with_update(player_name[i-1], 4 + PLAYERNAME_MIN_X(i), 4 + PLAYERNAME_MIN_Y(i), (player_edit == i), FALSE); if ((network_create || network_join) && player_type[i-1] != INPUT_LOCAL) { SDL_SetAlpha(i_highlighter, SDL_SRCALPHA, 128); put_image(i_highlighter, PLAYERNAME_MIN_X(i), PLAYERNAME_MIN_Y(i)); } } if (network_create) { put_image(i_game_name, GAMENAME_MIN_X, GAMENAME_MIN_Y); if (gamename == NULL) { gamename = malloc(16); strcpy(gamename,get_msg(M_NEWGAME)); } draw_message_with_update(gamename,GAMENAME_MIN_X + 110, 8 + GAMENAME_MIN_Y, gamename_edit, FALSE); } if (network_join) { LList *tmp = netgames; put_image(i_network_games, NETGAMES_MIN_X, NETGAMES_MIN_Y); for (i = 0; i < 6; i++) { put_image(i_empty_20040, GAMELIST_MIN_X(i), GAMELIST_MIN_Y(i)); if (tmp) { Game *game = (Game *)tmp->data; char *tmpname = strdup(game->name); netgames_ids[i] = game->id; if (strlen(tmpname) > 8) tmpname[8] = '\0'; draw_message_with_update(tmpname, GAMELIST_MIN_X(i) + 4, GAMELIST_MIN_Y(i) + 4, FALSE, FALSE); tmp = tmp->next; } } put_image(i_game_name, GAMENAME_MIN_X, GAMENAME_MIN_Y); if (mynetname == NULL) { mynetname = malloc(16); strcpy(mynetname,""); } draw_message_with_update(mynetname, GAMENAME_MIN_X + 110, 8 + GAMENAME_MIN_Y, FALSE, FALSE); SDL_SetAlpha(i_highlighter, SDL_SRCALPHA, 128); put_image(i_highlighter, GAMENAME_MIN_X + 107, GAMENAME_MIN_Y); } put_image(i_create_game, CREATEGAME_MIN_X, CREATEGAME_MIN_Y); put_image(i_join_game, JOINGAME_MIN_X, JOINGAME_MIN_Y); put_image(i_start, START_MIN_X, START_MIN_Y); put_image(i_help, HELP_MIN_X, HELP_MIN_Y); if (!strcmp(langpath, "en")) put_image(i_lfr, LANG_MIN_X, LANG_MIN_Y); else if (!strcmp(langpath, "fr")) put_image(i_les, LANG_MIN_X, LANG_MIN_Y); else if (!strcmp(langpath, "es")) put_image(i_len, LANG_MIN_X, LANG_MIN_Y); SDL_UpdateRect(screen, 0, 0, 0, 0); if (player_edit) { char append[2]={0,0}; int key = keyboard_grab(); if (key < 0) { key = -key; key += 'A' - 'a'; } if (key == SDLK_RETURN) { player_edit = 0; } else if (key == SDLK_BACKSPACE && strlen(player_name[player_edit-1]) > 0) { player_name[player_edit-1][strlen(player_name[player_edit-1])-1] = 0; } else if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z') || (key >= '0' && key <= '9') || key == ' ') { append[0] = key; if (strlen(player_name[player_edit-1]) < 9) strcat(player_name[player_edit-1], append); } continue; } else if (gamename_edit) { char append[2]={0,0}; int key = keyboard_grab(); if (key < 0) { key = -key; key += 'A' - 'a'; } if (key == SDLK_RETURN) { gamename_edit = 0; } else if (key == SDLK_BACKSPACE && strlen(gamename) > 0) { gamename[strlen(gamename)-1] = 0; } else if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z') || (key >= '0' && key <= '9') || key == ' ') { append[0] = key; if (strlen(gamename) < 15) strcat(gamename, append); } continue; } event = get_sdl_event(SDL_MOUSEBUTTONUP); if (event.type == SDL_USEREVENT || event.type == SDL_QUIT) return 0; /* exit waiting */ SDL_GetMouseState (&x, &y); if (IN_PLAYERS(x,y)) { num_players++; if (num_players > 2) num_players = 0; nump = num_players + 2; focus_changed = TRUE; if (network_create) { player_type[0] = INPUT_LOCAL; for (i = 1; i < nump; i++) { player_type[i] = INPUT_NETWORK; } } else { for (i = 0; i < nump; i++) { player_type[i] = INPUT_LOCAL; } } llist_free(netgames); if (network_join) netgames = net_get_games(nump); else netgames = NULL; } for (i = 1; i <= 4 && nump > i-1; i++) { if (IN_PLAYERNAME(i,x,y)) { if (!(network_join || network_create) || player_type[i - 1] == INPUT_LOCAL) { player_edit = i; if (!strncmp(player_name[i-1],get_msg(M_PLAYER), strlen(get_msg(M_PLAYER)))) strcpy(player_name[i-1],""); } } if (IN_PLAYERTYPE(i,x,y) && !(network_join || network_create)) { player_type[i-1]++; if (player_type[i-1] > INPUT_AI) player_type[i-1] = INPUT_LOCAL; } if (!network_create && !network_join && player_type[i-1] == INPUT_NETWORK) player_type[i-1] = INPUT_AI; } if (IN_GAMENAME(x,y)) { if (gamename) { gamename_edit = TRUE; if (!strcmp(gamename, get_msg(M_NEWGAME))) strcpy(gamename,""); } } if (IN_CREATEGAME(x,y)) { network_create = !network_create; network_join = FALSE; if (network_create) { player_type[0] = INPUT_LOCAL; for (i = 1; i < nump; i++) { player_type[i] = INPUT_NETWORK; } } else { for (i = 0; i < nump; i++) { player_type[i] = INPUT_LOCAL; } } } if (IN_JOINGAME(x,y)) { network_join = !network_join; network_create = FALSE; } if (IN_HELP(x,y)) { help_start(); } if (IN_LANG(x,y)) { if (!strcmp(langpath,"en")) langpath="fr"; else if (!strcmp(langpath,"fr")) langpath="es"; else if (!strcmp(langpath,"es")) langpath="en"; options_load_images(); } if (network_join && netgames == NULL) { netgames = net_get_games(nump); } #ifdef DEBUG printf("x %d, y %d\n", x, y); #endif for (i = 0; i < 6; i++) { if (IN_GAMELIST(i,x,y)) { LList *tmp = netgames; printf("gamelist clicked %d - id %d\n", i, netgames_ids[i]); if (netgames_ids[i] > 0) { int k = 0; Game *cur_game = NULL; do { cur_game = (Game *)tmp->data; tmp = tmp->next; } while (cur_game->id != netgames_ids[i] && tmp); assert(cur_game->id == netgames_ids[i]); my_game_id = netgames_ids[i]; net_get_info(cur_game); if (mynetname != NULL) free(mynetname); mynetname = strdup(cur_game->name); for (k = 0; k < cur_game->num_players; k++) { if (k+1 == cur_game->first_avail_spot) { player_type[k] = INPUT_LOCAL; my_local_player = k; } else { strcpy(player_name[k], cur_game->player_name[k]); player_type[k] = INPUT_NETWORK; } } printf("game infos:\n" "nump %d\n" "p0 name %s\n" "p1 name %s\n" "p2 name %s\n" "p3 name %s\n" "first avail spot %d\n", cur_game->num_players, cur_game->player_name[0] ? cur_game->player_name[0] : "", cur_game->player_name[1] ? cur_game->player_name[1] : "", cur_game->player_name[2] ? cur_game->player_name[2] : "", cur_game->player_name[3] ? cur_game->player_name[3] : "", cur_game->first_avail_spot); } } } } while (!IN_START(x,y)); set_num_players(nump); if ((player_type[0] == INPUT_NETWORK || player_type[1] == INPUT_NETWORK || player_type[2] == INPUT_NETWORK || player_type[3] == INPUT_NETWORK) && network_create) { use_net = TRUE; game_number = net_init_game(gamename, nump, player_type[0],player_name[0], player_type[1],player_name[1], player_type[2],player_name[2], player_type[3],player_name[3]); if (game_number < 0) { connection_problem: SDL_FillRect(screen, NULL, 0x00000000); SDL_UpdateRect(screen, 0, 0, 0, 0); draw_message(get_msg(M_ENOCONN), 200, 284, FALSE); SDL_Delay(2000); llist_for_each(netgames, game_free); netgames = NULL; goto choose_again; } } if (network_join && my_game_id > 0) { net_join(my_game_id, my_local_player, player_name[my_local_player]); use_net = TRUE; } if (use_net && net_wait_ready(nump, player_name) < 0) goto connection_problem; llist_for_each(netgames, game_free); netgames = NULL; SDL_FillRect(screen, NULL, 0x00000000); SDL_UpdateRect(screen, 0, 0, 0, 0); return 0; } const char *options_get_player_name(int i) { return player_name[i]; } int options_get_player_type(int i) { return player_type[i]; }