XBoard for Mac: draw non-recognition, feature or bug?

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

XBoard for Mac: draw non-recognition, feature or bug?

Post by sje »

Yesterday I added XBoard interface support to the Symbolic re-write and left it running overnight in a match vs tscp on a Mac.

In one game, Symbolic's simple, not-yet-pondering single threaded search got it into a position which resulted in a draw by the fifty move rule. (It was tscp which made the 100th consecutive quiet move.) But apparently XBoard didn't see or adjudicate the draw and instead told Symbolic to make a move. Well, Symbolic is kind of stubborn and doesn't like to move after a game is drawn.

If it makes any difference, Symbolic's XBoard support in its current state uses protocol version one only. The program recognizes only 22 commands:

Code: Select all

const std::string XbdCoPro::cmdstrvec[XcpCLen] =
{
  "black",
  "computer",
  "easy",
  "force",
  "go",
  "hard",
  "hint",
  "level",
  "new",
  "nopost",
  "otim",
  "post",
  "quit",
  "random",
  "remove",
  "result",
  "sd",
  "st",
  "time",
  "undo",
  "white",
  "xboard"
};
But at least it can match a command string quickly:

Code: Select all

XcpC XbdCoPro::MatchName(const std::string& verb)
{
  XcpC result = XcpCNil;
  si lo = 0, hi = XcpCLen - 1;

  while (IsXcpCNil(result) && (lo <= hi))
  {
    const si mi = (lo + hi) / 2;

    if (verb == cmdstrvec[mi])
      result = (XcpC) mi;
    else
    {
      if (verb < cmdstrvec[mi])
        hi = mi - 1;
      else
        lo = mi + 1;
    };
  };
  return result;
}
And so those multi-page if/then/else cascades can be avoided with:

Code: Select all

void XbdCoPro::Dispatch(void)
{
  const TokenNodePtr tnptr = tokens.GetHead();

  if (tnptr)
  {
    const XcpC xcpc = MatchName(tnptr->RefStr());

    if (IsXcpCNotNil(xcpc))
    {
      switch (xcpc)
      {
        case XcpCblack:    DoCblack();    break;
        case XcpCcomputer: DoCcomputer(); break;
        case XcpCeasy:     DoCeasy();     break;
        case XcpCforce:    DoCforce();    break;
        case XcpCgo:       DoCgo();       break;
        case XcpChard:     DoChard();     break;
        case XcpChint:     DoChint();     break;
        case XcpClevel:    DoClevel();    break;
        case XcpCnew:      DoCnew();      break;
        case XcpCnopost:   DoCnopost();   break;
        case XcpCotim:     DoCotim();     break;
        case XcpCpost:     DoCpost();     break;
        case XcpCquit:     DoCquit();     break;
        case XcpCrandom:   DoCrandom();   break;
        case XcpCremove:   DoCremove();   break;
        case XcpCresult:   DoCresult();   break;
        case XcpCsd:       DoCsd();       break;
        case XcpCst:       DoCst();       break;
        case XcpCtime:     DoCtime();     break;
        case XcpCundo:     DoCundo();     break;
        case XcpCwhite:    DoCwhite();    break;
        case XcpCxboard:   DoCxboard();   break;
        default:
          SwitchFault("XbdCoPro::Dispatch");
          break;
      };
      if (!isrunning)
        LogMsg("XbdCoPro::Dispatch: quit commanded");
    }
    else
    {
      // Handle move input

      Move move;

      if (!move.DecodeUCI(tokens.Arg(0), MyPosition()))
        WriteLn("Unregonized input");
      else
      {
        OppoMove(move);
        if ((progcolor != ColorVacant) && MyGame().IsNotOver())
          ProgMove(CalcMove());
      };
    };
  };
}
Also, a public thank-you goes out to Tom Kerrigan, the author of tscp. By the way, it appears that tscp won't recognize under-promotion moves if a lower case piece letter (UCI style) is used. This can be easily fixed by adding a few case labels in the parse_move() routine.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: XBoard for Mac: draw non-recognition, feature or bug?

Post by bob »

sje wrote:Yesterday I added XBoard interface support to the Symbolic re-write and left it running overnight in a match vs tscp on a Mac.

In one game, Symbolic's simple, not-yet-pondering single threaded search got it into a position which resulted in a draw by the fifty move rule. (It was tscp which made the 100th consecutive quiet move.) But apparently XBoard didn't see or adjudicate the draw and instead told Symbolic to make a move. Well, Symbolic is kind of stubborn and doesn't like to move after a game is drawn.

If it makes any difference, Symbolic's XBoard support in its current state uses protocol version one only. The program recognizes only 22 commands:

Code: Select all

const std::string XbdCoPro::cmdstrvec[XcpCLen] =
{
  "black",
  "computer",
  "easy",
  "force",
  "go",
  "hard",
  "hint",
  "level",
  "new",
  "nopost",
  "otim",
  "post",
  "quit",
  "random",
  "remove",
  "result",
  "sd",
  "st",
  "time",
  "undo",
  "white",
  "xboard"
};
But at least it can match a command string quickly:

Code: Select all

XcpC XbdCoPro::MatchName(const std::string& verb)
{
  XcpC result = XcpCNil;
  si lo = 0, hi = XcpCLen - 1;

  while (IsXcpCNil(result) && (lo <= hi))
  {
    const si mi = (lo + hi) / 2;

    if (verb == cmdstrvec[mi])
      result = (XcpC) mi;
    else
    {
      if (verb < cmdstrvec[mi])
        hi = mi - 1;
      else
        lo = mi + 1;
    };
  };
  return result;
}
And so those multi-page if/then/else cascades can be avoided with:

Code: Select all

void XbdCoPro::Dispatch(void)
{
  const TokenNodePtr tnptr = tokens.GetHead();

  if (tnptr)
  {
    const XcpC xcpc = MatchName(tnptr->RefStr());

    if (IsXcpCNotNil(xcpc))
    {
      switch (xcpc)
      {
        case XcpCblack:    DoCblack();    break;
        case XcpCcomputer: DoCcomputer(); break;
        case XcpCeasy:     DoCeasy();     break;
        case XcpCforce:    DoCforce();    break;
        case XcpCgo:       DoCgo();       break;
        case XcpChard:     DoChard();     break;
        case XcpChint:     DoChint();     break;
        case XcpClevel:    DoClevel();    break;
        case XcpCnew:      DoCnew();      break;
        case XcpCnopost:   DoCnopost();   break;
        case XcpCotim:     DoCotim();     break;
        case XcpCpost:     DoCpost();     break;
        case XcpCquit:     DoCquit();     break;
        case XcpCrandom:   DoCrandom();   break;
        case XcpCremove:   DoCremove();   break;
        case XcpCresult:   DoCresult();   break;
        case XcpCsd:       DoCsd();       break;
        case XcpCst:       DoCst();       break;
        case XcpCtime:     DoCtime();     break;
        case XcpCundo:     DoCundo();     break;
        case XcpCwhite:    DoCwhite();    break;
        case XcpCxboard:   DoCxboard();   break;
        default:
          SwitchFault("XbdCoPro::Dispatch");
          break;
      };
      if (!isrunning)
        LogMsg("XbdCoPro::Dispatch: quit commanded");
    }
    else
    {
      // Handle move input

      Move move;

      if (!move.DecodeUCI(tokens.Arg(0), MyPosition()))
        WriteLn("Unregonized input");
      else
      {
        OppoMove(move);
        if ((progcolor != ColorVacant) && MyGame().IsNotOver())
          ProgMove(CalcMove());
      };
    };
  };
}
Also, a public thank-you goes out to Tom Kerrigan, the author of tscp. By the way, it appears that tscp won't recognize under-promotion moves if a lower case piece letter (UCI style) is used. This can be easily fixed by adding a few case labels in the parse_move() routine.
A couple of things.

(1) 50 move draws are NOT forced draws. One side has to claim the draw. Or if he doesn't want the other side to claim the draw, he has to make a move that resets the counter. If he doesn't, the other side can either claim the draw or he can also decline to do so and the game has to continue. Same thing for repetitions.

(2) as a result, you must be prepared to make a move after the 50 move counter is reached since the opponent doesn't have to make the claim. YOU, on the other hand, can claim a 50 move draw before you make a move, or after you make a move, if the counter has been satisfied before your move or else after you make a move.

By the rules of chess, you would have lost that game if you didn't either claim the draw instantly, or else make a move and then claim the draw...
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: XBoard for Mac: draw non-recognition, feature or bug?

Post by sje »

bob wrote:By the rules of chess, you would have lost that game if you didn't either claim the draw instantly, or else make a move and then claim the draw...
I'm quite familiar with the rules. What I do not understand is why XBoard will adjudicate a draw based on insufficient material but will not adjudicate a draw based on the fifty move rule.
Robert Pope
Posts: 564
Joined: Sat Mar 25, 2006 8:27 pm
Location: USA
Full name: Robert Pope

Re: XBoard for Mac: draw non-recognition, feature or bug?

Post by Robert Pope »

What setting are you using for adjudicating draws? Xboard should be able to do it either way, depending on your settings.

http://hgm.nubati.net/xboard/winboard/help/html/17.htm
matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Re: XBoard for Mac: draw non-recognition, feature or bug?

Post by matthewlai »

sje wrote:
bob wrote:By the rules of chess, you would have lost that game if you didn't either claim the draw instantly, or else make a move and then claim the draw...
I'm quite familiar with the rules. What I do not understand is why XBoard will adjudicate a draw based on insufficient material but will not adjudicate a draw based on the fifty move rule.
Because insufficient material draws ARE forced draws. The players can't agree to play on even if they wanted to. Fifty moves or 3-fold draws aren't.
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: XBoard for Mac: draw non-recognition, feature or bug?

Post by bob »

sje wrote:
bob wrote:By the rules of chess, you would have lost that game if you didn't either claim the draw instantly, or else make a move and then claim the draw...
I'm quite familiar with the rules. What I do not understand is why XBoard will adjudicate a draw based on insufficient material but will not adjudicate a draw based on the fifty move rule.
I believe the FIDE rules address insufficient material. From FIDE:

The game is drawn when the player to move has no legal move and his king is not in check. The game is said to end in ‘stalemate’. This immediately ends the game, provided that the move producing the stalemate position was in accordance with Article 3 and Articles 4.2 – 4.7.

The game is drawn when a position has arisen in which neither player can checkmate the opponent’s king with any series of legal moves. The game is said to end in a ‘dead position’. This immediately ends the game, provided that the move producing the position was in accordance with Article 3 and Articles 4.2 – 4.7.

The game is drawn upon agreement between the two players during the game. This immediately ends the game.

The game may be drawn if an identical position is about to appear or has appeared on the chessboard at least three times (see Article 9.2).
The game may be drawn if each player has made at least the last 50 moves without the movement of any pawn and without any capture (see Article 9.3).

Insufficient material seems to be under the "dead position" clause...
User avatar
hgm
Posts: 28354
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: XBoard for Mac: draw non-recognition, feature or bug?

Post by hgm »

Indeed, Bob is right: in FIDE rules insufficient mating material is an automatic game end (like checkmate and stalemate), but 50-move and rep-draws are not, and have to be claimed by either player. XBoard just tries to follow FIDE rules in this respect.

There is a caveat: FIDE rules also stipulate an automatic draw for positions like
[d]4k3/8/8/p2p2p1/P2P2P1/8/8/4K3 w
where no conceivable series of legal moves can lead to mate. GUIs are in general not smart enough to validate such claims, and the protocol specs forbids programs to claim them. (Which they otherwise vould with a 1/2-1/2 command.) The KK, KBK, KNK and KBKB (like B) should be recognized, however. (But not KNNK, KBKN, KNKN, KBKB (unlike B), where according to FIDE rules draws are not even claimable, let alone automatic!)

Note that for convenience XBoard has an Adjudications menu dialog, where you can choose what conditions to adjudicate, how many reps or reversible moves have to occur before a draw is adjudicated, etc. This also because not all variants might have the same rules for this. (KNK is a win in Xiangqi; Makruk uses a 64-move rule, etc.) I think the default setting here is that XBoard would adjudicate draw only after 6 repeats or 51 reversible moves, to allow users to test the claim logic of their engine, ratherthan bypass it by immediate adjudication. (But still preventing non-claiming engines to continue forever.)
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: XBoard for Mac: draw non-recognition, feature or bug?

Post by sje »

I've modified Symbolic to keep on playing past a non-stalemate draw as a short term treatment.

Using XBoard protocol version one, is there a way for a program to claim a non-stalemate draw? This would be a better solution.
User avatar
hgm
Posts: 28354
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: XBoard for Mac: draw non-recognition, feature or bug?

Post by hgm »

There is, but it actually is a tricky thing because of a race condition when you want to make a claim pertaining to the position after your move. Because the protocol does not have a combined atomic move & claim. So the opponent could play an instant move between your move and the claim, making the claim invalid, while it would also be invalid before your moved, so you cannot claim first.

The protocol supports 2 engine->GUI commands to claim a draw:

1/2-1/2 {REASON}

where REASON can be any text (and the whole {REASON} part is optional). This command informs the GUI that the engine considers the game terminated, and won't play on no matter what. It should e used for stalemates and 50-move/rep-draw claims during your own move, which cannot be refused. Then there is

offer draw

which requests a draw that might be refused. This request will then be considered effective until your second move from when it is made. XBoard (and ICC) will honor such a pending request on their own autority when the 50-move or rep-draw condition is satisfied, in particular immediately after your next move. If no claimable draw emerges from your next move, a draw offer will be made to the opponnent at that time. Unless the opponent already had such an offer pending as well, in which case the game immediately ends as a draw.
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Questions

Post by sje »

hgm wrote:The protocol supports 2 engine->GUI commands to claim a draw:

1/2-1/2 {REASON}

where REASON can be any text (and the whole {REASON} part is optional). This command informs the GUI that the engine considers the game terminated, and won't play on no matter what. It should e used for stalemates and 50-move/rep-draw claims during your own move, which cannot be refused.
Does XBoard check to see if a program's draw claim is valid?

I haven't seen any stalemates yet; I thought that XBoard handled these just like it handles checkmates (which appears to be correct).

If my program makes a move which results in a fifty move draw, should it also send the 1/2-1/2 string immediately afterward? If my program gets a position which is already a fifty move draw, should it: A) move, B) send 1/2-1/2, C) do A then B, or D) do B then A? At present, it just sends a move although this is not a good solution.

Same question as above for threefold, insufficient, and stalemate.

Perhaps I should support XBoard protocol version two in the re-write, just as it was supported before the re-write. I admit to not have done much interface coding in a few years, so my knowledge on the topic may be out of date.

----

I had thought about not providing XBoard interface support and use UCI instead. But with a somewhat native Mac OS/X version of XBoard working, I reconsidered. But I also intend to have UCI support, and until the past few days, there was more UCI support in the re-write than there was for XBoard.

In the long term, I think the best approach is to develop new protocols for command/status communication and also for the actual transfer mechanism -- and they should be separate.

For command/status communication, there is a need for atomic operators which bundle together disperse data items to avoid synchronization difficulties. Instead of a text line format, a more general representation like XML could be used and free open source tools would be provided to help authors.

The separate specification for data transfer would abandon the old fashioned I/O pipes, signals, and their associated idiosyncrasies -- replacing them with the more modern and portable TCP/IP.

A chess program using the new protocals might not even need a GUI mediator, or any mediator at all. The program could be written just like any other program driven by an event loop with the connected opponent (or GUI) being just another event source.

While a GUI could start the chess program, the program could also be invoked separately and perhaps could run as just another server/service.