/*
* nttt.c - TCP/IP TIC TAC TOE by r4lph
* You guessed it. Tic tac toe, taken to the next level. Play your
* friends, play your mom, even play so1o! Works on *BSD* and Linux
* as far as I know. Mail r4lph@b4b0.org if it works on your non
* *BSD*\Linux system. If you don't like something in the code,
* for christs sake, don't tell me, just change it. Don't distribute
* modified versions, blah blah blah. The connector will always be
* X and the connected to will be O.
* compile: cc -O2 -o nttt nttt.c
* Have fun.
* Oct. 18/1998
* r4lph <r4lph@b4b0.org>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
/* defines */
#define X 1
#define O 0
#define PORT 9876
/* color defines */
#define END "[0m"
#define RED "[1;31m"
#define GREEN "[1;32m"
#define BLUE "[1;34m"
#define BOLDWHITE "[38m"
#define BGRED "[1;41m"
/* function prototypes */
int main(int argc, char *argv[]); /* duh */
unsigned long getip(char *hostname); /* resolve hostname */
void initiate(unsigned long ip); /* initiate a connection */
void wait_for_connection(void); /* listen for a connection */
void usage(char *name); /* -h */
void play_ttt(void); /* main ttt function */
void draw(void); /* draw the grid on the screen */
void x_input(void); /* input X value */
void o_input(void); /* input O value */
void x_plot(int x_coord); /* update the grid */
void o_plot(int o_coord);
void sync_players(void); /* synchronize players */
int continue_ttt(void);
int check(char xoro); /* check for winner */
void color_fix(int sig); /* signal handler */
void reset_ttt(void); /* reset the ttt grid */
/* global socket descriptors BADBADBAD! */
int sockfd, newsockfd, sfd;
/* two dimensional array for ttt grid */
char ttt[3][3] = {{'1','2','3'},{'4','5','6'},{'7','8','9'}};
/* player info struct */
struct players {
char remote[10]; /* usernames */
char local[10];
int x_or_o; /* are we X or O? */
}player;
/* duh */
int main(int argc, char *argv[])
{
int arg;
int cont = 1;
signal(SIGKILL, color_fix);
signal(SIGINT, color_fix);
if(argc < 2)
usage(argv[0]);
while((arg=getopt(argc, argv, "i:lh")) != EOF)
{
switch(arg)
{
case 'i': /* initiate */
{
printf("%splayername>%s%s ",BOLDWHITE,END,RED);
scanf("%9s", player.local);
initiate(getip(optarg));
while(cont == 1)
{
reset_ttt();
sync_players();
play_ttt();
cont = continue_ttt();
}
close(sockfd);
printf("%s", END);
exit(0);
}
case 'l': /* listen */
{
printf("%splayername>%s%s ",BOLDWHITE,END,RED);
scanf("%9s", player.local);
wait_for_connection();
while(cont == 1)
{
reset_ttt();
sync_players();
play_ttt();
cont = continue_ttt();
}
close(sockfd);
printf("%s", END);
exit(0);
}
case 'h':
{
usage(argv[0]);
}
default:
{
usage(argv[0]);
}
}
}
return(0);
}
unsigned long getip(char *hostname)
{
struct hostent *he;
if((he=gethostbyname(hostname)) == NULL) /* get that smaq */
{
herror("gethostbyname");
printf("%s", END);
exit(1);
}
return(inet_addr(inet_ntoa(*((struct in_addr *)he->h_addr)))); /* yuck. */
}
void usage(char *name)
{
fprintf(stderr, "%s%sTCP/IP TIC TAC TOE by r4lph%s\n",BGRED,BLUE,END);
fprintf(stderr, "%susage: %s -l [ listen for a connection ]\n",BLUE, name);
fprintf(stderr, " %s -i < remote host > [ initiate a connection ]\n", name);
fprintf(stderr, " %s -h [ help ]%s\n", name, END);
exit(0);
}
void draw(void)
{
(void)system("clear");
printf("\n\n\n\n\n\n\n\n\n\n");
printf("\t\t\t %s%c%s º %s %c %s º %s%c\n",BLUE,ttt[0][0],RED,BLUE,ttt[0][1],RED,BLUE,ttt[0][2]);
printf("\t\t\t %sÍÍÍÎÍÍÍÍÍÎÍÍÍ%s\n",RED,END);
printf("\t\t\t %s%c%s º %s %c %s º %s%c\n",BLUE,ttt[1][0],RED,BLUE,ttt[1][1],RED,BLUE,ttt[1][2]);
printf("\t\t\t %sÍÍÍÎÍÍÍÍÍÎÍÍÍ%s\n", RED, END);
printf("\t\t\t %s%c%s º %s %c %s º %s%c\n",BLUE,ttt[2][0],RED,BLUE,ttt[2][1],RED,BLUE,ttt[2][2]);
}
int continue_ttt(void)
{
char c;
printf("\n%s\t\t Play another game? (y)es/(n)o:%s%s ",BOLDWHITE,END,RED);
scanf("%1s", &c); /* PLEEZE SEY YES !@# */
if(c == 'y' || c == 'Y')
return(1);
else
return(0);
}
void reset_ttt(void)
{
ttt[0][0] = '1'; /* OINK */
ttt[0][1] = '2';
ttt[0][2] = '3';
ttt[1][0] = '4';
ttt[1][1] = '5';
ttt[1][2] = '6';
ttt[2][0] = '7';
ttt[2][1] = '8';
ttt[2][2] = '9';
}
void initiate(unsigned long ip)
{
struct sockaddr_in remote;
player.x_or_o = X; /* we are X */
bzero(&remote, sizeof(struct sockaddr_in));
remote.sin_family = AF_INET;
remote.sin_port = htons(PORT);
remote.sin_addr.s_addr = ip;
if((sfd=socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
printf("%s", END);
exit(1);
}
printf("%s%sWaiting for player...%s\n",END,BOLDWHITE,END);
if(connect(sfd, (struct sockaddr *)&remote, sizeof(struct sockaddr)) == -1)
{
perror("connect");
printf("%s", END);
close(sfd);
exit(1);
}
send(sfd, player.local, sizeof(player.local), 0);
recv(sfd, player.remote, sizeof(player.remote), 0);
printf("%s%sConnection established with%s%s %s [ %s ]%s\n",END,BOLDWHITE,END,RED,player.remote
,inet_ntoa(remote.sin_addr.s_addr),END);
sleep(2);
}
void wait_for_connection(void)
{
struct sockaddr_in remote;
struct sockaddr_in local;
int addrlen;
player.x_or_o = O; /* we are O */
addrlen = sizeof(struct sockaddr_in);
bzero(&remote, sizeof(struct sockaddr_in));
bzero(&local, sizeof(struct sockaddr_in));
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
local.sin_addr.s_addr = INADDR_ANY;
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
printf("%s", END);
exit(1);
}
if(bind(sockfd, (struct sockaddr *)&local, sizeof(struct sockaddr)) == -1)
{
perror("bind");
printf("%s", END);
close(sockfd);
exit(1);
}
if(listen(sockfd, 1) == -1)
{
perror("listen");
printf("%s", END);
close(sockfd);
exit(1);
}
printf("%s%sWaiting for player...\n%s",END,BOLDWHITE,END);
if((newsockfd=accept(sockfd, (struct sockaddr *)&remote, &addrlen)) == -1)
{
perror("accept");
printf("%s", END);
close(sockfd);
exit(1);
}
sfd = newsockfd;
recv(sfd, player.remote, sizeof(player.remote), 0);
send(sfd, player.local, sizeof(player.local), 0);
printf("%s%sConnection established with %s%s%s [ %s ]%s\n",END,BOLDWHITE,END,RED, player.remote
, inet_ntoa(remote.sin_addr.s_addr), END);
sleep(2);
}
void x_input(void)
{
int coord;
if(player.x_or_o == O)
{
recv(sfd, &coord, sizeof(coord), 0);
x_plot(coord);
draw();
return;
}
printf("\n");
printf("\t\t\t %s%sX>%s%s ",END,BOLDWHITE,END,RED);
scanf("%d", &coord); /* d0nt LOSE !@#$ */
send(sfd, &coord, sizeof(coord), 0);
x_plot(coord);
draw();
return;
}
void o_input(void)
{
int coord;
if(player.x_or_o == X)
{
recv(sfd, &coord, sizeof(coord), 0);
o_plot(coord);
draw();
return;
}
printf("\n");
printf("\t\t\t %s%sO>%s%s ",END,BOLDWHITE,END,RED);
scanf("%d", &coord);
send(sfd, &coord, sizeof(coord), 0);
o_plot(coord);
draw();
return;
}
void x_plot(int x_coord)
{
switch(x_coord)
{
case 1:
if(ttt[0][0] == 'o' || ttt[0][0] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[0][0] = 'x'; break;
case 2:
if(ttt[0][1] == 'o' || ttt[0][1] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[0][1] = 'x'; break;
case 3:
if(ttt[0][2] == 'o' || ttt[0][2] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[0][2] = 'x'; break;
case 4:
if(ttt[1][0] == 'o' || ttt[1][0] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[1][0] = 'x'; break;
case 5:
if(ttt[1][1] == 'o' || ttt[1][1] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[1][1] = 'x'; break;
case 6:
if(ttt[1][2] == 'o' || ttt[1][2] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[1][2] = 'x'; break;
case 7:
if(ttt[2][0] == 'o' || ttt[2][0] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[2][0] = 'x'; break;
case 8:
if(ttt[2][1] == 'o' || ttt[2][1] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[2][1] = 'x'; break;
case 9:
if(ttt[2][2] == 'o' || ttt[2][2] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, x_coord, END);
x_input();
}
else
ttt[2][2] = 'x'; break;
}
}
void o_plot(int o_coord)
{
switch(o_coord)
{
case 1:
if(ttt[0][0] == 'o' || ttt[0][0] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[0][0] = 'o'; break;
case 2:
if(ttt[0][1] == 'o' || ttt[0][1] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[0][1] = 'o'; break;
case 3:
if(ttt[0][2] == 'o' || ttt[0][2] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[0][2] = 'o'; break;
case 4:
if(ttt[1][0] == 'o' || ttt[1][0] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[1][0] = 'o'; break;
case 5:
if(ttt[1][1] == 'o' || ttt[1][1] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[1][1] = 'o'; break;
case 6:
if(ttt[1][2] == 'o' || ttt[1][2] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[1][2] = 'o'; break;
case 7:
if(ttt[2][0] == 'o' || ttt[2][0] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[2][0] = 'o'; break;
case 8:
if(ttt[2][1] == 'o' || ttt[2][1] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[2][1] = 'o'; break;
case 9:
if(ttt[2][2] == 'o' || ttt[2][2] == 'x')
{
printf("%s\t\t\tLocation %d is occupied%s",BOLDWHITE, o_coord, END);
o_input();
}
else
ttt[2][2] = 'o'; break;
}
}
void sync_players(void)
{
char buf[7];
if(player.x_or_o == X)
{
send(sfd, "sync", 5, 0);
recv(sfd, buf, sizeof(buf), 0);
if(strcmp("synced", buf) != 0)
{
fprintf(stderr, "%sCouldn't sync!%s\n", BOLDWHITE, END);
close(sfd);
exit(1);
}
}
if(player.x_or_o == O)
{
recv(sfd, buf, sizeof(buf), 0);
if(strcmp("sync", buf) != 0)
{
fprintf(stderr, "%sCouldn't sync!%s\n", BOLDWHITE, END);
close(sfd);
exit(1);
}
send(sfd, "synced", 7, 0);
}
}
void play_ttt(void)
{
int c = 0;
draw();
for(;;)
{
x_input();
if(check('x'))
return;
c++; /* heh */
if(c==9)
{
return;
}
o_input();
if(check('o'))
return;
c++; /* heh? */
if(c==9)
{
return;
}
}
}
int check(char xoro) /* sorta sounds like porno */
{
int blah;
if(xoro=='x')
blah = X;
if(xoro=='o')
blah = O;
if(ttt[0][0]==xoro && ttt[0][1]==xoro && ttt[0][2]==xoro)
{
if(player.x_or_o==blah)
{
printf("\n%s\t\t\t YOU WIN %s%s\n",GREEN, player.local, END);
return(1); /* bewm */
}
printf("\n%s\t\t\t YOU LOSE %s%s\n",GREEN, player.local, END);
return(1);
}
if(ttt[1][0]==xoro && ttt[1][1]==xoro && ttt[1][2]==xoro)
{
if(player.x_or_o==blah)
{
printf("\n%s\t\t\t YOU WIN %s%s\n",GREEN, player.local, END);
return(1);
}
printf("\n%s\t\t\t YOU LOSE %s%s\n",GREEN, player.local, END);
return(1);
}
if(ttt[2][0]==xoro && ttt[2][1]==xoro && ttt[2][2]==xoro)
{
if(player.x_or_o==blah)
{
printf("\n%s\t\t\t YOU WIN %s%s\n",GREEN, player.local, END);
return(1);
}
printf("\n%s\t\t\t YOU LOSE %s%s\n",GREEN, player.local, END);
return(1);
}
if(ttt[0][0]==xoro && ttt[1][0]==xoro && ttt[2][0]==xoro)
{
if(player.x_or_o==blah)
{
printf("\n%s\t\t\t YOU WIN %s%s\n",GREEN, player.local, END);
return(1);
}
printf("\n%s\t\t\t YOU LOSE %s%s\n",GREEN, player.local, END);
return(1);
}
if(ttt[0][1]==xoro && ttt[1][1]==xoro && ttt[2][1]==xoro)
{
if(player.x_or_o==blah)
{
printf("\n%s\t\t\t YOU WIN %s%s\n",GREEN, player.local, END);
return(1);
}
printf("\n%s\t\t\t YOU LOSE %s%s\n",GREEN, player.local, END);
return(1);
}
if(ttt[0][2]==xoro && ttt[1][2]==xoro && ttt[2][2]==xoro)
{
if(player.x_or_o==blah)
{
printf("\n%s\t\t\t YOU WIN %s%s\n",GREEN, player.local, END);
return(1);
}
printf("\n%s\t\t\t YOU LOSE %s%s\n",GREEN, player.local, END);
return(1);
}
if(ttt[0][0]==xoro && ttt[1][1]==xoro && ttt[2][2]==xoro)
{
if(player.x_or_o==blah)
{
printf("\n%s\t\t\t YOU WIN %s%s\n",GREEN, player.local, END);
return(1);
}
printf("\n%s\t\t\t YOU LOSE %s%s\n",GREEN, player.local, END);
return(1);
}
if(ttt[2][0]==xoro && ttt[1][1]==xoro && ttt[0][2]==xoro)
{
if(player.x_or_o==blah)
{
printf("\n%s\t\t\t YOU WIN %s%s\n",GREEN, player.local, END);
return(1);
}
printf("\n%s\t\t\t YOU LOSE %s%s\n",GREEN, player.local, END);
return(1);
}
return(0);
}
void color_fix(int sig)
{
printf("%s\n", END);
close(sfd);
exit(0);
}
syntax highlighted by Code2HTML, v. 0.9.1