/* * Playground+ - ttt.c * TicTacToe game written by Bron Gondwana * * The Mind Of The Machine 1.3 by Urmas Rosenberg (aka Sassist) * Contact : uraes@ut.ee * --------------------------------------------------------------------------- * * Changes made: * - Modifications to presentation * - Changed to compile cleanly under PG+ flags * - Added 'ttt computer' */ /* headers */ #include <stdlib.h> #include <string.h> #include "include/config.h" #include "include/player.h" #include "include/proto.h" /* interns */ void ttt_end_game(player * p, int winner); void computer_move(player *p); //comment this, if you wanna make Machine to be no so smart #define SMART 1 /* the game!! */ int ttt_is_end(player * p) { int i, board[9], draw = 1; for (i = 0; i < 9; i++) { board[i] = (p->ttt_board >> (i * 2)) % 4; if (!(board[i])) draw = 0; } if ((board[0] && ((board[0] == board[1]) && (board[0] == board[2]))) || (((board[0] == board[3]) && (board[0] == board[6])))) return board[0]; if ((board[4] && ((board[4] == board[0]) && (board[4] == board[8]))) || (((board[4] == board[1]) && (board[4] == board[7]))) || (((board[4] == board[2]) && (board[4] == board[6]))) || (((board[4] == board[3]) && (board[4] == board[5])))) return board[4]; if ((board[8] && ((board[8] == board[2]) && (board[8] == board[5]))) || (((board[8] == board[7]) && (board[8] == board[6])))) return board[8]; if (draw) return 3; return 0; } void ttt_print_board(player * p) { int i, temp, gameover = 0; char *oldstack, cells[9]; oldstack = stack; if (!p->against_computer){ if (!(p->ttt_opponent)) { TELLPLAYER(p, " TTT: EEEK.. seems we've lost your opponent!\n"); return; } if (((p->ttt_board) % (1 << 17)) != ((p->ttt_opponent->ttt_board) % (1 << 17))) { TELLPLAYER(p, " TTT: EEEK.. seems like you're playing on different boards!\n"); ttt_end_game(p, 0); return; } }//end of against computer for (i = 0; i < 9; i++) { temp = ((p->ttt_board) >> (i * 2)) % 4; switch (temp) { case 0: cells[i] = ' '; break; case 1: cells[i] = 'O'; break; case 2: cells[i] = 'X'; break; default: TELLPLAYER(p, " TTT: EEEK.. corrupt board file!!\n"); return; } } if (!p->against_computer){ if (p->ttt_board & TTT_MY_MOVE) ADDSTACK(" It's your move - with the board as:\n\n"); else if (p->ttt_opponent->ttt_board & TTT_MY_MOVE) ADDSTACK(" %s to move - with the board as:\n\n", p->ttt_opponent->name); else { ADDSTACK(" The final board was:\n"); gameover++; } } else //end of against_computer if (p->ttt_board & TTT_MY_MOVE) ADDSTACK(" It's your move - with the board as:\n\n"); else { ADDSTACK(" The final board was:\n"); gameover++; } ADDSTACK(" +-------+ +-------+\n"); for (i = 0; i < 9; i += 3) { ADDSTACK(" | %c %c %c | | %d %d %d |\n", cells[i], cells[i + 1], cells[i + 2], i + 1, i + 2, i + 3); } ADDSTACK(" +-------+ +-------+\n"); if (!gameover) { if (p->ttt_board & TTT_AM_NOUGHT) { ADDSTACK(" You are playing NOUGHTS\n"); } else { ADDSTACK(" You are playing CROSSES\n"); } } stack++; TELLPLAYER(p, oldstack); stack = oldstack; } void ttt_end_game(player * p, int winner) { int plyr = 1; if ((!(p->ttt_opponent)) && (!p->against_computer)) { TELLPLAYER(p, " TTT: EEEK.. seems we've lost your opponent!\n"); return; } if (!(p->ttt_board & TTT_AM_NOUGHT)) plyr++; tell_player(p,"END\n"); if (!p->against_computer) { if (winner == 3) { TELLPLAYER(p, " Your TTT game with %s is a draw.\n", p->ttt_opponent->name); TELLPLAYER(p->ttt_opponent, " Your TTT game with %s is a draw.\n", p->name); p->ttt_draw++; (p->ttt_opponent)->ttt_draw++; } else if (winner && (winner != plyr)) { TELLPLAYER(p, " Doh!! You lost TTT to %s.\n", p->ttt_opponent->name); TELLPLAYER(p->ttt_opponent, " Yippee!! You beat %s at TTT.\n", p->name); p->ttt_loose++; (p->ttt_opponent)->ttt_win++; } else if (winner) { TELLPLAYER(p, " Yippee!! You beat %s at TTT.\n", p->ttt_opponent->name); TELLPLAYER(p->ttt_opponent, " Doh!! you lost TTT to %s.\n", p->name); p->ttt_win++; (p->ttt_opponent)->ttt_loose++; } else { TELLPLAYER(p, " You abort your TTT game against %s.\n", p->ttt_opponent->name); TELLPLAYER(p->ttt_opponent, " %s aborts your TTT game.\n", p->name); } } else //if against_computer { if (winner == 3) { tell_player(p, " Your TTT game against computer is a draw.\n"); p->ttt_draw++; } else if (winner && (winner != plyr)) { tell_player(p, " Doh!! You lost TTT to computer.\n"); p->ttt_loose++; } else if (winner) { tell_player(p, " Yippee!! You beat The Mind Of The Machine at TTT.\n"); p->ttt_win++; } else { tell_player(p, " You abort your TTT game against computer.\n"); } }//end of against_computer p->ttt_board &= ~TTT_MY_MOVE; if (!p->against_computer) p->ttt_opponent->ttt_board &= ~TTT_MY_MOVE; ttt_print_board(p); if (!p->against_computer) ttt_print_board(p->ttt_opponent); if (!p->against_computer){ p->ttt_opponent->ttt_opponent = 0; p->ttt_opponent = 0; } if (p->against_computer) p->against_computer=0; } void ttt_new_game(player * p, char *str) { player *p2; if (!*str) { TELLPLAYER(p, " Format: ttt <player | computer>\n"); TELLPLAYER(p, " ttt <commands>\n"); return; } /*Here starts The Mind Of The Machine*/ if (!strcmp(str , "computer")){ tell_player(p," You started TTT against The Mind Of The Machine\n"); p->against_computer=1; p->ttt_board = 0; p->ttt_board = TTT_MY_MOVE + TTT_AM_NOUGHT; computer_move(p); ttt_print_board(p); return; } p2 = find_player_global(str); if (!p2) return; #ifdef ROBOTS if (p2->residency & ROBOT_PRIV) { tell_player(p, " You cannot play TTT against a robot\n"); return; } #endif if (p == p2) { TELLPLAYER(p, " Do you have NO life??? Sheesh - Forget it...\n"); return; } if ((p2->ttt_opponent) || (p2->against_computer)) { TELLPLAYER(p, " Sorry, but %s is currently playing someone else\n", p2->name); return; } if (!p2->residency) { TELLPLAYER(p, " You can't play %s, because %s is not resident\n", p2->name, gstring(p2)); return; } p->ttt_board = 0; p2->ttt_board = TTT_MY_MOVE + TTT_AM_NOUGHT; p->ttt_opponent = p2; p2->ttt_opponent = p; TELLPLAYER(p2, " %s has offered a game of Tic Tac Toe (\"ttt abort\" to cancel)\n", p->name); ttt_print_board(p2); ttt_print_board(p); } void ttt_make_move(player * p, char *str) { int winner, temp; if (!*str) { TELLPLAYER(p, " You're playing a game, so\n Format: ttt <square to play>\n" " Type \"aborttt\" to abort this game\n"); return; } if(!p->against_computer){ if (((p->ttt_board) % (1 << 17)) != ((p->ttt_opponent->ttt_board) % (1 << 17))) { TELLPLAYER(p, " Seems you're playing on different boards!"); ttt_end_game(p, 0); } }//end of against_computer temp = atoi(str); if ((temp < 1) || (temp > 9)) { TELLPLAYER(p, " Please play to a square on the board!!\n"); ttt_print_board(p); return; } temp--; temp *= 2; if (p->ttt_board & (3 << temp)) { TELLPLAYER(p, " Sorry, that square is already taken.. please choose another\n"); ttt_print_board(p); return; } if (p->ttt_board & TTT_AM_NOUGHT) { p->ttt_board |= (1 << temp); if (!p->against_computer) p->ttt_opponent->ttt_board |= (1 << temp); } else { p->ttt_board |= (2 << temp); if(!p->against_computer) p->ttt_opponent->ttt_board |= (2 << temp); } if (!p->against_computer){ p->ttt_board &= ~TTT_MY_MOVE; p->ttt_opponent->ttt_board |= TTT_MY_MOVE; }//end of against_computer winner = ttt_is_end(p); if (winner) { ttt_end_game(p, winner); } else { if(p->against_computer){ computer_move(p); winner = ttt_is_end(p); if (winner) { ttt_end_game(p, winner); return; } } ttt_print_board(p); if(!p->against_computer) ttt_print_board(p->ttt_opponent); } } /***************************************************** * The Mind Of The Machine (which should be better) * * * *****************************************************/ int can_we_win(player *p, int xx, int oo){ int i,j,k,board[3][3],board2[9]; int x,o,buttons=0; for (i = 0; i < 9; i++) board2[i] = (p->ttt_board >> (i * 2)) % 4; for (j = 0; j < 3; j++) for (i = 0; i < 3; i++) board[j][i] = board2[j*3+i]; /*1.2 (19072000)*/ for (j = 0; j < 3; j++) for (i = 0; i < 3; i++) if ((board[j][i] == 1)||(board[j][i] == 2)) buttons++; //If on the board is 2 buttons... if (buttons==2){ //if both buttons are at the top of same diagonal if ((board[0][0]==1 && board[2][2]==2)|| (board[0][2]==1 && board[2][0]==2)|| (board[2][2]==1 && board[0][0]==2)|| (board[2][0]==1 && board[0][2]==2)|| //if they are at the top of same line (board[0][0]==1 && board[0][2]==2)|| (board[0][2]==1 && board[2][2]==2)|| (board[2][2]==1 && board[2][0]==2)|| (board[2][0]==1 && board[0][0]==2) ) return 5; //Yea! That's cool:) } /* Now.. do we have two crosses on the line so that the 3rd place is emty? If we have than let computer win that game */ /*Horizontal check*/ x=o=0; for (j = 0; j < 3; j++){ for (i = 0; i < 3; i++){ if (board[j][i] == 1) o++; if (board[j][i] == 2) x++; } if ((x==xx) && (o==oo)) {for(k=0;k<3;k++){ if (board[j][k]!=1 && board[j][k]!=2 && board[j][k]!=0){ tell_player(p,"There is some problem with board\n"); return -1; } if (board[j][k]==0){ return j*3+k+1; } } } x=o=0; } /*Vertical check*/ x=o=0; for (i = 0; i < 3; i++){ for (j = 0; j < 3; j++){ if (board[j][i] == 1) o++; if (board[j][i] == 2) x++; } if ((x==xx) && (o==oo)) {for(k=0;k<3;k++){ if (board[k][i]!=1 && board[k][i]!=2 && board[k][i]!=0){ tell_player(p,"There is some problem with board\n"); return -1; } if (board[k][i]==0){ return (k*3+i+1); } } } x=o=0; } /*Diagonaal '\' */ x=o=0; for (i = 0,j = 0; i < 3; i++,j++){ if (board[j][i] == 1) o++; if (board[j][i] == 2) x++; } if ((x==xx) && (o==oo)) { if (board[0][0]==0)return 1; if (board[1][1]==0)return 5; if (board[2][2]==0)return 9; tell_player(p,"There is an problem in mind of mashine(1)\n"); return -1; } /*Diagonaal '/' */ x=o=0; for (i = 0,j = 2; i < 3; i++,j--){ if (board[j][i] == 1) o++; if (board[j][i] == 2) x++; } if ((x==xx) && (o==oo)) { if (board[0][2]==0)return 3; if (board[1][1]==0)return 5; if (board[2][0]==0)return 7; tell_player(p,"There is an problem in mind of mashine(2)\n"); return -1; } /*Hmm..*/ /* Special situations (ver 1.3)*/ /* That is the last point where computer could make a mistake and let users to win. */ #ifdef SMART if(buttons==2){ if((board[0][1]==2 && board[2][2]==1)|| (board[0][1]==2 && board[2][0]==1)|| (board[2][1]==2 && board[0][0]==1)|| (board[2][1]==2 && board[0][2]==1)|| (board[1][0]==2 && board[0][2]==1)|| (board[1][0]==2 && board[2][2]==1)|| (board[1][2]==2 && board[0][0]==1)|| (board[1][2]==2 && board[2][0]==1))return 5; } #endif return -2; } void computer_move(player *p){ int temp,temp2=0,nowin=0,allright; allright=0; random(); while (!allright){ temp=(rand()%9)+1; /*Let's do random move*/ temp--; temp *= 2; /* * NEXT STEP : * xx==2 && oo==0 This is where computer can win. On the line * is two crosses and the third place is emty.. * * xx==0 && oo==2 Oww. Player is near to win. Let's goin' to * to be evil.. the third place is emty and we can't win... * * xx==1 && oo==0 We have one cross on the line and we can't * win and player can't also so why must we choose square * randomly without check maybe there is better square to * choose. * */ if (!nowin) if ((temp2=can_we_win(p,2,0))<0) if ((temp2=can_we_win(p,0,2))<0) temp2=can_we_win(p,1,0); if (temp2 < 0)nowin = 1; /*Just incase*/ if (!nowin) if (temp2>0){ temp = temp2; temp--; temp *=2; } if (!(p->ttt_board & (3 << temp))) { p->ttt_board |= (2 << temp); allright=1; } }/*while allright*/ } /* wrappers */ void ttt_print(player * p, char *str) { if ((!p->ttt_opponent) && (!p->against_computer)) TELLPLAYER(p, " But you aren't playing a game!"); else ttt_print_board(p); } void ttt_abort(player * p, char *str) { if ((!p->ttt_opponent) && (!p->against_computer)) TELLPLAYER(p, " But you aren't playing a game!\n"); else ttt_end_game(p, 0); } void ttt_ver(player *p){ tell_player(p,"\n -=> Tic Tac Toe by Bron Gondwana\n"); #ifdef SMART tell_player(p," -=> The Mind Of The Machine 1.3 (SMART)(08112001) by Urmas Rosenberg\n"); #else tell_player(p," -=> The Mind Of The Machine 1.3 (08112001) by Urmas Rosenberg\n"); #endif } void ttt_commands(player *p){ tell_player(p," Tic Tac Toe with T.M.O.T.M. - Commands\n"); tell_player(p," ttt <player | computer>\n" " ttt version\n" " ttt abort\n" " ttt print\n" " ttt [square]\n" " ttt commands\n"); } /* Yuk!!! This should be written as ttt <sub_command>! Oh well, some peoples programing style ... --Silver */ void ttt_cmd(player * p, char *str) { if (!strcmp(str, "version")) ttt_ver(p); else if (!strcmp(str, "commands")) ttt_commands(p); else if ((!(p->ttt_opponent)) && (!p->against_computer)) ttt_new_game(p, str); else if (!strcmp(str, "abort")) ttt_abort(p, ""); else if (!strcmp(str, "print")) ttt_print(p, ""); else if (p->ttt_board & TTT_MY_MOVE) ttt_make_move(p, str); else { TELLPLAYER(p, " Sorry, but %s gets to make the next move\n", p->ttt_opponent->name); ttt_print_board(p); } } /* Mind you I suppose it does have its advantages ... */