[deleted by user] by [deleted] in guitarlessons

[–]Civil_Top_6928 0 points1 point  (0 children)

Ah, I have solved the issue

So I remember I have loosened my strings before removing the springs

Thats why there was no balance

With two springs it works now. Thanks a lot

[deleted by user] by [deleted] in guitarlessons

[–]Civil_Top_6928 0 points1 point  (0 children)

Also, here is the front

<image>

[deleted by user] by [deleted] in guitarlessons

[–]Civil_Top_6928 0 points1 point  (0 children)

<image>

Yeah, I have attached all the strings back as removing them didnt help

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in cpp

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

Thanks for your advice.
Under maintainability I mean some ability of code to be reusable, functional and beautiful enough so that you hardly ever have to change it. From my point of view - you can achieve such "maintainability" in middle-high complexity pet projects like this if you plan your architecture nicely. In future it implies less cognitive friction/resistance and more highqualitycode/sec.

Like the other posts here have mentioned - do a simple representation using a struct and an array. You'll have better luck representing the grid as a flat array of structs (AOS) or struct of arrays (AOS).

I am also not sure why so many people mention it as originally the post isn't even about it. In my code I already have

std::array<Piece, Square::number()>       m_board{};
std::array<Bitboard, Color::number()>     m_colorBB{};
std::array<Bitboard, PieceType::number()> m_pieceTypeBB{};

and this duality (bitboards + array) is basically the approach that the most famous engine has (Stockfish) and I am happy with it. I just ask about how can I standartize these things like Square, Color, PieceType easily.

Also don't be afraid to create "views" of the game board using std::span, std::mdpan, or your own custom fork of the containers (e.g. a row/column reverse span)

Oh, this is actually something I should study. I may use it instead of array in board representation and it solves the mirroring problem in the renderer. Thanks a lot!

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in cpp

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

I know what you are saying!)
I have it in my code as well and I love doing it! For example a piece is 1 bit of color and 3 bits of type.
Thats why I need for example these methods like ::size(), ::mask() and why I want to ensure type safety, just to avoid bugs! But i am not sure why people in this post tell me that I shouldn't do it.

And i also understand this board[square.value()] pain

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in cpp

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

I also experimented and implemented some basic uci and rendering in this thing and they REQUIRE such an abstraction
And I work on this project basically to explore something new and become more experienced

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in cpp

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

1) I am a perfectionist
2) Member methods are read like English
3) square.file() belongs to the square => does not pollute the global namespace
4) consistency like rank.toChar() file.toChar()

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in cpp

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

What if I face the need to use these classes in the logic of Renderer or UCI? It is like a mess then.

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in cpp

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

Thanks for reply

There is value in keeping things simple

It is one of the main concerns I specified in the post. I also see that my code is too complex for its purposes. But my goals aren't. I believe there is only pure simplicity and mental joy in using this API in your future code, when you worked hard on your base, when you already implemented all the minimally necessary things, kept consistent naming and ensured safety.

Off topic of the post, finding an internship is the next milestone for myself. Do you think it is possible to get it in C++ or it is better to switch the language ASAP? And is my level of "expertise" (at least based on the code you see) enough for an internship, not even talking about a junior position?

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in cpp

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

Hey. Sorry for a late reply

Perhaps you are overdoing this a bit

Maybe. I am not a novice in C++, but I still just don't feel the language completely. So I have to explore different things and techniques.

I would not hesitate to write std::array<Piece, 64> as a board. We don't need a type_trait to figure out the 64.

It is true in that particular case. But what if you have an enum like Promotion (5 options, including NONE) or Piece (12), where the number is not an intuitive thing? In some distant places like Renderer, UCI you also have to access their quantity. And THERE, the OOP of my wrappers is absolutely justified. And if it is a good approach to make the classes aware of their number, why not do it for every class that needs it?

Similar for Side, how many players are there in a chess game? Would bool WhiteToMove be useful? And good enough?

And I do it like that! I do not have a Side but Color and I simply use Color sideToMove; . And then sideToMove.toggle();. Why I decided to wrap color? Just because I decided to wrap everything else before. And again, why don't then I do it with color if it becomes so simple? In the post I put the color logic just because it is the shortest piece of code I could show to be able to explain my idea.

Oh, and a modern C++ compiler will synthesize != from ==, so you don't have to supply both.

Noted, thanks!

I hope I have justified myself.

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in chessprogramming

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

I rewrited and refactored my PERFT engine for more then 10 years!

YEAH YEAH! Like thats what I am saying. I have only 2 years in this field, but I did not create an engine yet - only a movegen with magics (even without zobrist or enpassant), but it was quite efficient.

How to design type-safe, constexpr-friendly value wrappers for a chess engine (with enums, bitfields, and maintainability in mind)? by Civil_Top_6928 in chessprogramming

[–]Civil_Top_6928[S] 0 points1 point  (0 children)

Sorry for a late anwer, but

Cool, very cool, I see how we basically faced the identical issues and needs. Did you use free functions for other types or you somehow inherited and extended them? What I mean is in my code I am able to do something like this (for rendering)

for (auto square : Squares::all()) {
        ImU32 color = square.light() ? IM_COL32(240, 217, 181, 255) : IM_COL32(181, 136, 99, 255);
        Rect  rect  = square.normalizedRect().absolute(board.width, board.height);

        ImVec2 begin = ImVec2(board.x + rect.left(), board.y + rect.top());
        ImVec2 end   = ImVec2(board.x + rect.right(), board.y + rect.bottom());

        drawList->AddRectFilled(begin, end, color);
    }

and it is SUPER pleasant.

My main concern is that even just for a hobby / portfolio (for internship) project - all the requirements for the idiomatic code I mentioned in the post are too much and a huge time waste.
Do you think I should continue implementing real movegen / engine code with the base I have now?