summaryrefslogtreecommitdiff
path: root/pgm7/TTT.c
diff options
context:
space:
mode:
Diffstat (limited to 'pgm7/TTT.c')
-rw-r--r--pgm7/TTT.c282
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]);
+}