Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improving storage of coordinates #75

Merged
merged 2 commits into from
Jul 16, 2024

Conversation

JeromeSchmied
Copy link
Contributor

@JeromeSchmied JeromeSchmied commented Jun 3, 2024

Title

Description

IMO the current implementation for coordinations [i8; 2] is not straightforward at all, also doesn't utilize Rust's awesome type-safety features.

I made a

struct Coord {
    row: u8,
    col: u8,
}

for this, which I think fits the purpose.

I've also implemented std::ops::Index and std::ops::IndexMut for Board to be able to index it with Coord, just like @joshka suggested.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes

@JeromeSchmied JeromeSchmied marked this pull request as ready for review June 6, 2024 17:27
@JeromeSchmied
Copy link
Contributor Author

JeromeSchmied commented Jun 9, 2024

But I have difficulties, as for several functions, only board::Board.board is passed, for which I can not implement std::ops::Index, as it's not a struct or anything defined in this crate, and therefore I can't utilize the [] operator in those functions, which is quite sad.

To address this issue, what I could do is:

  • make a new
 struct JustTheBoard { board: [[Option<(PieceType, PieceColor)>; 8]; 8] }

and implement std::ops::Index for that

  • to every function, that only gets board: [[Option<(PieceType, PieceColor)>; 8]; 8], pass the whole board::Board struct
  • almost same as previous: make functions, that use board: [[Option<(PieceType, PieceColor)>; 8]; 8] methods of board::Board

@thomas-mauran
Copy link
Owner

Looking it soon

@nicholasmello
Copy link
Contributor

But I have difficulties, as for several functions, only board::Board.board is passed, for which I can not implement std::ops::Index, as it's not a struct or anything defined in this crate, and therefore I can't utilize the [] operator in those functions, which is quite sad.

To address this issue, what I could do is:

* make a new
 struct JustTheBoard { board: [[Option<(PieceType, PieceColor)>; 8]; 8] }

and implement std::ops::Index for that

* to every function, that only gets `board: [[Option<(PieceType, PieceColor)>; 8]; 8]`, pass the whole `board::Board` struct

* almost same as previous: make functions, that use `board: [[Option<(PieceType, PieceColor)>; 8]; 8]` methods of `board::Board`

If we defined our own type, something like type Board = [[Option<(PieceType, PieceColor)>; 8]; 8];, we should be able to implement using it without the need for the struct. I coded up a quick test just to make sure it would work.

type Board = [[Option<i32>; 2]; 2];

struct Coord {
    row: u8,
    col: u8
}

impl std::ops::Index<&Coord> for Board {
    type Output = Option<i32>;

    fn index(&self, index: &Coord) -> &Self::Output {
        &self[index.row as usize][index.col as usize]
    }
}

fn main() {
    let board: Board = [
        [Some(0),Some(1)],
        [Some(2),Some(3)],
    ];
    let coord: Coord = Coord {row: 1, col: 0};
    println!("{:?}", board);
    println!("{:?}", board[&coord]);
}

Copy link
Contributor

@nicholasmello nicholasmello left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall love the changes, we should probably squash the commits before merging when we get to that point

Comment on lines -33 to +32
let new_coordinates = [y + dy, x + dx];

if !is_valid(new_coordinates) {
let Some(new_coordinates) =
Coord::opt_new(coordinates.row as i8 + dy, coordinates.col as i8 + dx)
else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing is_valid check for the knight moves

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check whether this commit: be4b1e4 fixes this

src/board.rs Outdated
Comment on lines 55 to 77
impl std::ops::Index<&Coord> for Board {
type Output = Option<(PieceType, PieceColor)>;

fn index(&self, index: &Coord) -> &Self::Output {
&self.board[index.row as usize][index.col as usize]
}
}

impl std::ops::IndexMut<&Coord> for Board {
fn index_mut(&mut self, index: &Coord) -> &mut Self::Output {
&mut self.board[index.row as usize][index.col as usize]
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing it but I don't see these functions being used anywhere

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this, I didn't fully read your comment... my bad 😳

Comment on lines -129 to +132
for i in 1..8i8 {
let new_x = x + i;
let new_y = y - i;
let new_coordinates = [new_y, new_x];

// Invalid coords
if !is_valid(new_coordinates) {
for i in 1..8u8 {
let new_x = x as i8 + i as i8;
let new_y = y as i8 - i as i8;
let Some(new_coordinates) = Coord::opt_new(new_y, new_x) else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x and y are of type u8 since they came from the new Coord, I think it would be better to keep them as u8 - u8 with checked sub to prevent a panic. Something like:

let some(new_x) = x.checked_sub(i) else {
    // Same thing as our invalid coord case
}

Also this is another case where we lost the is_valid check on the coordinates

Comment on lines -28 to +30
let new_y_front_one = y + direction;
let new_coordinates_front_one = [new_y_front_one, new_x_front_one];
let new_y_front_one = y as i8 + direction;
let new_coordinates_front_one = Coord::new(new_y_front_one as u8, new_x_front_one);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is another case where using checked_sub to avoid the signed and unsigned conversions would look a lot better

In this case especially, since we are just converting right back to u8, we aren't gaining any prevention from panicking over just doing the subtraction and unwrapping or something.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to leave a ton of comments but this applies to most of the rest of this file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you, but what you're suggesting might require loads of changes.
My idea is to make Coord::opt_new() check validity as well as overflow kind of things, I'll push the changes soon.

Copy link
Owner

@thomas-mauran thomas-mauran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A very nice addition overall ! thanks a lot to you and @nicholasmello for the additional comments, I don't see anything else that could be a problem. Sorry for the long delay of answer I have been occupied with a lot of other things those past weeks :D.

Waiting for you to take care of the suggestions, squash some of the commits and rebase from main to make sure there is no conflict and it's a merge ! thanks again for taking the time to improve chess-tui 🎉

@JeromeSchmied
Copy link
Contributor Author

Okay guys, thanks for the suggestions, I'll see what can be done and check back soon.
One more thing though: what does squashing commits mean?

@nicholasmello
Copy link
Contributor

Okay guys, thanks for the suggestions, I'll see what can be done and check back soon. One more thing though: what does squashing commits mean?

Squash is a rebase option to combine multiple commits into a single one. It is often done before merges to keep git history simpler, especially when history includes a lot of fixes that are related to each other. It doesn't have to be a single commit for something this big but fewer commits to not spam the git history would be preferred.

@JeromeSchmied
Copy link
Contributor Author

okay, so if I squash the commits, is this pr ready to merge?

@JeromeSchmied
Copy link
Contributor Author

squashing done

Copy link
Contributor

@nicholasmello nicholasmello left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, looks great! Just a couple places I found where we can fully switch over to the new type :)

}

impl std::ops::Index<&Coord> for GameBoard {
type Output = Option<(PieceType, PieceColor)>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be the new GameBoard type

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wont let me add a separate comment since it isn't edited code but same applies for pub fn is_piece_opposite_king(piece: Option<(PieceType, PieceColor)>, color: PieceColor) -> bool { in utils.rs on line 229.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, but I'm afraid, you're mistaken.
The GameBoard looks like: [[Option<(PieceType, PieceColor)>; 8]; 8], while the ones you suggested to change are only Option<(PieceType, PieceColor)> which we don't (yet) have a seperate type for.
Please correct me if I'm wrong.

@JeromeSchmied
Copy link
Contributor Author

is there anything else, I may do?

@thomas-mauran
Copy link
Owner

Nope my bad forgot to merge that, doing that tomorrow for sure been a bit overbooked recently 😅 @JeromeSchmied

@thomas-mauran thomas-mauran merged commit 84c4525 into thomas-mauran:main Jul 16, 2024
4 checks passed
@thomas-mauran
Copy link
Owner

Thank you very much for your contribution @JeromeSchmied and thx for the review @nicholasmello 💪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants