Beispiel #1
0
    def robot_bet_in(self, dic):
        id = dic.get("game_instance_id", "")  # 项目id
        user_id = dic.get("user_id", "")  # 用户id
        conin_id = dic.get("conin_id", 0)  # 投入币种id
        bet_amount = dic.get("bet_amount", 0)  # 投注数量
        time_stamp = dic.get("time_stamp", 0)  # 纪录时间戳

        with MysqlTools().session_scope() as session:
            # 查询项目
            model = session.query(GameDigitalInstanceModel).filter(
                GameDigitalInstanceModel._id == id).with_for_update().first()
            if model is None:
                raise_logger("机器人下注失败60001", "game_bet_in", "info")
                return 60001
            if model.status == 1:
                raise_logger("机器人下注失败60002", "game_bet_in", "info")
                return 60002
            if model.status == 2:
                raise_logger("机器人下注失败60003", "game_bet_in", "info")
                return 60003
            if model.status == 0:
                can_bet = model.need - model.bet_number
                if can_bet <= 0:
                    raise_logger("机器人下注失败60002", "game_bet_in", "info")
                    return 60005
                if int(bet_amount) > can_bet:
                    raise_logger("机器人下注失败60004", "game_bet_in", "info")
                    return 60004

            # 查询币价 币种实际需要金额
            exchange_rate = get_exchange_rate(int(conin_id))
            # (投注数量 * 投注单位) / 投注币种兑换usdt比例
            bet_money = (int(bet_amount) *
                         model.bet_unit) / exchange_rate['price']

            game_numbers = session.query(GameNumbersSetModel).filter(
                GameNumbersSetModel.game_serial ==
                model.game_serial).with_for_update().all()
            numbers = []
            for num in game_numbers:
                numbers.append(num.number)

            try:
                numbers = random.sample(numbers, int(bet_amount))
            except Exception as e:
                raise_logger("机器人下注失败 没有numbers", "game_bet_in", "info")
                return False
            if isinstance(numbers, list) and len(numbers) > 0:
                # try:
                # 修改机器人账户状态
                user = session.query(RobotAccountModel).filter(
                    RobotAccountModel.user_id ==
                    user_id).with_for_update().first()
                if user is None:
                    raise_logger("机器人下注失败70002", "game_bet_in", "info")
                    return 70002
                user.status = 0

                # 添加投注纪录
                participate_in_model = ParticipateInModel(
                    game_instance_id=model._id,
                    template_id=model.template_id,
                    game_serial=model.game_serial,
                    game_title=model.game_title,
                    release_type=model.release_type,
                    bet_unit=model.bet_unit,
                    bet_token=model.bet_token,
                    user_id=user_id,
                    nick_name=user.nick_name,
                    channel="0",
                    bet_number=int(bet_amount),
                    pay_token=int(conin_id),
                    pay_number=get_decimal(bet_money),
                    award_numbers=json.dumps(numbers),
                    user_type=1)
                session.add(participate_in_model)

                # 修改项目信息
                game_service = GameService()
                if game_service.modifyDigitalInstance(
                        model, {
                            "game_id": id,
                            "add_bet_number": int(bet_amount),
                            "full_load_time": participate_in_model.created_at,
                            "add_people": 1
                        }) is False:
                    session.rollback()
                    raise_logger("机器人下注失败80005", "game_bet_in", "info")
                    return 80005

                # 修改机器人配置纪录 下注状态
                record = session.query(RobotConfigRecordModel).filter(
                    RobotConfigRecordModel.game_instance_id == id,
                    RobotConfigRecordModel.user_id == user_id,
                    RobotConfigRecordModel.time_stamp ==
                    time_stamp).with_for_update().first()
                if record is None:
                    raise_logger("机器人下注失败70002", "game_bet_in", "info")
                    return 70002
                record.bet_status = 1

                # 查看本期 机器人是否都已下注完成
                is_finish = True
                robots = session.query(RobotConfigRecordModel).filter(
                    RobotConfigRecordModel.game_instance_id == id,
                    RobotConfigRecordModel.time_stamp == time_stamp).all()
                for r in robots:
                    if r.bet_status == 0 or r.bet_status == 2:
                        is_finish = False
                        break

                if is_finish:
                    # 修改 游戏机器人配置纪录
                    q = session.query(RobotGameConfigRecordModel).filter(
                        RobotGameConfigRecordModel.game_instance_id == id,
                        RobotGameConfigRecordModel.time_stamp ==
                        time_stamp).with_for_update().first()

                    if q is None:
                        raise_logger("机器人下注失败70003", "game_bet_in", "info")
                        return 70003

                    q.status = 2
                    q.end_of_real_time = datetime.datetime.utcnow().strftime(
                        '%Y-%m-%d %H:%M:%S')

                session.flush()

                try:
                    created_at_str = str(participate_in_model.created_at)
                    update_at_str = str(participate_in_model.update_at)
                    deleted_at_str = str(participate_in_model.deleted_at)
                    deleted_str = str(participate_in_model.deleted)
                    dic = {
                        "id": participate_in_model._id,
                        "created_at": created_at_str[0:19],
                        "update_at": update_at_str[0:19],
                        "deleted_at": deleted_at_str[0:19],
                        "deleted": deleted_str[0:19],
                        "game_instance_id":
                        participate_in_model.game_instance_id,
                        "template_id": participate_in_model.template_id,
                        "game_serial": participate_in_model.game_serial,
                        "bet_token": participate_in_model.bet_token,
                        "user_id": participate_in_model.user_id,
                        "nick_name": participate_in_model.nick_name,
                        "channel": participate_in_model.channel,
                        "pay_token": participate_in_model.pay_token,
                        "bet_number": participate_in_model.bet_number,
                        "pay_number": str(participate_in_model.pay_number),
                        "award_numbers": participate_in_model.award_numbers,
                        "user_type": participate_in_model.user_type,
                    }

                    if BlockChainInfoService().insert_block_chain_info(
                            user_id, participate_in_model.game_instance_id, 1,
                            dic):
                        participate_in_model.chain_status = 1

                except Exception as e:
                    session.rollback()
                    raise_logger("insert_block_chain_info", "game_bet_in",
                                 "info")

                g_service = model.game_serial
                for i in numbers:
                    session.query(GameNumbersSetModel).filter(
                        GameNumbersSetModel.game_serial == g_service,
                        GameNumbersSetModel.number == i).delete()
                # # 检测游戏是否售罄需要申请开奖
                if int(model.status) == 1:
                    add_result = WalletEosService().lottery_adduce(
                        id, get_timestamp(model.full_load_time))
                    if not add_result:
                        raise_logger("lottery_adduce fail", "game_bet_in",
                                     "info")

                session.commit()

                try:
                    # # 提交验证是否需要上线新项目
                    game_service.automatic_release(session, model.template_id)
                except Exception as e:
                    raise_logger("automatic_release", "game_bet_in", "info")

                return True

            # except Exception as e:
            #     session.rollback()
            #     raise_logger("机器人下注失败60006", "game_bet_in", "info")
            #     return 60006

            return False
Beispiel #2
0
    def bet_in(self, dic):
        id = dic.get("game_instance_id", "")  # 项目id
        user_id = dic.get("user_id", "")  # 用户id
        user_channel_id = dic.get("user_channel_id", "")  # 用户下注渠道id
        conin_id = dic.get("conin_id", "")  # 投入币种id
        bet_amount = dic.get("bet_amount", "")  # 投注数量
        merge_id = dic.get("merge_id", -1)  # 合并投注id
        # transaction_password = dic.get("transaction_password", "")  # 交易密码

        with MysqlTools().session_scope() as session:
            # 查询项目
            model = session.query(GameDigitalInstanceModel).filter(
                GameDigitalInstanceModel._id == id).with_for_update().first()
            if model is None:
                return self.return_error(60001)
            if model.status == 1:
                return self.return_error(60002)
            if model.status == 2:
                return self.return_error(60003)
            if model.status == 0:
                can_bet = model.need - model.bet_number
                if can_bet <= 0:
                    return self.return_error(60002)
                if int(bet_amount) > can_bet:
                    return self.return_error(60004)

            if model.support_token >= 0 and int(
                    conin_id) != model.support_token and int(conin_id) != int(
                        _COIN_ID_EXP):
                return self.return_error(60008)

            # 查询币价 币种实际需要金额
            exchange_rate = get_exchange_rate(int(conin_id))

            # (投注数量 * 投注单位) / 投注币种兑换usdt比例
            bet_money = (int(bet_amount) *
                         model.bet_unit) / exchange_rate['price']

            # 体验金相关逻辑
            if int(conin_id) == int(_COIN_ID_EXP):
                # 检查本次投注体验金使用数量 (允许范围: 1~10)
                if int(bet_amount) < 1 or int(bet_amount) > 10:
                    self.return_error(60015)
                # 体验金使用额度
                exp = int(model.experience / 100 * model.need)
                # 检查项目体验金占比剩余额度以及个人当天最大体验金使用额度(每天最多用10个)
                limit = self.check_instance_exp_limit(session, user_id, id)
                instance_limit = limit['instance_limit']
                user_limit = limit['user_limit']
                if user_limit > 10 - int(bet_amount):
                    self.return_error(60017)
                if instance_limit >= exp:
                    self.return_error(60016)

            # 查询用户资产
            account_service = AccountService()
            user_info = account_service.get_inner_user_account_by_token(
                session, user_id, conin_id)
            if isinstance(user_info, int):
                if user_info == 20001:
                    return self.return_error(20001)

            balance = get_decimal(user_info.get("balance"),
                                  digits=8,
                                  decimal_type="down")

            # 账户余额 < 需要下注金额
            if balance < bet_money:
                return self.return_error(60005)

            # 验证交易密码
            # if account_service.check_pay_password(user_id, transaction_password) is False:
            #     return self.return_error(35024)
            # raise_logger("begin", "game_bet_in", "info")
            # 获取下注编号
            game_numbers = session.query(GameNumbersSetModel).filter(
                GameNumbersSetModel.game_serial ==
                model.game_serial).with_for_update().all()
            numbers = []
            for num in game_numbers:
                numbers.append(num.number)
            numbers = random.sample(numbers, int(bet_amount))
            # raise_logger("get game_numbers", "game_bet_in", "info")
            if isinstance(numbers, list):
                nick_name = account_service.get_inner_user_account_info(
                    session, user_id).get("nick_name")
                try:
                    # 添加参与记录
                    participate_in_model = ParticipateInModel(
                        game_instance_id=model._id,
                        template_id=model.template_id,
                        game_serial=model.game_serial,
                        game_title=model.game_title,
                        release_type=model.release_type,
                        bet_token=model.bet_token,
                        bet_unit=model.bet_unit,
                        user_id=user_id,
                        nick_name=nick_name,
                        channel=user_channel_id,
                        bet_number=int(bet_amount),
                        pay_token=int(conin_id),
                        pay_number=get_decimal(bet_money,
                                               digits=8,
                                               decimal_type="down"),
                        award_numbers=json.dumps(numbers),
                        user_type=0,
                        merge_id=merge_id)
                    session.add(participate_in_model)
                    session.flush()
                    # raise_logger("add participate_in_model", "game_bet_in", "info")
                    # 提交扣款申请
                    result = account_service.do_bet(
                        session, user_id, conin_id,
                        get_decimal(bet_money, digits=8, decimal_type="down"),
                        str(participate_in_model._id), int(bet_amount),
                        model.game_serial, user_channel_id)
                    # raise_logger("do_bet success", "game_bet_in", "info")
                    if isinstance(result, int):
                        if result == 0:
                            # 修改项目状态
                            game_service = GameService()
                            # raise_logger("modifyDigitalInstance begin", "game_bet_in", "info")
                            if game_service.modifyDigitalInstance(
                                    model, {
                                        "game_id": id,
                                        "add_bet_number": int(bet_amount),
                                        "full_load_time":
                                        participate_in_model.created_at,
                                        "add_people": 1
                                    }) is False:
                                session.rollback()
                                raise_logger("modifyDigitalInstance err",
                                             "game_bet_in", "info")
                                return self.return_error(80005)
                            # raise_logger("modifyDigitalInstance succ", "game_bet_in", "info")
                            try:
                                created_at_str = str(
                                    participate_in_model.created_at)
                                update_at_str = str(
                                    participate_in_model.update_at)
                                deleted_at_str = str(
                                    participate_in_model.deleted_at)
                                deleted_str = str(participate_in_model.deleted)
                                if BlockChainInfoService(
                                ).insert_block_chain_info(
                                        user_id,
                                        participate_in_model.game_instance_id,
                                        1,
                                    {
                                        "id":
                                        participate_in_model._id,
                                        "created_at":
                                        created_at_str[0:19],
                                        "update_at":
                                        update_at_str[0:19],
                                        "deleted_at":
                                        deleted_at_str[0:19],
                                        "deleted":
                                        deleted_str[0:19],
                                        "game_instance_id":
                                        str(participate_in_model.
                                            game_instance_id),
                                        "template_id":
                                        participate_in_model.template_id,
                                        "game_serial":
                                        participate_in_model.game_serial,
                                        "bet_token":
                                        participate_in_model.bet_token,
                                        "user_id":
                                        participate_in_model.user_id,
                                        "nick_name":
                                        participate_in_model.nick_name,
                                        "channel":
                                        participate_in_model.channel,
                                        "pay_token":
                                        participate_in_model.pay_token,
                                        "bet_number":
                                        participate_in_model.bet_number,
                                        "pay_number":
                                        str(participate_in_model.pay_number),
                                        "award_numbers":
                                        participate_in_model.award_numbers,
                                        "user_type":
                                        participate_in_model.user_type,
                                    }):
                                    participate_in_model.chain_status = 1
                                    # raise_logger("insert_block succ", "game_bet_in", "info")
                                else:
                                    raise_logger("insert_block err",
                                                 "game_bet_in", "info")
                            except Exception as e:
                                session.rollback()
                                raise_logger(e, "game_bet_in", "info")
                            # raise_logger("pri del GameNumbersSetModel", "game_bet_in", "info")
                            for i in numbers:
                                # raise_logger("pri del GameNumbersSetModel", "game_bet_in", "info")
                                # game_number_filters = {"game_serial": model.game_serial, "number": i}
                                session.query(GameNumbersSetModel). \
                                    filter(GameNumbersSetModel.game_serial == model.game_serial,
                                           GameNumbersSetModel.number == i).delete()
                                # number_filter.time_stamp = 1
                                # session.delete(num_filters)
                            # raise_logger("GameNumbersSetModel delete succ", "game_bet_in", "info")

                            # # 检测游戏是否售罄需要申请开奖
                            # instance = session.query(GameDigitalInstanceModel).filter(
                            #     GameDigitalInstanceModel._id == id).first()
                            if int(model.status) == 1:
                                add_result = WalletEosService().lottery_adduce(
                                    id, get_timestamp(model.full_load_time))
                                if not add_result:
                                    raise_logger("lottery_adduce fail",
                                                 "game_bet_in", "info")

                            session.commit()
                            # raise_logger("commit succ", "game_bet_in", "info")
                            try:
                                # # 提交验证是否需要上线新项目
                                game_service.automatic_release(
                                    session, model.template_id)
                            except Exception as e:
                                raise_logger(e, "game_bet_in", "info")

                            can_merge = False
                            if int(
                                    bet_amount
                            ) >= model.merge_threshold and merge_id == -1:
                                can_merge = True
                            # raise_logger("pri return", "game_bet_in", "info")
                            return {
                                'numbers': numbers,
                                'can_merge': can_merge,
                                'part_in_id': participate_in_model._id
                            }

                        else:
                            session.rollback()
                            return self.return_error(60009)
                    else:
                        session.rollback()
                        return self.return_error(60010)

                except Exception as e:
                    raise_logger(e, "game_bet_in", "info")
                    session.rollback()
                    return self.return_error(60011)

                if isinstance(numbers, int):
                    session.rollback()
                    return self.return_error(60012)

            else:
                session.rollback()
                return self.return_error(60007)
def test_generate_board_should_fail_if_any_input_smaller_than_1():
    with pytest.raises(InvalidGameSettingsException) as e:
        mock_game = get_mock_game()
        service = GameService(mock_game)
        service._generate_board(5, 5, -26)
        assert e.message == "All values must be greater than zero"
def test_generate_board_should_fail_if_mine_count_greater_than_board_size():
    with pytest.raises(InvalidGameSettingsException) as e:
        mock_game = get_mock_game()
        service = GameService(mock_game)
        service._generate_board(5, 5, 26)
        assert e.message == "Number of mines must be less than the total board size"
 def setUp(self):
     self.__game_service = GameService()
class TestPieceMoving(unittest.TestCase):
    def setUp(self):
        self.__game_service = GameService()

    def test_all(self):
        self.test_basic_movement()
        self.test_check_situations()
        self.test_checkmate()

    def test_basic_movement(self):
        self.setUp()
        board = self.__game_service.board

        # move the left black knight - should work
        self.__game_service.move(0, 1, 2, 0, PieceColor.BLACK)
        self.assertEqual(board[0, 1], None)
        self.assertEqual(board[2, 0], Knight(board, 2, 0, PieceColor.BLACK))

        # attempt to move the left black knight on a cell occupied by a black piece - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 2, 0, 1, 2, PieceColor.BLACK)
        try:
            self.__game_service.move(2, 0, 1, 2, PieceColor.BLACK)
        except InvalidMoveError as invalidMoveError:
            self.assertEqual(str(invalidMoveError), 'InvalidMoveError: Cannot move to (1, 2) cell.')

        # attempt to simply move a pawn - should work
        self.__game_service.move(1, 1, 2, 1, PieceColor.BLACK)
        self.assertEqual(board[1, 1], None)
        self.assertEqual(board[2, 1], Pawn(board, 2, 1, PieceColor.BLACK))

        # attempt to double-move an already moved pawn - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 2, 1, 4, 1, PieceColor.BLACK)

        # attempt to double-move a pawn - should work
        self.__game_service.move(1, 2, 3, 2, PieceColor.BLACK)
        self.assertEqual(board[1, 2], None)
        self.assertEqual(board[3, 2], Pawn(board, 3, 2, PieceColor.BLACK))

        # attempt to attack-move a black pawn on a cell occupied by a black piece - should work
        self.assertRaises(InvalidMoveError, self.__game_service.move, 2, 1, 3, 2, PieceColor.BLACK)

        # attempt to move the left black rook - should work
        self.__game_service.move(0, 0, 0, 1, PieceColor.BLACK)
        self.assertEqual(board[0, 0], None)
        self.assertEqual(board[0, 1], Rook(board, 0, 1, PieceColor.BLACK))

        # attempt to move a white pawn by 2 cells - should work
        self.__game_service.move(6, 3, 4, 3, PieceColor.WHITE)
        self.assertEqual(board[6, 3], None)
        self.assertEqual(board[4, 3], Pawn(board, 4, 3, PieceColor.WHITE))

        # attempt to capture a white pawn with a black pawn - should work
        self.__game_service.move(3, 2, 4, 3, PieceColor.BLACK)
        self.assertEqual(board[3, 2], None)
        self.assertEqual(board[4, 3], Pawn(board, 4, 3, PieceColor.BLACK))

        # attempt to move the white queen - should work
        self.__game_service.move(7, 3, 5, 3, PieceColor.WHITE)
        self.assertEqual(board[7, 3], None)
        self.assertEqual(board[5, 3], Queen(board, 5, 3, PieceColor.WHITE))

        # attempt to move a black pawn on a cell occupied by the white queen - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 4, 3, 5, 3, PieceColor.BLACK)

        # attempt to diagonally move the white queen, involving also a capture - should work
        self.__game_service.move(5, 3, 2, 0, PieceColor.WHITE)
        self.assertEqual(board[5, 3], None)
        self.assertEqual(board[2, 0], Queen(board, 2, 0, PieceColor.WHITE))

        # attempt to move the black bishop - should work
        self.__game_service.move(0, 2, 1, 1, PieceColor.BLACK)
        self.assertEqual(board[0, 2], None)
        self.assertEqual(board[1, 1], Bishop(board, 1, 1, PieceColor.BLACK))

        # attempt to move the black bishop, involving a capture - should work
        self.__game_service.move(1, 1, 6, 6, PieceColor.BLACK)
        self.assertEqual(board[1, 1], None)
        self.assertEqual(board[6, 6], Bishop(board, 6, 6, PieceColor.BLACK))

        # attempt to move the white queen - should work
        self.__game_service.move(2, 0, 4, 2, PieceColor.WHITE)
        self.assertEqual(board[2, 0], None)
        self.assertEqual(board[4, 2], Queen(board, 4, 2, PieceColor.WHITE))

        # attempt to move the white queen through a cell already occupied by a black piece - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 4, 2, 0, 6, PieceColor.WHITE)

        # attempt to move the white queen through a cell already occupied by a white piece - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 4, 2, 7, 5, PieceColor.WHITE)

        # attempt to move the white queen - should work
        self.__game_service.move(4, 2, 5, 1, PieceColor.WHITE)
        self.assertEqual(board[4, 2], None)
        self.assertEqual(board[5, 1], Queen(board, 5, 1, PieceColor.WHITE))

        # attempt to move the white queen, involving a capture - should work
        self.__game_service.move(5, 1, 2, 1, PieceColor.WHITE)
        self.assertEqual(board[5, 1], None)
        self.assertEqual(board[2, 1], Queen(board, 2, 1, PieceColor.WHITE))

        # attempt to move the black rook through a cell already occupied by a white piece - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 0, 1, 4, 1, PieceColor.BLACK)

        # attempt to move the black rook, involving a capture - should work
        self.__game_service.move(0, 1, 2, 1, PieceColor.BLACK)
        self.assertEqual(board[0, 1], None)
        self.assertEqual(board[2, 1], Rook(board, 2, 1, PieceColor.BLACK))

        # attempt to move the black rook, involving a capture - should work
        self.__game_service.move(2, 1, 6, 1, PieceColor.BLACK)
        self.assertEqual(board[2, 1], None)
        self.assertEqual(board[6, 1], Rook(board, 6, 1, PieceColor.BLACK))

        # attempt to move the white knight - should work
        self.__game_service.move(7, 6, 5, 5, PieceColor.WHITE)
        self.assertEqual(board[7, 6], None)
        self.assertEqual(board[5, 5], Knight(board, 5, 5, PieceColor.WHITE))

        # attempt to move the white knight - should work
        self.__game_service.move(5, 5, 3, 4, PieceColor.WHITE)
        self.assertEqual(board[5, 5], None)
        self.assertEqual(board[3, 4], Knight(board, 3, 4, PieceColor.WHITE))

        # attempt to move the white knight, involving a capture - should work
        self.__game_service.move(3, 4, 1, 5, PieceColor.WHITE)
        self.assertEqual(board[3, 4], None)
        self.assertEqual(board[1, 5], Knight(board, 1, 5, PieceColor.WHITE))

        # attempt to diagonally move the white king, should work
        self.__game_service.move(7, 4, 6, 3, PieceColor.WHITE)
        self.assertEqual(board[7, 4], None)
        self.assertEqual(board[6, 3], King(board, 6, 3, PieceColor.WHITE))

        # attempt to move the white king, should work
        self.__game_service.move(6, 3, 5, 3, PieceColor.WHITE)
        self.assertEqual(board[6, 3], None)
        self.assertEqual(board[5, 3], King(board, 5, 3, PieceColor.WHITE))

        # attempt to move the black queen - should work
        self.__game_service.move(0, 3, 1, 2, PieceColor.BLACK)
        self.assertEqual(board[0, 3], None)
        self.assertEqual(board[1, 2], Queen(board, 1, 2, PieceColor.BLACK))

        # attempt to move the black queen - should work
        self.__game_service.move(1, 2, 4, 2, PieceColor.BLACK)
        self.assertEqual(board[1, 2], None)
        self.assertEqual(board[4, 2], Queen(board, 4, 2, PieceColor.BLACK))

        # attempt to move the white king while in chess - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 5, 3, 4, 3, PieceColor.WHITE)

        # attempt to move the white king, involving a capture - should work
        self.__game_service.move(5, 3, 4, 2, PieceColor.WHITE)
        self.assertEqual(board[5, 3], None)
        self.assertEqual(board[4, 2], King(board, 4, 2, PieceColor.WHITE))

        # attempt to move the king over two cells - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 4, 2, 2, 2, PieceColor.WHITE)

        # attempt to move the white king, involving entering in check - should fail
        self.assertRaises(InvalidMoveError, self.__game_service.move, 4, 2, 5, 2, PieceColor.WHITE)

        # attempt to move the white horse - should work
        self.__game_service.move(1, 5, 2, 7, PieceColor.WHITE)
        self.assertEqual(board[1, 5], None)
        self.assertEqual(board[2, 7], Knight(board, 2, 7, PieceColor.WHITE))

        # attempt to move the black rook - should work
        self.__game_service.move(6, 1, 0, 1, PieceColor.BLACK)
        self.assertEqual(board[6, 1], None)
        self.assertEqual(board[0, 1], Rook(board, 0, 1, PieceColor.BLACK))

        # attempt to move the white horse - should work
        self.__game_service.move(7, 1, 5, 2, PieceColor.WHITE)
        self.assertEqual(board[7, 1], None)
        self.assertEqual(board[5, 2], Knight(board, 5, 2, PieceColor.WHITE))

        # attempt to move the white rook - should work
        self.__game_service.move(7, 0, 7, 1, PieceColor.WHITE)
        self.assertEqual(board[7, 0], None)
        self.assertEqual(board[7, 1], Rook(board, 7, 1, PieceColor.WHITE))

        # attempt to move the black knight - should work
        self.__game_service.move(0, 6, 2, 5, PieceColor.BLACK)
        self.assertEqual(board[0, 6], None)
        self.assertEqual(board[2, 5], Knight(board, 2, 5, PieceColor.BLACK))

        # attempt to move the black knight - should work
        self.__game_service.move(2, 5, 3, 3, PieceColor.BLACK)
        self.assertEqual(board[2, 5], None)
        self.assertEqual(board[3, 3], Knight(board, 3, 3, PieceColor.BLACK))

        # attempt to move the white rook - should work
        self.__game_service.move(7, 1, 1, 1, PieceColor.WHITE)
        self.assertEqual(board[7, 1], None)
        self.assertEqual(board[1, 1], Rook(board, 1, 1, PieceColor.WHITE))

        # attempt to move the black knight - should work
        self.__game_service.move(3, 3, 2, 1, PieceColor.BLACK)
        self.assertEqual(board[3, 3], None)
        self.assertEqual(board[2, 1], Knight(board, 2, 1, PieceColor.BLACK))

        # attempt to move the white king, involving a capture - should work
        self.__game_service.move(4, 2, 3, 2, PieceColor.WHITE)
        self.assertEqual(board[4, 2], None)
        self.assertEqual(board[3, 2], King(board, 3, 2, PieceColor.WHITE))

        # attempt to move the black knight - should work
        self.__game_service.move(2, 1, 0, 2, PieceColor.BLACK)
        self.assertEqual(board[2, 1], None)
        self.assertEqual(board[0, 2], Knight(board, 0, 2, PieceColor.BLACK))

    def test_check_situations(self):
        board = self.__game_service.board

        # attempt to move a black pawn - should work (now white king is in check)
        self.__game_service.move(1, 3, 2, 3, PieceColor.BLACK)
        self.assertEqual(board[1, 3], None)
        self.assertEqual(board[2, 3], Pawn(board, 2, 3, PieceColor.BLACK))

        # because the king is in check the next white move must get the king out of check (else checkmate). In this case, only the king can move
        for piece in self.__game_service.board.whites:
            if piece.__class__.__name__ != "King" and piece.get_move_options() != []:
                assert False

        # the moves that the king can do in this situation
        king = board[3, 2]
        king_moves = king.get_move_options()
        assert (len(king_moves) == 4)

        moves = [(4, 3), (4, 2), (4, 1), (3, 1)]
        for move in moves:
            assert (move in king_moves)

        # the white rook (and the other pieces but for the king too) cannot move in this situation (because of the check)
        self.assertRaises(InvalidMoveError, self.__game_service.move, 1, 1, 1, 2, PieceColor.WHITE)

        # move the white king
        self.__game_service.move(3, 2, 4, 2, PieceColor.WHITE)

        # move the black pawn in order to produce again check
        self.__game_service.move(2, 3, 3, 3, PieceColor.BLACK)

        # now the white knight should have only one possible move, capturing the black pawn who produced the check
        assert (board[5, 2].get_move_options() == [(3, 3)])

        # all the other pieces (but for the white knight and the king) should not be able to move
        for piece in self.__game_service.board.whites:
            if piece.__class__.__name__ != "King" and piece.get_move_options() != []:
                if not piece.x == 5 or not piece.y == 2:
                    assert False

        # double check situation (triple check is not possible)
        board[3, 3] = None

        # move the black rook for initiating the double check situation
        board[0, 1] = None
        board[2, 2] = Rook(board, 2, 2, PieceColor.BLACK)

        # move the black bishop, now white king is double checked
        board[0, 5] = None
        board[2, 0] = Bishop(board, 2, 0, PieceColor.BLACK)

        # move the white horse, such that it could theoretically capture the black rook. However, the move is not possible because of the double check
        board[5, 2] = None
        board[3, 4] = Knight(board, 3, 4, PieceColor.WHITE)

        # note also that the white rook at (1, 1) could block the bishop. However, this is not enough to get rid of the double check
        # no blocking/capturing is possible. The only escape occurs if the king can move in a safe cell
        for piece in board.whites:
            if piece.__class__.__name__ != "King" and piece.get_move_options() != []:
                assert False

        # move the king such that it could theoretically capture one of the dangerous pieces and also escape check. This should work

        board[2, 0] = None
        self.__game_service.move(4, 2, 3, 1, PieceColor.WHITE)
        board[2, 0] = Bishop(board, 2, 0, PieceColor.BLACK)

        board[2, 2] = None
        board[5, 1] = Rook(board, 5, 1, PieceColor.BLACK)

        # move the white horse
        board[2, 7] = None
        board[6, 3] = Knight(board, 6, 3, PieceColor.WHITE)

        # move the white rook
        board[7, 7] = None
        board[7, 1] = Rook(board, 7, 1, PieceColor.WHITE)

        # no blocking/capturing from other piece but for the king is possible. The only escape occurs if the king can move in a safe cell
        for piece in board.whites:
            if piece.__class__.__name__ != "King" and piece.get_move_options() != []:
                assert False

    def test_checkmate(self):
        board = self.__game_service.board
        # move the white king and check the fact that the game can go on
        assert (not self.__game_service.move(3, 1, 3, 0, PieceColor.WHITE))

        # move the black bishop
        assert (not self.__game_service.move(2, 0, 6, 4, PieceColor.BLACK))

        # move a black pawn
        assert (not self.__game_service.move(4, 3, 5, 3, PieceColor.BLACK))

        # replace the black rooks
        board[0, 7] = None
        board[2, 1] = Rook(board, 2, 1, PieceColor.BLACK)

        assert (board[3, 0].get_move_options() == [(4, 0)])

        board[5, 1] = None
        board[4, 1] = Rook(board, 4, 1, PieceColor.BLACK)

        # check king check
        assert (board[3, 0].check_safe(3, 0))
        assert (board[3, 0].get_move_options() == [])

        # move a black knight to check the white king
        board[0, 2] = None
        board[4, 2] = Knight(board, 4, 2, PieceColor.BLACK)

        # still, no checkmate situation, because the checking black knight can be captured
        assert(self.__game_service.checkmate(PieceColor.BLACK) == self.__game_service.checkmate(PieceColor.WHITE) == False)

        # if the white horse moves away from its position, then the black horse checks again, we have a checkmate situation
        board[6, 3] = None
        assert(not self.__game_service.move(4, 2, 6, 1, PieceColor.BLACK))
        assert(not self.__game_service.move(3, 4, 2, 6, PieceColor.WHITE))
        assert(self.__game_service.move(6, 1, 4, 2, PieceColor.BLACK))

        for piece in board.whites:
            if piece.get_move_options():
                assert False

        # now, checkmate is no longer valid
        board[1, 0] = None
        board[4, 1] = None
        board[4, 4] = Rook(board, 4, 4, PieceColor.BLACK)
        board[4, 2] = None
        board[2, 2] = Knight(board, 2, 4,PieceColor.BLACK)
        assert(not self.__game_service.checkmate(PieceColor.WHITE))
Beispiel #7
0
from controllers.business_exception import BusinessException
from controllers.game_controller import GameController
from plugins.sqlalchemy_session_manager_plugin.bottle_sqlalchemy_session_manager_plugin import \
    BottleSQLAlchemySessionPlugin
from services.auth.auth_service import AuthService
from plugins.controller_plugin.controller_plugin import ControllerPlugin
from plugins.plugins import JsonPlugin, EnableCors, AuthPlugin, ErrorFilterPlugin
from plugins.pyjson.pyjson import PyJsonConverter
from plugins.pyjson_plugin.pyjson_plugin import BottlePyJsonPlugin
from db import ENGINE
from services.game_service import GameService

app = Bottle(autojson=False)

auth_service = AuthService()
game_service = GameService()

app.install(JsonPlugin())
app.install(ErrorFilterPlugin())
app.install(
    BottleSQLAlchemySessionPlugin(engine=ENGINE,
                                  commit=False,
                                  create_session_by_default=True))
app.install(AuthPlugin(auth_service))
app.install(EnableCors())
converter = PyJsonConverter()
app.install(BottlePyJsonPlugin(converter))
app.install(ControllerPlugin())

logger = ConsoleLogger()