#include<stdio.h>
//#define TRUE_RANDOM
#define xor ^
#define bool int
#define  MIN_PILE  2
#define  MAX_PILE  7
#define  MIN_STONE 7
#define  MAX_STONE 30
int myrandom(int lower, int upper);
void hello(), byebye();
void playNIM();
int main(){
   static char yesNo[99];
   hello();
   while(38){
      playNIM();
      fprintf(stderr, "Play again (Y,N): ");
      fgets(yesNo, 99, stdin);
      if( toupper(yesNo[0]) == 'N') break;
   }
   byebye();
}
int nPile,takeP,takeN;
int pile[MAX_PILE+2];
int userFirst;
int lastWin;
char tmp99[99];
void prepareStones();
void tellStatus();
bool gameOver();
void userTurn();
void computerTurn();
void playNIM(){
      static char yesNo[99];
    prepareStones();
    tellStatus();
    fprintf(stderr, "take last one to ");
    if(lastWin) fprintf(stderr, "Win!\n");
    else fprintf(stderr, "Lose!\n");
    userFirst = 1;
    fprintf(stderr, "Want to go first(Y,N)? ");
    fgets(yesNo, 99, stdin);
    if( toupper(yesNo[0]) == 'N') userFirst = 0;
    if(userFirst)
        userTurn();
    while(49){
        if(gameOver()){   /* user takes the last one */
            if(lastWin) printf("Congratulations! You win!\n");
            else printf("Ahh Ha! I win!\n");
            break;
        }
        computerTurn();
        if(gameOver()){
            if(lastWin) printf("Ahh Ha! I win!\n");
            else printf("Congratulations! You win!\n");
            break;
        }
        userTurn();
    } /* while(49) */
} /* playNIM */
bool gameOver( ){
     int i;
   int sum = 0; 
   for(i=1; i<= nPile; i++){
       sum += pile[i];
   }
   return sum == 0;    /* no stones left */
}
  /*****************/
void prepareStones(){
    int i;
    nPile = myrandom(MIN_PILE, MAX_PILE);
    for(i=1; i<= nPile; ++i){
        pile[i] = myrandom(MIN_STONE, MAX_STONE);
    }
    lastWin = 0;
    if( myrandom(0, 100) > 50) lastWin = 1;
   /***
     sound(400);  delay(200);  nosound;
      ***/
}
  /******/
bool leagleMove(int p, int n){
    if(p<1 || p > nPile) return 0;
    if(n<1 || n > pile[p]) return 0;
    return 1;
}
void tellStatus(){
    int i, ktemp;
    printf("There are %d piles of each has ", nPile);
    for(i=1; i<= nPile; ++i){
        printf( "  %d", pile[i]);
    }
    printf(" stones.\n");
}
void userTurn(){
    /** make sure the player makes a legal move **/
    int i, ktemp;
    tellStatus();
    do {
        /** sound(400);  delay(200);  nosound;  /*** ***/
       printf("Which Pile? ");
       gets(tmp99); takeP = atoi(tmp99);
       ktemp = 0; 
       if(leagleMove(takeP, 1) ) ktemp= pile[takeP];
       printf("How many stones in this pile?(1..%d) ", ktemp);
       gets(tmp99); takeN = atoi(tmp99);
    } while( ! leagleMove(takeP, takeN) );
    pile[takeP] -=  takeN;
    return;
} /* userTurn */
 /***************************/
void computerTurn(){          /* try to win if possible */
    int i;
    takeN = pile[1];   /* assume All stones in 1st pile is OK */
    /* first of all, calculate how many stones will the xor result be? */
    for(i=2; i<= nPile; ++i) takeN = takeN ^ pile[i];   /* xor */
    if( takeN == 0) {  /* I can Not win :-<  */
        /* I am supposed to lose so far. So just take one stone. */
        takeP = 1; takeN = pile[takeP];   /* takeN 暫時記住最多幾個stone */
        for(i=2; i<=nPile; ++i){
            if( pile[i] > takeN){
               takeP=i;  takeN= pile[takeP];
            }
        }
        takeN = 1;
    }else{
       /* now decide which pile we can remove some stones to win*/
       for(i = nPile; i>=1; --i){
           if ( (takeN xor pile[i]) < pile[i] ) takeP=i;
       }
       /* now calculate 真正該拿之石頭數 */
       takeN = pile[takeP] - (pile[takeP] xor takeN);    /***重要***/
    } /* if( takeN ==0 ... */
    pile[takeP] = pile[takeP] - takeN;
    fprintf(stderr, "Computer takes %d from pile %d\n", takeN, takeP);
    return;
}
void hello(){
    fprintf(stderr, "This is an old game of NIM.\n");
    fprintf(stderr, "You should pick up at least one stone.\n");
    fprintf(stderr, "And you can take at most all stones in one pile.\n");
}
void byebye(){
    fprintf(stderr, "\nThank you for playing NIM :-)\n");
}
int myrandom(int lower, int upper){
    static int firstFlag = 0;
#ifdef TRUE_RANDOM
    if(firstFlag == 0){
        srand( time(0) & 0xffff );
        ++firstFLAG;
    }
#endif
    int ans = rand() % (upper-lower+1);
    ans += lower;
    return ans;
}
