void PGNReadFromFile (const char *file) /**************************************************************************** * * To read a game from a PGN file. * ****************************************************************************/ { FILE *fp; char s[100], c, wmv[8], bmv[8]; int moveno; leaf *p; fp = fopen (file, "r"); if (fp == NULL) { printf ("Cannot open file %s\n", file); return; } /* Skip all the tags */ do { if ((c = fgetc (fp)) == '[') fgets (s, 100, fp); } while (c == '['); ungetc (c, fp); InitVars (); while (!feof (fp)) { c = fgetc(fp); if (c == '*') break; ungetc (c, fp); fscanf (fp, "%d. %7s %7s ", &moveno, wmv, bmv); p = ValidateMove (wmv); if (!p) { printf ("Illegal move %d. %s\n", moveno, wmv); break; } MakeMove (white, &p->move); strcpy (Game[GameCnt].SANmv, wmv); if (*bmv == '*' ) break; p = ValidateMove (bmv); if (!p) { printf ("Illegal move %d. ... %s\n", moveno, bmv); break; } MakeMove (black, &p->move); strcpy (Game[GameCnt].SANmv, bmv); } printf ("%d\n", GameCnt); fclose (fp); ShowBoard (); TTClear (); return; }
void test_validate_move() { printf("chess-test: testing validate move (a5)...\n"); leaf *result; result = ValidateMove("a5"); // invalid move returns null if (NULL != result) printf("chess-test: result was: %d\n", result->move); else printf("chess-test: result was NULL\n"); }
/* * Extracts a command from the engine input buffer. * * The command is removed from the buffer. * If the command is a move, the move is made. */ void NextEngineCmd( void ) { char engineinput[BUF_SIZE]=""; char enginemovestr[BUF_SIZE]=""; leaf* enginemove; if ( strlen( engineinputbuf ) > 0 ) { if ( GetNextLine( engineinputbuf, engineinput ) > 0 ) { dbg_printf("< ENGINE: %s\n", engineinput); if ( strncmp( engineinput, "move", 4 ) == 0 ) { /* Input from engine is a move */ sscanf( engineinput, "move %s", enginemovestr ); enginemove = ValidateMove( enginemovestr ); if ( enginemove == (leaf *) NULL ) { dbg_printf( "Bad move from engine\n" ); } else { dbg_printf( "Engine move: <%s> (%d,%d)\n", enginemovestr, (enginemove!=NULL ? enginemove->move : -1), (enginemove!=NULL ? enginemove->score : -1) ); SANMove (enginemove->move, 1); MakeMove( board.side, &(enginemove->move) ); strcpy (Game[GameCnt].SANmv, SANmv); if ( !(flags & XBOARD) ) { //ShowBoard(); dbg_printf("USER <: My move is : %s\n", SANmv); //printf( "\nMy move is : %s\n", SANmv ); printf( "\n<%i:%i>\n", FROMSQ(enginemove->move), TOSQ(enginemove->move) ); fflush( stdout ); } else { dbg_printf("USER <: %d. ... %s\n", GameCnt/2 + 1, enginemovestr ); printf ("%d. ... %s\n", GameCnt/2 + 1, enginemovestr ); fflush( stdout ); dbg_printf("USER <: My move is : %s\n", enginemovestr); printf( "My move is : %s\n", enginemovestr ); fflush( stdout ); } RealGameCnt = GameCnt; showprompt = 1; /* Check if the color must be changed, e.g. after a go command. */ if ( changeColor ) { RealGameCnt = GameCnt; RealSide = board.side; } } } else { dbg_printf( "USER <: %s\n",engineinput ); printf( "%s", engineinput ); if ( flags & XBOARD ) { fflush( stdout ); } } } } }
void BookPGNReadFromFile (const char *file) /**************************************************************************** * * To read a game from a PGN file and store out the hash entries to book. * ****************************************************************************/ { FILE *fp; char s[100], wmv[8], bmv[8]; int c; unsigned int i; char header[2000]; int moveno, result, ngames = 0; leaf *p; time_t t1, t2; double et; int examinecolor, playerfound[2]; /* Only players in the table below are permitted into the opening book from the PGN files. Please expand the table as needed. Generally, I would recommend only acknowledged GM's and IM's and oneself, but because of the self-changing nature of the book, anything inferior will eventually be eliminated through automatic play as long as you feed the games the program plays back to itself with "book add pgnfile" */ /* XXX: Is it really a good idea to have a list like this hardcoded? */ const char *const player[] = { "Alekhine", "Adams", "Anand", "Anderssen", "Andersson", "Aronin", "Averbakh", "Balashov", "Beliavsky", "Benko", "Bernstein", "Bird", "Bogoljubow", "Bolbochan", "Boleslavsky", "Byrne", "Botvinnik", "Bronstein", "Browne", "Capablanca", "Chigorin", "Christiansen", "De Firmian", "Deep Blue", "Deep Thought", "Donner", "Dreev", "Duras", "Euwe", "Evans", "Filip", "Fine", "Fischer", "Flohr", "Furman", "Gelfand", "Geller", "Gereben", "Glek", "Gligoric", "GNU", "Golombek", "Gruenfeld", "Guimard", "Hodgson", "Ivanchuk", "Ivkov", "Janowsky", "Kamsky", "Kan", "Karpov", "Kasparov", "Keres", "Korchnoi", "Kortschnoj", "Kotov", "Kramnik", "Kupreich", "Lasker", "Lautier", "Letelier", "Lilienthal", "Ljubojevic", "Marshall", "Maroczy", "Mieses", "Miles", "Morphy", "Mueller", /* Every other German has this name... */ "Nimzowitsch", "Nunn", "Opocensky", "Pachman", "Petrosian", "Piket", "Pilnik", "Pirc", "Polgar", "Portisch", "Psakhis", "Ragozin", "Reshevsky", "Reti", "Romanish", "Rubinstein", "Saemisch", "Seirawan", "Shirov", "Short", "Silman", "Smyslov", "Sokolsky", "Spassky", "Sveshnikov", "Stahlberg", "Steinitz", "Tal", "Tarjan", "Tartakower", "Timman", "Topalov", "Torre", "Vidmar" }; et = 0.0; t1 = time(NULL); result = -1; fp = fopen (file, "r"); if (fp == NULL) { fprintf(stderr, "Cannot open file %s: %s\n", file, strerror(errno)); return; } /* Maybe add some more clever error handling later */ if (BookBuilderOpen() != BOOK_SUCCESS) return; newpos = existpos = 0; nextgame: header[0] = 0; InitVars (); NewPosition (); CLEAR (flags, MANUAL); CLEAR (flags, THINK); myrating = opprating = 0; playerfound[black] = playerfound[white] = 0; /* Skip all the tags */ /* * XXX: This has two problems: 1) Leading whitespace leads to * undefined stuff in s, and completely confuses the program. * 2) If there is a game between two players in the list, only * the moves of the white player will be added. */ /* Skip whitespace */ while ((c=fgetc(fp)) != EOF) { if (c != ' ' && c != '\t' && c != '\n') { ungetc(c, fp); break; } } while ((c=fgetc(fp)) == '[') { ungetc(c, fp); fgets(s, 100, fp); strcat(header,s); if (strncmp(s+1, "White ",6) == 0) { examinecolor = white; ngames++; } else if (strncmp(s+1, "Black ",6) == 0) { examinecolor = black; } else if (strncmp(s+1, "Result", 6) == 0) { if (strncmp(s+7," \"1-0",5) == 0) { result = R_WHITE_WINS; } else if (strncmp(s+7," \"0-1",5) == 0) { result = R_BLACK_WINS; } else if (strncmp(s+7," \"1/2-1/2",9) == 0) { result = R_DRAW; } else { result = R_NORESULT; } continue; } else continue; /* * We get only here if White or Black matched, it is ugly but it * works. Attention: If at some point we want to put this array * of authorized players in some external file, we have to keep * track of the size of that array in some other way. */ for (i = 0; i < (sizeof(player) / sizeof(*player)); i++) { if (strstr(s+7, player[i]) != NULL) { playerfound[examinecolor] = 1; } } } ungetc(c, fp); while (1) { if (fscanf(fp, "%d. %7s ", &moveno, wmv) < 2) break; if (wmv[0] == '1' || wmv[0] == '[' || wmv[0] == '*' || strcmp(wmv, "0-1") == 0) break; p = ValidateMove (wmv); if (!p) { puts(header); ShowBoard(); printf ("Illegal move %d. %s\n", moveno, wmv); break; } MakeMove (white, &p->move); if (playerfound[white]) { if (BookBuilder (result, white) != BOOK_SUCCESS) break; } strcpy (Game[GameCnt].SANmv, wmv); if (fscanf(fp, "%7s ", bmv) < 1) break; if (bmv[0] == '1' || bmv[0] == '[' || bmv[0] == '*' || strcmp(bmv, "0-1") == 0) break; p = ValidateMove (bmv); if (!p) { puts (header); ShowBoard(); printf ("Illegal move %d. ... %s\n", moveno, bmv); break; } MakeMove (black, &p->move); if (playerfound[black] ) { if (BookBuilder (result, black) != BOOK_SUCCESS) break; } strcpy (Game[GameCnt].SANmv, bmv); } /* Read to end of game but don't parse */ while (!feof(fp)) { fgets(s,100,fp); if (s[0] == '\n') break; } /* printf ("%d(%d)\n", GameCnt,BOOKDEPTH); */ if (!feof(fp)) { if (ngames % 10 == 0) printf("%d\r",ngames); fflush(stdout); goto nextgame; } fclose (fp); if (BookBuilderClose() != BOOK_SUCCESS) { perror("Error writing opening book"); } /* Reset the board otherwise we leave the last position in the book on the board. */ header[0] = 0; InitVars (); NewPosition (); CLEAR (flags, MANUAL); CLEAR (flags, THINK); myrating = opprating = 0; t2 = time(NULL); et += difftime(t2, t1); putchar('\n'); /* Handle divide-by-zero problem */ if (et < 0.5) { et = 1.0; }; printf("Time = %.0f seconds\n", et); printf("Games compiled: %d\n",ngames); printf("Games per second: %f\n",ngames/et); printf("Positions scanned: %d\n",newpos+existpos); printf("Positions per second: %f\n",(newpos+existpos)/et); printf("New & unique added: %d positions\n",newpos); printf("Duplicates not added: %d positions\n",existpos); }
/******************************************************************************************************* * GANE ENGINE - handles the looping of the game *******************************************************************************************************/ void GameEngine() { // user input variables const int userInputLimit = 11; char userInput[userInputLimit] = {}; bool humanFinished = false; bool moveHuman = false; StringOO humanMove = "move south"; int loopCount = 0; // location variables const int locationNum = 11; Location *Locations[locationNum] = {}; int prevLocation = 0; int newLocation = 0; int finishLocation = locationNum - 1; // human player variables int humanLoc = 0; StringOO name = "Bruce"; int strength = 10; int health = 100; int luck = 10; int intellegence = 10; // enemy variables const int enemyNum = 5; Enemy * Enemies[enemyNum] = {}; // challenges variables const int challengeNum = 16; Challenge *Challenges[challengeNum] = {}; // initialise Locations InitLocations(Locations); // initialise human Human Human(humanLoc, name, strength, health, luck, intellegence); // initialise Enemies InitEnemies(Enemies, enemyNum); // initialise Challenges InitChallenges(Challenges); //AllocateChallenges(Locations, locationNum); AllocateChallengesManually(Locations, locationNum); AddEnemyToChallenge(Challenges, enemyNum, challengeNum); // initial splash screen SetConsole(); StartText(Human); // Game loop while (!humanFinished) { // print out details of room std::cout << Locations[Human.GetLocation()]->GetDescription() << std::endl; while (!moveHuman) { // get user to enter move std::cout << "+ "; std::cin.getline(userInput, userInputLimit); std::cout << std::endl; humanMove = userInput; if (loopCount == 5) { std::cout << "\n ENOUGH ALREADY...YOUR MOVING SOUTH!! \n\n"; //bored of guesses humanMove = "move south"; loopCount = 0; } // determine the new location newLocation = PlayerMove(Human, humanMove, Locations[Human.GetLocation()]->GetAjacentLoc()); // validate users move and if validate change their location if (ValidateMove(newLocation, prevLocation)) { // set challenge user has to perform before progrogressing to the next room Human.SetChallenge(Locations[Human.GetLocation()]->GetPathChallenge(Human.GetHeading())); // challenge User Challenge *ChallengePtr = Challenges[Human.GetChallenge()]; ApplyChallenge(ChallengePtr, Human, Enemies); // move user to new location prevLocation = Human.GetLocation(); Human.SetPrevHeading(Human.GetHeading()); Human.SetLocation(newLocation); moveHuman = true; loopCount = 0; std::cout << "\n***----------------------------* pop! *-------------------------------------**\n\n"; } else { // invalid move try again moveHuman = false; loopCount++; } } // reset move moveHuman = false; //check if user is in the finish location if (Human.GetLocation() == finishLocation) { humanFinished = true; std::cout << Locations[Human.GetLocation()]->GetDescription() << std::endl; FinishText(Human); } } //DestroyEnemies(Enemies, enemyNum); for (int i = 0; i < enemyNum; i++) { delete Enemies[i]; } //DestroyChallenges(Challenges, challengeNum); for (int i = 0; i < challengeNum; i++) { delete Challenges[i]; } //DestroyLocations(Locations, locationNum); for (int i = 0; i < locationNum; i++) { delete Locations[i]; } }
void InputCmd () /************************************************************************* * * This is the main user command interface driver. * *************************************************************************/ { const char *color[2] = { "White", "Black" }; int suffix; int i; leaf *ptr; int ncmds; char *x,*trim; CLEAR (flags, THINK); memset(userinput,0,sizeof(userinput)); memset(cmd,0,sizeof(cmd)); #ifndef HAVE_LIBREADLINE /* Why is this necessary anyway? */ memset(inputstr,0,sizeof(inputstr)); #endif #ifdef HAVE_LIBREADLINE if (isatty(STDIN_FILENO)) { sprintf(s,"%s (%d) %c ", color[board.side], (GameCnt+1)/2 + 1, prompt); inputstr = readline(s); if (inputstr == NULL) return; if (*inputstr) { add_history(inputstr); } if (strlen(inputstr) > INPUT_SIZE-1) { printf("Warning: Input line truncated to %d characters.\n", INPUT_SIZE -1 ); inputstr[INPUT_SIZE-1] = '\000'; } } else { inputstr = malloc(INPUT_SIZE); if (inputstr == NULL) { perror("InputCmd"); exit(EXIT_FAILURE); } fgets(inputstr, INPUT_SIZE, stdin); if (inputstr[0]) { inputstr[strlen(inputstr)-1] = 0; } } #else /* !HAVE_LIBREADLINE */ if (!(flags & XBOARD)) { printf ("%s (%d) %c ", color[board.side], (GameCnt+1)/2 + 1, prompt); fflush(stdout); } fgets (inputstr, INPUT_SIZE, stdin) ; #endif /* HAVE_LIBREADLINE */ cmd[0] = '\n'; strcpy(userinput,inputstr); sscanf (inputstr, "%s %[^\n]", cmd, inputstr); if (cmd[0] == '\n') goto done; cmd[0] = subcmd[0] = setting[0] = subsetting[0] = '\0'; ncmds = sscanf (userinput,"%s %s %s %[^\n]", cmd,subcmd,setting,subsetting); /* Put options after command back in inputstr - messy */ sprintf(inputstr,"%s %s %s",subcmd,setting,subsetting); trim = inputstr + strlen(inputstr) - 1; while ( trim>=inputstr && *trim==' ') *trim--='\0'; if (strcmp (cmd, "quit") == 0 || strcmp (cmd, "exit") == 0) SET (flags, QUIT); else if (strcmp (cmd, "help") == 0) ShowHelp (inputstr); else if (strcmp (cmd, "show") == 0) ShowCmd (inputstr); else if (strncmp (cmd, "book", 4) == 0) { if (strncmp(inputstr, "add",3) == 0) { sscanf (inputstr, "add %s", file); if (access(file,F_OK) < 0) { printf("The syntax to add a new book is:\n\n\tbook add file.pgn\n"); } else { BookPGNReadFromFile (file); } } else if (strncmp (inputstr, "on", 2) == 0 || strncmp (inputstr, "prefer", 6) == 0) { bookmode = BOOKPREFER; printf("book now on.\n"); } else if (strncmp (inputstr, "off", 3) == 0) { bookmode = BOOKOFF; printf("book now off.\n"); } else if (strncmp (inputstr, "best", 4) == 0) { bookmode = BOOKBEST; printf("book now best.\n"); } else if (strncmp (inputstr, "worst", 5) == 0) { bookmode = BOOKWORST; printf("book now worst.\n"); } else if (strncmp (inputstr, "random", 6) == 0) { bookmode = BOOKRAND; printf("book now random.\n"); } } else if (strcmp (cmd, "test") == 0) TestCmd (inputstr); else if (strcmp (cmd, "version") == 0) ShowVersion (); else if (strcmp (cmd, "pgnsave") == 0) { if ( strlen(inputstr) > 0 && strlen(inputstr) < INPUT_SIZE ) PGNSaveToFile (inputstr,""); else printf("Invalid filename.\n"); } else if (strcmp (cmd, "pgnload") == 0) PGNReadFromFile (inputstr); else if (strcmp (cmd, "manual") == 0) SET (flags, MANUAL); else if (strcmp (cmd, "debug") == 0) { SET (flags, DEBUGG); Debugmvl = 0; if (strcmp (inputstr, "debug") == 0) { while (strcmp (inputstr, s)) { sscanf (inputstr, "%s %[^\n]", s, inputstr); ptr = ValidateMove (s); Debugmv[Debugmvl++] = ptr->move; MakeMove (board.side, &ptr->move); } i = Debugmvl; while (i) { UnmakeMove (board.side, &Debugmv[--i]); } } } else if (strcmp (cmd, "force") == 0) SET (flags, MANUAL); else if (strcmp (cmd, "white") == 0) ; else if (strcmp (cmd, "black") == 0) ; else if (strcmp (cmd, "hard") == 0) ; else if (strcmp (cmd, "easy") == 0) ; else if (strcmp (cmd, "list") == 0) { if (inputstr[0] == '?') { printf("name - list known players alphabetically\n"); printf("score - list by GNU best result first \n"); printf("reverse - list by GNU worst result first\n"); } else { sscanf (inputstr, "%s %[^\n]", cmd, inputstr); if (inputstr == '\000') DBListPlayer("rscore"); else DBListPlayer(inputstr); } } else if (strcmp (cmd, "post") == 0) SET (flags, POST); else if (strcmp (cmd, "nopost") == 0) CLEAR (flags, POST); else if (strcmp (cmd, "name") == 0) { strcpy(name, inputstr); x = name; while (*x != '\000') { if (*x == ' ') { *x = '\000'; break; } x++; } suffix = 0; for (;;) { sprintf(logfile,"log.%03d",suffix); sprintf(gamefile,"game.%03d",suffix); if (access(logfile,F_OK) < 0) { ofp = fopen(logfile,"w"); break; } else suffix++; } } else if (strcmp (cmd, "result") == 0) { if (ofp != stdout) { fprintf(ofp, "result: %s\n",inputstr); fclose(ofp); ofp = stdout; printf("Save to %s\n",gamefile); PGNSaveToFile (gamefile, inputstr); DBUpdatePlayer (name, inputstr); } } else if (strcmp (cmd, "rating") == 0) { sscanf(inputstr,"%d %d",&myrating,&opprating); fprintf(ofp,"my rating = %d, opponent rating = %d\n",myrating,opprating); /* Change randomness of book based on opponent rating. */ /* Basically we play narrower book the higher the opponent */ if (opprating >= 1700) bookfirstlast = 2; else if (opprating >= 1700) bookfirstlast = 2; else bookfirstlast = 2; } else if (strcmp (cmd, "activate") == 0) { CLEAR (flags, TIMEOUT); CLEAR (flags, ENDED); } else if (strcmp (cmd, "new") == 0) { InitVars (); NewPosition (); CLEAR (flags, MANUAL); CLEAR (flags, THINK); myrating = opprating = 0; } else if (strcmp (cmd, "time") == 0) { sscanf (inputstr, "%s %[^\n]", s, inputstr); TimeLimit[1^board.side] = atoi(s) / 100.0f ; } else if (strcmp (cmd, "otim") == 0) ; else if (strcmp (cmd, "random") == 0) ; else if (strcmp (cmd, "hash") == 0) { sscanf (inputstr, "%s %[^\n]", cmd, inputstr); if (strcmp (cmd, "off") == 0) CLEAR (flags, USEHASH); else if (strcmp (cmd, "on") == 0) SET (flags, USEHASH); printf ("Hashing %s\n", flags & USEHASH ? "on" : "off"); } else if (strcmp (cmd, "hashsize") == 0) { if (inputstr[0] == 0) { printf("Current HashSize is %u slots\n", HashSize); } else { i = atoi (inputstr); TTHashMask = 0; while ((i >>= 1) > 0) { TTHashMask <<= 1; TTHashMask |= 1; } HashSize = TTHashMask + 1; printf ("Adjusting HashSize to %u slots\n", HashSize); InitHashTable (); } } else if (strcmp (cmd, "null") == 0)