src/main.c

changeset 2
0a08f79c320d
parent 1
e5fbb8f9edbe
child 3
3693fd2eb0e9
equal deleted inserted replaced
1:e5fbb8f9edbe 2:0a08f79c320d
27 * 27 *
28 */ 28 */
29 29
30 #include "terminal-chess.h" 30 #include "terminal-chess.h"
31 #include <string.h> 31 #include <string.h>
32 #include <time.h>
32 33
33 int get_settings(int argc, char **argv, Settings *settings) { 34 int get_settings(int argc, char **argv, Settings *settings) {
34 char *valid; 35 char *valid;
35 36 unsigned long int time, port;
36 for (char opt ; (opt = getopt(argc, argv, "hp:")) != -1 ;) { 37 uint8_t timeunit = 60;
38 size_t len;
39
40 for (char opt ; (opt = getopt(argc, argv, "a:bhp:rt:")) != -1 ;) {
37 switch (opt) { 41 switch (opt) {
38 case 'p': 42 case 'b':
39 if (strtol(optarg, &valid, 10) < 1025 || *valid != '\0') { 43 settings->gameinfo.servercolor = BLACK;
40 fprintf(stderr, 44 break;
41 "Invalid port number (%s) - choose a number > 1024\n", 45 case 'r':
42 optarg); 46 settings->gameinfo.servercolor = (rand()>>5) & 1 ? WHITE : BLACK;
43 return 1; 47 break;
48 case 't':
49 case 'a':
50 len = strlen(optarg);
51 if (optarg[len-1] == 's') {
52 optarg[len-1] = '\0';
53 timeunit = 1;
54 }
55
56 if ((time = strtoul(optarg, &valid, 10)) > TIME_MAX
57 || *valid != '\0') {
58 fprintf(stderr, "Specified time is invalid (%s)\n", optarg);
59 return 1;
60 } else {
61 if (opt=='t') {
62 settings->gameinfo.time = timeunit * time;
44 } else { 63 } else {
45 settings->port = optarg; 64 settings->gameinfo.addtime = time;
46 } 65 }
47 break; 66 }
48 case 'h': 67 break;
49 case '?': 68 case 'p':
50 settings->printhelp = 1; 69 port = strtol(optarg, &valid, 10);
51 break; 70 if (port < 1025 || port > 65535 || *valid != '\0') {
71 fprintf(stderr,
72 "Invalid port number (%s) - choose a number between "
73 "1025 and 65535\n",
74 optarg);
75 return 1;
76 } else {
77 settings->port = optarg;
78 }
79 break;
80 case 'h':
81 case '?':
82 settings->printhelp = 1;
83 break;
52 } 84 }
53 } 85 }
54 86
55 if (optind == argc - 1) { 87 if (optind == argc - 1) {
56 settings->serverhost = argv[optind]; 88 settings->serverhost = argv[optind];
63 } 95 }
64 96
65 Settings default_settings() { 97 Settings default_settings() {
66 Settings settings; 98 Settings settings;
67 memset(&settings, 0, sizeof(Settings)); 99 memset(&settings, 0, sizeof(Settings));
100 settings.gameinfo.servercolor = WHITE;
68 settings.port = "27015"; 101 settings.port = "27015";
69 return settings; 102 return settings;
103 }
104
105 void dump_gameinfo(Gameinfo *gameinfo) {
106 int serverwhite = gameinfo->servercolor == WHITE;
107 printf(
108 "Game details:\n"
109 " Server plays %s - Client plays %s\n",
110 serverwhite?"white":"black", serverwhite?"black":"White"
111 );
112 if (gameinfo->time > 0) {
113 if (gameinfo->time % 60) {
114 printf(" Time limit: %ds + %ds\n",
115 gameinfo->time, gameinfo->addtime);
116 } else {
117 printf(" Time limit: %dm + %ds\n",
118 gameinfo->time/60, gameinfo->addtime);
119 }
120 } else {
121 printf(" No time limit\n");
122 }
70 } 123 }
71 124
72 int cleanup(Settings *settings, int exitcode) { 125 int cleanup(Settings *settings, int exitcode) {
73 if (settings->server) { 126 if (settings->server) {
74 if (net_destroy(settings->server)) { 127 if (net_destroy(settings->server)) {
78 131
79 return exitcode; 132 return exitcode;
80 } 133 }
81 134
82 int main(int argc, char **argv) { 135 int main(int argc, char **argv) {
136 srand(time(NULL));
83 137
84 Settings settings = default_settings(); 138 Settings settings = default_settings();
85 get_settings(argc, argv, &settings); 139 if (get_settings(argc, argv, &settings)) {
140 return 1;
141 }
86 142
87 if (settings.printhelp) { 143 if (settings.printhelp) {
88 printf( 144 printf(
89 "Usage: %s [OPTION]... [HOST]\n" 145 "Usage: terminal-chess [OPTION]... [HOST]\n"
90 "Starts/joins a network chess game\n\n" 146 "Starts/joins a network chess game\n"
147 "\nGeneral options\n"
91 " -h This help page\n" 148 " -h This help page\n"
92 " -p TCP port to use (default: 27015)\n", 149 " -p TCP port to use (default: 27015)\n"
93 argv[0]); 150 "\nServer options\n"
151 " -a <time> Specifies the time to add after each move\n"
152 " -b Server plays black pieces (default: white)\n"
153 " -r Distribute color randomly\n"
154 " -t <time> Specifies time limit (default: no limit)\n"
155 "\nNotes\n"
156 "White pieces are displayed as uppercase and black pieces as "
157 "lowercase letters.\n"
158 "The time unit for -a is seconds and for -t minutes by default. To "
159 "specify\nseconds for the -t option, use the s suffix.\n"
160 "Example: -t 150s\n"
161 );
94 return EXIT_SUCCESS; 162 return EXIT_SUCCESS;
95 } 163 }
96 164
97 Server server; 165 Server server;
98 settings.server = &server; 166 settings.server = &server;
99 167
100 if (is_server(&settings)) { 168 if (is_server(&settings)) {
169 dump_gameinfo(&(settings.gameinfo));
170 printf("\nListening for client...\n");
171 if (net_create(&server, settings.port)) {
172 perror("Server creation failed");
173 return cleanup(&settings, EXIT_FAILURE);
174 }
175
176 if (net_listen(&server)) {
177 perror("Listening for client failed");
178 return cleanup(&settings, EXIT_FAILURE);
179 }
180
181 printf("Client connected - transmitting gameinfo...\n");
182 net_send(server.client->fd, NETCODE_GAMEINFO,
183 &(settings.gameinfo), sizeof(settings.gameinfo));
184 } else {
101 if (net_find(&server, settings.serverhost, settings.port)) { 185 if (net_find(&server, settings.serverhost, settings.port)) {
102 perror("Can't find server"); 186 perror("Can't find server");
103 return cleanup(&settings, EXIT_FAILURE); 187 return cleanup(&settings, EXIT_FAILURE);
104 } 188 }
105 189
106 if (net_connect(&server)) { 190 if (net_connect(&server)) {
107 perror("Can't connect to server"); 191 perror("Can't connect to server");
108 return cleanup(&settings, EXIT_FAILURE); 192 return cleanup(&settings, EXIT_FAILURE);
109 } 193 }
110 } else { 194
111 if (net_create(&server, settings.port)) { 195 printf("Connection established!\n\n");
112 perror("Server creation failed"); 196 if (net_recieve_code(server.fd) == NETCODE_GAMEINFO) {
113 return cleanup(&settings, EXIT_FAILURE); 197 net_recieve_data(server.fd, &(settings.gameinfo),
114 } 198 sizeof(settings.gameinfo));
115 199 dump_gameinfo(&(settings.gameinfo));
116 if (net_listen(&server)) { 200 } else {
117 perror("Listening for client failed"); 201 fprintf(stderr, "Server sent invalid gameinfo.\n");
118 return cleanup(&settings, EXIT_FAILURE);
119 } 202 }
120 } 203 }
121 204
122 return cleanup(&settings, EXIT_SUCCESS); 205 return cleanup(&settings, EXIT_SUCCESS);
123 } 206 }

mercurial