/** ******************************************************************************* @file /8Kingdoms.cpp @brief tohle se spusti, kdyz se to spusti @author Pavel @version 0.1 ******************************************************************************/ /** @mainpage 8 Kingdoms - DOKUMENTACE ZDROJOVEHO KODU Projekt 8 Kingdoms - turn-based strategicka hra. Hra 8 Kingdoms vznikla jako studentska prace na pude MFF-UK (Matematicko- fyzikalni fakulty Univerzity Karlovy v Praze) v ramci predmetu "PRG023 - Projekt" pod vedenim Mgr. Marty Vomlelové, Ph.D. Cilem projektu bylo vytvorit strategickou "turn-based" hru pro Windows i Linux, s 3D grafikou, umelou inteligenci, diplomacii, moznosti sitove hry, realistickymi a snadno modifikovatelnymi pravidly. */ /*****************************************************************************/ //rozhrani #include #include "common/Interface.h" #include "common/Msg.h" //moduly #include "common/rm/rminit.h" #include "net/netinit.h" #include "world/world_handler.h" #include "gui/GUI.h" #include "ai/ai.h" //gui navic #include "common/CommandLine.h" /** Spusti lokalni hru pro lidske hrace. Single hra - pouziva profily - pouziva parametry prikazove radky - vytvori vsechny lidske hrace */ void simulate_start_game(){ // PROFIL //----------------------------------------------------------------------------- // nastaveni PROFILU (je potreba} DA *rm_profiles; // rm::TRM_conf_i *rmconfi = (rm::TRM_conf_i*)KSend(MSG_GET_RM_CONF_I, 0); rmconfi->getProfiles(&rm_profiles); int prof_id = -1; //precti odnekud prof_id if(TCommandLine::cl->iUseProfileName) { for (int i = (*rm_profiles).getNext(-1); i != -1; i = (*rm_profiles).getNext(i)){ if( !strcmp((*rm_profiles)[i]->name, TCommandLine::cl->szProfileName) ) prof_id = i; } } else { prof_id = rmconfi->getLastUsedProfile(); } if( prof_id == -1 ) THROW(E_8K_GUI, "simulate_start_game(): no profile loaded"); gui::TGUI::gui_inst->profile = (*rm_profiles)[ prof_id ]; rmconfi->setLastUsedProfile(prof_id); delete rmconfi; // HERNI MOD //----------------------------------------------------------------------------- // zacni lokalni hru(MSG_GAME_MODE) PACKET_GAME_MODE pgm; pgm.address = NULL; strcpy(pgm.nick, gui::TGUI::gui_inst->profile->name); pgm.mode = GM_LOCAL; KSendGlobalMsg(MSG_GAME_MODE, ANNONYMOUS, BROADCAST, &pgm); // MAPA //----------------------------------------------------------------------------- // z konfigurace mapy... rm::TMapInfo* rm_info; rm::TRM_map_i* rmmapi = (rm::TRM_map_i*)KSendGlobalMessage(MSG_GET_RM_MAP_I,MOD_GUI,MOD_RM,NULL); // nacteni map rmmapi->loadMapsInfo(TCommandLine::cl->iMapType, 0); // najdi mapu DA* rm_mapinfos = NULL; rmmapi->getMapsInfo(&rm_mapinfos,TCommandLine::cl->iMapType); if (!rm_mapinfos) THROW(E_8K_GUI, "simulate_start_game(): no maps exist"); int ord=0; int map_id=-1; for (int l = (*rm_mapinfos).getNext(-1); l != -1; l = (*rm_mapinfos).getNext(l)) { if(ord == TCommandLine::cl->iRunMap){ map_id = l; break; } ord++; } if (map_id<0) THROW(E_8K_GUI, "simulate_start_game(): requested map not exists"); rmmapi->getMapInfo(&rm_info, map_id); delete rmmapi; // HRACI //----------------------------------------------------------------------------- // vytvor lokalni hrace char name[K8_MAX_NAME_LEN]; for(int j = 0; j < rm_info->players; j++){ snprintf(name, K8_MAX_NAME_LEN, "player%02d", j); KSendGlobalMsg(MSG_ADD_LOCAL_CLIENT, ANNONYMOUS, MOD_NET, name); } //cekani na asynchronni zpravy, snad dostatecny SDL_Delay(2000); // NASTAVENI HRY //----------------------------------------------------------------------------- // zacni hru(MSG_GAME_START) PACKET_GAME_START pgs; pgs.map_id = map_id; //projdi role int clid = 0; for(int i = 1; i <= MAX_PLAYERS; i++){ if(rm_info->roles[i]){ pgs.players[clid].player_id = i; pgs.players[clid].client_id = gui::TGUI::gui_inst->clientsinfo.cinfo[clid].clientid; if(i!=1) snprintf(pgs.players[clid].name, MAX_STRLEN, "Player%d", i); else snprintf(pgs.players[clid].name, MAX_STRLEN, "%s", gui::TGUI::gui_inst->profile->name); pgs.players[clid].type = World::PT_HUMAN; clid++; } } //dopln zbytek for(int k = clid; k < MAX_PLAYERS; k++){ pgs.players[k].client_id = -1; pgs.players[k].player_id = 0; } // START //----------------------------------------------------------------------------- //ukaz hodiny gui::TGUI::gui_inst->screen->selectContext("GAMELOADINGCONTEXT", gui::TContextParameter(gui::context_localgame, 0) ); //zaciname TPacket_SyncResult* result = (TPacket_SyncResult*)KSendGlobalMsg(MSG_GAME_START, ANNONYMOUS, BROADCAST, &pgs); if(result){ if(result->status){ delete result; THROW(E_8K_GUI, "Failed to start the game!"); } delete result; } } /** Spusti sitovou hru pro lidsky sitovy hrace. Sitova hra - pouziva profily - pouziva parametry prikazovy radky - vytvori lidsky hrace pokud se prihlasi do urciteho timeoutu, jinak je nahradi pocitacema */ void simulate_start_network_game(){ // PROFIL //----------------------------------------------------------------------------- // nastaveni PROFILU (je potreba} DA *rm_profiles; // rm::TRM_conf_i *rmconfi = (rm::TRM_conf_i*)KSend(MSG_GET_RM_CONF_I, 0); rmconfi->getProfiles(&rm_profiles); int prof_id = -1; //precti odnekud prof_id if(TCommandLine::cl->iUseProfileName) { for (int i = (*rm_profiles).getNext(-1); i != -1; i = (*rm_profiles).getNext(i)){ if( !strcmp((*rm_profiles)[i]->name, TCommandLine::cl->szProfileName) ) prof_id = i; } } else { prof_id = rmconfi->getLastUsedProfile(); } if( prof_id == -1 ) THROW(E_8K_GUI, "simulate_start_network_game(): no profile loaded"); gui::TGUI::gui_inst->profile = (*rm_profiles)[ prof_id ]; rmconfi->setLastUsedProfile(prof_id); delete rmconfi; // zacni lokalni hru(MSG_GAME_MODE) PACKET_GAME_MODE pgm; // HERNI MOD: SERVER //----------------------------------------------------------------------------- if( TCommandLine::cl->iNetworkHost ) { pgm.mode = GM_NET_SERVER; pgm.address = NULL; strcpy(pgm.nick, gui::TGUI::gui_inst->profile->name); KSendGlobalMsg(MSG_GAME_MODE, ANNONYMOUS, BROADCAST, &pgm); // MAPA //----------------------------------------------------------------------------- // z konfigurace mapy... rm::TMapInfo* rm_info; rm::TRM_map_i* rmmapi = (rm::TRM_map_i*)KSendGlobalMessage(MSG_GET_RM_MAP_I,MOD_GUI,MOD_RM,NULL); // nacteni map rmmapi->loadMapsInfo(TCommandLine::cl->iMapType, 0); // najdi mapu DA* rm_mapinfos = NULL; rmmapi->getMapsInfo(&rm_mapinfos, TCommandLine::cl->iMapType); if (!rm_mapinfos) THROW(E_8K_GUI, "simulate_start_network_game(): no maps exist"); int ord=0; int map_id=-1; for (int l = (*rm_mapinfos).getNext(-1); l != -1; l = (*rm_mapinfos).getNext(l)) { if(ord == TCommandLine::cl->iRunMap){ map_id = l; break; } ord++; } if (map_id<0) THROW(E_8K_GUI, "simulate_start_network_game(): requested map not exists"); rmmapi->getMapInfo(&rm_info, map_id); delete rmmapi; // HRACI //----------------------------------------------------------------------------- // Nejprve jeden loklani hrac u serveru KSendGlobalMsg(MSG_ADD_LOCAL_CLIENT, ANNONYMOUS, MOD_NET, gui::TGUI::gui_inst->profile->name); //cekej dokud timeout if( TCommandLine::cl->iNetworkHost ){ int t = SDL_GetTicks(); while(1){ if( (SDL_GetTicks() - t) > (unsigned)TCommandLine::cl->iTimeOut ) break; SDL_Delay(500); } } // NASTAVENI HRY //----------------------------------------------------------------------------- // zacni hru(MSG_GAME_START) PACKET_GAME_START pgs; pgs.map_id = map_id; //projdi role int clid = 0; for(int i = 1; i <= MAX_PLAYERS; i++){ if(rm_info->roles[i]){ pgs.players[clid].player_id = i; pgs.players[clid].client_id = gui::TGUI::gui_inst->clientsinfo.cinfo[clid].clientid; if(i!=1) snprintf(pgs.players[clid].name, MAX_STRLEN, "Player%d", i); else snprintf(pgs.players[clid].name, MAX_STRLEN, "%s", gui::TGUI::gui_inst->profile->name); pgs.players[clid].type = World::PT_HUMAN; clid++; } } //dopln zbytek for(int k = clid; k < MAX_PLAYERS; k++){ pgs.players[k].client_id = -1; pgs.players[k].player_id = 0; } // START //----------------------------------------------------------------------------- // "ukaz hodiny" gui::TGUI::gui_inst->screen->selectContext("GAMELOADINGCONTEXT", gui::TContextParameter(gui::context_networkgame, 0) ); // zaciname TPacket_SyncResult* result = (TPacket_SyncResult*)KSendGlobalMsg(MSG_GAME_START, ANNONYMOUS, BROADCAST, &pgs); if(result){ if(result->status){ delete result; THROW(E_8K_GUI, "Failed to start the game!"); } delete result; } } // HERNI MOD: CLIENT //----------------------------------------------------------------------------- else { pgm.mode = GM_NET_CLIENT; pgm.address = TCommandLine::cl->szConnectTo; strcpy(pgm.nick, gui::TGUI::gui_inst->profile->name); KSendGlobalMsg(MSG_GAME_MODE, ANNONYMOUS, BROADCAST, &pgm); //?? // "ukaz hodiny" gui::TGUI::gui_inst->screen->selectContext("GAMELOADINGCONTEXT", gui::TContextParameter(gui::context_networkgame, 0) ); } } /*** Vypisuje seznam dostupnych map. Vypisuje seznam savu, nebo novych map na konzoli, pokud je dostupna. */ void list_maps(){ rm::TMapInfo* rm_info; DA* rm_mapinfos = NULL; rm::TRM_map_i* rmmapi = (rm::TRM_map_i*)KSendGlobalMessage(MSG_GET_RM_MAP_I,MOD_GUI,MOD_RM,NULL); // vystupni stream std::stringstream str; // nacteni map rmmapi->loadMapsInfo(0, 0); rmmapi->getMapsInfo(&rm_mapinfos, 0); //zahalvi str.setf(std::ios::left); str << "8Kingdoms - new game:\n"; str.width(3); str << "#"; str.width(25); str << "FILE"; str.width(35); str << "NAME"; str.width(9); str << "SIZE"; str.width(2); str << "PLAYERS" << "\n"; str << "-------------------------------------------------------------------------------\n"; int no=0; int l; for (l = (*rm_mapinfos).getNext(-1); l != -1; l = (*rm_mapinfos).getNext(l)) { rm_info = (*rm_mapinfos)[l]; str.width(3); str << no; str.width(25); str << rm_info->file; str.width(35); str << rm_info->name; str.width(2); str << rm_info->sizex; str.width(1); str << "x"; str.width(6); str << rm_info->sizey; str.width(1); str << rm_info->players; str << "\n"; no++; } str << "\n"; rmmapi->loadMapsInfo(1, 0); rmmapi->getMapsInfo(&rm_mapinfos, 1); //zahalvi str << "8Kingdoms - saves:\n"; str.width(3); str << "#"; str.width(25); str << "FILE"; str.width(35); str << "NAME"; str.width(9); str << "SIZE"; str.width(2); str << "PLAYERS" << "\n"; str << "-------------------------------------------------------------------------------\n"; no=0; for (l = (*rm_mapinfos).getNext(-1); l != -1; l = (*rm_mapinfos).getNext(l)) { rm_info = (*rm_mapinfos)[l]; str.width(3); str << no; str.width(25); str << rm_info->file; str.width(35); str << rm_info->name; str.width(2); str << rm_info->sizex; str.width(1); str << "x"; str.width(6); str << rm_info->sizey; str.width(1); str << rm_info->players; str << "\n"; no++; } str << "\n"; //vystup #ifdef WIN32 CONSOLE("Sorry! The list of maps is not available in consoleless environment.\n"); #else CONSOLE((char*)str.str().c_str()); #endif } /** Help. Napoveda k parametrum prikazove radky. */ void print_help(){ char* helpmsg = "8Kingdoms " VERSION "\n"\ "parameters: \n"\ "\t -h this screen\n"\ "\t -m use the new map number \n"\ "\t -l use the saved map number \n"\ "\t -p log in as \n"\ "\t -s switch to \"network game \" mode and start the server \n"\ "\t -c switch to \"network game\" mode and connect to as a client \n"\ "\t -e list all maps\n"\ "\t -t timeout \n"; // CONSOLE(helpmsg); } /** Hlavni program. Zaciname: - parsovani commandline - iniciaalizace msgsystemu - iniciaalizace modulu - spusteni v rezimu podle parametru commandline: - help - hlavni menu - single hra - sitova hra - hostovat sitovou hru - pripojit se na hru - vstup do HLAVNI smycky gui - hlaseni gui po navratu - uvolneni modulu - uvolneni msgsystemu - odchytnuti chybovych hlasek - dump neuvolnene pameti @param argc Pocet parametru na prikazove radce. @param argv Parametry prikazove radky. */ int main(int argc, char** argv){ try{ //parametry z prikazoveho radku TCommandLine::parseCommandLine(argc, argv); if( TCommandLine::cl->iPrintHelp ){ print_help(); } else{ // globalni inicializace CheckDirectory(); KInitGlobalTransceiverQueue(); RMInit(); if( TCommandLine::cl->iListMaps ){ list_maps(); } else{ net::NETinit(); World::initWorldModules(); ai_ns::AIInit(); gui::TGUI::initGUI(); // rychle spusteni gui if( TCommandLine::cl->iRunMap >= 0 || TCommandLine::cl->iNetworkClient ) { // sitova hra if( TCommandLine::cl->iNetworkHost || TCommandLine::cl->iNetworkClient ) simulate_start_network_game(); // lokalni hra else simulate_start_game(); } // normalni spusteni gui else { #ifdef TEST gui::TGUI::gui_inst->screen->selectContext("TEST", gui::TContextParameter() ); #else gui::TGUI::gui_inst->screen->selectContext("MAINMENU", gui::TContextParameter(gui::context_profile, 0) ); #endif } // gui::TGUI::gui_inst->main(); gui::TGUI::gui_inst->reportState(); // globalni destrukce gui::TGUI::destroyGUI(); ai_ns::AIDestroy(); World::destroyWorldModules(); net::NETdestroy(); } RMDestroy(); KFreeGlobalTransceiverQueue(); } TCommandLine::freeCommandLine(); } catch(E_8K e){ std::stringstream str; str << e.getFileName() << " (" <