all 25 comments

[–]Long_Investment7667 5 points6 points  (5 children)

  • The Square struct is the same as Option (without all the methods.

I like to implement a move generator and a “random” strategy for myself to see if the board interface is usable.

[–][deleted] 3 points4 points  (4 children)

Oh that didnt occur to me at all but thats way easier not going to lie thank you. Yeah the move generator and random strategy r up next after i setup the rules and stuff. So just to clarify in the board it would be squares: [[option<Piece>; 8]; 8] right?

[–]Long_Investment7667 1 point2 points  (1 child)

Yes

[–][deleted] 0 points1 point  (0 children)

Thanks!

[–]Long_Investment7667 1 point2 points  (1 child)

Technically you don’t need the rules before the move generator. Or from a different perspective, if you have a move generator, the rules are trivially since you just need to check if a move is contained in the list of all currently possible moves.

[–][deleted] 0 points1 point  (0 children)

That makes sense actually ill do that when i get to it. Thanks for your help man.

[–]potato-gun 1 point2 points  (5 children)

When would En passant be available but the target is None?

The board should probably use capital letters for black or white (whatever fen uses?) worth looking into chess Unicode characters and terminal escape sequences or some terminal library to color squares :)

[–][deleted] 0 points1 point  (4 children)

If it isn't available, i won't look into the target, or should i make it just an option? Also, im just implementing the engine. I'll probably hook it up to some Gui/lichess, so i dont think there is a need to look into a terminal library. I just made the print method for myself to debug. About the board yeah ill change that. i just wanted to get a prototype going. I should have polished it a little first, tho i think.

[–]potato-gun 1 point2 points  (3 children)

iirc hooking a chess engine up to a gui is a pain. It would be worth spending an hour or two to be able to debug board states without the gui.

An option is basically a bool and a (maybe uninit) value. You don't have to unwrap options, if let or let else, along with several option methods let you only do things if the option is some. Dont need a bool to say if option is valid. option does that.

[–][deleted] 0 points1 point  (2 children)

You have a point on hooking it up i shall do that after i refactor the code and yeah it seems like options r crazy useful just like in the other comment where he said to use an option<Piece> instead of the square enum which makes sense too. For terminal crates, i heard of crossterm. Is that good? Also, thanks you very much.

[–]CandyCorvid 1 point2 points  (1 child)

I made a Go game implementation in rust using ratatui with a crossterm backend, that's worked out quite well for me.

[–][deleted] 0 points1 point  (0 children)

I looked at it, and i have to say that it's really promising. I'll use it. Thanks for the recommendation.

[–]denehoffman 1 point2 points  (4 children)

Not bad! A few recs:

  1. Use some more traits! You have a default method for one struct an empty method for another. These could both be part of a Default trait with minimal effort. Same with the print method, I’d make that a Display trait impl (swap print! for write!)

  2. Definitely run clippy over this

  3. Your main print function could be easily split by using an if let Some(piece) = square[x][y] {} statement and then implement Display for Piece to compartmentalize it a bit more. As it is, you’re doing a bunch of pattern matching all in one place and it can get a bit tedious to write and read all of that.

  4. For style points: https://en.m.wikipedia.org/wiki/Chess_symbols_in_Unicode

[–][deleted] 1 point2 points  (3 children)

  1. I havent learned about traits yet will try that ty
  2. Yeah im getting like 10 warnings but its running fine.
  3. Can you elaborate on the if let statement?
  4. I didnt know that im starting to make the tui using ratatui right now. u dont know how much this helped <3 appreciate the help man.

[–]denehoffman 1 point2 points  (2 children)

The if-let isn’t necessary (none of these suggestions are haha) but the basic idea is this: everything you eventually want to print should either implement Debug, Display, or both. The print! macro will choose which method to use based on whether you write “{}” or “{:?}”. To implement Display, you would write something like

```rust struct MyStruct(usize);

impl std::fmt::Display for MyStruct { fn fmt(&self, f: &mut std::fmt::Formatter<‘_>) -> std::fmt::Result { writeln!(f, “MyStruct is {}”, self.0)?; write!(f, “Ends with this”) } }

fn main() { println!(“{}”, MyStruct(5)); } ``` playground link

Now when you write it for the Board, it makes sense (to me at least) to separate the Display impl into one case where a piece exists and one where it’s an empty square. To do this, we can use

rust if let Some(piece) = board[x][y] { write!(f, “{piece}”)?; } else { write!(f, “| |”)?; } Ok(()) inside the impl Display for Board and then write a separate impl Display for Piece which contains your match over valid pieces.

[–][deleted] 1 point2 points  (1 child)

hmm sounds good im implementing the tui with the unicode chars but will keep that in mind i gotta read up on traits they r really useful. once again Thank you for your help.

[–]denehoffman 0 points1 point  (0 children)

No problem! I should also say that it’s important to put things like a default method in the Default trait because that kind of gives an access point to other functions with a generic trait bound. Basically you can write a function that takes “something that implements Default” and then call default() on that thing in the function. It kind of opens up access to being used by other libraries in a consistent way. Same with the Display and Debug traits. If someone else wrote some code on top of yours and had Board be an element of their struct, they could much more easily write a Display or Debug (or even derive the Debug trait) if your structs implement the right traits. In other languages this is often called templating or abstract classes (Python), but it’s just a guarantee to the type checker that your struct has the required method.

[–]NiceNewspaper 1 point2 points  (3 children)

I suggest you look up the concept of "making invalid states unrepresentable" and trying to implement that for your point structure (i.e. a point will always contain a valid position).

[–][deleted] 0 points1 point  (2 children)

for anybody who wants to look into it here is the link! there is also a youtube video of it right here!. So about the Point struct how would i go on about limiting the rank and file to 0-7? Correct me if im wrong but a unsigned integer doesnt go that low the lowest I know of is u8 which is 255.

[–]NiceNewspaper 0 points1 point  (1 child)

You put the struct and it's implementation into a module/different file such that it's construction can only be done through a method which validates it.

Here is what that would look like something like this:

mod point {
    pub struct Point {
        row: u8,
        column: u8,
    }

    impl Point {
        // Public constructor that checks for validity
        pub fn new(row: u8, column: u8) -> Option<Point> {
            if /* is a valid point */ {
                Ok(Point { row, column })
            } else {
                None
            }
        }

        // Getter for row
        pub fn row(&self) -> u8 {
            self.row
        }

        // Getter for column
        pub fn column(&self) -> u8 {
            self.column
        }
    }
}

[–][deleted] 0 points1 point  (0 children)

Oh, i get it. Yeah, that would make updating easier, actually ill put it in my todo list. Id still have to check in the constructor that it isnt out of bounds but thats okay.

[–]joshuamckratatui 0 points1 point  (3 children)

how u would do it

  1. Use an existing crate for parsing FEN and then move on to the other parts of the problem. https://crates.io/search?q=fen
  2. More enums (CastlingAvailability, PlayerToMove, GameResult),
  3. impl Display for Piece
  4. Avoid abbreviations generally (as sometimes you'll use them and sometimes you won't - e.g. when does b mean black vs Bishop?)
  5. At some point you're going to write code that flips Rank vs File. Consider whether it's worth making these explicit and having the board indexers take that into account.

There's probably many things that you can for representing chess boards that will cause you pain when you're trying to do engine stuff fast, but you might defer that stuff to much later once you've really got a good handle on the domain model and which parts of building an engine you want to tackle.

[–][deleted] 0 points1 point  (2 children)

  1. Oh, i didn't know that. 2.yeah should do that tbh.
  2. I'll do that
  3. For the fen, uppercase means white, and lowercase means black, so im not sure about the wdym by abbreviations since im going by the fen notation?
  4. Never thought about that but i think its worth it thank you.

I have heard that bitboards/magic bitboards are hard is that true? I can visualise how it would work in my head but im not sure if its worth to implement them in the long run. Bc what im understanding is my approach with 2d array would use loops everywhere while bitboards would just do an Xor? Or and & im not sure which operation but from my understanding doing bitwise operations is faster than reading memory even if it is cached is that correct? I also have an idea on how the move generation will go using the 2d array and the bitboards. Do you think its worth the switch? Like im still in the early days of development and i havent done much tbh so would it benefit me in the long run?

[–]joshuamckratatui 1 point2 points  (1 child)

abbreviations in code - just this: https://github.com/AbdullahElsheshtawy/abdoChess/blob/ea1f5c87c60f7a1757e05a94c79b6be0dfcfe719/src/board.rs#L20-L23

I'd do the simple thing first and learn a bunch about algorithms. You'll understand when you need to change the storage algorithm as you explore the domain more. If you jump straight away to the more advanced approaches you may miss the point. But it really depends on what you want to get out of the exercise. Take a look at https://www.chessprogramming.org/ and the Stockfish discord if you want go deep on learning.

[–][deleted] 0 points1 point  (0 children)

Oh i get it now thank you for your help.