diff --git a/README.md b/README.md index 99e4254c..ae26d420 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ You can then clone the repository into your development environment by using (substitute USER with your github username) git clone https://github.com/USER/unitary.git + cd unitary git remote add upstream https://github.com/quantumlib/unitary.git This will clone your fork so that you can work on it, while marking the diff --git a/unitary/examples/quantum_chinese_chess/enums.py b/unitary/examples/quantum_chinese_chess/enums.py index 49e54ddc..128f1843 100644 --- a/unitary/examples/quantum_chinese_chess/enums.py +++ b/unitary/examples/quantum_chinese_chess/enums.py @@ -15,6 +15,11 @@ from typing import Optional +class Language(enum.Enum): + EN = 0 # English + ZH = 1 # Chinese + + class SquareState(enum.Enum): EMPTY = 0 OCCUPIED = 1 @@ -42,31 +47,56 @@ class MoveVariant(enum.Enum): CAPTURE = 3 -class Piece(enum.Enum): - EMPTY = "." - SOLDIER = "s" - CANNON = "c" - ROOK = "r" - HORSE = "h" - ELEPHANT = "e" - ADVISOR = "a" - GENERAL = "g" +class Color(enum.Enum): + NA = 0 + RED = 1 + BLACK = 2 + - @classmethod - def type_of(cls, c: str) -> Optional["Piece"]: +class Type(enum.Enum): + """ + The names are from FEN for Xiangqi. + The four values are symbols corresponding to + - English red + - English black + - Chinese red + - Chinese black + """ + + EMPTY = (".", ".", ".", ".") + PAWN = ("P", "p", "兵", "卒") + CANNON = ("C", "c", "炮", "砲") + ROOK = ("R", "r", "车", "車") + HORSE = ("H", "h", "马", "馬") + ELEPHANT = ("E", "e", "象", "相") + ADVISOR = ("A", "a", "士", "仕") + KING = ("K", "k", "将", "帥") + + @staticmethod + def type_of(c: str) -> Optional["Type"]: return { - "s": Piece.SOLDIER, - "c": Piece.CANNON, - "r": Piece.ROOK, - "h": Piece.HORSE, - "e": Piece.ELEPHANT, - "a": Piece.ADVISOR, - "g": Piece.GENERAL, - ".": Piece.EMPTY, + "p": Type.PAWN, + "c": Type.CANNON, + "r": Type.ROOK, + "h": Type.HORSE, + "e": Type.ELEPHANT, + "a": Type.ADVISOR, + "k": Type.KING, + ".": Type.EMPTY, }.get(c.lower(), None) - def red_symbol(self) -> str: - return self.value.upper() - - def black_symbol(self) -> str: - return self.value + @staticmethod + def symbol(type_: "Type", color: Color, lang: Language = Language.EN) -> str: + if type_ == Type.EMPTY: + return "." + if lang == Language.EN: # Return English symbols + if color == Color.RED: + return type_.value[0] + elif color == Color.BLACK: + return type_.value[1] + elif lang == Language.ZH: # Return Chinese symbols + if color == Color.RED: + return type_.value[2] + elif color == Color.BLACK: + return type_.value[3] + raise ValueError("Unexpected combinations of language and color.") diff --git a/unitary/examples/quantum_chinese_chess/enums_test.py b/unitary/examples/quantum_chinese_chess/enums_test.py index 75b0bd50..894a4991 100644 --- a/unitary/examples/quantum_chinese_chess/enums_test.py +++ b/unitary/examples/quantum_chinese_chess/enums_test.py @@ -11,24 +11,30 @@ # 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 Piece +from unitary.examples.quantum_chinese_chess.enums import Type, Color, Language -def test_piece(): - assert Piece.type_of("s") == Piece.SOLDIER - assert Piece.type_of("S") == Piece.SOLDIER - assert Piece.type_of("g") == Piece.GENERAL - assert Piece.type_of("G") == Piece.GENERAL - assert Piece.type_of(".") == Piece.EMPTY - assert Piece.type_of("b") == None +def test_type_of(): + assert Type.type_of("p") == Type.PAWN + assert Type.type_of("P") == Type.PAWN + assert Type.type_of("k") == Type.KING + assert Type.type_of("K") == Type.KING + assert Type.type_of(".") == Type.EMPTY + assert Type.type_of("b") == None - assert Piece.CANNON.red_symbol() == "C" - assert Piece.CANNON.black_symbol() == "c" - assert Piece.HORSE.red_symbol() == "H" - assert Piece.HORSE.black_symbol() == "h" - assert Piece.type_of("r").red_symbol() == "R" - assert Piece.type_of("a").red_symbol() == "A" +def test_symbol(): + assert Type.symbol(Type.CANNON, Color.RED) == "C" + assert Type.symbol(Type.CANNON, Color.BLACK) == "c" + assert Type.symbol(Type.CANNON, Color.RED, Language.ZH) == "炮" + assert Type.symbol(Type.CANNON, Color.BLACK, Language.ZH) == "砲" - assert Piece.type_of(Piece.ELEPHANT.red_symbol()) == Piece.ELEPHANT - assert Piece.type_of(Piece.ELEPHANT.black_symbol()) == Piece.ELEPHANT + assert Type.symbol(Type.HORSE, Color.RED) == "H" + assert Type.symbol(Type.HORSE, Color.BLACK) == "h" + assert Type.symbol(Type.HORSE, Color.RED, Language.ZH) == "马" + assert Type.symbol(Type.HORSE, Color.BLACK, Language.ZH) == "馬" + + assert Type.symbol(Type.EMPTY, Color.RED) == "." + assert Type.symbol(Type.EMPTY, Color.BLACK) == "." + assert Type.symbol(Type.EMPTY, Color.RED, Language.ZH) == "." + assert Type.symbol(Type.EMPTY, Color.BLACK, Language.ZH) == "." diff --git a/unitary/examples/quantum_chinese_chess/piece.py b/unitary/examples/quantum_chinese_chess/piece.py new file mode 100644 index 00000000..6335c530 --- /dev/null +++ b/unitary/examples/quantum_chinese_chess/piece.py @@ -0,0 +1,33 @@ +# 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.alpha import QuantumObject +from unitary.examples.quantum_chinese_chess.enums import ( + SquareState, + Language, + Color, + Type, +) + + +class Piece(QuantumObject): + def __init__(self, name: str, state: SquareState, type_: Type, color: Color): + QuantumObject.__init__(self, name, state) + self.type_ = type_ + self.color = color + + def symbol(self, lang: Language = Language.EN) -> str: + return Type.symbol(self.type_, self.color, lang) + + def __str__(self): + return self.symbol() diff --git a/unitary/examples/quantum_chinese_chess/piece_test.py b/unitary/examples/quantum_chinese_chess/piece_test.py new file mode 100644 index 00000000..6141ff0a --- /dev/null +++ b/unitary/examples/quantum_chinese_chess/piece_test.py @@ -0,0 +1,49 @@ +# 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 ( + SquareState, + Language, + Color, + Type, +) +from unitary.examples.quantum_chinese_chess.piece import Piece +from unitary.alpha import QuantumWorld + + +def test_symbol(): + p0 = Piece("a0", SquareState.OCCUPIED, Type.CANNON, Color.RED) + assert p0.symbol() == "C" + assert p0.__str__() == "C" + assert p0.symbol(Language.ZH) == "炮" + + p1 = Piece("b1", SquareState.OCCUPIED, Type.HORSE, Color.BLACK) + assert p1.symbol() == "h" + assert p1.__str__() == "h" + assert p1.symbol(Language.ZH) == "馬" + + p2 = Piece("c2", SquareState.EMPTY, Type.EMPTY, Color.NA) + assert p2.symbol() == "." + assert p2.__str__() == "." + assert p2.symbol(Language.ZH) == "." + + +def test_enum(): + p0 = Piece("a0", SquareState.OCCUPIED, Type.CANNON, Color.RED) + p1 = Piece("b1", SquareState.OCCUPIED, Type.HORSE, Color.BLACK) + p2 = Piece("c2", SquareState.EMPTY, Type.EMPTY, Color.NA) + board = QuantumWorld([p0, p1, p2]) + assert board.peek() == [ + [SquareState.OCCUPIED, SquareState.OCCUPIED, SquareState.EMPTY] + ]