jordanbray / chess

A rust library to manage chess move generation
https://jordanbray.github.io/chess/
MIT License
245 stars 57 forks source link

Support for a safe_legal_quick(board: &Board, chess_move: ChessMove) -> bool #43

Closed kchalkias closed 3 years ago

kchalkias commented 3 years ago

At the moment our only option to check if a user's input move (not sanitized) is valid is to invoke the greedy board's

pub fn legal(&self, m: ChessMove) -> bool {
    MoveGen::new_legal(&self).find(|x| *x == m).is_some()
}

Are there any plans to support a safe_legal_quick validator without enumerating every possible valid move but only evaluating the provided source-destination pair?

jordanbray commented 3 years ago

I don't think I plan to support this. I've spent some time thinking this proposal over, and I have a few problems with it.

  1. The code for that legal function is gonna grow out of control pretty quick. In fact, I'm not even sure it would outperform what exists right now.
  2. The only use case for this that I know of is sanitizing a move from a user (or other computer system). This wouldn't be used inside an engine, for example. This makes it a lot less performance critical.

What I might accept as a pull request is a function for MoveGen.

This might look like (very pseudo-code):

impl MoveGen {
    pub fn is_legal(&self, m: ChessMove) -> bool {
        for (q in self.square_and_bitboard) {
            if q.source == m.source {
                  if q.dest & m.get_dest() != EMPTY {
                        if m.is_promotion() && is_pawn && is_back_rank {
                            return true;
                        }
                  }
            }
        }
    }
}

This might improve the performance a bit, but I'm honestly not convinced it's even faster.

kchalkias commented 3 years ago

@jordanbray thanks for your response. I'm personally involved in projects where the requested functionality is very important, in blockchains. I actually evaluated your library before posting here as I couldn't find many worth exploring Rust crates for this purpose. The idea of allowing chess move validation in smart contracts is super useful, because users usually play using some UI off-chain, but report all of their moves on-chain. The latter means that the only logic required in blockchains is single move-verification and check for draw/win, and these should be performed in the most efficient way possible, because blockchain transactions are expensive.

For instance, Ethereum experiments have shown that the complexity of move validation logic might make Chess impractical as a candidate blockchain game. I personally contributed to implementing Chess in the Corda blockchain, in a project called lightning-chess; there were not restrictions back then on the size/complexity, so even a naive inefficient algorithm would work.

What makes your Rust implementation interesting is now there exist a blockchain in Rust, called Diem (formerly known as Libra, supported by Facebook). I was thinking of using your api to implement such a proof of concept smart contract, but it has to be light-weight of course. The blockchain shouldn't not allow invalid moves and this is where we usually need fast Chess move validators. I really appreciate your quick answer, I might give it a try on my spare time anyway. Thanks again.

jordanbray commented 3 years ago

I checked the code on the "Ethereum experiments" page, and they are using some pretty slow code to validate moves. Quite a lot slower than what I'm doing here.

In addition, I don't even see the code they use to validate checkmate, which is where they claim there problem is. https://github.com/ise-ethereum/on-chain-chess

I'm not sure their conclusion is valid, but I don't know. It could be impossible to store the magic bitboards inside a contract, perhaps they are too big? That would cause them to need to use code similar to what they used.

If I were trying to do what you're doing, I'd (1) start writing a move generator in that language (copy the code from here, etc), (2) check to see what the maximum size of constant data is within one of these "contracts". If you have a lot of space to work with, then there's no reason this shouldn't be pretty speedy.

jordanbray commented 3 years ago

I'm closing this. I simply don't have the interest in this function. If one lands on my lap, and seems to be faster, I'll be happy to accept it. However, I the maintenance burden on that specific function is pretty huge, and I doubt could be used for the desired use-case anyways.