logicfk.js 137 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209
  1. 'use strict';
  2. //// 为什么选择 Lodash ?
  3. //// Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。
  4. //// Lodash 的模块化方法 非常适用于:
  5. //// 遍历 array、object 和 string
  6. //// 对值进行操作和检测
  7. //// 创建符合功能的函数
  8. var _ = require('lodash');
  9. var quick = require('quick-pomelo');
  10. var logger = quick.logger.getLogger('fhmj', __filename);
  11. // 所有牌
  12. const CARDS = [
  13. 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒
  14. 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万
  15. 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条
  16. // 51, // 中
  17. 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒
  18. 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万
  19. 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条
  20. // 51, // 中
  21. 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒
  22. 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万
  23. 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条
  24. // 51, // 中
  25. 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒
  26. 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万
  27. 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条
  28. // 51, // 中
  29. ];
  30. // 块类型
  31. const STYLE = {
  32. NULL: 0, // 无效
  33. CHI: 1, // 吃牌
  34. SUN: 2, // 顺序
  35. PENG: 3, // 碰子
  36. KE: 4, // 刻子
  37. GANG: 5, // 杠子
  38. ANGANG: 6, // 暗杠
  39. ZMGANG: 7, // 自摸明杠
  40. BU: 8, // 补子
  41. ANBU: 9, // 暗补
  42. ZMBU: 10, // 自摸明补
  43. // LIANGBD:9, // TL++两张百搭和一张普通牌组成一个块
  44. // SANBD:10, // TL++三张百搭和一张普通牌组成一个块
  45. };
  46. // 椅子数
  47. const CHAIR_COUNT = 4;
  48. const CARDS_COUNT = 13;
  49. // 构造方法
  50. var Logic = function (type,gameKindTL,playerAllCount,other) {
  51. // 类型
  52. this.type = type;
  53. this.other = other;//////TL++2人3人的游戏规则
  54. this.jiangmaCount = 2;////奖码张数(抓鸟张数)
  55. this.kexuanList = [0,0,0,0];
  56. if(this.other & 1){
  57. this.kexuanList[0] = 1;//勾选了中途大四喜
  58. }
  59. if(this.other & 2){
  60. this.kexuanList[1] = 1;//勾选了中途六六顺
  61. }
  62. if(this.other & 4){
  63. this.kexuanList[2] = 1;//勾选了门清
  64. }
  65. if(this.other & 256){
  66. this.kexuanList[3] = 1;//勾选了小胡只能自摸
  67. }
  68. this.hzCount = 0;/////红中个数
  69. this.fengDingType = 0;/////封顶类型1:不封顶;2:封顶56分;3:封顶112分;
  70. if(this.other & 8){
  71. this.fengDingType = 1;
  72. }
  73. else if(this.other & 16){
  74. this.fengDingType = 2;
  75. }
  76. else if(this.other & 32){
  77. this.fengDingType = 3;
  78. }
  79. this.ZNJSType = 0;/////中鸟结算类型1:中鸟相加;2:中鸟相乘;
  80. if(this.other & 64){
  81. this.ZNJSType = 1;
  82. }
  83. else if(this.other & 128){
  84. this.ZNJSType = 2;
  85. }
  86. this.gameKindTL = 1;//1:传统;2:割索;3:疯狂
  87. if(this.other & 512){
  88. this.gameKindTL = 2;
  89. }
  90. else if(gameKindTL == 3){
  91. this.gameKindTL = 3;//疯狂
  92. this.hzCount = 4;/////红中个数 疯狂模式默认为4张红中
  93. }
  94. this.isZNZM = false;/////是否只能自摸,拉杠情况可以胡
  95. // console.warn("封顶类型1:不封顶;2:封顶56分;3:封顶112分 "+this.fengDingType)
  96. // console.warn("中鸟结算类型1:中鸟相加;2:中鸟相乘 "+this.ZNJSType)
  97. // console.warn("logicfk可选列表 ffffkkkk222 "+this.kexuanList)
  98. // 七对
  99. // this.has7d = true;/////TL++因为奉化麻将当中本身就可以胡7对
  100. // 全牌
  101. var cards = _.clone(CARDS);
  102. // 添加红中红中
  103. if (this.hzCount > 0){
  104. for (let i = 0; i < this.hzCount; ++i) {
  105. cards[cards.length] = 51;
  106. }
  107. }
  108. this.castCount = 0;
  109. this.disCount = 0;
  110. this.lastCount = cards.length;//////设置剩余牌数为了测试海底捞月
  111. this.cardsPool = cards;
  112. this.cardsyl = _.clone(cards);
  113. // console.warn(" this.cardsyl "+this.cardsyl+" lastCount "+this.lastCount);
  114. //////以下变量全是TL++
  115. this.playerAllCount = playerAllCount || 4;////游戏人数 = 2表示2人局 = 3表示3人局 = 4表示4人局
  116. this.setCardFilerIndex = 0
  117. this.baiDaCard = 51;/////TL++,拿到百搭牌
  118. this.baiDaList = [0,0,0];/////TL++,拿到百搭牌数组
  119. this.sbyBDList = []//////得到某人手中的百搭牌数组
  120. this.chuPaiCountTL = 0//////TL++,记录出牌的个数,为了判断天胡和地胡
  121. this.moPaiCountTL = 0//////TL++,记录出牌的个数,为了判断天胡和地胡
  122. this.lastMoPaiChairID = 0//////TL++,最后一个摸牌玩家的id
  123. this.addThisIsHu = 0//////TL++,胡牌判断时加上这张能不能胡
  124. this.isSeleCatcedCard = false//////判断能否胡牌的那张牌是自己抓的还是别人打出来的
  125. this.currChairIDTL = 0/////当前判断胡的chairID,用于得到当前玩家的胡牌情况
  126. this.isGGMG = [false,false,false,false];//////TL++,是否刚刚直杠(明杠)用于判断是否是直杠杠开
  127. this.isGGAG = [false,false,false,false];//////TL++,是否刚刚暗杠用于判断是否暗杠杠开
  128. this.isGGFXG = [false,false,false,false];//////TL++,是否刚刚风险杠用于判断是否风险杠杠开
  129. this.isLaGang = false;//////TL++,是否刚刚被拉杠用于判断是否被拉杠胡
  130. this.isGuoHuList = [[false,-1],[false,-1],[false,-1],[false,-1],]/////TL++,各个玩家在本轮是否点击了过胡和点击过牌时的台数
  131. this.setCardFileName = '';/////设置手牌的文件名
  132. this.cardGroupIndex = 0;////要设置的牌型种类
  133. this.isZHYZ = false;/////是不是最后1张
  134. this.isMZWF = [0,1,2,3];/////是不是满足位风
  135. /////TL++每个人满足的的起手胡胡牌类型
  136. this.everyQSHType = [
  137. [],[],[],[]
  138. ]
  139. this.canSelects = [//各个起手胡玩家可以选择的牌型
  140. [],[],[],[]
  141. ];
  142. /////TL++每个人满足的的起手胡胡牌类型操作过的牌
  143. this.everyQSHCZGList = [
  144. [],[],[],[]
  145. ]
  146. /////TL++每个人满足的的起手胡胡牌类型操作过的牌
  147. this.everyQSHCZGList2 = [
  148. [],[],[],[]
  149. ]
  150. this.qshuTypeTL = [
  151. /////分别表示起手胡牌型和台数
  152. ["四喜",2,], ///// 0 起完牌后,玩家手上已有四张一样的牌;
  153. ["板板胡",2,], ///// 1 起完牌后,玩家手上没有一张2、5、8牌;
  154. ["缺一色",2,], ///// 2 起完牌后,玩家手上筒、索、万任缺一门;
  155. ["六六顺",2,], ///// 3 起完牌后,玩家手上已有2个刻子(刻子:三个一样的牌);
  156. ["中途四喜",2,], ///// 4 玩家在牌局过程中,手中有四张相同的牌;
  157. ["中途六六顺",2,], ///// 5 起完牌后,玩家手上已有2个刻子(刻子:三个一样的牌);
  158. // ["节节高",2,], ///// 4 起完牌后,起完牌后,玩家手上有3连对且同花色;(例如2个3万,2个4万,2个5万);
  159. // ["三同",2,], ///// 5 起完牌后,玩家手上有3对点数相同的牌;(例如2个3万,2个3筒,2个3条)
  160. // ["单将一枝花",2,], ///// 6 起完牌后,玩家手上只有一张将牌(2、5、8),且这只将牌为“5”;
  161. // ["单五一枝花",2,], ///// 7 起完牌后,玩家手上只有一张将牌(2、5、8),且这只将牌为“5”;
  162. ]
  163. this.everyXiaoHuList = [
  164. [],[],[],[]
  165. ];//每个玩家的起手胡牌型用于算分
  166. /////TL++每个人满足的的大胡胡牌类型
  167. this.everyDAHType = [
  168. [],[],[],[]
  169. ]
  170. this.dahuTypeTL = [
  171. /////分别表示大胡牌型和台数
  172. // ["天胡",6,], ///// 0 单指庄家,庄家起牌后,即已经胡牌。(需要2、5、8做将)
  173. // ["地胡",6,], ///// 1 指闲家,当庄家打出第一张牌时,给闲家点炮。(需要2、5、8做将);
  174. ["七小对",7,], ///// 0 胡牌时,手上任意七对将牌(无需2、5、8做将);
  175. ["豪华七小对",7,],///// 1 手上任意七对牌,且其中有4张一样的牌(不能杠,算作2对);
  176. ["双豪华七小对",7,],///// 2 手上任意七对牌,且其中有2种4张一样的牌(不能杠,算作2对);
  177. ["三豪华七小对",7,],///// 13手上任意七对牌,且其中有3种4张一样的牌(不能杠,算作2对);
  178. ["将将胡",7,], ///// 4 玩家手上每一张牌都为2、5、8;
  179. ["全求人",7,], ///// 5 玩家通过吃、碰、杠而使得最后手中只剩下一颗牌,当摸或其他玩家打出这张牌时,即可胡牌;
  180. ["门清",7,], ///// 6 玩家没有吃、碰、杠等操作,胡牌时手上有14张牌,自己摸到的算门清别人打的不算门清;
  181. ["清一色",7,], ///// 7 玩家手中的牌全部由同一种花色(万、筒、条)组成;
  182. ["碰碰胡",7,], ///// 8 碰碰胡:玩家所有的牌均为刻子或将牌,乱将(无需2、5、8做将),可碰,可杠,可自摸;
  183. ["杠开(杠炮)",7,], ///// 9 自己杠上开花(需要2、5、8做将)
  184. ["抢杠胡",7,], ///// 10 (需要2、5、8做将);
  185. ["海底胡",7,], ///// 11 最后一张牌为海底牌。玩家选择要海底牌且通过这张海底牌胡牌,则为海底捞月,(是否需要2、5、8将根据当前牌型决定)
  186. ["天胡",7,], ///// 12 单指庄家,庄家起牌后,就有4个红中
  187. // ["杠上炮",7,], ///// 10 单指庄家,庄家起牌后,即已经胡牌。(需要2、5、8做将)
  188. // ["海底炮",7,], ///// 11 单指庄家,庄家起牌后,即已经胡牌。(需要2、5、8做将)
  189. ]
  190. // console.warn("ppppppppppp 长度 "+cards.length+" cards "+cards);
  191. };
  192. Logic.setHCfileNameList =[/////全部设置牌型的文件名
  193. "setHandCard_tianhu",
  194. ]
  195. // 导出常量
  196. Logic.CARDS = CARDS;
  197. Logic.STYLE = STYLE;
  198. Logic.CHAIR_COUNT = CHAIR_COUNT;
  199. Logic.CARDS_COUNT = CARDS_COUNT;
  200. // 导出类
  201. module.exports = Logic;
  202. // 原型对象
  203. var proto = Logic.prototype;
  204. /////TL++为了得到百搭牌数组用于判断是否需要补花和手牌中百搭牌个数
  205. proto.setBDList = function () {
  206. this.baiDaList = [this.baiDaCard,this.baiDaCard,this.baiDaCard]/////TL++,拿到百搭牌
  207. };
  208. ///////TL++在table类中出牌函数中调用,为了判断天胡和地胡
  209. proto.chuPaiTL = function () {
  210. // console.warn("111c天胡判断不正确",this.chuPaiCountTL);
  211. this.chuPaiCountTL += 1//////这个其实并不是真实的出牌个数,因为这个方法的调用在判断吃碰杠胡之前调用的
  212. }
  213. ///////TL++在table类中出牌函数中调用,为了判断天胡和地胡
  214. proto.moPaiTL = function () {
  215. // console.warn("111c天胡判断不正确",this.chuPaiCountTL);
  216. this.moPaiCountTL += 1//////TL++,记录出牌的个数,为了判断天胡和地胡 += 1
  217. }
  218. ///////TL++重置默认数据,在每局游戏开始的洗牌函数中调用
  219. proto.resetDataOnGameStart = function () {
  220. for (let i = 0; i < this.everyQSHType.length; ++i) {
  221. this.everyQSHType[i] = []
  222. }
  223. for (let i = 0; i < this.everyQSHCZGList.length; ++i) {
  224. this.everyQSHCZGList[i] = []
  225. }
  226. for (let i = 0; i < this.everyQSHCZGList2.length; ++i) {
  227. this.everyQSHCZGList2[i] = []
  228. }
  229. for (let i = 0; i < this.everyXiaoHuList.length; ++i) {
  230. this.everyXiaoHuList[i] = []
  231. }
  232. for (let i = 0; i < this.everyDAHType.length; ++i) {
  233. this.everyDAHType[i] = []
  234. }
  235. this.chuPaiCountTL = 0//////TL++出牌个数
  236. this.moPaiCountTL = 0//////TL++,记录摸牌的个数,为了判断天胡和地胡
  237. this.lastMoPaiChairID = 0//////TL++,最后一个摸牌玩家的id
  238. this.addThisIsHu = 0//////TL++,胡牌判断时加上这张能不能胡
  239. this.isSeleCatcedCard = false//////判断能否胡牌的那张牌是自己抓的还是别人打出来的
  240. this.currChairIDTL = 0/////当前判断胡的chairID,用于得到当前玩家的花牌情况
  241. this.isGGMG = [false,false,false,false];;//////TL++,是否刚刚直杠(明杠)用于判断是否是直杠杠开
  242. this.isGGAG = [false,false,false,false];//////TL++,是否刚暗杠用于判断是否暗杠杠开
  243. this.isGGFXG = [false,false,false,false];//////TL++,是否刚刚风险杠用于判断是否风险杠杠开
  244. this.isLaGang = false;//////TL++,是否刚刚被拉杠用于判断是否被拉杠胡
  245. this.isGuoHuList = [[false,-1],[false,-1],[false,-1],[false,-1],]/////TL++,各个玩家在本轮是否点击了过胡和点击过牌时的台数
  246. this.isZHYZ = false;/////是不是最后1张
  247. }
  248. // 重新洗牌
  249. proto.shuffle = function () {
  250. this.castCount = 0;
  251. this.disCount = 0;
  252. this.cardsPool = _.clone(this.cardsyl);
  253. this.lastCount = this.cardsPool.length;
  254. this.cardsPool = _.shuffle(this.cardsPool);////随机打乱一个数组
  255. this.cardsPool = _.shuffle(this.cardsPool);////洗第二次牌
  256. // this.cardsPool = _.shuffle(this.cardsPool);////洗第三次牌
  257. };
  258. // 填充数组
  259. proto.fillDeep = function (array, o, isMore) {
  260. for (let i = 0; i < array.length; ++i) {
  261. if (!isMore) {
  262. array[i] = _.clone(o);
  263. } else {
  264. array[i] = _.cloneDeep(o);/////深度拷贝,就是重新分配内存空间,浅拷贝则是两个变量共用一个内存对象
  265. }
  266. }
  267. return array;
  268. };
  269. //////TL++ 深复制一个object类型的数据
  270. proto.deepCloneTL = function (obj){
  271. let objClone = Array.isArray(obj)?[]:{};
  272. if(obj && typeof obj==="object"){
  273. for(let key in obj){
  274. if(obj.hasOwnProperty(key)){
  275. //判断ojb子元素是否为对象,如果是,递归复制
  276. if(obj[key]&& typeof obj[key] ==="object"){
  277. objClone[key] = this.deepCloneTL(obj[key]);
  278. }else{
  279. //如果不是,简单复制
  280. objClone[key] = obj[key];
  281. }
  282. }
  283. }
  284. }
  285. return objClone;
  286. };
  287. // 获取类型
  288. proto.getType = function (card) {
  289. return Math.floor(card / 10);
  290. };
  291. // 获取牌值
  292. proto.getValue = function (card) {
  293. return card % 10;
  294. };
  295. // 手牌排序
  296. proto.sort = function (handCards) {
  297. return _.sortBy(handCards);///降序排序
  298. };
  299. // 删除手牌 /////TL++参数isBuHua表示是否因为补花而造成的删除牌
  300. proto.remove = function (handCards, cards) {
  301. if (typeof (cards) == 'number') {
  302. if (cards == handCards[handCards.length - 1]) {
  303. return (handCards.pop(), true);
  304. } else {
  305. let pos = handCards.indexOf(cards);
  306. if (pos == -1) return false;
  307. return (handCards.splice(pos, 1), true);
  308. }
  309. }
  310. var length = cards.length;
  311. if (length > 1 && cards[0] == cards[length - 1]) {
  312. if (cards[0] == handCards[handCards.length - 1]) {
  313. handCards.pop();
  314. length -= 1;
  315. }
  316. let pos = handCards.indexOf(cards[0]);
  317. if (pos == -1) return false;
  318. handCards.splice(pos, length);
  319. } else {
  320. for (let i = 0; i < length; ++i) {
  321. let pos = handCards.indexOf(cards[i]);
  322. if (pos == -1) return false;
  323. handCards.splice(pos, 1);
  324. }
  325. }
  326. return true;
  327. };
  328. // 调整手牌
  329. proto.adjust = function (handCards) {
  330. var length = handCards.length;
  331. if (length < 2) return false;
  332. if (handCards[length - 1] < handCards[length - 2]) {
  333. let moCard = handCards.pop();
  334. let pos = _.findIndex(handCards, (i) => (i >= moCard));
  335. if (pos == -1) handCards.push(moCard);
  336. else handCards.splice(pos, 0, moCard);
  337. }
  338. return true;
  339. };
  340. // 投骰子
  341. proto.dice = function () {
  342. return _.random(1, 6);
  343. };
  344. // 剩余牌数
  345. proto.leaveCount = function () {
  346. return this.lastCount;
  347. };
  348. //////TL++,人工设置测试牌型
  349. proto.setTestSendCardsTL = function () {
  350. this.setCardFileName = '';
  351. let fileName = "setHandCard_tianhu"
  352. if(!fileName) return;/////文件名字不存在
  353. // console.warn("设置手牌的文件名",fileName);
  354. this.setCardFileName = fileName
  355. delete require.cache[require.resolve('./setcard/' + fileName)];
  356. var SetHandCardTL = require('./setcard/' + fileName);
  357. if(!SetHandCardTL) return;
  358. //////TL++,设置手牌的文件
  359. this.setHandCardTL = new SetHandCardTL();
  360. ////console.error("洗牌之后的牌",this.cardsPool);
  361. let ccc = this.setHandCardTL.getSCFP(this.cardGroupIndex)
  362. if(ccc){//////已经设置的手牌发完了就随机发牌
  363. this.cardsPool = ccc/////设置手牌的地方 设置牌
  364. this.cardGroupIndex += 1; ////此句是否存在代表是否只发某一种牌型
  365. // SetHandCardTL.cardGroupIndex += 1; ////此句是否存在代表是否只发某一种牌型
  366. // if(SetHandCardTL.cardGroupIndex == 1) SetHandCardTL.cardGroupIndex = 0
  367. }
  368. else{
  369. this.setCardFilerIndex += 1;
  370. this.cardGroupIndex = 0;
  371. // SetHandCardTL.cardGroupIndex = 0;
  372. if(Logic.setCardFilerIndex < Logic.setHCfileNameList.length) this.setTestSendCardsTL()
  373. }
  374. }
  375. // 初始手牌
  376. proto.handCards = function (chBanker,_PJHF,_over,recordid,_ctime) {
  377. this.resetDataOnGameStart()//////TL++
  378. this.shuffle();
  379. // if(this.hzCount == 8) {
  380. // this.cardsPool = [21,51,33,33,15,26,24,29,26,35,14,29,17,11,19,14,13,38,29,35,23,51,17,51,27,19,33,28,22,21,17,51,21,13,38,34,39,39,38,34,26,14,36,33,37,39,19,27,17,37,12,24,28,31,32,22,11,23,12,15,25,29,34,36,16,36,18,12,21,11,32,13,11,22,19,38,24,15,35,32,16,27,39,37,31,18,51,28,16,51,25,27,32,16,51,14,31,18,51,35,15,26,23,28,22,34,12,36,31,25,23,37,13,25,18,24]
  381. // this.setTestSendCardsTL()///////设置手牌的地方,设置发牌 不需要设置的时候注释掉这个方法就可以了
  382. // this.lastCount = this.cardsPool.length;//////设置剩余牌数设置剩余牌数,测试完这句要删掉
  383. // }
  384. let dqjs = _over + 1;
  385. _PJHF.writexpJson(this.deepCloneTL(this.cardsPool),dqjs,recordid,_ctime);
  386. //// 下面这个是随机发牌但是起手发lzgs张癞子的逻辑
  387. // let lzgs = 2//癞子个数
  388. // let djg = 0;
  389. // for (let i = 0; i < this.cardsPool.length; i++) {
  390. // if(this.cardsPool[i] == 51){
  391. // let xx = this.cardsPool[djg]
  392. // this.cardsPool[djg] = 51;
  393. // this.cardsPool[i] = xx;
  394. // djg++
  395. // if(djg >= lzgs){
  396. // break
  397. // }
  398. // }
  399. // }
  400. /////TL++设置百搭牌数组
  401. this.setBDList()
  402. var result = [];
  403. var castCount = 0;
  404. for (let i = 0; i < this.playerAllCount; ++i) {
  405. let cardCount = CARDS_COUNT;
  406. if (i == chBanker) cardCount += 1;
  407. let cards = this.cardsPool.slice(castCount, castCount + cardCount);
  408. castCount += cardCount;
  409. result.push({ cards: this.sort(cards) });
  410. }
  411. this.castCount += castCount
  412. this.lastCount -= castCount;
  413. // this.lastCount -= this.disCountTL;////因为翻出来的百搭牌不能被摸走
  414. // console.error("发的手牌",result);
  415. return result;
  416. };
  417. // 是否无牌
  418. proto.isNoCards = function () {
  419. return this.lastCount <= 0;
  420. };
  421. // 摸牌函数
  422. proto.moCard = function (isgang) {
  423. // console.error("摸排摸排--------isgang ",isgang,this.disCountTL,this.lastCount);
  424. var card = 0;
  425. if(isgang){
  426. let card1 = 0;
  427. if (this.lastCount > 1) {
  428. card1 = this.cardsPool[this.castCount++];
  429. this.lastCount -= 1;
  430. }
  431. let card2 = 0;
  432. if (this.lastCount > 0) {
  433. card2 = this.cardsPool[this.castCount++];
  434. this.lastCount -= 1;
  435. }
  436. return { card1: card1,card2: card2 };
  437. }
  438. else{
  439. if (this.lastCount > 0) {
  440. card = this.cardsPool[this.castCount++];
  441. this.lastCount -= 1;
  442. }
  443. }
  444. return { card: card };
  445. };
  446. // 是否将牌
  447. proto.isJang = function (lcard, rcard) {
  448. return lcard == rcard;
  449. };
  450. ////判断吃碰补之后是否只剩下百搭牌了,因为如果吃碰补之后只剩下百搭牌,而百搭牌又不允许打出会造成玩家无牌可出的局面
  451. proto.isCanCPB = function (handCards,opeate,type) {
  452. // console.warn("判断吃碰补之后是否只剩下百搭牌了 length "+handCards.length +" handCards "+JSON.stringify(handCards)+" opeate "+opeate+" type "+type);
  453. let length = handCards.length;
  454. let baiDaCount22 = this.getBDCount(handCards)
  455. let needCost = 0;//进行操作需要消耗的张数
  456. if(opeate == STYLE.CHI || opeate == STYLE.PENG) needCost = 2;
  457. else if(opeate == STYLE.BU || opeate == STYLE.GANG){
  458. //补牌,1-普通补, 2-暗补, 3-自摸补
  459. //1-普通杠, 2-暗杠, 3-自摸明杠
  460. if(type == 1) needCost = 3;
  461. else if(type == 2) needCost = 4;
  462. else if(type == 3) needCost = 1;
  463. }
  464. // console.warn("判断吃碰补之后是否只剩下百搭牌了 length "+length +" baiDaCount22 "+baiDaCount22+" needCost "+needCost);
  465. return (length - needCost - baiDaCount22 > 0);
  466. }
  467. // 可否碰牌
  468. proto.isPeng = function (handCards, card) {
  469. if(card == 51) return false;
  470. for (let i = 0; i < handCards.length - 1; ++i) {
  471. if (handCards[i] == card && handCards[i + 1] == card) {
  472. return true;
  473. }
  474. }
  475. return false;
  476. };
  477. // 碰牌 TL++参数chirID为了判断圈风和位风
  478. proto.peng = function (chirID,handCards, card) {
  479. if (this.isPeng(handCards, card)) {
  480. return { style: STYLE.PENG, cards: [card, card, card], disc: [card] };
  481. }
  482. };
  483. // 吃牌,1-@**左吃, 2-*@*中吃, 3-@**右吃
  484. proto.chi = function (handCards, card, type) {
  485. var chis = this.chiAnalyze(handCards, card, type);
  486. if (chis[0]) {
  487. let res = { style: STYLE.CHI, type: type, disc: [card] };
  488. if (type == 1) {
  489. res.cards = [card, card + 1, card + 2];
  490. if (this.getValue(card) < 7) {
  491. res.disc.push(card + 3);
  492. }
  493. } else if (type == 2) {
  494. res.cards = [card - 1, card, card + 1];
  495. } else {
  496. res.cards = [card - 2, card - 1, card];
  497. if (this.getValue(card) > 3) {
  498. res.disc.push(card - 3);
  499. }
  500. }
  501. return res;
  502. }
  503. };
  504. // 杠牌,1-普通杠, 2-暗杠, 3-自摸明杠 TL++参数chirID为了判断圈风和位风
  505. proto.gang = function (chirID,handCards, card, type) {
  506. // 结果
  507. var res = null;
  508. // 明杠
  509. if (type == 1) {
  510. let gang = this.gangAnalyze(handCards, card);
  511. if (gang) {
  512. res = { style: STYLE.GANG, cards: [card, card, card] };
  513. }
  514. }
  515. // 暗杠
  516. else if (type == 2) {
  517. let anGang = this.anGangAnalyze(handCards, card);
  518. if (anGang[0]) {
  519. res = { style: STYLE.ANGANG, cards: [card, card, card] };
  520. }
  521. }
  522. return res;
  523. };
  524. // 自摸明杠,1-普通杠, 2-暗杠, 3-自摸明杠 TL++参数chirID为了判断圈风和位风
  525. proto.zmGang = function (chirID,handCards, huCards, card) {
  526. var zmGang = this.zmGangAnalyze(handCards, huCards, card);
  527. if (zmGang[0]) {
  528. return { style: STYLE.ZMGANG, cards: [card, card, card] };
  529. }
  530. };
  531. // 补牌,1-普通补, 2-暗补, 3-自摸明补 TL++参数chirID为了判断圈风和位风
  532. proto.bu = function (chirID,handCards, card, type) {
  533. // 结果
  534. var res = null;
  535. // 明补
  536. if (type == 1) {
  537. let bu = this.buAnalyze(handCards, card);
  538. if (bu) {
  539. res = { style: STYLE.BU, cards: [card, card, card] };
  540. }
  541. }
  542. // 暗补
  543. else if (type == 2) {
  544. let anBu = this.anBuAnalyze(handCards, card);
  545. if (anBu[0]) {
  546. res = { style: STYLE.ANBU, cards: [card, card, card] };
  547. }
  548. }
  549. return res;
  550. };
  551. // 自摸明补,1-普通补, 2-暗补, 3-自摸明补 TL++参数chirID为了判断圈风和位风
  552. proto.zmBu = function (chirID,handCards, huCards, card) {
  553. var zmBu = this.zmBuAnalyze(handCards, huCards, card);
  554. if (zmBu[0]) {
  555. return { style: STYLE.ZMBU, cards: [card, card, card] };
  556. }
  557. };
  558. // 吃牌分析,1-@**左吃, 2-*@*中吃, 3-@**右吃, type可以不传
  559. proto.chiAnalyze = function (handCards, card, type) {
  560. // 结果集合
  561. var result = [];
  562. if(card == 51) return result;
  563. // 排除风字
  564. if (handCards.length < 2 || card > 40) return result;
  565. // 查找句子
  566. var length = handCards.length;
  567. for (let i = 0; i < length; ++i) {
  568. // 牌面值
  569. let value = this.getValue(card);
  570. // @**左吃,吃类型(可以不指定)
  571. if (!type || type == 1) {
  572. if (value < 8 && i < length - 1) {
  573. if (handCards[i] == card + 1 && handCards[i + 1] == card + 2) {
  574. result.push({ type: 1, card: card });
  575. }
  576. }
  577. }
  578. // *@*中吃,吃类型(可以不指定)
  579. if (!type || type == 2) {
  580. if (value > 1 && value < 9 && i < length - 1) {
  581. if (handCards[i] == card - 1 && handCards[i + 1] != card - 1) {
  582. for (let j = i + 1; j < i + 5 && j < length; ++j) {
  583. if (handCards[j] == card + 1) {
  584. result.push({ type: 2, card: card });
  585. break;
  586. }
  587. }
  588. }
  589. }
  590. }
  591. // **@右吃,吃类型(可以不指定)
  592. if (!type || type == 3) {
  593. if (value > 2 && i < length - 1) {
  594. if (handCards[i] == card - 2 && handCards[i + 1] == card - 1) {
  595. result.push({ type: 3, card: card });
  596. }
  597. }
  598. }
  599. }
  600. return result;
  601. };
  602. // 普通杠分析,1-普通杠, 2-暗杠, 3-自摸明杠
  603. proto.gangAnalyze = function (handCards, card) {
  604. // 结果对象
  605. var result = null;
  606. if(card == 51) return result;//红中不能碰杠
  607. var length = handCards.length;
  608. if (length < 3) return result;
  609. // 查找同牌
  610. for (let i = 0; i < length - 2; ++i) {
  611. if (handCards[i] == card && handCards[i + 1] == card && handCards[i + 2] == card) {
  612. result = { type: 1, card: card };
  613. break;
  614. }
  615. }
  616. return result;
  617. };
  618. // 暗杠分析,1-普通杠, 2-暗杠, 3-自摸明杠, card可以不传
  619. proto.anGangAnalyze = function (handCards, card) {
  620. // 结果对象
  621. var result = [];
  622. var length = handCards.length;
  623. if (length < 4) return result;
  624. // 查找同牌
  625. var moCard = handCards[length - 1];
  626. for (let i = 0; i < length - 3; ++i) {
  627. // 指定杠牌,可以不指定
  628. if (card && handCards[i] != card) continue;
  629. // 判定是否刻子
  630. if (handCards[i] == handCards[i + 1] && handCards[i] == handCards[i + 2]) {
  631. // 手上有杠牌
  632. if (handCards[i] == handCards[i + 3]) {
  633. if(handCards[i] != 51){
  634. result.push({ type: 2, card: handCards[i] });
  635. }
  636. }
  637. // 刚摸到杠牌
  638. else if (handCards[i] == moCard) {
  639. if(handCards[i] != 51){
  640. result.push({ type: 2, card: moCard });
  641. }
  642. }
  643. }
  644. }
  645. return result;
  646. };
  647. // 自摸杠分析,1-普通杠, 2-暗杠, 3-自摸明杠, card可以不传
  648. proto.zmGangAnalyze = function (handCards, huCards, card) {
  649. // 返回结果
  650. var result = [];
  651. if(card == 51) return result;//红中不能碰杠
  652. // 遍历句子
  653. for (let i = 0; i < huCards.length; ++i) {
  654. if (huCards[i].style != STYLE.PENG) {
  655. continue;
  656. }
  657. let _card = huCards[i].cards[0];
  658. if (card && _card != card) continue;
  659. let pos = handCards.indexOf(_card);
  660. if (pos != -1) {
  661. result.push({ type: 3, card: _card });
  662. if (card) break;
  663. }
  664. }
  665. return result;
  666. };
  667. // 普通补分析,1-普通补, 2-暗补, 3-自摸明补
  668. proto.buAnalyze = function (handCards, card) {
  669. // 结果对象
  670. var result = null;
  671. if(card == 51) return result;//红中不能碰杠
  672. var length = handCards.length;
  673. if (length < 3) return result;
  674. // 查找同牌
  675. for (let i = 0; i < length - 2; ++i) {
  676. if (handCards[i] == card && handCards[i + 1] == card && handCards[i + 2] == card) {
  677. result = { type: 1, card: card };
  678. break;
  679. }
  680. }
  681. return result;
  682. };
  683. // 暗补分析,1-普通补, 2-暗补, 3-自摸明补, card可以不传
  684. proto.anBuAnalyze = function (handCards, card) {
  685. // 结果对象
  686. var result = [];
  687. if(card == 51) return result;//红中不能碰杠
  688. var length = handCards.length;
  689. if (length < 4) return result;
  690. // 查找同牌
  691. var moCard = handCards[length - 1];
  692. for (let i = 0; i < length - 3; ++i) {
  693. // 指定补牌,可以不指定
  694. if (card && handCards[i] != card) continue;
  695. // 判定是否刻子
  696. if (handCards[i] == handCards[i + 1] && handCards[i] == handCards[i + 2]) {
  697. // 手上有补牌
  698. if (handCards[i] == handCards[i + 3]) {
  699. if(handCards[i] != 51){
  700. result.push({ type: 2, card: handCards[i] });
  701. }
  702. }
  703. // 刚摸到补牌
  704. else if (handCards[i] == moCard) {
  705. if(handCards[i] != 51){
  706. result.push({ type: 2, card: moCard });
  707. }
  708. }
  709. }
  710. }
  711. return result;
  712. };
  713. // 自摸补分析,1-普通补, 2-暗补, 3-自摸明补, card可以不传
  714. proto.zmBuAnalyze = function (handCards, huCards, card) {
  715. // 返回结果
  716. var result = [];
  717. if(card == 51) return result;//红中不能碰杠
  718. // 遍历句子
  719. for (let i = 0; i < huCards.length; ++i) {
  720. if (huCards[i].style != STYLE.PENG) {
  721. continue;
  722. }
  723. let _card = huCards[i].cards[0];
  724. if (card && _card != card) continue;
  725. let pos = handCards.indexOf(_card);
  726. if (pos != -1) {
  727. result.push({ type: 3, card: _card });
  728. if (card) break;
  729. }
  730. }
  731. return result;
  732. };
  733. // 分析牌型
  734. proto.parseBlock = function (card1, card2, card3) {
  735. // 刻子
  736. if (card1 && card1 == card2 && card1 == card3) {
  737. return { style: STYLE.KE, cards: [card1, card2, card3] };
  738. }
  739. // 顺子(排除风字)
  740. var cards = this.sort([card1, card2, card3]);
  741. if (cards[2] < 40) {
  742. if (cards[2] == cards[1] + 1 && cards[1] == cards[0] + 1) {
  743. return { style: STYLE.SUN, cards: cards };
  744. }
  745. }
  746. };
  747. // 得到等待数据更新类型,因为在杠后2张牌时就可能会出现2个玩家可碰或可杠或可补,
  748. // 而出现这种情况时规则是操作优先级高的玩家优先操作若相同操作时谁距离杠的玩家距离最近的玩家操作优先级高
  749. // 如ABCD4个玩家A杠后两张牌为101和102,此时B可碰101C可碰102D可胡时,若B点碰后C点碰最后D点过之后
  750. // 按照之前的逻辑就会出现B碰102(本应B碰101,由于等待碰等待数据里记录this.pengCard记录的是102),但是
  751. // 实际B不能碰102就会判碰102失败导致卡住的bug
  752. proto.getDDGXType = function (type,chairId, ddcwj,gangch, ccount,masks) {
  753. let res = 0;//0:不更新等待操作数据,1:需将之前等待操作玩家的mask置0,2:需将等待数据设置回本次修改之前的
  754. if(gangch == -1) return res;//不是杠后不会出现多个人等待同一个操作直接返回
  755. if(ddcwj == -1) return res;//此操作目前没有等待的玩家
  756. let czym = 0;//操作掩码
  757. if(type == 1) czym = 5;//判断碰
  758. else if(type == 2) czym = 9;//判断杠
  759. else if(type == 3) czym = 33;//判断补
  760. if(czym == 0) return res;//参数错误直接返回
  761. let zjjl = 0;
  762. if((gangch + 1) % ccount == chairId) zjjl = 1;
  763. else if((gangch + 2) % ccount == chairId) zjjl = 2;
  764. else if((gangch + 3) % ccount == chairId) zjjl = 3;
  765. let qtjl = 0;
  766. if((gangch + 1) % ccount == ddcwj) qtjl = 1;
  767. else if((gangch + 2) % ccount == ddcwj) qtjl = 2;
  768. else if((gangch + 3) % ccount == ddcwj) qtjl = 3;
  769. if(zjjl > qtjl){
  770. if(masks[ddcwj] == czym){
  771. res = 2;
  772. return res
  773. }
  774. else{
  775. return 0;//正常不应该走到这里来,能进这里都是有错误的
  776. }
  777. }
  778. res = 1;
  779. return res
  780. };
  781. // TL++,得到手牌中百搭牌的个数
  782. proto.getBDCount = function (cards) {
  783. ////TL++,整个for循环判断手牌中的百搭牌个数
  784. let baiDaCount = 0
  785. for (let i = 0; i < cards.length; ++i) {
  786. if(cards[i] == this.baiDaCard) baiDaCount = baiDaCount + 1
  787. }
  788. return baiDaCount
  789. }
  790. //// TL++,得到手牌中百搭牌的shuzu数组
  791. proto.getBDListZZ = function (cards) {
  792. this.sbyBDList = []//////重置某人手牌中的百搭牌数组
  793. ////TL++,整个for循环判断手牌中的百搭牌个数
  794. let baiDaCount = 0
  795. let baiDali = []
  796. for (let i = 0; i < cards.length; ++i) {
  797. if(cards[i] == this.baiDaCard){
  798. baiDali[baiDaCount] = cards[i]
  799. baiDaCount = baiDaCount + 1
  800. }
  801. }
  802. return baiDali
  803. }
  804. ////TL++,得到手牌中百搭牌的index数组
  805. proto.getBDIndexList = function (cards) {
  806. ////TL++,整个for循环判断手牌中的百搭牌个数
  807. let baiDali = []
  808. for (let i = 0; i < cards.length; ++i) {
  809. let cardTL = cards[i];
  810. if(this.baiDaList[0] && cardTL == this.baiDaList[0]) baiDali[baiDali.length] = i;
  811. else if(this.baiDaList[1] && cardTL == this.baiDaList[1]) baiDali[baiDali.length] = i;
  812. else if(this.baiDaList[2] && cardTL == this.baiDaList[2]) baiDali[baiDali.length] = i;
  813. }
  814. return baiDali
  815. }
  816. // TL++,得到手牌中百搭牌的index,用于删除手牌中的百搭牌
  817. proto.getBDIndex = function (cards) {
  818. ////TL++,整个for循环判断手牌中的百搭牌个数
  819. let baiDali = []
  820. for (let i = 0; i < cards.length; ++i) {
  821. let cardTL = cards[i];
  822. if(this.sbyBDList[0] && cardTL == this.sbyBDList[0]) baiDali[baiDali.length] = i;
  823. if(this.sbyBDList[1] && cardTL == this.sbyBDList[1]) baiDali[baiDali.length] = i;
  824. if(this.sbyBDList[2] && cardTL == this.sbyBDList[2]) baiDali[baiDali.length] = i;
  825. if(this.sbyBDList[3] && cardTL == this.sbyBDList[3]) baiDali[baiDali.length] = i;
  826. }
  827. return baiDali
  828. }
  829. // TL++,得到默认手牌中百搭牌当的数组 cards: 手牌去除百搭之后的牌
  830. proto.getBDMakeList = function (cards,isNeedAllZi) {
  831. if(cards.length == 0){
  832. ////手上就剩百搭牌的时候 需要把所有牌都当一遍
  833. let reslist = [
  834. 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒
  835. 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万
  836. 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条
  837. ]
  838. return reslist;
  839. }
  840. ////TL++,整个for循环按照手牌情况确定百搭牌当的范围
  841. let makeList = this.deepCloneTL(cards)
  842. for (let i = 0; i < cards.length; ++i) {
  843. let cardTL = cards[i];
  844. let type = this.getType(cardTL);
  845. let vale = this.getValue(cardTL);
  846. if(type < 4){
  847. if(vale == 1){
  848. let makeValue = cardTL + 1;
  849. if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue;
  850. let makeValue2 = cardTL + 2;
  851. if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2;
  852. }
  853. else if(vale == 9){
  854. let makeValue = cardTL - 1;
  855. if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue;
  856. let makeValue2 = cardTL - 2;
  857. if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2;
  858. }
  859. else if(vale == 2){
  860. let makeValue = cardTL - 1;
  861. if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue;
  862. let makeValue2 = cardTL + 1;
  863. if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2;
  864. let makeValue3 = cardTL + 2;
  865. if(makeList.indexOf(makeValue3) == -1) makeList[makeList.length] = makeValue3;
  866. }
  867. else if(vale == 8){
  868. let makeValue = cardTL - 1;
  869. if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue;
  870. let makeValue2 = cardTL - 2;
  871. if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2;
  872. let makeValue3 = cardTL + 1;
  873. if(makeList.indexOf(makeValue3) == -1) makeList[makeList.length] = makeValue3;
  874. }
  875. else if(vale > 2 && vale < 8){
  876. let makeValue = cardTL - 1;
  877. if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue;
  878. let makeValue2 = cardTL + 1;
  879. if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2;
  880. let makeValue3 = cardTL - 2;
  881. if(makeList.indexOf(makeValue3) == -1) makeList[makeList.length] = makeValue3;
  882. let makeValue4 = cardTL + 2;
  883. if(makeList.indexOf(makeValue4) == -1) makeList[makeList.length] = makeValue4;
  884. }
  885. }
  886. }
  887. // let makeList2 = makeList.concat([41,42,43,44,51,52,53])/////给当的数组拼接字牌
  888. // var xx = [1,1,2,3,4,1,2]
  889. // var xx22 = _.uniq(xx)
  890. // console.warn("数组去重",xx,xx22);///[ 1, 1, 2, 3, 4, 1, 2 ] [ 1, 2, 3, 4 ]
  891. // xx[1] = 6
  892. // console.warn("22数组去重",xx,xx22);////[ 1, 6, 2, 3, 4, 1, 2 ] [ 1, 2, 3, 4 ]
  893. let ewbList = [12,15,18,22,25,28,32,35,38];
  894. for (let i = 0; i < ewbList.length; ++i) {
  895. if(makeList.indexOf(ewbList[i]) == -1) makeList[makeList.length] = ewbList[i];
  896. }
  897. return _.uniq(makeList);
  898. }
  899. // 提取成句 card:手上的所有牌删除2张用来做将的牌之后剩下的牌 整理是否为刻子或者顺子
  900. proto._dumpFixed = function (cards, huCards) {
  901. // if(this.currChairIDTL == 0){
  902. // console.error("sscc提取成句没有百搭cards",cards);
  903. // console.error("sscc提取成ju没有百搭huCards",huCards);
  904. // }
  905. for (let i = 0; i < cards.length - 2; ++i) {
  906. let card = cards[i];
  907. if (card <= 0) continue;
  908. if (card == cards[i + 1] && card == cards[i + 2]) {
  909. huCards.push({ style: STYLE.KE, cards: [card, card, card] });
  910. cards[i] = 0; cards[i + 1] = 0; cards[i + 2] = 0;
  911. i += 2; continue;
  912. }
  913. if (card > 40 || this.getValue(card) > 7) continue;
  914. let second = -1, third = -1;
  915. for (let j = i + 1; j < cards.length; ++j) {
  916. if (cards[j] == card + 1) second = j;
  917. if (cards[j] == card + 2) third = j;
  918. if (cards[j] > card + 2) break;
  919. if (second != -1 && third != -1) break;
  920. }
  921. if (second != -1 && third != -1) {
  922. huCards.push({ style: STYLE.SUN, cards: [card, cards[second], cards[third]] });
  923. cards[i] = 0; cards[second] = 0; cards[third] = 0;
  924. }
  925. }
  926. };
  927. proto._dumpFixedc = function (cards,huCards,baidaCount) {
  928. let spkzgs = 4 - huCards.length;//手牌可组个数
  929. let spkzzh = [];//手牌可组组合(1为刻2为顺)
  930. if(spkzgs == 1) spkzzh = [[1],[2]];
  931. else if(spkzgs == 2) spkzzh = [[1,1],[1,2],[2,2],[2,1]];
  932. else if(spkzgs == 3) spkzzh = [[1,1,1],[1,2,1],[1,1,2],[1,2,2],[2,2,2],[2,1,2],[2,2,1],[2,1,1]];
  933. else if(spkzgs == 4){
  934. spkzzh = [[1,1,1,1],[1,2,1,1],[1,1,2,1],[1,1,1,2],
  935. [1,2,2,1],[1,1,2,2],[1,2,1,2],[1,2,2,2],
  936. [2,2,2,2],[2,1,2,2],[2,2,1,2],[2,2,2,1],
  937. [2,1,1,2],[2,2,1,1],[2,1,2,1],[2,1,1,1]
  938. ]
  939. }
  940. //找到目标牌
  941. var getMBCard = (cscards) => {
  942. for (let i = 0; i < cscards.length; ++i) {
  943. let card = cscards[i];
  944. if (card <= 0) continue;
  945. else return card;
  946. }
  947. return -100;
  948. };
  949. // let mbpailist = [12,15,15,15,16,17,18,25,26,27]
  950. // let islog = true;
  951. // if(mbpailist.length == cards.length){
  952. // for (let i = 0; i < cards.length; ++i) {
  953. // if(mbpailist[i] != cards[i]) islog = false;
  954. // }
  955. // }
  956. // else{
  957. // islog = false;
  958. // }
  959. // let mbpailist2 = [15,15,16,17,18,25,26,27,28,28,28]
  960. // if(islog) console.warn("_dumpFixedc 提取成句 baidaCount "+baidaCount+" cards "+cards+ " indexof "+mbpailist2.indexOf(15));
  961. // console.warn("所有的判断组合 长度 "+spkzzh.length+" spkzzh "+JSON.stringify(spkzzh) )
  962. let dqdpd = [0,0]//当前的判断
  963. for (let x = 0; x < spkzzh.length; ++x) {
  964. let copyCards = this.deepCloneTL(cards)
  965. let bdCount = baidaCount;
  966. let huCards22 = [];
  967. // console.warn("当前的判断组合 "+dqdpd+" spkzzh[x] "+spkzzh[x]+" x "+x);
  968. // if(islog && x == 5) console.warn("当前的判断组合 "+dqdpd+" spkzzh[x] "+spkzzh[x]+" x "+x);
  969. for (let y = 0; y < spkzzh[x].length; ++y) {
  970. let ckORcs = spkzzh[x][y]//成刻或成顺(1为刻2为顺)
  971. // if(islog && x == 5) console.warn("当前的判断 "+dqdpd+" ckORcs "+ckORcs);
  972. if(ckORcs == 1){
  973. let mbCard = getMBCard(copyCards);//目标card(mbCard这次应该成刻)
  974. if(mbCard > 0){
  975. let index1 = copyCards.indexOf(mbCard);
  976. if(index1 != -1) copyCards[index1] = 0;
  977. else console.error("这里不正常,都没有目标牌");
  978. let cj = [mbCard];//成句
  979. let index2 = copyCards.indexOf(mbCard);
  980. if(index2 != -1){
  981. cj[cj.length] = mbCard;
  982. copyCards[index2] = 0;
  983. }
  984. else {
  985. if(bdCount > 0){
  986. cj[cj.length] = 51;
  987. bdCount -= 1;
  988. }
  989. }
  990. let index3 = copyCards.indexOf(mbCard);
  991. if(index3 != -1){
  992. cj[cj.length] = mbCard;
  993. copyCards[index3] = 0;
  994. }
  995. else {
  996. if(bdCount > 0){
  997. cj[cj.length] = 51;
  998. bdCount -= 1;
  999. }
  1000. }
  1001. if(cj.length == 3){
  1002. huCards22.push({ style: STYLE.KE, cards: cj });
  1003. }
  1004. else{
  1005. //mbCard不能成刻,说明spkzzh[x]这种组合是不行的,剩下的就不用判断了
  1006. // console.warn("mbCard不能成刻,说明spkzzh[x]这种组合是不行的,剩下的就不用判断了");
  1007. break;
  1008. }
  1009. }
  1010. else{
  1011. //手牌全部都判断过了
  1012. if(bdCount >= 3){
  1013. huCards22.push({ style: STYLE.KE, cards: [51, 51, 51] });
  1014. bdCount -= 3;
  1015. }
  1016. //因为手里最多8张百搭,最多可以有6张百搭做成2个百搭刻,所以需要两次if
  1017. if(bdCount >= 3){
  1018. huCards22.push({ style: STYLE.KE, cards: [51, 51, 51] });
  1019. bdCount -= 3;
  1020. }
  1021. break;
  1022. }
  1023. }
  1024. else if(ckORcs == 2){
  1025. let mbCard = getMBCard(copyCards);//目标card(mbCard这次应该成刻)
  1026. // if(islog && x == 5) console.warn("mbCard "+mbCard+" copyCards "+copyCards);
  1027. if (mbCard < 40){
  1028. if(mbCard > 0){
  1029. let index1 = copyCards.indexOf(mbCard);
  1030. if(index1 != -1) copyCards[index1] = 0;
  1031. else console.error("这里不正常,都没有目标牌");
  1032. let cj = [mbCard];//成句
  1033. if(this.getValue(mbCard) <= 7){
  1034. let index2 = copyCards.indexOf(mbCard+1);
  1035. if(index2 != -1){
  1036. cj[cj.length] = copyCards[index2];
  1037. copyCards[index2] = 0;
  1038. }
  1039. else {
  1040. if(bdCount > 0){
  1041. cj[cj.length] = 51;
  1042. bdCount -= 1;
  1043. }
  1044. }
  1045. let index3 = copyCards.indexOf(mbCard+2);
  1046. if(index3 != -1){
  1047. cj[cj.length] = copyCards[index3];
  1048. copyCards[index3] = 0;
  1049. }
  1050. else {
  1051. if(bdCount > 0){
  1052. cj[cj.length] = 51;
  1053. bdCount -= 1;
  1054. }
  1055. }
  1056. }
  1057. else if(this.getValue(mbCard) == 8){
  1058. let index2 = copyCards.indexOf(mbCard+1);
  1059. if(index2 != -1){
  1060. cj[cj.length] = copyCards[index2];
  1061. copyCards[index2] = 0;
  1062. }
  1063. else {
  1064. if(bdCount > 0){
  1065. cj[cj.length] = 51;
  1066. bdCount -= 1;
  1067. }
  1068. }
  1069. if(bdCount > 0){
  1070. cj[cj.length] = 51;
  1071. bdCount -= 1;
  1072. }
  1073. }
  1074. else if(this.getValue(mbCard) == 9){
  1075. if(bdCount > 1){
  1076. cj[cj.length] = 51;
  1077. cj[cj.length] = 51;
  1078. bdCount -= 2;
  1079. }
  1080. }
  1081. if(cj.length == 3){
  1082. huCards22.push({ style: STYLE.SUN, cards: cj });
  1083. }
  1084. else{
  1085. //mbCard不能成顺,说明spkzzh[x]这种组合是不行的,剩下的就不用判断了
  1086. break;
  1087. }
  1088. }
  1089. else{
  1090. //手牌全部都判断过了
  1091. if(bdCount >= 3){
  1092. huCards22.push({ style: STYLE.SUN, cards: [51, 51, 51] });
  1093. bdCount -= 3;
  1094. }
  1095. //因为手里最多8张百搭,最多可以有6张百搭做成2个百搭刻,所以需要两次if
  1096. if(bdCount >= 3){
  1097. huCards22.push({ style: STYLE.SUN, cards: [51, 51, 51] });
  1098. bdCount -= 3;
  1099. }
  1100. break;
  1101. }
  1102. }
  1103. }
  1104. // if(y < spkzzh[x].length-1) dqdpd=[x,y+1];
  1105. // else dqdpd=[x+1,0];
  1106. }
  1107. // if(islog && x == 5) console.warn("提取成句 组合 "+" spkzzh[x] "+spkzzh[x]+" huCards22 "+JSON.stringify(huCards22) );
  1108. if(huCards22.length + huCards.length == 4){
  1109. //已经可以胡牌了,其他的组合就不需要判断了
  1110. for (var i = 0; i < huCards22.length; i++) {
  1111. huCards.push(huCards22[i]);
  1112. }
  1113. break;
  1114. }
  1115. }
  1116. };
  1117. //////TL++,判断一手张牌是否为百搭牌
  1118. proto.judgeACardISBD = function (card) {
  1119. return card == this.baiDaCard;
  1120. }
  1121. // 胡牌分析 chairID(TL++这个参数) 手牌 加上这张判断能不能胡 手上的吃碰杠牌 是否自己摸上来的
  1122. proto.huAnalyze = function (chairID,handCards, card, huCards, isTouch) {
  1123. // console.error("sscc777胡牌分析card",card);
  1124. // console.error("sscc777胡牌分析handCards",handCards);
  1125. // console.error("sscc777胡牌分析huCards",huCards);
  1126. // console.error("sscc777胡牌分析isTouch",isTouch);
  1127. this.addThisIsHu = card//////TL++,胡牌判断时加上这张能不能胡
  1128. this.isSeleCatcedCard = isTouch//////判断能否胡牌的那张牌是自己抓的还是别人打出来的
  1129. this.currChairIDTL = chairID/////当前判断胡的chairID,用于得到当前玩家的花牌情况
  1130. this.dangAfterBDListTL = [];/////7月18日+的
  1131. // console.warn("胡牌分析 isGuoHuList ",this.isGuoHuList," chairID ",chairID," isTouch ",isTouch);
  1132. let baiDaCount22 = 0
  1133. let bdIndexlist = []
  1134. if (!isTouch){
  1135. // baiDaCount22 = this.getBDCount(handCards)
  1136. // this.sbyBDList = this.getBDListZZ(handCards)
  1137. handCards = handCards.concat(card);/////不是自己抓的就把这张牌拼接进手牌中
  1138. // handCards = this.sort(handCards);
  1139. // bdIndexlist = this.getBDIndexList(handCards)
  1140. }
  1141. else{
  1142. // handCards = this.sort(handCards);
  1143. // baiDaCount22 = this.getBDCount(handCards)
  1144. // this.sbyBDList = this.getBDListZZ(handCards)
  1145. // bdIndexlist = this.getBDIndexList(handCards)
  1146. }
  1147. handCards = this.sort(handCards);
  1148. //由于杠后两张牌里面的红中是按照百搭算的,而且红中不能打出,所以把找红中放在判断isTouch外面了
  1149. baiDaCount22 = this.getBDCount(handCards)
  1150. this.sbyBDList = this.getBDListZZ(handCards)
  1151. bdIndexlist = this.getBDIndexList(handCards)
  1152. let huCards2 = this.deepCloneTL(huCards)
  1153. // console.warn("判断13不搭手上百搭牌个数出错了?????",baiDaCount22,this.sbyBDList,bdIndexlist)
  1154. var huRes = { card: card, jiang: 0, huCards: [] };
  1155. // 重设将牌
  1156. var resetHuRes = (jiang) => {
  1157. huRes.jiang = jiang;
  1158. huRes.huCards = [];
  1159. for (let huCard of huCards) huRes.huCards.push(huCard);
  1160. };
  1161. // 手牌不全
  1162. var length = handCards.length;
  1163. if (length % 3 != 2) return;
  1164. let result = null
  1165. if(this.isSevenDouble(handCards)){
  1166. // console.warn("是个7对子了");
  1167. resetHuRes(-1);
  1168. result = huRes;
  1169. }
  1170. if(this.isJiangJiangHu(handCards,huCards2)){
  1171. // console.warn("是个将将胡了");
  1172. resetHuRes(-1);
  1173. result = huRes;
  1174. }
  1175. if(this.isTianHu(handCards,huCards2)){
  1176. // console.warn("是个天胡了");
  1177. resetHuRes(-1);
  1178. result = huRes;
  1179. }
  1180. // let hucardTL = huCards//////TL++,保存碰杠牌的初始值,因为这个参数会在下面的代码中被修改掉
  1181. let tempAllTai = -1/////临时总台数
  1182. let tempres = {}///临时成句
  1183. if(result){
  1184. let copyCards = this.deepCloneTL(handCards);
  1185. this.getCardTypeTL(chairID,copyCards,huCards2,result,isTouch);
  1186. for (let x = 0; x < this.everyDAHType[chairID].length; ++x) {
  1187. if(this.everyDAHType[chairID][x] == 1) tempAllTai++;
  1188. }
  1189. }
  1190. // console.warn("下面是计算普通胡法 "+handCards);
  1191. if(baiDaCount22 == 0){/////没有百搭的时候
  1192. // 确定将牌
  1193. for (let i = 0; i < length - 1; ++i) {
  1194. if (!this.isJang(handCards[i], handCards[i + 1])) continue;
  1195. resetHuRes(handCards[i]);////设置将牌
  1196. let bcjp = handCards[i];
  1197. let cards = handCards.slice(0, i);////手牌数组的前i个元素
  1198. cards = cards.concat(handCards.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1199. this._dumpFixed(cards, huRes.huCards);
  1200. i += 1;/////TL++,为了减少运算
  1201. if(huRes.huCards.length >= 4){
  1202. let temresult = null;
  1203. if(this.isNeedEWBZJ(handCards,huCards2,huRes,isTouch)){
  1204. let jiangValue = this.getValue(bcjp);
  1205. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1206. temresult = this.deepCloneTL(huRes);
  1207. }
  1208. }
  1209. else{
  1210. // console.error("不需要258做将 bcjp "+bcjp+" "+handCards)
  1211. temresult = this.deepCloneTL(huRes);
  1212. // console.error("不需要258做将 temresult "+JSON.stringify(temresult))
  1213. }
  1214. if(temresult){
  1215. let copyCards = this.deepCloneTL(handCards);
  1216. this.getCardTypeTL(chairID,copyCards,huCards2,temresult,isTouch);
  1217. let pxgs = 0;//牌型个数
  1218. for (let x = 0; x < this.everyDAHType[chairID].length; ++x) {
  1219. if(this.everyDAHType[chairID][x] == 1) pxgs++;
  1220. }
  1221. if(pxgs > tempAllTai){
  1222. result = this.deepCloneTL(temresult);
  1223. tempAllTai = pxgs;
  1224. }
  1225. }
  1226. }
  1227. }
  1228. }
  1229. else{/////有百搭的时候
  1230. let card2 = []//////用于存放手牌中将所有百搭牌去掉之后的手牌
  1231. let ccchandCards = this.deepCloneTL(handCards)
  1232. for (let xx = 0; xx < this.sbyBDList.length; ++xx){
  1233. card2 = ccchandCards.slice(0,bdIndexlist[xx] - xx)////得到数组中的前bdIndexlist[xx] 个元素
  1234. card2 = card2.concat(ccchandCards.slice(bdIndexlist[xx]+1 - xx))////得到数组中的最后bdIndexlist[xx] +1 个元素
  1235. ccchandCards = card2
  1236. // console.error("有百搭删除掉百搭牌",card2);
  1237. }
  1238. // console.warn("删除百搭之后的手牌111 card2 ",card2);
  1239. // console.warn("删除百搭之后的手牌222 handCards ",handCards);
  1240. let bdzs = this.sbyBDList.length;/////百搭张数
  1241. let copyhandCards = this.deepCloneTL(card2)
  1242. var huResTL = [];
  1243. for (let huCard of huCards) huResTL.push(huCard);
  1244. // console.warn("去掉百搭之后的手牌 copyhandCards "+copyhandCards);
  1245. if(copyhandCards.length == 0) {
  1246. result = this.deepCloneTL(huRes);
  1247. let copyCards = this.deepCloneTL(handCards);
  1248. this.getCardTypeTL(chairID,copyCards,huCards2,result,isTouch);
  1249. }
  1250. else if(copyhandCards.length > 0) {
  1251. //下面的for循环是用手牌的两张牌做将牌看能不能胡牌
  1252. for (let i = 0; i < copyhandCards.length - 1; ++i) {
  1253. let cards22 = this.deepCloneTL(copyhandCards)
  1254. if (!this.isJang(cards22[i], cards22[i + 1])) continue;
  1255. let bcjp = handCards[i];
  1256. let huRes3 = { card: card, jiang: 0, huCards: [] };
  1257. // 重设将牌
  1258. huRes3.jiang = cards22[i];
  1259. huRes3.huCards = [];
  1260. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1261. let cards2 = cards22.slice(0, i);////手牌数组的前i个元素
  1262. cards2 = cards2.concat(cards22.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1263. this._dumpFixedc(cards2, huRes3.huCards,bdzs);
  1264. // console.warn("判胡 2张手牌做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1265. if (huRes3.huCards.length >= 4){
  1266. let temresult = null;
  1267. if(this.isNeedEWBZJ(handCards,huCards2,huRes3,isTouch)){
  1268. let jiangValue = this.getValue(bcjp);
  1269. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1270. temresult = this.deepCloneTL(huRes3);
  1271. }
  1272. }
  1273. else{
  1274. // console.error("不需要258做将 bcjp "+bcjp+" "+handCards)
  1275. temresult = this.deepCloneTL(huRes3);
  1276. // console.error("不需要258做将 temresult "+JSON.stringify(temresult))
  1277. }
  1278. if(temresult){
  1279. let copyCards = this.deepCloneTL(handCards);
  1280. this.getCardTypeTL(chairID,copyCards,huCards2,temresult,isTouch);
  1281. let pxgs = 0;//牌型个数
  1282. for (let x = 0; x < this.everyDAHType[chairID].length; ++x) {
  1283. if(this.everyDAHType[chairID][x] == 1) pxgs++;
  1284. }
  1285. // console.error("可以胡牌了111 pxgs "+pxgs+ " temresult "+JSON.stringify(temresult));
  1286. if(pxgs > tempAllTai){
  1287. result = this.deepCloneTL(temresult);
  1288. tempAllTai = pxgs;
  1289. }
  1290. }
  1291. }
  1292. i += 1;/////TL++,为了减少运算
  1293. }
  1294. //下面的for循环是用一张手牌和一张百搭牌做将牌看能不能胡牌
  1295. if(bdzs >= 1){
  1296. let bcjp = 0;///////本次的将牌
  1297. for (let i = 0; i < copyhandCards.length; ++i) {
  1298. let cards22 = this.deepCloneTL(copyhandCards);
  1299. if(cards22[i] == bcjp) continue;
  1300. let huRes3 = { card: card, jiang: 0, huCards: [] };
  1301. // 重设将牌
  1302. huRes3.jiang = cards22[i];
  1303. huRes3.huCards = [];
  1304. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1305. bcjp = cards22[i]; ///////本次的将牌
  1306. let cards2 = cards22.slice(0, i);////手牌数组的前i个元素
  1307. cards2 = cards2.concat(cards22.slice(i + 1));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1308. // console.warn("判胡 1张手牌做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1309. this._dumpFixedc(cards2, huRes3.huCards,bdzs-1);
  1310. if (huRes3.huCards.length >= 4){
  1311. // return huRes3;
  1312. let temresult = null;
  1313. if(this.isNeedEWBZJ(handCards,huCards2,huRes3,isTouch)){
  1314. // console.error("需要258做将 bcjp "+bcjp)
  1315. let jiangValue = this.getValue(bcjp);
  1316. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1317. temresult = this.deepCloneTL(huRes3);
  1318. }
  1319. }
  1320. else{
  1321. // console.error("不需要258做将 bcjp "+bcjp+" "+handCards)
  1322. temresult = this.deepCloneTL(huRes3);
  1323. // console.error("不需要258做将 temresult "+JSON.stringify(temresult))
  1324. }
  1325. if(temresult){
  1326. // console.error("可胡 temresult "+JSON.stringify(temresult))
  1327. let copyCards = this.deepCloneTL(handCards);
  1328. this.getCardTypeTL(chairID,copyCards,huCards2,temresult,isTouch);
  1329. let pxgs = 0;//牌型个数
  1330. for (let x = 0; x < this.everyDAHType[chairID].length; ++x) {
  1331. if(this.everyDAHType[chairID][x] == 1) pxgs++;
  1332. }
  1333. // console.error("可以胡牌了222 pxgs "+pxgs+ " temresult "+JSON.stringify(temresult));
  1334. if(pxgs > tempAllTai){
  1335. result = this.deepCloneTL(temresult);
  1336. tempAllTai = pxgs;
  1337. }
  1338. }
  1339. }
  1340. }
  1341. }
  1342. //下面的for循环是用2张百搭牌做将牌看能不能胡牌
  1343. if(bdzs >= 2){
  1344. let cards22 = this.deepCloneTL(copyhandCards);
  1345. let huRes3 = { card: card, jiang: 0, huCards: [] };
  1346. // 重设将牌
  1347. huRes3.jiang = 51;
  1348. huRes3.huCards = [];
  1349. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1350. // console.warn("判胡 2张红中做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1351. this._dumpFixedc(cards22, huRes3.huCards,bdzs-2);
  1352. if (huRes3.huCards.length >= 4){
  1353. let temresult = null;
  1354. temresult = this.deepCloneTL(huRes3);
  1355. let copyCards = this.deepCloneTL(handCards);
  1356. this.getCardTypeTL(chairID,copyCards,huCards2,temresult,isTouch);
  1357. let pxgs = 0;//牌型个数
  1358. for (let x = 0; x < this.everyDAHType[chairID].length; ++x) {
  1359. if(this.everyDAHType[chairID][x] == 1) pxgs++;
  1360. }
  1361. // console.error("可以胡牌了222 pxgs "+pxgs+ " temresult "+JSON.stringify(temresult));
  1362. if(pxgs > tempAllTai){
  1363. result = this.deepCloneTL(temresult);
  1364. tempAllTai = pxgs;
  1365. }
  1366. }
  1367. }
  1368. }
  1369. }
  1370. if(result){
  1371. let copyCards = this.deepCloneTL(handCards);
  1372. // console.error("胡牌分析 判断可胡 大胡牌型111 ",chairID,copyCards);
  1373. // console.error("胡牌分析 判断可胡 大胡牌型huCards2 ",JSON.stringify(huCards2));
  1374. // console.error("胡牌分析 判断可胡 大胡牌型huRes ",JSON.stringify(huRes));
  1375. // console.error("胡牌分析 判断可胡 大胡牌型result ",JSON.stringify(result));
  1376. this.getCardTypeTL(chairID,copyCards,huCards2,result,isTouch);
  1377. // console.error("胡牌分析 可胡 大胡牌型 "+chairID+" "+this.everyDAHType[chairID]);
  1378. if(!isTouch){
  1379. // console.warn("不是此人摸牌 ",chairID,isTouch);
  1380. let pxgs = 0;
  1381. for (let x = 0; x < this.everyDAHType[chairID].length; ++x) {
  1382. if(this.everyDAHType[chairID][x] == 1) pxgs++;
  1383. }
  1384. // console.error("胡牌分析 可胡 是否过胡 "+this.isGuoHuList[chairID][0]+" 过胡牌型个数 "+this.isGuoHuList[chairID][1]+" 当前牌型个数 "+pxgs);
  1385. if(this.isGuoHuList[chairID][0] && this.isGuoHuList[chairID][1] >= pxgs){
  1386. // console.warn("此人点过胡了 ",chairID," isTouch ",(!isTouch));
  1387. return false;
  1388. }
  1389. }
  1390. }
  1391. if(!isTouch && this.kexuanList[3] == 1){
  1392. // console.error("胡牌分析 不是自己摸牌 勾选了小胡只能自摸 "+chairID+" "+this.everyDAHType[chairID]);
  1393. if(this.everyDAHType[chairID].indexOf(1) == -1){
  1394. // console.error("胡牌分析 不是自己摸牌 勾选了小胡只能自摸 没有大胡牌型 "+chairID+" "+this.everyDAHType[chairID]);
  1395. return false;
  1396. }
  1397. }
  1398. return result;
  1399. };
  1400. // // TL++胡牌提示 chairID(TL++这个参数) 手牌 手上的吃碰杠牌 这个是胡牌提示里不统计台数
  1401. proto.hutip = function (chairID,_handCards, _huCards,_allhuCards,outCards) {
  1402. // return {
  1403. // renyi:0,//////是否可胡任意牌,0表示不满足1表示满足
  1404. // kehuData:[]/////对象数组,分别表示打哪张可胡哪几张数据
  1405. // };////服务端运算量太大放到前端去计算了
  1406. this.yscs = 0
  1407. // console.warn("hutip777胡牌提示handCards ",chairID,_handCards,_huCards,this.yscs);
  1408. // console.error("sscc777胡牌提示huCards",_huCards);
  1409. let hutipRes = [];
  1410. let handCards1 = _.clone(_handCards);
  1411. // if(chairID == 1) console.warn("sscc777胡牌提示handCards1 ",chairID,_handCards);
  1412. let huCards = _.clone(_huCards);
  1413. let allhuCards = _.clone(_allhuCards);////用统计胡牌提示的剩余牌
  1414. let baiDaCount22 = this.getBDCount(_handCards);
  1415. let dangPaiList = this.getBDMakeList(handCards1);
  1416. // let dangPaiList = this.getYGLDPList(handCards1);
  1417. // console.warn("hutip777胡牌提示 dangPaiList ",dangPaiList.length,JSON.stringify(dangPaiList));
  1418. // console.warn("hutip777胡牌提示 dangPaiList2 ",dangPaiList2.length,JSON.stringify(dangPaiList2));
  1419. if(baiDaCount22 < this.hzCount && this.hzCount > 0 && _handCards.indexOf(this.baiDaCard) == -1 && this.baiDaCard < 60){
  1420. dangPaiList[dangPaiList.length] = this.baiDaCard;
  1421. }
  1422. // if(chairID == 1) console.warn("hutip777胡牌提示 dangPaiList ",dangPaiList.length,dangPaiList);
  1423. let kdcdp = 0;////可打出的牌 就是打出这个牌之后可以胡
  1424. let dczhkhdp = [];////打出kdcdp之后可以胡的牌
  1425. let yjpdgdsp = 0;////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了
  1426. // let yjpdgdzh = [];////已经判断过的组合 把28换成26 和 把26换成28 的结果是一样的所以可以剔除以减少运算
  1427. for (var i = 0; i < handCards1.length; i++) {
  1428. if(this.judgeACardISBD(handCards1[i])) continue;
  1429. kdcdp = handCards1[i];////可打出的牌
  1430. dczhkhdp = [];
  1431. if(handCards1[i] == yjpdgdsp) continue;////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了
  1432. yjpdgdsp = handCards1[i];////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了
  1433. var huResTL = [];
  1434. for (let huCard of huCards) huResTL.push(huCard);
  1435. let copyhandCards = this.deepCloneTL(_handCards)
  1436. for (let x = 0; x < copyhandCards.length; ++x) {
  1437. if(this.judgeACardISBD(copyhandCards[x])){
  1438. copyhandCards[x] = 0;////剔除手里的百搭去判断抛搭
  1439. }
  1440. }
  1441. copyhandCards[i] = 0;///剔除手里的百搭和打出那张之后剩下的手牌去判断抛搭
  1442. let copyhandCardsqbd = _.compact(_.clone(copyhandCards));
  1443. copyhandCardsqbd = this.sort(copyhandCardsqbd);
  1444. // let ispd = this.hutipJudgePAODA(baiDaCount22,copyhandCardsqbd,dangPaiList,huResTL.length,kdcdp);////打出kdcdp之后是否抛搭
  1445. //上面是旧的算法,下面是新的算法
  1446. let ispd = false;
  1447. if(copyhandCardsqbd.length == 0){
  1448. ispd = true;//手上全是百搭肯定抛搭了
  1449. }
  1450. else{
  1451. if(baiDaCount22 > 0){
  1452. ispd = this.hutipJudgePAODA2(baiDaCount22-1,copyhandCardsqbd,huResTL,kdcdp,huCards,handCards1);////打出kdcdp之后是否抛搭
  1453. }
  1454. }
  1455. // console.warn("打出kdcdp之后是否抛搭 ",kdcdp,ispd,this.yscs);
  1456. if(ispd){
  1457. ////打出kdcdp之后可以抛搭了
  1458. let data = {
  1459. "canTing": kdcdp,////表示打出这张牌之后可以听牌
  1460. "youjin": 1,////打出这张牌之后是不是游金(抛搭)这个在象山麻将里面没有用
  1461. "tpxq": dczhkhdp
  1462. }
  1463. hutipRes[hutipRes.length] = data;
  1464. }
  1465. else{
  1466. ////打出kdcdp之后不能抛搭
  1467. for (var k = 0; k < dangPaiList.length; k++) {
  1468. this.yscs++;
  1469. let handCards = _.clone(handCards1);
  1470. // console.error("222sscc777胡牌提示huCards",i,handCards[i] , dangPaiList[k],handCards);
  1471. handCards[i] = dangPaiList[k];
  1472. handCards = this.sort(handCards);
  1473. // 手牌不全
  1474. var length = handCards.length;
  1475. if (length % 3 != 2) return;
  1476. // console.warn("pandau 0ceccewcde -------开始调用 hutip33");
  1477. let huRes22 = this.hutip33(chairID,handCards, dangPaiList[k], huCards,false);
  1478. if (huRes22) {
  1479. // console.warn("胡牌提示 打出 "+kdcdp+" 如果摸到 "+dangPaiList[k]+" 可以胡");
  1480. ////打出kdcdp如果摸到dangPaiList[k]可以胡
  1481. let syzs = this.getACardSYZS(dangPaiList[k],_handCards,allhuCards,outCards);
  1482. // console.warn("111????????????????????????????????",dangPaiList[k],syzs);
  1483. dczhkhdp[dczhkhdp.length] = [dangPaiList[k],-1,syzs];////[可胡的牌,剩余张数]
  1484. }
  1485. }
  1486. // console.warn("222????????????????????????????????",dczhkhdp.length);
  1487. if(dczhkhdp.length > 0){
  1488. ////至此表示打出handCards[i]之后可以听牌
  1489. let data = {
  1490. "canTing": kdcdp,////表示打出这张牌之后可以听牌
  1491. "youjin": 0,////打出这张牌之后是不是游金(抛搭)这个在象山麻将里面没有用
  1492. "tpxq": dczhkhdp
  1493. }
  1494. hutipRes[hutipRes.length] = data;
  1495. }
  1496. }
  1497. }
  1498. // console.warn("333????????????????????????????????",hutipRes);
  1499. // console.warn("222sscc777胡牌提示handCards ",chairID,_handCards,_huCards,this.yscs);
  1500. let kehuData3 = {
  1501. renyi:0,//////是否可胡任意牌,0表示不满足1表示满足
  1502. kehuData:hutipRes/////对象数组,分别表示打哪张可胡哪几张数据
  1503. };
  1504. return kehuData3;
  1505. // return hutipRes;
  1506. };
  1507. ////TL++得到一张牌的剩余张数 用于胡牌提示提示该张的剩余张数
  1508. proto.getACardSYZS = function (card,_handCards,allhuCards,outCards) {
  1509. // console.warn("000得到一张牌的剩余张数 手牌张数",card,_handCards);
  1510. // console.warn("000得到一张牌的剩余张数 手牌张数",JSON.stringify(allhuCards));
  1511. // console.warn("000得到一张牌的剩余张数 手牌张数",JSON.stringify(outCards));
  1512. ////下面这段是适合胡牌提示里用的剩余牌数统计
  1513. let yjcxdzs = 0;////该牌已经出现的张数
  1514. for (var i = 0; i < _handCards.length; i++) {
  1515. if(card == _handCards[i]) yjcxdzs++;////该牌已经出现在自己手牌里的张数
  1516. }
  1517. // console.warn("111得到一张牌的剩余张数 手牌张数",yjcxdzs,_handCards);
  1518. for (var i = 0; i < allhuCards.length; i++) {
  1519. if(allhuCards[i].length == 0) continue;////该玩家没有碰杠牌
  1520. // console.warn("222得到一张牌的剩余张数 碰杠杠牌",card,yjcxdzs,i,JSON.stringify(_.clone(allhuCards[i])));
  1521. for (var k = 0; k < allhuCards[i].length; k++) {
  1522. let pgp = allhuCards[i][k].cards;
  1523. if(!pgp) continue;
  1524. if(allhuCards[i][k].style >= 5 && allhuCards[i][k].style <= 10 ){
  1525. if(allhuCards[i][k].cards[0] == card){
  1526. yjcxdzs+=4;//明杠暗杠自摸杠明补暗补自摸补
  1527. }
  1528. }
  1529. else{
  1530. // console.warn("得到一张牌的剩余张数 "+pgp+" card "+card);
  1531. for (var j = 0; j < pgp.length; j++) {
  1532. if(card == pgp[j]) yjcxdzs++;////该牌已经出现在自己手牌里的张数
  1533. }
  1534. }
  1535. }
  1536. }
  1537. for (var i = 0; i < outCards.length; i++) {
  1538. if(outCards[i].length == 0) continue;////该玩家没有碰杠牌
  1539. // console.warn("2得到一张牌的剩余张数 打出去的牌",card,yjcxdzs,i,JSON.stringify(_.clone(outCards[i])));
  1540. for (var k = 0; k < outCards[i].length; k++) {
  1541. if(card == outCards[i][k]) yjcxdzs++;////该牌已经出现在所有打出去牌里的张数;
  1542. }
  1543. }
  1544. let zs = 4
  1545. if(card == 51) zs = this.hzCount;
  1546. // if(this.judgeACardISBD(card)) zs = 3;
  1547. let syzs = zs - yjcxdzs;////剩余张数 = 总张数 - 已经出现的张数
  1548. // console.warn("333得到一张牌的剩余张数",card,syzs);
  1549. return syzs;
  1550. };
  1551. // //////TL++,胡牌提示判断抛搭
  1552. proto.hutipJudgePAODA2 = function (_baidacount,_hd,_huCards,_addThisIsHu,_huCards2,_handCards1) {
  1553. // console.warn("胡牌提示判断抛搭 _baidacount "+_baidacount+" _hd.length "+_hd.length +" _hd "+_hd);
  1554. // console.warn("胡牌提示判断抛搭 _addThisIsHu "+_addThisIsHu+" _huCards "+JSON.stringify(_huCards) +" _huCards2 "+JSON.stringify(_huCards2)+" _handCards1 "+_handCards1);
  1555. let cards2 = this.deepCloneTL(_hd);
  1556. //是否七对抛搭
  1557. if(cards2.length+_baidacount+1 == CARDS_COUNT){
  1558. var dcount = 0;
  1559. var counts = {};
  1560. for (let i = 0; i < cards2.length; ++i) {
  1561. let card = cards2[i];
  1562. counts[card] = (counts[card] || 0) + 1;
  1563. if (counts[card] >= 2) {
  1564. dcount += 1;
  1565. counts[card] = 0;
  1566. }
  1567. }
  1568. // console.warn("七对抛搭了 ???? dcount "+dcount+" _baidacount "+_baidacount );
  1569. if(dcount + _baidacount >= 6) {
  1570. // console.warn("七对抛搭了 dcount "+dcount);
  1571. return true;
  1572. }
  1573. }
  1574. // console.warn("至此七对没有抛搭");
  1575. let huRes3 = { card: 0, jiang: 0, huCards: [] };
  1576. huRes3.huCards = [];
  1577. for (let huCard of _huCards) huRes3.huCards.push(huCard);
  1578. this._dumpFixedc(cards2, huRes3.huCards,_baidacount);
  1579. // console.warn("胡牌提示 判断判断抛搭 length "+huRes3.huCards.length+" huRes3.huCards "+ JSON.stringify(huRes3.huCards));
  1580. if (huRes3.huCards.length >= 4){
  1581. // console.warn("胡牌提示 判断判断抛搭 可以抛搭222 length "+huRes3.huCards.length+" huRes3.huCards "+ JSON.stringify(huRes3.huCards));
  1582. // console.warn("胡牌提示 判断判断抛搭 huRes3 "+ JSON.stringify(huRes3));
  1583. // return true;
  1584. let handCards = this.deepCloneTL(_handCards1);
  1585. let huCards2 = this.deepCloneTL(_huCards2);
  1586. if(this.isNeedEWBZJ(handCards,huCards2,huRes3,true)) {
  1587. // console.warn("胡牌提示===================抛搭 ")
  1588. for (let i = 0; i < huRes3.huCards.length; ++i) {
  1589. let hrcItem = huRes3.huCards[i].cards;
  1590. if(hrcItem[0] == hrcItem[1] && hrcItem.indexOf(51) != -1){
  1591. let jiangValue = this.getValue(hrcItem[0]);
  1592. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1593. //如果成句中存在比如35,35,51这种组合,可以让35做将,
  1594. //让腾出来的51和已经去掉的51再加上任何一张牌组成一个城成句,这样也能抛搭
  1595. return true;
  1596. }
  1597. }
  1598. }
  1599. return false;
  1600. }
  1601. else return true;
  1602. }
  1603. // console.warn("不能抛搭");
  1604. return false;
  1605. }
  1606. // 胡牌分析(胡牌提示里调用) chairID(TL++这个参数) 手牌 加上这张判断能不能胡 手上的吃碰杠牌 是否自己摸上来的
  1607. proto.hutip33 = function (chairID,handCards, card, huCards, isTouch) {
  1608. // console.error("sscc777胡牌分析card",card);
  1609. // console.error("sscc777胡牌提示分析handCards",handCards);
  1610. // console.error("sscc777胡牌分析huCards",huCards);
  1611. // console.error("sscc777胡牌分析isTouch",isTouch);
  1612. // let tempres = {}///本函数的返回值
  1613. // this.addThisIsHu = card//////TL++,胡牌判断时加上这张能不能胡
  1614. // this.isSeleCatcedCard = isTouch//////判断能否胡牌的那张牌是自己抓的还是别人打出来的
  1615. // this.currChairIDTL = chairID/////当前判断胡的chairID,用于得到当前玩家的花牌情况
  1616. // this.dangAfterBDListTL = [];/////7月18日+的
  1617. let baiDaCount22 = 0
  1618. let bdIndexlist = []
  1619. handCards = this.sort(handCards);
  1620. baiDaCount22 = this.getBDCount(handCards)
  1621. this.sbyBDList = this.getBDListZZ(handCards)
  1622. bdIndexlist = this.getBDIndexList(handCards)
  1623. // console.warn("判断13不搭手上百搭牌个数出错了?????",baiDaCount22,this.sbyBDList,bdIndexlist)
  1624. // 手牌不全
  1625. // var length = handCards.length;
  1626. // // console.warn("胡牌提示 length "+length+" baiDaCount22 "+baiDaCount22);
  1627. // if (length % 3 != 2) return;
  1628. let huCards2 = this.deepCloneTL(huCards)
  1629. if(this.isSevenDouble(handCards)){
  1630. // console.warn("胡牌提示 是个7对子了");
  1631. return true;
  1632. }
  1633. if(this.isJiangJiangHu(handCards,huCards2)){
  1634. // console.warn("胡牌提示 是个将将胡了");
  1635. return true;
  1636. }
  1637. // let hucardTL = huCards//////TL++,保存碰杠牌的初始值,因为这个参数会在下面的代码中被修改掉
  1638. // 确定将牌
  1639. var length = handCards.length;
  1640. // console.warn("胡牌提示 length "+length+" baiDaCount22 "+baiDaCount22);
  1641. if (length % 3 != 2) return;
  1642. if(baiDaCount22 == 0){/////没有百搭的时候
  1643. var huRes = { card: card, jiang: 0, huCards: [] };
  1644. // 重设将牌
  1645. var resetHuRes = (jiang) => {
  1646. huRes.jiang = jiang;
  1647. huRes.huCards = [];
  1648. for (let huCard of huCards) huRes.huCards.push(huCard);
  1649. };
  1650. for (let i = 0; i < handCards.length - 1; ++i) {
  1651. if (!this.isJang(handCards[i], handCards[i + 1])) continue;
  1652. resetHuRes(handCards[i]);////设置将牌
  1653. let bcjp = handCards[i]; ///////本次的将牌 7月18日+的
  1654. let cards = handCards.slice(0, i);////手牌数组的前i个元素
  1655. cards = cards.concat(handCards.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1656. this._dumpFixed(cards, huRes.huCards);
  1657. i += 1;/////TL++,为了减少运算
  1658. // let tempres22 = this.outHures(huRes,handCards,hucardTL);
  1659. if(huRes.huCards.length >= 4){
  1660. if(this.isNeedEWBZJ(handCards,huCards2,huRes,true)){
  1661. let jiangValue = this.getValue(bcjp);
  1662. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1663. return true;
  1664. }
  1665. }
  1666. else{
  1667. return true;
  1668. }
  1669. }
  1670. }
  1671. }
  1672. else{/////有百搭的时候
  1673. let card2 = []//////用于存放手牌中将所有百搭牌去掉之后的手牌
  1674. let ccchandCards = this.deepCloneTL(handCards)
  1675. for (let xx = 0; xx < this.sbyBDList.length; ++xx){
  1676. card2 = ccchandCards.slice(0,bdIndexlist[xx] - xx)////得到数组中的前bdIndexlist[xx] 个元素
  1677. card2 = card2.concat(ccchandCards.slice(bdIndexlist[xx]+1 - xx))////得到数组中的最后bdIndexlist[xx] +1 个元素
  1678. ccchandCards = card2
  1679. // console.error("有百搭删除掉百搭牌",card2);
  1680. }
  1681. let bdzs = this.sbyBDList.length;/////百搭张数
  1682. let copyhandCards = this.deepCloneTL(card2)
  1683. var huResTL = [];
  1684. for (let huCard of huCards) huResTL.push(huCard);
  1685. // console.warn("去掉百搭之后的手牌 copyhandCards "+copyhandCards);
  1686. if(copyhandCards.length == 0) {
  1687. result = this.deepCloneTL(huRes);
  1688. let copyCards = this.deepCloneTL(handCards);
  1689. this.getCardTypeTL(chairID,copyCards,huCards2,result,isTouch);
  1690. }
  1691. else if(copyhandCards.length > 0) {
  1692. //下面的for循环是用手牌的两张牌做将牌看能不能胡牌
  1693. for (let i = 0; i < copyhandCards.length - 1; ++i) {
  1694. let cards22 = this.deepCloneTL(copyhandCards)
  1695. if (!this.isJang(cards22[i], cards22[i + 1])) continue;
  1696. let bcjp = handCards[i];
  1697. let huRes3 = { card: card, jiang: 0, huCards: [] };
  1698. // 重设将牌
  1699. huRes3.jiang = cards22[i];
  1700. huRes3.huCards = [];
  1701. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1702. let cards2 = cards22.slice(0, i);////手牌数组的前i个元素
  1703. cards2 = cards2.concat(cards22.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1704. this._dumpFixedc(cards2, huRes3.huCards,bdzs);
  1705. // console.warn("判胡 2张手牌做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1706. if (huRes3.huCards.length >= 4){
  1707. if(this.isNeedEWBZJ(handCards,huCards2,huRes3,isTouch)){
  1708. let jiangValue = this.getValue(bcjp);
  1709. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1710. return true;
  1711. }
  1712. }
  1713. else{
  1714. return true;
  1715. }
  1716. }
  1717. i += 1;/////TL++,为了减少运算
  1718. }
  1719. //下面的for循环是用一张手牌和一张百搭牌做将牌看能不能胡牌
  1720. if(bdzs >= 1){
  1721. let bcjp = 0;///////本次的将牌
  1722. for (let i = 0; i < copyhandCards.length; ++i) {
  1723. let cards22 = this.deepCloneTL(copyhandCards);
  1724. if(cards22[i] == bcjp) continue;
  1725. let huRes3 = { card: card, jiang: 0, huCards: [] };
  1726. // 重设将牌
  1727. huRes3.jiang = cards22[i];
  1728. huRes3.huCards = [];
  1729. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1730. bcjp = cards22[i]; ///////本次的将牌
  1731. let cards2 = cards22.slice(0, i);////手牌数组的前i个元素
  1732. cards2 = cards2.concat(cards22.slice(i + 1));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1733. // console.warn("判胡 1张手牌做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1734. this._dumpFixedc(cards2, huRes3.huCards,bdzs-1);
  1735. if (huRes3.huCards.length >= 4){
  1736. if(this.isNeedEWBZJ(handCards,huCards2,huRes3,isTouch)){
  1737. let jiangValue = this.getValue(bcjp);
  1738. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1739. return true;
  1740. }
  1741. }
  1742. else{
  1743. return true;
  1744. }
  1745. }
  1746. }
  1747. }
  1748. //下面的for循环是用2张百搭牌做将牌看能不能胡牌
  1749. if(bdzs >= 2){
  1750. let cards22 = this.deepCloneTL(copyhandCards);
  1751. let huRes3 = { card: card, jiang: 0, huCards: [] };
  1752. // 重设将牌
  1753. huRes3.jiang = 51;
  1754. huRes3.huCards = [];
  1755. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1756. // console.warn("判胡 2张红中做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1757. this._dumpFixedc(cards22, huRes3.huCards,bdzs-2);
  1758. if (huRes3.huCards.length >= 4){
  1759. return true;
  1760. }
  1761. }
  1762. }
  1763. }
  1764. return false;
  1765. };
  1766. // TL++,得到和手牌有关联的牌的数组,用于判断是否听牌 cards: 13张手牌
  1767. proto.getYGLDPList = function (_cards) {
  1768. let cards = this.deepCloneTL(_cards)
  1769. cards = this.sort(cards);
  1770. let cannotList = [];
  1771. ////TL++,整个for循环按照手牌情况确定百搭牌当的范围
  1772. let makeList = this.deepCloneTL(cards)
  1773. for (let i = 0; i < cards.length; ++i) {
  1774. let cardTL = cards[i];
  1775. let type = this.getType(cardTL);
  1776. let vale = this.getValue(cardTL);
  1777. if(cardTL == cards[i+1] && cardTL == cards[i+2] && cardTL == cards[i+3]){
  1778. i += 3;
  1779. cannotList[cannotList.length] = cardTL;
  1780. }
  1781. if(type < 4){
  1782. if(vale == 1){
  1783. let makeValue = cardTL + 1;
  1784. if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue;
  1785. }
  1786. else if(vale == 9){
  1787. let makeValue = cardTL - 1;
  1788. if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue;
  1789. }
  1790. else{
  1791. let makeValue = cardTL - 1;
  1792. if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue;
  1793. let makeValue2 = cardTL + 1;
  1794. if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2;
  1795. }
  1796. }
  1797. }
  1798. // console.warn("22数组去重",xx,xx22);////[ 1, 6, 2, 3, 4, 1, 2 ] [ 1, 2, 3, 4 ]
  1799. //return _.uniq(makeList);
  1800. makeList = _.uniq(makeList);
  1801. let ewbList = [12,15,18,22,25,28,32,35,38];
  1802. for (let i = 0; i < ewbList.length; ++i) {
  1803. if(makeList.indexOf(ewbList[i]) == -1) makeList[makeList.length] = ewbList[i];
  1804. }
  1805. this.remove(makeList,cannotList);
  1806. return makeList;
  1807. }
  1808. //判断是否可以杠,14张手牌去掉可以暗杠的4张牌(或者13张牌去掉可以明杠的3张牌)之后可以听牌则可以杠否则不能杠
  1809. proto.isCanGang = function (cards,_huCards,gangtype,gangcard) {
  1810. // console.error("判断是否可以杠 cards "+cards,_huCards,gangtype,gangcard);
  1811. let huCards = [];
  1812. for (let huCard of _huCards) huCards.push(huCard);
  1813. let handCards = this.deepCloneTL(cards);
  1814. handCards = this.sort(handCards);
  1815. let needDelList = [];
  1816. //1-普通杠, 2-暗杠, 3-自摸明杠
  1817. if(gangtype == 1){
  1818. needDelList[needDelList.length] = [gangcard,gangcard,gangcard]
  1819. huCards.push({ style: STYLE.GANG, cards: [gangcard,gangcard,gangcard] });
  1820. }
  1821. else if(gangtype == 2){
  1822. if(gangcard != 0){
  1823. needDelList[needDelList.length] = [gangcard,gangcard,gangcard,gangcard];
  1824. huCards.push({ style: STYLE.ANGANG, cards: [gangcard,gangcard,gangcard] });
  1825. }
  1826. else{
  1827. for (let i = 0; i < handCards.length - 3; ++i) {
  1828. let card = handCards[i];
  1829. // 判定是否刻子
  1830. if (card == handCards[i + 1] && card == handCards[i + 2] && card == handCards[i + 3]) {
  1831. needDelList[needDelList.length] = [card,card,card,card];
  1832. huCards.push({ style: STYLE.ANGANG, cards: [card,card,card] });
  1833. i+=3
  1834. }
  1835. }
  1836. }
  1837. }
  1838. else if(gangtype == 3){
  1839. needDelList[needDelList.length] = [gangcard];
  1840. }
  1841. // console.error("判断是否可以杠 needDelList "+needDelList.length,needDelList);
  1842. for (let i = 0; i < needDelList.length; ++i) {
  1843. let handCards2 = this.deepCloneTL(handCards);
  1844. this.remove(handCards2,needDelList[i]);
  1845. // console.error("判断是否可以杠 handCards2 "+handCards2+" needDelList[i] "+needDelList[i]);
  1846. if(this.checkTing(handCards2,huCards)){
  1847. // console.error("判断是否可以杠 可以杠");
  1848. return true;
  1849. }
  1850. }
  1851. return false;
  1852. }
  1853. //检查是否可以听牌
  1854. proto.checkTing = function (_cards,huCards) {
  1855. // console.error("检查是否可以听牌 length "+_cards.length+" cards "+_cards);
  1856. // console.error("检查是否可以听牌111 length "+huCards.length+" huCards "+JSON.stringify(huCards) );
  1857. if (_cards.length % 3 != 1) return;
  1858. let handCards = this.deepCloneTL(_cards)
  1859. let dangPaiList = this.getBDMakeList(handCards);
  1860. // let dangPaiList = this.getYGLDPList(handCards);
  1861. let huCards2 = this.deepCloneTL(huCards)
  1862. for (let n = 0; n < dangPaiList.length; ++n) {
  1863. var huRes = { card: 0, jiang: 0, huCards: [] };
  1864. // 重设将牌
  1865. var resetHuRes = (jiang) => {
  1866. huRes.jiang = jiang;
  1867. huRes.huCards = [];
  1868. for (let huCard of huCards) huRes.huCards.push(huCard);
  1869. };
  1870. let cards22 = this.deepCloneTL(handCards)/////百搭牌当完之后的手牌数组
  1871. cards22[cards22.length] = dangPaiList[n];
  1872. cards22 = this.sort(cards22);
  1873. let baiDaCount22 = 0
  1874. let bdIndexlist = []
  1875. baiDaCount22 = this.getBDCount(cards22)
  1876. this.sbyBDList = this.getBDListZZ(cards22)
  1877. bdIndexlist = this.getBDIndexList(cards22)
  1878. if(this.isJiangJiangHu(handCards,huCards2)){
  1879. // console.error("是个将将胡了");
  1880. return true;
  1881. }
  1882. if(this.isSevenDouble(cards22)){
  1883. return true;
  1884. }
  1885. if(baiDaCount22 == 0){/////没有百搭的时候
  1886. // 确定将牌
  1887. for (let i = 0; i < cards22.length - 1; ++i) {
  1888. if (!this.isJang(cards22[i], cards22[i + 1])) continue;
  1889. resetHuRes(cards22[i]);////设置将牌
  1890. let bcjp = cards22[i]; ///////本次的将牌 7月18日+的
  1891. // this.judgePAODA(1,cards22[i],dangAfterBDList);/////判断抛搭 /////7月18日以前在这里
  1892. let cards = cards22.slice(0, i);////手牌数组的前i个元素
  1893. cards = cards.concat(cards22.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1894. this._dumpFixed(cards, huRes.huCards);
  1895. if(huRes.huCards.length >= 4){
  1896. // if(handCards.length == 1) return true;
  1897. if(this.isNeedEWBZJ(cards22,huCards2,huRes,true)){
  1898. let jiangValue = this.getValue(bcjp);
  1899. // return (jiangValue == 2 || jiangValue == 5 || jiangValue == 8);
  1900. if((jiangValue == 2 || jiangValue == 5 || jiangValue == 8)){
  1901. // console.error("检查是否可以听牌 可以听牌111");
  1902. return true;
  1903. }
  1904. }
  1905. else{
  1906. // console.error("检查是否可以听牌 可以听牌222");
  1907. return true;
  1908. }
  1909. }
  1910. i += 1;/////TL++,为了减少运算
  1911. }
  1912. }
  1913. else{/////有百搭的时候
  1914. let card2 = []//////用于存放手牌中将所有百搭牌去掉之后的手牌
  1915. let ccchandCards = this.deepCloneTL(cards22)
  1916. for (let xx = 0; xx < this.sbyBDList.length; ++xx){
  1917. card2 = ccchandCards.slice(0,bdIndexlist[xx] - xx)////得到数组中的前bdIndexlist[xx] 个元素
  1918. card2 = card2.concat(ccchandCards.slice(bdIndexlist[xx]+1 - xx))////得到数组中的最后bdIndexlist[xx] +1 个元素
  1919. ccchandCards = card2
  1920. }
  1921. let bdzs = this.sbyBDList.length;/////百搭张数
  1922. // console.error("有百搭删除掉百搭牌",bdzs,JSON.stringify(card2));
  1923. let copyhandCards = this.deepCloneTL(card2)
  1924. var huResTL = [];
  1925. for (let huCard of huCards) huResTL.push(huCard);
  1926. // console.warn("去掉百搭之后的手牌 copyhandCards "+copyhandCards);
  1927. if(copyhandCards.length == 0) {
  1928. result = this.deepCloneTL(huRes);
  1929. let copyCards = this.deepCloneTL(cards22);
  1930. this.getCardTypeTL(chairID,copyCards,huCards2,result,isTouch);
  1931. }
  1932. else if(copyhandCards.length > 0) {
  1933. //下面的for循环是用手牌的两张牌做将牌看能不能胡牌
  1934. for (let i = 0; i < copyhandCards.length - 1; ++i) {
  1935. let cards2t = this.deepCloneTL(copyhandCards)
  1936. if (!this.isJang(cards2t[i], cards2t[i + 1])) continue;
  1937. let bcjp = cards22[i];
  1938. let huRes3 = { card: dangPaiList[n], jiang: bcjp, huCards: [] };
  1939. // 重设将牌
  1940. huRes3.jiang = cards2t[i];
  1941. huRes3.huCards = [];
  1942. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1943. let cards2 = cards2t.slice(0, i);////手牌数组的前i个元素
  1944. cards2 = cards2.concat(cards2t.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1945. this._dumpFixedc(cards2, huRes3.huCards,bdzs);
  1946. // console.warn("判胡 2张手牌做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1947. if (huRes3.huCards.length >= 4){
  1948. if(this.isNeedEWBZJ(cards22,huCards2,huRes3,false)){
  1949. let jiangValue = this.getValue(bcjp);
  1950. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1951. return true;
  1952. }
  1953. }
  1954. else{
  1955. return true;
  1956. }
  1957. }
  1958. i += 1;/////TL++,为了减少运算
  1959. }
  1960. //下面的for循环是用一张手牌和一张百搭牌做将牌看能不能胡牌
  1961. if(bdzs >= 1){
  1962. let bcjp = 0;///////本次的将牌
  1963. for (let i = 0; i < copyhandCards.length; ++i) {
  1964. let cards2t = this.deepCloneTL(copyhandCards);
  1965. if(cards2t[i] == bcjp) continue;
  1966. let huRes3 = { card: dangPaiList[n], jiang: bcjp, huCards: [] };
  1967. // 重设将牌
  1968. huRes3.jiang = cards2t[i];
  1969. huRes3.huCards = [];
  1970. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1971. bcjp = cards22[i]; ///////本次的将牌
  1972. let cards2 = cards2t.slice(0, i);////手牌数组的前i个元素
  1973. cards2 = cards2.concat(cards2t.slice(i + 1));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  1974. // console.warn("判胡 1张手牌做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1975. this._dumpFixedc(cards2, huRes3.huCards,bdzs-1);
  1976. if (huRes3.huCards.length >= 4){
  1977. if(this.isNeedEWBZJ(cards22,huCards2,huRes3,false)){
  1978. let jiangValue = this.getValue(bcjp);
  1979. if(jiangValue == 2 || jiangValue == 5 || jiangValue == 8){
  1980. return true;
  1981. }
  1982. }
  1983. else{
  1984. return true;
  1985. }
  1986. }
  1987. }
  1988. }
  1989. //下面的for循环是用2张百搭牌做将牌看能不能胡牌
  1990. if(bdzs >= 2){
  1991. let cards22 = this.deepCloneTL(copyhandCards);
  1992. let huRes3 = { card: dangPaiList[n], jiang: 0, huCards: [] };
  1993. // 重设将牌
  1994. huRes3.jiang = 51;
  1995. huRes3.huCards = [];
  1996. for (let huCard of huCards) huRes3.huCards.push(huCard);
  1997. // console.warn("判胡 2张红中做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards));
  1998. this._dumpFixedc(cards22, huRes3.huCards,bdzs-2);
  1999. if (huRes3.huCards.length >= 4){
  2000. return true;
  2001. }
  2002. }
  2003. }
  2004. }
  2005. }
  2006. // console.warn("检查是否可以听牌 不能听牌");
  2007. return false;
  2008. }
  2009. //是否需要二五八做将
  2010. proto.isNeedEWBZJ = function (handCards,huCards,hures,isTouch) {
  2011. // console.error("是否需要二五八做将 isTouch "+isTouch +" handCards " +handCards+" huCards "+JSON.stringify(huCards)+" hures "+JSON.stringify(hures));
  2012. let shoupai = handCards/////手牌
  2013. let PGPai = huCards/////手上的碰杠牌
  2014. let chengju = hures/////整理好之后成句的牌(包括碰杠牌)
  2015. for (var i = 5; i < this.dahuTypeTL.length; i++) {
  2016. if( i == 5 && this.isQQR(shoupai,PGPai,chengju)){
  2017. // console.warn("不需要2,5,8做将1");
  2018. return false;
  2019. }
  2020. // else if( i == 6 && isTouch && this.isMQ(shoupai,PGPai,chengju)){
  2021. // console.warn("不需要2,5,8做将2");
  2022. // return false;
  2023. // }
  2024. else if( i == 7 && this.isQYS(shoupai,PGPai,chengju)){
  2025. // console.warn("不需要2,5,8做将3");
  2026. return false;
  2027. }
  2028. else if( i == 8 && this.isPengPengHu(shoupai,PGPai,chengju)){
  2029. // console.warn("不需要2,5,8做将4");
  2030. return false;
  2031. }
  2032. else if( i == 12 && this.isTianHu(shoupai,PGPai,chengju)){
  2033. // console.warn("不需要2,5,8做将4");
  2034. return false;
  2035. }
  2036. // else if( i == 9 && this.isGangKai(shoupai,PGPai,chengju)){
  2037. // console.warn("不需要2,5,8做将5");
  2038. // return false;
  2039. // }
  2040. // else if( i == 10 && this.isQiangGang(shoupai,PGPai,chengju)){
  2041. // console.warn("不需要2,5,8做将6");
  2042. // return false;
  2043. // }
  2044. // else if( i == 11 && this.isHDLY(shoupai,PGPai,chengju)){
  2045. // console.warn("不需要2,5,8做将7");
  2046. // return false;
  2047. // }
  2048. }
  2049. // console.error("是否需要二五八做将 需要 ");
  2050. return true;
  2051. }
  2052. // 是否可以出牌,别人有权限的时候不能出牌需要等待
  2053. proto.getIsCanOut = function (masks) {
  2054. let isCanOut = true;
  2055. for (let x = 0; x < masks.length; ++x) {
  2056. if(masks[x] > 0){
  2057. isCanOut = false;
  2058. break;
  2059. }
  2060. }
  2061. return isCanOut;
  2062. };
  2063. //删除起手胡牌型的操作权限
  2064. proto.getNewMask = function (oldMask) {
  2065. let list = [1,2,4,8,16,32];
  2066. let isCanOperateList = [];
  2067. for (let i = 0; i < list.length; ++i) {
  2068. // if(oldMask < list[i]) break;
  2069. if(oldMask & list[i]) isCanOperateList[isCanOperateList.length] = 1;
  2070. else isCanOperateList[isCanOperateList.length] = 0;
  2071. }
  2072. let newMask = 0;
  2073. for (let i = 0; i < isCanOperateList.length; ++i) {
  2074. if(isCanOperateList[i] == 1){
  2075. newMask |= list[i]
  2076. }
  2077. }
  2078. return newMask;
  2079. }
  2080. ////得到list1里面是否包含list2
  2081. proto.getISBH = function (_list1,list2) {
  2082. //因为运算过程中会改变_list1的值所以需要备份数据
  2083. let list1 = this.deepCloneTL(_list1);
  2084. for (let i = 0; i < list2.length; ++i) {
  2085. let pos = list1.indexOf(list2[i]);
  2086. if (pos == -1){
  2087. return false;
  2088. }
  2089. list1.splice(pos, 1);
  2090. }
  2091. return true
  2092. }
  2093. ////得到list1[[],[],[]]里面是否包含list2
  2094. proto.getISBH2 = function (_list1,list2) {
  2095. // console.warn("得到list1[[],[],[]]里面是否包含list2 "+JSON.stringify(_list1)+" list2 "+list2);
  2096. for (let i = 0; i < _list1.length; ++i) {
  2097. if(_list1[i].length == list2.length){
  2098. for (let x = 0; x < _list1[i].length; ++x) {
  2099. if(_list1[i][x] == list2[x]){
  2100. // console.warn("包含了 第i个 "+i);
  2101. return true;
  2102. }
  2103. }
  2104. }
  2105. }
  2106. // console.warn("不包含");
  2107. return false
  2108. }
  2109. //// 得到是否是起手
  2110. proto.getIsQS = function () {
  2111. let isqs = this.castCount == (this.playerAllCount*CARDS_COUNT+1);//是否起手
  2112. if(isqs){
  2113. if(this.chuPaiCountTL == 0) return true;
  2114. }
  2115. return false;
  2116. }
  2117. // 起手胡牌分析 chairID(TL++这个参数) 手牌 加上这张判断能不能胡 手上的吃碰杠牌 是否自己摸上来的
  2118. proto.qshuAnalyze = function (chairID,handCards) {
  2119. this.everyQSHType[chairID] = [];
  2120. this.canSelects[chairID] = [];
  2121. let isqs = this.getIsQS();
  2122. let shoupai = this.deepCloneTL(handCards);
  2123. // this.remove(shoupai,this.everyQSHCZGList[chairID]);
  2124. shoupai = this.sort(shoupai);
  2125. for (let i = 0; i < this.qshuTypeTL.length; ++i) {
  2126. this.everyQSHType[chairID][i] = 0;
  2127. if( i == 0 && isqs && this.isSiXi(chairID,shoupai,isqs)){
  2128. this.everyQSHType[chairID][i] = 1;
  2129. }
  2130. else if( i == 1 && isqs && this.isBanBanHu(chairID,shoupai,isqs)){
  2131. this.everyQSHType[chairID][i] = 1;
  2132. }
  2133. else if( i == 2 && isqs && this.isQueYiSe(chairID,shoupai,isqs)){
  2134. this.everyQSHType[chairID][i] = 1;
  2135. }
  2136. else if( i == 3 && isqs && this.isLiuLiuShun(chairID,shoupai,isqs)){
  2137. this.everyQSHType[chairID][i] = 1;
  2138. }
  2139. else if( i == 4 && (!isqs) && this.isSiXi(chairID,shoupai,isqs)){
  2140. this.everyQSHType[chairID][i] = 1;
  2141. }
  2142. else if( i == 5 && (!isqs) && this.isLiuLiuShun(chairID,shoupai,isqs)){
  2143. this.everyQSHType[chairID][i] = 1;
  2144. }
  2145. // else if( i == 4 && this.isJieJieGao(shoupai)){
  2146. // this.everyQSHType[chairID][i] = 1;
  2147. // }
  2148. // else if( i == 5 && this.everyQSHType[chairID][2] == 0 && this.isSanTong(shoupai)){
  2149. // //是缺一色的情况下不可能是三同
  2150. // this.everyQSHType[chairID][i] = 1;
  2151. // }
  2152. // else if( i == 6 && this.everyQSHType[chairID][1] == 0 && this.isDanJiang(shoupai)){
  2153. // //是板板胡的话不可能是单将一枝花
  2154. // this.everyQSHType[chairID][i] = 1;
  2155. // }
  2156. // else if( i == 7 && this.everyQSHType[chairID][1] == 0 && this.everyQSHType[chairID][6] == 0 && this.isDanWu(shoupai)){
  2157. // //是板板胡的话不可能是单五一枝花
  2158. // //只有一张五的情况下都满足单将一枝花和单五一枝花,这种情况算单将一枝花单五一枝花不成立
  2159. // this.everyQSHType[chairID][i] = 1;
  2160. // }
  2161. }
  2162. }
  2163. //起手的六六顺消耗过的牌起手四喜不能再次使用,中途的六六顺消耗过的牌中途四喜不能再次使用,
  2164. //起手的六六顺消耗过的牌中途四喜可以再次使用,(四喜和六六顺同理)
  2165. // 是否四喜
  2166. proto.isSiXi = function (chairID,handCards,isqs) {
  2167. // console.error("是否四喜===111 chairID "+chairID+" everyQSHCZGList "+JSON.stringify(this.everyQSHCZGList[chairID]));
  2168. // console.error("是否四喜===222 chairID "+chairID+" everyQSHCZGList2 "+JSON.stringify(this.everyQSHCZGList2[chairID]));
  2169. // console.error("是否四喜===333 chairID "+chairID+" handCards "+JSON.stringify(handCards));
  2170. if(!isqs && this.kexuanList[0] != 1) return false;//没有勾选中途大四喜
  2171. let canSelects = [];
  2172. var dcount = 0;
  2173. for (let i = 0; i < handCards.length-3; ++i) {
  2174. let card = handCards[i];
  2175. if (card == handCards[i+1] && card == handCards[i+2] && card == handCards[i+3]) {
  2176. if(!this.getISBH(this.everyQSHCZGList[chairID],[card,card,card])){
  2177. dcount += 1;
  2178. i+=3;
  2179. canSelects.push([card,card,card,card])
  2180. }
  2181. else{
  2182. // console.error("是否四喜===222 chairID isqs " + isqs)
  2183. //添加这个else是为了满足下面这个规则,如果消耗过的牌不能再次使用就不要这个else了
  2184. //起手的六六顺消耗过的牌起手四喜不能再次使用,中途的六六顺消耗过的牌中途四喜不能再次使用,
  2185. //起手的六六顺消耗过的牌中途四喜可以再次使用,(四喜和六六顺同理)
  2186. if(!isqs && !this.getISBH2(this.everyQSHCZGList2[chairID],[card,card,card,card])){
  2187. dcount += 1;
  2188. i+=3;
  2189. canSelects.push([card,card,card,card])
  2190. }
  2191. }
  2192. }
  2193. }
  2194. if(dcount >= 1){
  2195. let type = 0;
  2196. if(!isqs) type = 4;
  2197. let obj = {
  2198. type:type,
  2199. cards:canSelects
  2200. }
  2201. this.canSelects[chairID].push(obj)
  2202. return true;
  2203. }
  2204. return false;
  2205. };
  2206. // 是否板板胡
  2207. proto.isBanBanHu = function (chairID,handCards,isqs) {
  2208. if(this.everyXiaoHuList[chairID].indexOf(1) != -1) return false;
  2209. for (let i = 0; i < handCards.length; ++i) {
  2210. let card = this.getValue(handCards[i]);
  2211. if (card == 2 || card == 5 || card == 8) {
  2212. return false;
  2213. }
  2214. }
  2215. let obj = {
  2216. type:1,
  2217. cards:[]
  2218. }
  2219. this.canSelects[chairID].push(obj);
  2220. return true;
  2221. };
  2222. // 是否缺一色
  2223. proto.isQueYiSe = function (chairID,handCards,isqs) {
  2224. // console.warn("是否缺一色 chairID "+chairID+" handCards "+handCards + " isqs "+isqs);
  2225. let huaSeCount = [0,0,0,0];
  2226. for (let i = 0; i < handCards.length; ++i) {
  2227. let card = handCards[i];
  2228. if(this.getType(card) == 1 ) huaSeCount[0] = 1;
  2229. if(this.getType(card) == 2 ) huaSeCount[1] = 1;
  2230. if(this.getType(card) == 3 ) huaSeCount[2] = 1;
  2231. }
  2232. let huase = 0;
  2233. for (let n = 0; n < huaSeCount.length; ++n) {
  2234. if(huaSeCount[n] == 1) huase += 1;
  2235. }
  2236. if(huase <= 2){
  2237. let ismz = false;
  2238. let yjhgdqyscs = 0;//已经胡过的缺一色次数
  2239. for (let i = 0; i < this.everyXiaoHuList[chairID].length; ++i) {
  2240. if(this.everyXiaoHuList[chairID][i] == 2) yjhgdqyscs++
  2241. }
  2242. if(huase == 2){
  2243. if(yjhgdqyscs == 0) ismz = true;
  2244. }
  2245. else if(huase == 1){
  2246. //手上只有一种花色可以胡缺一色两次
  2247. if(yjhgdqyscs < 2) ismz = true;
  2248. }
  2249. // console.warn("缺一色==== "+ismz+" yjhgdqyscs "+yjhgdqyscs + " huase "+huase);
  2250. if(ismz){
  2251. let obj = {
  2252. type:2,
  2253. cards:[]
  2254. }
  2255. this.canSelects[chairID].push(obj);
  2256. return true;
  2257. }
  2258. }
  2259. return false;
  2260. };
  2261. // 是否六六顺
  2262. proto.isLiuLiuShun = function (chairID,handCards,isqs) {
  2263. if(!isqs && this.kexuanList[1] != 1) return false;//没有勾选中途大四喜
  2264. var keList = [];
  2265. for (let i = 0; i < handCards.length-2; ++i) {
  2266. let card = handCards[i];
  2267. if (card == handCards[i+1] && card == handCards[i+2]) {
  2268. keList.push([card,card,card])
  2269. i+=2;
  2270. }
  2271. }
  2272. if(keList.length >= 2){
  2273. let cards = [];
  2274. for (let i = 0; i < keList.length; ++i) {
  2275. for (let j = i+1; j < keList.length; ++j) {
  2276. if(!this.getISBH(this.everyQSHCZGList[chairID],keList[i]) && !this.getISBH(this.everyQSHCZGList[chairID],keList[j])){
  2277. let cc = keList[i].concat(keList[j]);
  2278. cards.push(cc);
  2279. }
  2280. }
  2281. }
  2282. if(cards.length > 0){
  2283. let type = 3;
  2284. if(!isqs) type = 5;
  2285. let obj = {
  2286. type:type,
  2287. cards:cards
  2288. }
  2289. this.canSelects[chairID].push(obj);
  2290. return true
  2291. }
  2292. return false;
  2293. }
  2294. return false;
  2295. };
  2296. // 是否节节高
  2297. // proto.isJieJieGao = function (handCards) {
  2298. // var duiziList = [];
  2299. // for (let i = 0; i < handCards.length-1; ++i) {
  2300. // let card = handCards[i];
  2301. // if (card == handCards[i+1]) {
  2302. // if(duiziList.indexOf(card) == -1){
  2303. // duiziList[duiziList.length] = card;
  2304. // }
  2305. // i+=1;
  2306. // }
  2307. // }
  2308. // for (let i = 0; i < duiziList.length; ++i) {
  2309. // let value = this.getValue(duiziList[i])
  2310. // if(value < 8 && duiziList[i]+1 == duiziList[i+ 1] && duiziList[i]+2 == duiziList[i+ 2]){
  2311. // return true
  2312. // }
  2313. // }
  2314. // return false;
  2315. // };
  2316. // // 是否三同
  2317. // proto.isSanTong = function (handCards) {
  2318. // var duiziList = [];
  2319. // for (let i = 0; i < handCards.length-1; ++i) {
  2320. // let card = handCards[i];
  2321. // if (card == handCards[i+1]) {
  2322. // if(duiziList.indexOf(card) == -1){
  2323. // duiziList[duiziList.length] = card;
  2324. // }
  2325. // i+=1;
  2326. // }
  2327. // }
  2328. // for (let i = 0; i < duiziList.length; ++i) {
  2329. // let card = handCards[i];
  2330. // let type = this.getType(duiziList[i])
  2331. // if(type < 2){
  2332. // if(duiziList.indexOf(card + 10) != -1 && duiziList.indexOf(card + 20) != -1){
  2333. // return true;
  2334. // }
  2335. // }
  2336. // else {
  2337. // return false;
  2338. // }
  2339. // }
  2340. // return false;
  2341. // };
  2342. // // 是否单将一枝花
  2343. // proto.isDanJiang = function (handCards) {
  2344. // let count = 0;
  2345. // for (let i = 0; i < handCards.length; ++i) {
  2346. // let value = this.getValue(handCards[i])
  2347. // if (value == 2 || value == 5 || value == 8) {
  2348. // count++;
  2349. // if(count >= 2) return false;
  2350. // }
  2351. // }
  2352. // return true;
  2353. // };
  2354. // // 是否单五一枝花
  2355. // proto.isDanWu = function (handCards) {
  2356. // let count1 = 0;
  2357. // let count2 = 0;
  2358. // let count3 = 0;
  2359. // for (let i = 0; i < handCards.length; ++i) {
  2360. // let value = this.getValue(handCards[i])
  2361. // if (value == 2) count1++;
  2362. // if (value == 5) count2++;
  2363. // if (value == 8) count3++;
  2364. // }
  2365. // if(count1 == 1 || count2 == 1 || count3 == 1) return true;
  2366. // };
  2367. //得到除7对和将将胡之外的大胡牌型,大胡牌型可以乱将
  2368. proto.getCardTypeTL = function (chairID,handCards, huCards,hures,isTouch) {
  2369. // console.warn("得到除7对和将将胡之外的大胡牌型,大胡牌型可以乱将 "+this.dahuTypeTL.length);
  2370. let shoupai = handCards/////手牌
  2371. let PGPai = huCards/////手上的碰杠牌
  2372. let chengju = hures/////整理好之后成句的牌(包括碰杠牌)
  2373. for (var i = 0; i < this.dahuTypeTL.length; i++) {
  2374. this.everyDAHType[chairID][i] = 0;
  2375. if( i == 0 && this.isSevenDouble(shoupai,PGPai,chengju)){
  2376. this.everyDAHType[chairID][i] = 1;
  2377. }
  2378. if( i == 1 && this.everyDAHType[chairID][0] == 1 && this.isHHSevenDouble(shoupai,PGPai,chengju)){
  2379. this.everyDAHType[chairID][i] = 1;
  2380. }
  2381. if( i == 2 && this.everyDAHType[chairID][0] == 1 && this.isSHHSevenDouble(shoupai,PGPai,chengju)){
  2382. this.everyDAHType[chairID][i] = 1;
  2383. }
  2384. if( i == 3 && this.everyDAHType[chairID][0] == 1 && this.isSSHHSevenDouble(shoupai,PGPai,chengju)){
  2385. this.everyDAHType[chairID][i] = 1;
  2386. }
  2387. if( i == 4 && this.isJiangJiangHu(shoupai,PGPai,chengju)){
  2388. this.everyDAHType[chairID][i] = 1;
  2389. }
  2390. if( i == 5 && this.isQQR(shoupai,PGPai,chengju)){
  2391. this.everyDAHType[chairID][i] = 1;
  2392. }
  2393. else if( i == 6 && isTouch && this.isMQ(shoupai,PGPai,chengju)){
  2394. this.everyDAHType[chairID][i] = 1;
  2395. }
  2396. else if( i == 7 && this.isQYS(shoupai,PGPai,chengju)){
  2397. this.everyDAHType[chairID][i] = 1;
  2398. }
  2399. else if( i == 8 && this.isPengPengHu(shoupai,PGPai,chengju)){
  2400. this.everyDAHType[chairID][i] = 1;
  2401. }
  2402. else if( i == 9 && this.isGangKai(shoupai,PGPai,chengju)){
  2403. this.everyDAHType[chairID][i] = 1;
  2404. }
  2405. else if( i == 10 && this.isQiangGang(shoupai,PGPai,chengju)){
  2406. this.everyDAHType[chairID][i] = 1;
  2407. }
  2408. else if( i == 11 && this.isHDLY(shoupai,PGPai,chengju)){
  2409. this.everyDAHType[chairID][i] = 1;
  2410. }
  2411. else if( i == 12 && this.isTianHu(shoupai,PGPai,chengju)){
  2412. this.everyDAHType[chairID][i] = 1;
  2413. }
  2414. }
  2415. }
  2416. // 是否七对
  2417. proto.isSevenDouble = function (handCards,PGPai,chengju) {
  2418. if (handCards.length <= CARDS_COUNT) return false;
  2419. let baiDaCount22 = this.sbyBDList.length////TL++
  2420. var dcount = 0;
  2421. var counts = {};
  2422. for (let i = 0; i < handCards.length; ++i) {
  2423. let card = handCards[i];
  2424. if(this.judgeACardISBD(card)) continue;/////百搭牌不做基础牌进行判断
  2425. counts[card] = (counts[card] || 0) + 1;
  2426. if (counts[card] >= 2) {
  2427. dcount += 1;
  2428. counts[card] = 0;
  2429. }
  2430. }
  2431. // console.warn("是否是7对 ",baiDaCount22,dcount,handCards);
  2432. return (dcount + baiDaCount22 >= 7);
  2433. };
  2434. // 是否豪华七对
  2435. proto.isHHSevenDouble = function (handCards,PGPai,chengju) {
  2436. if (handCards.length <= CARDS_COUNT) return false;
  2437. let baiDaCount22 = this.sbyBDList.length////TL++
  2438. var gcount = 0;
  2439. for (let i = 0; i < handCards.length-3; ++i) {
  2440. let card = handCards[i];
  2441. if(this.judgeACardISBD(card)) continue;/////百搭牌不做基础牌进行判断
  2442. if (card == handCards[i+1] && card == handCards[i+2] && card == handCards[i+3]) {
  2443. gcount += 1;
  2444. i+=3;
  2445. }
  2446. }
  2447. // console.warn("是否是豪华七对 "+gcount+" baiDaCount22 "+baiDaCount22+" handCards "+JSON.stringify(handCards));
  2448. if(gcount >= 1){
  2449. return true;
  2450. }
  2451. if(baiDaCount22 >= 1){
  2452. var kcount = 0;
  2453. for (let i = 0; i < handCards.length-2; ++i) {
  2454. let card = handCards[i];
  2455. if(this.judgeACardISBD(card)) continue;/////百搭牌不做基础牌进行判断
  2456. if (card == handCards[i+1] && card == handCards[i+2]) {
  2457. kcount += 1;
  2458. i+=2;
  2459. }
  2460. }
  2461. // console.warn("是否是豪华七对 有百搭111 kcount "+kcount);
  2462. if(kcount >= 1) return true;
  2463. //至此手上只有对子和单牌
  2464. var dcount = 0;
  2465. var counts = {};
  2466. for (let i = 0; i < handCards.length; ++i) {
  2467. let card = handCards[i];
  2468. if(this.judgeACardISBD(card)) continue;/////百搭牌不做基础牌进行判断
  2469. counts[card] = (counts[card] || 0) + 1;
  2470. if (counts[card] >= 2) {
  2471. dcount += 1;
  2472. counts[card] = 0;
  2473. }
  2474. }
  2475. // console.warn("是否是豪华七对 dcount "+dcount+" kcount "+kcount)
  2476. if(dcount == 5 && baiDaCount22 >= 3) return true;//5对+4百搭 或者5对1单3百搭
  2477. else if(dcount == 6 && baiDaCount22 == 2) return true;
  2478. }
  2479. return false;
  2480. };
  2481. // 是否双豪华七对
  2482. proto.isSHHSevenDouble = function (handCards,PGPai,chengju) {
  2483. if (handCards.length <= CARDS_COUNT) return false;
  2484. let baiDaCount22 = this.sbyBDList.length////TL++
  2485. var gcount = 0;
  2486. for (let i = 0; i < handCards.length-3; ++i) {
  2487. let card = handCards[i];
  2488. if(this.judgeACardISBD(card)) continue;/////百搭牌不做基础牌进行判断
  2489. if (card == handCards[i+1] && card == handCards[i+2] && card == handCards[i+3]) {
  2490. gcount += 1;
  2491. i+=3;
  2492. }
  2493. }
  2494. if(gcount >= 2) return true;
  2495. if(baiDaCount22 >= 1){
  2496. gcount = 0;
  2497. var kcount = 0;
  2498. var dcount = 0;
  2499. for (let i = 0; i < handCards.length-1; ++i) {
  2500. let card = handCards[i];
  2501. if(this.judgeACardISBD(card)) continue;/////百搭牌不做基础牌进行判断
  2502. if (handCards[i+2] && handCards[i+3] && card == handCards[i+1] && card == handCards[i+2] && card == handCards[i+3]) {
  2503. gcount += 1;
  2504. i+=3;
  2505. }
  2506. if (handCards[i+2] && card == handCards[i+1] && card == handCards[i+2]) {
  2507. kcount += 1;
  2508. i+=2;
  2509. }
  2510. else if (card == handCards[i+1]) {
  2511. dcount += 1;
  2512. i+=1;
  2513. }
  2514. }
  2515. // console.warn("是否是双豪华七对 有百搭111 gcount "+gcount+" kcount "+kcount+" dcount "+dcount);
  2516. if(gcount == 0){
  2517. if(kcount == 0){
  2518. //无杠无刻情况下只能是5对+4百搭 组成双豪华七对
  2519. if(dcount == 5 && baiDaCount22 == 4) return true;
  2520. }
  2521. else if(kcount == 1){
  2522. //无杠1刻情况下 1刻4对3百搭 组成双豪华七对
  2523. if(dcount == 4 && baiDaCount22 == 3) return true;
  2524. //无杠1刻情况下 1刻3对1单牌4百搭 组成双豪华七对
  2525. else if(dcount == 3 && baiDaCount22 == 4) return true;
  2526. }
  2527. else if(kcount == 2){
  2528. //无杠2刻情况下 2刻3对2百搭 组成双豪华七对
  2529. if(dcount == 3 && baiDaCount22 == 2) return true;
  2530. //无杠2刻情况下 2刻2对1单3百搭 组成双豪华七对
  2531. else if(dcount == 2 && baiDaCount22 == 3) return true;
  2532. //无杠2刻情况下 2刻2对4百搭 组成双豪华七对
  2533. else if(dcount == 2 && baiDaCount22 == 4) return true;
  2534. }
  2535. else if(kcount == 3){
  2536. //无杠3刻情况下 3刻1对3百搭 组成双豪华七对
  2537. if(dcount == 1 && baiDaCount22 == 3) return true;
  2538. //无杠3刻情况下 3刻0对1单4百搭 组成双豪华七对
  2539. else if(dcount == 0 && baiDaCount22 == 4) return true;
  2540. }
  2541. }
  2542. if(gcount == 1){
  2543. if(kcount == 0){
  2544. //1杠无刻情况下 1杠0刻4对2百搭 组成双豪华七对
  2545. if(dcount == 4 && baiDaCount22 == 2) return true;
  2546. //1杠无刻情况下 1杠0刻3对4百搭 组成双豪华七对
  2547. else if(dcount == 3 && baiDaCount22 == 4) return true;
  2548. }
  2549. else if(kcount == 1){
  2550. //1杠1刻情况下 1杠1刻3对1百搭 组成双豪华七对
  2551. if(dcount == 3 && baiDaCount22 == 1) return true;
  2552. //1杠1刻情况下 1杠1刻2对1单2百搭 组成双豪华七对
  2553. else if(dcount == 2 && baiDaCount22 == 2) return true;
  2554. //1杠1刻情况下 1杠1刻2对3百搭 组成双豪华七对
  2555. else if(dcount == 2 && baiDaCount22 == 3) return true;
  2556. //1杠1刻情况下 1杠1刻1对2单3百搭 组成双豪华七对
  2557. else if(dcount == 1 && baiDaCount22 == 3) return true;
  2558. //1杠1刻情况下 1杠1刻0对3单牌4百搭 组成双豪华七对
  2559. else if(dcount == 0 && baiDaCount22 == 4) return true;
  2560. }
  2561. else if(kcount == 2){
  2562. //1杠2刻情况下 1杠2刻1对2百搭 组成双豪华七对
  2563. if(dcount == 1 && baiDaCount22 == 2) return true;
  2564. //1杠2刻情况下 1杠2刻0对1单3百搭 组成双豪华七对
  2565. else if(dcount == 0 && baiDaCount22 == 3) return true;
  2566. //1杠2刻情况下 1杠2刻0对0单4百搭 组成双豪华七对
  2567. else if(dcount == 0 && baiDaCount22 == 4) return true;
  2568. }
  2569. }
  2570. }
  2571. return false;
  2572. };
  2573. // 是否三豪华七对
  2574. proto.isSSHHSevenDouble = function (handCards,PGPai,chengju) {
  2575. if (handCards.length <= CARDS_COUNT) return false;
  2576. let baiDaCount22 = this.sbyBDList.length////TL++
  2577. var gcount = 0;
  2578. for (let i = 0; i < handCards.length-3; ++i) {
  2579. let card = handCards[i];
  2580. if (card == handCards[i+1] && card == handCards[i+2] && card == handCards[i+3]) {
  2581. gcount += 1;
  2582. i+=3;
  2583. }
  2584. }
  2585. if(gcount >= 3) return true;
  2586. if(baiDaCount22 >= 1){
  2587. gcount = 0;
  2588. var kcount = 0;
  2589. var dcount = 0;
  2590. for (let i = 0; i < handCards.length-1; ++i) {
  2591. let card = handCards[i];
  2592. if(this.judgeACardISBD(card)) continue;/////百搭牌不做基础牌进行判断
  2593. if (handCards[i+2] && handCards[i+3] && card == handCards[i+1] && card == handCards[i+2] && card == handCards[i+3]) {
  2594. gcount += 1;
  2595. i+=3;
  2596. }
  2597. if (handCards[i+2] && card == handCards[i+1] && card == handCards[i+2]) {
  2598. kcount += 1;
  2599. i+=2;
  2600. }
  2601. else if (card == handCards[i+1]) {
  2602. dcount += 1;
  2603. i+=1;
  2604. }
  2605. }
  2606. // console.warn("是否是三豪华七对 有百搭111 gcount "+gcount+" kcount "+kcount+" dcount "+dcount);
  2607. if(gcount == 0){
  2608. if(kcount == 2){
  2609. //无杠2刻情况下 2刻2对4百搭 组成三豪华七对
  2610. if(dcount == 2 && baiDaCount22 == 4) return true;
  2611. }
  2612. else if(kcount == 3){
  2613. //无杠3刻情况下 3刻1对3百搭 组成三豪华七对
  2614. if(dcount == 1 && baiDaCount22 == 3) return true;
  2615. //无杠3刻情况下 3刻0对1单4百搭 组成三豪华七对
  2616. else if(dcount == 0 && baiDaCount22 == 4) return true;
  2617. }
  2618. }
  2619. if(gcount == 1){
  2620. if(kcount == 0){
  2621. //1杠无刻情况下 1杠0刻3对4百搭 组成三豪华七对
  2622. if(dcount == 3 && baiDaCount22 == 4) return true;
  2623. }
  2624. else if(kcount == 1){
  2625. //1杠1刻情况下 1杠1刻2对3百搭 组成三豪华七对
  2626. if(dcount == 2 && baiDaCount22 == 3) return true;
  2627. //1杠1刻情况下 1杠1刻1对1单牌4百搭 组成三豪华七对
  2628. else if(dcount == 1 && baiDaCount22 == 4) return true;
  2629. }
  2630. else if(kcount == 2){
  2631. //1杠2刻情况下 1杠2刻1对2百搭 组成三豪华七对
  2632. if(dcount == 1 && baiDaCount22 == 2) return true;
  2633. //1杠2刻情况下 1杠2刻0对1单3百搭 组成三豪华七对
  2634. else if(dcount == 0 && baiDaCount22 == 3) return true;
  2635. //1杠2刻情况下 1杠2刻0对0单4百搭 组成三豪华七对
  2636. else if(dcount == 0 && baiDaCount22 == 4) return true;
  2637. }
  2638. }
  2639. if(gcount == 2){
  2640. if(kcount == 0){
  2641. //2杠无刻情况下 2杠0刻1对1单3百搭 组成三豪华七对
  2642. if(dcount == 1 && baiDaCount22 == 3) return true;
  2643. //2杠无刻情况下 2杠0刻1对4百搭 组成三豪华七对
  2644. else if(dcount == 1 && baiDaCount22 == 4) return true;
  2645. }
  2646. else if(kcount == 1){
  2647. //2杠1刻情况下 2杠1刻1对1百搭 组成三豪华七对
  2648. if(dcount == 1 && baiDaCount22 == 1) return true;
  2649. //2杠1刻情况下 2杠1刻1对1单2百搭 组成三豪华七对
  2650. else if(dcount == 1 && baiDaCount22 == 2) return true;
  2651. //2杠1刻情况下 2杠1刻0对0单牌3百搭 组成三豪华七对
  2652. else if(dcount == 0 && baiDaCount22 == 3) return true;
  2653. }
  2654. }
  2655. }
  2656. return false;
  2657. };
  2658. // 是否将将胡
  2659. proto.isJiangJiangHu = function (handCards,PGPai,chengju) {
  2660. for (let i = 0; i < handCards.length; ++i) {
  2661. if(this.judgeACardISBD(handCards[i])) continue;/////百搭牌不做基础牌进行判断
  2662. let value = this.getValue(handCards[i]);
  2663. if (value == 2 || value == 5 || value == 8) continue;
  2664. else return false;
  2665. }
  2666. ////上面是统计手牌2,5,8,下面是统计碰杠牌的2,5,8
  2667. if(PGPai && PGPai.length > 0){
  2668. for (let i = 0; i < PGPai.length; ++i) {
  2669. if(!PGPai[i]) continue;
  2670. let pgcardlist = PGPai[i].cards;
  2671. if(!pgcardlist) continue;
  2672. for (let j = 0; j < pgcardlist.length; ++j) {
  2673. let card2 = pgcardlist[j];
  2674. let value = this.getValue(card2);
  2675. if (value == 2 || value == 5 || value == 8) continue;
  2676. else return false;
  2677. }
  2678. }
  2679. }
  2680. return true;
  2681. }
  2682. //是否 "全求人",
  2683. proto.isQQR = function (shoupai,PGPai,chengju) {
  2684. // console.warn("判断全求人 shoupai "+shoupai);
  2685. if(shoupai.length == 2){
  2686. if(shoupai[0] == shoupai[1]) return true;
  2687. if(shoupai.indexOf(51) != -1) return true;
  2688. }
  2689. return false;
  2690. }
  2691. //是否 "门清",
  2692. proto.isMQ = function (shoupai,PGPai,chengju) {
  2693. if(this.kexuanList[2] != 1) return false;
  2694. return shoupai.length == (CARDS_COUNT+1) && PGPai.length == 0
  2695. }
  2696. //是否 "清一色",
  2697. proto.isQYS = function (shoupai,PGPai,chengju) {
  2698. let huaSe= 0;
  2699. for (let n = 0; n < shoupai.length; ++n) {
  2700. let card = shoupai[n];
  2701. if(this.judgeACardISBD(card)) continue;
  2702. if(huaSe == 0){
  2703. huaSe = this.getType(card);
  2704. }
  2705. else{
  2706. if(this.getType(card) != huaSe){
  2707. return false;
  2708. }
  2709. }
  2710. }
  2711. ////上面是统计手牌花色种类,下面是统计碰杠牌的花色
  2712. if(PGPai && PGPai.length > 0){
  2713. for (let i = 0; i < PGPai.length; ++i) {
  2714. if(!PGPai[i]) continue;
  2715. let pgcardlist = PGPai[i].cards;
  2716. if(!pgcardlist) continue;
  2717. let card2 = pgcardlist[0];
  2718. if(this.judgeACardISBD(card2)) continue;
  2719. if(this.getType(card2) != huaSe){
  2720. return false;
  2721. }
  2722. }
  2723. }
  2724. return true;
  2725. };
  2726. // 是否碰碰胡
  2727. proto.isPengPengHu = function (shoupai,PGPai,chengju) {
  2728. // console.warn("是否碰碰胡000 shoupai "+shoupai+" PGPai "+JSON.stringify(PGPai));
  2729. // console.warn("是否碰碰胡111 chengju "+JSON.stringify(chengju));
  2730. let cjlist = chengju.huCards
  2731. if(!cjlist) return false;/////七对的话没有chengju,所以直接返回false
  2732. // console.warn("是否碰碰胡222 "+JSON.stringify(chengju));
  2733. let keOrGangCount = 0;
  2734. for (let i = 0; i < cjlist.length; ++i) {
  2735. if(cjlist[i].style >= 3 && cjlist[i].style <= 10) keOrGangCount += 1;
  2736. }
  2737. return keOrGangCount == 4 && chengju.jiang > 0;
  2738. // if(keOrGangCount == 4 && chengju.jiang > 0) return true;
  2739. // let huCards2 = this.deepCloneTL(PGPai)
  2740. // // console.warn("判断13不搭手上百搭牌个数出错了?????",baiDaCount22,this.sbyBDList,bdIndexlist)
  2741. // var huRes = { card: 0, jiang: 0, huCards: [] };
  2742. // // 重设将牌
  2743. // var resetHuRes = (jiang) => {
  2744. // huRes.jiang = jiang;
  2745. // huRes.huCards = [];
  2746. // for (let huCard of huCards2) huRes.huCards.push(huCard);
  2747. // };
  2748. // for (let i = 0; i < shoupai.length - 1; ++i) {
  2749. // let handCards = this.deepCloneTL(shoupai)
  2750. // if (!this.isJang(handCards[i], handCards[i + 1])) continue;
  2751. // // console.warn("判断13不搭手上百搭牌个数出错了?????000 ",JSON.stringify(huRes))
  2752. // resetHuRes(handCards[i]);////设置将牌
  2753. // // console.warn("判断13不搭手上百搭牌个数出错了?????111 ",JSON.stringify(huRes))
  2754. // let bcjp = handCards[i];
  2755. // let cards = handCards.slice(0, i);////手牌数组的前i个元素
  2756. // cards = cards.concat(handCards.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌
  2757. // this._dumpFixed(cards, huRes.huCards);
  2758. // // console.warn("判断13不搭手上百搭牌个数出错了?????222 ",JSON.stringify(huRes))
  2759. // i += 1;/////TL++,为了减少运算
  2760. // if(huRes.huCards.length == 4){
  2761. // let keOrGangCount = 0;
  2762. // for (let j = 0; j < huRes.huCards.length; ++j) {
  2763. // if(huRes.huCards[j].style >= 3 && huRes.huCards[j].style <= 10) keOrGangCount += 1;
  2764. // }
  2765. // // console.warn("是否碰碰胡333 "+JSON.stringify(huRes)+" keOrGangCount "+keOrGangCount);
  2766. // if(keOrGangCount == 4 && huRes.jiang > 0) return true;
  2767. // }
  2768. // }
  2769. // return false;
  2770. };
  2771. //是否杠开
  2772. proto.isGangKai = function (shoupai,PGPai,chengju) {
  2773. // console.warn("是否杠开 ",this.currChairIDTL,JSON.stringify(this.isGGMG),JSON.stringify(this.isGGAG),JSON.stringify(this.isGGFXG));
  2774. // if(this.isSeleCatcedCard){
  2775. // if(this.isGGMG[this.currChairIDTL] || this.isGGAG[this.currChairIDTL] || this.isGGFXG[this.currChairIDTL]){
  2776. // return true;/////普通杠开
  2777. // }
  2778. // }
  2779. ////上面是判断刚开的方法,下面是可以杠开和杠炮都判断,因为杠开和杠炮不能同时存在
  2780. for (var i = 0; i < this.isGGMG.length; i++) {
  2781. if(this.isGGMG[i]) return true;
  2782. }
  2783. for (var i = 0; i < this.isGGAG.length; i++) {
  2784. if(this.isGGAG[i]) return true;
  2785. }
  2786. for (var i = 0; i < this.isGGFXG.length; i++) {
  2787. if(this.isGGFXG[i]) return true;
  2788. }
  2789. return false;
  2790. }
  2791. //是否抢杠胡
  2792. proto.isQiangGang = function (shoupai,PGPai,chengju) {
  2793. return this.isLaGang
  2794. }
  2795. //是否海底捞月
  2796. proto.isHDLY = function (shoupai,PGPai,chengju) {
  2797. // console.error("是否海底捞月 "+" this.isZHYZ "+this.isZHYZ+" this.lastCount "+this.lastCount);
  2798. return (this.isZHYZ && this.lastCount == 0)
  2799. }
  2800. //是否天胡
  2801. proto.isTianHu = function (shoupai,PGPai,chengju) {
  2802. // console.error("是否天胡 "+" chuPaiCountTL "+this.chuPaiCountTL+" this.sbyBDList.length "+this.sbyBDList.length);
  2803. return this.chuPaiCountTL == 0 && this.getBDCount(shoupai) == 4;
  2804. }
  2805. // 获得奖码列表和计算奖码分数函数
  2806. proto.getJiangmaInfo = function () {
  2807. // console.warn("获得奖码列表函数 奖码类型:-1:不奖码,1:159奖码,2:摸几奖几,3:一码全中 "+this.jiangmaType)
  2808. let jiangmaList = []
  2809. let jmzs = this.jiangmaCount;//奖码张数
  2810. let castC1 = this.castCount;//已经消耗的
  2811. let lastC1 = this.lastCount;
  2812. for (var i = 0; i < jmzs; i++) {
  2813. let card = 0;
  2814. if (lastC1 > 0) {
  2815. card = this.cardsPool[castC1++];
  2816. lastC1 -= 1;
  2817. }
  2818. if(card > 0) jiangmaList[i] = card;
  2819. else break;
  2820. }
  2821. let startNum1 = 0;/////骰子1的点数
  2822. let startNum2 = 0;/////骰子2的点数
  2823. if(jiangmaList.length < jmzs){
  2824. //抓鸟牌时牌堆剩余牌张数不足的时候通过掷骰子来凑数
  2825. startNum1 = this.dice();/////骰子1的点数
  2826. startNum2 = this.dice();/////骰子2的点数
  2827. }
  2828. // console.warn("获得奖码列表函数 奖码列表 ",jiangmaList," 长度 ",jiangmaList.length," addThisIsHu ",this.addThisIsHu)
  2829. //下面是计算奖码分数
  2830. let mafen = 0;
  2831. return { jiangmaList:jiangmaList,mafen:mafen,startNum1:startNum1,startNum2:startNum2}
  2832. };
  2833. //得到本局的各个玩家的中鸟个数
  2834. proto.getBJGWJZBGS = function (chairId,jiangmaList,diceNum1,diceNum2,lead,yjList) {
  2835. // console.warn("每个玩家中鸟个数 chairId " , chairId,jiangmaList,diceNum1,diceNum2,lead,JSON.stringify(yjList));
  2836. let tzdsfbqk = [0,0,0,0];//点数分布情况
  2837. if(jiangmaList.length == 0){
  2838. let dices = diceNum1;
  2839. if(dices == 1 || dices == 5) tzdsfbqk[0]++;
  2840. else if(dices == 2 || dices == 6) tzdsfbqk[1]++;
  2841. else if(dices == 3) tzdsfbqk[2]++;
  2842. else if(dices == 4) tzdsfbqk[3]++;
  2843. let dices2 = diceNum2;
  2844. if(dices2 == 1 || dices2 == 5) tzdsfbqk[0]++;
  2845. else if(dices2 == 2 || dices2 == 6) tzdsfbqk[1]++;
  2846. else if(dices2 == 3) tzdsfbqk[2]++;
  2847. else if(dices2 == 4) tzdsfbqk[3]++;
  2848. }
  2849. else if(jiangmaList.length == 1){
  2850. let dices = diceNum1+diceNum2;
  2851. if(dices == 5 || dices == 9) tzdsfbqk[0]++;
  2852. else if(dices == 2 || dices == 6 || dices == 10) tzdsfbqk[1]++;
  2853. else if(dices == 3 || dices == 7 || dices == 11) tzdsfbqk[2]++;
  2854. else if(dices == 4 || dices == 8 || dices == 12) tzdsfbqk[3]++;
  2855. let cardValue = this.getValue(jiangmaList[0])
  2856. if(cardValue == 1 || cardValue == 5 || cardValue == 9) tzdsfbqk[0]++;
  2857. else if(cardValue == 2 || cardValue == 6) tzdsfbqk[1]++;
  2858. else if(cardValue == 3 || cardValue == 7) tzdsfbqk[2]++;
  2859. else if(cardValue == 4 || cardValue == 8) tzdsfbqk[3]++;
  2860. }
  2861. else if(jiangmaList.length == 2){
  2862. for (var i = 0; i < jiangmaList.length; i++) {
  2863. let cardValue = this.getValue(jiangmaList[i])
  2864. if(cardValue == 1 || cardValue == 5 || cardValue == 9) tzdsfbqk[0]++;
  2865. else if(cardValue == 2 || cardValue == 6) tzdsfbqk[1]++;
  2866. else if(cardValue == 3 || cardValue == 7) tzdsfbqk[2]++;
  2867. else if(cardValue == 4 || cardValue == 8) tzdsfbqk[3]++;
  2868. }
  2869. }
  2870. // let result = [];
  2871. // if(this.playerAllCount == 2) result = [0,0];
  2872. // else if(this.playerAllCount == 3) result = [0,0,0];
  2873. // else if(this.playerAllCount == 4) result = [0,0,0,0];
  2874. // let cell = this.qshuTypeTL[qshType][1] || 0;
  2875. // console.warn("每个玩家中鸟个数000==== tzdsfbqk " + tzdsfbqk);
  2876. let everyZNGS = [0,0,0,0];//每个玩家中鸟个数
  2877. if(this.playerAllCount == 2){
  2878. if(chairId == 0) everyZNGS = [tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[3]];
  2879. else if(chairId == 1) everyZNGS = [tzdsfbqk[1],tzdsfbqk[0],tzdsfbqk[2],tzdsfbqk[3]];
  2880. }
  2881. else if(this.playerAllCount == 3){
  2882. if(chairId == 0) everyZNGS = [tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[3]];
  2883. else if(chairId == 1) everyZNGS = [tzdsfbqk[2],tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[3]];
  2884. else if(chairId == 2) everyZNGS = [tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[0],tzdsfbqk[3]];
  2885. }
  2886. else if(this.playerAllCount == 4){
  2887. if(chairId == 0) everyZNGS = [tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[3]];
  2888. else if(chairId == 1) everyZNGS = [tzdsfbqk[3],tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[2]];
  2889. else if(chairId == 2) everyZNGS = [tzdsfbqk[2],tzdsfbqk[3],tzdsfbqk[0],tzdsfbqk[1]];
  2890. else if(chairId == 3) everyZNGS = [tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[3],tzdsfbqk[0]];
  2891. }
  2892. // console.warn("每个玩家中鸟个数111==== everyZNGS " + everyZNGS);
  2893. if(lead != -1){
  2894. for (var i = 0; i < everyZNGS.length; i++) {
  2895. if(chairId == lead){
  2896. //自己是抓鸟者又是点炮者,说明自己是一炮多响了
  2897. //一炮多响的时候,不是赢家也不是点炮者不中鸟
  2898. if (yjList.indexOf(i) == -1 && i != lead) everyZNGS[i] = 0;
  2899. }
  2900. else{
  2901. //正常的点炮,不是点炮者也不是赢家就不中鸟了
  2902. if(i != chairId && i != lead) everyZNGS[i] = 0;
  2903. }
  2904. }
  2905. }
  2906. // console.warn("每个玩家中鸟个数222==== everyZNGS " + everyZNGS);
  2907. return everyZNGS;
  2908. }
  2909. //得到起手胡牌型的总分
  2910. proto.getQSHFen = function (chairID) {
  2911. // console.error("得到起手胡牌型的总分 "+chairID+" "+this.everyXiaoHuList[chairID]+" cd "+this.everyXiaoHuList[chairID].length);
  2912. let count = 0;
  2913. for (var i = 0; i < this.everyXiaoHuList[chairID].length; i++) {
  2914. let zl = this.everyXiaoHuList[chairID][i];
  2915. count+=this.qshuTypeTL[zl][1];
  2916. }
  2917. return count;
  2918. };
  2919. //得到本次起手/中途胡牌型的各个玩家的输赢
  2920. proto.getBCQSHSY = function (chairId,qshType,diceNum1,diceNum2) {
  2921. let result = [];
  2922. if(this.playerAllCount == 2) result = [0,0];
  2923. else if(this.playerAllCount == 3) result = [0,0,0];
  2924. else if(this.playerAllCount == 4) result = [0,0,0,0];
  2925. let cell = this.qshuTypeTL[qshType][1] || 0;
  2926. let dices = [diceNum1,diceNum2];
  2927. let tzdsfbqk = [0,0,0,0];//骰子点数分布情况
  2928. for (var i = 0; i < dices.length; i++) {
  2929. if(dices[i] == 1 || dices[i] == 5) tzdsfbqk[0]++;
  2930. else if(dices[i] == 2 || dices[i] == 6) tzdsfbqk[1]++;
  2931. else if(dices[i] == 3) tzdsfbqk[2]++;
  2932. else if(dices[i] == 4) tzdsfbqk[3]++;
  2933. }
  2934. let everyZNGS = [0,0,0,0];//每个玩家中鸟个数
  2935. if(this.playerAllCount == 2){
  2936. if(chairId == 0) everyZNGS = [tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[3]];
  2937. else if(chairId == 1) everyZNGS = [tzdsfbqk[1],tzdsfbqk[0],tzdsfbqk[2],tzdsfbqk[3]];
  2938. }
  2939. else if(this.playerAllCount == 3){
  2940. if(chairId == 0) everyZNGS = [tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[3]];
  2941. else if(chairId == 1) everyZNGS = [tzdsfbqk[2],tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[3]];
  2942. else if(chairId == 2) everyZNGS = [tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[0],tzdsfbqk[3]];
  2943. }
  2944. else if(this.playerAllCount == 4){
  2945. if(chairId == 0) everyZNGS = [tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[3]];
  2946. else if(chairId == 1) everyZNGS = [tzdsfbqk[3],tzdsfbqk[0],tzdsfbqk[1],tzdsfbqk[2]];
  2947. else if(chairId == 2) everyZNGS = [tzdsfbqk[2],tzdsfbqk[3],tzdsfbqk[0],tzdsfbqk[1]];
  2948. else if(chairId == 3) everyZNGS = [tzdsfbqk[1],tzdsfbqk[2],tzdsfbqk[3],tzdsfbqk[0]];
  2949. }
  2950. let bsList = [1,2,4];//分表表示中0,1,2鸟输1,2,4倍
  2951. for (let i = 0; i < this.playerAllCount; ++i) {
  2952. if(i == chairId) continue;
  2953. let gs = everyZNGS[i]+everyZNGS[chairId];
  2954. let sy = bsList[gs] * cell;
  2955. result[i] -= sy;
  2956. result[chairId] += sy;
  2957. }
  2958. // console.warn("每个玩家中鸟个数==== tzdsfbqk "+tzdsfbqk + " everyZNGS " + everyZNGS+" result "+result);
  2959. // for (var i = 0; i < result.length; i++) {
  2960. // if(everyZNGS[i] == 0) result = cell;
  2961. // else if(everyZNGS[i] == 1) result = cell*2;
  2962. // else if(everyZNGS[i] == 2) result = cell*4;
  2963. // }
  2964. return result;
  2965. }
  2966. //得到大胡牌型的总分
  2967. proto.getDaHuFen = function (chairID) {
  2968. let count = 0;
  2969. for (var i = 0; i < this.everyDAHType[chairID].length; i++) {
  2970. if(this.everyDAHType[chairID][i] == 1) count+=this.dahuTypeTL[i][1];
  2971. }
  2972. if(count == 0) count = 2;
  2973. return count;
  2974. };
  2975. //得到大胡牌型的总分2
  2976. proto.getDaHuFen2 = function (chairID,typeList) {
  2977. let count = 0;
  2978. for (var i = 0; i < typeList.length; i++) {
  2979. if(typeList[i] == 1) count+=this.dahuTypeTL[i][1];
  2980. }
  2981. if(count == 0) count = 2;
  2982. return count;
  2983. };
  2984. //得到点炮者
  2985. proto.getLead = function (chairID,lead,yjList) {
  2986. let res = -100;
  2987. if(chairID != -1){
  2988. let yjgs = yjList.length
  2989. if(yjgs > 1){
  2990. res = chairID;
  2991. }
  2992. else if(yjgs == 1){
  2993. if(yjList[0] == chairID){
  2994. res = -1;
  2995. }
  2996. else{
  2997. res = chairID;
  2998. }
  2999. }
  3000. else if(yjgs == 0){
  3001. res = -1;
  3002. }
  3003. }
  3004. if(res == -100) res = lead;
  3005. return res;
  3006. }