game_server.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. #define _GNU_SOURCE
  2. #include "game_server.h"
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <signal.h>
  8. #include <ctype.h>
  9. #include "utils.h"
  10. //#include "users.c"
  11. #include "boggle4/dictionary.c"
  12. #include "boggle4/words.c"
  13. Player *player_list = NULL;
  14. Client *client_list = NULL;
  15. int round_num =0 ;
  16. int score;
  17. int word_score;
  18. int old_score;
  19. int skip=0;
  20. Client special_client;
  21. short port = -1;
  22. int in_newgame = 0;
  23. int action;
  24. char input[17];
  25. struct sigaction newact;
  26. char dice[16][6] = {
  27. {'R', 'I', 'F', 'O', 'B', 'X'},
  28. {'I', 'F', 'E', 'H', 'E', 'Y'},
  29. {'D', 'E', 'N', 'O', 'W', 'S'},
  30. {'U', 'T', 'O', 'K', 'N', 'D'},
  31. {'H', 'M', 'S', 'R', 'A', 'O'},
  32. {'L', 'U', 'P', 'E', 'T', 'S'},
  33. {'A', 'C', 'I', 'T', 'O', 'A'},
  34. {'Y', 'L', 'G', 'K', 'U', 'E'},
  35. {'Q', 'B', 'M', 'J', 'O', 'A'},
  36. {'E', 'H', 'I', 'S', 'P', 'N'},
  37. {'V', 'E', 'T', 'I', 'G', 'N'},
  38. {'B', 'A', 'L', 'I', 'Y', 'T'},
  39. {'E', 'Z', 'A', 'V', 'N', 'D'},
  40. {'R', 'A', 'L', 'E', 'S', 'C'},
  41. {'U', 'W', 'I', 'L', 'R', 'G'},
  42. {'P', 'A', 'C', 'E', 'M', 'D'}
  43. };
  44. char* actions[2] = {"quit", "logout"};
  45. char* messages[7] = {"Too Short", "Already Found", "Not on Board", "Not a Word", "Welcome to Boggle", "Hello Again", "New Round"};
  46. int listenfd;
  47. int board[16];
  48. void swap(int* i, int* j) {
  49. int temp = *i;
  50. *i = *j;
  51. *j = temp;
  52. }
  53. void generate_board() {
  54. srand(time(0));
  55. int order[16];
  56. int i;
  57. for (i = 0; i < 16; i++) {
  58. order[i] = i;
  59. }
  60. for (i = 0; i < 16; i++) {
  61. swap(order + i, order + (rand() % (16-i)) + i);
  62. }
  63. for (i = 0; i < 16; i++) {
  64. board[i] = dice[order[i]][rand() % 6];
  65. }
  66. }
  67. void refresh_screen(int score, int bonus, char* prev, Client * p) {
  68. char mes[256];
  69. sprintf(mes, "Round %d\n", round_num);
  70. sendclient(p, mes);
  71. for (int i = 0; i < 4; ++i) {
  72. for (int j = 0; j < 4; ++j) {
  73. char arr[3];
  74. arr[0] = (char)board[i*4+j];
  75. arr[1] = ' ';
  76. arr[2] = '\0';
  77. sendclient(p, arr);
  78. }
  79. sendclient(p, "\n");
  80. }
  81. sprintf(mes, "Score: %d\n", score);
  82. sendclient(p, mes);
  83. if (bonus > 0) {
  84. sprintf(mes, "Last Word: %s (%d points)\n", prev, bonus);
  85. sendclient(p, mes);
  86. }
  87. else {
  88. sprintf(mes, "%s\n", messages[0-bonus]);
  89. sendclient(p, mes);
  90. }
  91. }
  92. void get_info(struct client * p, char * mess){
  93. char *after = p->buf + p->inbuf;
  94. int room = BUFFER_SIZE - p->inbuf;
  95. int nbytes;
  96. if ((nbytes = read(p->fd, after, room)) > 0) {
  97. p->inbuf += nbytes;
  98. int where = find_network_newline(p->buf, p->inbuf);
  99. if (where >= 0) {
  100. p->buf[where] = '\0';
  101. p->buf[where+1] = '\0';
  102. strcpy(mess, p->buf);
  103. where+=2;
  104. p->inbuf -= where;
  105. memmove(p->buf, p->buf + where, p->inbuf);
  106. }
  107. room = sizeof(p->buf) - p->inbuf;
  108. after = p->buf + p->inbuf;
  109. } else {
  110. remove_client(p->fd);
  111. }
  112. }
  113. void handler(int code) {
  114. if (code == SIGALRM) {
  115. }
  116. else if (code == SIGINT) {
  117. scoreboard();
  118. sendclient(&special_client, "Game Over\n");
  119. write_users();
  120. free_dictionaries();
  121. free_players();
  122. exit(0);
  123. }
  124. }
  125. void start_game(Client * p){
  126. score = 0;
  127. old_score = 0;
  128. skip = 0;
  129. round_num++;
  130. reset_words();
  131. generate_board();
  132. if (word_score > -4) {
  133. word_score = -6;
  134. }
  135. refresh_screen(score, word_score, NULL, &special_client);
  136. if (skip) {
  137. word_score = verify_word(input);
  138. if (word_score > 0) {
  139. score += word_score;
  140. }
  141. refresh_screen(score, word_score, input, p);
  142. }
  143. else
  144. {
  145. skip = 1;
  146. }
  147. if (!(strcmp(input, "q") && strcmp(input, "u"))) {
  148. if (input[0] == 'q') {
  149. action = 0;
  150. }
  151. else {
  152. action = 1;
  153. }
  154. update_scores(score, old_score);
  155. scoreboard();
  156. char mes[256];
  157. sprintf(mes, "Type y to confirm %s. Type anything else to cancel\n", actions[action]);
  158. sendclient(p, mes);
  159. get_info(p, input);
  160. if (input[0] == 'y') {
  161. }
  162. else {
  163. old_score = score;
  164. }
  165. }
  166. }
  167. void check_word(Client * p, char * input){
  168. if (skip) {
  169. word_score = verify_word(input);
  170. if (word_score > 0) {
  171. score += word_score;
  172. }
  173. refresh_screen(score, word_score, input, p);
  174. }
  175. else
  176. {
  177. skip = 1;
  178. }
  179. if (!(strcmp(input, "q") && strcmp(input, "u"))) {
  180. if (input[0] == 'q') {
  181. action = 0;
  182. }
  183. else {
  184. action = 1;
  185. }
  186. update_scores(score, old_score);
  187. scoreboard();
  188. char mes[256];
  189. sprintf(mes, "Type y to confirm %s. Type anything else to cancel\n", actions[action]);
  190. sendclient(p, mes);
  191. get_info(p, input);
  192. if (input[0] == 'y') {
  193. }
  194. else {
  195. old_score = score;
  196. }
  197. }
  198. }
  199. void game(Client * p){
  200. while (1) {
  201. score = 0;
  202. old_score = 0;
  203. strcpy(input, "a");
  204. raise(SIGALRM);
  205. skip = 1;
  206. while (1) {
  207. get_info(p, input);
  208. sendclient(p, p->buf);
  209. if (skip) {
  210. word_score = verify_word(input);
  211. if (word_score > 0) {
  212. score += word_score;
  213. }
  214. refresh_screen(score, word_score, input, p);
  215. }
  216. else
  217. {
  218. skip = 1;
  219. }
  220. if (!(strcmp(input, "q") && strcmp(input, "u"))) {
  221. if (input[0] == 'q') {
  222. action = 0;
  223. }
  224. else {
  225. action = 1;
  226. }
  227. update_scores(score, old_score);
  228. scoreboard();
  229. char mes[256];
  230. sprintf(mes, "Type y to confirm %s. Type anything else to cancel\n", actions[action]);
  231. sendclient(p, mes);
  232. get_info(p, input);
  233. if (input[0] == 'y') {
  234. break;
  235. }
  236. else {
  237. old_score = score;
  238. }
  239. }
  240. }
  241. if (action == 0) {
  242. raise(SIGINT);
  243. }
  244. else {
  245. round_num = 0;
  246. }
  247. }
  248. }
  249. int main(int argc, char* argv[]) {
  250. struct client *p;
  251. if (argc > 1)
  252. port = (short)(atoi(argv[1]));
  253. else
  254. port = PORT;
  255. listenfd = setup();
  256. struct sigaction alarm_handler;
  257. alarm_handler.sa_handler = timer_handler;
  258. sigemptyset(&alarm_handler.sa_mask);
  259. alarm_handler.sa_flags = 0;
  260. sigaction(SIGALRM, &alarm_handler, NULL);
  261. struct timeval select_wait_length;
  262. select_wait_length.tv_sec = TIMER_TICK - 1;
  263. select_wait_length.tv_usec = 0;
  264. alarm(TIMER_TICK);
  265. strcpy(input, "a");
  266. initialzie_dictionary();
  267. read_users();
  268. newact.sa_handler = handler;
  269. newact.sa_flags = 0;
  270. sigemptyset(&newact.sa_mask);
  271. sigaction(SIGALRM, &newact, NULL);
  272. sigaction(SIGINT, &newact, NULL);
  273. while(1){
  274. fd_set fds_to_read;
  275. FD_ZERO(&fds_to_read);
  276. FD_SET(listenfd, &fds_to_read);
  277. int fd_max = listenfd + 1;
  278. Client* current_client = client_list;
  279. while (current_client != NULL) {
  280. FD_SET(current_client->fd, &fds_to_read);
  281. if (current_client->fd + 1 > fd_max) {
  282. fd_max = current_client->fd + 1;
  283. }
  284. current_client = current_client->next;
  285. }
  286. int select_return_value;
  287. if ((select_return_value = select(fd_max, &fds_to_read, NULL, NULL, &select_wait_length)) < 0) {
  288. } else if (select_return_value == 0) {
  289. fprintf(stderr, "Select() Timed Out\n");
  290. } else {
  291. current_client = client_list;
  292. while (current_client != NULL) {
  293. if (FD_ISSET(current_client->fd, &fds_to_read)) {
  294. p = current_client;
  295. receiveclient(p, 0);
  296. break;
  297. }
  298. current_client = current_client->next;
  299. }
  300. if (FD_ISSET(listenfd, &fds_to_read)) {
  301. new_connection(listenfd);
  302. }
  303. }
  304. select_wait_length.tv_sec = TIMER_TICK - 1;
  305. select_wait_length.tv_usec = 0;
  306. }
  307. return 0;
  308. }
  309. void timer_handler(int sig) {
  310. Client *curr;
  311. for (curr = client_list; curr!=NULL; curr = curr->next) {
  312. sendclient(curr, "Game over\r\n");
  313. }
  314. alarm(TIMER_TICK);
  315. }
  316. int setup (void) {
  317. int on = 1, status;
  318. struct sockaddr_in self;
  319. int listenfd;
  320. if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  321. perror("socket");
  322. exit(1);
  323. }
  324. status = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
  325. (const char *) &on, sizeof(on));
  326. if(status == -1) {
  327. perror("setsockopt -- REUSEADDR");
  328. }
  329. memset(&self, '\0', sizeof(self));
  330. self.sin_family = AF_INET;
  331. self.sin_addr.s_addr = INADDR_ANY;
  332. self.sin_port = htons(port);
  333. printf("Listening on %d\n", port);
  334. if (bind(listenfd, (struct sockaddr *)&self, sizeof(self)) == -1) {
  335. perror("bind");
  336. exit(1);
  337. }
  338. if (listen(listenfd, 5) == -1) {
  339. perror("listen");
  340. exit(1);
  341. }
  342. return listenfd;
  343. }
  344. void add_client(int fd, struct in_addr addr){
  345. struct client *p = (Client *)malloc(sizeof(struct client));
  346. if (!p) {
  347. perror("malloc failure");
  348. exit(1);
  349. }
  350. printf("Adding client %s\n", inet_ntoa(addr));
  351. fflush(stdout);
  352. p->fd = fd;
  353. p->state = NAME;
  354. p->inbuf = 0;
  355. if (client_list == NULL) {
  356. client_list = p;
  357. p->next = NULL;
  358. sendclient(p, "What is your player name?\n");
  359. return;
  360. }else{
  361. Client * head = client_list;
  362. while (head->next != NULL) {
  363. head = head->next;
  364. }
  365. head->next = p;
  366. p->next = NULL;
  367. sendclient(p, "What is your player name?\n");
  368. }
  369. }
  370. void new_connection (int listenfd) {
  371. int fd;
  372. struct sockaddr_in r;
  373. socklen_t socklen = sizeof(r);
  374. if ((fd = accept(listenfd, (struct sockaddr *)&r, &socklen)) < 0) {
  375. perror("accept");
  376. return;
  377. }
  378. printf("connection from %s\n", inet_ntoa(r.sin_addr));
  379. add_client(fd, r.sin_addr);
  380. }
  381. char * int2str(int n) {
  382. if (n == 0) {
  383. return "0";
  384. }
  385. char * str = (char*)malloc(sizeof(char) * 256);
  386. char buf[10] = "";
  387. int i = 0;
  388. int len = 0;
  389. int temp = n < 0 ? -n : n;
  390. if (str == NULL) {
  391. return NULL;
  392. }
  393. while (temp) {
  394. buf[i++] = (temp % 10) + '0';
  395. temp = temp / 10;
  396. }
  397. len = n < 0 ? ++i : i;
  398. str[i] = 0;
  399. while (1) {
  400. i--;
  401. if (buf[len - i - 1] == 0) {
  402. break;
  403. }
  404. str[i] = buf[len - i - 1];
  405. }
  406. if (i == 0) {
  407. str[i] = '-';
  408. }
  409. return str;
  410. }
  411. void remove_client(int fd) {
  412. fd_set fds_to_read;
  413. FD_ZERO(&fds_to_read);
  414. FD_SET(fd, &fds_to_read);
  415. int fd_max = listenfd + 1;
  416. Client* current_client = client_list;
  417. while (current_client != NULL) {
  418. FD_SET(current_client->fd, &fds_to_read);
  419. if (current_client->fd + 1 > fd_max) {
  420. fd_max = current_client->fd + 1;
  421. }
  422. current_client = current_client->next;
  423. }
  424. current_client = client_list;
  425. Client * ct = current_client;
  426. Client * p = NULL;
  427. while (current_client != NULL) {
  428. if (FD_ISSET(current_client->fd, &fds_to_read)) {
  429. p = current_client;
  430. receiveclient(p, 0);
  431. break;
  432. }
  433. ct = current_client;
  434. current_client = current_client->next;
  435. }
  436. if (ct == current_client) {
  437. player_list = player_list->next;
  438. } else if(current != NULL){
  439. ct->next = current_client->next;
  440. }
  441. }
  442. void receiveclient(struct client *p, int flag) {
  443. char *after = p->buf + p->inbuf;
  444. int room = BUFFER_SIZE - p->inbuf;
  445. int nbytes;
  446. if ((nbytes = read(p->fd, after, room)) > 0) {
  447. p->inbuf += nbytes;
  448. int where = find_network_newline(p->buf, p->inbuf);
  449. if (where >= 0) {
  450. p->buf[where] = '\0';
  451. p->buf[where+1] = '\0';
  452. interpret_message(p, flag);
  453. where+=2; // skip over \r\n
  454. p->inbuf -= where;
  455. memmove(p->buf, p->buf + where, p->inbuf);
  456. }
  457. room = sizeof(p->buf) - p->inbuf;
  458. after = p->buf + p->inbuf;
  459. } else {
  460. remove_client(p->fd);
  461. }
  462. }
  463. int create_player(const char * name, Player ** list) {
  464. Player * p = (Player *)malloc(sizeof(Player));
  465. strcpy(p->name, name);
  466. p->max_score = 0;
  467. p->total_score = 0;
  468. p->total_games = 0;
  469. p->next = NULL;
  470. if (player_list == NULL) {
  471. player_list = p;
  472. } else {
  473. Player * cur = player_list;
  474. while (cur->next != NULL) {
  475. cur = cur->next;
  476. }
  477. cur->next = p;
  478. }
  479. return 0;
  480. }
  481. void interpret_message(Client *p, int flag) {
  482. char *buf;
  483. if (p->state == NAME) {
  484. strcpy(p->name, p->buf);
  485. switch (create_player(p->name, &player_list)) {
  486. case 1:
  487. sendclient(p, "Welcome back.\r\n");
  488. break;
  489. case 2:
  490. asprintf(&buf, "Username too long, truncated to %d chars.\r\n", (MAX_NAME-1));
  491. sendclient(p, buf);
  492. break;
  493. case 0:
  494. sendclient(p, "Welcome, new player\r\n");
  495. break;
  496. }
  497. printf("Added %s to the client list\n",p->name);
  498. p->state = COMMAND;
  499. sendclient(p, "Go ahead and enter player commands>\r\n");
  500. } else if (!strcmp(p->buf, "q")) {
  501. remove_client(p->fd);
  502. parse_line(p, flag);
  503. } else {
  504. parse_line(p, flag);
  505. }
  506. }
  507. int parse_line(Client *p, int flag) {
  508. char * input = p->buf;
  509. char *cmd_argv[INPUT_ARG_MAX_NUM];
  510. int cmd_argc;
  511. char *next_token = strtok(input, DELIM);
  512. cmd_argc = 0;
  513. while (next_token != NULL) {
  514. cmd_argv[cmd_argc] = next_token;
  515. cmd_argc++;
  516. next_token = strtok(NULL, DELIM);
  517. }
  518. return (cmd_argc > 0 && do_command(p, cmd_argc, cmd_argv, flag));
  519. }
  520. int sort_player_by_score(const void * a1, const void * a2){
  521. Player * p1 = (Player *) a1;
  522. Player * p2 = (Player *) a2;
  523. if (p1->total_score < p2->total_score) {
  524. return -1;
  525. } else if (p1->total_score > p2->total_score){
  526. return 1;
  527. } else {
  528. return 0;
  529. }
  530. }
  531. void print_list(Player * playlist){
  532. Player * cur = playlist;
  533. while (cur != NULL) {
  534. cur = cur->next;
  535. }
  536. }
  537. Player* find_player(const char * name, const Player * head){
  538. Player * cur = player_list;
  539. while (cur != NULL) {
  540. if (strcmp(cur->name, name)==0) {
  541. return cur;
  542. }
  543. cur = cur->next;
  544. }
  545. return NULL;
  546. }
  547. int do_command(struct client * p, int cmd_argc, char **cmd_argv, int flag) {
  548. if (flag == 1) {
  549. char a[256];
  550. strcat(a, "input over:");
  551. strcat(a, cmd_argv[0]);
  552. strcat(a, "\n");
  553. sendclient(p, a);
  554. return 0;
  555. }
  556. if (cmd_argc <= 0) {
  557. return 0;
  558. } else if (strcmp(cmd_argv[0], "q") == 0 && cmd_argc == 1) {
  559. sendclient(p, "close the connection with server\n");
  560. sendclient(p, "exit\n");
  561. remove_client(p->fd);
  562. return -1;
  563. } else if (strcmp(cmd_argv[0], "all_players") == 0 && cmd_argc == 1) {
  564. Player * head = player_list;
  565. while (head != NULL){
  566. sendclient(p, "username: ");
  567. sendclient(p, head->name);
  568. sendclient(p, "; max_score: ");
  569. sendclient(p, int2str(head->max_score));
  570. sendclient(p, "; total_score: ");
  571. sendclient(p, int2str(head->total_score));
  572. sendclient(p, "; total_games: ");
  573. sendclient(p, int2str(head->total_games));
  574. sendclient(p, "\n");
  575. head = head->next;
  576. }
  577. } else if (strcmp(cmd_argv[0], "top_3") == 0 && cmd_argc == 1) {
  578. Player * head = player_list;
  579. Player * ct = player_list;
  580. int count = 0;
  581. while (ct != NULL) {
  582. ct = ct->next;
  583. count ++;
  584. }
  585. qsort(head, count, sizeof(Player), sort_player_by_score);
  586. char * message = (char *)malloc(sizeof(char) * 256);
  587. int index = 1;
  588. while (head != NULL) {
  589. strcat(message, int2str(index));
  590. strcat(message, ". ");
  591. strcat(message, head->name);
  592. strcat(message, " ");
  593. strcat(message, int2str(head->total_score));
  594. strcat(message, "\n");
  595. index += 1;
  596. head = head->next;
  597. }
  598. if(count == 0) {
  599. sendclient(p, "there no players\n");
  600. } else {
  601. sendclient(p, message);
  602. }
  603. } else if (strcmp(cmd_argv[0], "add_score") == 0 && cmd_argc == 2) {
  604. char str [BUFFER_SIZE - 10];
  605. int score =atoi(cmd_argv[1]);
  606. sendclient(p, p->name);
  607. print_list(player_list);
  608. sendclient(p, "\n");
  609. Player *player = find_player(p->name, player_list);
  610. player->total_score+=score;
  611. if (score > player->max_score)
  612. player->max_score = score;
  613. sprintf (str, "added score %d for player %s\r\n", score, p->name);
  614. sendclient(p, str);
  615. } else if (strcmp(cmd_argv[0], "new_game") == 0 && cmd_argc == 1) {
  616. special_client = * p;
  617. start_game(p);
  618. if(player_list == NULL) {
  619. printf("Playerlist is null\n");
  620. }
  621. Player * pl = player_list;
  622. while (pl != NULL) {
  623. if (strcmp(pl->name,p->name)==0){
  624. break;
  625. }
  626. pl = pl->next;
  627. }
  628. pl->total_games += 1;
  629. in_newgame = 1;
  630. }else if(in_newgame == 0){
  631. sendclient(p, "Incorrect syntax\r\n");
  632. } else {
  633. word_score = verify_word(cmd_argv[0]);
  634. if (word_score > 0) {
  635. score += word_score;
  636. }
  637. refresh_screen(score, word_score, input, p);
  638. Player *player = find_player(p->name, player_list);
  639. player->total_score+=word_score;
  640. if (score > player->max_score)
  641. player->max_score = score;
  642. }
  643. return 0;
  644. }
  645. void sendclient(Client *p, char *msg) {
  646. write(p->fd, msg, strlen(msg));
  647. }
  648. int find_network_newline(char *buf, int inbuf) {
  649. int i;
  650. for (i = 0; i < inbuf - 1; i++)
  651. if ((buf[i] == '\r') && (buf[i + 1] == '\n'))
  652. return i;
  653. return -1;
  654. }