FEN parsing issue

Code, algorithms, languages, construction...
Post Reply
CDaley11
Posts: 42
Joined: Thu Jan 10, 2013 6:23 am
Real Name: Christian Daley

FEN parsing issue

Post by CDaley11 » Sun Feb 03, 2013 11:33 pm

I've lately noticed a strange problem in my FEN parsing function. For example, if I give my engine the following command:
position fen rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1
This is the starting position with white's first move being e2e4. After parsing the fen my program prints out a text based board to show what the board currently looks like. If I run my program from within the debugger in Xcode, it gets the board position correct, every time. But if I instead launch the executable myself and run it from within terminal, it doesn't get the position right and it is all messed up. But it only messes up around half the time! This is bothering me, it simply doesn't make sense for a program to mess up only half of the time. And here's another strange part: I added in a line of code that spits back out the fen string token , just to make sure it was getting the token right in both cases. In both cases it was getting the token right. But with printing out the fen string before parsing it, the program never messes up, in either xcode or terminal. But if I simply make it so that my program does not print out the fen string before parsing it, then it will mess up half of the time while running in terminal. I've tried this dozens of times, it really is very strange.

User923005
Posts: 616
Joined: Thu May 19, 2011 1:35 am

Re: FEN parsing issue

Post by User923005 » Mon Feb 04, 2013 3:32 pm

Probably undefined behavior.
Turn your compiler warnings to maximum. Look for things like "Unitialized variable" in the output.

User923005
Posts: 616
Joined: Thu May 19, 2011 1:35 am

Re: FEN parsing issue

Post by User923005 » Tue Feb 05, 2013 7:07 pm

Did you find your problem?

CDaley11
Posts: 42
Joined: Thu Jan 10, 2013 6:23 am
Real Name: Christian Daley

Re: FEN parsing issue

Post by CDaley11 » Wed Feb 06, 2013 8:44 pm

No, unfortunately i didn't :(. I've spent quite a while fiddling with it and I just cannot seem to get it to work right. It works fine in the debugger in Xcode but it simply wont work when I run it in terminal or with a gui. It really is very strange. I'll keep working on it though and ill post if I can get it to function right.

User923005
Posts: 616
Joined: Thu May 19, 2011 1:35 am

Re: FEN parsing issue

Post by User923005 » Wed Feb 06, 2013 8:56 pm

If you post your source code, someone can probably figure it out for you.
If you don't want to expose your code, that is fine too.

CDaley11
Posts: 42
Joined: Thu Jan 10, 2013 6:23 am
Real Name: Christian Daley

Re: FEN parsing issue

Post by CDaley11 » Thu Feb 07, 2013 3:56 am

This is my Fen parsing code. In case you're wondering, board is a struct.

EDIT: One really weird thing I noticed, if I add this code right before the parsing loop:

Code: Select all

for (int a=0;a<0;a++) {

}
Then it works fine! But as far as I can tell, this loop does absolutely nothing.
Attachments
Fen.cpp
(2.13 KiB) Downloaded 272 times

User923005
Posts: 616
Joined: Thu May 19, 2011 1:35 am

Re: FEN parsing issue

Post by User923005 » Thu Feb 07, 2013 8:45 pm

I analyzed this:

Code: Select all

#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#define BLACK 0
#define WHITE 1

typedef struct board_type {
    int turn;
    int enPassantSquare;
    int castling[2][2];
    int movesSincePawnPushOrCapture;
    int totalFullMoves;
} board_type;

board_type b;

board_type *board = &b;

char *getToken(char *, char *);
void clearBoard(board_type *);
void setSquare(board_type *,  int , int , int);
int parseSquare(char *);

char *parseFen(char *ptr) { // The fen parsing function
    clearBoard(board);
    const char *pieceNames = "PRNBQKprnbqk";
    int rank = 7; // Rank and file iterator
    int file = 0;
    char *token = new char[80];

    ptr = getToken(ptr, token);  // Get the first token in the string, which should be the piece positions
    while (rank >= 0) {
        if (*token == '/')
            token++;
        char temp = *token;
        int n = 0;
        if ((n = atoi(&temp))) {
            file += n;
            if (file >= 8) {
                file = 0;
                rank--;
            }
            token++;
            continue;
        }
        for (int a=0; a < 2; a++) {
            for (int b=0; b < 6; b++) {
                if (temp == pieceNames[a * 6 + b]) {
                    // Sets a specific square on the board to a specific piece type and color. b = color, a = piece type
                    setSquare(board, b, a, rank * 8 + file);
                    break;
                }
            }
        }
        file++;
        if (file >= 8) {
            file = 0;
            rank--;
        }
        token++;
    }
    ptr = getToken(ptr, token);
    if (*token == 'w')
        board->turn = WHITE;
    else
        board->turn = BLACK;
    ptr = getToken(ptr, token);
    for (int a=0; a < strlen(token); a++) {
        if (token[a] == 'Q')
            board->castling[WHITE][0] = true;
        else if (token[a] == 'K')
            board->castling[WHITE][1] = true;
        else if (token[a] == 'q')
            board->castling[BLACK][0] = true;
        else if (token[a] == 'k')
            board->castling[BLACK][1] = true;
    }
    ptr = getToken(ptr, token);
    if (*token != '-') {
        char square[2] = {token[0], token[1]};
        int sq = parseSquare(square);
        board->enPassantSquare = 1ULL << sq;
    }
    ptr = getToken(ptr, token);
    board->movesSincePawnPushOrCapture = atoi(token);
    ptr = getToken(ptr, token);
    board->totalFullMoves = atoi(token);
    return ptr;
}
I don't see anything obviously obnoxious in there.
I suspect that the fault is in one of these routines:
char *getToken(char *, char *);
void clearBoard(board_type *);
void setSquare(board_type *, int , int , int);
int parseSquare(char *);

It will be much easier to help you if you attach code in a state that actually compiles.

CDaley11
Posts: 42
Joined: Thu Jan 10, 2013 6:23 am
Real Name: Christian Daley

Re: FEN parsing issue

Post by CDaley11 » Sun Feb 10, 2013 12:36 am

I finally figured out the problem! When I give it the FEN rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1 Then for some reason when I run the program in the debugger it interprets the 1 (in bold) just fine, but when running in terminal it interprets it as a 10! This is using the basic atoi(const char *) function. I changed this code:

Code: Select all

n = atoi(&temp); // Where temp is the current character being looked at
To this:

Code: Select all

char numString[] = {temp, '\0'};
n = atoi(numString);
And it worked.

User923005
Posts: 616
Joined: Thu May 19, 2011 1:35 am

Re: FEN parsing issue

Post by User923005 » Sun Feb 10, 2013 12:43 am

The atoi function assumes that a zero terminated string is supplied.
Now, since the next character is the letter P, conversion should stop.
So a return of 10 seems quite strange to me.
What compiler are you using?

HumbleProgrammer
Posts: 40
Joined: Sat Jun 19, 2010 11:00 pm
Real Name: Lee Neuse

Re: FEN parsing issue

Post by HumbleProgrammer » Sun Feb 10, 2013 1:43 pm

If you are only parsing a single digit -- such as in FEN parsing -- a simple trick is to compute the result:

Code: Select all

char[] temp = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1";
int iSkip = (int)(temp[18] - '0'); // subtract character for zero, NOT zero value!
This will convert the single digits '0' through '9' to their integer equivalents [0..9]. It obviously does not work on negative numbers, or numbers greater than 9.

Cheers!
Humble Programmer
,,,^..^,,,

Post Reply