# LCOV - test.info - terminal-stg/server.cpp

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