""" Practice Projects: Chess Dictionary Validator Page 127 """ import sys tests = [ # Valid { "1h": "bking", "6c": "wqueen", "2g": "bbishop", "5h": "bqueen", "3e": "wking", }, # Invalid: Illegal total amount of pieces { "1a": "wrook", "1b": "wknight", "1c": "wbishop", "1d": "wqueen", "1e": "wking", "1f": "wbishop", "1g": "wknight", "1h": "wrook", "2a": "wpawn", "2b": "wpawn", "2c": "wpawn", "2d": "wpawn", "2e": "wpawn", "2f": "wpawn", "2g": "wpawn", "2h": "wpawn", "3a": "wrook", }, # Invalid: Illegal amount of pieces { "8h": "wking", "7h": "wking", }, # Invalid: Illegal position length { "9": "bking", }, # Invalid: Illegal position length { "9hh": "bking", }, # Invalid: Illegal tile number { "9h": "bking", }, # Invalid: Illegal tile letter { "1r": "bking", }, # Invalid: Illegal player color { "8h": "cking", }, # Invalid: Illegal piece name { "8h": "wring", }, # Invalid: Illegal piece data type { "8h": None, }, # Invalid: Illegal board data type None, ] def invalidAmount(name, present, expected): err = f"AmountError: total {name}" return f"{err}; total == {present}, expected: <= {expected}" def invalidPos(name, pos, present, expected): err = f"PositionError: {name} '{pos}'" return f"{err}; length == {present}, expected: {expected}" def invalidPiece(name, color_piece, present, expected): err = f"PieceError: {name} '{color_piece}'" return f"{err}; {name} == {present}, expected: {expected}" def invalidType(name, present, expected): err = f"TypeError: {name} type" return False, f"{err}; type == {present}, expected: {expected}" def isValidPos(pos): if len(pos) != 2: return invalidPos("length", pos, len(pos), 2) number, letter = pos[0], pos[1] if number not in "12345678": return invalidPos("number", pos, number, "1-8") if letter not in "abcdefgh": return invalidPos("letter", pos, letter, "a-h") def isValidPiece(color_piece): pieces = "pawn knight bishop rook queen king".split() color, piece = color_piece[0], color_piece[1:] if color not in "bw": return invalidPiece("color", color_piece, color, "w | b") if piece not in pieces: return invalidPiece("piece", color_piece, piece, " | ".join(pieces)) def isValidAmount(player): totals = { "all": 16, "pawn": 8, "king": 1, } total = 0 for key, val in totals.items(): if key in player.keys() and player[key] > val: return invalidAmount(f"'{key}'", player[key], val) for val in player.values(): total += val if total > totals["all"]: return invalidAmount("pieces", total, totals["all"]) def isValidChessBoard(board): players, valid, msg = {}, True, "Valid" if not isinstance(board, dict): return invalidType("board", type(board), type({})) for pos, piece in board.items(): if not isinstance(piece, str): return invalidType("piece", type(piece), type("")) players.setdefault(piece[0], {}) player = players[piece[0]] player.setdefault(piece[1:], 0) player[piece[1:]] += 1 checks = [isValidPos(pos), isValidPiece(piece), isValidAmount(player)] for check in checks: if check is not None: valid, msg = False, check break return valid, msg valid = True for test in tests: print(f"Testing board '{test}': ") valid, msg = isValidChessBoard(test) print("=>", msg) if not valid: sys.exit(1)