Skip to content

Commit

Permalink
Merge pull request #159 from madcpf/board
Browse files Browse the repository at this point in the history
Add Board class
  • Loading branch information
madcpf authored Oct 5, 2023
2 parents 2c414f6 + fb6db0b commit f01775f
Show file tree
Hide file tree
Showing 2 changed files with 222 additions and 0 deletions.
121 changes: 121 additions & 0 deletions unitary/examples/quantum_chinese_chess/board.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Copyright 2023 The Unitary Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import List
import unitary.alpha as alpha
from unitary.examples.quantum_chinese_chess.enums import (
SquareState,
Color,
Type,
Language,
)
from unitary.examples.quantum_chinese_chess.piece import Piece


# The default initial state of the game.
_INITIAL_FEN = "RHEAKAEHR/9/1C5C1/P1P1P1P1P/9/9/p1p1p1p1p/1c5c1/9/rheakaehr w---1"


class Board:
"""Board holds the assemble of all pieces. Each piece could be either in classical or quantum state."""

def __init__(
self, board: alpha.QuantumWorld, current_player: int, king_locations: List[str]
):
self.board = board
self.current_player = current_player
self.king_locations = king_locations
self.lang = Language.EN # The default language is English.

def set_language(self, lang: Language):
self.lang = lang

@classmethod
def from_fen(cls, fen: str = _INITIAL_FEN) -> "Board":
"""
Translates FEN (Forsyth-Edwards Notation) symbols into the whole QuantumWorld board.
FEN rule for Chinese Chess could be found at https://www.wxf-xiangqi.org/images/computer-xiangqi/fen-for-xiangqi-chinese-chess.pdf
"""
chess_board = {}
row_index = 9
king_locations = []
pieces, turns = fen.split(" ", 1)
for row in pieces.split("/"):
col = ord("a")
for char in row:
# Add empty board pieces.
if "1" <= char <= "9":
for i in range(int(char)):
name = f"{chr(col)}{row_index}"
chess_board[name] = Piece(
name, SquareState.EMPTY, Type.EMPTY, Color.NA
)
col += 1
# Add occupied board pieces.
else:
name = f"{chr(col)}{row_index}"
piece_type = Type.type_of(char)
if piece_type == Type.KING:
king_locations.append(name)
color = Color.RED if char.isupper() else Color.BLACK
chess_board[name] = Piece(
name, SquareState.OCCUPIED, piece_type, color
)
col += 1
row_index -= 1
board = alpha.QuantumWorld(chess_board.values())
# Here 0 means the player RED while 1 the player BLACK.
current_player = 0 if "w" in turns else 1
return cls(board, current_player, king_locations)

def __str__(self):
num_rows = 10
board_string = ["\n "]
# Print the top line of col letters.
for col in "abcdefghi":
board_string.append(f" {col}")
board_string.append("\n")
for row in range(num_rows):
# Print the row index on the left.
board_string.append(f"{row} ")
for col in "abcdefghi":
piece = self.board[f"{col}{row}"]
board_string += piece.symbol(self.lang)
if self.lang == Language.EN:
board_string.append(" ")
# Print the row index on the right.
board_string.append(f" {row}\n")
board_string.append(" ")
# Print the bottom line of col letters.
for col in "abcdefghi":
board_string.append(f" {col}")
board_string.append("\n")
if self.lang == Language.EN:
return "".join(board_string)
# We need to turn letters into their full-width counterparts to align
# a mix of letters + Chinese characters.
chars = "".join(chr(c) for c in range(ord(" "), ord("z")))
full_width_chars = "\N{IDEOGRAPHIC SPACE}" + "".join(
chr(c)
for c in range(
ord("\N{FULLWIDTH EXCLAMATION MARK}"),
ord("\N{FULLWIDTH LATIN SMALL LETTER Z}"),
)
)
translation = str.maketrans(chars, full_width_chars)
return (
"".join(board_string)
.replace(" ", "")
.replace("abcdefghi", " abcdefghi")
.translate(translation)
)
101 changes: 101 additions & 0 deletions unitary/examples/quantum_chinese_chess/board_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Copyright 2023 The Unitary Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from unitary.examples.quantum_chinese_chess.enums import Language
from unitary.examples.quantum_chinese_chess.board import Board


def test_init_with_default_fen():
board = Board.from_fen()
assert (
board.__str__()
== """
a b c d e f g h i
0 r h e a k a e h r 0
1 . . . . . . . . . 1
2 . c . . . . . c . 2
3 p . p . p . p . p 3
4 . . . . . . . . . 4
5 . . . . . . . . . 5
6 P . P . P . P . P 6
7 . C . . . . . C . 7
8 . . . . . . . . . 8
9 R H E A K A E H R 9
a b c d e f g h i
"""
)

board.set_language(Language.ZH)
assert (
board.__str__()
== """
 abcdefghi
0車馬相仕帥仕相馬車0
1.........1
2.砲.....砲.2
3卒.卒.卒.卒.卒3
4.........4
5.........5
6兵.兵.兵.兵.兵6
7.炮.....炮.7
8.........8
9车马象士将士象马车9
 abcdefghi
"""
)

assert board.king_locations == ["e9", "e0"]


def test_init_with_specified_fen():
board = Board.from_fen("4kaR2/4a4/3hR4/7H1/9/9/9/9/4Ap1r1/3AK3c w---1 ")

assert (
board.__str__()
== """
a b c d e f g h i
0 . . . A K . . . c 0
1 . . . . A p . r . 1
2 . . . . . . . . . 2
3 . . . . . . . . . 3
4 . . . . . . . . . 4
5 . . . . . . . . . 5
6 . . . . . . . H . 6
7 . . . h R . . . . 7
8 . . . . a . . . . 8
9 . . . . k a R . . 9
a b c d e f g h i
"""
)

board.set_language(Language.ZH)
assert (
board.__str__()
== """
 abcdefghi
0...士将...砲0
1....士卒.車.1
2.........2
3.........3
4.........4
5.........5
6.......马.6
7...馬车....7
8....仕....8
9....帥仕车..9
 abcdefghi
"""
)

assert board.king_locations == ["e9", "e0"]

0 comments on commit f01775f

Please sign in to comment.