summaryrefslogtreecommitdiff
path: root/pgm4/ttt.c
diff options
context:
space:
mode:
Diffstat (limited to 'pgm4/ttt.c')
-rw-r--r--pgm4/ttt.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/pgm4/ttt.c b/pgm4/ttt.c
new file mode 100644
index 0000000..572c588
--- /dev/null
+++ b/pgm4/ttt.c
@@ -0,0 +1,257 @@
+/* ttt.c
+ *
+ * Utilizes code from P. Kearns - 1987, 2009
+ * Adam Carpenter - 2017
+ */
+
+#include "ttt.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+int main(int argc, char *argv[]) {
+ int queryFlag;
+ struct timeval timeout;
+ int i;
+ int errno;
+ int hits;
+ fd_set readSockets;
+ // fd_set writeSockets;
+
+ char message[MESSAGE_BUFF];
+ char playerHandle[MESSAGE_BUFF];
+ char opponentHandle[MESSAGE_BUFF];
+ char playerSide;
+ char opponentSide;
+ char gameBoard[9];
+ char playerMove;
+ int connSock;
+
+ char hostname[MAX_HOSTNAME];
+ char port[100];
+ struct sockaddr_in *serverAddr;
+ struct addrinfo hints, *addrlist;
+
+ i = 1;
+ queryFlag = FALSE;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ while (argv[i]) {
+
+ if (strcmp(argv[i], "-q") == 0) {
+ queryFlag = TRUE;
+ }
+ else if (strcmp(argv[i], "-t") == 0) {
+
+ if (!argv[i + 1]) {
+ fprintf(stderr, "usage: ./ttt {-q} {-t} [timeout]\n");
+ exit(1);
+ }
+
+ timeout.tv_sec = strtol(argv[i + 1], NULL, 10);
+ errno = 0;
+
+ if (timeout.tv_sec <= 0) {
+ fprintf(stderr, "ttt: timeout must be a positive, nonzero integer.\n");
+ exit(1);
+ }
+ else if (errno == ERANGE) {
+ fprintf(stderr, "ttt: timeout must be of integer size.\n");
+ exit(1);
+ }
+ else if (errno == EINVAL) {
+ fprintf(stderr, "ttt: timeout must be integer type.\n");
+ exit(1);
+ }
+
+ i++;
+ }
+ else {
+ fprintf(stderr, "usage: ./ttt {-q} {-t} [timeout]\n");
+ exit(1);
+ }
+
+ i++;
+ }
+
+ // Get server sockaddr.
+ memset( &hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+
+ if (queryFlag) {
+ hints.ai_socktype = SOCK_DGRAM;
+ }
+ else {
+ hints.ai_socktype = SOCK_STREAM;
+
+ }
+
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_protocol = 0;
+ hints.ai_canonname = NULL;
+ hints.ai_addr = NULL;
+ hints.ai_next = NULL;
+
+ // (Read name and port from file.)
+ FILE *addrfile;
+
+ if (!(addrfile = fopen("prof.falken", "r"))) {
+ sleep(60);
+ if (!(addrfile = fopen("prof.falken", "r"))) {
+ fprintf(stderr, "ttt: couldn't open file -- is server running?\n");
+ exit(1);
+ }
+ }
+
+ fscanf(addrfile, "%s\n", hostname);
+ fscanf(addrfile, "%s\n", port);
+
+ if (queryFlag) {
+ fscanf(addrfile, "%s\n", port);
+ }
+
+ fclose(addrfile);
+
+ if (getaddrinfo(hostname, port, &hints, &addrlist) != 0) {
+ fprintf(stderr, "ttt: couldn't getaddrinfo.\n");
+ exit(1);
+ }
+
+ serverAddr = (struct sockaddr_in *) addrlist->ai_addr;
+
+ if ((connSock = socket(addrlist->ai_family, addrlist->ai_socktype, 0)) < 0) {
+ fprintf(stderr, "ttt: couldn't create socket.\n");
+ exit(1);
+ }
+
+ if (queryFlag) { // Wait for query from server if requested.
+ printf("Querying server...\n");
+ message[0] = '\0';
+ timeout.tv_sec = 10;
+ timeout.tv_usec = 0;
+ setsockopt(connSock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &timeout, sizeof(timeout));
+ sendto(connSock, "q\0", strlen("q\0"), 0, (struct sockaddr *) serverAddr, sizeof(struct sockaddr_in));
+ recvfrom(connSock, message, MESSAGE_BUFF, 0, NULL, NULL);
+
+ if (message[0] == '\0') {
+ printf("Connection timed out.\n");
+ }
+ else {
+ printf("%s\n", message);
+ }
+
+ exit(0);
+ }
+ else { // Else connect to virtual circuit with server.
+ if (connect(connSock, (struct sockaddr *) serverAddr, sizeof(struct sockaddr_in)) < 0) {
+ fprintf(stderr, "ttt: couldn't connect to socket.\n");
+ exit(1);
+ }
+ }
+
+ printf("Waiting for server...\n");
+ playerHandle[0] = '\0';
+
+ // Enter main client loop.
+ for(;;) {
+ FD_ZERO(&readSockets);
+ FD_SET(connSock, &readSockets);
+
+ if (timeout.tv_sec == 0) {
+ hits = select(FD_SETSIZE, &readSockets, NULL, NULL, NULL);
+ }
+ else {
+ hits = select(FD_SETSIZE, &readSockets, NULL, NULL, &timeout);
+ }
+
+ if (hits < 0) {
+ fprintf(stderr, "ttt: failed to select.\n");
+ exit(1);
+ }
+ else if (hits == 0) {
+ fprintf(stderr, "ttt: connection timed out.\n");
+ exit(0);
+ }
+
+ // Get instructions from server.
+ getMessage(connSock, message);
+
+ if (strcmp(message, HANDLE) == 0) { // Get and send handle.
+
+ if (playerHandle[0] == '\0') {
+ printf("Who are you? ");
+ scanf("%20[^\n]", playerHandle);
+ }
+
+ sendMessage(connSock, playerHandle);
+ printf("Waiting for opponent...\n");
+ }
+ else if (strcmp(message, ABORT) == 0) { // Abort.
+ printf("Server ordered shutdown. Buhbye!\n");
+ exit(0);
+ }
+ else if (message[0] == PLAYERID) { // Print name and sides.
+ sscanf(message, "p %c %c %[^\n]", &playerSide, &opponentSide, opponentHandle);
+
+ if (playerSide == 'X') {
+ opponentSide = 'O';
+ }
+ else {
+ opponentSide = 'X';
+ }
+
+ printf("%s, you are %cs. Your opponent %s is %cs.\n", playerHandle, playerSide, opponentHandle, opponentSide);
+ timeout.tv_sec = 0; // Game established -- end timeout.
+ }
+ else if (message[0] == BOARD) { // Draw the game board.
+ sscanf(message, "b %s", gameBoard);
+ printf("\n %c | %c | %c\n-----------\n %c | %c | %c\n-----------\n %c | %c | %c\n\n",
+ gameBoard[0], gameBoard[1], gameBoard[2],
+ gameBoard[3], gameBoard[4], gameBoard[5],
+ gameBoard[6], gameBoard[7], gameBoard[8]);
+ }
+ else if (strcmp(message, WAIT) == 0) { // Wait for opponent.
+ printf("Waiting for opponent...\n");
+ }
+ else if (strcmp(message, MOVE) == 0) { // Get and send move.
+ playerMove = '0';
+
+ while (playerMove < '1' || playerMove > '9' || gameBoard[playerMove - '0' - 1] != playerMove) {
+ if (playerMove != '\n') {
+ printf("Choose an available number on the board.\nYour move: ");
+ }
+
+ playerMove = getchar();
+ }
+
+ gameBoard[playerMove - '0' - 1] = playerSide;
+ strcpy(message, gameBoard);
+ sendMessage(connSock, message);
+ printf("Waiting for opponent...");
+ }
+ else if (message[0] == ENDGAME) { // End Game.
+
+ if (message[1] == playerSide) {
+ printf("\nYou won %s! Congratulations!\n", playerHandle);
+ }
+ else if (message[1] == opponentSide) {
+ printf("\nYou lost! %s won the match.\nBetter luck next time.\n", opponentHandle);
+ }
+ else {
+ printf("\nThe match was a tie!\nBetter luck next time.\n");
+ }
+ exit(0);
+ }
+
+ }
+
+ exit(0);
+}