lichess.org
Donate

Improvements for the immediate draw rule

In a game, when neither side can checkmate the other, the game should be immediately drawn. However, if a checkmate is possible, no matter how, then the game should continue.

For example, this game should go on, because white can win with Ng6#:
(A) lichess.org/tr6za6qg

This game should be drawn immediately, because neither side can deliver a checkmate:
(B) lichess.org/pnenns77

This game should be drawn as well, but there's no quick way to detect it:
(C) lichess.org/5f98pco2

I suggest you to change the implementation according to the following list - it would be an easy patch for examples A and B, while there's nothing we can do about example C:

>>>>
If

(White has nothing but a king), and (Black has nothing but a king and one knight), or

(White has nothing but a king and one knight), and (Black has nothing but a king), or

(White has nothing but a king and (zero or more same-square-coloured bishops)), and (Black has nothing but a king and (zero or more bishops that are of the same square colour as White's bishops)),

then the game is immediately drawn.
<<<<

P.S.:
Thanks, Mephostophilis! The list idea is better than I thought!
Case A can be avoided easily enough by assuming that you can always stand a chance of checkmating if you have a King+Knight vs. King+x, where x is anything except:
1) nothing (only the King)
2) 1 or more major pieces (a major piece is always either a rook or a Queen), and no minor pieces (bishop, knight)

of course if #2 applies, then it is not draw by Insufficient Material, only by timeout if the side with the major piece(s) and no minor pieces times out.

So yeah, King+Knight v. King is on its own isle.
Everything else currently supported by this site's detection of Insufficient Material revolves all around bishops and nothing else.
Currently your list is about the same as current Lichess rules except, you add support for the possibility of more than just 1 bishop, but they are all same-square-color.

This is easy enough to add to the site, but I would wager that case C is a lot more likely to happen than case B (and a lot harder to algorithmically detect than case B), so I would not worry too deeply over the change, so much as fixing the draw false assumptions on timeout.
>>Case A can be avoided easily enough by assuming that you can always stand a chance of checkmating if you have ...<<
Have a close look into the link I provided for example A. Use the replay and analyse feature to see the last two (half)moves before the (false) automatic draw.

You'll see that example A is actually a forced checkmate sequence against Black. Black had no way to avoid being checkmated this way, at least not within the last two moves. Likewise, there was no way for White to force a checkmate with fewer moves than this way.
The example could be extended to have any length of forced checkmate sequence.

Example B of course is not really likely to happen; but neither is it difficult to implement: For the computer, it's not more difficult check for multiple bishops than just for one.

I think this would be a very easy thing to implement, especially because it can use shared source code with the implementation of the other list I posted just before.
Actually these two lists are very similiar, because this one, the immediate draw rule, is just a special case of the other one, the more general timeout rule; i.e. "neither side can checkmate the other" is just a special case of the more general "one side cannot chckmate the other".
So, if both lists get implemented, the overall amount of code to write could even be smaller than if just one of them is implemented, due to their inherent correlation.

Example C is just one of the examples of the website you posted at the very beginning: I think there's no way of improving this without requesting an engine's helpmate analysis after every player's move. As people here want to play rapid 0+1 and 1+0 timed games, there's no way of doing this, because such analysis can take up to a second of CPU time.
Wow...so, you're saying, A was drawn automatically?

Right after 35...Bxg8, Lichess showed a draw right in front of your face before you could reply 36.Ng6#?

I didn't know it was that bad. :D

Jesus Christ, where on the Internet, anywhere, does it say King + Bishop v. King + Knight is automatically a draw?

The implementation is more flawed than I thought.

Yeah, forget example C. It's way less common to happen on compared to the game dougthehead posted. I would prioritize on that.
I agree with the idea posted at the top of the page

If a checkmate is possible (even if it required terrible helpmate level play), then there is no draw. It is the duty of the person who can be checkmated to demonstrate that he/she can avoid the checkmate until time expires or until the pieces change so that a checkmate isn't possible.

If a game has come down to that point, then the 50 move rule can draw the game should the player that can be mated play acceptable defense. This would be an acceptable way to deal with those situations so that they don't continue endlessly.

chesscaptcha! :D
>>Wow...so, you're saying, A was drawn automatically?

Right after 35...Bxg8, Lichess showed a draw right in front of your face before you could reply 36.Ng6#?<<

Yes, exactly! :-)

>>Jesus Christ, where on the Internet, anywhere, does it say King + Bishop v. King + Knight is automatically a draw?<<

I can show you, here it is:

file github.com/ornicar/scalachess/blob/master/src/main/scala/Board.scala
lines 115 and following

>>>>
def autoDraw: Boolean =
history.positionHashes.size > 100 ||
(Color.all forall { !hasEnoughMaterialToMate(_) })

def hasEnoughMaterialToMate(color: Color) =
rolesOf(color) filterNot (_ == King) match {
case roles if roles.size > 1 => true
case List(Knight) => false
case List(Bishop) => false
case Nil => false
case _ => true
}
<<<<

You can see that an automatic draw in this implementation is very specifically defined to be triggered when there are more than 100 position hashes in the history (???), or when neither side "hasEnoughMaterialToMate". And this "hasEnoughMaterialToMate" is defined as having more than one piece, or having one piece that is not knight or bishop.

So in the king+knight vs. king+bishop example, "hasEnoughMaterialToMate" returns false for both sides, and thus the game is drawn immediately. :-(

I have the gut feeling that this "hasEnoughMaterialToMate" function is also called from the code that has to decide between draw or loss on timeout. Unfortunately I haven't found the corresponding location in the source code yet.

So, how can we patch that?

I think the idea to trigger an automatic draw when neither side "hasEnoughMaterialToMate" is quite good. Outsourcing the definition of enough material to mate into a separate function, appears better to me than hardcoding a set of conditions into the "autoDraw" function.
This way we can use the same definition of the "hasEnoughMaterialToMate" function in two places: It is called on timeout to check whether the non-timeout'ed player has the ability to checkmate the timeout'ed player; and it is called twice (once for each player) after every move to check whether an automatic draw should be triggered.

The only thing we need to change is the defintion of the "hasEnoughMaterialToMate" function.
I suggest to change it according to the list of material conditions I recently posted in the other thread.

So, patch suggestion:

file github.com/ornicar/scalachess/blob/master/src/main/scala/Board.scala
line 119, function chess.Board.hasEnoughMaterialToMate(color:Color)
>>>>
def hasEnoughMaterialToMate(color:Color) = !{
val playerRoles = rolesOf(color) filterNot (_ == King)
val opponentRoles = rolesOf(!color) filterNot (_ == King)

// Player has nothing but a king, or
playerRoles == Nil ||

// (Player has nothing but a king and one knight, and
(playerRoles == List(Knight) &&

// Opponent has nothing but a king and (zero or more queens)), or
opponentRoles filterNot (_ == Queen) == Nil) ||

// (Player has nothing but a king and (one or more bishops), and
(playerRoles filter (_ == Bishop) != Nil && playerRoles filterNot (_ == Bishop) == Nil &&

// Opponent has nothing but a king and (zero or more out of queens, rooks, and bishops), and
opponentRoles filterNot (_ == Queen || _ == Rook || _ == Bishop) == Nil &&

// all bishops are of the same square colour)
{ val allBishops = pieces filter (_._2 is Bishop)
val squareColor = (allBishops.head._1.x + allBishops.head._1.y) % 2
allBishops filterNot ((_._1.x + _._1.y) % 2 == squareColor) == Nil
})
}
<<<<

This is just a first and very vague draft, so nothing to rely on. We need some developer to test and error check it (Thibby, where are you?). I'm not familiar with Scala, so it will probably have some syntax errors.

Comments, suggestions? Please post!
I really don't understand Scala as well as you do (or anybody else on here really :P), so it's all Japanese to me.

But, if you can get Lichess to compile and/or setup a Git repository where you can fork Lichess and do a pull request to thibault with your suggested change, I'm sure he'll be happy to adopt it if it fixes the problem when he gets back from (Brazil? Afghanistan? Antarctica?) to where he can code.
mephos is right! The code looks good, especially for someone who claims not to know scala well. Please compile and test that, and send a pull request on github.
err..., that's gonna be difficult: I'm traveling, too, and I can't install the dev tools in some internet cafe :-(

Of course, I could do a pull request on github, but how would that help if the code isn't tested?

Are there any other developers outthere? Familiar with Lichess, maybe already having cloned the repository? Anyone with compilation/testing environment could help.

Otherwise, we'd have to wait until the first one of us returns home :-(

This topic has been archived and can no longer be replied to.