//bat6ok.c  -- @CopyLeft by tsaiwn@csie.nctu.edu.tw
//BATtle of NUMbers
//modified by __學號__  _姓_名_  and  __學號__  _姓_名_ 
///
// 若用 Java 則須用 class 包起來; class名稱須與檔案名稱相同 !
// 且 main 必須 public static void main(String xxx[ ]) {
#define repeat  do {
#define until(x)   } while(! (x) )

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

#define MAX_STONE 31
#define MIN_STONE 18
#define MAX_TAKE 9
//Java 內以上須用這樣 public final static int MAX_TAKE = 9;

#ifndef __cplusplus
  typedef enum {false=0, true } bool; // C 不認識 這些
#endif

// 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 is taking the stone? 輪到誰?
  // Java 的 enum 請看本檔案最後的補充 ! 
void hello( ), prepareGame( ), playGame( );
bool askUserFirst( ), askPlayAgain( );
void userTurn( ), computerTurn( );
void randomize( ) { srand(time(0));  } // 抓時間來當作亂數種子

int main( ) {
   hello( ); 
   randomize( );  // randomize; make it true random
   repeat
      prepareGame( );
      userFirst = askUserFirst( );
      playGame( );
      playAgain = askPlayAgain( );
   until( ! playAgain );
   printf("Thank you for your play.\r\n");
   return 0;
}

void hello( ) {  
   printf("Welcome to the BATNUM game ...\r\n");
}

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("\r\nThere are %d stones.\r\n", nStone);
   printf("At least take 1, at most %d stones.\r\n", maxTake);
   printf("The one who take the last stone will ");
   printf("%s\r\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( ) {
   bool userWin=true; // assume user win
   if(userFirst) userTurn( );
   else printf(" OK. I go first.\r\n");
   while(nStone > 0 ) {
      computerTurn( );
      if(nStone <= 0) break; // gameOver
      userTurn( );
   } // game Over when leave the while Loop
   userWin = true; // assume you win
   if(lastToWin && (who == COMPUTER) ) userWin = false; // user 輸!
   if( (!lastToWin) && (who == USER) ) userWin = false; // user 也是輸
   if(userWin) printf(" Congratulations! You win!\r\n");
   else printf(" Sorry, I won! Ha ha!\n");
} // playGame

void userTurn( ) { 
   int nTake, 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);
   fgets(buf, sizeof(buf), stdin);
   nTake = (int)atol(buf);  
   // check if the nTake is legal ?
   // .. 若不符規定則要求 USER 重新輸入
   // .. 也可寫成若輸入負數表示 give up, 就結束此 game :-(
   while(nTake < 1 || nTake > canTake) { // illegal
      printf("  ?? Error, please re-type(1..%d)? ", canTake);
      fgets(buf, sizeof(buf), stdin);
      nTake = (int)atol(buf);  
   }
   nStone -= nTake;
   if(nStone == 0) printf(" You just took the last stone.\r\n");
   else printf(" %d stone(s) left.\r\n", nStone);
   return;
} // userTurn

void computerTurn( ) {
   int nTake = 1;
   who = COMPUTER;  // now is COMPUTER 's turn 記住輪到 COMPUTER
   // 必贏的策略?  須考慮拿最後一個贏還是輸
   nTake = nStone;
   if(!lastToWin) nTake--;  // 拿最後一個是輸ㄝ, 留一個給對手
   nTake = nTake % (1+maxTake);
   if(nTake == 0) nTake = 1; // 電腦會輸, 先賴皮拿一個等對手拿錯:-)
   if(nTake > nStone) nTake = nStone; // 沒那麼多! (不可能發生)
  ///
   nStone -= nTake;  // 拿走啊
   printf(" I take %d stone", nTake);
   if(nTake > 1) printf("s");  // 複數
   printf(" this time.");
   if(nStone == 0) printf(" I just took the last stone.\r\n");
   else printf(" Now %d stone(s) left.\r\n", nStone);
} // computerTurn
///   === === END of the program BATNUM === ===
/*** 關於 Java 的 enum: 在 C/C++ 的 enum 其實是整數, 可 Java 不是!
  Java 的 enum 是會變成 class ! 請編譯完後看看目錄中多出的 class 檔!
  以下是個簡單範例, 可編譯並且執行:
  //gg.java  -- test enum in Java, by tsaiwn@csie.nctu.edu.tw
  //avac gg.java
  //java gg
  //javap gg$player
  class gg {
       enum player {USER, COMPUTER}; 
    public static void main(String xx[ ]) {
       player yy = player.USER;
       System.out.println("user="+yy);
       if(yy == player.USER) System.out.println("YES yy is player.USER");
       else System.out.println("NO hahaha!");
    }//main
  } // class gg
*************************************************************/
