python-shogi: a pure Python shogi library
=========================================
.. image:: https://coveralls.io/repos/gunyarakun/python-shogi/badge.svg
:target: https://coveralls.io/r/gunyarakun/python-shogi
.. image:: https://badge.fury.io/py/python-shogi.svg
:target: https://pypi.python.org/pypi/python-shogi
.. image:: https://github.com/gunyarakun/python-shogi/actions/workflows/pythonpackage.yml/badge.svg
:target: https://github.com/gunyarakun/python-shogi/actions/workflows/pythonpackage.yml
.. image:: https://github.com/gunyarakun/python-shogi/actions/workflows/codeql-analysis.yml/badge.svg
:target: https://github.com/gunyarakun/python-shogi/actions/workflows/codeql-analysis.yml
Introduction
------------
This is the module for shogi written in Pure Python. It's based on python-chess `commit <https://github.com/niklasf/python-chess/commit/6203406259504cddf6f271e6a7b1e04ba0c96165>`__
This is the scholars mate in python-shogi:
.. code:: python
>>> import shogi
>>> board = shogi.Board()
>>> board.push(shogi.Move.from_usi('7g7f'))
>>> board.push_usi('3c3d')
Move.from_usi('3c3d')
>>> board.push_usi('8h2b+')
Move.from_usi('8h2b+')
>>> board.push_usi('4a5b')
Move.from_usi('4a5b')
>>> board.push_usi('B*4b')
Move.from_usi('B*4b')
>>> board.push_usi('5a4a')
Move.from_usi('5a4a')
>>> board.push_usi('2b3a')
Move.from_usi('2b3a')
>>> board.is_checkmate()
True
Features
--------
* Supports Python 3.3+.
* Supports standard shogi (hon shogi)
* Legal move generator and move validation.
.. code:: python
>>> shogi.Move.from_usi("5i5a") in board.legal_moves
False
* Make and unmake moves.
.. code:: python
>>> last_move = board.pop() # Unmake last move
>>> last_move
Move.from_usi('2b3a')
>>> board.push(last_move) # Restore
* Show a simple ASCII board.
.. code:: python
>>> print(board)
l n s g . k +B n l
. r . . g B . . .
p p p p p p . p p
. . . . . . p . .
. . . . . . . . .
. . P . . . . . .
P P . P P P P P P
. . . . . . . R .
L N S G K G S N L
<BLANKLINE>
S*1
* Show a KIF style board.
.. code:: python
>>> print(board.kif_str())
後手の持駒:
9 8 7 6 5 4 3 2 1
+---------------------------+
|v香v桂v銀v金 ・v玉 馬v桂v香|一
| ・v飛 ・ ・v金 角 ・ ・ ・|二
|v歩v歩v歩v歩v歩v歩 ・v歩v歩|三
| ・ ・ ・ ・ ・ ・v歩 ・ ・|四
| ・ ・ ・ ・ ・ ・ ・ ・ ・|五
| ・ ・ 歩 ・ ・ ・ ・ ・ ・|六
| 歩 歩 ・ 歩 歩 歩 歩 歩 歩|七
| ・ ・ ・ ・ ・ ・ ・ 飛 ・|八
| 香 桂 銀 金 玉 金 銀 桂 香|九
+---------------------------+
先手の持駒: 銀
* Detects checkmates, stalemates.
.. code:: python
>>> board.is_stalemate()
False
>>> board.is_game_over()
True
* Detects repetitions. Has a half move clock.
.. code:: python
>>> board.is_fourfold_repetition()
False
>>> board.move_number
8
* Detects checks and attacks.
.. code:: python
>>> board.is_check()
True
>>> board.is_attacked_by(shogi.BLACK, shogi.A4)
True
>>> attackers = board.attackers(shogi.BLACK, shogi.H5)
>>> attackers
SquareSet(0b111000010000000000000000000000000000000000000000000000000000000000000000000000)
>>> shogi.H2 in attackers
True
>>> print(attackers)
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . 1 .
. . . 1 1 1 . . .
* Parses and creates USI representation of moves.
.. code:: python
>>> board = shogi.Board()
>>> shogi.Move(shogi.E2, shogi.E4).usi()
'2e4e'
* Parses and creates SFENs
.. code:: python
>>> board.sfen()
'lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1'
>>> board.piece_at(shogi.I5)
Piece.from_symbol('K')
* Read KIFs.
.. code:: python
>>> import shogi.KIF
>>> kif = shogi.KIF.Parser.parse_file('data/games/habu-fujii-2006.kif')[0]
>>> kif['names'][shogi.BLACK]
'羽生善治'
>>> kif['names'][shogi.WHITE]
'藤井猛'
>>> kif['moves'] # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
['7g7f',
'3c3d',
...,
'9a9b',
'7a7b+']
>>> kif['win']
'b'
* Export to KIFs.
.. code:: python
>>> import shogi
>>> import shogi.KIF
>>> board = shogi.Board()
>>> shogi.KIF.Exporter.kif_move_from('7g7f', board)
'7六歩(77)'
>>> sfen_summary = {'moves': ['7g7f', '3c3d'], 'sfen': 'lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1', 'names': ['羽生善治', '藤井猛'], 'win': 'w'}
>>> shogi.KIF.Exporter.kif(sfen_summary)
開始日時: \r
終了日時: \r
手合割:平手\r
先手:羽生善治\r
後手:藤井猛\r
手数----指手---------消費時間-- \r
1 7六歩(77) \r
2 3四歩(33) \r
3 投了 \r
まで2手で後手の勝ち\r
* Communicate with a CSA protocol.
Please see `random_csa_tcp_match <https://github.com/gunyarakun/python-shogi/blob/master/scripts/random_csa_tcp_match>`_.
* Parse professional shogi players' name
>>> import shogi.Person
>>> shogi.Person.Name.is_professional('羽生 善治 名人・棋聖・王位・王座')
True
Performance
-----------
python-shogi is not intended to be used by serious shogi engines where
performance is critical. The goal is rather to create a simple and relatively
highlevel library.
You can install the `gmpy2 <https://pypi.org/project/gmpy2>`__ or `gmpy <https://pypi.org/project/gmpy>`__ modules
in order to get a slight performance boost on basic operations like bit scans
and population counts.
python-shogi will only ever import very basic general (non-shogi-related)
operations from native libraries. All logic is pure Python. There will always
be pure Python fallbacks.
Installing
----------
* With pip:
::
pip install python-shogi
How to test
-----------
::
> make test
If you want to print lines from the standard output, execute nosetests like following.
::
> poetry run nosetests -s
How to release
--------------
::
poetry config repositories.testpypi https://test.pypi.org/legacy/
# poetry config pypi-token.testpypi "Test PyPI API Token"
make test-upload
# poetry config pypi-token.pypi "PyPI API Token"
make upload
ToDo
----
- Support board.generate_attacks() and use it in board.is_attacked_by() and board.attacker_mask().
- Remove rotated bitboards and support `Shatranj-style direct lookup
<http://arxiv.org/pdf/0704.3773.pdf>`_ like recent python-chess.
- Support %MATTA etc. in CSA TCP Protocol.
- Support board.is_pinned() and board.pin().
Raw data
{
"_id": null,
"home_page": "https://github.com/gunyarakun/python-shogi",
"name": "python-shogi",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.4",
"maintainer_email": "",
"keywords": "shogi,csa,kif",
"author": "Tasuku SUENAGA a.k.a. gunyarakun",
"author_email": "tasuku-s-github@titech.ac",
"download_url": "https://files.pythonhosted.org/packages/75/4e/8ce69bf56ae03df008c04351cffac186b4b1b0723985ea76ea02f9a91c2b/python_shogi-1.1.1.tar.gz",
"platform": null,
"description": "python-shogi: a pure Python shogi library\n=========================================\n\n.. image:: https://coveralls.io/repos/gunyarakun/python-shogi/badge.svg\n :target: https://coveralls.io/r/gunyarakun/python-shogi\n\n.. image:: https://badge.fury.io/py/python-shogi.svg\n :target: https://pypi.python.org/pypi/python-shogi\n\n.. image:: https://github.com/gunyarakun/python-shogi/actions/workflows/pythonpackage.yml/badge.svg\n :target: https://github.com/gunyarakun/python-shogi/actions/workflows/pythonpackage.yml\n \n.. image:: https://github.com/gunyarakun/python-shogi/actions/workflows/codeql-analysis.yml/badge.svg\n :target: https://github.com/gunyarakun/python-shogi/actions/workflows/codeql-analysis.yml \n\nIntroduction\n------------\n\nThis is the module for shogi written in Pure Python. It's based on python-chess `commit <https://github.com/niklasf/python-chess/commit/6203406259504cddf6f271e6a7b1e04ba0c96165>`__\n\n\nThis is the scholars mate in python-shogi:\n\n.. code:: python\n\n >>> import shogi\n\n >>> board = shogi.Board()\n\n >>> board.push(shogi.Move.from_usi('7g7f'))\n\n >>> board.push_usi('3c3d')\n Move.from_usi('3c3d')\n >>> board.push_usi('8h2b+')\n Move.from_usi('8h2b+')\n >>> board.push_usi('4a5b')\n Move.from_usi('4a5b')\n >>> board.push_usi('B*4b')\n Move.from_usi('B*4b')\n >>> board.push_usi('5a4a')\n Move.from_usi('5a4a')\n >>> board.push_usi('2b3a')\n Move.from_usi('2b3a')\n >>> board.is_checkmate()\n True\n\nFeatures\n--------\n\n* Supports Python 3.3+.\n\n* Supports standard shogi (hon shogi)\n\n* Legal move generator and move validation.\n\n .. code:: python\n\n >>> shogi.Move.from_usi(\"5i5a\") in board.legal_moves\n False\n\n* Make and unmake moves.\n\n .. code:: python\n\n >>> last_move = board.pop() # Unmake last move\n >>> last_move\n Move.from_usi('2b3a')\n\n >>> board.push(last_move) # Restore\n\n* Show a simple ASCII board.\n\n .. code:: python\n\n >>> print(board)\n l n s g . k +B n l\n . r . . g B . . .\n p p p p p p . p p\n . . . . . . p . .\n . . . . . . . . .\n . . P . . . . . .\n P P . P P P P P P\n . . . . . . . R .\n L N S G K G S N L\n <BLANKLINE>\n S*1\n\n* Show a KIF style board.\n\n .. code:: python\n\n >>> print(board.kif_str())\n \u5f8c\u624b\u306e\u6301\u99d2\uff1a\n \uff19 \uff18 \uff17 \uff16 \uff15 \uff14 \uff13 \uff12 \uff11\n +---------------------------+\n |v\u9999v\u6842v\u9280v\u91d1 \u30fbv\u7389 \u99acv\u6842v\u9999|\u4e00\n | \u30fbv\u98db \u30fb \u30fbv\u91d1 \u89d2 \u30fb \u30fb \u30fb|\u4e8c\n |v\u6b69v\u6b69v\u6b69v\u6b69v\u6b69v\u6b69 \u30fbv\u6b69v\u6b69|\u4e09\n | \u30fb \u30fb \u30fb \u30fb \u30fb \u30fbv\u6b69 \u30fb \u30fb|\u56db\n | \u30fb \u30fb \u30fb \u30fb \u30fb \u30fb \u30fb \u30fb \u30fb|\u4e94\n | \u30fb \u30fb \u6b69 \u30fb \u30fb \u30fb \u30fb \u30fb \u30fb|\u516d\n | \u6b69 \u6b69 \u30fb \u6b69 \u6b69 \u6b69 \u6b69 \u6b69 \u6b69|\u4e03\n | \u30fb \u30fb \u30fb \u30fb \u30fb \u30fb \u30fb \u98db \u30fb|\u516b\n | \u9999 \u6842 \u9280 \u91d1 \u7389 \u91d1 \u9280 \u6842 \u9999|\u4e5d\n +---------------------------+\n \u5148\u624b\u306e\u6301\u99d2\uff1a\u3000\u9280\n\n* Detects checkmates, stalemates.\n\n .. code:: python\n\n >>> board.is_stalemate()\n False\n >>> board.is_game_over()\n True\n\n* Detects repetitions. Has a half move clock.\n\n .. code:: python\n\n >>> board.is_fourfold_repetition()\n False\n >>> board.move_number\n 8\n\n* Detects checks and attacks.\n\n .. code:: python\n\n >>> board.is_check()\n True\n >>> board.is_attacked_by(shogi.BLACK, shogi.A4)\n True\n >>> attackers = board.attackers(shogi.BLACK, shogi.H5)\n >>> attackers\n SquareSet(0b111000010000000000000000000000000000000000000000000000000000000000000000000000)\n >>> shogi.H2 in attackers\n True\n >>> print(attackers)\n . . . . . . . . .\n . . . . . . . . .\n . . . . . . . . .\n . . . . . . . . .\n . . . . . . . . .\n . . . . . . . . .\n . . . . . . . . .\n . . . . . . . 1 .\n . . . 1 1 1 . . .\n\n* Parses and creates USI representation of moves.\n\n .. code:: python\n\n >>> board = shogi.Board()\n >>> shogi.Move(shogi.E2, shogi.E4).usi()\n '2e4e'\n\n* Parses and creates SFENs\n\n .. code:: python\n\n >>> board.sfen()\n 'lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1'\n >>> board.piece_at(shogi.I5)\n Piece.from_symbol('K')\n\n* Read KIFs.\n\n .. code:: python\n\n >>> import shogi.KIF\n\n >>> kif = shogi.KIF.Parser.parse_file('data/games/habu-fujii-2006.kif')[0]\n\n >>> kif['names'][shogi.BLACK]\n '\u7fbd\u751f\u5584\u6cbb'\n >>> kif['names'][shogi.WHITE]\n '\u85e4\u4e95\u731b'\n >>> kif['moves'] # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE\n ['7g7f',\n '3c3d',\n ...,\n '9a9b',\n '7a7b+']\n >>> kif['win']\n 'b'\n\n* Export to KIFs.\n\n .. code:: python\n\n >>> import shogi\n >>> import shogi.KIF\n\n >>> board = shogi.Board()\n >>> shogi.KIF.Exporter.kif_move_from('7g7f', board)\n '\uff17\u516d\u6b69(77)'\n\n >>> sfen_summary = {'moves': ['7g7f', '3c3d'], 'sfen': 'lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1', 'names': ['\u7fbd\u751f\u5584\u6cbb', '\u85e4\u4e95\u731b'], 'win': 'w'}\n >>> shogi.KIF.Exporter.kif(sfen_summary)\n \u958b\u59cb\u65e5\u6642\uff1a \\r\n \u7d42\u4e86\u65e5\u6642\uff1a \\r\n \u624b\u5408\u5272\uff1a\u5e73\u624b\\r\n \u5148\u624b\uff1a\u7fbd\u751f\u5584\u6cbb\\r\n \u5f8c\u624b\uff1a\u85e4\u4e95\u731b\\r\n \u624b\u6570----\u6307\u624b---------\u6d88\u8cbb\u6642\u9593-- \\r\n 1 \uff17\u516d\u6b69(77) \\r\n 2 \uff13\u56db\u6b69(33) \\r\n 3 \u6295\u4e86 \\r\n \u307e\u30672\u624b\u3067\u5f8c\u624b\u306e\u52dd\u3061\\r\n\n* Communicate with a CSA protocol.\n\n Please see `random_csa_tcp_match <https://github.com/gunyarakun/python-shogi/blob/master/scripts/random_csa_tcp_match>`_.\n\n* Parse professional shogi players' name\n\n >>> import shogi.Person\n\n >>> shogi.Person.Name.is_professional('\u7fbd\u751f\u3000\u5584\u6cbb \u540d\u4eba\u30fb\u68cb\u8056\u30fb\u738b\u4f4d\u30fb\u738b\u5ea7')\n True\n\nPerformance\n-----------\npython-shogi is not intended to be used by serious shogi engines where\nperformance is critical. The goal is rather to create a simple and relatively\nhighlevel library.\n\nYou can install the `gmpy2 <https://pypi.org/project/gmpy2>`__ or `gmpy <https://pypi.org/project/gmpy>`__ modules\nin order to get a slight performance boost on basic operations like bit scans\nand population counts.\n\npython-shogi will only ever import very basic general (non-shogi-related)\noperations from native libraries. All logic is pure Python. There will always\nbe pure Python fallbacks.\n\nInstalling\n----------\n\n* With pip:\n\n ::\n\n pip install python-shogi\n\nHow to test\n-----------\n\n::\n\n > make test\n\nIf you want to print lines from the standard output, execute nosetests like following.\n\n::\n\n > poetry run nosetests -s\n\nHow to release\n--------------\n\n::\n\n poetry config repositories.testpypi https://test.pypi.org/legacy/\n # poetry config pypi-token.testpypi \"Test PyPI API Token\"\n make test-upload\n # poetry config pypi-token.pypi \"PyPI API Token\"\n make upload\n\nToDo\n----\n\n- Support board.generate_attacks() and use it in board.is_attacked_by() and board.attacker_mask().\n\n- Remove rotated bitboards and support `Shatranj-style direct lookup\n <http://arxiv.org/pdf/0704.3773.pdf>`_ like recent python-chess.\n\n- Support %MATTA etc. in CSA TCP Protocol.\n\n- Support board.is_pinned() and board.pin().\n",
"bugtrack_url": null,
"license": "GPL-3.0-only",
"summary": "A pure Python shogi library with move generation and validation and handling of common formats.",
"version": "1.1.1",
"project_urls": {
"Homepage": "https://github.com/gunyarakun/python-shogi"
},
"split_keywords": [
"shogi",
"csa",
"kif"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "63b9d1ed6dd2912617b7d716010b3eac7fc4bceee003260f24857ca53a9721ff",
"md5": "60548df2a127ab10d240a0e83ecab948",
"sha256": "c626671fa7330ac1c9a4673ea6023c94a3ca9eb1d87aeb9ab2740453773dc821"
},
"downloads": -1,
"filename": "python_shogi-1.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "60548df2a127ab10d240a0e83ecab948",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.4",
"size": 70788,
"upload_time": "2024-02-09T02:36:02",
"upload_time_iso_8601": "2024-02-09T02:36:02.931738Z",
"url": "https://files.pythonhosted.org/packages/63/b9/d1ed6dd2912617b7d716010b3eac7fc4bceee003260f24857ca53a9721ff/python_shogi-1.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "754e8ce69bf56ae03df008c04351cffac186b4b1b0723985ea76ea02f9a91c2b",
"md5": "e16b6a5e513ffe52da04712cb37f6156",
"sha256": "c33a53ff9decba2d31f21be3ff313548552706739ee50827ea902045900aaf0b"
},
"downloads": -1,
"filename": "python_shogi-1.1.1.tar.gz",
"has_sig": false,
"md5_digest": "e16b6a5e513ffe52da04712cb37f6156",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.4",
"size": 70462,
"upload_time": "2024-02-09T02:36:05",
"upload_time_iso_8601": "2024-02-09T02:36:05.456753Z",
"url": "https://files.pythonhosted.org/packages/75/4e/8ce69bf56ae03df008c04351cffac186b4b1b0723985ea76ea02f9a91c2b/python_shogi-1.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-02-09 02:36:05",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "gunyarakun",
"github_project": "python-shogi",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "python-shogi"
}