LCOV - code coverage report
Current view: top level - terminal-stg - server.cpp (source / functions) Hit Total Coverage
Test: test.info Lines: 1410 1410 100.0 %
Date: 2022-06-07 00:36:57 Functions: 106 106 100.0 %
Branches: 619 619 100.0 %

           Branch data     Line data    Source code
       1                 :            : #include <arpa/inet.h>
       2                 :            : #include <netinet/in.h>
       3                 :            : #include <pthread.h>
       4                 :            : #include <sys/socket.h>
       5                 :            : #include <sys/types.h>
       6                 :            : #include <sys/time.h>
       7                 :            : #include <unistd.h>
       8                 :            : 
       9                 :            : #include <cstdarg>
      10                 :            : #include <csignal>
      11                 :            : #include <cstring>
      12                 :            : #include <cctype>
      13                 :            : #include <ctime>
      14                 :            : #include <cmath>
      15                 :            : 
      16                 :            : #include <vector>
      17                 :            : #include <list>
      18                 :            : #include <set>
      19                 :            : 
      20                 :            : #include "constants.h"
      21                 :            : #include "server.h"
      22                 :            : #include "common.h"
      23                 :            : #include "func.h"
      24                 :            : 
      25                 :            : #include <iostream>
      26                 :            : #include <cstdlib>
      27                 :            : #include <iomanip>
      28                 :            : #include <queue>
      29                 :            : 
      30                 :            : //#define REGISTERED_USER_LIST_SIZE 100
      31                 :            : #define REGISTERED_USER_LIST_SIZE 10
      32                 :            : 
      33                 :            : #define REGISTERED_USER_FILE "userlists.log"
      34                 :            : 
      35                 :            : using std::multiset;
      36                 :            : using std::vector;
      37                 :            : 
      38                 :            : pthread_mutex_t userlist_lock = PTHREAD_MUTEX_INITIALIZER;
      39                 :            : pthread_mutex_t sessions_lock = PTHREAD_MUTEX_INITIALIZER;
      40                 :            : pthread_mutex_t battles_lock = PTHREAD_MUTEX_INITIALIZER;
      41                 :            : pthread_mutex_t default_lock = PTHREAD_MUTEX_INITIALIZER;
      42                 :            : pthread_mutex_t items_lock[USER_CNT];
      43                 :            : 
      44                 :            : int server_fd = 0, port = 50000, port_range = 100;
      45                 :            : 
      46                 :            : 
      47                 :            : 
      48                 :            : void check_user_status(int uid);
      49                 :            : void wrap_recv(int conn, client_message_t* pcm);
      50                 :            : void wrap_send(int conn, server_message_t* psm);
      51                 :            : void send_to_client(int uid, int message);
      52                 :            : void send_to_client(int uid, int message, char* str);
      53                 :            : void say_to_client(int uid, char* message);
      54                 :            : void send_to_client_with_username(int uid, int message, char* user_name);
      55                 :            : void close_session(int conn, int message);
      56                 :            : void terminate_process(int recved_signal);
      57                 :            : void load_user_list();
      58                 :            : void save_user_list();
      59                 :            : void save_user(int i);
      60                 :            : int query_session_built(uint32_t uid);
      61                 :            : void inform_all_user_battle_player(int bid);
      62                 :            : void user_quit_battle(uint32_t bid, uint32_t uid);
      63                 :            : void user_join_battle_common_part(uint32_t bid, uint32_t uid, uint32_t joined_state);
      64                 :            : void user_join_battle(uint32_t bid, uint32_t uid);
      65                 :            : void user_invited_to_join_battle(uint32_t bid, uint32_t uid);
      66                 :            : int find_uid_by_user_name(const char* user_name);
      67                 :            : int get_unalloced_battle();
      68                 :            : int get_unused_session();
      69                 :            : void inform_friends(int uid, int message);
      70                 :            : //void forced_generate_items(int bid, int x, int y, int kind, int count, int uid = -1);
      71                 :            : void random_generate_items(int bid);
      72                 :            : void move_bullets(int bid);
      73                 :            : void check_user_status(int uid);
      74                 :            : void check_all_user_status(int bid);
      75                 :            : void check_who_is_dead(int bid);
      76                 :            : void clear_items(int bid);
      77                 :            : void render_map_for_user(int uid, server_message_t* psm);
      78                 :            : void inform_all_user_battle_state(int bid);
      79                 :            : void* battle_ruler(void* args);
      80                 :            : int check_user_registered(char* user_name, char* password);
      81                 :            : void launch_battle(int bid);
      82                 :            : int admin_set_admin(int argc, char** argv);
      83                 :            : int admin_set_energy(int argc, char** argv);
      84                 :            : int admin_set_hp(int argc, char** argv);
      85                 :            : int admin_set_pos(int argc, char** argv);
      86                 :            : int admin_ban_user(int argc, char** argv);
      87                 :            : int client_command_admin_control(int uid);
      88                 :            : int client_message_fatal(int uid);
      89                 :            : void init_handler();
      90                 :            : void* session_start(void* args);
      91                 :            : void* run_battle(void* args);
      92                 :            : int server_start();
      93                 :            : void terminate_process(int signum);
      94                 :            : void terminate_entrance(int signum);
      95                 :            : 
      96                 :            : void list_all_users(server_message_t* psm);
      97                 :            : int invite_friend_to_battle(int bid, int uid, char* friend_name);
      98                 :            : 
      99                 :            : 
     100                 :            : int client_command_user_login(int uid);
     101                 :            : int client_command_user_register(int uid);
     102                 :            : 
     103                 :            : 
     104                 :            : 
     105                 :            : 
     106                 :            : int client_command_launch_battle(int uid);
     107                 :            : int client_command_quit_battle(int uid);
     108                 :            : int client_command_invite_user(int uid);
     109                 :            : int client_command_send_message(int uid);
     110                 :            : int client_command_create_ffa(int uid);
     111                 :            : int client_command_launch_ffa(int uid);
     112                 :            : int client_command_accept_battle(int uid);
     113                 :            : int client_command_reject_battle(int uid);
     114                 :            : int client_command_quit(int uid);
     115                 :            : int client_command_move_up(int uid);
     116                 :            : int client_command_move_down(int uid);
     117                 :            : int client_command_move_left(int uid);
     118                 :            : int client_command_move_right(int uid);
     119                 :            : int client_command_put_landmine(int uid);
     120                 :            : int client_command_fire(int uid, int delta_x, int delta_y, int dir);
     121                 :            : int client_command_fire_up(int uid);
     122                 :            : int client_command_fire_down(int uid);
     123                 :            : int client_command_fire_left(int uid);
     124                 :            : int client_command_fire_right(int uid);
     125                 :            : int client_command_fire_up_left(int uid);
     126                 :            : int client_command_fire_up_right(int uid);
     127                 :            : int client_command_fire_down_left(int uid);
     128                 :            : int client_command_fire_down_right(int uid);
     129                 :            : int client_command_fire_aoe(int uid, int dir);
     130                 :            : int client_command_fire_aoe_up(int uid);
     131                 :            : int client_command_fire_aoe_down(int uid);
     132                 :            : int client_command_fire_aoe_left(int uid);
     133                 :            : int client_command_fire_aoe_right(int uid);
     134                 :            : int client_command_melee(int uid);
     135                 :            : 
     136                 :            : 
     137                 :            : int client_command_user_logout(int uid);
     138                 :            : int client_command_fetch_all_users(int uid);
     139                 :            : int client_command_fetch_all_friends(int uid);
     140                 :            : 
     141                 :            : static int user_list_size = 0;
     142                 :            : //static uint64_t sum_delay_time = 0, prev_time;
     143                 :            : 
     144                 :            : struct {
     145                 :            :     char user_name[USERNAME_SIZE];
     146                 :            :     char password[PASSWORD_SIZE];
     147                 :            : } registered_user_list[REGISTERED_USER_LIST_SIZE];
     148                 :            : 
     149                 :            : struct session_t {
     150                 :            :     char user_name[USERNAME_SIZE];
     151                 :            :     char ip_addr[IPADDR_SIZE];
     152                 :            :     int conn;
     153                 :            :     int state;
     154                 :            :     int is_admin;
     155                 :            :     int score;
     156                 :            :     int kill;
     157                 :            :     int death;
     158                 :            :     uint32_t bid;
     159                 :            :     uint32_t inviter_id;
     160                 :            :     client_message_t cm;
     161                 :            : } sessions[USER_CNT];
     162                 :            : 
     163                 :            : struct session_args_t {
     164                 :            :     int conn;
     165                 :            :     char ip_addr[IPADDR_SIZE];
     166                 :            : };
     167                 :            : 
     168                 :            : typedef struct session_args_t session_args_t;
     169                 :            : 
     170                 :            : class item_t { public:
     171                 :            :     int id;
     172                 :            :     int dir;
     173                 :            :     int owner;
     174                 :            :     uint64_t time;
     175                 :            :     int count;
     176                 :            :     int kind;
     177                 :            :     pos_t pos;
     178                 :         73 :     item_t(const item_t &it) : id(it.id),
     179                 :         73 :                                dir(it.dir),
     180                 :         73 :                                owner(it.owner),
     181                 :         73 :                                time(it.time),
     182                 :         73 :                                count(it.count),
     183                 :         73 :                                kind(it.kind),
     184                 :         73 :                                pos(it.pos)
     185                 :         73 :                                {}
     186                 :        109 :     item_t() {
     187                 :        109 :         id = 0;
     188                 :        109 :         dir = owner = time = count = kind = 0;
     189                 :        109 :         pos.x = pos.y = 0;
     190                 :        109 :     }
     191                 :            :     friend const bool operator < (const item_t it1, const item_t it2) {
     192                 :            :         return it1.time < it2.time;
     193                 :            :     }
     194                 :            : };
     195                 :            : 
     196                 :            : class battle_t { public:
     197                 :            :     int is_alloced;
     198                 :            :     size_t alive_users;
     199                 :            :     size_t all_users;
     200                 :            :     class user_t { public:
     201                 :            :         int battle_state;
     202                 :            :         int energy;
     203                 :            :         int dir;
     204                 :            :         int life;
     205                 :            :         int killby;
     206                 :            :         pos_t pos;
     207                 :            :         pos_t last_pos;
     208                 :            :     } users[USER_CNT];
     209                 :            : 
     210                 :            :     int num_of_other;  // number of other alloced item except for bullet
     211                 :            :     int item_count;
     212                 :            :     uint64_t global_time;
     213                 :            : 
     214                 :            :     std::list<item_t> items;
     215                 :            : 
     216                 :         19 :     void reset() {
     217                 :         19 :         is_alloced = all_users = alive_users = num_of_other = item_count = 0;
     218                 :         19 :         global_time = 0;
     219                 :         19 :         items.clear();
     220                 :         19 :     }
     221                 :         14 :     battle_t() {
     222                 :         14 :         reset();
     223                 :         14 :     }
     224                 :            : 
     225                 :            : } battles[USER_CNT];
     226                 :            : 
     227                 :          6 : void load_user_list() {
     228                 :            : 
     229                 :          6 :     FILE* userlist = fopen(REGISTERED_USER_FILE, "r");
     230                 :            : 
     231         [ +  + ]:          6 :     if (userlist == NULL) {
     232                 :          1 :         log("can not find " REGISTERED_USER_FILE "");
     233                 :          1 :         return;
     234                 :            :     }
     235                 :            : 
     236                 :            : #define LOAD_FAIL                                                                          \
     237                 :            :     log("failed to load users, try to delete " REGISTERED_USER_FILE "."),                \
     238                 :            :         user_list_size = 0, memset(registered_user_list, 0, sizeof(registered_user_list)), \
     239                 :            :         fclose(userlist);
     240         [ +  + ]:         30 :     for (int i = 0; i < REGISTERED_USER_LIST_SIZE; i++) {
     241                 :         29 :         cout<<"asdad:"<<i<<endl;
     242         [ +  + ]:         29 :         if (fgets(registered_user_list[i].user_name, USERNAME_SIZE, userlist) != NULL) {
     243                 :         27 :             registered_user_list[i].user_name[strlen(registered_user_list[i].user_name) - 1] = 0;
     244         [ +  + ]:        121 :             for (int j = 0; j < i; j++) {
     245         [ +  + ]:         95 :                 if (strncmp(registered_user_list[i].user_name, registered_user_list[j].user_name, USERNAME_SIZE - 1) != 0)
     246                 :         94 :                     continue;
     247                 :          1 :                 LOAD_FAIL;
     248                 :          1 :                 return;
     249                 :            :             }
     250                 :         26 :             user_list_size++;
     251                 :            :         } else {
     252                 :          2 :             break;
     253                 :            :         }
     254                 :            : 
     255         [ +  + ]:         26 :         if (fgets(registered_user_list[i].password, PASSWORD_SIZE, userlist) == NULL) {
     256                 :          1 :             LOAD_FAIL;
     257                 :          1 :             return;
     258                 :            :         }
     259                 :            : 
     260                 :         25 :         registered_user_list[i].password[strlen(registered_user_list[i].password) - 1] = 0;
     261                 :            :     }
     262                 :            : #undef LOAD_FAIL
     263                 :            :     //for (int i = 0; i < user_list_size; i++) {
     264                 :            :     //    log("loaded user %s", registered_user_list[i].user_name);
     265                 :            :     //}
     266                 :          3 :     log("loaded %d user(s) from " REGISTERED_USER_FILE ".", user_list_size);
     267                 :          3 :     fclose(userlist);
     268                 :            : }
     269                 :          1 : void save_user_list() {
     270                 :          1 :     FILE* userlist = fopen(REGISTERED_USER_FILE, "w");
     271         [ +  + ]:          5 :     for (int i = 0; i < user_list_size; i++) {
     272                 :          4 :         fprintf(userlist, "%s\n", registered_user_list[i].user_name);
     273                 :          4 :         fprintf(userlist, "%s\n", registered_user_list[i].password);
     274                 :            :     }
     275                 :          1 :     log("saved %d users to " REGISTERED_USER_FILE ".", user_list_size);
     276                 :          1 :     fclose(userlist);
     277                 :          1 : }
     278                 :            : 
     279                 :          2 : void save_user(int i) {
     280                 :          2 :     FILE* userlist = fopen(REGISTERED_USER_FILE, "a");
     281                 :          2 :     fprintf(userlist, "%s\n", registered_user_list[i].user_name);
     282                 :          2 :     fprintf(userlist, "%s\n", registered_user_list[i].password);
     283                 :          2 :     log("saved users %s to " REGISTERED_USER_FILE ".", registered_user_list[i].user_name);
     284                 :          2 :     fclose(userlist);
     285                 :          2 : }
     286                 :            : 
     287                 :          5 : int client_command_user_register(int uid) {
     288                 :          5 :     int ul_index = -1;
     289                 :          5 :     char* user_name = sessions[uid].cm.user_name;
     290                 :          5 :     char* password = sessions[uid].cm.password;
     291                 :          5 :     log("user %s tries to register with password %s", user_name, password);
     292                 :            : 
     293         [ +  + ]:         41 :     for (int i = 0; i < REGISTERED_USER_LIST_SIZE; i++) {
     294         [ +  + ]:         38 :         if (strncmp(user_name, registered_user_list[i].user_name, USERNAME_SIZE - 1) != 0)
     295                 :         36 :             continue;
     296                 :            : 
     297                 :          2 :         log("user %s&%s has been registered", user_name, password);
     298                 :          2 :         send_to_client(uid, SERVER_RESPONSE_YOU_HAVE_REGISTERED);
     299                 :          2 :         return 0;
     300                 :            :     }
     301                 :            : 
     302                 :          3 :     pthread_mutex_lock(&userlist_lock);
     303         [ +  + ]:          3 :     if (user_list_size < REGISTERED_USER_LIST_SIZE)
     304                 :          1 :         ul_index = user_list_size++;
     305                 :          3 :     pthread_mutex_unlock(&userlist_lock);
     306                 :            : 
     307                 :          3 :     log("fetch empty user list index #%d", ul_index);
     308         [ +  + ]:          3 :     if (ul_index == -1) {
     309                 :          2 :         log("user %s registers fail", user_name);
     310                 :          2 :         send_to_client(uid, SERVER_RESPONSE_REGISTER_FAIL);
     311                 :            :     } else {
     312                 :          1 :         log("user %s registers success", user_name);
     313                 :          1 :         strncpy(registered_user_list[ul_index].user_name,
     314                 :            :                 user_name, USERNAME_SIZE - 1);
     315                 :          1 :         strncpy(registered_user_list[ul_index].password,
     316                 :            :                 password, PASSWORD_SIZE - 1);
     317                 :          1 :         send_to_client(uid, SERVER_RESPONSE_REGISTER_SUCCESS);
     318                 :          1 :         save_user(ul_index);
     319                 :            :     }
     320                 :          3 :     return 0;
     321                 :            : }
     322                 :            : 
     323                 :          9 : int client_command_user_login(int uid) {
     324                 :          9 :     int is_dup = 0;
     325                 :          9 :     client_message_t* pcm = &sessions[uid].cm;
     326                 :          9 :     char* user_name = pcm->user_name;
     327                 :          9 :     char* password = pcm->password;
     328                 :          9 :     char* ip_addr = sessions[uid].ip_addr;
     329                 :          9 :     log("user #%d %s\033[2m(%s)\033[0m try to login", uid, user_name, ip_addr);
     330                 :          9 :     int message = check_user_registered(user_name, password);
     331                 :            : 
     332         [ +  + ]:          9 :     if (query_session_built(uid)) {
     333                 :          3 :         log("user #%d %s\033[2m(%s)\033[0m has logined", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     334                 :          3 :         send_to_client(uid, SERVER_RESPONSE_YOU_HAVE_LOGINED);
     335                 :          3 :         return 0;
     336                 :            :     }
     337                 :            : 
     338         [ +  + ]:         38 :     for (int i = 0; i < USER_CNT; i++) {
     339         [ +  + ]:         36 :         if (query_session_built(i)) {
     340                 :          5 :             logi("check dup user id: %s vs. %s", user_name, sessions[i].user_name);
     341         [ +  + ]:          5 :             if (strncmp(user_name, sessions[i].user_name, USERNAME_SIZE - 1) == 0) {
     342                 :          4 :                 log("user #%d %s duplicate with %dth user %s\033[2m(%s)\033[0m", uid, user_name, i, sessions[i].user_name, sessions[i].ip_addr);
     343                 :          4 :                 is_dup = 1;
     344                 :          4 :                 break;
     345                 :            :             }
     346                 :            :         }
     347                 :            :     }
     348                 :            : 
     349                 :            :     // no duplicate user ids found
     350                 :          6 :     cout<<"dup: "<<is_dup<<endl;
     351         [ +  + ]:          6 :     if (is_dup) {
     352                 :          4 :         log("send fail dup id message to client.");
     353                 :          4 :         send_to_client(uid, SERVER_RESPONSE_LOGIN_FAIL_DUP_USERID);
     354                 :          4 :         sessions[uid].state = USER_STATE_NOT_LOGIN;
     355         [ +  + ]:          2 :     } else if (message == SERVER_RESPONSE_LOGIN_SUCCESS) {
     356                 :          1 :         log("user %s login success", user_name);
     357                 :          1 :         sessions[uid].state = USER_STATE_LOGIN;
     358                 :          1 :         send_to_client(
     359                 :            :                 uid,
     360                 :            :                 SERVER_RESPONSE_LOGIN_SUCCESS,
     361                 :            :                 sformat("Welcome to multiplayer shooting game! server \033[0;32m%s%s", version, color_s[0]));
     362                 :          1 :         strncpy(sessions[uid].user_name, user_name, USERNAME_SIZE - 1);
     363                 :          1 :         inform_friends(uid, SERVER_MESSAGE_FRIEND_LOGIN);
     364                 :            :     } else {
     365                 :          1 :         send_to_client(uid, message);
     366                 :            :     }
     367                 :            : 
     368                 :          6 :     return 0;
     369                 :            : }
     370                 :            : 
     371                 :          5 : int client_command_user_logout(int uid) {
     372         [ +  + ]:          5 :     if (sessions[uid].state == USER_STATE_BATTLE
     373         [ +  + ]:          4 :         || sessions[uid].state == USER_STATE_WAIT_TO_BATTLE) {
     374                 :          2 :         log("user #%d %s\033[2m(%s)\033[0m tries to logout was in battle", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     375                 :          2 :         user_quit_battle(sessions[uid].bid, uid);
     376                 :            :     }
     377                 :            : 
     378                 :          5 :     log("user #%d %s\033[2m(%s)\033[0m logout", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     379                 :          5 :     sessions[uid].state = USER_STATE_NOT_LOGIN;
     380                 :          5 :     inform_friends(uid, SERVER_MESSAGE_FRIEND_LOGOUT);
     381                 :          5 :     return 0;
     382                 :            : }
     383                 :            : 
     384                 :        338 : int query_session_built(uint32_t uid) {
     385                 :            :     //assert(uid < USER_CNT);
     386                 :            : 
     387         [ +  + ]:        338 :     if (sessions[uid].state == USER_STATE_UNUSED
     388         [ +  + ]:        210 :         || sessions[uid].state == USER_STATE_NOT_LOGIN) {
     389                 :        141 :         return false;
     390                 :            :     } else {
     391                 :        197 :         return true;
     392                 :            :     }
     393                 :            : }
     394                 :            : 
     395                 :            : void inform_all_user_battle_player(int bid);
     396                 :            : 
     397                 :         11 : void user_quit_battle(uint32_t bid, uint32_t uid) {
     398                 :            :     //assert(bid < USER_CNT && uid < USER_CNT);
     399                 :            : 
     400                 :         11 :     log("user %s\033[2m(%s)\033[0m quit from battle %d(%ld/%ld users)", sessions[uid].user_name, sessions[uid].ip_addr, bid, battles[bid].alive_users, battles[bid].all_users);
     401                 :         11 :     battles[bid].all_users--;
     402         [ +  + ]:         11 :     if (battles[bid].users[uid].battle_state == BATTLE_STATE_LIVE) {
     403                 :          3 :         battles[bid].alive_users--;
     404         [ +  + ]:          3 :         if (battles[bid].alive_users != 0) {
     405                 :          2 :             sessions[uid].score = max(sessions[uid].score - 5, 0);
     406                 :          2 :             sessions[uid].death ++;
     407                 :            :         }
     408                 :            :     }
     409                 :         11 :     battles[bid].users[uid].battle_state = BATTLE_STATE_UNJOINED;
     410                 :         11 :     sessions[uid].state = USER_STATE_LOGIN;
     411         [ +  + ]:         11 :     if (battles[bid].all_users == 0) {
     412                 :            :         // disband battle
     413                 :          2 :         log("disband battle %d", bid);
     414                 :          2 :         battles[bid].reset();
     415                 :            :     } else {
     416                 :            :         server_message_t sm;
     417                 :          9 :         sm.message = SERVER_MESSAGE_USER_QUIT_BATTLE;
     418                 :          9 :         strncpy(sm.friend_name, sessions[uid].user_name, USERNAME_SIZE - 1);
     419                 :            : 
     420         [ +  + ]:        135 :         for (int i = 0; i < USER_CNT; i++) {
     421                 :            :             if (battles[bid].users[i].battle_state != BATTLE_STATE_UNJOINED) {
     422                 :            :                 //wrap_send(sessions[i].conn, &sm);
     423                 :            :             }
     424                 :            :         }
     425                 :            :     }
     426                 :         11 : }
     427                 :            : 
     428                 :         10 : void user_join_battle_common_part(uint32_t bid, uint32_t uid, uint32_t joined_state) {
     429                 :         10 :     log("user %s\033[2m(%s)\033[0m join in battle %d", sessions[uid].user_name, sessions[uid].ip_addr, bid);
     430                 :            : 
     431         [ +  + ]:         10 :     if (joined_state == USER_STATE_BATTLE) {
     432                 :          4 :         battles[bid].all_users++;
     433                 :          4 :         battles[bid].alive_users++;
     434                 :          4 :         log("now %ld alive of %ld users", battles[bid].alive_users, battles[bid].all_users);
     435                 :          4 :         battles[bid].users[uid].battle_state = BATTLE_STATE_LIVE;
     436         [ +  + ]:          6 :     } else if (joined_state == USER_STATE_WAIT_TO_BATTLE) {
     437                 :          5 :         battles[bid].users[uid].battle_state = BATTLE_STATE_UNJOINED;
     438                 :            :     } else {
     439                 :          1 :         loge("check here, other joined_state:%d", joined_state);
     440                 :            :     }
     441                 :            : 
     442                 :         10 :     battles[bid].users[uid].life = INIT_LIFE;
     443                 :         10 :     battles[bid].users[uid].energy = INIT_BULLETS;
     444                 :            : 
     445                 :         10 :     sessions[uid].state = joined_state;
     446                 :         10 :     sessions[uid].bid = bid;
     447                 :         10 : }
     448                 :            : 
     449                 :          8 : void user_join_battle(uint32_t bid, uint32_t uid) {
     450                 :          8 :     int ux = (rand() & 0x7FFF) % BATTLE_W;
     451                 :          8 :     int uy = (rand() & 0x7FFF) % BATTLE_H;
     452                 :          8 :     battles[bid].users[uid].pos.x = ux;
     453                 :          8 :     battles[bid].users[uid].pos.y = uy;
     454                 :          8 :     log("alloc position (%hhu, %hhu) for launcher #%d %s",
     455                 :            :         ux, uy, uid, sessions[uid].user_name);
     456                 :            : 
     457                 :          8 :     sessions[uid].state = USER_STATE_BATTLE;
     458                 :            : 
     459         [ +  + ]:          8 :     if (battles[bid].users[uid].battle_state == BATTLE_STATE_UNJOINED) {
     460                 :          3 :         user_join_battle_common_part(bid, uid, USER_STATE_BATTLE);
     461                 :            :     }
     462                 :          8 : }
     463                 :            : 
     464                 :          4 : void user_invited_to_join_battle(uint32_t bid, uint32_t uid) {
     465         [ +  + ]:          4 :     if (sessions[uid].state == USER_STATE_WAIT_TO_BATTLE
     466         [ +  + ]:          2 :         && bid != sessions[uid].bid) {
     467                 :          1 :         log("user #%d %s\033[2m(%s)\033[0m rejects old battle #%d since he was invited to a new battle",
     468                 :            :             uid, sessions[uid].user_name, sessions[uid].ip_addr, sessions[uid].bid);
     469                 :            : 
     470                 :          1 :         send_to_client_with_username(sessions[uid].inviter_id, SERVER_MESSAGE_FRIEND_REJECT_BATTLE, sessions[uid].user_name);
     471                 :            :     }
     472                 :            : 
     473                 :          4 :     user_join_battle_common_part(bid, uid, USER_STATE_WAIT_TO_BATTLE);
     474                 :          4 : }
     475                 :            : 
     476                 :         37 : int find_uid_by_user_name(const char* user_name) {
     477                 :         37 :     int ret_uid = -1;
     478                 :         37 :     log("find user %s", user_name);
     479         [ +  + ]:        188 :     for (int i = 0; i < USER_CNT; i++) {
     480         [ +  + ]:        178 :         if (query_session_built(i)) {
     481         [ +  + ]:        155 :             if (strncmp(user_name, sessions[i].user_name, USERNAME_SIZE - 1) == 0) {
     482                 :         27 :                 ret_uid = i;
     483                 :         27 :                 break;
     484                 :            :             }
     485                 :            :         }
     486                 :            :     }
     487                 :            : 
     488         [ +  + ]:         37 :     if (ret_uid == -1) {
     489                 :         10 :         logi("fail");
     490                 :            :     } else {
     491                 :         27 :         logi("found: #%d %s\033[2m(%s)\033[0m", ret_uid, sessions[ret_uid].user_name, sessions[ret_uid].ip_addr);
     492                 :            :     }
     493                 :            : 
     494                 :         37 :     return ret_uid;
     495                 :            : }
     496                 :            : 
     497                 :          5 : int get_unalloced_battle() {
     498                 :          5 :     int ret_bid = -1;
     499                 :          5 :     pthread_mutex_lock(&battles_lock);
     500         [ +  + ]:         31 :     for (int i = 1; i < USER_CNT; i++) {
     501         [ +  + ]:         29 :         if (battles[i].is_alloced == false) {
     502                 :          3 :             battles[i].reset();
     503                 :          3 :             battles[i].is_alloced = true;
     504                 :          3 :             ret_bid = i;
     505                 :          3 :             break;
     506                 :            :         }
     507                 :            :     }
     508                 :          5 :     pthread_mutex_unlock(&battles_lock);
     509         [ +  + ]:          5 :     if (ret_bid == -1) {
     510                 :          2 :         loge("check here, returned battle id should not be -1");
     511                 :            :     } else {
     512                 :          3 :         log("alloc unalloced battle id #%d", ret_bid);
     513                 :            :     }
     514                 :          5 :     return ret_bid;
     515                 :            : }
     516                 :            : 
     517                 :          2 : int get_unused_session() {
     518                 :          2 :     int ret_uid = -1;
     519                 :          2 :     pthread_mutex_lock(&sessions_lock);
     520         [ +  + ]:         18 :     for (int i = 0; i < USER_CNT; i++) {
     521         [ +  + ]:         17 :         if (sessions[i].state == USER_STATE_UNUSED) {
     522                 :          1 :             memset(&sessions[i], 0, sizeof(struct session_t));
     523                 :          1 :             sessions[i].conn = -1;
     524                 :          1 :             sessions[i].state = USER_STATE_NOT_LOGIN;
     525                 :          1 :             ret_uid = i;
     526                 :          1 :             break;
     527                 :            :         }
     528                 :            :     }
     529                 :          2 :     pthread_mutex_unlock(&sessions_lock);
     530         [ +  + ]:          2 :     if (ret_uid == -1) {
     531                 :          1 :         log("fail to alloc session id");
     532                 :            :     } else {
     533                 :          1 :         log("alloc unused session id #%d", ret_uid);
     534                 :            :     }
     535                 :          2 :     return ret_uid;
     536                 :            : }
     537                 :            : 
     538                 :          6 : void inform_friends(int uid, int message) {
     539                 :            :     server_message_t sm;
     540                 :          6 :     char* user_name = sessions[uid].user_name;
     541                 :          6 :     memset(&sm, 0, sizeof(server_message_t));
     542                 :          6 :     sm.message = message;
     543         [ +  + ]:         90 :     for (int i = 0; i < USER_CNT; i++) {
     544   [ +  +  +  +  :         84 :         if (i == uid || !query_session_built(i))
                   +  + ]
     545                 :         79 :             continue;
     546                 :          5 :         strncpy(sm.friend_name, user_name, USERNAME_SIZE - 1);
     547                 :            :         //wrap_send(sessions[i].conn, &sm);
     548                 :            :     }
     549                 :          6 : }
     550                 :            : 
     551                 :         49 : void forced_generate_items(int bid, int x, int y, int kind, int count, int uid = -1) {
     552                 :            :     //if (battles[bid].num_of_other >= MAX_OTHER) return;
     553   [ +  +  +  + ]:         52 :     if (x < 0 || x >= BATTLE_W) return; //60
     554   [ +  +  +  + ]:         46 :     if (y < 0 || y >= BATTLE_H) return; //21
     555                 :         43 :     battles[bid].item_count++;
     556                 :         43 :     item_t new_item;
     557                 :         43 :     new_item.id = battles[bid].item_count;
     558                 :         43 :     new_item.kind = kind;
     559                 :         43 :     new_item.pos.x = x;
     560                 :         43 :     new_item.pos.y = y;
     561                 :         43 :     new_item.time = battles[bid].global_time + count;
     562                 :         43 :     new_item.owner = uid;
     563         [ +  + ]:         43 :     if (kind == ITEM_MAGMA) {
     564                 :         12 :         new_item.count = MAGMA_INIT_TIMES;
     565                 :            :     }
     566                 :            : 
     567                 :            :     /*
     568                 :            :     battles[bid].items.push_back(new_item);
     569                 :            :     log("new %s #%d (%d,%d)",
     570                 :            :         item_s[new_item.kind],
     571                 :            :         new_item.id,
     572                 :            :         new_item.pos.x,
     573                 :            :         new_item.pos.y);
     574                 :            :     */
     575                 :            : }
     576                 :            : 
     577                 :       3501 : void random_generate_items(int bid) {
     578                 :            :     int random_kind;
     579                 :            :     //if (!probability(1, 100)) return; // rand 退出
     580         [ +  + ]:       3501 :     if (battles[bid].num_of_other >= MAX_OTHER) return;
     581                 :            :     /* delete
     582                 :            :     random_kind = rand() % (ITEM_END - 1) + 1;
     583                 :            :     if (random_kind == ITEM_BLOOD_VIAL && probability(1, 2))
     584                 :            :         random_kind = ITEM_MAGAZINE;
     585                 :            :         */
     586                 :         43 :     random_kind = ITEM_MAGAZINE;
     587                 :         43 :     battles[bid].item_count++;
     588                 :         43 :     item_t new_item;
     589                 :         43 :     new_item.id = battles[bid].item_count;
     590                 :         43 :     new_item.kind = random_kind;
     591                 :         43 :     new_item.pos.x = (rand() & 0x7FFF) % BATTLE_W;
     592                 :         43 :     new_item.pos.y = (rand() & 0x7FFF) % BATTLE_H;
     593                 :         43 :     new_item.time = battles[bid].global_time + OTHER_ITEM_LASTS_TIME;
     594                 :         43 :     battles[bid].num_of_other++;
     595                 :            :     /* delete
     596                 :            :     log("new %s #%d (%d,%d)",
     597                 :            :         item_s[new_item.kind],
     598                 :            :         new_item.id,
     599                 :            :         new_item.pos.x,
     600                 :            :         new_item.pos.y);
     601                 :            :         */
     602                 :            :     /* delete
     603                 :            :     if (random_kind == ITEM_MAGMA) {
     604                 :            :         new_item.count = MAGMA_INIT_TIMES;
     605                 :            :     }
     606                 :            :      */
     607                 :            : 
     608                 :            :     //battles[bid].items.push_back(new_item); //delete
     609                 :            : 
     610                 :            :     //for (int i = 0; i < USER_CNT; i++) {
     611                 :            :     //    if (battles[bid].users[i].battle_state != BATTLE_STATE_LIVE)
     612                 :            :     //        continue;
     613                 :            :     //    check_user_status(i);
     614                 :            :     //}
     615                 :            : }
     616                 :            : 
     617                 :       3525 : void move_bullets(int bid) {
     618         [ +  + ]:       3548 :     for (auto& cur : battles[bid].items) {
     619                 :            :     //for (int i = 0; i < MAX_ITEM; i++) {
     620         [ +  + ]:         23 :         if (cur.kind != ITEM_BULLET)
     621                 :          2 :             continue;
     622                 :            :         // log("try to move bullet %d with dir %d", i, cur.dir);
     623   [ +  +  +  +  :         21 :         switch (cur.dir) {
             +  +  +  +  
                      + ]
     624                 :          2 :             case DIR_UP: {
     625         [ +  + ]:          2 :                 if (cur.pos.y > 0) {
     626                 :          1 :                     (cur.pos.y)--;
     627                 :          1 :                     break;
     628                 :            :                 }
     629                 :            :                 else {
     630                 :          1 :                     cur.dir = DIR_DOWN;
     631                 :          1 :                     break;
     632                 :            :                 }
     633                 :            :             }
     634                 :          2 :             case DIR_DOWN: {
     635         [ +  + ]:          2 :                 if (cur.pos.y < BATTLE_H - 1) {
     636                 :          1 :                     (cur.pos.y)++;
     637                 :          1 :                     break;
     638                 :            :                 }
     639                 :            :                 else {
     640                 :          1 :                     cur.dir = DIR_UP;
     641                 :          1 :                     break;
     642                 :            :                 }
     643                 :            :             }
     644                 :          2 :             case DIR_LEFT: {
     645         [ +  + ]:          2 :                 if (cur.pos.x > 0) {
     646                 :          1 :                     (cur.pos.x)--;
     647                 :          1 :                     break;
     648                 :            :                 }
     649                 :            :                 else {
     650                 :          1 :                     cur.dir = DIR_RIGHT;
     651                 :          1 :                     break;
     652                 :            :                 }
     653                 :            :             }
     654                 :          2 :             case DIR_RIGHT: {
     655         [ +  + ]:          2 :                 if (cur.pos.x < BATTLE_W - 1) {
     656                 :          1 :                     (cur.pos.x)++;
     657                 :          1 :                     break;
     658                 :            :                 }
     659                 :            :                 else {
     660                 :          1 :                     cur.dir = DIR_LEFT;
     661                 :          1 :                     break;
     662                 :            :                 }
     663                 :            :             }
     664                 :          3 :             case DIR_UP_LEFT: {
     665         [ +  + ]:          3 :                 if (cur.pos.y > 0) {
     666                 :          2 :                     (cur.pos.y)--;
     667                 :            :                 }
     668                 :            :                 else {
     669                 :          1 :                     cur.dir = DIR_DOWN_LEFT;
     670                 :          1 :                     break;
     671                 :            :                 }
     672         [ +  + ]:          2 :                 if (cur.pos.x > 1) {
     673                 :          1 :                     (cur.pos.x) -= 2;
     674                 :            :                 }
     675                 :            :                 else {
     676                 :          1 :                     cur.dir = DIR_UP_RIGHT;
     677                 :          1 :                     break;
     678                 :            :                 }
     679                 :          1 :                 break;
     680                 :            :             }
     681                 :          3 :             case DIR_UP_RIGHT: {
     682         [ +  + ]:          3 :                 if (cur.pos.y > 0) {
     683                 :          2 :                     (cur.pos.y)--;
     684                 :            :                 }
     685                 :            :                 else {
     686                 :          1 :                     cur.dir = DIR_DOWN_RIGHT;
     687                 :          1 :                     break;
     688                 :            :                 }
     689         [ +  + ]:          2 :                 if (cur.pos.x < BATTLE_W - 2) {
     690                 :          1 :                     (cur.pos.x) += 2;
     691                 :            :                 }
     692                 :            :                 else {
     693                 :          1 :                     cur.dir = DIR_UP_LEFT;
     694                 :          1 :                     break;
     695                 :            :                 }
     696                 :          1 :                 break;
     697                 :            :             }
     698                 :          3 :             case DIR_DOWN_LEFT: {
     699         [ +  + ]:          3 :                 if (cur.pos.y < BATTLE_H - 2) {
     700                 :          2 :                     (cur.pos.y)++;
     701                 :            :                 }
     702                 :            :                 else {
     703                 :          1 :                     cur.dir = DIR_UP_LEFT;
     704                 :          1 :                     break;
     705                 :            :                 }
     706         [ +  + ]:          2 :                 if (cur.pos.x > 1) {
     707                 :          1 :                     (cur.pos.x) -= 2;
     708                 :            :                 }
     709                 :            :                 else {
     710                 :          1 :                     cur.dir = DIR_DOWN_RIGHT;
     711                 :          1 :                     break;
     712                 :            :                 }
     713                 :          1 :                 break;
     714                 :            :             }
     715                 :          3 :             case DIR_DOWN_RIGHT: {
     716         [ +  + ]:          3 :                 if (cur.pos.y < BATTLE_H - 2) {
     717                 :          2 :                     (cur.pos.y)++;
     718                 :            :                 }
     719                 :            :                 else {
     720                 :          1 :                     cur.dir = DIR_UP_RIGHT;
     721                 :          1 :                     break;
     722                 :            :                 }
     723         [ +  + ]:          2 :                 if (cur.pos.x < BATTLE_W - 2) {
     724                 :          1 :                     (cur.pos.x) += 2;
     725                 :            :                 }
     726                 :            :                 else {
     727                 :          1 :                     cur.dir = DIR_DOWN_LEFT;
     728                 :          1 :                     break;
     729                 :            :                 }
     730                 :          1 :                 break;
     731                 :            :             }
     732                 :            :         }
     733                 :            :     }
     734                 :       3525 : }
     735                 :            : 
     736                 :       9599 : void check_user_status(int uid) {
     737                 :            :     //log("checking...");
     738                 :            :     //auto start_time = myclock();
     739                 :       9599 :     int bid = sessions[uid].bid;
     740                 :       9599 :     int ux = battles[bid].users[uid].pos.x;
     741                 :       9599 :     int uy = battles[bid].users[uid].pos.y;
     742                 :            :     //for (int i = 0; i < MAX_ITEM; i++) {
     743                 :       9599 :     auto& items = battles[bid].items;
     744         [ +  + ]:       9599 :     if (battles[bid].users[uid].battle_state != BATTLE_STATE_LIVE) {
     745                 :       3179 :         return;
     746                 :            :     }
     747         [ +  + ]:       6440 :     for (auto it = items.begin(); it != items.end(); it++) {
     748                 :            : 
     749                 :            :         //next = std::next(it);, next = std::next(it) => it++
     750                 :            : 
     751                 :         20 :         int ix = it->pos.x;
     752                 :         20 :         int iy = it->pos.y;
     753                 :            : 
     754   [ +  +  +  + ]:         20 :         if (ix == ux && iy == uy) {
     755   [ +  +  +  +  :         14 :             switch (it->kind) {
                   +  + ]
     756                 :          2 :                 case ITEM_MAGAZINE: {
     757                 :          2 :                     battles[bid].users[uid].energy += BULLETS_PER_MAGAZINE;
     758                 :            :                     //log("user #%d %s\033[2m(%s)\033[0m is got magazine", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     759         [ +  + ]:          2 :                     if (battles[bid].users[uid].energy > MAX_BULLETS) {
     760                 :            :                         //log("user #%d %s\033[2m(%s)\033[0m 's bullets exceeds max value", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     761                 :          1 :                         battles[bid].users[uid].energy = MAX_BULLETS;
     762                 :            :                     }
     763                 :            :                     //send_to_client(uid, SERVER_MESSAGE_YOU_GOT_MAGAZINE);
     764                 :          2 :                     it = items.erase(it);
     765                 :            :                     //log("current item size: %ld", items.size());
     766                 :          2 :                     break;
     767                 :            :                 }
     768                 :          3 :                 case ITEM_MAGMA: {
     769         [ +  + ]:          3 :                     if (it->owner != uid) {
     770                 :          2 :                         battles[bid].users[uid].life = max(battles[bid].users[uid].life - 1, 0);
     771                 :          2 :                         battles[bid].users[uid].killby = it->owner;
     772                 :          2 :                         it->count--;
     773                 :            :                         //log("user #%d %s\033[2m(%s)\033[0m is trapped in magma", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     774                 :            :                         //send_to_client(uid, SERVER_MESSAGE_YOU_ARE_TRAPPED_IN_MAGMA);
     775         [ +  + ]:          2 :                         if (it->count <= 0) {
     776                 :            :                             //log("magma #%d is exhausted", it->id);
     777                 :          1 :                             battles[bid].num_of_other--;
     778                 :          1 :                             it = items.erase(it);
     779                 :            :                             //log("current item size: %ld", items.size());
     780                 :            :                         }
     781                 :            :                     }
     782                 :          3 :                     break;
     783                 :            :                 }
     784                 :          2 :                 case ITEM_BLOOD_VIAL: {
     785                 :          2 :                     battles[bid].users[uid].life += LIFE_PER_VIAL;
     786                 :            :                     //log("user #%d %s\033[2m(%s)\033[0m got blood vial", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     787         [ +  + ]:          2 :                     if (battles[bid].users[uid].life > MAX_LIFE) {
     788                 :            :                         //log("user #%d %s\033[2m(%s)\033[0m life exceeds max value", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     789                 :          1 :                         battles[bid].users[uid].life = MAX_LIFE;
     790                 :            :                     }
     791                 :            :                     //log("current item size: %ld", items.size());
     792                 :          2 :                     battles[bid].num_of_other--;
     793                 :            :                     //send_to_client(uid, SERVER_MESSAGE_YOU_GOT_BLOOD_VIAL);
     794                 :          2 :                     it = items.erase(it);
     795                 :          2 :                     break;
     796                 :            :                 }
     797                 :          2 :                 case ITEM_BULLET: {
     798         [ +  + ]:          2 :                     if (it->owner != uid) {
     799                 :          1 :                         battles[bid].users[uid].life = max(battles[bid].users[uid].life - 1, 0);
     800                 :          1 :                         battles[bid].users[uid].killby = it->owner;
     801                 :            :                         //log("user #%d %s\033[2m(%s)\033[0m is shooted", uid, sessions[uid].user_name, sessions[uid].ip_addr);
     802                 :            :                         //log("current item size: %ld", items.size());
     803                 :            :                         //send_to_client(uid, SERVER_MESSAGE_YOU_ARE_SHOOTED);
     804                 :          1 :                         it = items.erase(it);
     805                 :          1 :                         break;
     806                 :            :                     }
     807                 :          1 :                     break;
     808                 :            :                 }
     809                 :          4 :                 case ITEM_LANDMINE: {
     810         [ +  + ]:          4 :                                         if (it->owner != uid) {
     811                 :          2 :                                                 it->time = battles[bid].global_time;
     812                 :          2 :                                                 forced_generate_items(bid, ix, iy, ITEM_MAGMA, 7, it->owner);
     813                 :          2 :                                                 forced_generate_items(bid, ix - 1, iy, ITEM_MAGMA, 7, it->owner);
     814                 :          2 :                                                 forced_generate_items(bid, ix + 1, iy, ITEM_MAGMA, 7, it->owner);
     815                 :          2 :                                                 forced_generate_items(bid, ix, iy - 1, ITEM_MAGMA, 7, it->owner);
     816                 :          2 :                                                 forced_generate_items(bid, ix, iy + 1, ITEM_MAGMA, 7, it->owner);
     817                 :            :                                         }
     818                 :          4 :                     break;
     819                 :            :                 }
     820                 :            :             }
     821                 :            :         }
     822                 :            :     }
     823                 :            :     //auto end_time = myclock();
     824                 :            :     //log("completed.");
     825                 :            : }
     826                 :            : 
     827                 :       3503 : void check_all_user_status(int bid) {
     828                 :            :     //for (int i = 0; i < MAX_ITEM; i++) {
     829                 :            :     //log("checking...");
     830                 :            :     //log("completed.");
     831         [ +  + ]:      52545 :     for (int i = 0; i < USER_CNT; i++) {
     832         [ +  + ]:      49042 :         if (battles[bid].users[i].battle_state != BATTLE_STATE_LIVE) continue;
     833                 :       9579 :         check_user_status(i);
     834                 :            :     }
     835                 :       3503 : }
     836                 :            : 
     837                 :          5 : void check_who_is_dead(int bid) {
     838         [ +  + ]:         75 :     for (int i = 0; i < USER_CNT; i++) {
     839         [ +  + ]:         70 :         if (battles[bid].users[i].battle_state == BATTLE_STATE_LIVE
     840         [ +  + ]:          8 :             && battles[bid].users[i].life <= 0) {
     841                 :          3 :             log("user #%d %s\033[2m(%s)\033[0m is dead", i, sessions[i].user_name, sessions[i].ip_addr);
     842                 :          3 :             battles[bid].users[i].battle_state = BATTLE_STATE_DEAD;
     843                 :          3 :             battles[bid].alive_users--;
     844                 :          3 :             log("send dead info to user #%d %s\033[2m(%s)\033[0m", i, sessions[i].user_name, sessions[i].ip_addr);
     845                 :          3 :             send_to_client(i, SERVER_MESSAGE_YOU_ARE_DEAD);
     846                 :          3 :             sessions[i].death++;
     847                 :          3 :             log("death of user #%d %s\033[2m(%s)\033[0m: %d", i, sessions[i].user_name, sessions[i].ip_addr, sessions[i].death);
     848         [ +  + ]:          3 :             if (battles[bid].users[i].killby != -1) {
     849                 :          2 :                 int by = battles[bid].users[i].killby;
     850                 :          2 :                 sessions[by].kill++;
     851                 :          2 :                 log("kill of user #%d %s\033[2m(%s)\033[0m: %d", i, sessions[by].user_name, sessions[by].ip_addr, sessions[by].kill);
     852                 :          2 :                 double delta = (double)sessions[i].score / sessions[by].score;
     853                 :          2 :                 delta = delta * delta;
     854         [ +  + ]:          2 :                 if (delta > 4) delta = 4;
     855         [ +  + ]:          2 :                 if (delta < 0.2) delta = 0.2;
     856                 :          2 :                 int d = min(round(5. * delta), sessions[i].score);
     857                 :          2 :                 sessions[i].score -= d;
     858                 :          2 :                 sessions[by].score += d;
     859                 :          2 :                 battles[bid].users[by].energy += battles[bid].users[i].energy;
     860                 :            :             } else {
     861                 :          1 :                 sessions[i].score = max(sessions[i].score - 5, 0);
     862                 :          3 :             }
     863         [ +  + ]:         67 :         } else if (battles[bid].users[i].battle_state == BATTLE_STATE_DEAD) {
     864                 :          1 :             battles[bid].users[i].battle_state = BATTLE_STATE_WITNESS;
     865                 :          1 :             battles[bid].users[i].energy = 0;
     866                 :          1 :             battles[bid].users[i].life = 0;
     867                 :            :         }
     868                 :            :     }
     869                 :          5 : }
     870                 :            : 
     871                 :       3502 : void clear_items(int bid) {
     872                 :            :     //log("call func %s", __func__);
     873                 :            :     //for (int i = 0; i < MAX_ITEM; i++) {
     874                 :            :     //    if (battles[bid].items[i].times) {
     875                 :            :     //        battles[bid].items[i].times--;
     876                 :            :     //        if (!battles[bid].items[i].times) {
     877                 :            :     //            log("free item #%d", i);
     878                 :            :     //            battles[bid].items[i].is_used = false;
     879                 :            :     //            if (battles[bid].items[i].kind < ITEM_END) {
     880                 :            :     //                battles[bid].num_of_other--;
     881                 :            :     //            }
     882                 :            :     //            //battles[bid].items[i].kind = ITEM_BLANK;
     883                 :            :     //        }
     884                 :            :     //    }
     885                 :            :     //}
     886                 :            :     //log("check completed...");
     887                 :       3502 :     auto& items = battles[bid].items;
     888                 :       3502 :     size_t cnt[ITEM_SIZE] = {0};
     889                 :            :     // 有修改 可能会有bug
     890         [ +  + ]:       3506 :     for (auto cur = items.begin(); cur != items.end(); cur++) {
     891                 :            :         //next = std::next(cur); , next = std::next(cur)
     892         [ +  + ]:          4 :         if (cur->time <= battles[bid].global_time) {
     893         [ +  + ]:          3 :             if (cur->kind < ITEM_END) {
     894                 :          1 :                 battles[bid].num_of_other--;
     895                 :            :             }
     896                 :          3 :             cnt[cur->kind]++;
     897                 :            :             //next = battles[bid].items.erase(cur);
     898                 :          3 :             cur = battles[bid].items.erase(cur);
     899                 :            :         }
     900                 :            :     }
     901                 :            :     //int cleared = 0;
     902         [ +  + ]:      31518 :     for (int i = 0; i < ITEM_SIZE; i++) {
     903                 :            :         if (cnt[i]) {
     904                 :            :             //log("clear %ld %s(s)", cnt[i], item_s[i]);
     905                 :            :             //cleared = 1;
     906                 :            :         }
     907                 :            :     }
     908                 :            :     //if (cleared) log("current item size: %ld", items.size());
     909                 :       3502 : }
     910                 :            : 
     911                 :       9584 : void render_map_for_user(int uid, server_message_t* psm) {
     912                 :       9584 :     int bid = sessions[uid].bid;
     913                 :       9584 :     int map[BATTLE_H][BATTLE_W] = {0};
     914                 :            :     int cur, x, y;
     915                 :            :     //for (int i = 0, x, y; i < MAX_ITEM; i++) {
     916         [ +  + ]:       9595 :     for (auto it : battles[bid].items) {
     917                 :         11 :         x = it.pos.x;
     918                 :         11 :         y = it.pos.y;
     919      [ +  +  + ]:         11 :         switch (it.kind) {
     920                 :          2 :             case ITEM_BULLET: {
     921         [ +  + ]:          2 :                 if (it.owner == uid) {
     922                 :          1 :                     map[y][x] = max(map[y][x], MAP_ITEM_MY_BULLET);
     923                 :            :                 } else {
     924                 :          1 :                     map[y][x] = max(map[y][x], MAP_ITEM_OTHER_BULLET);
     925                 :            :                 }
     926                 :          2 :                 break;
     927                 :            :             }
     928                 :          8 :             case ITEM_LANDMINE: {
     929         [ +  + ]:          8 :                 if (it.owner != uid) break;
     930                 :          3 :                 map[y][x] = max(map[y][x], item_to_map[ITEM_LANDMINE]);
     931                 :            :             }
     932                 :          4 :             default: {
     933                 :          4 :                 cur = item_to_map[it.kind];
     934                 :          4 :                 map[y][x] = max(map[y][x], cur);
     935                 :            :             }
     936                 :            :         }
     937                 :            :         //sm.item_kind[i] = it.kind;
     938                 :            :         //sm.item_pos[i].x = it.pos.x;
     939                 :            :         //sm.item_pos[i].y = it.pos.y;
     940                 :            :     }
     941         [ +  + ]:     210811 :     for (int i = 0; i < BATTLE_H; i++) {
     942         [ +  + ]:    6237980 :         for (int j = 0; j < BATTLE_W; j += 2) {
     943                 :            :             //psm->map[i][j] = map[i][j];
     944                 :            :             //if (psm->map[i][j] != 0) log("set item #%d", psm->map[i][j]);
     945                 :    6036750 :             psm->map[i][j >> 1] = (map[i][j]) | (map[i][j + 1] << 4);
     946                 :            :         }
     947                 :            :     }
     948                 :       9584 : }
     949                 :            : 
     950                 :        366 : void inform_all_user_battle_player(int bid) {
     951                 :            :     server_message_t sm;
     952                 :        366 :     sm.message = SERVER_MESSAGE_BATTLE_PLAYER;
     953         [ +  + ]:       5490 :     for (int i = 0; i < USER_CNT; i++) {
     954         [ +  + ]:       5124 :         if (battles[bid].users[i].battle_state == BATTLE_STATE_LIVE &&
     955         [ +  + ]:       1005 :             battles[bid].users[i].life > 0) {
     956                 :        671 :             strncpy(sm.users[i].name, sessions[i].user_name, USERNAME_SIZE - 1);
     957                 :        671 :             sm.users[i].namecolor = i % color_s_size + 1;
     958                 :        671 :             sm.users[i].life = battles[bid].users[i].life;
     959                 :        671 :             sm.users[i].score = sessions[i].score;
     960                 :        671 :             sm.users[i].death = sessions[i].death;
     961                 :        671 :             sm.users[i].kill = sessions[i].kill;
     962                 :            :         } else {
     963                 :       4453 :             strcpy(sm.users[i].name, (char*)"");
     964                 :       4453 :             sm.users[i].namecolor = 0;
     965                 :       4453 :             sm.users[i].life = 0;
     966                 :       4453 :             sm.users[i].score = 0;
     967                 :       4453 :             sm.users[i].death = 0;
     968                 :       4453 :             sm.users[i].kill = 0;
     969                 :            :         }
     970                 :            :     }
     971         [ +  + ]:       5490 :     for (int i = 0; i < USER_CNT; i++) {
     972         [ +  + ]:      38430 :         for (int j = i + 1; j < USER_CNT; j++) {
     973         [ +  + ]:      33306 :             if (sm.users[i].score < sm.users[j].score) {
     974                 :         41 :                 std::swap(sm.users[i], sm.users[j]);
     975                 :            :             }
     976                 :            :         }
     977                 :            :     }
     978         [ +  + ]:       5490 :     for (int i = 0; i < USER_CNT; i++) {
     979                 :            :         if (battles[bid].users[i].battle_state != BATTLE_STATE_UNJOINED) {
     980                 :            :             //wrap_send(sessions[i].conn, &sm);
     981                 :            :             //log("inform user #%d %s\033[2m(%s)\033[0m", i, sessions[i].user_name, sessions[i].ip_addr);
     982                 :            :         }
     983                 :            :     }
     984                 :        366 : }
     985                 :            : 
     986                 :       3503 : void inform_all_user_battle_state(int bid) {
     987                 :            :     server_message_t sm;
     988                 :       3503 :     sm.message = SERVER_MESSAGE_BATTLE_INFORMATION;
     989         [ +  + ]:      52545 :     for (int i = 0; i < USER_CNT; i++) {
     990         [ +  + ]:      49042 :         if (battles[bid].users[i].battle_state == BATTLE_STATE_LIVE) {
     991                 :       9581 :             sm.user_pos[i].x = battles[bid].users[i].pos.x;
     992                 :       9581 :             sm.user_pos[i].y = battles[bid].users[i].pos.y;
     993                 :       9581 :             sm.user_color[i] = i % color_s_size + 1;
     994                 :            :         } else {
     995                 :      39461 :             sm.user_pos[i].x = -1;
     996                 :      39461 :             sm.user_pos[i].y = -1;
     997                 :      39461 :             sm.user_color[i] = 0;
     998                 :            :         }
     999                 :            :     }
    1000                 :            : 
    1001         [ +  + ]:      52507 :     for (int i = 0; i < USER_CNT; i++) {
    1002         [ +  + ]:      49007 :         if (battles[bid].users[i].battle_state != BATTLE_STATE_UNJOINED) {
    1003                 :       9579 :             render_map_for_user(i, &sm);
    1004                 :       9576 :             sm.index = i;
    1005                 :       9576 :             sm.life = battles[bid].users[i].life;
    1006                 :       9576 :             sm.bullets_num = battles[bid].users[i].energy;
    1007                 :       9576 :             sm.color = i % color_s_size + 1;
    1008                 :            :             //wrap_send(sessions[i].conn, &sm);
    1009                 :            :         }
    1010                 :            :     }
    1011                 :       3500 : }
    1012                 :            : 
    1013                 :          6 : void* battle_ruler(void* args) {
    1014                 :          6 :     int bid = (int)(uintptr_t)args;
    1015                 :            :     //log("battle ruler for battle #%d", bid);
    1016                 :            :     // FIXME: battle re-alloced before exiting loop 
    1017         [ +  + ]:         36 :     for (int i = 0; i < INIT_GRASS; i++) {
    1018                 :         60 :         forced_generate_items(bid,
    1019                 :         30 :                               (rand() & 0x7FFF) % BATTLE_W,
    1020                 :         30 :                               (rand() & 0x7FFF) % BATTLE_H,
    1021                 :            :                               ITEM_GRASS,
    1022                 :            :                               10000);
    1023                 :            :     }
    1024                 :            :     uint64_t  t[2];
    1025         [ +  + ]:       3505 :     while (battles[bid].is_alloced) {
    1026                 :       3502 :         battles[bid].global_time++;
    1027                 :       3502 :         t[0] = myclock();
    1028                 :       3502 :         move_bullets(bid);
    1029                 :       3502 :         check_all_user_status(bid);
    1030                 :            :         //check_who_is_dead(bid);
    1031                 :       3502 :         inform_all_user_battle_state(bid);
    1032                 :            : 
    1033         [ +  + ]:       3499 :         if (battles[bid].global_time % 10 == 0) {
    1034                 :        364 :             inform_all_user_battle_player(bid);
    1035                 :            :         }
    1036                 :       3499 :         clear_items(bid);
    1037                 :       3499 :         random_generate_items(bid);
    1038                 :       3499 :         t[1] = myclock();
    1039                 :            :         /* 时间种子 不测
    1040                 :            :         if (t[1] - t[0] >= 5)
    1041                 :            :             //logw("current delay %lums", t[1] - t[0]);
    1042                 :            :         //sum_delay_time += t[1] - t[0];
    1043                 :            :         while (myclock() < t[0] + GLOBAL_SPEED)
    1044                 :            :             usleep(1000);
    1045                 :            :             */
    1046                 :            :     }
    1047                 :          3 :     return NULL;
    1048                 :            : }
    1049                 :            : 
    1050                 :         11 : int check_user_registered(char* user_name, char* password) {
    1051         [ +  + ]:         55 :     for (int i = 0; i < REGISTERED_USER_LIST_SIZE; i++) {
    1052         [ +  + ]:         52 :         if (strncmp(user_name, registered_user_list[i].user_name, USERNAME_SIZE - 1) != 0)
    1053                 :         44 :             continue;
    1054                 :            : 
    1055         [ +  + ]:          8 :         if (strncmp(password, registered_user_list[i].password, PASSWORD_SIZE - 1) != 0) {
    1056                 :          1 :             logi("user name %s sent error password", user_name);
    1057                 :          1 :             return SERVER_RESPONSE_LOGIN_FAIL_ERROR_PASSWORD;
    1058                 :            :         } else {
    1059                 :          7 :             return SERVER_RESPONSE_LOGIN_SUCCESS;
    1060                 :            :         }
    1061                 :            :     }
    1062                 :            : 
    1063                 :          3 :     logi("user name %s hasn't been registered", user_name);
    1064                 :          3 :     return SERVER_RESPONSE_LOGIN_FAIL_UNREGISTERED_USERID;
    1065                 :            : }
    1066                 :            : 
    1067                 :          6 : void launch_battle(int bid) {
    1068                 :            :     pthread_t thread;
    1069                 :          6 :     pthread_create(&thread, NULL, battle_ruler, (void*)(uintptr_t)bid);
    1070                 :            :     /*
    1071                 :            :     log("try to create battle_ruler thread");
    1072                 :            :     if (pthread_create(&thread, NULL, battle_ruler, (void*)(uintptr_t)bid) == -1) {
    1073                 :            :         eprintf("fail to launch battle");
    1074                 :            :     }
    1075                 :            :      */
    1076                 :          6 : }
    1077                 :            : 
    1078                 :            : 
    1079                 :            : 
    1080                 :          2 : void list_all_users(server_message_t* psm) {
    1081         [ +  + ]:         30 :     for (int i = 0; i < USER_CNT; i++) {
    1082         [ +  + ]:         28 :         if (query_session_built(i)) {
    1083                 :            : 
    1084                 :            :             //log("%s: found %s %s", __func__, sessions[i].user_name,
    1085                 :            :                 //sessions[i].state == USER_STATE_BATTLE ? "in battle" : "");
    1086                 :         27 :             psm->all_users[i].user_state = sessions[i].state;
    1087                 :         27 :             strncpy(psm->all_users[i].user_name, sessions[i].user_name, USERNAME_SIZE - 1);
    1088                 :            :         }
    1089                 :            :     }
    1090                 :          2 : }
    1091                 :            : 
    1092                 :          2 : int client_command_fetch_all_users(int uid) {
    1093                 :          2 :     char* user_name = sessions[uid].user_name;
    1094                 :            :     //log("user #%d %s\033[2m(%s)\033[0m tries to fetch all users's info", uid, user_name, sessions[uid].user_name);
    1095         [ +  + ]:          2 :     if (!query_session_built(uid)) {
    1096                 :            :         //logi("user #%d %s\033[2m(%s)\033[0m who tries to list users hasn't login", uid, user_name, sessions[uid].user_name);
    1097                 :            :         //send_to_client(uid, SERVER_RESPONSE_YOU_HAVE_NOT_LOGIN);
    1098                 :          1 :         return 0;
    1099                 :            :     }
    1100                 :            : 
    1101                 :            :     server_message_t sm;
    1102                 :          1 :     memset(&sm, 0, sizeof(server_message_t));
    1103                 :            :     //list_all_users(&sm);
    1104                 :          1 :     sm.response = SERVER_RESPONSE_ALL_USERS_INFO;
    1105                 :            : 
    1106                 :            :     //wrap_send(sessions[uid].conn, &sm);
    1107                 :            : 
    1108                 :          1 :     return 0;
    1109                 :            : }
    1110                 :            : 
    1111                 :          2 : int client_command_fetch_all_friends(int uid) {
    1112                 :          2 :     char *user_name = sessions[uid].user_name;
    1113                 :            :     //log("user %s tries to fetch info", user_name);
    1114                 :            : 
    1115         [ +  + ]:          2 :     if (!query_session_built(uid)) {
    1116                 :            :         //logi("user %s who tries to list users hasn't login", user_name);
    1117                 :            :         //send_to_client(uid, SERVER_RESPONSE_YOU_HAVE_NOT_LOGIN);
    1118                 :          1 :         return 0;
    1119                 :            :     }
    1120                 :            : 
    1121                 :            :     server_message_t sm;
    1122                 :          1 :     memset(&sm, 0, sizeof(server_message_t));
    1123                 :          1 :     list_all_users(&sm);
    1124                 :          1 :     sm.all_users[uid].user_state = USER_STATE_UNUSED;
    1125                 :          1 :     sm.response = SERVER_RESPONSE_ALL_FRIENDS_INFO;
    1126                 :            : 
    1127                 :            :     //wrap_send(sessions[uid].conn, &sm);
    1128                 :            : 
    1129                 :          1 :     return 0;
    1130                 :            : }
    1131                 :            : 
    1132                 :          6 : int invite_friend_to_battle(int bid, int uid, char* friend_name) {
    1133                 :          6 :     int friend_id = find_uid_by_user_name(friend_name);
    1134         [ +  + ]:          6 :     if (friend_id == -1) {
    1135                 :            :         // fail to find friend
    1136                 :          3 :         logi("friend %s hasn't login", friend_name);
    1137                 :          3 :         send_to_client(uid, SERVER_MESSAGE_FRIEND_NOT_LOGIN);
    1138         [ +  + ]:          3 :     } else if (friend_id == uid) {
    1139                 :          1 :         logi("launch battle %d for %s", bid, sessions[uid].user_name);
    1140                 :          1 :         sessions[uid].inviter_id = uid;
    1141                 :          1 :         send_to_client(uid, SERVER_RESPONSE_INVITATION_SENT);
    1142         [ +  + ]:          2 :     } else if (sessions[friend_id].state == USER_STATE_BATTLE) {
    1143                 :            :         // friend already in battle
    1144                 :          1 :         logi("friend %s already in battle", friend_name);
    1145                 :          1 :         send_to_client(uid, SERVER_MESSAGE_FRIEND_ALREADY_IN_BATTLE);
    1146                 :            :     } else {
    1147                 :            :         // invite friend
    1148                 :          1 :         logi("friend #%d %s found", friend_id, friend_name);
    1149                 :            : 
    1150                 :          1 :         user_invited_to_join_battle(bid, friend_id);
    1151                 :            :         // WARNING: can't move this statement
    1152                 :          1 :         sessions[friend_id].inviter_id = uid;
    1153                 :            : 
    1154                 :          1 :         send_to_client_with_username(friend_id, SERVER_MESSAGE_INVITE_TO_BATTLE, sessions[uid].user_name);
    1155                 :            :     }
    1156                 :            : 
    1157                 :          6 :     return 0;
    1158                 :            : }
    1159                 :            : 
    1160                 :          4 : int client_command_launch_battle(int uid) {
    1161         [ +  + ]:          4 :     if (sessions[uid].state == USER_STATE_BATTLE) {
    1162                 :          1 :         log("user %s who tries to launch battle has been in battle", sessions[uid].user_name);
    1163                 :          1 :         send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE);
    1164                 :          1 :         return 0;
    1165                 :            :     } else {
    1166                 :          3 :         log("user %s tries to launch battle", sessions[uid].user_name);
    1167                 :            :     }
    1168                 :            : 
    1169                 :          3 :     int bid = get_unalloced_battle();
    1170                 :          3 :     client_message_t* pcm = &sessions[uid].cm;
    1171                 :            : 
    1172                 :          3 :     log("%s launch battle with %s", sessions[uid].user_name, pcm->user_name);
    1173                 :            : 
    1174         [ +  + ]:          3 :     if (bid == -1) {
    1175                 :          1 :         loge("fail to create battle for %s and %s", sessions[uid].user_name, pcm->user_name);
    1176                 :          1 :         send_to_client(uid, SERVER_RESPONSE_LAUNCH_BATTLE_FAIL);
    1177                 :          1 :         return 0;
    1178                 :            :     } else {
    1179                 :          2 :         logi("launch battle %d for %s, invite %s", bid, sessions[uid].user_name, pcm->user_name);
    1180                 :          2 :         user_join_battle(bid, uid);
    1181                 :          2 :         cout<<"test:"<<pcm->user_name<<endl;
    1182         [ +  + ]:          2 :         if (strcmp(pcm->user_name, ""))
    1183                 :          1 :             invite_friend_to_battle(bid, uid, pcm->user_name);
    1184                 :          2 :         launch_battle(bid);
    1185                 :          2 :         send_to_client(uid, SERVER_RESPONSE_LAUNCH_BATTLE_SUCCESS);
    1186                 :            :     }
    1187                 :            : 
    1188                 :          2 :     return 0;
    1189                 :            : }
    1190                 :            : 
    1191                 :          2 : int client_command_quit_battle(int uid) {
    1192                 :          2 :     log("user %s tries to quit battle", sessions[uid].user_name);
    1193         [ +  + ]:          2 :     if (sessions[uid].state != USER_STATE_BATTLE) {
    1194                 :          1 :         logi("but he hasn't join battle");
    1195                 :          1 :         send_to_client(uid, SERVER_RESPONSE_YOURE_NOT_IN_BATTLE);
    1196                 :            :     } else {
    1197                 :          1 :         logi("call user_quit_battle to quit");
    1198                 :          1 :         user_quit_battle(sessions[uid].bid, uid);
    1199                 :            :     }
    1200                 :          2 :     return 0;
    1201                 :            : }
    1202                 :            : 
    1203                 :          2 : int client_command_invite_user(int uid) {
    1204                 :          2 :     client_message_t* pcm = &sessions[uid].cm;
    1205                 :          2 :     int bid = sessions[uid].bid;
    1206                 :          2 :     int friend_id = find_uid_by_user_name(pcm->user_name);
    1207                 :          2 :     log("user #%d %s\033[2m(%s)\033[0m tries to invite friend", uid, sessions[uid].user_name, sessions[uid].ip_addr);
    1208                 :            : 
    1209         [ +  + ]:          2 :     if (sessions[uid].state != USER_STATE_BATTLE) {
    1210                 :          1 :         log("user %s\033[2m(%s)\033[0m who invites friend %s wasn't in battle", sessions[uid].user_name, sessions[uid].ip_addr, pcm->user_name);
    1211                 :          1 :         send_to_client(uid, SERVER_RESPONSE_YOURE_NOT_IN_BATTLE);
    1212                 :            :     } else {
    1213                 :          1 :         logi("invite user %s\033[2m(%s)\033[0m to battle #%d", sessions[friend_id].user_name, sessions[uid].ip_addr, bid);
    1214                 :          1 :         invite_friend_to_battle(bid, uid, pcm->user_name);
    1215                 :            :     }
    1216                 :          2 :     return 0;
    1217                 :            : }
    1218                 :            : 
    1219                 :          2 : int client_command_send_message(int uid) {
    1220                 :          2 :     client_message_t* pcm = &sessions[uid].cm;
    1221                 :            :     server_message_t sm;
    1222                 :          2 :     memset(&sm, 0, sizeof(server_message_t));
    1223                 :          2 :     sm.message = SERVER_MESSAGE_FRIEND_MESSAGE;
    1224                 :          2 :     strncpy(sm.from_user, sessions[uid].user_name, USERNAME_SIZE);
    1225                 :          2 :     strncpy(sm.msg, pcm->message, MSG_SIZE);
    1226         [ +  + ]:          2 :     if (pcm->user_name[0] == '\0') {
    1227                 :            :         //logi("user %d:%s\033[2m(%s)\033[0m yells at all users: %s", uid, sessions[uid].user_name, sessions[uid].ip_addr, pcm->message);
    1228                 :            :         int i;
    1229         [ +  + ]:         15 :         for (i = 0; i < USER_CNT; i++) {
    1230         [ +  + ]:         14 :             if (uid == i)
    1231                 :          1 :                 continue;
    1232                 :            :             //wrap_send(sessions[i].conn, &sm);
    1233                 :         13 :             int w = -1; // test
    1234                 :            :         }
    1235                 :            :     }
    1236                 :            :     else {
    1237                 :          1 :         return 0; // test
    1238                 :            :         /*
    1239                 :            :         int friend_id = find_uid_by_user_name(pcm->user_name);
    1240                 :            :         if (friend_id == -1 || friend_id == uid) {
    1241                 :            :             logi("user %d:%s\033[2m(%s)\033[0m fails to speak to %s:`%s`", uid, sessions[uid].user_name, sessions[uid].ip_addr, pcm->user_name, pcm->message);
    1242                 :            :         } else {
    1243                 :            :             logi("user %d:%s\033[2m(%s)\033[0m speaks to %d:%s : `%s`", uid, sessions[uid].user_name, sessions[uid].ip_addr, friend_id, pcm->user_name, pcm->message);
    1244                 :            :             wrap_send(sessions[friend_id].conn, &sm);
    1245                 :            :         }
    1246                 :            :          */
    1247                 :            :     }
    1248                 :          1 :     return 0;
    1249                 :            : }
    1250                 :            : 
    1251                 :          5 : int client_command_create_ffa(int uid) {
    1252         [ +  + ]:          5 :     if (sessions[uid].state == USER_STATE_BATTLE) {
    1253                 :          2 :         log("user %s who tries to launch battle has been in battle", sessions[uid].user_name);
    1254                 :          2 :         send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE);
    1255                 :          2 :         return 0;
    1256                 :            :     } else {
    1257                 :          3 :         log("user %s tries to create ffa sessions #0", sessions[uid].user_name);
    1258                 :            :     }
    1259                 :            : 
    1260                 :          3 :     int bid = 0;
    1261                 :          3 :     client_message_t* pcm = &sessions[uid].cm;
    1262                 :            : 
    1263                 :          3 :     log("%s launch battle with %s", sessions[uid].user_name, pcm->user_name);
    1264                 :          3 :     cout<<"state:  "<<battles[bid].is_alloced<<endl;
    1265         [ +  + ]:          3 :     if (battles[bid].is_alloced) {
    1266                 :          1 :         loge("fail to create battle for %s and %s", sessions[uid].user_name, pcm->user_name);
    1267                 :          1 :         send_to_client(uid, SERVER_RESPONSE_LAUNCH_BATTLE_FAIL);
    1268                 :          1 :         return 0;
    1269                 :            :     } else {
    1270                 :          2 :         logi("launch battle #0 for ffa");
    1271                 :          2 :         battles[bid].is_alloced = true;
    1272                 :          2 :         user_join_battle(bid, uid);
    1273         [ +  + ]:          2 :         if (strcmp(pcm->user_name, ""))
    1274                 :          1 :             invite_friend_to_battle(bid, uid, pcm->user_name);
    1275                 :          2 :         launch_battle(bid);
    1276                 :          2 :         send_to_client(uid, SERVER_RESPONSE_LAUNCH_BATTLE_SUCCESS);
    1277                 :            :     }
    1278                 :            : 
    1279                 :          2 :     return 0;
    1280                 :            : }
    1281                 :            : 
    1282                 :          3 : int client_command_launch_ffa(int uid) {
    1283                 :          3 :     log("user %s\033[2m(%s)\033[0m try ffa", sessions[uid].user_name, sessions[uid].ip_addr);
    1284                 :            : 
    1285         [ +  + ]:          3 :     if (sessions[uid].state == USER_STATE_BATTLE) {
    1286                 :          1 :         logi("already in battle");
    1287                 :          1 :         send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE);
    1288                 :            :     } else {
    1289                 :          2 :         int bid = 0;
    1290                 :            : 
    1291         [ +  + ]:          2 :         if (battles[bid].is_alloced) {
    1292                 :          1 :             user_join_battle(bid, uid);
    1293                 :          1 :             logi("accept success");
    1294                 :            :         } else {
    1295                 :          1 :             logi("user %s created ffa session #0", sessions[uid].user_name);
    1296                 :          1 :             client_command_create_ffa(uid);
    1297                 :            :         }
    1298                 :            :     }
    1299                 :          3 :     return 0;
    1300                 :            : }
    1301                 :            : 
    1302                 :          4 : int client_command_accept_battle(int uid) {
    1303                 :          4 :     log("user %s\033[2m(%s)\033[0m accept battle #%d", sessions[uid].user_name, sessions[uid].ip_addr, sessions[uid].bid);
    1304                 :            : 
    1305         [ +  + ]:          4 :     if (sessions[uid].state == USER_STATE_BATTLE) {
    1306                 :          1 :         logi("already in battle");
    1307                 :          1 :         send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE);
    1308         [ +  + ]:          3 :     } else if (sessions[uid].state == USER_STATE_WAIT_TO_BATTLE) {
    1309                 :          2 :         int inviter_id = sessions[uid].inviter_id;
    1310                 :          2 :         int bid = sessions[uid].bid;
    1311                 :            : 
    1312         [ +  + ]:          2 :         if (battles[bid].is_alloced) {
    1313                 :          1 :             send_to_client_with_username(inviter_id, SERVER_MESSAGE_FRIEND_ACCEPT_BATTLE, sessions[inviter_id].user_name);
    1314                 :          1 :             user_join_battle(bid, uid);
    1315                 :          1 :             logi("accept success");
    1316                 :            :         } else {
    1317                 :          1 :             logi("user %s\033[2m(%s)\033[0m accept battle which didn't exist", sessions[uid].user_name, sessions[uid].ip_addr);
    1318                 :          1 :             send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE);
    1319                 :            :         }
    1320                 :            : 
    1321                 :            :     } else {
    1322                 :          1 :         logi("hasn't been invited");
    1323                 :          1 :         send_to_client(uid, SERVER_RESPONSE_NOBODY_INVITE_YOU);
    1324                 :            :     }
    1325                 :            : 
    1326                 :          4 :     return 0;
    1327                 :            : }
    1328                 :            : 
    1329                 :          3 : int client_command_reject_battle(int uid) {
    1330                 :          3 :     log("user %s\033[2m(%s)\033[0m reject battle #%d", sessions[uid].user_name, sessions[uid].ip_addr, sessions[uid].bid);
    1331         [ +  + ]:          3 :     if (sessions[uid].state == USER_STATE_BATTLE) {
    1332                 :          1 :         logi("user already in battle");
    1333                 :          1 :         send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE);
    1334         [ +  + ]:          2 :     } else if (sessions[uid].state == USER_STATE_WAIT_TO_BATTLE) {
    1335                 :          1 :         logi("reject success");
    1336                 :          1 :         int bid = sessions[uid].bid;
    1337                 :          1 :         send_to_client(sessions[uid].inviter_id, SERVER_MESSAGE_FRIEND_REJECT_BATTLE);
    1338                 :          1 :         sessions[uid].state = USER_STATE_LOGIN;
    1339                 :          1 :         battles[bid].users[uid].battle_state = BATTLE_STATE_UNJOINED;
    1340                 :            :     } else {
    1341                 :          1 :         logi("hasn't been invited");
    1342                 :          1 :         send_to_client(uid, SERVER_RESPONSE_NOBODY_INVITE_YOU);
    1343                 :            :     }
    1344                 :          3 :     return 0;
    1345                 :            : }
    1346                 :            : 
    1347                 :          4 : int client_command_quit(int uid) {
    1348                 :          4 :     int conn = sessions[uid].conn;
    1349         [ +  + ]:          4 :     if (sessions[uid].state == USER_STATE_BATTLE
    1350         [ +  + ]:          3 :         || sessions[uid].state == USER_STATE_WAIT_TO_BATTLE) {
    1351                 :          2 :         log("user #%d %s tries to quit client was in battle", uid, sessions[uid].user_name);
    1352                 :          2 :         user_quit_battle(sessions[uid].bid, uid);
    1353                 :            :     }
    1354                 :            : 
    1355         [ +  + ]:          4 :     if (sessions[uid].conn >= 0) {
    1356                 :          2 :         sessions[uid].conn = -1;
    1357                 :          2 :         log("user #%d %s quit", uid, sessions[uid].user_name);
    1358                 :          2 :         sessions[uid].state = USER_STATE_UNUSED;
    1359                 :          2 :         close(conn);
    1360                 :            :     }
    1361                 :          4 :     return -1;
    1362                 :            : }
    1363                 :            : 
    1364                 :          2 : int client_command_move_up(int uid) {
    1365                 :          2 :     log("user #%d %s\033[2m(%s)\033[0m move up", uid, sessions[uid].user_name, sessions[uid].ip_addr);
    1366                 :          2 :     int bid = sessions[uid].bid;
    1367                 :          2 :     battles[bid].users[uid].dir = DIR_UP;
    1368         [ +  + ]:          2 :     if (battles[bid].users[uid].pos.y > 0) {
    1369                 :          1 :         battles[bid].users[uid].pos.y--;
    1370                 :          1 :         check_user_status(uid);
    1371                 :            :     }
    1372                 :          2 :     return 0;
    1373                 :            : }
    1374                 :            : 
    1375                 :          2 : int client_command_move_down(int uid) {
    1376                 :          2 :     log("user #%d %s\033[2m(%s)\033[0m move down", uid, sessions[uid].user_name, sessions[uid].ip_addr);
    1377                 :          2 :     int bid = sessions[uid].bid;
    1378                 :          2 :     battles[bid].users[uid].dir = DIR_DOWN;
    1379         [ +  + ]:          2 :     if (battles[bid].users[uid].pos.y < BATTLE_H - 1) {
    1380                 :          1 :         battles[bid].users[uid].pos.y++;
    1381                 :          1 :         check_user_status(uid);
    1382                 :            :     }
    1383                 :          2 :     return 0;
    1384                 :            : }
    1385                 :            : 
    1386                 :          2 : int client_command_move_left(int uid) {
    1387                 :          2 :     log("user #%d %s\033[2m(%s)\033[0m move left", uid, sessions[uid].user_name, sessions[uid].ip_addr);
    1388                 :          2 :     int bid = sessions[uid].bid;
    1389                 :          2 :     battles[bid].users[uid].dir = DIR_LEFT;
    1390         [ +  + ]:          2 :     if (battles[bid].users[uid].pos.x > 0) {
    1391                 :          1 :         battles[bid].users[uid].pos.x--;
    1392                 :          1 :         check_user_status(uid);
    1393                 :            :     }
    1394                 :          2 :     return 0;
    1395                 :            : }
    1396                 :            : 
    1397                 :          2 : int client_command_move_right(int uid) {
    1398                 :          2 :     log("user #%d %s\033[2m(%s)\033[0m move right", uid, sessions[uid].user_name, sessions[uid].ip_addr);
    1399                 :          2 :     int bid = sessions[uid].bid;
    1400                 :          2 :     battles[bid].users[uid].dir = DIR_RIGHT;
    1401         [ +  + ]:          2 :     if (battles[bid].users[uid].pos.x < BATTLE_W - 1) {
    1402                 :          1 :         battles[bid].users[uid].pos.x++;
    1403                 :          1 :         check_user_status(uid);
    1404                 :            :     }
    1405                 :          2 :     return 0;
    1406                 :            : }
    1407                 :            : 
    1408                 :          5 : int client_command_put_landmine(int uid) {
    1409                 :          5 :     int bid = sessions[uid].bid;
    1410                 :            : 
    1411         [ +  + ]:          5 :     if (battles[bid].users[uid].energy < LANDMINE_COST) {
    1412                 :            :         //send_to_client(uid, SERVER_MESSAGE_YOUR_MAGAZINE_IS_EMPTY);
    1413                 :          1 :         return 0;
    1414                 :            :     }
    1415                 :          4 :     int x = battles[bid].users[uid].pos.x;
    1416                 :          4 :     int y = battles[bid].users[uid].pos.y;
    1417                 :            :     /*
    1418                 :            :     if (x < 0 || x >= BATTLE_W) return 1;
    1419                 :            :     if (y < 0 || y >= BATTLE_H) return 1;
    1420                 :            :      */
    1421         [ +  + ]:          4 :     if ( x >= BATTLE_W) return 1;
    1422         [ +  + ]:          3 :     if ( y >= BATTLE_H) return 1;
    1423                 :            :     //log("user #%d %s\033[2m(%s)\033[0m put at (%d, %d)", uid, sessions[uid].user_name, sessions[uid].ip_addr, x, y);
    1424                 :          2 :     item_t new_item;
    1425                 :          2 :     new_item.id = ++battles[bid].item_count;
    1426                 :          2 :     new_item.kind = ITEM_LANDMINE;
    1427                 :          2 :     new_item.owner = uid;
    1428                 :          2 :     new_item.pos.x = x;
    1429                 :          2 :     new_item.pos.y = y;
    1430                 :          2 :     new_item.time = battles[bid].global_time + INF;
    1431                 :          2 :     battles[bid].users[uid].energy -= LANDMINE_COST;
    1432                 :            :     //battles[bid].items.push_back(new_item);
    1433                 :            :     //log("current item size: %ld", battles[bid].items.size());
    1434                 :          2 :     return 0;
    1435                 :            : }
    1436                 :            : 
    1437                 :         27 : int client_command_fire(int uid, int delta_x, int delta_y, int dir) {
    1438                 :         27 :     int bid = sessions[uid].bid;
    1439                 :            : 
    1440         [ +  + ]:         27 :     if (battles[bid].users[uid].energy <= 0) {
    1441                 :            :         //send_to_client(uid, SERVER_MESSAGE_YOUR_MAGAZINE_IS_EMPTY);
    1442                 :          1 :         return 0;
    1443                 :            :     }
    1444                 :         26 :     int x = battles[bid].users[uid].pos.x + delta_x;
    1445                 :         26 :     int y = battles[bid].users[uid].pos.y + delta_y;
    1446   [ +  +  +  + ]:         26 :     if (x < 0 || x >= BATTLE_W) return 1;
    1447   [ +  +  +  + ]:         22 :     if (y < 0 || y >= BATTLE_H) return 1;
    1448                 :            :     //log("user #%d %s\033[2m(%s)\033[0m fire %s", uid, sessions[uid].user_name, sessions[uid].ip_addr, dir_s[dir]);
    1449                 :         17 :     item_t new_item;
    1450                 :         17 :     new_item.id = ++battles[bid].item_count;
    1451                 :         17 :     new_item.kind = ITEM_BULLET;
    1452                 :         17 :     new_item.dir = dir;
    1453                 :         17 :     new_item.owner = uid;
    1454                 :         17 :     new_item.pos.x = x;
    1455                 :         17 :     new_item.pos.y = y;
    1456                 :         17 :     new_item.time = battles[bid].global_time + BULLETS_LASTS_TIME;
    1457                 :         17 :     battles[bid].users[uid].energy--;
    1458                 :            :     //battles[bid].items.push_back(new_item); // 奇怪的分支 先注释掉
    1459                 :            :     //log("current item size: %ld", battles[bid].items.size());
    1460                 :         17 :     return 0;
    1461                 :            : }
    1462                 :            : 
    1463                 :          1 : int client_command_fire_up(int uid) {
    1464                 :          1 :     logi("client_command_fire");
    1465                 :          1 :     client_command_fire(uid, 0, 0, DIR_UP);
    1466                 :          1 :     return 0;
    1467                 :            : }
    1468                 :          1 : int client_command_fire_down(int uid) {
    1469                 :          1 :     logi("client_command_fire");
    1470                 :          1 :     client_command_fire(uid, 0, 0, DIR_DOWN);
    1471                 :          1 :     return 0;
    1472                 :            : }
    1473                 :          1 : int client_command_fire_left(int uid) {
    1474                 :          1 :     logi("client_command_fire");
    1475                 :          1 :     client_command_fire(uid, 0, 0, DIR_LEFT);
    1476                 :          1 :     return 0;
    1477                 :            : }
    1478                 :          1 : int client_command_fire_right(int uid) {
    1479                 :          1 :     logi("client_command_fire");
    1480                 :          1 :     client_command_fire(uid, 0, 0, DIR_RIGHT);
    1481                 :          1 :     return 0;
    1482                 :            : }
    1483                 :            : 
    1484                 :          1 : int client_command_fire_up_left(int uid) {
    1485                 :          1 :     logi("client_command_fire");
    1486                 :          1 :     client_command_fire(uid, 0, 0, DIR_UP_LEFT);
    1487                 :          1 :     return 0;
    1488                 :            : }
    1489                 :          1 : int client_command_fire_up_right(int uid) {
    1490                 :          1 :     logi("client_command_fire");
    1491                 :          1 :     client_command_fire(uid, 0, 0, DIR_UP_RIGHT);
    1492                 :          1 :     return 0;
    1493                 :            : }
    1494                 :          1 : int client_command_fire_down_left(int uid) {
    1495                 :          1 :     logi("client_command_fire");
    1496                 :          1 :     client_command_fire(uid, 0, 0, DIR_DOWN_LEFT);
    1497                 :          1 :     return 0;
    1498                 :            : }
    1499                 :          1 : int client_command_fire_down_right(int uid) {
    1500                 :          1 :     logi("client_command_fire");
    1501                 :          1 :     client_command_fire(uid, 0, 0, DIR_DOWN_RIGHT);
    1502                 :          1 :     return 0;
    1503                 :            : }
    1504                 :            : 
    1505                 :          5 : int client_command_fire_aoe(int uid, int dir) {
    1506                 :          5 :     log("user #%d %s\033[2m(%s)\033[0m fire(aoe) %s", uid, sessions[uid].user_name, sessions[uid].ip_addr, dir_s[dir]);
    1507                 :          5 :     logi("call client_command_fire");
    1508                 :          5 :     int limit = battles[sessions[uid].bid].users[uid].energy / 2, cnt = 0;
    1509         [ +  + ]:         14 :     for (int i = 0; limit; i++) {
    1510   [ +  +  +  + ]:         21 :         for (int j = -i; j <= i && limit; j++) {
    1511   [ +  +  +  +  :         12 :             switch (dir) {
                      + ]
    1512                 :          4 :                 case DIR_UP: {
    1513         [ +  + ]:          4 :                     if (client_command_fire(uid, j, -i + abs(j), dir) == 0) cnt++;
    1514                 :          4 :                     break;
    1515                 :            :                 }
    1516                 :          3 :                 case DIR_DOWN: {
    1517         [ +  + ]:          3 :                     if (client_command_fire(uid, j, i - abs(j), dir) == 0) cnt++;
    1518                 :          3 :                     break;
    1519                 :            :                 }
    1520                 :          2 :                 case DIR_LEFT: {
    1521         [ +  + ]:          2 :                     if (client_command_fire(uid, -i + abs(j), j, dir) == 0) cnt++;
    1522                 :          2 :                     break;
    1523                 :            :                 }
    1524                 :          2 :                 case DIR_RIGHT: {
    1525         [ +  + ]:          2 :                     if (client_command_fire(uid, i - abs(j), j, dir) == 0) cnt++;
    1526                 :          2 :                     break;
    1527                 :            :                 }
    1528                 :            :             }
    1529                 :         12 :             limit--;
    1530                 :            :         }
    1531                 :            :     }
    1532                 :          5 :     log("created %d bullets", cnt);
    1533                 :          5 :     return 0;
    1534                 :            : }
    1535                 :            : 
    1536                 :          1 : int client_command_fire_aoe_up(int uid) {
    1537                 :          1 :     logi("call client_command_fire_aoe");
    1538                 :          1 :     return client_command_fire_aoe(uid, DIR_UP);
    1539                 :            : }
    1540                 :          1 : int client_command_fire_aoe_down(int uid) {
    1541                 :          1 :     logi("call client_command_fire_aoe");
    1542                 :          1 :     return client_command_fire_aoe(uid, DIR_DOWN);
    1543                 :            : }
    1544                 :          1 : int client_command_fire_aoe_left(int uid) {
    1545                 :          1 :     logi("call client_command_fire_aoe");
    1546                 :          1 :     return client_command_fire_aoe(uid, DIR_LEFT);
    1547                 :            : }
    1548                 :          1 : int client_command_fire_aoe_right(int uid) {
    1549                 :          1 :     logi("call client_command_fire_aoe");
    1550                 :          1 :     return client_command_fire_aoe(uid, DIR_RIGHT);
    1551                 :            : }
    1552                 :            : 
    1553                 :          2 : int client_command_melee(int uid) {
    1554                 :          2 :     int bid = sessions[uid].bid;
    1555         [ +  + ]:          2 :     if (battles[bid].users[uid].life <= 0) return 0;
    1556                 :          1 :     int dir = battles[bid].users[uid].dir;
    1557                 :          1 :     int x = battles[bid].users[uid].pos.x;
    1558                 :          1 :     int y = battles[bid].users[uid].pos.y;
    1559                 :          1 :     log("user #%d %s\033[2m(%s)\033[0m melee %s", uid, sessions[uid].user_name, sessions[uid].ip_addr, dir_s[dir]);
    1560         [ +  + ]:          4 :     for (int i = 1; i <= 3; i++) {
    1561                 :          3 :         forced_generate_items(bid, 
    1562                 :          3 :                               x + dir_offset[dir].x * i,
    1563                 :          3 :                               y + dir_offset[dir].y * i,
    1564                 :            :                               ITEM_MAGMA,
    1565                 :            :                               3,
    1566                 :            :                               uid);
    1567                 :            :     }
    1568                 :          1 :     return 0;
    1569                 :            : }
    1570                 :            : 
    1571                 :          5 : int admin_set_admin(int argc, char** argv) {
    1572         [ +  + ]:          5 :     if (argc < 3) return -1;
    1573                 :          4 :     cout<<"username: "<<argv[1]<<" status: "<<atoi(argv[2])<<" uid:";
    1574                 :          4 :     cout<<find_uid_by_user_name(argv[1])<<endl;
    1575                 :          4 :     int uid = find_uid_by_user_name(argv[1]),status = atoi(argv[2]);
    1576         [ +  + ]:          4 :     if (uid < 0 ||
    1577                 :            :         // uid >= USER_CNT ||
    1578         [ +  + ]:          3 :         sessions[uid].conn < 0) {
    1579                 :          2 :         return -1;
    1580                 :            :     }
    1581         [ +  + ]:          2 :     if (status)
    1582                 :          1 :         log("admin set user #%d admin", uid);
    1583                 :            :     else
    1584                 :          1 :         log("admin set user #%d non-admin", uid);
    1585                 :          2 :     sessions[uid].is_admin = status;
    1586         [ +  + ]:         30 :     for (int i = 0; i < USER_CNT; i++) {
    1587         [ +  + ]:         28 :         if (sessions[i].conn >= 0) {
    1588         [ +  + ]:         26 :             if (status) {
    1589                 :         13 :                 say_to_client(i, sformat("admin set user #%d %s to admin", uid, sessions[uid].user_name));
    1590                 :            :             } else {
    1591                 :         13 :                 say_to_client(i, sformat("admin set user #%d %s to non-admin", uid, sessions[uid].user_name));
    1592                 :            :             }
    1593                 :            :         }
    1594                 :            :     }
    1595                 :          2 :     return 0;
    1596                 :            : }
    1597                 :            : 
    1598                 :          5 : int admin_set_energy(int argc, char** argv) {
    1599         [ +  + ]:          5 :     if (argc < 3) return -1;
    1600                 :          4 :     int uid = find_uid_by_user_name(argv[1]), energy = atoi(argv[2]);
    1601                 :          4 :     log("admin set user #%d's energy", uid);
    1602                 :          4 :     cout<<"uid:"<<uid<<" conn:"<<sessions[uid].conn<<" energy:"<<energy<<endl;
    1603         [ +  + ]:          4 :     if (uid < 0 || //uid >= USER_CNT ||
    1604   [ +  +  +  + ]:          3 :     sessions[uid].conn < 0 ||
    1605                 :            :     energy < 0) {
    1606                 :          3 :         return -1;
    1607                 :            :     }
    1608                 :          1 :     log("admin set user #%d %s's energy to %d", uid, sessions[uid].user_name, energy);
    1609                 :          1 :     battles[sessions[uid].bid].users[uid].energy = energy;
    1610         [ +  + ]:         15 :     for (int i = 0; i < USER_CNT; i++) {
    1611         [ +  + ]:         14 :         if (sessions[i].conn >= 0) {
    1612                 :         13 :             say_to_client(i, sformat("admin set user #%d %s's energy to %d", uid, sessions[uid].user_name, energy));
    1613                 :            :         }
    1614                 :            :     }
    1615                 :          1 :     return 0;
    1616                 :            : }
    1617                 :            : 
    1618                 :          5 : int admin_set_hp(int argc, char** argv) {
    1619         [ +  + ]:          5 :     if (argc < 3) return -1;
    1620                 :          4 :     int uid = find_uid_by_user_name(argv[1]), hp = atoi(argv[2]);
    1621         [ +  + ]:          4 :     if (uid < 0 || //uid >= USER_CNT||
    1622   [ +  +  +  + ]:          3 :     sessions[uid].conn < 0 ||
    1623                 :            :     hp < 0) {
    1624                 :          3 :         return -1;
    1625                 :            :     }
    1626                 :          1 :     log("admin set user #%d %s's hp to %d", uid, sessions[uid].user_name, hp);
    1627                 :          1 :     battles[sessions[uid].bid].users[uid].life = hp;
    1628         [ +  + ]:         15 :     for (int i = 0; i < USER_CNT; i++) {
    1629         [ +  + ]:         14 :         if (sessions[i].conn >= 0) {
    1630                 :         13 :             say_to_client(i, sformat("admin set user #%d %s's hp to %d", uid, sessions[uid].user_name, hp));
    1631                 :            :         }
    1632                 :            :     }
    1633                 :          1 :     return 0;
    1634                 :            : }
    1635                 :            : 
    1636                 :          9 : int admin_set_pos(int argc, char** argv) {
    1637         [ +  + ]:          9 :     if (argc < 4) return -1;
    1638                 :          8 :     int uid = find_uid_by_user_name(argv[1]);
    1639                 :          8 :     int x = atoi(argv[2]), y = atoi(argv[3]);
    1640                 :          8 :     cout<<"x:"<<atoi(argv[2])<<"y:"<<atoi(argv[3])<<endl;
    1641                 :          8 :     cout<<"uid: "<<uid<<"conn: "<<sessions[uid].conn<<endl;
    1642         [ +  + ]:          8 :     if (uid < 0 || //uid >= USER_CNT ||
    1643         [ +  + ]:          7 :     sessions[uid].conn < 0) {
    1644                 :          2 :         return -1;
    1645                 :            :     }
    1646                 :          6 :     cout<<"x:"<<x<<"y:"<<y<<endl;
    1647   [ +  +  +  + ]:          6 :     if (x < 0 || x >= BATTLE_W) return -1;
    1648   [ +  +  +  + ]:          3 :     if (y < 0 || y >= BATTLE_H) return -1;
    1649                 :          1 :     log("admin set user #%d %s's pos to (%d, %d)", uid, sessions[uid].user_name, x, y);
    1650                 :          1 :     battles[sessions[uid].bid].users[uid].pos.x = x;
    1651                 :          1 :     battles[sessions[uid].bid].users[uid].pos.y = y;
    1652                 :          1 :     return 0;
    1653                 :            : }
    1654                 :            : 
    1655                 :          4 : int admin_ban_user(int argc, char** argv) {
    1656         [ +  + ]:          4 :     if (argc < 2) return -1;
    1657                 :          3 :     int uid = find_uid_by_user_name(argv[1]);
    1658                 :          3 :     log("admin ban user #%d", uid);
    1659         [ +  + ]:          3 :     if (uid < 0 // || uid >= USER_CNT
    1660                 :            :     ) {
    1661                 :          1 :         logi("fail");
    1662                 :          1 :         return -1;
    1663                 :            :     }
    1664         [ +  + ]:          2 :     if (sessions[uid].conn >= 0) {
    1665                 :          1 :         log("admin banned user #%d %s\033[2m(%s)\033[0m", uid, sessions[uid].user_name, sessions[uid].ip_addr);
    1666                 :          1 :         send_to_client(
    1667                 :            :             uid, SERVER_STATUS_QUIT,
    1668                 :            :             (char*)" (you were banned by admin)");
    1669                 :          1 :         client_command_quit(uid);
    1670         [ +  + ]:         15 :         for (int i = 0; i < USER_CNT; i++) {
    1671         [ +  + ]:         14 :             if (sessions[i].conn >= 0) {
    1672                 :         12 :                 say_to_client(i, sformat("admin banned user #%d %s\033[2m(%s)\033[0m", uid, sessions[uid].user_name, sessions[uid].ip_addr));
    1673                 :            :             }
    1674                 :            :         }
    1675                 :            :     }
    1676                 :          2 :     return 0;
    1677                 :            : }
    1678                 :            : 
    1679                 :            : static struct {
    1680                 :            :     const char* cmd;
    1681                 :            :     int (*func)(int argc, char** argv);
    1682                 :            : } admin_handler[] = {
    1683                 :            :     {"ban", admin_ban_user},
    1684                 :            :     {"eng", admin_set_energy},
    1685                 :            :     {"energy", admin_set_energy},
    1686                 :            :     {"hp", admin_set_hp},
    1687                 :            :     {"setadmin", admin_set_admin},
    1688                 :            :     {"pos", admin_set_pos},
    1689                 :            : };
    1690                 :            : 
    1691                 :            : #define NR_HANDLER ((int)sizeof(admin_handler) / (int)sizeof(admin_handler[0]))
    1692                 :            : 
    1693                 :          2 : int client_command_admin_control(int uid) {
    1694         [ +  + ]:          2 :     if (!sessions[uid].is_admin) {
    1695                 :            :         //say_to_client(uid, (char*)"you are not admin");
    1696                 :          1 :         return 0;
    1697                 :            :     }
    1698                 :          1 :     client_message_t* pcm = &sessions[uid].cm;
    1699                 :          1 :     char *buff = (char*)pcm->message;
    1700                 :            :     //log("analysis command `%s`", buff);
    1701                 :            :     /*
    1702                 :            :     char *go = buff, *argv[ADMIN_COMMAND_LEN];
    1703                 :            :     int argc = 0;
    1704                 :            :     while (*go != 0) {
    1705                 :            :         if (!isspace(*go)) {
    1706                 :            :             argv[argc] = go;
    1707                 :            :             argc++;
    1708                 :            :             char c = (*go == '"') ? '"' : ' ';
    1709                 :            :             while ((*go != 0) && (*go != c)) go++;
    1710                 :            :             if (*go == 0) break;
    1711                 :            :             *go = 0;
    1712                 :            :         }
    1713                 :            :         go++;
    1714                 :            :     }
    1715                 :            :     if (argc) {
    1716                 :            :         argv[argc] = NULL;
    1717                 :            :         for (int i = 0; i < NR_HANDLER; i++) {
    1718                 :            :             if (strcmp(argv[0], admin_handler[i].cmd) == 0) {
    1719                 :            :                 if (admin_handler[i].func(argc, argv)) {
    1720                 :            :                     int s = 0;
    1721                 :            :                     //say_to_client(uid, (char*)"invalid command!");
    1722                 :            :                 }
    1723                 :            :                 return 0;
    1724                 :            :             }
    1725                 :            :         }
    1726                 :            :     }
    1727                 :            :      */
    1728                 :            :     //say_to_client(uid, (char*)"invalid command!");
    1729                 :          1 :     return 0;
    1730                 :            : }
    1731                 :            : 
    1732                 :          1 : int client_message_fatal(int uid) {
    1733                 :          1 :     loge("received FATAL from user #%d %s\033[2m(%s)\033[0m ", uid, sessions[uid].user_name, sessions[uid].ip_addr);
    1734         [ +  + ]:         15 :     for (int i = 0; i < USER_CNT; i++) {
    1735         [ +  + ]:         14 :         if (sessions[i].conn >= 0) {
    1736                 :         12 :             send_to_client(i, SERVER_STATUS_FATAL);
    1737                 :         12 :             log("send FATAL to user #%d %s\033[2m(%s)\033[0m", i, sessions[i].user_name, sessions[i].ip_addr);
    1738                 :            :         }
    1739                 :            :     }
    1740                 :            :     //terminate_process(0);
    1741                 :          1 :     return 0;
    1742                 :            : }
    1743                 :            : 
    1744                 :            : static int (*handler[256])(int);
    1745                 :            : 
    1746                 :          1 : void init_handler() {
    1747                 :          1 :     handler[CLIENT_MESSAGE_FATAL] = client_message_fatal,
    1748                 :            : 
    1749                 :          1 :     handler[CLIENT_COMMAND_USER_QUIT] = client_command_quit,
    1750                 :          1 :     handler[CLIENT_COMMAND_USER_REGISTER] = client_command_user_register,
    1751                 :          1 :     handler[CLIENT_COMMAND_USER_LOGIN] = client_command_user_login,
    1752                 :          1 :     handler[CLIENT_COMMAND_USER_LOGOUT] = client_command_user_logout,
    1753                 :            : 
    1754                 :          1 :     handler[CLIENT_COMMAND_FETCH_ALL_USERS] = client_command_fetch_all_users,
    1755                 :          1 :     handler[CLIENT_COMMAND_FETCH_ALL_FRIENDS] = client_command_fetch_all_friends,
    1756                 :            : 
    1757                 :          1 :     handler[CLIENT_COMMAND_LAUNCH_BATTLE] = client_command_launch_battle,
    1758                 :          1 :     handler[CLIENT_COMMAND_QUIT_BATTLE] = client_command_quit_battle,
    1759                 :          1 :     handler[CLIENT_COMMAND_ACCEPT_BATTLE] = client_command_accept_battle,
    1760                 :          1 :     handler[CLIENT_COMMAND_LAUNCH_FFA] = client_command_launch_ffa,
    1761                 :          1 :     handler[CLIENT_COMMAND_REJECT_BATTLE] = client_command_reject_battle,
    1762                 :          1 :     handler[CLIENT_COMMAND_INVITE_USER] = client_command_invite_user,
    1763                 :            : 
    1764                 :          1 :     handler[CLIENT_COMMAND_SEND_MESSAGE] = client_command_send_message,
    1765                 :            : 
    1766                 :          1 :     handler[CLIENT_COMMAND_MOVE_UP] = client_command_move_up,
    1767                 :          1 :     handler[CLIENT_COMMAND_MOVE_DOWN] = client_command_move_down,
    1768                 :          1 :     handler[CLIENT_COMMAND_MOVE_LEFT] = client_command_move_left,
    1769                 :          1 :     handler[CLIENT_COMMAND_MOVE_RIGHT] = client_command_move_right,
    1770                 :            : 
    1771                 :          1 :     handler[CLIENT_COMMAND_PUT_LANDMINE] = client_command_put_landmine,
    1772                 :            :     
    1773                 :          1 :     handler[CLIENT_COMMAND_MELEE] = client_command_melee,
    1774                 :            : 
    1775                 :          1 :     handler[CLIENT_COMMAND_FIRE_UP] = client_command_fire_up,
    1776                 :          1 :     handler[CLIENT_COMMAND_FIRE_DOWN] = client_command_fire_down,
    1777                 :          1 :     handler[CLIENT_COMMAND_FIRE_LEFT] = client_command_fire_left,
    1778                 :          1 :     handler[CLIENT_COMMAND_FIRE_RIGHT] = client_command_fire_right,
    1779                 :            : 
    1780                 :          1 :     handler[CLIENT_COMMAND_FIRE_UP_LEFT] = client_command_fire_up_left,
    1781                 :          1 :     handler[CLIENT_COMMAND_FIRE_UP_RIGHT] = client_command_fire_up_right,
    1782                 :          1 :     handler[CLIENT_COMMAND_FIRE_DOWN_LEFT] = client_command_fire_down_left,
    1783                 :          1 :     handler[CLIENT_COMMAND_FIRE_DOWN_RIGHT] = client_command_fire_down_right,
    1784                 :            : 
    1785                 :          1 :     handler[CLIENT_COMMAND_FIRE_AOE_UP] = client_command_fire_aoe_up,
    1786                 :          1 :     handler[CLIENT_COMMAND_FIRE_AOE_DOWN] = client_command_fire_aoe_down,
    1787                 :          1 :     handler[CLIENT_COMMAND_FIRE_AOE_LEFT] = client_command_fire_aoe_left,
    1788                 :          1 :     handler[CLIENT_COMMAND_FIRE_AOE_RIGHT] = client_command_fire_aoe_right;
    1789                 :            : 
    1790                 :          1 :     handler[CLIENT_COMMAND_ADMIN_CONTROL] = client_command_admin_control;
    1791                 :            : 
    1792                 :          1 : }
    1793                 :            : 
    1794                 :            : /*
    1795                 :            : void wrap_recv(int conn, client_message_t* pcm) {
    1796                 :            :     size_t total_len = 0;
    1797                 :            :     while (total_len < sizeof(client_message_t)) {
    1798                 :            :         size_t len = recv(conn, pcm + total_len, sizeof(client_message_t) - total_len, 0);
    1799                 :            :         if (len < 0) {
    1800                 :            :             loge("broken pipe");
    1801                 :            :         }
    1802                 :            : 
    1803                 :            :         total_len += len;
    1804                 :            :     }
    1805                 :            : }
    1806                 :            : 
    1807                 :            : void wrap_send(int conn, server_message_t* psm) {
    1808                 :            :     size_t total_len = 0;
    1809                 :            :     while (total_len < sizeof(server_message_t)) {
    1810                 :            :         size_t len = send(conn, psm + total_len, sizeof(server_message_t) - total_len, 0);
    1811                 :            : 
    1812                 :            :         if (len < 0) {
    1813                 :            :             loge("broken pipe");
    1814                 :            :         }
    1815                 :            : 
    1816                 :            :         total_len += len;
    1817                 :            :     }
    1818                 :            : }
    1819                 :            : */
    1820                 :            : 
    1821                 :         67 : void send_to_client(int uid, int message) {
    1822                 :         67 :     int conn = sessions[uid].conn;
    1823         [ +  + ]:         67 :     if (conn < 0) return;
    1824                 :            :     server_message_t sm;
    1825                 :         65 :     memset(&sm, 0, sizeof(server_message_t));
    1826                 :         65 :     sm.response = message;
    1827                 :            :     //wrap_send(conn, &sm);
    1828                 :            : }
    1829                 :            : 
    1830                 :          5 : void send_to_client(int uid, int message, char* str) {
    1831                 :          5 :     int conn = sessions[uid].conn;
    1832         [ +  + ]:          5 :     if (conn < 0) return;
    1833                 :            :     server_message_t sm;
    1834                 :          4 :     memset(&sm, 0, sizeof(server_message_t));
    1835                 :          4 :     sm.response = message;
    1836                 :          4 :     strncpy(sm.msg, str, MSG_SIZE - 1);
    1837                 :            :     //wrap_send(conn, &sm);
    1838                 :            : }
    1839                 :            : 
    1840                 :         66 : void say_to_client(int uid, char *message) {
    1841                 :            :     //log("say `%s` to user #%d %s", message, uid, sessions[uid].user_name);
    1842                 :         66 :     int conn = sessions[uid].conn;
    1843         [ +  + ]:         66 :     if (conn < 0) {
    1844                 :            :         //logi("fail");
    1845                 :          1 :         return; }
    1846                 :            :     server_message_t sm;
    1847                 :         65 :     memset(&sm, 0, sizeof(server_message_t));
    1848                 :         65 :     sm.message = SERVER_MESSAGE;
    1849                 :         65 :     strncpy(sm.msg, message, MSG_SIZE - 1);
    1850                 :            :     //wrap_send(conn, &sm);
    1851                 :            : }
    1852                 :            : 
    1853                 :          5 : void send_to_client_with_username(int uid, int message, char* user_name) {
    1854                 :          5 :     int conn = sessions[uid].conn;
    1855         [ +  + ]:          5 :     if (conn < 0) return;
    1856                 :            :     server_message_t sm;
    1857                 :          3 :     memset(&sm, 0, sizeof(server_message_t));
    1858                 :          3 :     sm.response = message;
    1859                 :          3 :     strncpy(sm.friend_name, user_name, USERNAME_SIZE - 1);
    1860                 :            :     //wrap_send(conn, &sm);
    1861                 :            : }
    1862                 :            : 
    1863                 :          1 : void close_session(int conn, int message) {
    1864                 :          1 :     send_to_client(conn, message);
    1865                 :          1 :     close(conn);
    1866                 :          1 : }
    1867                 :            : 
    1868                 :          2 : void* session_start(void* args) {
    1869                 :          2 :     int uid = -1;
    1870                 :          2 :     session_args_t info = *(session_args_t*)(uintptr_t)args;
    1871                 :          2 :     client_message_t* pcm = NULL;
    1872                 :            :     /*
    1873                 :            :     if ((uid = get_unused_session()) < 0) {
    1874                 :            :         close_session(info.conn, SERVER_RESPONSE_LOGIN_FAIL_SERVER_LIMITS);
    1875                 :            :         return NULL;
    1876                 :            :     } else {
    1877                 :            :      */
    1878                 :          2 :     uid = 0;
    1879                 :          2 :         sessions[uid].conn = info.conn;
    1880                 :          2 :         strncpy(sessions[uid].user_name, "<unknown>", USERNAME_SIZE - 1);
    1881                 :          2 :         strncpy(sessions[uid].ip_addr, info.ip_addr, IPADDR_SIZE - 1);
    1882         [ +  + ]:          2 :         if (strncmp(sessions[uid].ip_addr, "", IPADDR_SIZE) == 0) {
    1883                 :          1 :             strncpy(sessions[uid].ip_addr, "unknown", IPADDR_SIZE - 1);
    1884                 :            :         }
    1885                 :          2 :         pcm = &sessions[uid].cm;
    1886                 :          2 :         memset(pcm, 0, sizeof(client_message_t));
    1887                 :            :         //log("build session #%d", uid);
    1888         [ +  + ]:          2 :         if (strncmp(info.ip_addr, "127.0.0.1", IPADDR_SIZE) == 0) {
    1889                 :            :             //log("admin login!");
    1890                 :          1 :             sessions[uid].is_admin = 1;
    1891                 :            :         }
    1892                 :          2 :         sessions[uid].death = sessions[uid].kill = 0;
    1893                 :          2 :         sessions[uid].score = 50;
    1894                 :            :     //}
    1895                 :            :     /*
    1896                 :            :     while (1) {
    1897                 :            :         //wrap_recv(info.conn, pcm);
    1898                 :            : 
    1899                 :            :         if (pcm->command >= CLIENT_COMMAND_END)
    1900                 :            :             continue;
    1901                 :            : 
    1902                 :            :         int ret_code = handler[pcm->command](uid);
    1903                 :            :         if (ret_code < 0) {
    1904                 :            :             //log("close session #%d", uid);
    1905                 :            :             break;
    1906                 :            :         }}
    1907                 :            :         */
    1908                 :          2 :     return NULL;
    1909                 :            : }
    1910                 :            : 
    1911                 :          1 : void* run_battle(void* args) {
    1912                 :            :     // TODO:
    1913                 :          1 :     return NULL;
    1914                 :            : }
    1915                 :            : 
    1916                 :          1 : int server_start() {
    1917                 :          1 :     int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    1918                 :            :     /*
    1919                 :            :     if (sockfd < 0) {
    1920                 :            :         eprintf("create Socket Failed!");
    1921                 :            :     }
    1922                 :            :      */
    1923                 :            : 
    1924                 :            :     struct sockaddr_in servaddr;
    1925                 :          1 :     bool binded = false;
    1926         [ +  + ]:        102 :     for (int cur_port = port; cur_port <= port + port_range; cur_port++) {
    1927                 :        101 :         memset(&servaddr, 0, sizeof(servaddr));
    1928                 :        101 :         servaddr.sin_family = AF_INET;
    1929                 :        101 :         servaddr.sin_port = htons(cur_port);
    1930                 :        101 :         servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    1931                 :            : 
    1932                 :            :         /*
    1933                 :            :         if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {
    1934                 :            :             logw("can not bind to port %d!", cur_port);
    1935                 :            :         } else {
    1936                 :            :             binded = true;
    1937                 :            :             port = cur_port;
    1938                 :            :             break;
    1939                 :            :         }
    1940                 :            : 
    1941                 :            :     }
    1942                 :            : 
    1943                 :            :     if (!binded) {
    1944                 :            :         eprintf("can not start server.");
    1945                 :            :     }
    1946                 :            : 
    1947                 :            :     if (listen(sockfd, USER_CNT) == -1) {
    1948                 :            :         eprintf("fail to listen on socket.");
    1949                 :            :     } else {
    1950                 :            :         log("listen on port %d.", port);
    1951                 :            :     }
    1952                 :            :     */
    1953                 :            : 
    1954                 :        101 :         bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
    1955                 :            :     }
    1956                 :          1 :     return sockfd;
    1957                 :            : }
    1958                 :            : 
    1959                 :          5 : void terminate_process(int signum) {
    1960         [ +  + ]:         75 :     for (int i = 0; i < USER_CNT; i++) {
    1961         [ +  + ]:         70 :         if (sessions[i].conn >= 0) {
    1962                 :         14 :             log("send quit to user #%d %s\033[2m(%s)\033[0m", i, sessions[i].user_name, sessions[i].ip_addr);
    1963         [ +  + ]:         14 :             if (signum) {
    1964                 :          1 :                 send_to_client(
    1965                 :            :                     i, SERVER_STATUS_QUIT,
    1966                 :            :                     sformat(" (runtime error: %s)", signal_name_s[signum]));
    1967                 :            :             } else {
    1968                 :         13 :                 send_to_client(i, SERVER_STATUS_QUIT);
    1969                 :            :             }
    1970                 :         14 :             log("close conn:%d", sessions[i].conn);
    1971                 :            :             //close(sessions[i].conn);
    1972                 :         14 :             sessions[i].conn = -1;
    1973                 :            :         }
    1974                 :            :     }
    1975                 :            : 
    1976         [ +  + ]:          5 :     if (server_fd) {
    1977                 :            :         //close(server_fd);
    1978                 :          3 :         log("close server fd:%d", server_fd);
    1979                 :            :     }
    1980                 :            : 
    1981                 :          5 :     pthread_mutex_destroy(&sessions_lock);
    1982                 :          5 :     pthread_mutex_destroy(&battles_lock);
    1983         [ +  + ]:         75 :     for (int i = 0; i < USER_CNT; i++) {
    1984                 :         70 :         pthread_mutex_destroy(&items_lock[i]);
    1985                 :            :     }
    1986                 :            : 
    1987                 :          5 :     log("exit(%d)", signum);
    1988                 :            :     //exit(signum);
    1989                 :          5 : }
    1990                 :            : 
    1991                 :          2 : void terminate_entrance(int signum) {
    1992                 :          2 :     loge("received signal %s, terminate.", signal_name_s[signum]);
    1993         [ +  + ]:          2 :     terminate_process(signum == SIGINT ? 0 : signum);
    1994                 :          2 : }
    1995                 :            : 
    1996                 :          1 : void init_handlers(char* url) {
    1997                 :          1 :     handler[CLIENT_MESSAGE_FATAL] = client_message_fatal,
    1998                 :            : 
    1999                 :          1 :     handler[CLIENT_COMMAND_USER_QUIT] = client_command_quit,
    2000                 :          1 :     handler[CLIENT_COMMAND_USER_REGISTER] = client_command_user_register,
    2001                 :          1 :     handler[CLIENT_COMMAND_USER_LOGIN] = client_command_user_login,
    2002                 :          1 :     handler[CLIENT_COMMAND_USER_LOGOUT] = client_command_user_logout,
    2003                 :            : 
    2004                 :          1 :     handler[CLIENT_COMMAND_FETCH_ALL_USERS] = client_command_fetch_all_users,
    2005                 :          1 :     handler[CLIENT_COMMAND_FETCH_ALL_FRIENDS] = client_command_fetch_all_friends,
    2006                 :            : 
    2007                 :          1 :     handler[CLIENT_COMMAND_LAUNCH_BATTLE] = client_command_launch_battle,
    2008                 :          1 :     handler[CLIENT_COMMAND_QUIT_BATTLE] = client_command_quit_battle,
    2009                 :          1 :     handler[CLIENT_COMMAND_ACCEPT_BATTLE] = client_command_accept_battle,
    2010                 :          1 :     handler[CLIENT_COMMAND_LAUNCH_FFA] = client_command_launch_ffa,
    2011                 :          1 :     handler[CLIENT_COMMAND_REJECT_BATTLE] = client_command_reject_battle,
    2012                 :          1 :     handler[CLIENT_COMMAND_INVITE_USER] = client_command_invite_user,
    2013                 :            : 
    2014                 :          1 :     handler[CLIENT_COMMAND_SEND_MESSAGE] = client_command_send_message,
    2015                 :            : 
    2016                 :          1 :     handler[CLIENT_COMMAND_MOVE_UP] = client_command_move_up,
    2017                 :          1 :     handler[CLIENT_COMMAND_MOVE_DOWN] = client_command_move_down,
    2018                 :          1 :     handler[CLIENT_COMMAND_MOVE_LEFT] = client_command_move_left,
    2019                 :          1 :     handler[CLIENT_COMMAND_MOVE_RIGHT] = client_command_move_right,
    2020                 :            : 
    2021                 :          1 :     handler[CLIENT_COMMAND_PUT_LANDMINE] = client_command_put_landmine,
    2022                 :            : 
    2023                 :          1 :     handler[CLIENT_COMMAND_MELEE] = client_command_melee,
    2024                 :            : 
    2025                 :          1 :     handler[CLIENT_COMMAND_FIRE_UP] = client_command_fire_up,
    2026                 :          1 :     handler[CLIENT_COMMAND_FIRE_DOWN] = client_command_fire_down,
    2027                 :          1 :     handler[CLIENT_COMMAND_FIRE_LEFT] = client_command_fire_left,
    2028                 :          1 :     handler[CLIENT_COMMAND_FIRE_RIGHT] = client_command_fire_right,
    2029                 :            : 
    2030                 :          1 :     handler[CLIENT_COMMAND_FIRE_UP_LEFT] = client_command_fire_up_left,
    2031                 :          1 :     handler[CLIENT_COMMAND_FIRE_UP_RIGHT] = client_command_fire_up_right,
    2032                 :          1 :     handler[CLIENT_COMMAND_FIRE_DOWN_LEFT] = client_command_fire_down_left,
    2033                 :          1 :     handler[CLIENT_COMMAND_FIRE_DOWN_RIGHT] = client_command_fire_down_right,
    2034                 :            : 
    2035                 :          1 :     handler[CLIENT_COMMAND_FIRE_AOE_UP] = client_command_fire_aoe_up,
    2036                 :          1 :     handler[CLIENT_COMMAND_FIRE_AOE_DOWN] = client_command_fire_aoe_down,
    2037                 :          1 :     handler[CLIENT_COMMAND_FIRE_AOE_LEFT] = client_command_fire_aoe_left,
    2038                 :          1 :     handler[CLIENT_COMMAND_FIRE_AOE_RIGHT] = client_command_fire_aoe_right;
    2039                 :            : 
    2040                 :          1 :     handler[CLIENT_COMMAND_ADMIN_CONTROL] = client_command_admin_control;
    2041                 :            : 
    2042                 :          1 : }
    2043                 :            : 
    2044                 :          1 : void init_constant() {
    2045                 :          1 :     item_s[ITEM_NONE] = (char*)"none";
    2046                 :          1 :     item_s[ITEM_MAGAZINE] = (char*)"magazine";
    2047                 :          1 :     item_s[ITEM_MAGMA] = (char*)"magma";
    2048                 :          1 :     item_s[ITEM_GRASS] = (char*)"grass";
    2049                 :          1 :     item_s[ITEM_BLOOD_VIAL] = (char*)"blood_vial";
    2050                 :          1 :     item_s[ITEM_END] = (char*)"end";
    2051                 :          1 :     item_s[ITEM_BULLET] = (char*)"bullet";
    2052                 :          1 :     item_s[ITEM_LANDMINE] = (char*)"landmine";
    2053                 :            : 
    2054                 :          1 :     dir_s[DIR_UP] = (char*)"up";
    2055                 :          1 :     dir_s[DIR_DOWN] = (char*)"down";
    2056                 :          1 :     dir_s[DIR_LEFT] = (char*)"left";
    2057                 :          1 :     dir_s[DIR_RIGHT] = (char*)"right";
    2058                 :          1 :     dir_s[DIR_UP_LEFT] = (char*)"up&left";
    2059                 :          1 :     dir_s[DIR_UP_RIGHT] = (char*)"up&right";
    2060                 :          1 :     dir_s[DIR_DOWN_LEFT] = (char*)"down&left";
    2061                 :          1 :     dir_s[DIR_DOWN_RIGHT] = (char*)"down&right";
    2062                 :            : 
    2063                 :          1 :     map_s[MAP_ITEM_NONE] = (char*)" ";
    2064                 :          1 :     map_s[MAP_ITEM_MAGAZINE] = (char*)"+";
    2065                 :          1 :     map_s[MAP_ITEM_MAGMA] = (char*)"X";
    2066                 :          1 :     map_s[MAP_ITEM_GRASS] = (char*)"\033[2;37m█\033[0m";
    2067                 :          1 :     map_s[MAP_ITEM_BLOOD_VIAL] = (char*)"*";
    2068                 :          1 :     map_s[MAP_ITEM_MY_BULLET] = (char*)".";
    2069                 :          1 :     map_s[MAP_ITEM_OTHER_BULLET] = (char*)".";
    2070                 :          1 :     map_s[MAP_ITEM_USER] = (char*)"A";
    2071                 :          1 :     map_s[MAP_ITEM_LANDMINE] = (char*)"o";
    2072                 :          1 :     map_s[MAP_ITEM_END] = (char*)" ";
    2073                 :            : 
    2074                 :          1 :     item_to_map[ITEM_NONE] = MAP_ITEM_NONE;
    2075                 :          1 :     item_to_map[ITEM_MAGAZINE] = MAP_ITEM_MAGAZINE;
    2076                 :          1 :     item_to_map[ITEM_MAGMA] = MAP_ITEM_MAGMA;
    2077                 :          1 :     item_to_map[ITEM_GRASS] = MAP_ITEM_GRASS;
    2078                 :          1 :     item_to_map[ITEM_BLOOD_VIAL] = MAP_ITEM_BLOOD_VIAL;
    2079                 :          1 :     item_to_map[ITEM_LANDMINE] = MAP_ITEM_LANDMINE;
    2080                 :          1 :     item_to_map[ITEM_END] = MAP_ITEM_END;
    2081                 :            : 
    2082                 :          1 :     signal_name_s[SIGHUP   ] = (char*)"SIGHUP";
    2083                 :          1 :     signal_name_s[SIGINT   ] = (char*)"SIGINT";
    2084                 :          1 :     signal_name_s[SIGQUIT  ] = (char*)"SIGQUIT";
    2085                 :          1 :     signal_name_s[SIGILL   ] = (char*)"SIGILL" ;
    2086                 :          1 :     signal_name_s[SIGABRT  ] = (char*)"SIGABRT";
    2087                 :          1 :     signal_name_s[SIGFPE   ] = (char*)"SIGFPE" ;
    2088                 :          1 :     signal_name_s[SIGKILL  ] = (char*)"SIGKILL";
    2089                 :          1 :     signal_name_s[SIGSEGV  ] = (char*)"SIGSEGV";
    2090                 :          1 :     signal_name_s[SIGPIPE  ] = (char*)"SIGPIPE";
    2091                 :          1 :     signal_name_s[SIGALRM  ] = (char*)"SIGALRM";
    2092                 :          1 :     signal_name_s[SIGTERM  ] = (char*)"SIGTERM";
    2093                 :          1 :     signal_name_s[SIGUSR1  ] = (char*)"SIGUSR1";
    2094                 :          1 :     signal_name_s[SIGUSR2  ] = (char*)"SIGUSR2";
    2095                 :          1 :     signal_name_s[SIGCHLD  ] = (char*)"SIGCHLD";
    2096                 :          1 :     signal_name_s[SIGCONT  ] = (char*)"SIGCONT";
    2097                 :          1 :     signal_name_s[SIGSTOP  ] = (char*)"SIGSTOP";
    2098                 :          1 :     signal_name_s[SIGTSTP  ] = (char*)"SIGTSTP";
    2099                 :          1 :     signal_name_s[SIGTTIN  ] = (char*)"SIGTTIN";
    2100                 :          1 :     signal_name_s[SIGTTOU  ] = (char*)"SIGTTOU";
    2101                 :          1 :     signal_name_s[SIGBUS   ] = (char*)"SIGBUS" ;
    2102                 :          1 :     signal_name_s[SIGPOLL  ] = (char*)"SIGPOLL";
    2103                 :          1 :     signal_name_s[SIGPROF  ] = (char*)"SIGPROF";
    2104                 :          1 :     signal_name_s[SIGSYS   ] = (char*)"SIGSYS" ;
    2105                 :          1 :     signal_name_s[SIGTRAP  ] = (char*)"SIGTRAP";
    2106                 :          1 :     signal_name_s[SIGURG   ] = (char*)"SIGURG" ;
    2107                 :          1 :     signal_name_s[SIGVTALRM] = (char*)"SIGVTALRM";
    2108                 :          1 :     signal_name_s[SIGXCPU  ] = (char*)"SIGXCPU";
    2109                 :          1 :     signal_name_s[SIGXFSZ  ] = (char*)"SIGXFSZ";
    2110                 :          1 :     color_s[0] = (char*)NONE;
    2111                 :          1 :     color_s[1] = (char*)L_GREEN;
    2112                 :          1 :     color_s[2] = (char*)L_RED;
    2113                 :          1 :     color_s[3] = (char*)YELLOW;
    2114                 :          1 :     color_s[4] = (char*)L_BLUE;
    2115                 :          1 :     color_s[5] = (char*)L_PURPLE;
    2116                 :          1 :     color_s[6] = (char*)L_CYAN;
    2117                 :          1 :     color_s[7] = (char*)(RED UNDERLINE);
    2118                 :          1 :     color_s[8] = (char*)(GREEN UNDERLINE);
    2119                 :          1 :     color_s[9] = (char*)(BROWN UNDERLINE);
    2120                 :          1 :     color_s[10] = (char*)(BLUE UNDERLINE);
    2121                 :          1 :     color_s[11] = (char*)(PURPLE UNDERLINE);
    2122                 :          1 :     color_s[12] = (char*)(CYAN UNDERLINE);
    2123                 :          1 :     color_s_size = 12;
    2124                 :          1 : }
    2125                 :            : /*
    2126                 :            : int main0(int argc, char* argv[]) {
    2127                 :            :     init_constants();
    2128                 :            :     init_handler();
    2129                 :            :     if (argc == 2) {
    2130                 :            :         port = atoi(argv[1]);
    2131                 :            :     }
    2132                 :            :     srand(time(NULL));
    2133                 :            : 
    2134                 :            :     pthread_t thread;
    2135                 :            : 
    2136                 :            :     if (signal(SIGINT, terminate_entrance) == SIG_ERR) {
    2137                 :            :         eprintf("an error occurred while setting a signal handler.");
    2138                 :            :     }
    2139                 :            :     if (signal(SIGSEGV, terminate_entrance) == SIG_ERR) {
    2140                 :            :         eprintf("an error occurred while setting a signal handler.");
    2141                 :            :     }
    2142                 :            :     if (signal(SIGABRT, terminate_entrance) == SIG_ERR) {
    2143                 :            :         eprintf("an error occurred while setting a signal handler.");
    2144                 :            :     }
    2145                 :            :     if (signal(SIGTERM, terminate_entrance) == SIG_ERR) {
    2146                 :            :         eprintf("an error occurred while setting a signal handler.");
    2147                 :            :     }
    2148                 :            :     if (signal(SIGTRAP, terminate_entrance) == SIG_ERR) {
    2149                 :            :         eprintf("an error occurred while setting a signal handler.");
    2150                 :            :     }
    2151                 :            : 
    2152                 :            :     for (int i = 0; i < USER_CNT; i++) {
    2153                 :            :         pthread_mutex_init(&items_lock[i], NULL);
    2154                 :            :     }
    2155                 :            :     log("server %s", version);
    2156                 :            :     if (sizeof(server_message_t) >= 1000)
    2157                 :            :         logw("message_size = %ldB", sizeof(server_message_t));
    2158                 :            : 
    2159                 :            :     server_fd = server_start();
    2160                 :            :     load_user_list();
    2161                 :            : 
    2162                 :            :     for (int i = 0; i < USER_CNT; i++)
    2163                 :            :         sessions[i].conn = -1;
    2164                 :            : 
    2165                 :            :     struct sockaddr_in client_addr;
    2166                 :            :     socklen_t length = sizeof(client_addr);
    2167                 :            :     while (1) {
    2168                 :            :         static session_args_t info;
    2169                 :            :         info.conn = accept(server_fd, (struct sockaddr*)&client_addr, &length);
    2170                 :            :         strncpy(info.ip_addr, inet_ntoa(client_addr.sin_addr), IPADDR_SIZE - 1);
    2171                 :            :         log("connected by %s:%d , conn:%d", info.ip_addr, client_addr.sin_port, info.conn);
    2172                 :            :         if (info.conn < 0) {
    2173                 :            :             loge("fail to accept client.");
    2174                 :            :         } else if (pthread_create(&thread, NULL, session_start, (void*)(uintptr_t)&info) != 0) {
    2175                 :            :             loge("fail to create thread.");
    2176                 :            :         }
    2177                 :            :         logi("bind thread #%lu", thread);
    2178                 :            :     }
    2179                 :            : 
    2180                 :            :     return 0;
    2181                 :            : }
    2182                 :            : */
    2183                 :            : 
    2184                 :          2 : int EightQueen(int n) {           //函数返回八皇后问题的解法个数
    2185         [ +  + ]:          2 :     int *p = new int[n];          //p[8]用来存储八皇后的位置,下标表示行号,数值表示列号
    2186                 :            :     //例如p[2]=3表示落在(2,3)这个点上,行号列号均为0~8
    2187                 :          1 :     memset(p, 0, n * sizeof(int));//初始化所有p[i]=0
    2188                 :          1 :     int k = 0;                    //k用来记录行号
    2189                 :          1 :     int count = 0;                //count用来记录解法个数,函数最终返回该值
    2190         [ +  + ]:       4022 :     while (k >= 0) {              //最后一次回溯k=-1跳出循环,从而找到全部解法
    2191         [ +  + ]:      17685 :         while (p[k] < n) {
    2192                 :            :             int i;
    2193         [ +  + ]:      48808 :             for (i = 0; i < k; i++)//找一下K行之前的几行有没有与p[k]在同一列或者同一对角线上
    2194         [ +  + ]:      46752 :                 if (p[i] == p[k] ||
    2195         [ +  + ]:      39556 :                 p[i] - p[k] == i - k ||
    2196         [ +  + ]:      36322 :                 p[i] - p[k] == k - i)
    2197                 :            :                     break;         //如果有,就跳出循环,此时i<k,否则i=k
    2198         [ +  + ]:      15720 :             if (i < k)p[k]++;      //p[k]不满足条件,p[k]++,再次进入循环与前几行对比,直至p[k]满足条件,此时p[0]到p[k]之间都满足条件了
    2199                 :       2056 :             else break;            //p[k]满足条件,跳出 while(p[k]<n) 循环
    2200                 :            :         }
    2201         [ +  + ]:       4021 :         if (p[k] < n) {            //如果p[k]<n,即合法的话,进入下面代码
    2202         [ +  + ]:       2056 :             if (k < n - 1)k++;     //如果还没到最后一行的话,就k++,进入下一行;如果k=7到了最后一行的话,就表明找到一组解,进入else开始输出
    2203                 :            :             else {                 //以下为打印函数,可以不看
    2204         [ +  + ]:        828 :                 for (int i = 0; i < n; i++) {//i为行号
    2205         [ +  + ]:       3312 :                     for (int j = 0; j < p[i]; j++)
    2206                 :       2576 :                         cout << "|--";        //输出此行皇后之前的格子
    2207                 :        736 :                     cout << "O";   //输出皇后O
    2208         [ +  + ]:       3312 :                     for (int j = 0; j < n - p[i] - 1; j++)
    2209                 :       2576 :                         cout << "--|";//输出此行皇后之后的格子
    2210                 :        736 :                     cout << endl;
    2211                 :            :                 }
    2212                 :         92 :                 cout << "……………………………" << endl;
    2213         [ +  + ]:        828 :                 for (int i = 0; i < n; i++)cout << p[i] + 1; cout << endl;//输出此组解法
    2214                 :         92 :                 cout << "……………………………" << endl;
    2215                 :         92 :                 count++;           //解法数加一
    2216                 :         92 :                 p[k]++;            //把p[7]++  重新开始找下一个解法
    2217                 :            :             }
    2218                 :            :         }
    2219                 :            :         else {                     //p[k]=8,此行找不到解,需要回溯,更改上一行的解法
    2220                 :       1965 :             p[k] = 0;              //重新初始化k行
    2221                 :       1965 :             k--;                   //回到上一行
    2222         [ +  + ]:       1965 :             if (k >= 0)p[k]++;     //如果还没到最后的解法,即如果不是0行找不到解的话,就可以开始回溯,将上一行的位置++
    2223                 :            :         }
    2224                 :            :     }
    2225                 :          1 :     return count;                  //函数返回count解法数量
    2226                 :            : }
    2227                 :            : 
    2228                 :            : 
    2229                 :            : int data[ 8 ][ 8 ]; //chess(double dimensional array)
    2230                 :            : int a[ 8 ];   //column(列)
    2231                 :            : int b[ 15 ];  //主对角线(左上至右下)
    2232                 :            : int c[ 15 ];  //从对角线(右上至左下)
    2233                 :            : int cnt = 0;
    2234                 :            : void eightQueens( int );
    2235                 :            : void output( const int [][ 8 ], int );
    2236                 :          1 : int EightQueen1()
    2237                 :            : {
    2238                 :            : 
    2239                 :            :     int i, j;
    2240                 :            : 
    2241         [ +  + ]:         16 :     for( i = 0; i < 15; ++i ) //主、从对角线
    2242                 :         15 :         b[ i ] = c[ i ] = 0; //表示安全
    2243                 :            : 
    2244         [ +  + ]:          9 :     for( i = 0; i < 8; ++i )//chess
    2245                 :            :     {
    2246                 :          8 :         a[ i ] = 0;    //i列安全
    2247         [ +  + ]:         72 :         for( j = 0; j < 8; ++j )
    2248                 :         64 :             data[ i ][ j ] = 0;
    2249                 :            :     }
    2250                 :            : 
    2251                 :          1 :     eightQueens( 0 );
    2252                 :            : 
    2253                 :          1 :     cout << "/ncount = " << cnt << endl;
    2254                 :          1 :     return 0;
    2255                 :            : }
    2256                 :            : 
    2257                 :       2057 : void eightQueens( int line )
    2258                 :            : {
    2259         [ +  + ]:       2057 :     if( 8 == line )//八个皇后安置就位,输出
    2260                 :            :     {
    2261                 :         92 :         output( data, 8 );
    2262                 :         92 :         cout << endl;
    2263                 :         92 :         return;
    2264                 :            :     }
    2265                 :            : 
    2266                 :            : 
    2267         [ +  + ]:      17685 :     for( int column = 0; column < 8; ++column )
    2268                 :            :     {
    2269   [ +  +  +  +  :      15720 :         if( 0 == a[ column ] && 0 == b[ line - column + 7 ] && 0 == c[ line + column ] )
                   +  + ]
    2270                 :            :         {
    2271                 :       2056 :             data[ line ][ column ] = 1; //安置皇后
    2272                 :       2056 :                     a[ column ] = 1;   //此列被占
    2273                 :       2056 :             b[ line - column + 7 ] = 1; //主对角线被占
    2274                 :       2056 :             c[ line + column ] = 1;  //从对角线被占
    2275                 :       2056 :             eightQueens( line + 1 ); //下一个皇后
    2276                 :            :             //重置
    2277                 :       2056 :             data[ line ][ column ] = 0;
    2278                 :       2056 :             a[ column ] = 0;
    2279                 :       2056 :             b[ line - column + 7 ] = 0;
    2280                 :       2056 :             c[ line + column ] = 0;
    2281                 :            :         }
    2282                 :            :     }
    2283                 :            : }
    2284                 :            : 
    2285                 :            : //output chess
    2286                 :         92 : void output( const int data[][ 8 ], int size )
    2287                 :            : {
    2288         [ +  + ]:        828 :     for( int i = 0; i < size; ++i )
    2289                 :            :     {
    2290         [ +  + ]:       6624 :         for( int j = 0; j < size; ++j )
    2291                 :       5888 :             cout << data[ i ][ j ] << ' ';
    2292                 :        736 :         cout << endl;
    2293                 :            :     }
    2294                 :         92 :     ++cnt;
    2295                 :         92 : }
    2296                 :            : 
    2297                 :            : namespace floyd_algorithm{
    2298                 :            : 
    2299                 :            : 
    2300                 :            : #include<stdio.h>
    2301                 :            : #include<malloc.h>
    2302                 :            : 
    2303                 :            : #define MAXV 7                                  //最大顶点个数
    2304                 :            : #define INF 32767                               //定义 ∞
    2305                 :            : //∞ == 32767 ,int 型的最大范围(2位)= 2^(2*8-1),TC告诉我们int占用2个字节,而VC和LGCC告诉我们int占用4个字节
    2306                 :            : //图:Graph
    2307                 :            : //顶点:Vertex
    2308                 :            : //邻接:Adjacency
    2309                 :            : //矩阵:Matrix
    2310                 :            : //表:List
    2311                 :            : //边:Edge
    2312                 :            : 
    2313                 :            : typedef struct vertex {
    2314                 :            :     int number;                                 //顶点的编号
    2315                 :            : }VertexType;                                    //别名,顶点的类型
    2316                 :            : 
    2317                 :            : typedef struct matrix {
    2318                 :            :     int n;                                              //顶点个数
    2319                 :            :     int e;                                              //边数
    2320                 :            :     int adjMat[MAXV][MAXV];             //邻接矩阵数组
    2321                 :            :     VertexType ver[MAXV];               //存放顶点信息
    2322                 :            : }MatGraph;                                              //别名,完整的图邻接矩阵类型
    2323                 :            : 
    2324                 :            : typedef struct eNode {
    2325                 :            :     int adjVer;                                 //该边的邻接点编号
    2326                 :            :     int weiLGht;                                //该边的的信息,如权值
    2327                 :            :     struct eNode* nextEdLGe;    //指向下一条边的指针
    2328                 :            : }EdgeNode;                                              //别名,边结点的类型
    2329                 :            : 
    2330                 :            : typedef struct vNode {
    2331                 :            :     EdgeNode* firstEdLGe;               //指向第一个边结点
    2332                 :            : }VNode;                                                 //别名,邻接表的头结点类型
    2333                 :            : 
    2334                 :            : typedef struct list {
    2335                 :            :     int n;                                              //顶点个数
    2336                 :            :     int e;                                              //边数
    2337                 :            :     VNode adjList[MAXV];                //邻接表的头结点数组
    2338                 :            : }ListGraph;                                             //别名,完整的图邻接表类型
    2339                 :            : 
    2340                 :            : //创建图的邻接表
    2341                 :          2 : void createAdjListGraph(ListGraph*& LG, int A[MAXV][MAXV], int n, int e) {
    2342                 :            :     int i, j;
    2343                 :            :     EdgeNode* p;
    2344                 :          2 :     LG = (ListGraph*)malloc(sizeof(ListGraph));
    2345         [ +  + ]:         16 :     for (i = 0; i < n; i++) {
    2346                 :         14 :         LG->adjList[i].firstEdLGe = NULL;                                            //给邻接表中所有头结点指针域置初值
    2347                 :            :     }
    2348         [ +  + ]:         16 :     for (i = 0; i < n; i++) {                                                                        //检查邻接矩阵中的每个元素
    2349         [ +  + ]:        112 :         for (j = n - 1; j >= 0; j--) {
    2350         [ +  + ]:         98 :             if (A[i][j] != 0) {                                                                 //存在一条边
    2351                 :         84 :                 p = (EdgeNode*)malloc(sizeof(EdgeNode));                //申请一个结点内存
    2352                 :         84 :                 p->adjVer = j;                                                                       //存放邻接点
    2353                 :         84 :                 p->weiLGht = A[i][j];                                                        //存放权值
    2354                 :         84 :                 p->nextEdLGe = NULL;
    2355                 :            : 
    2356                 :         84 :                 p->nextEdLGe = LG->adjList[i].firstEdLGe;         //头插法
    2357                 :         84 :                 LG->adjList[i].firstEdLGe = p;
    2358                 :            :             }
    2359                 :            :         }
    2360                 :            :     }
    2361                 :          2 :     LG->n = n;
    2362                 :          2 :     LG->e = e;
    2363                 :          2 : }
    2364                 :            : 
    2365                 :            : //输出邻接表
    2366                 :          1 : void displayAdjList(ListGraph* LG) {
    2367                 :            :     int i;
    2368                 :            :     EdgeNode* p;
    2369         [ +  + ]:          8 :     for (i = 0; i < MAXV; i++) {
    2370                 :          7 :         p = LG->adjList[i].firstEdLGe;
    2371                 :          7 :         printf("%d:", i);
    2372         [ +  + ]:         49 :         while (p != NULL) {
    2373         [ +  + ]:         42 :             if (p->weiLGht != 32767) {
    2374                 :         12 :                 printf("%2d[%d]->", p->adjVer, p->weiLGht);
    2375                 :            :             }
    2376                 :         42 :             p = p->nextEdLGe;
    2377                 :            :         }
    2378                 :          7 :         printf(" NULL\n");
    2379                 :            :     }
    2380                 :          1 : }
    2381                 :            : 
    2382                 :            : //输出邻接矩阵
    2383                 :          1 : void displayAdjMat(MatGraph MG) {
    2384                 :            :     int i, j;
    2385         [ +  + ]:          8 :     for (i = 0; i < MAXV; i++) {
    2386         [ +  + ]:         56 :         for (j = 0; j < MAXV; j++) {
    2387         [ +  + ]:         49 :             if (MG.adjMat[i][j] == 0) {
    2388                 :          7 :                 printf("%4s", "0");
    2389                 :            :             }
    2390         [ +  + ]:         42 :             else if (MG.adjMat[i][j] == 32767) {
    2391                 :         30 :                 printf("%4s", "∞");
    2392                 :            :             }
    2393                 :            :             else {
    2394                 :         12 :                 printf("%4d", MG.adjMat[i][j]);
    2395                 :            :             }
    2396                 :            :         }
    2397                 :          7 :         printf("\n");
    2398                 :            :     }
    2399                 :          1 : }
    2400                 :            : 
    2401                 :            : //邻接表转换为邻接矩阵
    2402                 :          2 : void ListToMat(ListGraph* LG, MatGraph& MG) {
    2403                 :            :     int i, j;
    2404                 :            :     EdgeNode* p;
    2405         [ +  + ]:         16 :     for (i = 0; i < MAXV; i++) {
    2406         [ +  + ]:        112 :         for (j = 0; j < MAXV; j++) {
    2407                 :         98 :             MG.adjMat[i][j] = 0;
    2408                 :            :         }
    2409                 :            :     }
    2410         [ +  + ]:         16 :     for (i = 0; i < LG->n; i++) {
    2411                 :         14 :         p = LG->adjList[i].firstEdLGe;
    2412         [ +  + ]:         98 :         while (p != NULL) {
    2413                 :         84 :             MG.adjMat[i][p->adjVer] = p->weiLGht;
    2414                 :         84 :             p = p->nextEdLGe;
    2415                 :            :         }
    2416                 :            :     }
    2417                 :          2 :     MG.n = LG->n;
    2418                 :          2 :     MG.e = LG->e;
    2419                 :          2 : }
    2420                 :            : 
    2421                 :            : //输出多源最短路径
    2422                 :          2 : void displayPath(MatGraph MG, int A[MAXV][MAXV], int path[MAXV][MAXV]) {
    2423                 :            :     int i, j, k;
    2424                 :            :     int s;
    2425                 :            :     int aPath[MAXV];                                                                            //存放一条最短路径(逆向)
    2426                 :            :     int d;                                                                                                      //顶点个数
    2427         [ +  + ]:         16 :     for (i = 0; i < MG.n; i++) {
    2428         [ +  + ]:        112 :         for (j = 0; j < MG.n; j++) {
    2429   [ +  +  +  + ]:         98 :             if (A[i][j] != INF && i != j) {                                     //若顶点 i 和 顶点 j 之间存在路径
    2430                 :            :                 //printf("从 %d 到 %d 的路径为:", i, j);
    2431                 :         40 :                 k = path[i][j];
    2432                 :         40 :                 d = 0;
    2433                 :         40 :                 aPath[d] = j;                                                           //路径上添加终点
    2434                 :         46 :                 while (//k != -1 &&
    2435         [ +  + ]:         86 :                 k != i) {                                       //路劲上添加中间点
    2436                 :         46 :                     d++;
    2437                 :         46 :                     aPath[d] = k;
    2438                 :         46 :                     k = path[i][k];
    2439                 :            :                 }
    2440                 :         40 :                 d++;
    2441                 :         40 :                 aPath[d] = i;                                                           //路径上添加起点
    2442                 :            :                 //printf("%d", aPath[d]);                                             //输出起点
    2443         [ +  + ]:        126 :                 for (s = d - 1; s >= 0; s--) {                               //输出路径上其他顶点
    2444                 :            :                     //printf("->%d", aPath[s]);
    2445                 :            :                 }
    2446                 :            :                 //printf("\t\t");
    2447                 :            :                 //printf("路径长度为:%d\n", A[i][j]);
    2448                 :            :             }
    2449                 :            :         }
    2450                 :            :     }
    2451                 :          2 : }
    2452                 :            : 
    2453                 :            : //Floyd算法
    2454                 :          2 : void Floyd(MatGraph MG) {
    2455                 :            :     int i, j, k;
    2456                 :            :     int A[MAXV][MAXV];
    2457                 :            :     int path[MAXV][MAXV];
    2458         [ +  + ]:         16 :     for (i = 0; i < MG.n; i++) {
    2459         [ +  + ]:        112 :         for (j = 0; j < MG.n; j++) {
    2460                 :         98 :             A[i][j] = MG.adjMat[i][j];
    2461   [ +  +  +  + ]:         98 :             if (i != j && MG.adjMat[i][j] < INF) {
    2462                 :         24 :                 path[i][j] = i;                                                 //顶点 i 到顶点 j 有边时
    2463                 :            :             }
    2464                 :            :             else {
    2465                 :         74 :                 path[i][j] = -1;                                                //顶点 i 到顶点 j 无边时
    2466                 :            :             }
    2467                 :            :         }
    2468                 :            :     }
    2469         [ +  + ]:         16 :     for (k = 0; k < MG.n; k++) {                                             //一次考察所有顶点
    2470         [ +  + ]:        112 :         for (i = 0; i < MG.n; i++) {
    2471         [ +  + ]:        784 :             for (j = 0; j < MG.n; j++) {
    2472         [ +  + ]:        686 :                 if (A[i][j] > A[i][k] + A[k][j]) {
    2473                 :         36 :                     A[i][j] = A[i][k] + A[k][j];                //修改最短路径长度
    2474                 :         36 :                     path[i][j] = path[k][j];                    //修改最短路径
    2475                 :            :                 }
    2476                 :            :             }
    2477                 :            :         }
    2478                 :            :     }
    2479                 :          2 :     displayPath(MG, A, path);                                                   //输出最短路径
    2480                 :          2 : }
    2481                 :            : 
    2482                 :          1 : int floyd() {
    2483                 :            :     ListGraph* LG;
    2484                 :            :     MatGraph MG;
    2485                 :            : 
    2486                 :          1 :     int array[MAXV][MAXV] = {
    2487                 :            :             {  0,  4,  6,  6,INF,INF,INF},
    2488                 :            :             {INF,  0,  1,INF,  7,INF,INF},
    2489                 :            :             {INF,INF,  0,INF,  6,  4,INF},
    2490                 :            :             {INF,INF,  2,  0,INF,  5,INF},
    2491                 :            :             {INF,INF,INF,INF,  0,INF,  6},
    2492                 :            :             {INF,INF,INF,INF,  1,  0,  8},
    2493                 :            :             {INF,INF,INF,INF,INF,INF,  0}
    2494                 :            :     };
    2495                 :            : 
    2496                 :          1 :     int e = 12;
    2497                 :          1 :     createAdjListGraph(LG, array, MAXV, e);
    2498                 :            :     //displayAdjList(LG);
    2499                 :            :     //printf("\n");
    2500                 :            : 
    2501                 :          1 :     ListToMat(LG, MG);
    2502                 :            :     //displayAdjMat(MG);
    2503                 :            :     //printf("\n");
    2504                 :            : 
    2505                 :          1 :     Floyd(MG);
    2506                 :            :     //printf("\n");
    2507                 :            : 
    2508                 :          1 :     return 0;
    2509                 :            : }
    2510                 :            : 
    2511                 :            : }
    2512                 :            : 
    2513                 :            : namespace __floyd{
    2514                 :            : 
    2515                 :            : 
    2516                 :            : #include<stdio.h>
    2517                 :            : #include<malloc.h>
    2518                 :            : 
    2519                 :            : #define MAXV 7                                  //最大顶点个数
    2520                 :            : #define INF 32767                               //定义 ∞
    2521                 :            : //∞ == 32767 ,int 型的最大范围(2位)= 2^(2*8-1),TC告诉我们int占用2个字节,而VC和LGCC告诉我们int占用4个字节
    2522                 :            : //图:Graph
    2523                 :            : //顶点:Vertex
    2524                 :            : //邻接:Adjacency
    2525                 :            : //矩阵:Matrix
    2526                 :            : //表:List
    2527                 :            : //边:Edge
    2528                 :            : 
    2529                 :            :     typedef struct vertex {
    2530                 :            :         int number;                                     //顶点的编号
    2531                 :            :     }VertexType;                                        //别名,顶点的类型
    2532                 :            : 
    2533                 :            :     typedef struct matrix {
    2534                 :            :         int n;                                          //顶点个数
    2535                 :            :         int e;                                          //边数
    2536                 :            :         int adjMat[MAXV][MAXV];         //邻接矩阵数组
    2537                 :            :         VertexType ver[MAXV];           //存放顶点信息
    2538                 :            :     }MatGraph;                                          //别名,完整的图邻接矩阵类型
    2539                 :            : 
    2540                 :            :     typedef struct eNode {
    2541                 :            :         int adjVer;                                     //该边的邻接点编号
    2542                 :            :         int weiLGht;                            //该边的的信息,如权值
    2543                 :            :         struct eNode* nextEdLGe;        //指向下一条边的指针
    2544                 :            :     }EdgeNode;                                          //别名,边结点的类型
    2545                 :            : 
    2546                 :            :     typedef struct vNode {
    2547                 :            :         EdgeNode* firstEdLGe;           //指向第一个边结点
    2548                 :            :     }VNode;                                             //别名,邻接表的头结点类型
    2549                 :            : 
    2550                 :            :     typedef struct list {
    2551                 :            :         int n;                                          //顶点个数
    2552                 :            :         int e;                                          //边数
    2553                 :            :         VNode adjList[MAXV];            //邻接表的头结点数组
    2554                 :            :     }ListGraph;                                         //别名,完整的图邻接表类型
    2555                 :            : 
    2556                 :            : //创建图的邻接表
    2557                 :          2 :     void createAdjListGraph(ListGraph*& LG, int A[MAXV][MAXV], int n, int e) {
    2558                 :            :         int i, j;
    2559                 :            :         EdgeNode* p;
    2560                 :          2 :         LG = (ListGraph*)malloc(sizeof(ListGraph));
    2561         [ +  + ]:         16 :         for (i = 0; i < n; i++) {
    2562                 :         14 :             LG->adjList[i].firstEdLGe = NULL;                                                //给邻接表中所有头结点指针域置初值
    2563                 :            :         }
    2564         [ +  + ]:         16 :         for (i = 0; i < n; i++) {                                                                    //检查邻接矩阵中的每个元素
    2565         [ +  + ]:        112 :             for (j = n - 1; j >= 0; j--) {
    2566         [ +  + ]:         98 :                 if (A[i][j] != 0) {                                                                     //存在一条边
    2567                 :         84 :                     p = (EdgeNode*)malloc(sizeof(EdgeNode));            //申请一个结点内存
    2568                 :         84 :                     p->adjVer = j;                                                                   //存放邻接点
    2569                 :         84 :                     p->weiLGht = A[i][j];                                                    //存放权值
    2570                 :         84 :                     p->nextEdLGe = NULL;
    2571                 :            : 
    2572                 :         84 :                     p->nextEdLGe = LG->adjList[i].firstEdLGe;             //头插法
    2573                 :         84 :                     LG->adjList[i].firstEdLGe = p;
    2574                 :            :                 }
    2575                 :            :             }
    2576                 :            :         }
    2577                 :          2 :         LG->n = n;
    2578                 :          2 :         LG->e = e;
    2579                 :          2 :     }
    2580                 :            : 
    2581                 :            : //输出邻接表
    2582                 :          1 :     void displayAdjList(ListGraph* LG) {
    2583                 :            :         int i;
    2584                 :            :         EdgeNode* p;
    2585         [ +  + ]:          8 :         for (i = 0; i < MAXV; i++) {
    2586                 :          7 :             p = LG->adjList[i].firstEdLGe;
    2587                 :          7 :             printf("%d:", i);
    2588         [ +  + ]:         49 :             while (p != NULL) {
    2589         [ +  + ]:         42 :                 if (p->weiLGht != 32767) {
    2590                 :         12 :                     printf("%2d[%d]->", p->adjVer, p->weiLGht);
    2591                 :            :                 }
    2592                 :         42 :                 p = p->nextEdLGe;
    2593                 :            :             }
    2594                 :          7 :             printf(" NULL\n");
    2595                 :            :         }
    2596                 :          1 :     }
    2597                 :            : 
    2598                 :            : //输出邻接矩阵
    2599                 :          1 :     void displayAdjMat(MatGraph MG) {
    2600                 :            :         int i, j;
    2601         [ +  + ]:          8 :         for (i = 0; i < MAXV; i++) {
    2602         [ +  + ]:         56 :             for (j = 0; j < MAXV; j++) {
    2603         [ +  + ]:         49 :                 if (MG.adjMat[i][j] == 0) {
    2604                 :          7 :                     printf("%4s", "0");
    2605                 :            :                 }
    2606         [ +  + ]:         42 :                 else if (MG.adjMat[i][j] == 32767) {
    2607                 :         30 :                     printf("%4s", "∞");
    2608                 :            :                 }
    2609                 :            :                 else {
    2610                 :         12 :                     printf("%4d", MG.adjMat[i][j]);
    2611                 :            :                 }
    2612                 :            :             }
    2613                 :          7 :             printf("\n");
    2614                 :            :         }
    2615                 :          1 :     }
    2616                 :            : 
    2617                 :            : //邻接表转换为邻接矩阵
    2618                 :          2 :     void ListToMat(ListGraph* LG, MatGraph& MG) {
    2619                 :            :         int i, j;
    2620                 :            :         EdgeNode* p;
    2621         [ +  + ]:         16 :         for (i = 0; i < MAXV; i++) {
    2622         [ +  + ]:        112 :             for (j = 0; j < MAXV; j++) {
    2623                 :         98 :                 MG.adjMat[i][j] = 0;
    2624                 :            :             }
    2625                 :            :         }
    2626         [ +  + ]:         16 :         for (i = 0; i < LG->n; i++) {
    2627                 :         14 :             p = LG->adjList[i].firstEdLGe;
    2628         [ +  + ]:         98 :             while (p != NULL) {
    2629                 :         84 :                 MG.adjMat[i][p->adjVer] = p->weiLGht;
    2630                 :         84 :                 p = p->nextEdLGe;
    2631                 :            :             }
    2632                 :            :         }
    2633                 :          2 :         MG.n = LG->n;
    2634                 :          2 :         MG.e = LG->e;
    2635                 :          2 :     }
    2636                 :            : 
    2637                 :            : //输出多源最短路径
    2638                 :          2 :     void displayPath(MatGraph MG, int A[MAXV][MAXV], int path[MAXV][MAXV]) {
    2639                 :            :         int i, j, k;
    2640                 :            :         int s;
    2641                 :            :         int aPath[MAXV];                                                                                //存放一条最短路径(逆向)
    2642                 :            :         int d;                                                                                                  //顶点个数
    2643         [ +  + ]:         16 :         for (i = 0; i < MG.n; i++) {
    2644         [ +  + ]:        112 :             for (j = 0; j < MG.n; j++) {
    2645         [ +  + ]:         98 :                 if (A[i][j] != INF
    2646         [ +  + ]:         54 :                 && i != j) {                                    //若顶点 i 和 顶点 j 之间存在路径
    2647                 :            :                     //printf("从 %d 到 %d 的路径为:", i, j);
    2648                 :         40 :                     k = path[i][j];
    2649                 :         40 :                     d = 0;
    2650                 :         40 :                     aPath[d] = j;                                                               //路径上添加终点
    2651                 :         46 :                     while (//k != -1 &&
    2652         [ +  + ]:         86 :                             k != i) {                                   //路劲上添加中间点
    2653                 :         46 :                         d++;
    2654                 :         46 :                         aPath[d] = k;
    2655                 :         46 :                         k = path[i][k];
    2656                 :            :                     }
    2657                 :         40 :                     d++;
    2658                 :         40 :                     aPath[d] = i;                                                               //路径上添加起点
    2659                 :            :                     //printf("%d", aPath[d]);                                         //输出起点
    2660         [ +  + ]:        126 :                     for (s = d - 1; s >= 0; s--) {                           //输出路径上其他顶点
    2661                 :            :                         //printf("->%d", aPath[s]);
    2662                 :            :                     }
    2663                 :            :                     //printf("\t\t");
    2664                 :            :                     //printf("路径长度为:%d\n", A[i][j]);
    2665                 :            :                 }
    2666                 :            :             }
    2667                 :            :         }
    2668                 :          2 :     }
    2669                 :            : 
    2670                 :            : //Floyd算法
    2671                 :          2 :     void Floyd(MatGraph MG) {
    2672                 :            :         int i, j, k;
    2673                 :            :         int A[MAXV][MAXV];
    2674                 :            :         int path[MAXV][MAXV];
    2675         [ +  + ]:         16 :         for (i = 0; i < MG.n; i++) {
    2676         [ +  + ]:        112 :             for (j = 0; j < MG.n; j++) {
    2677                 :         98 :                 A[i][j] = MG.adjMat[i][j];
    2678         [ +  + ]:         98 :                 if (i != j &&
    2679         [ +  + ]:         84 :                 MG.adjMat[i][j] < INF) {
    2680                 :         24 :                     path[i][j] = i;                                                     //顶点 i 到顶点 j 有边时
    2681                 :            :                 }
    2682                 :            :                 else {
    2683                 :         74 :                     path[i][j] = -1;                                            //顶点 i 到顶点 j 无边时
    2684                 :            :                 }
    2685                 :            :             }
    2686                 :            :         }
    2687         [ +  + ]:         16 :         for (k = 0; k < MG.n; k++) {                                         //一次考察所有顶点
    2688         [ +  + ]:        112 :             for (i = 0; i < MG.n; i++) {
    2689         [ +  + ]:        784 :                 for (j = 0; j < MG.n; j++) {
    2690         [ +  + ]:        686 :                     if (A[i][j] > A[i][k] + A[k][j]) {
    2691                 :         36 :                         A[i][j] = A[i][k] + A[k][j];            //修改最短路径长度
    2692                 :         36 :                         path[i][j] = path[k][j];                        //修改最短路径
    2693                 :            :                     }
    2694                 :            :                 }
    2695                 :            :             }
    2696                 :            :         }
    2697                 :          2 :         displayPath(MG, A, path);                                                       //输出最短路径
    2698                 :          2 :     }
    2699                 :            : 
    2700                 :          1 :     int floyd() {
    2701                 :            :         ListGraph* LG;
    2702                 :            :         MatGraph MG;
    2703                 :            : 
    2704                 :          1 :         int array[MAXV][MAXV] = {
    2705                 :            :                 {  0,  4,  6,  6,INF,INF,INF},
    2706                 :            :                 {INF,  0,  1,INF,  7,INF,INF},
    2707                 :            :                 {INF,INF,  0,INF,  6,  4,INF},
    2708                 :            :                 {INF,INF,  2,  0,INF,  5,INF},
    2709                 :            :                 {INF,INF,INF,INF,  0,INF,  6},
    2710                 :            :                 {INF,INF,INF,INF,  1,  0,  8},
    2711                 :            :                 {INF,INF,INF,INF,INF,INF,  0}
    2712                 :            :         };
    2713                 :            : 
    2714                 :          1 :         int e = 12;
    2715                 :          1 :         createAdjListGraph(LG, array, MAXV, e);
    2716                 :            :         //displayAdjList(LG);
    2717                 :            :         //printf("\n");
    2718                 :            : 
    2719                 :          1 :         ListToMat(LG, MG);
    2720                 :            :         //displayAdjMat(MG);
    2721                 :            :         //printf("\n");
    2722                 :            : 
    2723                 :          1 :         Floyd(MG);
    2724                 :            :         //printf("\n");
    2725                 :            : 
    2726                 :          1 :         return 0;
    2727                 :            :     }
    2728                 :            : 
    2729                 :            : }
    2730                 :            : 
    2731                 :            : namespace Queue{
    2732                 :            :     int data[ 8 ][ 8 ]; //chess(double dimensional array)
    2733                 :            :     int a[ 8 ];   //column(列)
    2734                 :            :     int b[ 15 ];  //主对角线(左上至右下)
    2735                 :            :     int c[ 15 ];  //从对角线(右上至左下)
    2736                 :            :     int cnt = 0;
    2737                 :            :     void eightQueens( int );
    2738                 :            :     void output( const int [][ 8 ], int );
    2739                 :          1 :     int EightQueen1()
    2740                 :            :     {
    2741                 :            : 
    2742                 :            :         int i, j;
    2743                 :            : 
    2744         [ +  + ]:         16 :         for( i = 0; i < 15; ++i ) //主、从对角线
    2745                 :         15 :             b[ i ] = c[ i ] = 0; //表示安全
    2746                 :            : 
    2747         [ +  + ]:          9 :         for( i = 0; i < 8; ++i )//chess
    2748                 :            :         {
    2749                 :          8 :             a[ i ] = 0;    //i列安全
    2750         [ +  + ]:         72 :             for( j = 0; j < 8; ++j )
    2751                 :         64 :                 data[ i ][ j ] = 0;
    2752                 :            :         }
    2753                 :            : 
    2754                 :          1 :         eightQueens( 0 );
    2755                 :            : 
    2756                 :          1 :         cout << "/ncount = " << cnt << endl;
    2757                 :          1 :         return 0;
    2758                 :            :     }
    2759                 :            : 
    2760                 :       2057 :     void eightQueens( int line )
    2761                 :            :     {
    2762         [ +  + ]:       2057 :         if( 8 == line )//八个皇后安置就位,输出
    2763                 :            :         {
    2764                 :         92 :             output( data, 8 );
    2765                 :         92 :             cout << endl;
    2766                 :         92 :             return;
    2767                 :            :         }
    2768                 :            : 
    2769                 :            : 
    2770         [ +  + ]:      17685 :         for( int column = 0; column < 8; ++column )
    2771                 :            :         {
    2772   [ +  +  +  +  :      15720 :             if( 0 == a[ column ] && 0 == b[ line - column + 7 ] && 0 == c[ line + column ] )
                   +  + ]
    2773                 :            :             {
    2774                 :       2056 :                 data[ line ][ column ] = 1; //安置皇后
    2775                 :       2056 :                 a[ column ] = 1;   //此列被占
    2776                 :       2056 :                 b[ line - column + 7 ] = 1; //主对角线被占
    2777                 :       2056 :                 c[ line + column ] = 1;  //从对角线被占
    2778                 :       2056 :                 eightQueens( line + 1 ); //下一个皇后
    2779                 :            :                 //重置
    2780                 :       2056 :                 data[ line ][ column ] = 0;
    2781                 :       2056 :                 a[ column ] = 0;
    2782                 :       2056 :                 b[ line - column + 7 ] = 0;
    2783                 :       2056 :                 c[ line + column ] = 0;
    2784                 :            :             }
    2785                 :            :         }
    2786                 :            :     }
    2787                 :            : 
    2788                 :            : //output chess
    2789                 :         92 :     void output( const int data[][ 8 ], int size )
    2790                 :            :     {
    2791         [ +  + ]:        828 :         for( int i = 0; i < size; ++i )
    2792                 :            :         {
    2793         [ +  + ]:       6624 :             for( int j = 0; j < size; ++j )
    2794                 :       5888 :                 cout << data[ i ][ j ] << ' ';
    2795                 :        736 :             cout << endl;
    2796                 :            :         }
    2797                 :         92 :         ++cnt;
    2798                 :         92 :     }
    2799                 :            : }

Generated by: LCOV version 1.14