legal moves vs pseudolegal moves

Discussion of chess software programming and technical issues.

Moderator: Ras

OliverBr
Posts: 794
Joined: Tue Dec 18, 2007 9:38 pm
Location: Munich, Germany
Full name: Dr. Oliver Brausch

legal moves vs pseudolegal moves

Post by OliverBr »

There are two ways of move generation: 1) Legal moves and 2) pseudolegal moves.

In 1) The generation itself ist more complicated, but there is no test needed.
In 2) Also "illegal" moves are generated, where the king could be captured. Later, in the search, those moves will be omitted.

OliThink uses 1) but it looks as it is one of the only engine who does it this way.

Is there are common sense, which way is the better, the more effective way? Oder it is just a matter of taste?
Chess Engine OliThink: http://brausch.org/home/chess
OliThink GitHub:https://github.com/olithink
AndrewGrant
Posts: 1955
Joined: Tue Apr 19, 2016 6:08 am
Location: U.S.A
Full name: Andrew Grant

Re: legal moves vs pseudolegal moves

Post by AndrewGrant »

Pseudo is almost certainly faster in practice. You can make some minimal efforts to reduce the # of illegal moves generated with cheap operations. For example, if attackers > 2, return only king moves. If attackers == 1, do some masking to either only capture or block the attack and/or move the king. It would be nice if pure legal was faster, but it is just not. Especially when you consider that you might prune an illegal move without ever verifying it is correct.
Aldus
Posts: 27
Joined: Mon Sep 03, 2018 12:59 pm
Location: Romania
Full name: Cristi Ilovan

Re: legal moves vs pseudolegal moves

Post by Aldus »

If you have 36 pseudo-legal moves and after searching 2 of them you get a cutoff, you no longer need to test the legality of the remaining 34. Move generation can be kept simple and the legality test is only performed for the first 2 moves (in Search).

Being lazy really pays off. :)
expositor
Posts: 60
Joined: Sat Dec 11, 2021 5:03 am
Full name: expositor

Re: legal moves vs pseudolegal moves

Post by expositor »

OliThink uses 1) but it looks as it is one of the only engine who does it this way.
Expositor does legal-only move generation, too! and the move generator includes a fair amount of information in each move it emits:
  • source square
  • destination square
  • the kind of piece moving
  • the kind of piece a pawn is promoting to
  • the kind of piece being captured
  • a bitmask characterizing the move type, such as whether it is a manoeuvre, capture, castling move, pawn manoeuvre, pawn capture, capture en passant, promotion, or capture by promotion
  • whether the move gives direct check
  • whether the move gives discovered check
Each move is one machine word (eight bytes), but these are lossily compressed down to two bytes for storage in the transposition table.

I was getting single-threaded perft numbers of around 35 to 50 Mnps (depending on the position) before I added the updates to NNUE first-layer activations during move application, which was fast enough for my needs.

Although I certainly prefer doing it this way (i.e. legal-only move generation), it's hard to say whether I'd recommend it to anyone.
Patrice Duhamel
Posts: 194
Joined: Sat May 25, 2013 11:17 am
Location: France
Full name: Patrice Duhamel

Re: legal moves vs pseudolegal moves

Post by Patrice Duhamel »

AndrewGrant wrote: Wed Jan 18, 2023 5:37 am Especially when you consider that you might prune an illegal move without ever verifying it is correct.
This will change the move count used for LMR and LMP ?
Anything that can go wrong will go wrong.
User avatar
hgm
Posts: 28353
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: legal moves vs pseudolegal moves

Post by hgm »

It all depends on how you test the legality. If you do that on a per-move basis for each pseudo-legal move you generate, it is petty obvious that it is better to postpone such testing to the point where the move comes up for searching. Otherwise you would be subjecting many moves that you would never even want to search to the test. And the worst way to do such a test is through a general IsKingAttacked() routine, making no use about known characteristics of the current position (such as whether you are in check and which piece is checking you) and the move.

There are methods to do 'bulk-testing', where a simple test decides about the legality of an entire group of moves. Then it is not so clear. E.g., when a piece is pinned, it would make a lot of its moves illegal. So your initial move generator could start testing whether the piece it is going to generate moes for is pinned, and if it is, fall back on generation code that only generates moves along the pin ray (which presumably is known as a side effect of the pin test). That would not only relieve you of the necessity to test whether the move with the piece discovered a check on your King, but it would actually save time during the generation of the pseudo-legal moves, as you now have to generate fewer.

The case of being in check was already mentioned. King moves will always be potential evasions, but on a double check these are the only moves you have to generate and verify. On a contact check you only have to generate capture of the checker, which usually can be done far faster than generating all moves, and testing each of those for whether they capture the checker.
User avatar
lithander
Posts: 915
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: legal moves vs pseudolegal moves

Post by lithander »

In the last couple of days I've worked on something that could probably be called semi-legal move generation where there's a dedicated bit in the move to store whether this move needs to be validated or not. I hope that this will give me the best of both worlds because for about 50% of the moves it's trivial to say they are legal. But when it would be expensive to filter out the illegal moves I just generate them all but their flag indicates that it's not safe to play them without the validation through IsKingAttacked() afterwards.
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
abulmo2
Posts: 465
Joined: Fri Dec 16, 2016 11:04 am
Location: France
Full name: Richard Delorme

Re: legal moves vs pseudolegal moves

Post by abulmo2 »

OliverBr wrote: Wed Jan 18, 2023 3:52 am There are two ways of move generation: 1) Legal moves and 2) pseudolegal moves.

In 1) The generation itself ist more complicated, but there is no test needed.
In 2) Also "illegal" moves are generated, where the king could be captured. Later, in the search, those moves will be omitted.

OliThink uses 1) but it looks as it is one of the only engine who does it this way.

Is there are common sense, which way is the better, the more effective way? Oder it is just a matter of taste?
Olithink is not alone. My too engines, Amoeba and Dumb only generate legal moves too. I do not believe that Olithink Amoeba or Dumb can be qualified as slow engines. So I think it is just a matter of taste.
Richard Delorme
alessandro
Posts: 52
Joined: Tue Aug 12, 2014 11:21 am
Location: Lund
Full name: Alessandro Iavicoli

Re: legal moves vs pseudolegal moves

Post by alessandro »

OliverBr wrote: Wed Jan 18, 2023 3:52 am There are two ways of move generation: 1) Legal moves and 2) pseudolegal moves.

In 1) The generation itself ist more complicated, but there is no test needed.
In 2) Also "illegal" moves are generated, where the king could be captured. Later, in the search, those moves will be omitted.

OliThink uses 1) but it looks as it is one of the only engine who does it this way.

Is there are common sense, which way is the better, the more effective way? Oder it is just a matter of taste?
AdaChess do generate legal moves. The move generator is optimized and smart enought to test for legalty only when necessary and in a relatively optmized way.

Some considerations:
1) Engines spent 5-10% of their time in generating moves, therefore a fast generator can be "fast enough" without the need to optimize it further.
2) If the procedure to test for legality is smart enough, it won't waste too much time to check it.
3) Although I havent a proof, I suspect that a legal move generator can be implemented smart enough to be even faster than a pseudo legal (consider the situation of an absolute-pinned queen: a smart generator detect it and accept moves only along the pinned direction(s). A pseudo-legal will loop through all the queen moves wasting a lot of effort. Another example: a king under double-check can only escape from his position, avoiding the generation of pseudo legal moves that will be only waste of time.. AdaChess do generate moves this way and the algorithm is well optimized and, imho, very good and cool :)
4) Generating pseudo legal moves is also more error prone because you can't prove the correctenss easily in a perft test.
--
AdaChess - Smart Chess Engine - https://github.com/adachess/AdaChess

Image
User avatar
Bo Persson
Posts: 257
Joined: Sat Mar 11, 2006 8:31 am
Location: Malmö, Sweden
Full name: Bo Persson

Re: legal moves vs pseudolegal moves

Post by Bo Persson »

alessandro wrote: Sat Jan 21, 2023 2:01 pm
3) Although I havent a proof, I suspect that a legal move generator can be implemented smart enough to be even faster than a pseudo legal (consider the situation of an absolute-pinned queen: a smart generator detect it and accept moves only along the pinned direction(s). A pseudo-legal will loop through all the queen moves wasting a lot of effort. Another example: a king under double-check can only escape from his position, avoiding the generation of pseudo legal moves that will be only waste of time.. AdaChess do generate moves this way and the algorithm is well optimized and, imho, very good and cool :)
The counter argument is of course that in most positions the queen is not pinned, and the king is hardly ever double-checked. So does this save any search time, or does it only complicate the code?