Page 1 of 1

Winboard_F and chess960 (FRC)

PostPosted: 16 Nov 2007, 19:32
by Pedro Castro
Hi H.G.,

I see that you have created many new variants and all are grouped in the File menu --> New variant ... However variant FRC continues apart. I think that it might also be included in this group.

I have problems with variant FRC, for example, DanaSah (3.13frc) and AICE 0.99.2 (wb) are capable of playing chess fischerandom in Arena or ChessGui, but I have not managed to play with them in Winboard_x or Winboard_F.

The first problem seems to be that when I make a new game FRC, I do not get unlike Arena the command setboard with the new arrangement of the pieces.

Then I do not know as Winboard makes castling, in my case as Arena indicated I sent or hope to receive "O-O" for the castling on the right and "O-O-O" for the castling to the left.

It is possible to modify Winboard_F to make the engines winboard playing FRC does so Winboard_F?

Re: Winboard_F and chess960 (FRC)

PostPosted: 16 Nov 2007, 21:27
by H.G.Muller
The problem is that I really don't know FRC. I saw a lot of code in the Winboard_x version I started from, which referred to FDC. According to the accompanying comment it was put there by Tord and Fabien. I contacted Tord about it, but he said the code was not enough to play FRC, and that if it were made to do so, it somehow interfered with palying normal Chess. There seems to exist a separate version of Winboard that plays only FRC. So I did not pay any attention to that code, and just left it as it was.

In any case O-O-O or O-O is in violation of WinBoard protocol. The protocol clearly states that moves have to be sent as coordinates. From the code of Tord and Fabien I understood that the notation for castling should give the location of the Rook as toSquare. WinBoard_F definitely understands that (through Tord & Fabien's code), as I discovered when TSCP-Gothic used that move against Fairy-Max. Winboard accepted the move as a castling and passed it on to Fairy-Max, who of course rejected it as an illegal move (and got the game forfeited because /testClaims was on). So I added code to translate FRC-style castlings from the engine to standard notation if the variant is not FRC.

I am not sure why the setboard isn't sent, it seems easy enough to do so. If I start Winboard_F with the option /variant=fischeRandom (with only a single R, I don't know why the variant is named like that), the option new "FRC game..." becomes active, and when I click it, a new game is set up in Winboard. But somehow it is not communicated to the engines.

I can easily add that in a next version.

Re: Winboard_F and chess960 (FRC)

PostPosted: 16 Nov 2007, 23:40
by Reinhard Scharnagl
May I comment on this question: I repeatedly proposed a compatible mimic for to handle FRC castlings, and there is a living example for that: SMIRF. But that is not really important, instead the method used is.

If the King is at least two squares distant to his castling target, use this as destination coordinate (full compatible to traditional approaches), else use the involved Rook's coordinate as destination. This all is to avoid a possible misinterpretation of the castling move either as a normal King's move or as a kind of nullmove.

An additional effect of this method is, that this will also define a clear and compatible input gesture for to input FRC castling moves without a need for any additional hint towards the GUI.

Reinhard.

Re: Winboard_F and chess960 (FRC)

PostPosted: 17 Nov 2007, 00:27
by Pedro Castro
Hi H.G.,

Arena has not breached the protocol xboard, I see that Arena has been adjusted to what the protocol says. ChessGui also.

H.G.Muller wrote:In any case O-O-O or O-O is in violation of WinBoard protocol.


O-O and O-O-O is not a violation

Protocol xboard -->

MOVE
See below for the syntax of moves. If the move is illegal, print an error message; see the section "Commands from the engine to xboard". If the move is legal and in turn, make it. If not in force mode, stop the opponent's clock, start the engine's clock, start thinking, and eventually make a move.
When xboard sends your engine a move, it normally sends coordinate algebraic notation. Examples:

Normal moves: e2e4
Pawn promotion: e7e8q
Castling: e1g1, e1c1, e8g8, e8c8
Bughouse/crazyhouse drop: P@h3
ICS Wild 0/1 castling: d1f1, d1b1, d8f8, d8b8
FischerRandom castling: O-O, O-O-O (oh, not zero)


/variant=fischeRandom (with only a single R, I don't know why the variant is named like that),.


I understand that is something that decided Tim Mann.

variant VARNAME
If the game is not standard chess, but a variant, this command is sent after "new" and before the first move or "edit" command. Currently defined variant names are:
wildcastle Shuffle chess where king can castle from d file
nocastle Shuffle chess with no castling at all
fischerandom Fischer Random (not supported yet)
bughouse Bughouse, ICC/FICS rules
crazyhouse Crazyhouse, ICC/FICS rules
losers Win by losing all pieces or getting mated (ICC)
suicide Win by losing all pieces including king, or by having fewer pieces when one player has no legal moves (FICS)
giveaway Win by losing all pieces including king, or by having no legal moves (ICC)
twokings Weird ICC wild 9
kriegspiel Kriegspiel (engines not supported)
atomic Atomic
3check Win by giving check 3 times
unknown Unknown variant (not supported)

Re: Winboard_F and chess960 (FRC)

PostPosted: 17 Nov 2007, 12:15
by H.G.Muller
I guess you are right as far as GUI -> engine communication is concerned. The code by Tord and Fabien already seems to do that, in FRC (controlled by an additional option, useOOCastle, that can be set by the engine through the features command in protocol 2, and defaults to TRUE).

For engine -> GUI it is not that clear. Engines are discouraged to use anything different from coordinate representation. WinBoard is pretty tolerant in this respect (but not all other WB compatible GUIs are!), and uses the full SAN parser on the engine output. But FRC does not seem implemented there: the parser translates O-O always to e1g1, which in FRC might be another legal, non-castling move.

I guess I will have to do something there. Giving the squares of the King and Rook should work, though.

Re: Winboard_F and chess960 (FRC)

PostPosted: 17 Nov 2007, 17:10
by Pedro Castro
Perhaps this can help (sorry code in spanish). Steps that I have to make the engine compatible with chess960:

1) The engine must have a function setboard. I changed setboard to do 2 things. On the one hand, I keep the position of the rooks (and Kings), and when I undoing a castling, the engine knows where to go the rooks. (easy)

Code: Select all
   int ntb = 0, ntn = 0;

   for (i = 0; i < 64; i++) {
      if (color[i] == VACIO)
         continue;
        if (color[i] == BLANCO) { // white
         switch (pieza[i]) {
            case TORRE: // rook
               ntb++;
               if (ntb == 1) tb2 = i;
               else if (ntb == 2) tb1 = i;
               break;
            case REY: // king
               rb = i;
               break;
         }
      }
      else  {
         switch (pieza[i]) {
            case TORRE:
               ntn++;
               if (ntn == 1) tn2 = i;
               else if (ntn == 2) tn1 = i;
               break;
            case REY:
               rn = i;
               break;
         }
      }
   }


I also modify the mask for castling. (easy)

Code: Select all
Before-->
int enroque_mascara[64] = { //as TSCP
    7, 15, 15, 15,  3, 15, 15, 11,
   15, 15, 15, 15, 15, 15, 15, 15,
   15, 15, 15, 15, 15, 15, 15, 15,
   15, 15, 15, 15, 15, 15, 15, 15,
   15, 15, 15, 15, 15, 15, 15, 15,
   15, 15, 15, 15, 15, 15, 15, 15,
   15, 15, 15, 15, 15, 15, 15, 15,
   13, 15, 15, 15, 12, 15, 15, 14
};

The new mask has to take into account where the kings and the rooks.

So I do

   for (i = 0; i < 64; i++) {
      enroque_mascara[i] = 15;
   }

   enroque_mascara[rb] = 12; // white king
   enroque_mascara[rn] = 3;   // black king
   enroque_mascara[tb2] = 13; // white rook left
   enroque_mascara[tb1] = 14; // white rook right
   enroque_mascara[tn2] = 7; // black rook left
   enroque_mascara[tn1] = 11; // black rook right



2) GUI --> engine

In the function xboard () I check if we get a command or move. When I got a move I expected to receive it in notation coordinates, the first check if I get a letter a-h then a number 1-8...
In this case I also add that I can receive O-O or O-O-O (easy)

Code: Select all
   //comprobamos si recibimos un enroque en chess960
   if (strcmp (s,"O-O") == 0) {
      if (turno == BLANCO) {
         de = rb;
         a = 62;
      }
      else {
         de = rn;
         a = 6;
      }
      tipo = ENROQUE;
   }
   else if (strcmp (s,"O-O-O") == 0) {
      if (turno == BLANCO) {
         de = rb;
         a = 58;
      }
      else {
         de = rn;
         a = 2;
      }
      tipo = ENROQUE;
   }
   else {
   //comprueba si estamos recibiendo un movimiento
      if (s[0] < 'a' || s[0] > 'h' ||
         s[1] < '0' || s[1] > '9' ||
         s[2] < 'a' || s[2] > 'h' ||
         s[3] < '0' || s[3] > '9') {
         printf("Error (unknown command): %s\n", s);   // si no es un movimiento debe ser un comando desconocido
         return;
         }
...


3) engine --> GUI

When I send a move to the engine if the variant is fischerandom and the move is a castling I sent O-O or O-O-O. (easy)

Code: Select all
   //Enviamos un enroque si estamos jugando a chess960
   if ((strcmp (variante,"fischerandom") == 0) && m.tipo == ENROQUE) {
      if (m.a == 62 || m.a == 6)
         printf("move O-O\n");
      if (m.a == 58 || m.a == 2)
         printf("move O-O-O\n");
   }
   // si estamos en un juego normal
   else {
      switch (m.tipo) {
         case PROMOCION_A_DAMA:
            c = 'q';
            break;
         case PROMOCION_A_TORRE:
            c = 'r';
            break;
         case PROMOCION_A_ALFIL:
            c = 'b';
            break;
         case PROMOCION_A_CABALLO:
            c = 'n';
            break;
         default:
            c = ' ';
      }
   
      /*al enviar el movimiento al gui debemos anteponer la palabra move*/
      printf("move %c%d%c%d%c\n",
            'a' + COLUMNA(m.de),
            8 - FILA(m.de),
            'a' + COLUMNA(m.a),
            8 - FILA(m.a),
            c);
   }


I also do the same when I print the pv. (easy)

4) When generates the castling I have care, before the king is always moving (in my case of the squares 60 or 4) to its position in the castling (62, 58, 6 or 3). Now the final position is the same but we have in mind that the initial position of the king could be different. (easy)

Code: Select all
   //generamos los enroques
   if (turno == BLANCO) {
      if (enroque & 1)
         Generar_Movimiento_Enroque_PVS(rb, 62, plista, &cuenta);
      if (enroque & 2)
         Generar_Movimiento_Enroque_PVS(rb, 58, plista, &cuenta);
   }
   if (turno == NEGRO) {
      if (enroque & 4)
         Generar_Movimiento_Enroque_PVS(rn, 6, plista, &cuenta);
      if (enroque & 8)
         Generar_Movimiento_Enroque_PVS(rn, 2, plista, &cuenta);
   }


5) Makemove. (hard)

If we have a castling, we must also move the rook, I have 2 different paths depending if we are in the normal variant or fischerandom. In variant fischerandom have more squares to check if castling is possible, we must also have in mind that perhaps the king can jump above the rook.

Code: Select all
   if (m.tipo == ENROQUE) { //en caso de enroque movemos la torre
      if (strcmp (variante,"normal") == 0) {
         switch (m.a) {
            case 62:
               if ((color[61] != VACIO) || (color[62] != VACIO) ||
                  (atacado (60, BLANCO)) || (atacado (61, BLANCO)))
                  return FALSO;
               de = 63;
               a = 61;
               break;
            case 58:
               if ((color[57] != VACIO) || (color[58] != VACIO) || (color[59] != VACIO) ||
                  (atacado (60, BLANCO)) || (atacado (59, BLANCO)))
                  return FALSO;
               de = 56;
               a = 59;
               break;
            case 6:
               if ((color[5] != VACIO) || (color[6] != VACIO) ||
                  (atacado (4, NEGRO)) || (atacado (5, NEGRO)))
                  return FALSO;
               de = 7;
               a = 5;
               break;
            case 2:
               if ((color[1] != VACIO) || (color[2] != VACIO) || (color[3] != VACIO) ||
               (atacado (4, NEGRO)) || (atacado (3, NEGRO)))
                  return FALSO;
               de = 0;
               a = 3;
               break;
            default:    //no debería llegar aquí
               de = -1;
               a = -1;
               break;
         }
      }
      else if (strcmp (variante,"fischerandom") == 0) {
         switch (m.a) {
            case 62:
               if (rb < 62 ) {
                  for (i = rb; i < 62; i++) {
                     if (atacado (i, BLANCO))
                        return FALSO;
                     if (color[i+1] != VACIO) {
                        if ((pieza[i+1] == TORRE) && (color[i+1] == BLANCO) && ((i+1) == tb1))
                           continue;
                        else
                           return FALSO;
                     }
                  }
               }
               else if (rb == 62) {
                  if (color[61] != VACIO)
                     return FALSO;
               }
               de = tb1;
               a = 61;
               break;
            case 58:
               if (rb > 58) {
                  for (i = rb; i > 58; i--) {
                     if (atacado (i, BLANCO))
                        return FALSO;
                     if (color[i-1] != VACIO) {
                        if ((pieza[i-1] == TORRE) && (color[i-1] == BLANCO) && ((i-1) == tb2))
                           continue;
                        else
                           return FALSO;
                     }
                  }
                  if ((tb2 == 56) && (color[57] != VACIO))
                     return FALSO;
               }
               else if (rb == 58) {
                  if (tb2 == 57) {
                     if (color[59] != VACIO)
                        return FALSO;
                  }
                  else if (tb2 == 56) {
                     if ((color[57] != VACIO) || (color[59] != VACIO))
                        return FALSO;
                  }
               }
               else if (rb == 57) {
                  if (atacado (57, BLANCO))
                     return FALSO;
                  if ((color[58] != VACIO) || (color[59] != VACIO))
                     return FALSO;
               }
               de = tb2;
               a = 59;
               break;
            case 6:
               if (rn < 6) {
                  for (i = rn; i < 6; i++) {
                     if (atacado (i, NEGRO))
                        return FALSO;
                     if (color[i+1] != VACIO) {
                        if ((pieza[i+1] == TORRE) && (color[i+1] == NEGRO) && ((i+1) == tn1))
                           continue;
                        else
                           return FALSO;
                     }
                  }
               }
               else if (rn == 6) {
                  if(color[5] != VACIO)
                     return FALSO;
               }            
               de = tn1;
               a = 5;
               break;
            case 2:
               if (rn > 2) {
                  for (i = rn; i > 2; i--) {
                     if (atacado (i, NEGRO))
                        return FALSO;
                     if (color[i-1] != VACIO) {
                        if ((pieza[i-1] == TORRE) && (color[i-1] == NEGRO) && ((i-1) == tn2))
                           continue;
                        else
                           return FALSO;
                     }
                  }
                  if ((tn2 == 0) && (color[1] != VACIO))
                     return FALSO;
               }
               else if (rn == 2) {
                  if (tn2 == 1) {
                     if (color[3] != VACIO)
                        return FALSO;
                  }
                  else if (tn2 == 0) {
                     if ((color[1] != VACIO) || (color[3] != VACIO))
                        return FALSO;
                  }
               }
               else if (rn == 1) {
                  if (atacado (1, NEGRO))
                     return FALSO;
                  if ((color[2] != VACIO) || (color[3] != VACIO))
                     return FALSO;
               }               
               de = tn2;
               a = 3;
               break;
            default:    //no debería llegar aquí
               de = -1;
               a = -1;
               break;
         }
      }
   }


Usually when we move a piece of one square to another, we are erasing what was in the first square, if we make a castling and the square initial and final of the King is the same we have to be careful not to remove the original square. And while the king has not been moved, we must upgrade the mask of castling.

Code: Select all
   // si la pieza está en su sitio no la debemos borrar, esto es pensando en el rey en chess960
   if (m.tipo == ENROQUE && m.a == m.de) {
      pieza[m.a] = pieza[m.de];
      color[m.a] = color[m.de];
      //desactivamos los enroques correspondientes aunque no hayamos movido el rey
      if (m.a == 62 || m.a == 58) enroque &= 12;
      if (m.a == 6 || m.a == 2) enroque &= 3;
   }
   else {
      pieza[m.a] = pieza[m.de];
      color[m.a] = color[m.de];
      pieza[m.de] = VACIO;
      color[m.de] = VACIO;
      //actualizar enroques despues de mover un rey o torre
      enroque &= enroque_mascara[m.de] & enroque_mascara[m.a];
   }


Lastly if we are making a castling we must move the rook to final square and we erase the square initial of rook if the square is not the square end of King in the castling.

Code: Select all
   // si estamos haciendo un enroque debemos mover la torre a su sitio
   if (m.tipo == ENROQUE) {
      if (a != de) {
         pieza[a] = TORRE;
         color[a] = color[de];
         if ((m.a == 62 && tb1 != 62) || (m.a == 6 && tn1 != 6) || (m.a == 58 && tb2 != 58) || (m.a == 2 && tn2 != 2)) {
            color[de] = VACIO;
            pieza[de] = VACIO;
         }
      }
   }


6) Undo (hard)

If we are undoing a castling, the first test to bring the rook to its original square while it will not be placed where it is still the king. In the opposite case we undo first the move of the king.

Code: Select all
   if (m.tipo == ENROQUE) { // colocamos la torre en su sitio si deshacemos el enroque
      switch(m.a) {
         case 62:
            de = 61;
            a = tb1;
            break;
         case 58:
            de = 59;
            a = tb2;
            break;
         case 6:
            de = 5;
            a = tn1;
            break;
         case 2:
            de = 3;
            a = tn2;
            break;
         default:  /* no debería llegar aquí */
            de = -1;
            a = -1;
            break;
      }
      /*si estamos deshaciendo un enroque, primero probamos a llevar la torre a su sitio original
       siempre y cuando no vaya a colocarse donde todavía está el rey*/
      if (a != de && a != 62 && a != 6 && a != 2 && a != 58) {
         pieza[a] = pieza[de];
         color[a] = color[de];
         color[de] = VACIO;
         pieza[de] = VACIO;
         td = VERDADERO;
      }
   }


Once undone the move of the king, if the rook had not been brought to its original square we do now, but only if the initial and final square of the rook in the castling is not the same and to move the rook, we have to remove the square initial when this is not the final position of the king.

Code: Select all
   if (m.tipo == ENROQUE) { // colocamos la torre en su sitio si deshacemos el enroque y todavía no lo hemos hecho
      if (!td && a != de) {
         pieza[a] = TORRE;
         color[a] = color[de];
         if (m.de != de) {
            color[de] = VACIO;
            pieza[de] = VACIO;
         }
      }
   }

Re: Winboard_F and chess960 (FRC)

PostPosted: 27 Nov 2007, 07:36
by PulsarMike
hi,

I'm pleased to see some work is being done on winboard and fischer random castling. I just started teaching pulsar, my chess program, http://www.adam16mr.org/pulsar.html to play fischer random this last week. It allready plays a number of variants including crazyhouse, atomic and 3check.

I started with arena and the clean and simple O-O and O-O-O is nice. but i got winboard X on friday or saterday and began programming for its d1f1 etc notation. It seems the first square like d1 indicates queen side castling. it seems odd the second square is f1 but i've gotten used to it.

Now here is the issue. While i have received caslte moves in this notation, my program castling has largely been broken but i fixed that last night. Its only tried to castle once, I think. From what i recall winboard sent the move to the ics ( i was playing online on a chess server, my program plays on both fics and icc) in its funny notation. Of course the ics rejected it as an illegal move expecting ooo or oo. I think this issue was raised earlier as far as other chess engines rejecting the move as well in engine matches.

I think its conceivable programmers will program for winboard_f if it plays a game of fr that covers all cases. But teh ics's wont change their code for it i suspect. Could winboard_f translate castle moves and output them to the servers ( ics's) as O-O or O-O-O at some point in the code just before send? Thats if i was accurate in gaging the behavior of winboard_x. I havent tried winboard_f yet but i'm interested it if plays a legally consistent game and can be used on an ics.

Just my thoughts,
and thanks for the effort and work that has gone into
both winboard_x and winboard_f
Mike Adams
adam16mr.org

Re: Winboard_F and chess960 (FRC)

PostPosted: 27 Nov 2007, 11:55
by H.G.Muller
As I said I have not really changed anything in the FRC castling code that was already put there by Tord and Fabien. I know that Winboard should understand both SAN input (like O-O and O-O-O) as well as coordinate notation. In coordinate notation you can either give the ToSquare of the King (which depends on board size for King-side castling), or the position of the Rook you castle with.

I think if it sends a move to the engine, it uses O-O(-O) if the variant is FRC, and King FromSquare and ToSquare in other variants.

Re: Winboard_F and chess960 (FRC)

PostPosted: 29 Nov 2007, 00:43
by Alessandro Scotti
H.G.Muller wrote:... with the option /variant=fischeRandom (with only a single R, I don't know why the variant is named like that) ...


IIRC it doesn't really matter how many "R" are there, the program just checks for the strings "Fischer" and "Random" separately.