void Replay::clear() { file_not_found = false; holds_level = false; version_min = gloB->version_min; built_required = gloB->empty_string; level_filename = gloB->empty_filename; player_local = -1; max_updates = 0; players .clear(); permu = Permu(); data .clear(); }
/* i|0 1 2 3 4 5 6 7 8 9 10 11 12 13 ----------------------------------- |A 2 3 4 5 6 7 8 9 T J Q K A */ int Straight( const int hd[], int cg, int us ){ int i, j,k; // 反復変数 int a,b,c; // 計算に使う一時変数 int chng=-1; // 交換するnum int ret = -1; struct card deck[14] = {0}; // 山札の構造体 double deck_pro[14] = {0}; // デッキからストレートのできる各々のnumの確率 deck_pro[0] = A = deck_pro[13] double hand_pro[13] = {0}; // 手札のカードの確率 double min =100; int count = 0; int tmp1, tmp2; if( poker_point(hd) >= P4 ){ return -1; } /*----- 事前処理--------------------- -------------------- */ for( i=0; i< 4; i++ ){ deck[i].mark = 13-(sut[i] + udsut[i]); } // (手札と捨て札から)山札のマーク残り数を求める for( i=0; i<13; i++ ){ deck[i].num = 4-(Num[i] + udNum[i]); } // (手札と捨て札から)山札の数字の残り数を求める deck[13].num = deck[0].num; //------------------------ 手札に同じ数字がある場合、山札に多い方を残す for( i=0; i<4; i++ ){ if( 1 < Num[i] ){ // 同じ数字が2枚ある場合 for( j=0; j<HNUM; j++){ if( hand[j].num == i ){ tmp1 = j; break;} // 数字からマークを調べる } for( k=0; k<HNUM; k++){ if( hand[k].num == i && tmp1 != k ){ tmp2 = k; } // 数字からマークを調べる } if( deck[tmp1].num < deck[tmp2].num ){ // 手札の tmp1 番目 と tmp2 番目が同じ数字 残りマークの少ない方を捨てる return tmp1; }else{ return tmp2; } } } //------------------------ for( i=0; i<HNUM; i++ ){ for( j=0; j<14; j++ ){ if( hand[i].num != j && flg[j] != -1 ){ // 手札にあるものは -1 とする flg[j] = deck[j].num; }else{ flg[j] = -1; } } } flg[13] = flg[0]; for( i=0; i<14-4; i++ ){ // 5つの塊で見ていく a = 1; count = 0; for( j=i; j<i+HNUM; j++ ){ if( flg[j] != -1 && flg[j] != 0 ){ // 手札にない かつ 山札の枚数が 0でない a *= flg[j]; // 手札にないカードについて確率の一部分を求める count++; } } b = Permu( (52-HNUM-us)-count, count); c = Permu( 52-HNUM-us, CHNG-cg ); for( k=i; k<i+HNUM; k++ ){ deck_pro[k] += (double)(a*b)/c; } } deck_pro[0] += deck_pro[13]; // AとKの後のAは同じため // 捨てる捜索範囲は i=0 i<13 まで 仮想Aは 含めない // 手札の番号について確率を格納し、その5つの中から比較する。 for( i=0; i<13; i++ ){ for( j=0; j<HNUM; j++ ){ if( i == hand[j].num ){ hand_pro[i] = deck_pro[i]; } } } // 確率が最小のものを探す。 for( i=0; i<13; i++ ){ if( hand_pro[i] < min && hand_pro[i] != 0 ){ min = hand_pro[i]; chng = i; } } // 手札から交換対象 chng を探す for( i=0; i<HNUM; i++ ){ if( hand[i].num == chng ){ ret = i; } } return ret; }
void NetClient::calc() { ENetEvent event; if (me && server) while (enet_host_service(me, &event, 0) > 0) { char type = (event.type == ENET_EVENT_TYPE_RECEIVE) ? (char) event.packet->data[0] : LEMNET_NOTHING; if (event.type == ENET_EVENT_TYPE_CONNECT) { // Server shall check if protocols and versions match. send_welcome_data(); } else if (event.type == ENET_EVENT_TYPE_DISCONNECT) { exit = true; } else if (type == LEMNET_DISCON_SILENT) { exit = true; } else if (type == LEMNET_WELCOME_DATA) { // The server sends out packets of this sort, but that only // happens to inform clients before 2009 Oct 25 of their very // old version. The server will probably stop that in some // months, and until then we simply ignore these. } else if (type == LEMNET_YOU_TOO_OLD || type == LEMNET_YOU_TOO_NEW) { const bool old = (type == LEMNET_YOU_TOO_OLD); if (old) Console::push_back(Language::net_chat_we_too_old); else Console::push_back(Language::net_chat_we_too_new); std::string msg = Language::net_chat_version_yours; msg += Help::version_to_string(gloB->version); msg += Language::net_chat_version_server; msg += Help::version_to_string( get_uint32_from(event.packet->data + 2)); msg += '.'; Console::push_back(msg); if (old) Console::push_back(Language::net_chat_please_download); else Console::push_back(Language::net_chat_server_update); // The server will throw us out. } else if (type == LEMNET_SOMEONE_OLD || type == LEMNET_SOMEONE_NEW) { int who_nr = event.packet->data[1]; PlDatIt who = players.begin(); while (who != players.end() && who->number != who_nr) ++who; if (type == LEMNET_SOMEONE_NEW) { Console::push_back(Language::net_chat_someone_new); Console::push_back(Language::net_chat_server_update); } // There exists someone with that number else if (who != players.end()) { std::string s = who->name + ' ' + Language::net_chat_named_guy_old; Console::push_back(s); } else Console::push_back(Language::net_chat_someone_old); // This is independent from new or old if (who != players.end()) { // reset player players.erase(who); set_nobody_ready(); player_data_change = true; } } else if (type == LEMNET_RECHECK) { send_welcome_data(); } else if (type == LEMNET_ASSIGN_NUMBER) { PlayerData pd(event.packet->data[2], gloB->user_name.c_str()); pd.style = pd.number % (LixEn::STYLE_MAX-1) + 1; if (useR->network_last_style > 0 && useR->network_last_style < LixEn::STYLE_MAX) pd.style = static_cast <char> (useR->network_last_style); // The lobby saves the style to useR->... players.clear(); players.push_back(pd); ourself = players.begin(); ENetPacket* p = pd.create_packet(); enet_peer_send(server, LEMNET_CHANNEL_MAIN, p); } else if (type == LEMNET_ROOM_DATA) { rooms.clear(); for (int room = 0; room < NETWORK_ROOMS_MAX; ++room) if (event.packet->data[2 + room] > 0) { RoomData rd; rd.number = room; rd.members = event.packet->data[2 + room]; rooms.insert(rd); } room_data_change = true; } else if (type == LEMNET_ROOM_CHANGE) { // Throw out all people other than us, because we'll soon receive // LEMNET_PLAYER_BEFORE packets for everyone in the new room. PlayerData temp_ourself = *ourself; players.clear(); players.push_back(temp_ourself); ourself = players.begin(); const char target_room = event.packet->data[2]; if (ourself->room == -1) Console::push_back(Language::net_chat_we_connected); else if (target_room == 0) Console::push_back(Language::net_chat_we_in_lobby); else { std::ostringstream message; message << Language::net_chat_we_in_room << (int) target_room << Language::net_chat_we_in_room_2; Console::push_back(message.str()); } ourself->room = target_room; } else if (type == LEMNET_PLAYER_DATA || type == LEMNET_PLAYER_BEFORE) { PlayerData pd; pd.read_from(event.packet); PlDatIt known = get_player(pd.number); // A new person has joined if (known == players.end()) { // Insert new data before the first higher data, so that // the players list is still sorted by operator <. PlDatIt insert_here = --players.end(); while (insert_here != --players.begin() && pd < *insert_here) --insert_here; players.insert(++insert_here, pd); set_nobody_ready(); if (type == LEMNET_PLAYER_DATA) { std::ostringstream message; message << pd.name; if (ourself->room == 0) message << Language::net_chat_player_in_lobby; else { message << Language::net_chat_player_in_room; message << (int) ourself->room; message << Language::net_chat_player_in_room_2; } Console::push_back(message.str()); Sound::play_loud(Sound::JOIN); } } else { // Only the information about readiness doesn't set back // all ready states. Everything else does. // snr = set nobody ready bool dont_call_snr = *known == pd; known->ready = !known->ready; // *known will be overwr. anyway dont_call_snr = dont_call_snr || *known == pd; *known = pd; if (!dont_call_snr) set_nobody_ready(); } player_data_change = true; } else if (type == LEMNET_PLAYER_CLEAR || type == LEMNET_PLAYER_OUT_TO) { unsigned nr = event.packet->data[1]; PlDatIt who = get_player(nr); if (who != players.end()) { std::ostringstream message; message << who->name; if (type == LEMNET_PLAYER_CLEAR) { message << Language::net_chat_disconnection; } else { int room = event.packet->data[2]; if (room == 0) { message << Language::net_chat_player_out_lobby; } else { message << Language::net_chat_player_out_room; message << room; message << Language::net_chat_player_out_room_2; } } Console::push_back(message.str()); players.erase(who); player_data_change = true; set_nobody_ready(); } } else if (type == LEMNET_LEVEL_FILE) { set_nobody_ready(); std::istringstream str((char*) event.packet->data + 2); level.load_from_stream(str); level_change = true; PlDatIt who = get_player(event.packet->data[1]); if (who != players.end()) { std::ostringstream msg; msg << who->name << ' ' << Language::net_chat_level_change << ' ' << level.get_name(); Console::push_back(msg.str()); } } else if (type == LEMNET_CHAT_MESSAGE) { std::string message = (const char*) &event.packet->data[2]; Console::push_back(message, true); // true = weiss } else if (type == LEMNET_GAME_START) { // Reset things to make it possible to play multiple games one // after another set_nobody_ready(); replay_data.clear(); permu = Permu(event.packet->data[2],(char*)event.packet->data + 3); // Jetzt aber... auf geht's! game_start = true; updates_change = 0; std::ostringstream start_message; start_message << Language::net_game_start; if (useR->key_chat > 0 && useR->key_chat < KEY_MAX) { start_message << Language::net_game_how_to_chat_1; start_message << Help::scancode_to_string(useR->key_chat); start_message << Language::net_game_how_to_chat_2; } Console::push_back(start_message.str()); } else if (type == LEMNET_GAME_END) { game_end = true; Console::push_back(Language::net_game_end); } else if (type == LEMNET_REPLAY_DATA) { // Only make available if we aren't the sender if (event.packet->data[1] != ourself->number) { ReplayData data; data.read_from(event.packet); replay_data.push_back(data); } } else if (type == LEMNET_UPDATES) { updates_change = get_uint32_from(&event.packet->data[2]); } if (event.type == ENET_EVENT_TYPE_RECEIVE) enet_packet_destroy(event.packet); } }
void Replay::load_from_file(const Filename& fn) { clear(); level_filename = fn; // Standardwert: Annahme, Level in Replaydatei unsigned long vm = 0; // version_min erst spaeter setzen wegen add() std::vector <IO::Line> lines; if (!IO::fill_vector_from_file(lines, fn.get_rootful())) { file_not_found = true; holds_level = false; return; } for (IO::LineIt i = lines.begin(); i != lines.end(); ++i) switch(i->type) { case '$': if (i->text1 == gloB->replay_built_required) built_required = i->text2; else if (i->text1 == gloB->replay_permu ) permu = Permu (i->text2); else if (i->text1 == gloB->replay_level_filename) { // We changed the names of the directories on 2012-04-12. Probably // a year from this time on, there shouldn't be any important // replays with the old path anymore. Then, remove this erase() // to finally allow a directory (levels-dir)/levels/ in theory. std::string filestr = i->text2; if (filestr.substr(0, 7) == "levels/") filestr.erase(0, 7); level_filename = Filename( gloB->dir_levels.get_dir_rootless() + filestr); } break; case '#': if (i->text1 == gloB->replay_version_min ) vm = i->nr1; break; case '+': if (i->text1 == gloB->replay_player || i->text1 == gloB->replay_friend) { add_player(i->nr1, LixEn::string_to_style(i->text2), i->text3); if (i->text1 == gloB->replay_player) player_local = i->nr1; } break; case '!': { Data d; d.update = i->nr1; // d.player ist zwar ein char, aber wir lesen ja d.player = i->nr2; // nicht aktiv longs ein, sondern weisen nur zu. d.what = i->nr3; if (i->text1 == gloB->replay_spawnint ) d.action = SPAWNINT; else if (i->text1 == gloB->replay_skill ) d.action = SKILL; else if (i->text1 == gloB->replay_assign ) d.action = ASSIGN; else if (i->text1 == gloB->replay_assign_legacy) d.action = ASSIGN; else if (i->text1 == gloB->replay_aim ) d.action = AIM; else if (i->text1 == gloB->replay_nuke ) d.action = NUKE; add(d); break; } default: break; } // Variablen nach dem Laden zuweisen, damit add() nichts kaputtmacht version_min = vm; // check whether the pointed-to level exists, otherwise use itself // as a fallback level Level pointedto(level_filename); if (pointedto.get_status() == Level::BAD_FILE_NOT_FOUND || pointedto.get_status() == Level::BAD_EMPTY) { level_filename = fn; } // load the replay file itself as a level, to see whether there's a level // in the file itself. This is important e.g. for the extract button. Level itself(fn); if (itself.get_status() == Level::BAD_FILE_NOT_FOUND || itself.get_status() == Level::BAD_EMPTY) { holds_level = false; } else { holds_level = true; if (level_filename == fn) { built_required = Level::get_built(level_filename); } } }