def Can_Hu(extra_card, data, is_ZIMO): ## give extra_card(draw or others play), judge if can HU and return # if_Hu(bool), action, data play_ID, quan, pack, hand, hua = data["info"] #将list转换成tuple new_pack = [] for item in pack: new_pack.append(tuple(item)) new_pack = tuple(new_pack) try: new_hand = decode_card(hand) #transfer list[int] -> list[string] ans = MahjongFanCalculator(new_pack, new_hand, extra_card, hua, is_ZIMO, False, False, False, play_ID, quan) fan = 0 for item in ans: fan += item[0] fan = fan - hua if fan < 8: #未到8番 raise Exception except Exception as err: #not HU return False, "", "" else: action = "HU" data = "" return True, action, data
def judgeHu(self, last_card, playerID, isGANG, dianPao=False): hand = [] for ind, cardcnt in enumerate(self.hand_free): for _ in range(cardcnt): hand.append(self.getCardName(ind)) if self.history[self.getCardInd(last_card)] == 4: isJUEZHANG = True else: isJUEZHANG = False if self.tile_count[(playerID + 1) % 4] == 0: isLAST = True else: isLAST = False if not dianPao: hand.remove(last_card) try: ans = MahjongFanCalculator(tuple(self.hand_fixed_data), tuple(hand), last_card, 0, playerID==self.myPlayerID, isJUEZHANG, isGANG, isLAST, self.myPlayerID, self.quan) except Exception as err: if str(err) == 'ERROR_NOT_WIN': return 0 else: if not self.botzone: print(hand, last_card, self.hand_fixed_data) print(self.fname) print(err) return 0 else: fan_count = 0 for fan in ans: fan_count += fan[0] return fan_count
def judge_hu(dat, isZimo, isGang): # 调用算番库判定有没有胡牌 # 当前明牌、和牌 cur_pack = tuple((tuple(pk) for pk in dat['pack'])) winTile = dat['cur_request'][-1] # 自摸一张牌(包括杠上开花),此时新的那张牌已经加入avail_cards了,但判胡时不应在手牌里,所以去掉 if isZimo: dat['avail_cards'].remove(winTile) cur_hand = tuple(dat['avail_cards']) # 当前手牌 # 判定海底捞月、妙手回春需要计算别人的牌墙 if isZimo: next_id = (dat['id'] + 1) % 4 # 判断我的下家牌墙里有没有牌 else: next_id = (int(dat['cur_request'][1]) + 1) % 4 # 判断出牌者的下家牌墙里有没有牌 isLast = (dat['card_wall_remain'][next_id] == 0) # 没牌了,则是妙手回春/海底捞月,即isLast if isGang and not isZimo: # 但是如果是抢杠胡,isLast一定是False,这块需要特判,因为那张胡牌实际上没打出来,没有所谓的下家 isLast = False # 判定和绝张需要判定明牌里面是否已经有三张winTile if dat['all_shown_cards'].count(winTile) + int(isZimo) >= 4: isJuezhang = True else: isJuezhang = False try: judge_res = MahjongFanCalculator(cur_pack, cur_hand, winTile, 0, isZimo, isJuezhang, isGang, isLast, dat['quan'], dat['id']) except Exception as err: judge_res = str(err) # print(judge_res, '\n', isZimo, isGang, isLast, isJuezhang) if isinstance(judge_res, str): cur_fan = 0 else: cur_fan = sum([fan[0] for fan in judge_res]) # 之后还得恢复回来,因为还可能计算别的 if isZimo: dat['avail_cards'].append(winTile) if cur_fan >= 8: return True, judge_res else: return False, judge_res
def naive_cal_fan(dat, card): cur_pack = tuple((tuple(pk) for pk in dat['pack'])) cur_hand = tuple(dat['avail_cards']) # 当前手牌 isLast = False isZimo = True # 自摸比较容易 isGang = False isJuezhang = False if dat['all_shown_cards'].count(card) == 3: isJuezhang = True try: judge_res = MahjongFanCalculator(cur_pack, cur_hand, card, 0, isZimo, isJuezhang, isGang, isLast, dat['quan'], dat['id']) except Exception as err: judge_res = str(err) if isinstance(judge_res, str): cur_fan = 0 else: cur_fan = sum([fan[0] for fan in judge_res]) return cur_fan
def _checkMahjong(self, player, isSelfDrawn = False, isAboutKong = False): try: fans = MahjongFanCalculator( pack = tuple(self.packs[player]), hand = tuple(self.hands[player]), winTile = self.curTile, flowerCount = len(self.flowers[player]), isSelfDrawn = isSelfDrawn, is4thTile = self.shownTiles[self.curTile] == 4, isAboutKong = isAboutKong, isWallLast = self.wallLast, seatWind = player, prevalentWind = self.prevalentWind, verbose = True ) f = [] fanCnt = 0 for fanPoint, cnt, fanName, fanNameEn in fans: f.append(dict(name = fanName, cnt = cnt, value = fanPoint)) fanCnt += fanPoint * cnt if fanCnt < 8: raise Error('Not Enough Fans') if isSelfDrawn: score = [-(8 + fanCnt)] * 4 score[player] = (8 + fanCnt) * 3 else: score = [-8] * 4 score[player] = 8 * 3 + fanCnt score[self.curPlayer] -= fanCnt self.display.append(dict( action = 'HU', player = player, fan = f, fanCnt = fanCnt, score = score )) self.round = None return tuple(score) except Exception as e: raise Error(player)
from MahjongGB import MahjongFanCalculator, MahjongShanten # Non-positional arguments print( MahjongFanCalculator((), ("W1", "W1", "W1", "W2", "W2", "W2", "W3", "W3", "W3", "W4", "W4", "W4", "W5"), "W5", 1, True, False, False, True, 0, 0)) print( MahjongShanten((), ("W1", "W1", "W1", "W2", "W2", "W2", "W3", "W3", "W3", "W4", "W4", "W4", "W5"))) print( MahjongShanten((), ("W1", "B1", "T1", "W2", "W2", "W2", "W3", "J3", "F3", "F4", "W4", "W4", "W9"))) # Support keyword arguments print( MahjongFanCalculator(pack=(("GANG", "W1", 2), ), hand=("W2", "W2", "W2", "W3", "W3", "W3", "W4", "W4", "W4", "W5"), winTile="W5", flowerCount=2, isSelfDrawn=False, is4thTile=False, isAboutKong=False, isWallLast=False, seatWind=0, prevalentWind=0)) print( MahjongShanten(pack=(("GANG", "W1", 2), ), hand=("W1", "B1", "T1", "W2", "W2", "W2", "W3", "J3", "F3", "F4")))
def step(self, action:list): ''' 用于update状态 @param: action: example: [("PASS", 0), ("PASS", 1), ("PASS", 2), ("PASS", 3)] 0/1/2/3分别表示玩家的id ''' new_action = [] for x in action: tmp = json.loads(x[0]) new_action.append((tmp['response'], x[1])) action = new_action if self.game_state[:9] == "NEED_PASS": if self.game_state != "NEED_PASS": ''' 这里可以胡牌 ''' for i in range(4): if action[i][0][:2] == "HU": player_id = action[i][1] tmp_hand = copy.deepcopy(self.hand[player_id]) try: result = MahjongFanCalculator( tuple(self.pack[player_id]), tuple(tmp_hand), self.disc_tile, len(self.flower[player_id]), False, self.desk.count(self.disc_tile) == 3, False, # 这里没完全理解到这个参数啥意思。。 len(self.wall) == 0, player_id, self.wind ) sumv = 0 for x in result: sumv += x[0] if sumv < 8: raise BaseException(f"{player_id} 进行了错胡") except: raise BaseException(f"{player_id} 进行了错胡") self.is_end = True self.result = player_id return for i in range(4): if action[i][0][:4] != "PASS": raise BaseException(f"{action[i][1]} 你应该输出PASS") self.game_state = "" elif self.game_state == "DRAW": for i in range(4): if action[i][0][:4] == "PASS": if action[i][1] == (self.prev_player+1)%4: raise BaseException(f"{action[i][1]} 你不应该输出PASS"+str(action[i])) continue if action[i][1] != (self.prev_player+1)%4: raise BaseException(f"{action[i][1]}你现在应该输出PASS") player_id = action[i][1] if action[i][0][:4] == "PLAY": self.game_state = "PLAYED" self.player_id = player_id self.disc_tile = action[i][0][5:7] if self.hand[player_id].count(self.disc_tile) == 0: raise BaseException(f"{player_id} 试图discard他没有的牌") self.hand[player_id].pop(self.hand[player_id].index(self.disc_tile)) return elif action[i][0][:4] == "GANG": self.game_state = "GANGED" self.player_id = player_id self.disc_tile = action[i][0][5:7] if self.hand[player_id].count(self.disc_tile) < 4: raise BaseException(f"{player_id} 试图gang他没有的牌") for j in range(4): self.hand[player_id].pop(self.hand[player_id].index(self.disc_tile)) self.pack[player_id].append(("GANG", self.disc_tile, 0)) return elif action[i][0][:4] == "BUGANG": self.game_state = "BUGANGED" self.player_id = player_id self.disc_tile = action[i][0][7:9] if self.hand[player_id].count(self.disc_tile) == 0: raise BaseException(f"{player_id} 试图bugang他没有的牌") self.hand[player_id].pop(self.hand[player_id].index(self.disc_tile)) ok = False for i in range(len(self.pack[player_id])): if self.pack[player_id][i][1] == self.disc_tile: self.pack[player_id][i][0] = "GANG" ok = True break if not ok: raise BaseException(f"{player_id} 试图bugang他没有的PENG") return elif action[i][0][:4] == "HU": tmp_hand = copy.deepcopy(self.hand[player_id]) tmp_hand.pop(tmp_hand.index(self.last_draw)) try: result = MahjongFanCalculator( tuple(self.pack[player_id]), tuple(tmp_hand), self.last_draw, len(self.flower[player_id]), True, self.desk.count(self.last_draw) == 3, self.ganged == 1, len(self.wall) == 0, player_id, self.wind ) sumv = 0 for x in result: sumv += x[0] if sumv < 8: raise BaseException(f"{player_id} 进行了错胡") except Exception as err: raise BaseException(f"{player_id} 进行了错胡") self.is_end = True self.result = player_id return elif self.game_state == "PLAYED_WAITING": for i in range(len(action)): player_id = action[i][1] if action[i][0][:2] == "HU": tmp_hand = copy.deepcopy(self.hand[player_id]) try: result = MahjongFanCalculator( tuple(self.pack[player_id]), tuple(tmp_hand), self.disc_tile, len(self.flower[player_id]), False, self.desk.count(self.disc_tile) == 3, False, len(self.wall) == 0, player_id, self.wind ) sumv = 0 for x in result: sumv += x[0] if sumv < 8: raise BaseException(f"{player_id} 进行了错胡 {sumv}") except: raise BaseException(f"{player_id} 进行了错胡") self.is_end = True self.result = player_id return for i in range(len(action)): player_id = action[i][1] if action[i][0][:4] == "PENG": self.desk.pop(self.desk.index(self.disc_tile)) self.pack[player_id].append(("PENG", self.disc_tile, (player_id-self.player_id+4)%4)) if self.hand[player_id].count(self.disc_tile) < 2: raise BaseException(f"{player_id} 试图peng他没有的牌") for j in range(2): self.hand[player_id].pop(self.hand[player_id].index(self.disc_tile)) self.disc_tile = action[i][0].split(' ')[1] if self.hand[player_id].count(self.disc_tile) == 0: raise BaseException(f"{player_id} 试图在peng的时候discard他没有的牌") self.hand[player_id].pop(self.hand[player_id].index(self.disc_tile)) self.player_id = player_id self.game_state = "PENGED" return elif action[i][0][:4] == "GANG": self.desk.pop(self.desk.index(self.disc_tile)) self.pack[player_id].append(("GANG", self.disc_tile, (player_id-self.player_id+4)%4)) if self.hand[player_id].count(self.disc_tile) < 3: raise BaseException(f"{player_id} 试图gang他没有的牌") for j in range(3): self.hand[player_id].pop(self.hand[player_id].index(self.disc_tile)) self.disc_tile = "" self.player_id = -1 self.game_state = "GANGED" return for i in range(len(action)): player_id = action[i][1] if action[i][0][:3] == "CHI": self.desk.pop(self.desk.index(self.disc_tile)) if (player_id+3)%4 != self.player_id: raise BaseException(f"{player_id} 试图从错误的位置进行吃牌") chi_tile = action[i][0][4:6] out_tile = action[i][0][7:9] self.hand[player_id].append(self.disc_tile) if self.hand[player_id].count(out_tile) == 0: raise BaseException(f"{player_id} 试图使用他没有的牌 {out_tile}") if self.hand[player_id].count(chi_tile) == 0: raise BaseException(f"{player_id} 试图使用他没有的牌 {chi_tile}") if self.hand[player_id].count(prevTile(chi_tile)) == 0: raise BaseException(f"{player_id} 试图使用他没有的牌 {prevTile(chi_tile)}") if self.hand[player_id].count(backTile(chi_tile)) == 0: raise BaseException(f"{player_id} 试图使用他没有的牌 {backTile(chi_tile)}") self.hand[player_id].pop(self.hand[player_id].index(out_tile)) self.hand[player_id].pop(self.hand[player_id].index(chi_tile)) self.hand[player_id].pop(self.hand[player_id].index(prevTile(chi_tile))) self.hand[player_id].pop(self.hand[player_id].index(backTile(chi_tile))) number = 2 if prevTile(chi_tile) == self.disc_tile: number = 1 if backTile(chi_tile) == self.disc_tile: number = 3 self.pack[player_id].append(("CHI", chi_tile, number)) self.chi_tile = chi_tile self.disc_tile = out_tile self.player_id = player_id self.game_state = "CHIED" return self.game_state = "" self.player_id = -1 return
from MahjongGB import MahjongFanCalculator try: ans=MahjongFanCalculator((),("W1","W1","W1","W2","W2","W2","W3","W3","W3","W4","W4","W4","W5"),"W5",1,True,False,False,True,0,0) except Exception as err: print(err) else: print(ans) try: ans=MahjongFanCalculator((("GANG","W1",2),),("W2","W2","W2","W3","W3","W3","W4","W4","W4","W5"),"W5",1,False,False,False,False,0,0) except Exception as err: print(err) else: print(ans) #错误 try: ans=MahjongFanCalculator((),("W1","W1","W1","W2","W2","W2","W3","W3","W3","W4","W4","W4"),"W5",1,True,False,False,True,0,0) except Exception as err: print(err) else: print(ans) #没和 try: ans=MahjongFanCalculator((("CHI","W1",0),),("W2","W2","W2","W3","W3","W3","W4","W4","W4","W5"),"W7",1,False,False,False,False,0,0) except Exception as err: print(err) else: print(ans)