def handleTableCallChi(self, user_id, seat_id, message): """ 玩家吃牌上行消息 (框架调用) 参数说明: @param user_id, 协议发送方的用户id @param seat_id, 协议发送方的座位号 @param message 协议其他数据 协议示例 {"cmd":"table_call","params":{"action":"chi","action_id":24,"tile":4,"pattern":[2,3,4],"seatId":0, "roomId":72018031001,"tableId":720180310010200,"gameId":7201,"userId":10001,"clientId":"Android_3.901_weixin,tyGuest.alipay.0-hall7201.youle.hengyangmj"} """ action_id = message.getParam('action_id') if action_id == self.table.actionID: tile = message.getParam('tile', None) pattern = message.getParam('pattern', None) pattern.sort() if not pattern or not tile: HYLog.error('handleTableCallChi: wrong pattern or tile word!', pattern, tile) self.table.do_chow_tile(seat_id, tile, pattern) else: HYLog.info('handleTableCallChi: wrong actionId:', action_id, ' ,now table actionId:', self.table.actionID, ', message:', message) pass
def send_tiles(self, active_seat_id, count): """ 发牌 @param active_seat_id, 发牌对象座位号 @param count, 获取牌的张数 @:return 返回花色list PS: 1.通过脚本热加载手段 设定HYTestTrickTile.Tiles数据 2.self.tiles 是定义在父类中的@property """ tiles = [] if len(self.tiles) < count: return tiles if HYTestTrickTile.Debug and len( HYTestTrickTile.Tiles[active_seat_id]) >= count: for _ in range(count): tiles.append(HYTestTrickTile.Tiles[active_seat_id].pop(0)) pass HYLog.debug('send_tiles: trick tiles:', tiles) # 手牌中要移除trick后的牌 for tile in tiles: if tile in self.tiles: self.tiles.remove(tile) else: for _ in range(count): tiles.append(self.tiles.pop(0)) pass HYLog.debug('send_tiles: tiles:', tiles) return tiles
def handleTableCallGang(self, user_id, seat_id, message): """ 玩家杠牌上行消息 (框架调用) 参数说明: @param user_id, 协议发送方的用户id @param seat_id, 协议发送方的座位号 @param message 协议其他数据 协议示例 {"cmd":"table_call","params":{"action":"gang","action_id":24,"tile":4,"gang":{"style":1,"pattern":[4,4,4,4]},"seatId":0, "roomId":72018031001,"tableId":720180310010200,"gameId":7201,"userId":10001,"clientId":"Android_3.901_weixin,tyGuest.alipay.0-hall7201.youle.hengyangmj"} """ action_id = message.getParam('action_id') if action_id == self.table.actionID: kong = message.getParam('gang', None) tile = message.getParam('tile', None) if not kong or not tile: HYLog.error('handleTableCallGang: wrong gang or tile word!', kong, tile) return style = kong.get('style') pattern = kong.get('pattern') pattern.sort() self.table.do_kong_tile(seat_id, tile, pattern, style) else: HYLog.info('handleTableCallGang: wrong actionId:', action_id, ' ,now table actionId:', self.table.actionID, ', message:', message) pass
def calc_gang(self): """计算杠的输赢""" # 明杠暗杠统计 resultStat = [[] for _ in range(self.__player_count)] self.__results[self.KEY_TYPE] = HYOneBudget.KEY_TYPE_NAME_GANG base = self.__table_config.get(MTDefine.GANG_BASE, 0) if self.style == MPlayerTileGang.AN_GANG: self.__results[self.KEY_NAME] = "暗杠" base *= 2 resultStat[self.__active_seat_id].append({HYOneBudget.STAT_ANGANG: 1}) else: self.__results[self.KEY_NAME] = "明杠" resultStat[self.__active_seat_id].append({HYOneBudget.STAT_MINGGANG: 1}) if self.__passvie_seat_id != self.__active_seat_id: scores = [0 for _ in range(self.__player_count)] scores[self.__active_seat_id] = base scores[self.__passvie_seat_id] = -base else: scores = [-base for _ in range(self.__player_count)] scores[self.__active_seat_id] = (self.__player_count - 1) * base HYLog.debug('MOneResult.calcGang gangType:', self.__results[self.KEY_NAME], ' scores', scores) self.__results[self.KEY_SCORE] = scores self.__results[self.KEY_STAT] = resultStat
def calc_gang(self): """计算杠的输赢""" # 明杠暗杠统计 resultStat = [[] for _ in range(self.__player_count)] self.__results[self.KEY_TYPE] = HYOneBudget.KEY_TYPE_NAME_GANG base = self.__table_config.get(MTDefine.GANG_BASE, 0) if self.style == MPlayerTileGang.AN_GANG: self.__results[self.KEY_NAME] = "暗杠" base *= 2 resultStat[self.__active_seat_id].append( {HYOneBudget.STAT_ANGANG: 1}) else: self.__results[self.KEY_NAME] = "明杠" resultStat[self.__active_seat_id].append( {HYOneBudget.STAT_MINGGANG: 1}) if self.__passvie_seat_id != self.__active_seat_id: scores = [0 for _ in range(self.__player_count)] scores[self.__active_seat_id] = base scores[self.__passvie_seat_id] = -base else: scores = [-base for _ in range(self.__player_count)] scores[self.__active_seat_id] = (self.__player_count - 1) * base HYLog.debug('MOneResult.calcGang gangType:', self.__results[self.KEY_NAME], ' scores', scores) self.__results[self.KEY_SCORE] = scores self.__results[self.KEY_STAT] = resultStat
def unserialize(self, obj): """反序列化""" HYLog.debug('HYWinLoseResult.unSerialize: ', obj) self.__play_mode = obj.get('playMode', None) self.__banker_seat_id = obj.get('bankerSeatId', None) self.__active_seat_id = obj.get('winSeatId', None) self.__passvie_seat_id = obj.get('lastSeatId', None) self.__win_tile = obj.get('winTile', 0) self.__aciton_id = obj.get('actionID', 0) self.__player_count = obj.get('playCount', 4) self.__table_config = obj.get('tableConfig', None)
def calc_score(self): """计算输赢数值""" # 放在这里补充环境数据,要么不方便单元测试 self.__player_all_tiles for player in self.__table_tile_mgr.players: # 按手牌格式的数组 self.__player_all_tiles[player.curSeatId] = player.copyTiles() # 合到一个数组中 self.__player_all_tiles_arr[player.curSeatId].extend( MHand.copyAllTilesToList( self.__player_all_tiles[player.curSeatId])) # 只获取手牌,手牌不包含所胡的牌,加上胡的牌 self.__player_hand_tiles_with_hu[ player.curSeatId] = player.copyHandTiles() if player.curSeatId == self.winSeatId: self.__player_hand_tiles_with_hu[player.curSeatId].append( self.winTile) # 听亮的状态 self.__player_ting_liang[player.curSeatId] = player.isTingLiang() HYLog.info('MKawuxingOneResult.calcScore __player_all_tiles=', self.__player_all_tiles) HYLog.info('MKawuxingOneResult.calcScore __player_all_tiles_arr=', self.__player_all_tiles_arr) HYLog.info('MKawuxingOneResult.calcScore __player_hand_tiles_with_hu=', self.__player_hand_tiles_with_hu) HYLog.info('MKawuxingOneResult.calcScore __player_ting_liang=', self.__player_ting_liang) if self.winSeatId == self.lastSeatId: # 自摸 winMode = MWinRule.WIN_BY_MYSELF else: winMode = MWinRule.WIN_BY_OTHERS tiles = { MHand.TYPE_HAND: self.__player_hand_tiles_with_hu[self.winSeatId] } winResult, winPattern = MWinRuleFactory.getWinRule( MPlayMode.KAWUXING).isHu( tiles, self.winTile, self.tableTileMgr.players[self.winSeatId].isTing(), winMode) # 此处有坑,winPattern只有一种牌型,似乎优先一样的牌,比如:[14,14,14,15,15,16,16,16,19,19,19,20,20],最后抓15 # 如果卡五星比碰碰胡番数高,此处应该算卡五星,所以isHu应该返回所有可能的胡的牌型,结算时计算最优的番型 # 此处预留isHu的修改 # 此处不用winNodes主要原因是,卡五星可以不听/亮牌,直接胡 self.__win_patterns = [winPattern] HYLog.info('MKawuxingOneResult.calcScore __win_patterns=', self.__win_patterns)
def __init__(self, tableId, room): super(HYMajiangFriendTable, self).__init__(tableId, room) # 逻辑处理者 self.logic_table = HYMajiangTableLogic(self.maxSeatN, self.playMode, MRunMode.LONGNET) self.logic_table.setTableConfig(self._tableConf) self.logic_table.msgProcessor.setInfo(self.gameId, self.roomId, self.tableId, self.playMode, self.tableType, self.maxSeatN) self.logic_table.msgProcessor.setRoomInfo(self._roomConf, self._tableConf) # 指向本地的操作处理 self.setActionHandler(HYActionHandlerLongNet()).setTable(self.logic_table) HYLog.debug("HYMajiangFriendTable's actionHandler has table:", self.actionHander.table) observer = QuJingTableObserver(self.gameId, self.roomId, self.tableId) self.setTableObserver(observer)
def serialize(self): """序列化""" obj = {} if self.__play_mode: obj['playMode'] = self.__play_mode if self.__banker_seat_id: obj['bankerSeatId'] = self.__banker_seat_id if self.__active_seat_id: obj['winSeatId'] = self.__active_seat_id if self.__passvie_seat_id: obj['lastSeatId'] = self.__passvie_seat_id if self.__win_tile: obj['winTile'] = self.__win_tile if self.__aciton_id: obj['actionID'] = self.__aciton_id if self.__player_count: obj['playCount'] = self.__player_count if self.__table_config: obj['tableConfig'] = self.__table_config HYLog.debug('HYWinLoseResult.serialize: ', obj)
def calc_score(self): """计算输赢数值""" # 放在这里补充环境数据,要么不方便单元测试 self.__player_all_tiles for player in self.__table_tile_mgr.players: # 按手牌格式的数组 self.__player_all_tiles[player.curSeatId] = player.copyTiles() # 合到一个数组中 self.__player_all_tiles_arr[player.curSeatId].extend( MHand.copyAllTilesToList(self.__player_all_tiles[player.curSeatId])) # 只获取手牌,手牌不包含所胡的牌,加上胡的牌 self.__player_hand_tiles_with_hu[player.curSeatId] = player.copyHandTiles() if player.curSeatId == self.winSeatId: self.__player_hand_tiles_with_hu[player.curSeatId].append(self.winTile) # 听亮的状态 self.__player_ting_liang[player.curSeatId] = player.isTingLiang() HYLog.info('MKawuxingOneResult.calcScore __player_all_tiles=', self.__player_all_tiles) HYLog.info('MKawuxingOneResult.calcScore __player_all_tiles_arr=', self.__player_all_tiles_arr) HYLog.info('MKawuxingOneResult.calcScore __player_hand_tiles_with_hu=', self.__player_hand_tiles_with_hu) HYLog.info('MKawuxingOneResult.calcScore __player_ting_liang=', self.__player_ting_liang) if self.winSeatId == self.lastSeatId: # 自摸 winMode = MWinRule.WIN_BY_MYSELF else: winMode = MWinRule.WIN_BY_OTHERS tiles = {MHand.TYPE_HAND: self.__player_hand_tiles_with_hu[self.winSeatId]} winResult, winPattern = MWinRuleFactory.getWinRule(MPlayMode.KAWUXING).isHu(tiles, self.winTile, self.tableTileMgr.players[ self.winSeatId].isTing(), winMode) # 此处有坑,winPattern只有一种牌型,似乎优先一样的牌,比如:[14,14,14,15,15,16,16,16,19,19,19,20,20],最后抓15 # 如果卡五星比碰碰胡番数高,此处应该算卡五星,所以isHu应该返回所有可能的胡的牌型,结算时计算最优的番型 # 此处预留isHu的修改 # 此处不用winNodes主要原因是,卡五星可以不听/亮牌,直接胡 self.__win_patterns = [winPattern] HYLog.info('MKawuxingOneResult.calcScore __win_patterns=', self.__win_patterns)
def handleTableCallWin(self, user_id, seat_id, message): """ 玩家胡牌上行消息 (框架调用) 参数说明: @param user_id, 协议发送方的用户id @param seat_id, 协议发送方的座位号 @param message 协议其他数据 协议示例 {"cmd":"table_call","params":{"action":"win","action_id":24,"tile":4,"seatId":0, "roomId":72018031001,"tableId":720180310010200,"gameId":7201,"userId":10001,"clientId":"Android_3.901_weixin,tyGuest.alipay.0-hall7201.youle.hengyangmj"} """ action_id = message.getParam('action_id') if action_id == self.table.actionID: tile = message.getParam('tile') if not tile: HYLog.error('handleTableCallWin: wrong tile word!', tile) return self.table.do_win_tile(seat_id, tile) else: HYLog.info('handleTableCallWin: wrong actionId:', action_id, ' ,now table actionId:', self.table.actionID, ', message:', message)
def __init__(self, tableId, room): super(HYMajiangFriendTable, self).__init__(tableId, room) # 逻辑处理者 self.logic_table = HYMajiangTableLogic(self.maxSeatN, self.playMode, MRunMode.LONGNET) self.logic_table.setTableConfig(self._tableConf) self.logic_table.msgProcessor.setInfo(self.gameId, self.roomId, self.tableId, self.playMode, self.tableType, self.maxSeatN) self.logic_table.msgProcessor.setRoomInfo(self._roomConf, self._tableConf) # 指向本地的操作处理 self.setActionHandler(HYActionHandlerLongNet()).setTable( self.logic_table) HYLog.debug("HYMajiangFriendTable's actionHandler has table:", self.actionHander.table) observer = QuJingTableObserver(self.gameId, self.roomId, self.tableId) self.setTableObserver(observer)
# -*- coding=utf-8
def calcWin(self): """卡五星算番规则""" winnerResult = self.getWinnerResults() maxFan = self.tableConfig.get(MTDefine.MAX_FAN, 0) score = [0 for _ in range(self.playerCount)] if self.lastSeatId != self.winSeatId: # 放炮和牌 finalResult = [] finalResult.extend(winnerResult) finalResult.extend(self.getPaoResults()) finalResult.extend(self.getLooserResults(self.lastSeatId)) winScore = self.getScoreByResults(finalResult, maxFan) score[self.lastSeatId] = -winScore score[self.winSeatId] = winScore else: # 自摸胡牌 winScore = 0 for seatId in range(len(score)): finalResult = [] if seatId != self.winSeatId: finalResult.extend(winnerResult) finalResult.extend(self.getLooserResults(seatId)) tableScore = self.getScoreByResults(finalResult, maxFan) score[seatId] = -tableScore winScore += tableScore score[self.winSeatId] = winScore HYLog.info('MKawuxingOneResult.calcWin score:', score) self.results[self.KEY_SCORE] = score # 只有一种KEY_NAME不合理,名称的优先级根据需求再加 self.results[self.KEY_NAME] = MOneResult.KEY_TYPE_NAME_HU self.results[self.KEY_TYPE] = MOneResult.KEY_TYPE_NAME_HU self.results[self.KEY_FAN_PATTERN] = [[] for _ in range(self.playerCount)] self.results[self.KEY_FAN_PATTERN][self.winSeatId] = self.getFanPatternListByResults(winnerResult) # 目前从前端代码上看,winMode只能区分:平胡(非自摸和牌),自摸,点炮 self.results[self.KEY_WIN_MODE] = [MOneResult.WIN_MODE_LOSS for _ in range(self.playerCount)] self.results[self.KEY_STAT] = [[] for _ in range(self.playerCount)] if self.winSeatId == self.lastSeatId: # 自摸 self.results[self.KEY_WIN_MODE][self.winSeatId] = MOneResult.WIN_MODE_ZIMO # 自摸者自摸+1 self.results[self.KEY_STAT][self.winSeatId].append({MOneResult.STAT_ZIMO: 1}) else: # 点炮,赢的人平胡 self.results[self.KEY_WIN_MODE][self.winSeatId] = MOneResult.WIN_MODE_PINGHU # 点炮,放跑者标为点炮 self.results[self.KEY_WIN_MODE][self.lastSeatId] = MOneResult.WIN_MODE_DIANPAO # 点炮,点炮者点炮+1 self.results[self.KEY_STAT][self.lastSeatId].append({MOneResult.STAT_DIANPAO: 1}) # 最大番,当前的赢家番数,如果超过封顶,也显示原始番数 self.results[self.KEY_STAT][self.winSeatId].append( {MOneResult.STAT_ZUIDAFAN: self.getFanByResults(winnerResult)}) HYLog.debug('MYunnanOneResult calcScore:KEY_SCORE:', self.results[self.KEY_SCORE]) HYLog.debug('MYunnanOneResult calcScore:KEY_NAME:', self.results[self.KEY_NAME]) HYLog.debug('MYunnanOneResult calcScore:KEY_TYPE:', self.results[self.KEY_TYPE]) HYLog.debug('MYunnanOneResult calcScore:KEY_WIN_MODE:', self.results[self.KEY_WIN_MODE]) HYLog.debug('MYunnanOneResult calcScore:KEY_FAN_PATTERN:', self.results[self.KEY_FAN_PATTERN]) HYLog.debug('MYunnanOneResult calcScore:KEY_STAT:', self.results[self.KEY_STAT])
def find_unformed_tiles(cls, tiles=[], pair=2): """ 在tiles里找到不成型牌,排除顺子和刻子 @param tiles:花色一维数组 @param pair:根据将牌来搜牌型,依次可以搜出3种不同结构 @return:返回不成型牌列表,刻子列表,顺子列表,杠牌列表 根据将牌来搜牌型,依次可以搜出3种不同结构,选择unformed_tiles02最少的结果 """ tiles_map = HYWinRuleFunction.find_repeat_tile_info(tiles) HYLog.debug("find_unformed_tiles: pair&tiles_map:", pair, tiles_map) triplet_tiles = [] sequence_tiles = [] unformed_tiles00 = {} # 非刻子花色字典, 标记每个花色的张数, 计数器 unformed_tiles01 = [] # 非刻子花色数组, 标记剩余的花色 unformed_tiles02 = [] # 非成型花色数组, 标记剔除刻子,顺子,杠的剩余牌张花色(可能包含将牌) pair_tiles = [] # 剔除刻子&2,5,8 将牌 for tile in tiles_map: if tiles_map[tile] == 4: # 4张牌按顺子处理, 如果不杠的话 unformed_tiles00[tile] = 1 unformed_tiles01.append(tile) triplet_tiles.append([tile for _ in range(3)]) pass elif tiles_map[tile] == 3: triplet_tiles.append([tile for _ in range(3)]) elif tiles_map[tile] == 2 and cls.do_tile_to_single_digit( tile) == pair: # 必须有指定将牌,eg:2 5 8 pair_tiles.extend([tile for _ in range(2)]) elif tiles_map[tile] < 3: unformed_tiles00[tile] = tiles_map[tile] unformed_tiles01.append(tile) # 剔除顺子,利用牌张计数器 count = len(unformed_tiles01) i = 0 unformed_tiles01.sort() # 非刻子花色数组升序排列 while (i < count): a = unformed_tiles01[i] b = 0 if i + 1 >= count else unformed_tiles01[i + 1] c = 0 if i + 2 >= count else unformed_tiles01[i + 2] if b == 0 or c == 0 or (b != a + 1 or c != a + 2) or (a + c) % 2 != 0: if unformed_tiles00[a] > 0: unformed_tiles02.append(a) i += 1 else: # 计算至少可以成几个顺子 minv minv = min(unformed_tiles00[a], unformed_tiles00[b], unformed_tiles00[c]) unformed_tiles00[a] -= minv unformed_tiles00[b] -= minv unformed_tiles00[c] -= minv sequence_tiles.extend([[a, b, c] for _ in range(minv)]) if unformed_tiles00[a] > 0: unformed_tiles02.append(a) i += 1 pass return [unformed_tiles02, pair_tiles, sequence_tiles, triplet_tiles]
def calcWin(self): """卡五星算番规则""" winnerResult = self.getWinnerResults() maxFan = self.tableConfig.get(MTDefine.MAX_FAN, 0) score = [0 for _ in range(self.playerCount)] if self.lastSeatId != self.winSeatId: # 放炮和牌 finalResult = [] finalResult.extend(winnerResult) finalResult.extend(self.getPaoResults()) finalResult.extend(self.getLooserResults(self.lastSeatId)) winScore = self.getScoreByResults(finalResult, maxFan) score[self.lastSeatId] = -winScore score[self.winSeatId] = winScore else: # 自摸胡牌 winScore = 0 for seatId in range(len(score)): finalResult = [] if seatId != self.winSeatId: finalResult.extend(winnerResult) finalResult.extend(self.getLooserResults(seatId)) tableScore = self.getScoreByResults(finalResult, maxFan) score[seatId] = -tableScore winScore += tableScore score[self.winSeatId] = winScore HYLog.info('MKawuxingOneResult.calcWin score:', score) self.results[self.KEY_SCORE] = score # 只有一种KEY_NAME不合理,名称的优先级根据需求再加 self.results[self.KEY_NAME] = MOneResult.KEY_TYPE_NAME_HU self.results[self.KEY_TYPE] = MOneResult.KEY_TYPE_NAME_HU self.results[self.KEY_FAN_PATTERN] = [[] for _ in range(self.playerCount)] self.results[self.KEY_FAN_PATTERN][ self.winSeatId] = self.getFanPatternListByResults(winnerResult) # 目前从前端代码上看,winMode只能区分:平胡(非自摸和牌),自摸,点炮 self.results[self.KEY_WIN_MODE] = [ MOneResult.WIN_MODE_LOSS for _ in range(self.playerCount) ] self.results[self.KEY_STAT] = [[] for _ in range(self.playerCount)] if self.winSeatId == self.lastSeatId: # 自摸 self.results[self.KEY_WIN_MODE][ self.winSeatId] = MOneResult.WIN_MODE_ZIMO # 自摸者自摸+1 self.results[self.KEY_STAT][self.winSeatId].append( {MOneResult.STAT_ZIMO: 1}) else: # 点炮,赢的人平胡 self.results[self.KEY_WIN_MODE][ self.winSeatId] = MOneResult.WIN_MODE_PINGHU # 点炮,放跑者标为点炮 self.results[self.KEY_WIN_MODE][ self.lastSeatId] = MOneResult.WIN_MODE_DIANPAO # 点炮,点炮者点炮+1 self.results[self.KEY_STAT][self.lastSeatId].append( {MOneResult.STAT_DIANPAO: 1}) # 最大番,当前的赢家番数,如果超过封顶,也显示原始番数 self.results[self.KEY_STAT][self.winSeatId].append( {MOneResult.STAT_ZUIDAFAN: self.getFanByResults(winnerResult)}) HYLog.debug('MYunnanOneResult calcScore:KEY_SCORE:', self.results[self.KEY_SCORE]) HYLog.debug('MYunnanOneResult calcScore:KEY_NAME:', self.results[self.KEY_NAME]) HYLog.debug('MYunnanOneResult calcScore:KEY_TYPE:', self.results[self.KEY_TYPE]) HYLog.debug('MYunnanOneResult calcScore:KEY_WIN_MODE:', self.results[self.KEY_WIN_MODE]) HYLog.debug('MYunnanOneResult calcScore:KEY_FAN_PATTERN:', self.results[self.KEY_FAN_PATTERN]) HYLog.debug('MYunnanOneResult calcScore:KEY_STAT:', self.results[self.KEY_STAT])