diff options
Diffstat (limited to 'pgm7/TTT.c')
-rw-r--r-- | pgm7/TTT.c | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/pgm7/TTT.c b/pgm7/TTT.c new file mode 100644 index 0000000..cec9023 --- /dev/null +++ b/pgm7/TTT.c @@ -0,0 +1,282 @@ +/************************************************************************ + TTT.c + Castrated TTT server. No datagram queries, no timeouts. Assumes + completely well-behaved clients. Uses deprecated network address + translation. + + Phil Kearns + April 12, 1998 + Modified March, 2014 + + Adapted with GUI by Adam Carpenter - acarpent - acarpenter@email.wm.edu + Modified April 2017 +*************************************************************************/ + +#include "common.h" + +char board[9]; /* The tic-tac-toe board */ + +int main(int argc, char **argv) + +{ + int listener; /* fd for socket on which we get connection requests */ + int Xfd, Ofd; /* fds for sockets onto VCs to clients */ + + struct sockaddr_in s1, Xaddr, Oaddr; + int length, sfile, i, moveto, result, Xresult, Oresult; + unsigned short lport; + int currentmove; /* 0->X, 1->O */ + char hostid[128], Xhandle[32], Ohandle[32]; + struct tttmsg outmsg, inmsg; + + if (argc != 1) { + fprintf(stderr,"TTT:usage is TTT\n"); + exit(1); + } + + if ( (sfile = open(SFILE, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) { + perror("TTT:sfile"); + exit(1); + } + + if (gethostname(hostid,128) < 0){ + perror("TTT:gethostname"); + exit(1); + } + + i=0; + while (hostid[i] != '\0') + write(sfile,&hostid[i++], 1); + write(sfile,"\0", 1); + + if ( (listener = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) { + perror("TTT:socket"); + exit(1); + } + + bzero((char *) &s1, sizeof(s1)); + s1.sin_family = AF_INET; + s1.sin_addr.s_addr = INADDR_ANY; /* Any of this host's interfaces is OK. */ + s1.sin_port = 0; /* bind() will gimme unique port. */ + if (bind(listener, (struct sockaddr *)&s1, sizeof(s1)) < 0) { + perror("TTT:bind"); + exit(1); + } + + length = sizeof(s1); + if (getsockname(listener, (struct sockaddr *)&s1, (socklen_t *)&length) < 0) { + perror("TTT:getsockname"); + exit(1); + } + lport = s1.sin_port; + write(sfile, &lport, sizeof(unsigned short)); + close(sfile); + + listen(listener,5); + + length = sizeof(Xaddr); + if ((Xfd = accept(listener, (struct sockaddr *)&Xaddr, (socklen_t *)&length)) < 0) { + perror("TTT:accept X"); + exit(1); + } + + /* Send WHO to X */ + + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type = WHO; + putmsg(Xfd, &outmsg); + + /* Await HANDLE from X */ + + bzero((char *)&inmsg, sizeof(inmsg)); + getmsg(Xfd, &inmsg); + if (inmsg.type != HANDLE) protocol_error(HANDLE, &inmsg); + strncpy(Xhandle, inmsg.data, 31); + Xhandle[31] = '\0'; + + length = sizeof(Oaddr); + if ((Ofd = accept(listener, (struct sockaddr *)&Oaddr, (socklen_t *)&length)) < 0) { + perror("TTT:accept O"); + exit(1); + } + + /* Send WHO to O */ + + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type = WHO; + putmsg(Ofd, &outmsg); + + /* Await HANDLE from O */ + + bzero((char *)&inmsg, sizeof(inmsg)); + getmsg(Ofd, &inmsg); + if (inmsg.type != HANDLE) protocol_error(HANDLE, &inmsg); + strncpy(Ohandle, inmsg.data, 31); + Ohandle[31] = '\0'; + + /* WE HAVE A MATCH */ + + for(i=0; i<9; i++) board[i]=' '; + + /* Send MATCH to X */ + + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type=MATCH; + strncpy(outmsg.data, Ohandle, 31); + outmsg.data[31] = '\0'; + outmsg.board[0] = 'X'; + putmsg(Xfd, &outmsg); + + /* Send MATCH to O */ + + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type=MATCH; + strncpy(outmsg.data, Xhandle, 31); + outmsg.data[31] = '\0'; + outmsg.board[0] = 'O'; + putmsg(Ofd, &outmsg); + + while(1) { + + /* Send WHATMOVE to X */ + + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type=WHATMOVE; + for(i=0; i<9; i++) outmsg.board[i]=board[i]; + putmsg(Xfd, &outmsg); + + /* Await MOVE from X */ + + bzero((char *)&inmsg, sizeof(inmsg)); + getmsg(Xfd, &inmsg); + + // End the match if player X resigned. + if (inmsg.type == RESIGNED) { + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type=ABORT; + putmsg(Ofd, &outmsg); + exit(0); + } + else if (inmsg.type != MOVE) { + protocol_error(MOVE, &inmsg); + } + + currentmove = 0; /* X's move being reported*/ + moveto = inmsg.res & 0xF; + if (board[moveto] != ' ') { + fprintf(stderr, "TTT: invalid move\n"); + exit(1); + } + board[moveto] = 'X'; + if ((result = check_board(currentmove)) != 0) break; + + /* Send WHATMOVE to O */ + + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type=WHATMOVE; + for(i=0; i<9; i++) outmsg.board[i]=board[i]; + putmsg(Ofd, &outmsg); + + /* Await MOVE from O */ + + bzero((char *)&inmsg, sizeof(inmsg)); + getmsg(Ofd, &inmsg); + + // End the match if player O resigned. + if (inmsg.type == RESIGNED) { + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type=ABORT; + putmsg(Xfd, &outmsg); + exit(0); + } + else if (inmsg.type != MOVE) { + protocol_error(MOVE, &inmsg); + } + + if (inmsg.type != MOVE) protocol_error(MOVE, &inmsg); + currentmove = 1; /* O's move being reported*/ + moveto = inmsg.res & 0xF; + if (board[moveto] != ' ') { + fprintf(stderr, "TTT: invalid move\n"); + exit(1); + } + board[moveto] = 'O'; + if ((result = check_board(currentmove)) != 0) break; + } /* while */ + + /* Match is over, report the result to both clients */ + + if (result == 2) { + Xresult = Oresult = 'D'; + } + else { /* result must be 1, we have a winner */ + if (currentmove == 0) { Xresult = 'W'; Oresult = 'L';} + else { Xresult = 'L'; Oresult = 'W';} + } + + /* Send RESULT to X */ + + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type = RESULT; + outmsg.res = Xresult; + for(i=0; i<9; i++) outmsg.board[i]=board[i]; + putmsg(Xfd, &outmsg); + + /* Send RESULT to O */ + + bzero((char *)&outmsg, sizeof(outmsg)); + outmsg.type = RESULT; + outmsg.res = Oresult; + for(i=0; i<9; i++) outmsg.board[i]=board[i]; + putmsg(Ofd, &outmsg); + + /* The game is finished */ + + return(0); +} + + +/************************************************************************ + check_board() returns 0 if no winner + 1 if winner + 2 if draw + Brute force. +************************************************************************/ +int +check_board(player) +int player; /* X is 0, O is 1 */ +{ + char match; + int i,spaces; + + match = (player?'O':'X'); + + if (((board[0] == match) && (board[1] == match) && (board[2] == match)) || + ((board[3] == match) && (board[4] == match) && (board[5] == match)) || + ((board[6] == match) && (board[7] == match) && (board[8] == match)) || + ((board[0] == match) && (board[3] == match) && (board[6] == match)) || + ((board[1] == match) && (board[4] == match) && (board[7] == match)) || + ((board[2] == match) && (board[5] == match) && (board[8] == match)) || + ((board[0] == match) && (board[4] == match) && (board[8] == match)) || + ((board[2] == match) && (board[4] == match) && (board[6] == match))) return 1; + spaces = 0; + for(i=0; i<9; i++) + if (board[i] == ' ') { + spaces++; + break; + } + if (!spaces) return 2; + return 0; +} + +void +dump_board(s,board) +FILE *s; +char board[]; +{ + fprintf(s,"%c | %c | %c\n", board[0], board[1], board[2]); + fprintf(s,"----------\n"); + fprintf(s,"%c | %c | %c\n", board[3], board[4], board[5]); + fprintf(s,"----------\n"); + fprintf(s,"%c | %c | %c\n", board[6], board[7], board[8]); +} |