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 : : }
|