
/********BATNUM -- BATtle of NUMbers, an old game ********/
/* by Wen-Nung Tsai. Written in Turbo C. */
/* tcc batnum.c */
/* TurBo C++ only ******/
#include <stdio.h>
#include <stdlib.h>
/* HUo conio.h u Turbo C++ ~ */
#include <conio.h>
#define not !
#define mod %
#define and &&
#define ord
#define repeat do{
#define until(expr)  }while(! (expr))
#define false 0
#define true 1
#define then
#define begin {
#define end }
#define ELSE ;else
#define procedure void
#define write cprintf
#define writeln cprintf
#define readln gets        /* note taht cgets has different syntax */
#define ReadKey getch()
typedef int bool;
typedef unsigned char byte;
typedef char str40[41];
const
    char whowin[][5] =  {"loss", "win "};
/* var */
 int totalStone, maxtotake;
 int c1,c2;   str40 tmpstr; /* used for readln */
 char * pstr;
 bool user_first, user_win, last_to_win;   /* FLAGs */
procedure hello(void);
procedure prepare_stone(void);
procedure ask_who_go_first(void);
procedure computer_turn(void);
procedure user_turn(void);
/*****************************************************************/
procedure hello(void)
begin
     writeln(" Welcome to play BATNUM --- BATtle of NUMbers,\n\r");
     writeln("                 ---------- by tsaiwn@csie.nctu\n\r");
end;
procedure prepare_stone(void)
begin
     totalStone  =  random(20) + 11;   /* 11..30 */
     maxtotake   =  3 + random(4);     /* 3..6 */
     last_to_win =  true;
     if( random(100) < 50) then last_to_win  =  false;
end;
procedure ask_who_go_first(void)
begin
     write("Initially, we have ");    /* tell him the status */
     textcolor(YELLOW); write("%d",totalStone);
     normvideo();
     writeln(" stones.\n\r");
     writeln("At least take 1. At most take %d.\n\r",maxtotake);
     write("The one who takes ");
     textcolor(LIGHTRED+BLINK);
     writeln("last stone to %s.\n\r", whowin[last_to_win]);
     normvideo(); write(  "You want to go first(N,Y)? "); /* default is No */
     c1 = ReadKey; if(ord(c1)==0)then c2 = ReadKey;
     writeln("%c\n\r",c1);
     user_first = false; if(toupper(c1)=='Y') then user_first = true;
     if(not user_first) then writeln("OK. I go first.\n\r");
end;
procedure computer_turn(void)
 /*var */
begin
  int  metake,tmp;
     tmp  =  totalStone;
     if(not last_to_win) then tmp =  tmp-1;   /* take last stone to loss */
     metake =  tmp mod (1+ maxtotake);  /* try my best to WIN */
     if( metake == 0) then metake = 1;    /* seems that I will loss this game */
     totalStone  =  totalStone - metake;
     writeln("I take %d.\n\r",metake);
     if( totalStone==0) then begin   /* last stone took by computer */
	writeln("I just took the last stone.\n\r");
	user_win =  true;  /* assume take last to loss */
	if(last_to_win) then user_win =  false; /* I won */
     end else begin
	write("There ");
	if(totalStone>1)then write("are ") ELSE write("is ");
	textcolor(YELLOW); write("%d",totalStone);
	normvideo();   write(" stone");
	if(totalStone>1)then write("s");
	writeln(" left.\n\r");
     end;/*if totalS..*/
end;
procedure user_turn(void)
begin
long lnumber; char * endptr;
  int num_can_be,heTake,errorcode; bool ask_before;
     num_can_be = maxtotake;  ask_before = false;
     if(num_can_be > totalStone) then num_can_be  =  totalStone;
     repeat
	if(ask_before) then write(" Error, ");
	write("How many you take(1..%d)? ",num_can_be);
	readln(tmpstr); ask_before =  true;
	/*  val(tmpstr,heTake, errorcode);   /***/
	lnumber = strtol(tmpstr, &endptr, 10);
	heTake = (int) lnumber;

     until( (heTake >=1) and (heTake <= num_can_be) );
     /* accept only legal move */
     totalStone  =  totalStone - heTake;
end;
procedure play_BATNUM(void)
begin
   if (not user_first) then computer_turn();
   while( totalStone > 0)  begin
      user_turn();
      if( totalStone==0) then begin
	 writeln("You just took the last stone.\n\r");
	 user_win =  false;  /* assume take last to loss */
	 if(last_to_win) then user_win =  true;
      end;
      if( totalStone > 0) then computer_turn();
   end;  /* take turn until no more stone */
   /* game over */
end;
int main(void)
{    /* main */
   randomize();
   repeat
      window(1,1,80,25); clrscr();
      hello();    window(40,3,77,9);
      prepare_stone();   ask_who_go_first();    window(1,5,39,24);
      play_BATNUM();
      if( user_win) then writeln("Congratulations! You Win!\n\r")
      ELSE begin
	   writeln("Ar-Ha! I win!\n\r");
	   sound(350); delay(500); sound(300); delay(400); sound(250);
	   delay(500); nosound(); delay(500);
      end;
      write("Play more(Y,N)? ");
      c1 = ReadKey; if(ord(c1)==0)then c2 = ReadKey;
      printf("%c\n\r\n\r",c1);
   until( toupper(c1)== 'N');
   writeln("Bye Bye!\n\r");
   normvideo(); return 0;
}
