1.1 --- a/src/main.c Wed Feb 05 14:07:43 2014 +0100 1.2 +++ b/src/main.c Sun Feb 23 21:03:35 2014 +0100 1.3 @@ -29,26 +29,58 @@ 1.4 1.5 #include "terminal-chess.h" 1.6 #include <string.h> 1.7 +#include <time.h> 1.8 1.9 int get_settings(int argc, char **argv, Settings *settings) { 1.10 char *valid; 1.11 + unsigned long int time, port; 1.12 + uint8_t timeunit = 60; 1.13 + size_t len; 1.14 1.15 - for (char opt ; (opt = getopt(argc, argv, "hp:")) != -1 ;) { 1.16 + for (char opt ; (opt = getopt(argc, argv, "a:bhp:rt:")) != -1 ;) { 1.17 switch (opt) { 1.18 - case 'p': 1.19 - if (strtol(optarg, &valid, 10) < 1025 || *valid != '\0') { 1.20 - fprintf(stderr, 1.21 - "Invalid port number (%s) - choose a number > 1024\n", 1.22 - optarg); 1.23 - return 1; 1.24 + case 'b': 1.25 + settings->gameinfo.servercolor = BLACK; 1.26 + break; 1.27 + case 'r': 1.28 + settings->gameinfo.servercolor = (rand()>>5) & 1 ? WHITE : BLACK; 1.29 + break; 1.30 + case 't': 1.31 + case 'a': 1.32 + len = strlen(optarg); 1.33 + if (optarg[len-1] == 's') { 1.34 + optarg[len-1] = '\0'; 1.35 + timeunit = 1; 1.36 + } 1.37 + 1.38 + if ((time = strtoul(optarg, &valid, 10)) > TIME_MAX 1.39 + || *valid != '\0') { 1.40 + fprintf(stderr, "Specified time is invalid (%s)\n", optarg); 1.41 + return 1; 1.42 + } else { 1.43 + if (opt=='t') { 1.44 + settings->gameinfo.time = timeunit * time; 1.45 } else { 1.46 - settings->port = optarg; 1.47 + settings->gameinfo.addtime = time; 1.48 } 1.49 - break; 1.50 - case 'h': 1.51 - case '?': 1.52 - settings->printhelp = 1; 1.53 - break; 1.54 + } 1.55 + break; 1.56 + case 'p': 1.57 + port = strtol(optarg, &valid, 10); 1.58 + if (port < 1025 || port > 65535 || *valid != '\0') { 1.59 + fprintf(stderr, 1.60 + "Invalid port number (%s) - choose a number between " 1.61 + "1025 and 65535\n", 1.62 + optarg); 1.63 + return 1; 1.64 + } else { 1.65 + settings->port = optarg; 1.66 + } 1.67 + break; 1.68 + case 'h': 1.69 + case '?': 1.70 + settings->printhelp = 1; 1.71 + break; 1.72 } 1.73 } 1.74 1.75 @@ -65,10 +97,31 @@ 1.76 Settings default_settings() { 1.77 Settings settings; 1.78 memset(&settings, 0, sizeof(Settings)); 1.79 + settings.gameinfo.servercolor = WHITE; 1.80 settings.port = "27015"; 1.81 return settings; 1.82 } 1.83 1.84 +void dump_gameinfo(Gameinfo *gameinfo) { 1.85 + int serverwhite = gameinfo->servercolor == WHITE; 1.86 + printf( 1.87 + "Game details:\n" 1.88 + " Server plays %s - Client plays %s\n", 1.89 + serverwhite?"white":"black", serverwhite?"black":"White" 1.90 + ); 1.91 + if (gameinfo->time > 0) { 1.92 + if (gameinfo->time % 60) { 1.93 + printf(" Time limit: %ds + %ds\n", 1.94 + gameinfo->time, gameinfo->addtime); 1.95 + } else { 1.96 + printf(" Time limit: %dm + %ds\n", 1.97 + gameinfo->time/60, gameinfo->addtime); 1.98 + } 1.99 + } else { 1.100 + printf(" No time limit\n"); 1.101 + } 1.102 +} 1.103 + 1.104 int cleanup(Settings *settings, int exitcode) { 1.105 if (settings->server) { 1.106 if (net_destroy(settings->server)) { 1.107 @@ -80,17 +133,32 @@ 1.108 } 1.109 1.110 int main(int argc, char **argv) { 1.111 + srand(time(NULL)); 1.112 1.113 Settings settings = default_settings(); 1.114 - get_settings(argc, argv, &settings); 1.115 + if (get_settings(argc, argv, &settings)) { 1.116 + return 1; 1.117 + } 1.118 1.119 if (settings.printhelp) { 1.120 printf( 1.121 - "Usage: %s [OPTION]... [HOST]\n" 1.122 - "Starts/joins a network chess game\n\n" 1.123 + "Usage: terminal-chess [OPTION]... [HOST]\n" 1.124 + "Starts/joins a network chess game\n" 1.125 + "\nGeneral options\n" 1.126 " -h This help page\n" 1.127 - " -p TCP port to use (default: 27015)\n", 1.128 - argv[0]); 1.129 + " -p TCP port to use (default: 27015)\n" 1.130 + "\nServer options\n" 1.131 + " -a <time> Specifies the time to add after each move\n" 1.132 + " -b Server plays black pieces (default: white)\n" 1.133 + " -r Distribute color randomly\n" 1.134 + " -t <time> Specifies time limit (default: no limit)\n" 1.135 + "\nNotes\n" 1.136 + "White pieces are displayed as uppercase and black pieces as " 1.137 + "lowercase letters.\n" 1.138 + "The time unit for -a is seconds and for -t minutes by default. To " 1.139 + "specify\nseconds for the -t option, use the s suffix.\n" 1.140 + "Example: -t 150s\n" 1.141 + ); 1.142 return EXIT_SUCCESS; 1.143 } 1.144 1.145 @@ -98,6 +166,22 @@ 1.146 settings.server = &server; 1.147 1.148 if (is_server(&settings)) { 1.149 + dump_gameinfo(&(settings.gameinfo)); 1.150 + printf("\nListening for client...\n"); 1.151 + if (net_create(&server, settings.port)) { 1.152 + perror("Server creation failed"); 1.153 + return cleanup(&settings, EXIT_FAILURE); 1.154 + } 1.155 + 1.156 + if (net_listen(&server)) { 1.157 + perror("Listening for client failed"); 1.158 + return cleanup(&settings, EXIT_FAILURE); 1.159 + } 1.160 + 1.161 + printf("Client connected - transmitting gameinfo...\n"); 1.162 + net_send(server.client->fd, NETCODE_GAMEINFO, 1.163 + &(settings.gameinfo), sizeof(settings.gameinfo)); 1.164 + } else { 1.165 if (net_find(&server, settings.serverhost, settings.port)) { 1.166 perror("Can't find server"); 1.167 return cleanup(&settings, EXIT_FAILURE); 1.168 @@ -107,15 +191,14 @@ 1.169 perror("Can't connect to server"); 1.170 return cleanup(&settings, EXIT_FAILURE); 1.171 } 1.172 - } else { 1.173 - if (net_create(&server, settings.port)) { 1.174 - perror("Server creation failed"); 1.175 - return cleanup(&settings, EXIT_FAILURE); 1.176 - } 1.177 - 1.178 - if (net_listen(&server)) { 1.179 - perror("Listening for client failed"); 1.180 - return cleanup(&settings, EXIT_FAILURE); 1.181 + 1.182 + printf("Connection established!\n\n"); 1.183 + if (net_recieve_code(server.fd) == NETCODE_GAMEINFO) { 1.184 + net_recieve_data(server.fd, &(settings.gameinfo), 1.185 + sizeof(settings.gameinfo)); 1.186 + dump_gameinfo(&(settings.gameinfo)); 1.187 + } else { 1.188 + fprintf(stderr, "Server sent invalid gameinfo.\n"); 1.189 } 1.190 } 1.191