/****** HIT & BLOW game ******/
/*                           */
/*      COPYRIGHT 1989,1991  */
/*                 H.Asano   */
/*               1989.09.12  */
/*               1991.01.17  */
/*               1991.02.28  */
/*****************************/
#include <stdio.h>
#include <stdlib.h>

#define  OK   0
#define  NG  (-1)

static int comatr, opeatr, qesno;
static char comsu    [4+1];
static char opesu    [4+1]   ;
static char opesuinit[4+1]   ;
char        hitsu2   [BUFSIZ];
char        blowsu2  [BUFSIZ];

main()
{
 void hb10000(),hb20000(),hb21100(),hb30000(),hb40000();

 /** process **/

      hb10000();   /* initialize */
      while(comatr==0 || opeatr==0)
      {
        qesno+=1;
	if(qesno==14) {
	  printf("\x01b[20;5H疲れたでしょう。もうやめましょうね。\n");
	  hb21100();
	}
	if(comatr==0) hb20000();
        if(opeatr==0) hb30000();
      }
      hb40000() ;  /* terminate */
}

/***** hb10000()  initialize routine ****/

void hb10000()
{
 int i;
 void hb11000() ;

  printf("\x01b*");
  printf("\t====== HIT & BLOW [V1.1] ======  (Copyright 1991 H.Asano)\n");
  printf("\n");
  printf("\t\t----------------------------------\n");
  printf("\t\t| 回数 | 計算機の数 | あなたの数 |\n");
  printf("\t\t-------|------------|------------|\n");
  for(i=1;i<14;i++)
    printf("\t\t| %4d |            |            |\n",i);
  printf("\t\t----------------------------------\n");

  hb11000();   /* generate computer number */
  qesno=0; comatr=0; opeatr=0;
}
/****** hb11000() generate computer number routine ***/


void hb11000() 
{
 long now;

 void  hbbtc();
 unsigned int getrnd();

    srand(time(&now));
    hbbtc(getrnd(),comsu);
    hbbtc(getrnd(),opesu);
    memcpy(opesuinit,opesu,4);
}

/****** hb20000() computer number routine *****/

void hb20000()
{
  int hitsu, blowsu ;
  char situmonsu[4+1] ;
  void hb21000();
  void hbhb()   ;

      hb21000(situmonsu);
      hbhb(comsu,situmonsu,&hitsu,&blowsu);
      if(hitsu==4) {
        comatr=qesno;
	printf("\x01b[7m\x01b[%d;25H %s(4H0B)\x01b[m",qesno+5,situmonsu);
      }
      else 
	printf("\x01b[%d;25H %s(%1dH%1dB)\n",qesno+5,situmonsu,hitsu,blowsu);
}
        
/****** hb21000() computer number question routine ****/

void hb21000(situmonsu)
char *situmonsu;
{
 int keka  = NG   ;
 char indata[BUFSIZ] ;
 void hb21100() ;
 short hbctb()  ;

     while(keka==NG) { 
      printf("\x01b[20;5H\x01b[K計算機の数を当ててください? ");
      gets(indata);
      if(strcmp(indata,"0") == 0) hb21100() ;
      if((keka=hbctb(indata))!=NG) keka=hbchofk(indata);
     }
     strcpy(situmonsu,indata);
}

/****** hb21100() give up routine *****/

void hb21100() 
{
  printf("    計算機の数は %s でした｡\n",comsu);
  exit(0);
}

/****** hb30000() operator number routine ****/

void hb30000()
{
 int hitsu;
 int blowsu;
 void hb31000() ;
 void hb32000() ;

      hb31000(&hitsu,&blowsu);
      if(hitsu==4) {
	printf("\x01b[7m\x01b[%d;38H %s(4H0B)\x01b[m",qesno+5,opesu);
        opeatr=qesno;
        return;
      }
      hb32000(hitsu,blowsu) ;
}

/****** hb31000() operator number input routine ****/

void hb31000(hitsu,blowsu)
int *hitsu;
int *blowsu;
{
 int keka = NG  ;

     while(keka == NG)  {
       printf("\x01b[20;5H\x01b[Kあなたの数は %s ですか?",opesu);

       while(1){
	 printf("\x01b[20;32H\x01b[K H= ");
         memset(hitsu2,NULL,BUFSIZ);
         gets(hitsu2);
         if(hitsu2[0]=='\0' || strlen(hitsu2)>1) continue;
         if(hitsu2[0]>='0' && hitsu2[0]<='4')   {
           *hitsu=atoi(hitsu2);
           break;
         }
       }
       if(*hitsu==4 || *hitsu==3)    { 
         *blowsu=0 ;
         keka = OK ;
	 break    ;
       }
       while(1){
	 printf("\x01b[20;37H\x01b[K B= ");
         memset(blowsu2,NULL,BUFSIZ);
         gets(blowsu2);
         if(blowsu2[0]=='\0' || strlen(blowsu2)>1) break;
         if(blowsu2[0]>='0' && blowsu2[0]<='4')   {
           *blowsu=atoi(blowsu2);
           if(*hitsu+*blowsu <=4){
             keka = OK ;
             break ;
           }
         }else break;
       }
     }
     printf("\x01b[%d;38H %s(%1dH%1dB)",qesno+5,opesu,*hitsu,*blowsu);
     }

/****** hb32000() compute operator number routine *****/

void hb32000(hitsu,blowsu) 
int hitsu ;
int blowsu ;
{
 static char  q[11][4+1] ;
 static int  h[11] , b[11] ;
 int i;
 short wk;
 int repflg;
 int hit, blow;
 short hbctb();
 void hb21100() ;

    strcpy(q[qesno],opesu) ;
    h[qesno] = hitsu;
    b[qesno] = blowsu;
    i=1; repflg=NG;
    while(i<=qesno)  {
      while(repflg==NG)  {
        wk=hbctb(opesu);
        if(strcmp(opesu,"9876") == 0 ) {
          memcpy(opesu,"0123",4) ;
        }
        hbbtc(++wk,opesu) ;
        if(strcmp(opesu,opesuinit) == 0) {
	  printf("\x01b[20;5HあなたのHとBの返答に矛盾があるため続行できません｡\n");
          if(comatr==0) hb21100() ;
          else          exit(0)   ;
        }
        repflg=hbchofk(opesu);
      }
      hbhb(opesu,q[i],&hit,&blow);
      if(h[i]==hit && b[i]==blow) {
        i++; repflg=OK;
      }
      else {
        i=1 ; repflg=NG;
      }
    }
}
        
/****** hb40000() terminate routine *****/

void hb40000()
{
  if(comatr == opeatr) 
    printf("\x01b[20;5H\x01b[K引分けです。\n");
  else
    if(comatr > opeatr)
      printf("\x01b[20;5H\x01b[K計算機の勝ちです｡\n");
    else
      printf("\x01b[20;5H\x01b[Kあなたの勝ちです｡\n");
  exit(0);
}

/****** hbchofk() chofuku number  check routine ****/

int hbchofk(comsu)
char *comsu ;
{
int i, j ;

     for(i=0; i<3; i++)
       for(j=i+1; j<4; j++)
         if(comsu[i] == comsu[j])  return(NG) ;
     return(OK)  ;
}

/**** hbhb() compute hit & blow routine ****/

void hbhb(su1,su2,hitsu,blowsu)
char *su1;
char *su2;
int *hitsu;
int *blowsu;
{
 int i , j ;

    *hitsu=0; *blowsu=0;
    for(i=0; i<4; i++)
      for(j=0; j<4; j++)
        if(su1[i] == su2[j] && i==j)  {
          (*hitsu)++  ;
          break    ;
        }
        else  {
          if(su1[i] == su2[j])  {
            (*blowsu)++ ;
            break    ;
          }
        }
}

/**** hbbtc()  binary to charactor convert routine ***/

void hbbtc(num,str)
short num ;
char *str ;
{
  int i;

    for(i=3;i>=0;i--) {
      str[i] = num%10+'0' ;
      num = num/10        ;
    }
 }
  
/****** hbctb() convert charactor to binary  routine ******/

short hbctb(str)
char *str ;
{
 int i ;
 int num ;

     for(i=0; str[i] != 0; i++)
       if((str[i] < '0') || (str[i] > '9')) return(NG);
     if(i != 4) return(NG);
     for(num=0,i=0; str[i] != 0; i++)
       num=10*num+(str[i]-'0') ;
     return(num);
}
/*****************************/
unsigned int getrnd()
{
	unsigned	number;
	char		mojitime[5];

	memset(mojitime,NULL,5);
	while(1){
	   sprintf(mojitime,"%d",rand());
	   if(mojitime[0] != mojitime[1])
	      if(mojitime[0] != mojitime[2])
	         if(mojitime[0] != mojitime[3])
	            if(mojitime[1] != mojitime[2])
	               if(mojitime[1] != mojitime[3])
	                  if(mojitime[2] != mojitime[3]) {
			     number=(unsigned)atoi(mojitime);
			     if(123<=number && number<=9876) {
			        break;

			     }
		          }
	}
	return(number);
}
