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
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))
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()