//bat2.c  -- @CopyLeft by tsaiwn@csie.nctu.edu.tw
//BATtle of NUMbers;   ==> try this:  TCC -DDEBUG bat2.c
#define repeat  do {
#define until(x)   } while(! (x) )
#define bool  int
#define TRUE (38==38)   // good idea, works even in Java Language
#define FALSE (38==49)   // C 不認識 true / false

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_STONE 31
#define MIN_STONE 15
#define MAX_TAKE 9

// define some global variables for the Game
int nStone; // number of Stone
int maxTake; // max stone to take for some game
bool lastToWin;  // Win or Lose if took last one stone?
bool userFirst, playAgain;
///
enum player {USER, COMPUTER};  // 這樣寫後面可以用USER/COMPUTER
enum player who; // who's turn? who is taking the stone? 輪到誰?

void hello( ), prepareGame( ), playGame( );
bool askUserFirst( ), askPlayAgain( );
void userTurn( ), computerTurn( );

int main( ) {
   hello( ); 
   srand(time(0));   // randomize; make it TRUE random
   repeat
      prepareGame( );
      userFirst = askUserFirst( );
      playGame( );
      playAgain = askPlayAgain( );
   until( ! playAgain );
   printf("Thank you for your play.\n");
   return 0;
}
void hello( ) {  
}
void prepareGame( ) {
   char msg[ ][88]={"Lose the game.", "win the game."};
   nStone = MIN_STONE + rand( ) % (MAX_STONE-MIN_STONE+1);
   maxTake = 3 + rand( ) % (MAX_TAKE -3 +1);  // 3..
   lastToWin = (rand( )%2 == 1);  // half chance 一半的機會
   printf("\nThere are %d stones.\n", nStone);
   printf("At least take 1, at most %d stones.\n", maxTake);
   printf("The one who take the last one will ");
   printf("%s\n", msg[lastToWin]); // 拿最後一個輸還是贏?
#ifdef DEBUG
   printf("lastToWin=%d\n", lastToWin);
#endif
} // prepareGame
bool askUserFirst( ) {
   static char buf[99];
   fprintf(stderr, "Do you want to go first(Y, N)? ");
   fgets(buf, sizeof(buf), stdin);
   if(buf[0]=='N' || buf[0]=='n') return FALSE; //no
   if(buf[0]==0) return FALSE;  // no!  C不認識 true/false
   return TRUE;  //  Yes otherwise
}
bool askPlayAgain( ) {
   static char buf[99];
   fprintf(stderr, " Play again(Y, N)? ");
   fgets(buf, sizeof(buf), stdin);
   if(buf[0]=='N' || buf[0]=='n') return FALSE; //no
   if(feof(stdin)) return FALSE;  // EOF encounted
   return TRUE;  // Yes
} // askPlayAgain
void playGame( ) {
   int userWin=1; // Local variable is enough here
   if(userFirst) userTurn( );   // userFirst 是 global variable
   else printf(" OK. I go first.\n");
   while(nStone > 0 ) {
      computerTurn( );
      if(nStone <= 0) break; // gameOver
      userTurn( );
   } // game Over when leave the while Loop
   userWin = 1; // assume USER win
   if(lastToWin && (who == COMPUTER) ) userWin = 0; // 這樣 USER 輸!
   if( (!lastToWin) && (who == USER) ) userWin = 0; // USER 也是輸
   if(userWin) printf(" Congratulations! You win!\n");
   else printf(" Sorry, I won! Ha ha!\n");
} // playGame
void userTurn( ) { 
   int nTake, canTake;  // canTake 是要算出這次可拿幾個?
   static char buf[99];
   who = USER;  // now USER 's turn  記住輪到 USER
   canTake = maxTake;  // 照規定最多只能拿取 maxTake
   if(nStone < maxTake) canTake = nStone;  // 沒那麼多了
   printf(" How many you want to take(1..%d)? ", canTake);
   //讀取 USER 要拿幾個, then check if the nTake is leagle ?
   // .. 若不符規定則要求 USER 重新輸入, 直到 nTake 合乎規定
   // .. 也可寫成若輸入負數表示 USER give up, 就結束此 game :-(
   nStone -= nTake;   // 阿就拿走 nTake 個啊
   if(nStone == 0) printf(" You just took the last stone.\n");
   else printf(" %d stone(s) left.\n", nStone);
   return;
} // userTurn
void computerTurn( ) {
   int nTake = 1;
   who = COMPUTER;  // now is COMPUTER 's turn 記住輪到 COMPUTER
   nTake = 1 + nStone % maxTake;   // 隨便拿
   if(nTake > nStone) nTake = nStone; // 沒那麼多! 只剩 nStone 個
   // 請改為可以贏就要贏
   // 必贏的策略?  須考慮拿最後一個贏還是輸
   /// 這策略很簡單! 先令 nTake = nStone;
   ///  然後若拿最後一個是輸則令 nTake = nTake - 1; 表留一個給對手拿
   ///   再來, 令 nTake = nTake % (1+maxTake); 這樣拿就會贏
   ///   若是算出 nTake 為 0 則表示必輸的, 就先拿一個等對手出錯!
   /// ///
   nStone -= nTake;   // 阿就拿走 nTake 個啊
   // print out some message
   return;
} // computerTurn
