Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Do you have code to check if a FEN is legal position?

Author: Gerd Isenberg

Date: 06:32:07 02/05/05

Go up one level in this thread


On February 05, 2005 at 04:51:35, Uri Blass wrote:

>I want to have a loop on all the legal FEN of tablebases positions (at least fen
>of 4 pieces) in order to debug my code to use tablebases and also to debug the
>function that I plan to write that should check if a FEN is legal.
>
>I gave the source code of movei to Dann Corbit and he wrote for me a function
>that does part of it that is not based on the rest of the code of movei but it
>does not check things like if the side to move can capture the opponent king and
>I find the program hard to understand because for some reason Dann used a lot of
>char ** that I never use  in movei.
>
>It may be because of my lack of knowledge in programming but I see no reason to
>use ** for tasks like that and I see no advantage in it and it only cause
>problems in understanding such a code.
>
>I understand that ** should be pointer to pointer but not more than it and
>I have no experience with code like that.
>
>I think simply to read the FEN string char after char and collect information
>when I never need to go backward in the string when Dann's code does not do it
>and in order to check if there is a single king it simply count K in the
>relevant part of the string that is called piece_placement
>
>It is used as char ** in one function tokenize_position_string and as char * in
>another function setup that calls tokenize_position_string(I guess that the
>computer simply translate char* to char **)
>
>
>I still do not fully understand the code that Dann wrote for me at this
>moment(note that this code has nothing to do with the moves of the engine and it
>is only about checking the FEN that the program does not use during games) and I
>feel that I spend too much time about trying to understand things that are not
>relevant to the playing strength.
>
>I think that I will write my own code for that task instead of Dann's code and
>I already started with it.
>
>I wonder if you do it.
>
>Uri


Hi Uri,

char** is quite common in C syntax parsers.

You may have a char* pointer to the string to be parsed.
This char* is incremented during the process, but you may have several
(recursive) instances of routines using the pointer, eg. expression, sum and
product for a simple const-expression syntax parser. Therefore you have to pass
a reference (or pointer) to the char* pointer to the routines.

The problem in C is, if you want to avoid globals, there is no way to share a
pointer between instances of several functions other than passing a pointer or
reference of a pointer as paramter around.

In C++ one may encapsulate the char* and all functions working on it inside a
class or struct.

Following on the fly bnf-parser to make that clear.
(to keep it simple no white space handling and only +|* operators)

exp   ::= sum [ "+" sum]...
sum   ::= pro [ "*" pro]...
pro   ::= const | "(" exp ")"
const ::= digit [digit]...
digit ::= "0"..."9"

int exp (char **pptr)
{
   int e = sum (pptr);
   char* ptr = *pptr; // get current pointer
   while (*ptr == '+')
   {
      ptr++;
      pptr = &ptr;
      e   += sum (pptr);
      ptr  = *pptr;
   }
   pptr = &ptr; // current pointer back
   return e;
}

int sum (char **pptr)
{
   int s = pro (pptr);
   char* ptr = *pptr; // get current pointer
   while (*ptr == '*')
   {
      ptr++;
      pptr = &ptr;
      s   *= pro (pptr);
      ptr  = *pptr;
   }
   pptr = &ptr; // current pointer back
   return s;
}

int pro (char **pptr)
{
   int r;
   char* ptr = *pptr; // get current pointer
   if ( *ptr == '(')
   {
      ptr++;
      pptr = &ptr;
      r = exp(pptr);
      ptr = *pptr;
      if (*ptr != ')')
        throw syntaxError;
      ptr++;
      pptr = &ptr; // current pointer back
   }
   else
   {
      if ( !isDigit(*ptr))
        throw syntaxError;
      r = 0;
      do
      {
         r = r*10 + *ptr - '0'; // ascii2int
         ptr++;
      }
      while (isDigit(*ptr));
      pptr = &ptr; // current pointer back
   }
   return r;
}

// same with a C++ class
class CMySimpleParser
{
   char* m_ptr;
    ...;
   int exp ()
   {
      int e = sum ();
      while (*m_ptr == '+')
      {
         m_ptr++;
         e  += sum ();
      }
      return e;
   }

   int sum ()
   {
      int s = pro ();
      while (*m_ptr == '*')
      {
         m_ptr++;
         s *= pro ();
      }
      return s;
   }

   int pro ()
   {
      int r;
      if ( *m_ptr == '(')
      {
         m_ptr++;
         r = exp();
         if (*m_ptr != ')')
            throw syntaxError;
         m_ptr++;
      }
      else
      {
         if ( !isDigit(*m_ptr))
           throw syntaxError;
         r = 0;
         do
         {
            r = r*10 + *m_ptr - '0'; // ascii2int
            m_ptr++;
         }
         while (isDigit(*m_ptr));
      }
      return r;
   }
}; // class

Cheers,
Gerd



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.