Giter Site home page Giter Site logo

lichs's Introduction


Lichs (Lichess in the Terminal)

project-active contributions-welcome license-mit pypi-version

NOTE!

This project has not been updated in over a year. Feel free to check out the code, however there could be multiple errors upon running it.

Info and requirements

  • Uses Lichess, which means that you need to have a Lichess account
  • Only Classical and Rapid games because the Lichess API doesn't allow anything else
  • This program uses SAN-notation, see the Important-section.

Lichs uses the Lichess API (more exactly berserk) to make it possible for you to play against other real players directly in the terminal on Lichess servers. If you like this project, be sure to also check out Nick Zuber's Chs-project, since it was his project that inspired me to do this in the first place.

Installation

This package is available on PyPi, therefore just run:

$ pip install lichs

and the program will be installed. The next step is to generate a personal API-key.

How to generate a personal API token

  1. Create a Lichess API token, log into Lichess if necessary
  2. Click the button Submit in the lower right corner
  3. Copy the token shown in the brown box
  4. Jump into your terminal and write lichs <api_token> (put your API token instead of <api_token>) and run the command. To get this clear, an example would have been lichs lzRceo5XOUND74Lm. You should then see a message to confirm that the API token has been saved.

Usage

You start playing by typing the command lichs into your terminal:

$ lichs

That will take you to the intro screen:

Welcome to Lichess!

What kind of chess do you want to play?
1. Rapid (10+0)
2. Classical (30+0)

Enter 1 or 2:

That should be pretty self-explanatory, you basically choose between Rapid and Classical (the Lichess API doesn't support anything else) by entering either 1 or 2. The timing of the games is also listed there; Rapid is 10min and Classical 30min (without extra-time, I might add support for extra-time later)

When you have input either 1 or 2, the program will start to search after an opponent. It shouldn't take long and the game should start pretty quickly.

Searching after opponent...
An opponent was found!

Then the program will let you know whether you're the color white or black. After that you will start playing; the program will output the board after every move and ask for your move when it's your turn.

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

Above is an example of the board displayed.

Important

When the program asks for your move, you need to input the move in standard algebraic notation (SAN). Basically, it specifies which piece to move and to where. As an example, to move a knight from g1 to f3, you type in Nf3 (N is for Knight, since King uses K). If you want to learn more, click on the link above.

The program will inform you if you can't make the move you have input.

Support for UCI-notation might get added later.

Contributions

See the CONTRIBUTING.md file for how to contribute.

lichs's People

Contributors

actor10 avatar cqsi avatar ddugovic avatar dependabot[bot] avatar ornicar avatar ralacerda avatar samthegitguy avatar silva-nick avatar younishd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lichs's Issues

Play against AI problem.

Hello.
I'm trying to make a match against the lichess AI.
using berserk this can be generated,

reto = berserk.clients.Challenges(session) 
(...)
reto.create_ai(level=6, clock_limit=None, clock_increment=None, days=None, color="black", variant=None, position=None)

but I have a problem ...
If I play with white against the AI everything works great. But, if the AI plays with white the code is broken ... this happens because the AI has neither "user" nor "id".
if player_id != client.games.export(event['game']['id'])['players']['white']['user']['id']:

Therefore, I thought about eliminating those fields (just to test ...), the error is not generated there but the AI move does not reach me. The AI moves for example e2e4 ... and it never reaches me. In fact, the AI movement only comes when I enter the website and cancel the game.

Thanks for your time.

This is obviously something that is not in your program but I ask you since you worked with this a lot, you may notice where the problem could be.

I cant put the token...

Sorry my dumb question but... i cant paste the token.... is strange because i have a previous version of lichs, and there i can paste... but cant in this "new version". Cant even write.
Probably a easy solution, but... i dont know how.
Thanks.

Multiple errors on raspberry pi

Hi
I am able to install the application using instructions given.I am able to give lichess api key also but aftter that it is giving me constant errors i have included here

Traceback (most recent call last):
  File "/home/pi/.local/bin/lichs", line 10, in <module>
    sys.exit(main())
  File "/home/pi/.local/lib/python3.7/site-packages/lichs/__main__.py", line 44, in main
    account_data = client.account.get()
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/clients.py", line 115, in get
    return self._r.get(path, converter=models.Account.convert)
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/session.py", line 60, in get
    return self.request('GET', *args, **kwargs)
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/session.py", line 56, in request
    return fmt.handle(response, is_stream=is_stream, converter=converter)
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/formats.py", line 35, in handle
    return converter(self.parse(response))
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/formats.py", line 76, in parse
    return response.json(cls=self.decoder)
  File "/usr/lib/python3/dist-packages/requests/models.py", line 889, in json
    self.content.decode(encoding), **kwargs
  File "/usr/lib/python3/dist-packages/simplejson/__init__.py", line 535, in loads
    return cls(encoding=encoding, **kw).decode(s)
TypeError: __init__() got an unexpected keyword argument 'encoding'

Lichess. How close the connection?

Hi.
This is a question, not about lichs. Maybe you can help me. Im using berserk to manage the lichess api.
I want to cancel a seek i create. How i can do that? In the lichess api reference says this:

Keep the connection open to keep the seek active.

If the client closes the connection, the seek is canceled. This way, if the client terminates, the user won't be paired in a game they wouldn't play. When the seek is accepted, or expires, the server closes the connection.

But, how close the connection? Dont find anything, probably is too obvius and im ignorant. im using berserk.
How you would "close the connection" in your program?

Thanks!

Game_state - KeyError: 'bdraw'

Hi.
In this error im playing with White and I'm getting that "b" that generate this error. (the "b" the 0 position for black, but why can handle this¿) What can be wrong here¿
What can i do¿


File "/usr/lib/python3.10/threading.py", line 1009, in _bootstrap_inner
    self.run()
File "/home/panchines/.local/lib/python3.10/site-packages/lichs/Game.py", line 27, in run
    self.handle_state_change(event)

File "/home/panchines/.local/lib/python3.10/site-packages/lichs/Game.py", line 35, in handle_state_change
    if game_state[self.color[0].lower() + "draw"] == True:
KeyError: 'bdraw'

Emojis

We can use emojis instead of text:

♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
♟ ♟ ♟ ♟ ♟ ♟ ♟ ♟
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . ♙ . . .
♙ ♙ ♙ ♙ . ♙ ♙ ♙
♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖

How the time is taken has a downside.

The way in which time is taken has the downside that if there is a delay, lag, then time is out of phase and what is reported does not coincide with the game.

No support for algebraic notation

Lichs currently only supports move input using UCI (e.g. e2e4) and not algrebraic notation (e.g. e4). While UCI is standard for engine chess and computer communication of moves, algebraic notation is very much the standard for modern human play.

Support for algebraic notation would be great for usability as players would not need to learn a new coordinate system to make their moves.

Issues with API access token error message

If a user attempts to launch lichs without an API key, the following error is displayed:

The API-key is either empty or wrong. Please run the command 'lichess' and input your API-key as a second argument, i.e 'lichess <api_key>'. If you need more help, please see the instructions in the Github README: 
https://github.com/Cqsi/lichess_terminal#how-to-generate-a-personal-api-token

But:

  • The command is lichs not lichess.
  • The header-tied link is https://github.com/Cqsi/lichs#how-to-generate-a-personal-api-key not https://github.com/Cqsi/lichess_terminal#how-to-generate-a-personal-api-token.
  • Lichess refers to the API keys as "API access tokens" not "API-keys." This isn't crucial to change, but could help consistency for users.

Problem with berserk?

Hi.
Im having this error. I install like this "pip3 install lichs".
Im running this on a raspberry pi zero w.

After put the token, im getting this:

pi@chess:~/.local/bin $ python3 lichs
Traceback (most recent call last):
  File "lichs", line 10, in <module>
    sys.exit(main())
  File "/home/pi/.local/lib/python3.7/site-packages/lichs/__main__.py", line 34, in main
    account_data = client.account.get()
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/clients.py", line 115, in get
    return self._r.get(path, converter=models.Account.convert)
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/session.py", line 60, in get
    return self.request('GET', *args, **kwargs)
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/session.py", line 56, in request
    return fmt.handle(response, is_stream=is_stream, converter=converter)
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/formats.py", line 35, in handle
    return converter(self.parse(response))
  File "/home/pi/.local/lib/python3.7/site-packages/berserk/formats.py", line 76, in parse
    return response.json(cls=self.decoder)
  File "/usr/lib/python3/dist-packages/requests/models.py", line 889, in json
    self.content.decode(encoding), **kwargs
  File "/usr/lib/python3/dist-packages/simplejson/__init__.py", line 535, in loads
    return cls(encoding=encoding, **kw).decode(s)
TypeError: __init__() got an unexpected keyword argument 'encoding'

Thanks.

Loop menu

Hello,

I was thinking about adding a Loop menu (one of the TODOs in the code).
This way it doesn't exit abruptly if you write a wrong command.

Something similar to:

def menu(account_data, client, board, session):
    player_username = account_data["username"]
    print("Welcome to Lichess {}!".format(player_username))

    while True:
        print("""
        P to play
        H for help
        Q to quit
        """)
        ans = input("command: ").lower()

        if ans.lower== "q":
            sys.exit()

This use the player would also go back to the menu after a game, maybe change a configuration, token, etc.

I can try to remake the current menu in this format so we can test it out before adding new features.

Moves like e2e4?

Hi. I am making a chess board based on a tutorial (which is not 100% finished, you has to create certain solutions) (the truth is that I know little about programming but I am moving forward), once finished I would like to make it work with lichess .
The code of my program is in python (2.7 currently).
"My code" sends the moves like g1f3, e2e4, etc. (currently playing against stockfish)
Would it be possible to implement this type of change in your code?
Greetings and thank you very much.

Reworking Game class

Hello, I was wondering if there should be an effort to re-write the Game class.
I think having separated functions to deal with moving and priting the board ( like in #7 ) would make it easier later on if we want to change how the board is displayed, or if you want a way to change between UCI and Algebric.
Here are some changes I propose and some code to get us started:
(I'm no pyhon expert, so please let me know if there is a better way to do this)

I don't think we need Game to inherent Thread (since we are most likely playing just one game each time).

Game only needs to take three arguments:

  • Lichess board instance, which is how we connect to Lichess
  • The game_id, to get the stream of events and send moves
  • player_id, so we can check if the player is playing white or black

Each Game() instance should create its own chess.Board() instance, instead of a global chess.Board().

Instead of making the move on the chess.Board() and sending it to Lichess at the same time, I think we need to first send the command to Lichess, and then we wait for Lichess to send our own move.
I think it would then be better to check the legality of the move locally before sending it to Lichess.

I think there is a lot of python-chess features we can use like chess.WHITE and chess.BLACK.

We should also use chess.Board.turn() everytime we get a move update, instead of trying to keep track locally.

import chess

class Game:

    def __init__(self, lichess_board, game_id, player_id):
        self.lichess_board = lichess_board
        self.game_id = game_id
        self.player_id = player_id
        self.stream = self.lichess_board.stream_game_state(self.game_id)

        self.initial_status = next(self.stream)

        self.list_move = self.initial_status["state"]["moves"].split(" ")

        self.chess_board = chess.Board()

We store lichess_board, game_id and player_id
We call next(self.stream) for the first time, which will always send us the game information, and the moves so far (we save those to a list).
We create an instance of chess.Board().

    def set_player_color(self):
        if "id" in self.initial_status["white"]:
            if self.initial_status["white"]["id"] == self.player_id:
                print("Player is white")
                self.player_color = chess.WHITE
            else:
                print("Player is black")
                self.player_color = chess.BLACK
        else:
            print("Player is black")
            self.player_color = chess.BLACK

This function just checks if the player is white or black.
We need to check if "id" is a valid key, because when playing the AI it has no "id".

    def print_board(self):
        if self.player_color is chess.WHITE:
            print(self.chess_board)
        else:
            vertical_flip = self.chess_board.transform(chess.flip_vertical)
            final_flip = vertical_flip.transform(chess.flip_horizontal)
            print(final_flip)

This function flips the board, we can also use ( #7 ).

    def start_game(self):
        self.set_player_color()

        for move_uci in self.list_move:
            move = self.chess_board.parse_uci(move_uci)
            self.chess_board.push(move)

        self.print_board()

We start the game by setting the player color, pushing the stored moves to our local board (this means you can connect to a game midway). And we print the board.

What is missing right now is the event loop for the game. I suggest we go the following way:

  1. chess.Board.turn() checks if it is the player turn:

    • Ask the player for input, if it is valid, send it to lichess, then call next(self.stream)
    • Otherwise, call next(self.stream)
  2. When we receive a new change of state from lichess, we make the move in our local board (this can be either player move), we go back to 1. again.

I think this changes to the class would lead to the following:

  • Easier to test
  • Easier to change function for printing the board and making moves later on
  • Being able to join a game in the middle of it
  • Being able to play multiple games at the same time
  • I think we can even spectate and watch replays this way (not sure if this is a wanted feature, but it wouldn't be hard to implement it).

Please let me know what you guys think.
We can create a separated branch and test it out.

README.md contains Windows-centric instructions.

By default, READMEs should be OS-neutral or following GNU/Linux conventions as they are the most easily mapped to other OSs. This is of course unless the program is a Windows-exclusive, but that doesn't make a lot of sense for this.

The README.md contains a few very Windows-centric instructions that may confuse non-Windows users, e.g:

  • The instructions say to use C:\> pip install lichs instead of simply pip install lichs or ($ pip install lichs to indicate that it's in a shell).
  • Step 6 of "How to generate a personal API-key" says to "Jump into CMD" which is a specific program. Instead of "CMD" it should say "terminal", which is the generic term for the progams one can use to input the commands.
  • Under Usage it explicity says to type the command into the "Windows Command Prompt."

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.