Sun, 23 Feb 2014 21:03:35 +0100
fixed network code + added game info and transmission of game info
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2014 Mike Becker. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
30 #include "terminal-chess.h"
31 #include <string.h>
32 #include <time.h>
34 int get_settings(int argc, char **argv, Settings *settings) {
35 char *valid;
36 unsigned long int time, port;
37 uint8_t timeunit = 60;
38 size_t len;
40 for (char opt ; (opt = getopt(argc, argv, "a:bhp:rt:")) != -1 ;) {
41 switch (opt) {
42 case 'b':
43 settings->gameinfo.servercolor = BLACK;
44 break;
45 case 'r':
46 settings->gameinfo.servercolor = (rand()>>5) & 1 ? WHITE : BLACK;
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 }
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;
63 } else {
64 settings->gameinfo.addtime = time;
65 }
66 }
67 break;
68 case 'p':
69 port = strtol(optarg, &valid, 10);
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;
84 }
85 }
87 if (optind == argc - 1) {
88 settings->serverhost = argv[optind];
89 } else if (optind < argc - 1) {
90 fprintf(stderr, "Too many arguments\n");
91 return 1;
92 }
94 return 0;
95 }
97 Settings default_settings() {
98 Settings settings;
99 memset(&settings, 0, sizeof(Settings));
100 settings.gameinfo.servercolor = WHITE;
101 settings.port = "27015";
102 return settings;
103 }
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 }
123 }
125 int cleanup(Settings *settings, int exitcode) {
126 if (settings->server) {
127 if (net_destroy(settings->server)) {
128 perror("Server shutdown failed");
129 }
130 }
132 return exitcode;
133 }
135 int main(int argc, char **argv) {
136 srand(time(NULL));
138 Settings settings = default_settings();
139 if (get_settings(argc, argv, &settings)) {
140 return 1;
141 }
143 if (settings.printhelp) {
144 printf(
145 "Usage: terminal-chess [OPTION]... [HOST]\n"
146 "Starts/joins a network chess game\n"
147 "\nGeneral options\n"
148 " -h This help page\n"
149 " -p TCP port to use (default: 27015)\n"
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 );
162 return EXIT_SUCCESS;
163 }
165 Server server;
166 settings.server = &server;
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 }
176 if (net_listen(&server)) {
177 perror("Listening for client failed");
178 return cleanup(&settings, EXIT_FAILURE);
179 }
181 printf("Client connected - transmitting gameinfo...\n");
182 net_send(server.client->fd, NETCODE_GAMEINFO,
183 &(settings.gameinfo), sizeof(settings.gameinfo));
184 } else {
185 if (net_find(&server, settings.serverhost, settings.port)) {
186 perror("Can't find server");
187 return cleanup(&settings, EXIT_FAILURE);
188 }
190 if (net_connect(&server)) {
191 perror("Can't connect to server");
192 return cleanup(&settings, EXIT_FAILURE);
193 }
195 printf("Connection established!\n\n");
196 if (net_recieve_code(server.fd) == NETCODE_GAMEINFO) {
197 net_recieve_data(server.fd, &(settings.gameinfo),
198 sizeof(settings.gameinfo));
199 dump_gameinfo(&(settings.gameinfo));
200 } else {
201 fprintf(stderr, "Server sent invalid gameinfo.\n");
202 }
203 }
205 return cleanup(&settings, EXIT_SUCCESS);
206 }