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

Board.__str__ including grid labels #971

Open
jamesbraza opened this issue Mar 2, 2023 · 10 comments
Open

Board.__str__ including grid labels #971

jamesbraza opened this issue Mar 2, 2023 · 10 comments

Comments

@jamesbraza
Copy link
Contributor

To me, it's easier to see/understand a board's printed representation with the rank/file shown.

In [1]: import chess
In [2]: board = chess.Board()
In [3]: print(board)
r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
P P P P P P P P
R N B Q K B N R

It would be nice to support the ability to show the grid:

In [4]: print(board.grid())
  | a b c d e f g h
- + ---------------
8 | r n b q k b n r
7 | p p p p p p p p
6 | . . . . . . . .
5 | . . . . . . . .
4 | . . . . . . . .
3 | . . . . . . . .
2 | P P P P P P P P
1 | R N B Q K B N R

Alternately, an instance attribute verbose could be added that somehow enables behaviors like this when __str__ is invoked.

@niklasf
Copy link
Owner

niklasf commented Mar 6, 2023

I think this looks good. I wonder if it's acceptable to just change __str__, or if that would be considered a breaking change.

@jamesbraza
Copy link
Contributor Author

Yeah I think it would be fine to change __str__ too.

One question is, how do you see board.mirror() affecting things?

@niklasf
Copy link
Owner

niklasf commented Mar 6, 2023

One question is, how do you see board.mirror() affecting things?

board.mirror() should not need special consideration. It's not to be confused with changing the orientation of looking at the board - chess.Board() has no concept of that. board.mirror() returns a different position, that happens to have pieces in mirrored positions.

@dubiousjim
Copy link

For reference, here is a prettifying wrapper I use around str(Board):

def diagram(b, *, flipped=False, labels=0, pretty=False):
    # pylint: disable=multiple-statements,consider-using-f-string
    assert isinstance(b, Board), f"Not a Board: {repr(b)}"
    string = b.unicode(empty_square='.') if pretty else str(b)
    if flipped:
        rows = [''.join(reversed(row)) for row in reversed(string.split('\n'))]
        if labels == 0: return '\n'.join(rows)
        elif labels == 1: return '\n'.join('%d %s' % (i,row) for i,row in enumerate(rows, start=1)) + '\n  h g f e d c b a'
        elif labels == -1: return '  h g f e d c b a\n' + '\n'.join('  %s %d' % (row,i) for i,row in enumerate(rows, start=1))
        else: return '    h g f e d c b a\n  + --------------- +\n' + '\n'.join('%d | %s | %d' % (i,row,i) for i,row in enumerate(rows, start=1)) + '\n  + --------------- +\n    h g f e d c b a'
    else:
        rows = string.split('\n')
        if labels == 0: return '\n'.join(rows)
        # pylint: disable=consider-using-in
        elif labels == 1 or labels == -1: return '\n'.join('%d %s' % (8-i,row) for i,row in enumerate(rows)) + '\n  a b c d e f g h'
        else: return '    a b c d e f g h\n  + --------------- +\n' + '\n'.join('%d | %s | %d' % (8-i,row,8-i) for i,row in enumerate(rows)) + '\n  + --------------- +\n    a b c d e f g h'

@dubiousjim
Copy link

Use pretty=True to get Unicode pieces. Use flipped=True to invert the perspective (putting black on bottom). Use labels=1 to get row/column labels to the left and bottom of the board. When flipped=True, you can also use labels=-1 to get labels on the top and right of the board instead. (When flipped=False, labels=-1 works just like labels=1.)

No grid lines. But this is a starting point that someone can use to write something more full-featured.

@jamesbraza
Copy link
Contributor Author

jamesbraza commented Mar 11, 2023

@dubiousjim I like your support of unicode, nice! I am using this now 👍, with a few mods:

  • I changed labels arg name to verbosity and only support [0, 1, 2]
  • I moved from "\n" to os.linesep
  • From this comment above:

board.mirror() should not need special consideration.

I think this means no need to support flipped capability, just rely on the caller previously invoking board.apply_mirror() or board.mirror().

One possible improvement for labels/verbosity=2: maybe add the player whose turn it is with * or . as the corner. This can be discerned with board.turn == chess.WHITE and board.turn == chess.BLACK.

For example, if it's white player's turn, note the *:

    a b c d e f g h
  . --------------- .
8 | r . b q k b . r | 8
7 | p p . n p p . p | 7
6 | . . p p . n p . | 6
5 | . . . . . . . . | 5
4 | . . . . P . . . | 4
3 | . . N . . N . P | 3
2 | P P P P B P P . | 2
1 | R . B Q K . . R | 1
  * --------------- *
    a b c d e f g h

@dubiousjim
Copy link

Flipped board just displays the 8 rank at the bottom, it doesn't change any piece positions. (White K still starts at e1, this is just now displayed at the top instead of at the bottom.) Mirrored board moves the piece that was at a6 instead to a3. These are different concepts.

@jamesbraza
Copy link
Contributor Author

Okay I see, sorry I didn't scrutinize that much. I think the default chess behavior is 8th rank on the top.

One other cool feature in a display function would be to highlight captures, check, or checkmates, possibly via colors. This behavior could be turned on with an additional color flag.

@baelany
Copy link

baelany commented Mar 13, 2023

I would be interested in taking on this issue!

@R3dan
Copy link

R3dan commented Dec 31, 2023

I would also be interested in taking this, if someone already is in development though, please say

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

No branches or pull requests

5 participants