诸暨麻将添加redis
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

1916 lignes
59 KiB

  1. #include "stdafx.h"
  2. #include "TableFrameSinkPoker.h"
  3. #include "消息定义/CMD_Poker_Sparrow.h"
  4. #define MyZeroMemory(x) ZeroMemory(x,sizeof(x))
  5. CTableFrameSinkPoker::CTableFrameSinkPoker()
  6. {
  7. m_pITableFrame = NULL;
  8. m_pGameServiceOption = NULL;
  9. memset(&m_gameConfig, 0, sizeof(CMD_S_GameConfig_Poker));
  10. m_cbPlayerNum = GAME_PLAYER;
  11. m_cbCardNum = FULL_COUNT_Poker;
  12. // // 用户状态
  13. ZeroMemory(m_cbOffline, sizeof(m_cbOffline));//是否断线 0正常 1断线
  14. ZeroMemory(m_cbTrustee, sizeof(m_cbTrustee));//是否托管 0正常 1托管
  15. ZeroMemory(m_cbTimeOutCount, sizeof(m_cbTimeOutCount));//超时次数 连续两次触发托管
  16. // // 玩家分数
  17. //16局积分
  18. ZeroMemory(m_lGameTatolScore, sizeof(m_lGameTatolScore));
  19. //流水详情
  20. MyZeroMemory(m_HuPaiLiuShui);
  21. // 游戏回放
  22. m_bReplayRecordStart = false;
  23. m_UserReplayRecord.clear();
  24. // 单局变量
  25. MyZeroMemory(m_GameScore);//本局总积分
  26. MyZeroMemory(m_lGameGongXianScore);//本局贡献分
  27. MyZeroMemory(m_lGameAwardScore);//本局双扣基础分
  28. m_wBankerUser = INVALID_CHAIR;//庄家用户
  29. MyZeroMemory(m_bTrustee);
  30. m_bSwitchChair = false;//交换位置
  31. MyZeroMemory(m_wSourceID);//原始ID
  32. MyZeroMemory(m_wTargetID);//目标ID
  33. MyZeroMemory(m_bResponse);//用户反馈
  34. m_wCurrentUser = INVALID_CHAIR;
  35. m_wCurrentOperate = INVALID_CHAIR;
  36. m_cbStartRandCard = 0xff;
  37. m_cbTurnCardCount = 0;
  38. m_wWinCount = 0;
  39. m_wWinOrder[0] = 255;
  40. m_wWinOrder[1] = 255;
  41. m_wWinOrder[2] = 255;
  42. m_wWinOrder[3] = 255;
  43. MyZeroMemory(m_BomoCouut);
  44. //输赢情况
  45. MyZeroMemory(m_winLoseCount);
  46. m_lastLianxianInfo = 0;
  47. MyZeroMemory(&m_struOutCard);
  48. MyZeroMemory(m_cbJokerReplacePoker);
  49. MyZeroMemory(m_BoomCountInfo);
  50. }
  51. CTableFrameSinkPoker::~CTableFrameSinkPoker()
  52. {
  53. }
  54. void * CTableFrameSinkPoker::QueryInterface(const IID & Guid, DWORD dwQueryVer)
  55. {
  56. if ((Guid == IID_ITableFrameSink) && (InterfaceVersionCompare(dwQueryVer, VER_ITableFrameSinkZhiPai)))
  57. return static_cast<ITableFrameSink *>(this);
  58. QUERYINTERFACE(ITableUserAction, Guid, dwQueryVer);
  59. if ((Guid == IID_IUnknownEx) && (InterfaceVersionCompare(dwQueryVer, VER_IUnknownEx)))
  60. return static_cast<IUnknownEx *>(static_cast<ITableFrameSink *>(this));
  61. return NULL;
  62. }
  63. bool CTableFrameSinkPoker::Initialization(IUnknownEx * pIUnknownEx)
  64. {
  65. //查询接口
  66. ASSERT(pIUnknownEx != NULL);
  67. m_pITableFrame = QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx, ITableFrame);
  68. if (m_pITableFrame == NULL)
  69. return false;
  70. //获取参数
  71. m_pGameServiceOption = m_pITableFrame->GetGameServiceOption();
  72. ASSERT(m_pGameServiceOption != NULL);
  73. //开始模式
  74. m_pITableFrame->SetStartMode(START_MODE_FULL_READY);
  75. return true;
  76. }
  77. //复位桌子
  78. VOID CTableFrameSinkPoker::RepositionSink()
  79. {
  80. // // 用户状态
  81. ZeroMemory(m_cbOffline, sizeof(m_cbOffline));//是否断线 0正常 1断线
  82. ZeroMemory(m_cbTrustee, sizeof(m_cbTrustee));//是否托管 0正常 1托管
  83. ZeroMemory(m_cbTimeOutCount, sizeof(m_cbTimeOutCount));//超时次数 连续两次触发托管
  84. //游戏回放
  85. m_bReplayRecordStart = false;
  86. // 单局变量
  87. MyZeroMemory(m_GameScore);//本局总积分
  88. MyZeroMemory(m_lGameGongXianScore);//本局贡献分
  89. MyZeroMemory(m_lGameAwardScore);//本局双扣基础分
  90. m_wBankerUser = INVALID_CHAIR;//庄家用户
  91. MyZeroMemory(m_bTrustee);
  92. m_bSwitchChair = false;//交换位置
  93. MyZeroMemory(m_wSourceID);//原始ID
  94. MyZeroMemory(m_wTargetID);//目标ID
  95. MyZeroMemory(m_bResponse);//用户反馈
  96. m_wCurrentUser = INVALID_CHAIR;
  97. m_wCurrentOperate = INVALID_CHAIR;
  98. m_cbStartRandCard = 0xff;
  99. m_cbTurnCardCount = 0;
  100. m_wWinCount = 0;
  101. m_wWinOrder[0] = 255;
  102. m_wWinOrder[1] = 255;
  103. m_wWinOrder[2] = 255;
  104. m_wWinOrder[3] = 255;
  105. MyZeroMemory(m_BomoCouut);
  106. m_lastLianxianInfo = 0;
  107. MyZeroMemory(&m_struOutCard);
  108. MyZeroMemory(m_cbJokerReplacePoker);
  109. m_listOutCard.clear();
  110. MyZeroMemory(m_BoomCountInfo);
  111. }
  112. void CTableFrameSinkPoker::DeletePrivateTable(bool bSendState /*= false*/)
  113. {
  114. tagScoreInfo ScoreInfoArray[GAME_PLAYER];
  115. ZeroMemory(&ScoreInfoArray, sizeof(ScoreInfoArray));
  116. WORD wChairCount = m_pITableFrame->GetChairCount();
  117. for (int i = 0; i < wChairCount; ++i)
  118. {
  119. IServerUserItem *pIUserItem = m_pITableFrame->GetTableUserItem(i);
  120. if (pIUserItem == NULL)
  121. continue;
  122. ScoreInfoArray[i].cbType = SCORE_TYPE_END;
  123. ScoreInfoArray[i].lScore = 0; //记录临时分
  124. }
  125. m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray));
  126. ConcludeGame(GAME_STATUS_DELETE, bSendState);
  127. m_pITableFrame->DeletePrivateTableNow();
  128. }
  129. bool CTableFrameSinkPoker::OnActionUserConnect(WORD wChairID, IServerUserItem * pIServerUserItem)
  130. {
  131. //TRACE("断线重连 wChairID = %d \n", wChairID);
  132. if (wChairID >= m_cbCardNum) return false;
  133. m_cbOffline[wChairID] = 1;
  134. return true;
  135. }
  136. //用户坐下
  137. bool CTableFrameSinkPoker::OnActionUserSitDown(WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
  138. {
  139. return TRUE;
  140. }
  141. //用户起来
  142. bool CTableFrameSinkPoker::OnActionUserStandUp(WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
  143. {
  144. //庄家设置
  145. if (bLookonUser == false && !QueryUseTemporaryScore())
  146. {
  147. m_cbTrustee[wChairID] = false;
  148. //托管广播
  149. CMD_C_Trustee_SK Trustee = { 0 };
  150. Trustee.cbTrustee = 0;
  151. Trustee.wChairID = wChairID;
  152. RepayRecord(INVALID_CHAIR, SUB_S_TRUSTEE_Poker, &Trustee, sizeof(Trustee));
  153. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_TRUSTEE_Poker, &Trustee, sizeof(Trustee));
  154. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_TRUSTEE_Poker, &Trustee, sizeof(Trustee));
  155. }
  156. return true;
  157. }
  158. bool CTableFrameSinkPoker::OnActionUserOnReady(WORD wChairID, IServerUserItem * pIServerUserItem, void * pData, WORD wDataSize)
  159. {
  160. return true;
  161. }
  162. //游戏中途旁观进入
  163. bool CTableFrameSinkPoker::PerformLookonLogin(IServerUserItem * pIServerUserItem)
  164. {
  165. CMD_S_PangGuan_Poler StatusPlay = { 0 };
  166. CopyMemory(&StatusPlay.gameConfig, &m_gameConfig, sizeof(CMD_S_GameConfig));
  167. CopyMemory(StatusPlay.lUserTmpScore, m_lGameTatolScore, sizeof(m_lGameTatolScore));
  168. StatusPlay.gameConfig.IsOwner = m_pITableFrame->GetPrivateTableOwnerID() == pIServerUserItem->GetUserID() ? 1 : 0;
  169. StatusPlay.GameStatus = m_pITableFrame->IsDrawStarted();
  170. if (StatusPlay.GameStatus)
  171. {
  172. //发送场景
  173. StatusPlay.wBankerUser = m_wBankerUser;
  174. StatusPlay.wCurrentUser = m_wCurrentUser;
  175. StatusPlay.cbCurrPlayCount = m_gameConfig.wHadPlayCount;
  176. StatusPlay.cbTotaPlayCount = m_gameConfig.wPlayCountRule;
  177. StatusPlay.leftOptTime = 0;
  178. int tmpUser = m_wCurrentUser;
  179. for (BYTE i = 0; i < m_cbPlayerNum; i++)
  180. {
  181. tmpUser = (tmpUser - 1) % m_cbPlayerNum;
  182. if (tmpUser < 0) tmpUser += m_cbPlayerNum;
  183. if (tmpUser == m_wCurrentUser)
  184. continue;
  185. if (m_cbResponse[tmpUser] == 1)
  186. StatusPlay.cbOtherOperate[tmpUser] = OPERATE_MASK_PASS_Poker;
  187. else if (m_cbResponse[tmpUser] == 2)
  188. {
  189. StatusPlay.cbCardType = m_struOutCard.cbOutCardType;
  190. StatusPlay.cbOtherOperate[tmpUser] = OPERATE_MASK_OUT_Poker;
  191. std::list<OutCard>::reverse_iterator rIt;
  192. for (rIt = m_listOutCard.rbegin(); rIt != m_listOutCard.rend(); rIt++)
  193. {
  194. if (rIt->wOutCardUser == tmpUser)
  195. {
  196. memcpy(StatusPlay.cbOutCardData[tmpUser], rIt->cbOutCardData, MAX_COUNT_Poker*sizeof(BYTE));
  197. break;
  198. }
  199. }
  200. }
  201. }
  202. StatusPlay.cbCardType = m_wCurrentOperate;
  203. StatusPlay.cbDiscardType = m_struOutCard.cbOutCardType;
  204. CopyMemory(StatusPlay.cbReplaceCard, m_cbJokerReplacePoker, sizeof(m_cbJokerReplacePoker));
  205. //扑克数目、玩家手牌
  206. for (BYTE i = 0; i < m_cbPlayerNum; i++)
  207. {
  208. StatusPlay.cbCardCount[i] = m_cbCardDataCount[i];
  209. StatusPlay.cbRankIndex[i] = m_wWinOrder[i];
  210. StatusPlay.cbTrusteeStatus[i] = m_cbTrustee[i];
  211. StatusPlay.UserGongXianScore[i] = m_lGameGongXianScore[i];
  212. memset(StatusPlay.cbCardData[i], 0xff, StatusPlay.cbCardCount[i]);
  213. }
  214. StatusPlay.LeftMinPokerVal = m_cbStartRandCard;
  215. }
  216. CString strOut;
  217. strOut.Format(L"局数 [%d/%d] 扑克数目[%d %d %d %d] 随机牌[%x] 当前积分[%d %d %d %d] 贡献分 [%d %d %d %d]",
  218. StatusPlay.cbCurrPlayCount, StatusPlay.cbTotaPlayCount,
  219. StatusPlay.cbCardCount[0], StatusPlay.cbCardCount[1], StatusPlay.cbCardCount[2], StatusPlay.cbCardCount[3],
  220. StatusPlay.LeftMinPokerVal,
  221. StatusPlay.lUserTmpScore[0], StatusPlay.lUserTmpScore[1], StatusPlay.lUserTmpScore[2], StatusPlay.lUserTmpScore[3],
  222. StatusPlay.UserGongXianScore[0], StatusPlay.UserGongXianScore[1], StatusPlay.UserGongXianScore[2], StatusPlay.UserGongXianScore[3]);
  223. return m_pITableFrame->SendUserItemData(pIServerUserItem, SUB_S_PANGGUAN, &StatusPlay, sizeof(StatusPlay));
  224. }
  225. void CTableFrameSinkPoker::SetGameConfig(VOID * pDataBuffer, WORD wDataSize, std::wstring sPrivateRoomId)
  226. {
  227. //TRACE("游戏配置设置 \n");
  228. memset(&m_gameConfig, 0, sizeof(CMD_S_GameConfig_Poker));
  229. CMD_S_GameConfig_Poker* ppConfig = (CMD_S_GameConfig_Poker*)pDataBuffer;
  230. CopyMemory(&m_gameConfig, ppConfig, sizeof(CMD_S_GameConfig_Poker));
  231. m_gameConfig.wHadPlayCount = 0;
  232. m_GameLogic.SetMagicType(m_gameConfig.bDuoLai);
  233. m_cbPlayerNum = m_gameConfig.PeoplesNum;
  234. m_cbCardNum = FULL_COUNT_Poker;
  235. m_pITableFrame->SetChairCount(m_cbPlayerNum);
  236. }
  237. //翻牌换桌
  238. void CTableFrameSinkPoker::SwapSeat()
  239. {
  240. BOOL bSwitch = FALSE;
  241. FindCardOwner(bSwitch);
  242. if (bSwitch==FALSE)
  243. {
  244. return;
  245. }
  246. //队友换桌,对面
  247. IServerUserItem *pIServerUserItem = m_pITableFrame->GetTableUserItem(m_wSourceID[0]);
  248. pIServerUserItem->SetChairID(m_wSourceID[1]);
  249. pIServerUserItem = m_pITableFrame->GetTableUserItem(m_wSourceID[1]);
  250. pIServerUserItem->SetChairID(m_wSourceID[0]);
  251. m_pITableFrame->SwapChair();
  252. //换手牌,总积分,流水详情
  253. swap(m_cbCardData[m_wSourceID[0]], m_cbCardData[m_wSourceID[1]]);
  254. // CString outFen2 = _T("变换前的分数 ");
  255. // for (int i = 0; i < 4; i++)
  256. // {
  257. // CString TMP;
  258. // TMP.Format(_T(" %d "), m_lGameTatolScore[i]);
  259. // outFen2 += TMP;
  260. // }
  261. // OutputDebugString(outFen2);
  262. //换总积分
  263. int lGameScore = m_lGameTatolScore[m_wSourceID[0]];
  264. m_lGameTatolScore[m_wSourceID[0]] = m_lGameTatolScore[m_wSourceID[1]];
  265. m_lGameTatolScore[m_wSourceID[1]] = lGameScore;
  266. // CString outFen;
  267. // outFen = _T("变换后的分数 ");
  268. // for (int i = 0; i < 4;i++)
  269. // {
  270. // CString TMP;
  271. // TMP.Format(_T(" %d "), m_lGameTatolScore[i]);
  272. // outFen += TMP;
  273. // }
  274. // OutputDebugString(outFen);
  275. //
  276. // 换流水 和
  277. for (BYTE i = 0; i < (m_gameConfig.wHadPlayCount - 1); i++)
  278. {
  279. lGameScore = m_HuPaiLiuShui[i * m_cbPlayerNum + m_wSourceID[0]];
  280. m_HuPaiLiuShui[i * m_cbPlayerNum + m_wSourceID[0]] = m_HuPaiLiuShui[i * m_cbPlayerNum + m_wSourceID[1]];
  281. m_HuPaiLiuShui[i * m_cbPlayerNum + m_wSourceID[1]] = lGameScore;
  282. }
  283. // 输赢次数
  284. int wins = 0;
  285. wins = m_winLoseCount[m_wSourceID[0]];
  286. m_winLoseCount[m_wSourceID[0]] = m_winLoseCount[ m_wSourceID[0]];
  287. m_winLoseCount[m_wSourceID[1]] = wins;
  288. }
  289. bool CTableFrameSinkPoker::OnUserHint(WORD wChairID)
  290. {
  291. if (m_wCurrentUser != wChairID)
  292. return false;
  293. if (m_cbCurrentHintNum + 1 > m_cbHintNum)
  294. m_cbCurrentHintNum = 0;
  295. TRACE("用户出牌提示 wChairID = %d m_cbCurrentHintNum = %d m_cbHintNum = %d \n", wChairID, m_cbCurrentHintNum, m_cbHintNum);
  296. // CString strBuffer;
  297. // strBuffer.Format(L"用户出牌提示 wChairID = %d m_cbCurrentHintNum = %d m_cbHintNum = %d ", wChairID, m_cbCurrentHintNum, m_cbHintNum);
  298. // OutputDebugString(strBuffer);
  299. //提示结果
  300. CMD_S_Hint_Result_Poker HintResult = { 0 };
  301. memcpy(HintResult.cbHintCardData, mHistList[m_cbCurrentHintNum].cbHintLogicCardData, MAX_COUNT_Poker*sizeof(BYTE));
  302. HintResult.cbCardType = mHistList[m_cbCurrentHintNum].cbCardType;
  303. //特殊处理 将所有 1 2 转换成14 15
  304. for (int i = 0; i < MAX_COUNT_Poker;i++)
  305. {
  306. if (HintResult.cbHintCardData[i]==0)
  307. {
  308. break;
  309. }
  310. if (HintResult.cbHintCardData[i]<=2)
  311. {
  312. HintResult.cbHintCardData[i] = m_GameLogic.GetCardLogicValue(HintResult.cbHintCardData[i]);
  313. }
  314. }
  315. PrintCards(HintResult.cbHintCardData, MAX_COUNT_Poker);
  316. m_pITableFrame->SendTableData(wChairID, SUB_S_HINT_RESULT, &HintResult, sizeof(HintResult));
  317. m_cbCurrentHintNum++;
  318. return true;
  319. }
  320. bool CTableFrameSinkPoker::OnEventGameStart()
  321. {
  322. TRACE("游戏开始 \n");
  323. m_pITableFrame->SetGameStatus(GS_MJ_PLAY);
  324. m_gameConfig.wHadPlayCount++;
  325. //开始记录回放数据
  326. RepayRecordStart();
  327. //混乱扑克
  328. WORD wRoomId = m_gameConfig.RoomId;
  329. m_GameLogic.RandCardList(m_cbRepertoryCard, CountArray(m_cbRepertoryCard), m_gameConfig.tmp2, wRoomId);
  330. ReadGameData();
  331. //////////////////////////////////////////////////////////////////////////
  332. {
  333. m_cbLeftCardCount = FULL_COUNT_Poker;
  334. //发牌
  335. for (BYTE i = 0; i < m_cbPlayerNum; i++)
  336. {
  337. m_cbCardDataCount[i] = MAX_COUNT_Poker;
  338. CopyMemory(&m_cbCardData[i], &(m_cbRepertoryCard[i*m_cbCardDataCount[i]]), MAX_COUNT_Poker);
  339. }
  340. }
  341. //////////////////////////////////////////////////////////////////////////
  342. // //发送数据
  343. // OutputDebugString(_T("洗牌后4个玩家的数据输出"));
  344. //
  345. // for (int i = 0; i < m_cbPlayerNum;i++)
  346. // {
  347. // PrintCards(m_cbCardData[i], MAX_COUNT_Poker);
  348. // }
  349. // OutputDebugString(_T("洗牌后4个玩家的数据输出End"));
  350. //随机取一张牌
  351. BYTE cbRandData = m_cbRepertoryCard[rand() % FULL_COUNT_Poker];
  352. m_cbStartRandCard = cbRandData;
  353. SwapSeat();
  354. for (int i = 0; i < 4; i++)
  355. {
  356. PrintCards(m_cbCardData[i], m_cbCardDataCount[i]);
  357. }
  358. //排列扑克
  359. for (WORD i = 0; i < GAME_PLAYER; i++)
  360. {
  361. m_GameLogic.SortCardList(m_cbCardData[i], m_cbCardDataCount[i], ST_ORDER);
  362. }
  363. for (int i = 0; i < 4; i++)
  364. {
  365. PrintCards(m_cbCardData[i], m_cbCardDataCount[i]);
  366. }
  367. //游戏变量
  368. m_wTurnWiner = INVALID_CHAIR;
  369. m_wCurrentUser = m_wBankerUser;
  370. CMD_S_GameStart_SK GameStart;
  371. ZeroMemory(&GameStart, sizeof(GameStart));
  372. GameStart.wCurrentUser = m_wCurrentUser;
  373. //交换位置
  374. for (INT i = 0; i < GAME_PLAYER; i++){
  375. IServerUserItem * pIServerUserItem = m_pITableFrame->GetTableUserItem(i);
  376. m_unUserID[i] = pIServerUserItem->GetUserID();
  377. }
  378. // CString strUserID;
  379. // for (int i = 0; i < m_cbPlayerNum;i++)
  380. // {
  381. // CString tmp;
  382. // tmp.Format(_T("wchaid=%d userid=%d \r\n"),i,m_unUserID[i]);
  383. // strUserID += tmp;
  384. // }
  385. // OutputDebugString(strUserID);
  386. for (int i = 0; i < m_cbPlayerNum;i++)
  387. {
  388. GameStart.lCellScore[i] = m_lGameTatolScore[i];
  389. }
  390. ZeroMemory(GameStart.cbPartnerCardData, MAX_COUNT_Poker);
  391. GameStart.bTrustee = false;
  392. GameStart.cbStartRandCard = m_cbStartRandCard;
  393. CopyMemory(GameStart.userSortID, m_unUserID, sizeof(m_unUserID));
  394. GameStart.cbCurrPlay = (BYTE)m_gameConfig.wHadPlayCount;
  395. ZeroMemory(GameStart.cbCardData, GAME_PLAYER*MAX_COUNT_Poker);
  396. for (int i = 0; i < m_cbPlayerNum;i++)
  397. {
  398. CopyMemory(GameStart.cbCardData[i], m_cbCardData[i], MAX_COUNT_Poker);
  399. }
  400. RepayRecord(INVALID_CHAIR, SUB_S_GAME_START_Poker, &GameStart, sizeof(GameStart));
  401. for (int i = 0; i < m_cbPlayerNum;i++)
  402. {
  403. ZeroMemory(GameStart.cbCardData, GAME_PLAYER*MAX_COUNT_Poker);
  404. CopyMemory(GameStart.cbCardData[i], m_cbCardData[i], MAX_COUNT_Poker);
  405. m_pITableFrame->SendTableData(i, SUB_S_GAME_START_Poker, &GameStart, sizeof(GameStart));
  406. }
  407. ZeroMemory(GameStart.cbCardData, sizeof(GameStart.cbCardData));//用户回放
  408. //清手牌 旁观只能发一次
  409. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_START_Poker, &GameStart, sizeof(GameStart));
  410. m_wCurrentOperate = OPERATE_MASK_OUT_Poker | OPERATE_MASK_HINT_Poker;
  411. m_GameLogic.FindAllHit(m_cbCardData[m_wCurrentUser], m_cbCardDataCount[m_wCurrentUser], mHistList);
  412. m_cbHintNum = mHistList.size();
  413. return TRUE;
  414. }
  415. //游戏消息处理
  416. bool CTableFrameSinkPoker::OnGameMessage(WORD wSubCmdID, VOID * pDataBuffer, WORD wDataSize, IServerUserItem * pIServerUserItem)
  417. {
  418. WORD wChairId = pIServerUserItem->GetChairID();
  419. // CString str;
  420. // str.Format(_T("OnGameMessage wSubCmdID =%d"), wSubCmdID);
  421. // OutputDebugString(str);
  422. switch (wSubCmdID){
  423. case SUB_C_OPERATE_CALLBACK_Poker:{
  424. //用户操作 出牌/ 过 / 要不起
  425. //效验消息
  426. ASSERT(wDataSize == sizeof(struct CMD_C_OPERATE_CALLBACK_SK ));
  427. if (wDataSize != sizeof(CMD_C_OPERATE_CALLBACK_SK))
  428. return false;
  429. //消息处理
  430. CMD_C_OPERATE_CALLBACK_SK * pOperateCallback = (CMD_C_OPERATE_CALLBACK_SK *)pDataBuffer;
  431. bool ret = OnUserOperate(wChairId, pOperateCallback);
  432. // if (ret)
  433. // {
  434. // OutputDebugString(_T("OnUserOperate Ret True"));
  435. // }
  436. // else{
  437. // OutputDebugString(_T("OnUserOperate Ret False"));
  438. // }
  439. return ret;
  440. break;
  441. }
  442. //用户托管
  443. case SUB_C_TRUSTEE_Poker:{
  444. //效验消息
  445. ASSERT(wDataSize == sizeof(CMD_C_Trustee));
  446. if (wDataSize != sizeof(CMD_C_Trustee))
  447. return false;
  448. CMD_C_Trustee *pTrustee = (CMD_C_Trustee *)pDataBuffer;
  449. m_cbTrustee[wChairId] = pTrustee->bTrustee;
  450. m_cbTimeOutCount[wChairId] = 0;
  451. //托管广播
  452. CMD_S_Trustee_Poler Trustee = { 0 };
  453. Trustee.cbTrustee = pTrustee->bTrustee;
  454. Trustee.wChairID = wChairId;
  455. RepayRecord(INVALID_CHAIR, SUB_S_TRUSTEE_Poker, &Trustee, sizeof(Trustee));
  456. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_TRUSTEE_Poker, &Trustee, sizeof(Trustee));
  457. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_TRUSTEE_Poker, &Trustee, sizeof(Trustee));
  458. TRACE("用户托管 %d 是否托管 %d \n", wChairId, pTrustee->bTrustee);
  459. //当前玩家托管、立刻响应
  460. if (m_cbTrustee[wChairId])
  461. {
  462. if (m_wCurrentUser == wChairId)
  463. return TrusteeOut(wChairId);
  464. }
  465. else if (m_cbTrustee[wChairId] == 0 && m_wCurrentUser == wChairId)
  466. {
  467. //m_pITableFrame->KillGameTimer(17);
  468. //m_pITableFrame->KillGameTimer(18);
  469. }
  470. return true;
  471. break;
  472. }
  473. }
  474. return true;
  475. }
  476. bool CTableFrameSinkPoker::OnFrameMessage(WORD wSubCmdID, VOID * pDataBuffer, WORD wDataSize, IServerUserItem * pIServerUserItem)
  477. {
  478. return false;
  479. }
  480. bool CTableFrameSinkPoker::OnEventSendGameScene(WORD wChiarID, IServerUserItem * pIServerUserItem, BYTE cbGameStatus, bool bSendSecret)
  481. {
  482. // CString str;
  483. // str.Format(L"OnEventSendGameScene wChiarID =%d cbGameStatus=%d ", wChiarID, cbGameStatus);
  484. // OutputDebugString(str);
  485. switch (cbGameStatus)
  486. {
  487. case GS_MJ_FREE: //空闲状态
  488. {
  489. TRACE("发送场景 wChairID = %d 空闲状态 \n", wChiarID);
  490. //发送场景
  491. CMD_S_StatusFree StatusFree = { 0 };
  492. CopyMemory(&StatusFree.gameConfig, &m_gameConfig, sizeof(CMD_S_GameConfig));
  493. StatusFree.gameConfig.IsOwner = m_pITableFrame->GetPrivateTableOwnerID() == pIServerUserItem->GetUserID() ? 1 : 0;
  494. CopyMemory(StatusFree.lUserTmpScore, m_lGameTatolScore, sizeof(m_lGameTatolScore));
  495. StatusFree.UserStat = pIServerUserItem->GetUserInfo()->cbUserStatus;
  496. return m_pITableFrame->SendGameScene(pIServerUserItem, &StatusFree, sizeof(StatusFree));
  497. }
  498. case GS_MJ_PLAY: //游戏状态
  499. {
  500. TRACE("发送场景 wChairID = %d 游戏状态 \n", wChiarID);
  501. for (int i = 0; i < m_cbPlayerNum;i++)
  502. {
  503. m_GameLogic.SortCardList(m_cbCardData[i], m_cbCardDataCount[i]);
  504. }
  505. try
  506. {
  507. CMD_S_StatusPlay_SK StatusPlay = {0};
  508. StatusPlay.gameConfig.IsOwner = m_pITableFrame->GetPrivateTableOwnerID() == pIServerUserItem->GetUserID() ? 1 : 0;
  509. CopyMemory(&StatusPlay.gameConfig, &m_gameConfig, sizeof(CMD_S_GameConfig_Poker));
  510. CopyMemory(StatusPlay.lUserTmpScore, m_lGameTatolScore, sizeof(m_lGameTatolScore));
  511. int cfgSize = sizeof(CMD_S_GameConfig_Poker);
  512. StatusPlay.wBankerUser = m_wBankerUser;
  513. StatusPlay.wCurrentUser = m_wCurrentUser;
  514. //如果是 正在出牌的玩家重连
  515. if (m_wCurrentUser == wChiarID)
  516. StatusPlay.cbcardType = m_wCurrentOperate;
  517. int tmpUser = wChiarID;
  518. for (int userindex = 0; userindex < m_cbPlayerNum; userindex++)
  519. {
  520. StatusPlay.cbOtherOperateType[tmpUser] = m_cbUserOPerate_mask[tmpUser];
  521. //没看懂
  522. tmpUser = (tmpUser - 1) % m_cbPlayerNum;
  523. if (tmpUser < 0) tmpUser += m_cbPlayerNum;
  524. if (tmpUser == wChiarID && wChiarID == m_wCurrentUser)
  525. continue;
  526. //记录每个人的操作
  527. if (m_cbResponse[tmpUser] == 1)
  528. StatusPlay.cbOtherOperateType[tmpUser] = m_cbUserOPerate_mask[tmpUser];
  529. else if (m_cbResponse[tmpUser] == 2)
  530. {
  531. BYTE cbLevel;
  532. BomoType bomoinof;
  533. BYTE cbReplaceCards[27] = { 0 };
  534. m_GameLogic.ReplaceWangCards(m_cbTurnCardData, m_cbTurnCardCount, m_cbJokerReplacePoker[tmpUser], cbReplaceCards);
  535. StatusPlay.cbDiscardType = m_GameLogic.GetCardType(cbReplaceCards, m_cbTurnCardCount, cbLevel, bomoinof);
  536. StatusPlay.cbOtherOperateType[tmpUser] = OPERATE_MASK_OUT_Poker;
  537. std::list<OutCard>::reverse_iterator rIt;
  538. for (rIt = m_listOutCard.rbegin(); rIt != m_listOutCard.rend(); rIt++)
  539. {
  540. if (rIt->wOutCardUser == tmpUser)
  541. {
  542. memcpy(StatusPlay.cbOutCardData[tmpUser], rIt->cbOutCardData, MAX_COUNT_Poker*sizeof(BYTE));
  543. break;
  544. }
  545. }
  546. }
  547. }
  548. //扑克数目、玩家手牌
  549. for (BYTE i = 0; i < m_cbPlayerNum; i++)
  550. {
  551. StatusPlay.cbCardCount[i] = m_cbCardDataCount[i];
  552. StatusPlay.lUserTmpScore[i] = m_lGameTatolScore[i];
  553. StatusPlay.UserGongXianScore[i] = m_lGameGongXianScore[i];
  554. if (i==wChiarID)
  555. {
  556. if (m_cbCardDataCount[i]==0)
  557. {
  558. //此时可以看对家的牌
  559. CopyMemory(StatusPlay.cbTeamCardData, m_cbCardData[(i + 2) % GAME_PLAYER],MAX_COUNT_Poker);
  560. PrintCards(StatusPlay.cbTeamCardData, MAX_COUNT_Poker);
  561. }
  562. //我自己的牌
  563. CopyMemory(StatusPlay.cbCardData[i], m_cbCardData[i], MAX_COUNT_Poker);
  564. }
  565. StatusPlay.cbRankIndex[i] = m_wWinOrder[i];
  566. }
  567. StatusPlay.LeftMinPokerVal = m_cbStartRandCard;
  568. StatusPlay.cbCurrPlayCount = m_gameConfig.wHadPlayCount;
  569. StatusPlay.cbTotaPlayCount = m_gameConfig.wPlayCountRule;
  570. StatusPlay.LianXianInfo = m_lastLianxianInfo;
  571. CopyMemory(StatusPlay.cbReplaceCard, m_cbJokerReplacePoker, sizeof(m_cbJokerReplacePoker));
  572. // OutputDebugString(L"断线癞子替换");
  573. // PrintCards(StatusPlay.cbReplaceCard,16);
  574. // CString strInfo;
  575. // strInfo.Format(_T("积分:[%d %d %d %d] 贡献分:[%d %d %d %d] 当前用户[%d] 我的出牌类型[%d] 名次 [%d %d %d %d] 当前扑克->"),
  576. // StatusPlay.lUserTmpScore[0], StatusPlay.lUserTmpScore[1], StatusPlay.lUserTmpScore[2], StatusPlay.lUserTmpScore[3],
  577. // StatusPlay.UserGongXianScore[0], StatusPlay.UserGongXianScore[1], StatusPlay.UserGongXianScore[2], StatusPlay.UserGongXianScore[3],
  578. // StatusPlay.wCurrentUser, StatusPlay.cbcardType, StatusPlay.cbRankIndex[0], StatusPlay.cbRankIndex[1], StatusPlay.cbRankIndex[2], StatusPlay.cbRankIndex[3]
  579. // );
  580. // CString csPoker;
  581. // for (int i = 0; i < m_cbCardDataCount[wChiarID];i++)
  582. // {
  583. // CString tmp;
  584. // tmp.Format(_T("%02x,"), StatusPlay.cbCardData[wChiarID][i]);
  585. // csPoker += tmp;
  586. // }
  587. // strInfo += csPoker;
  588. // OutputDebugString(strInfo);
  589. // CString tmp;
  590. // for (int i = 0; i < sizeof(StatusPlay);i++)
  591. // {
  592. // CString strTmp;
  593. // strTmp.Format(_T("%02x "), ((BYTE*)&StatusPlay)[i]);
  594. // tmp += strTmp;
  595. // }
  596. // OutputDebugString(tmp);
  597. return m_pITableFrame->SendGameScene(pIServerUserItem, &StatusPlay, sizeof(StatusPlay));
  598. }
  599. catch (...) {}
  600. }
  601. }
  602. return false;
  603. return true;
  604. }
  605. bool CTableFrameSinkPoker::OnEventGameConclude(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason, bool bSendState /*= false*/)
  606. {
  607. TRACE("游戏结束 wChairID = %d cbReason = %#X \n", wChairID, cbReason);
  608. bool bFinish = (m_gameConfig.wHadPlayCount >= m_gameConfig.wPlayCountRule) ? 1 : 0;
  609. switch (cbReason)
  610. {
  611. case GER_DELETE_PRIVATE:
  612. //bFinish = true;
  613. //bDelete = true;
  614. //if (!m_pITableFrame->IsGameStarted())
  615. //{
  616. // DeletePrivateTable(bSendState);
  617. // return true;
  618. //}
  619. ConcludeGame(GS_MJ_FREE);
  620. DeletePrivateTable(bSendState);
  621. return true;
  622. case GER_NORMAL:
  623. {
  624. //常规结束
  625. CMD_S_GameEnd_SK GameEnd = { 0 };
  626. GameEnd.cbEndType = 1;
  627. //玩家手牌//名次排行
  628. for (int i = 0; i < m_cbPlayerNum; i++)
  629. {
  630. GameEnd.cbCardCount[i] = m_cbCardDataCount[i];
  631. CopyMemory(GameEnd.cbCardData[i], m_cbCardData[i], m_cbCardDataCount[i]);
  632. }
  633. if (m_wWinOrder[0] == (m_wWinOrder[1] + 2) % GAME_PLAYER)//双扣判断
  634. {
  635. //游戏积分 胜利玩家 每人+4
  636. ZeroMemory(GameEnd.cbWinorLose, sizeof(GameEnd.cbWinorLose));
  637. //玩家输赢情况
  638. GameEnd.cbWinorLose[m_wWinOrder[0]] = 1;
  639. GameEnd.cbWinorLose[(m_wWinOrder[0] + 2) % GAME_PLAYER] = 1;
  640. //玩家输赢次数 //双扣分数
  641. for (int i = 0; i < m_cbPlayerNum; i++)
  642. {
  643. if (i == m_wWinOrder[0] || i == ((m_wWinOrder[0] + 2) % GAME_PLAYER))
  644. {
  645. m_winLoseCount[i]++;
  646. m_lGameAwardScore[i] += 3;
  647. }
  648. else
  649. {
  650. //m_winLoseCount[i]--;
  651. m_lGameAwardScore[i] -= 3;
  652. }
  653. }
  654. //切换庄家
  655. m_wBankerUser = rand() % 4;
  656. }
  657. else
  658. //单双扣 判断
  659. if (m_wWinOrder[0] == (m_wWinOrder[2] + 2) % GAME_PLAYER) //单扣判断
  660. {
  661. //游戏积分 胜利玩家没人+2
  662. ZeroMemory(GameEnd.cbWinorLose, sizeof(GameEnd.cbWinorLose));
  663. //玩家输赢情况
  664. GameEnd.cbWinorLose[m_wWinOrder[0]] = 1;
  665. GameEnd.cbWinorLose[(m_wWinOrder[0]+2)%GAME_PLAYER] = 1;
  666. //玩家输赢次数 //双扣分数
  667. for (int i = 0; i < m_cbPlayerNum; i++)
  668. {
  669. if (i == m_wWinOrder[0] || i == ((m_wWinOrder[0] + 2) % GAME_PLAYER))
  670. {
  671. m_winLoseCount[i]++;
  672. m_lGameAwardScore[i] += 2;
  673. }
  674. else
  675. {
  676. //m_winLoseCount[i]--;
  677. m_lGameAwardScore[i] -= 2;
  678. }
  679. }
  680. //切换庄家
  681. m_wBankerUser = m_wWinOrder[0];
  682. }else
  683. {
  684. BOOL DuiJiabChu = FALSE;
  685. for (int i = 0; i < 4; i++)
  686. {
  687. if (((m_wWinOrder[0] + 2) % GAME_PLAYER) == m_wWinOrder[i])
  688. {
  689. DuiJiabChu = TRUE;
  690. }
  691. }
  692. if (DuiJiabChu==FALSE) //平扣判断
  693. {
  694. //游戏积分 胜利玩家 没人+1
  695. //玩家输赢情况
  696. GameEnd.cbWinorLose[m_wWinOrder[0]] = 1;
  697. GameEnd.cbWinorLose[(m_wWinOrder[0] + 2) % GAME_PLAYER] = 1;
  698. //玩家输赢次数
  699. for (int i = 0; i < m_cbPlayerNum; i++)
  700. {
  701. if (i == m_wWinOrder[0] || i == ((m_wWinOrder[0] + 2) % GAME_PLAYER))
  702. {
  703. m_winLoseCount[i]++;
  704. m_lGameAwardScore[i] += 1;
  705. }
  706. else
  707. {
  708. //m_winLoseCount[i]--;
  709. m_lGameAwardScore[i] -= 1;
  710. }
  711. }
  712. //切换庄家
  713. m_wBankerUser = rand() % 4;
  714. }
  715. }
  716. //排名逻辑 单独处理
  717. //特殊处理 游戏结束 排名
  718. BYTE outCrank[4] = { 0xff };
  719. RestartRank(m_wWinOrder, outCrank);
  720. for (BYTE i = 0; i < m_cbPlayerNum;i++)
  721. {
  722. //本局总积分
  723. m_GameScore[i] = m_lGameGongXianScore[i] + m_lGameAwardScore[i];
  724. //16局总积分
  725. m_lGameTatolScore[i] += m_GameScore[i];
  726. //结束消息
  727. //玩家排名
  728. GameEnd.cbRank[i] = outCrank[i];
  729. //输赢次数
  730. GameEnd.cbWinorLoseCount[i] = m_winLoseCount[i];
  731. //本局积分
  732. GameEnd.nWanJiaScore[i] = m_GameScore[i];
  733. //贡献分
  734. GameEnd.GongxianScore[i] = m_lGameGongXianScore[i];
  735. //奖金
  736. GameEnd.AwardScore[i] = m_lGameAwardScore[i];
  737. //16局总积分
  738. GameEnd.cbWanJiaTotalScore[i] = m_lGameTatolScore[i];
  739. }
  740. for (BYTE i = 0; i < m_cbPlayerNum;i++)
  741. {
  742. //流水
  743. m_HuPaiLiuShui[(m_gameConfig.wHadPlayCount - 1) * m_cbPlayerNum + i] = m_GameScore[i];
  744. }
  745. CopyMemory(GameEnd.lGameScoreDetail, m_HuPaiLiuShui, sizeof(m_HuPaiLiuShui));
  746. /*PrintCards(GameEnd.lGameScoreDetail, sizeof(GameEnd.lGameScoreDetail));*/
  747. //写入积分 稍后写
  748. tagScoreInfo ScoreInfoArray[GAME_PLAYER];
  749. ZeroMemory(&ScoreInfoArray, sizeof(ScoreInfoArray));
  750. for (WORD i = 0; i < m_cbPlayerNum; i++)
  751. {
  752. IServerUserItem *pUserItem = m_pITableFrame->GetTableUserItem(i);
  753. if (NULL == pUserItem) continue;
  754. BYTE ScoreKind;
  755. if (m_GameScore[i] > 0L) ScoreKind = SCORE_TYPE_WIN;
  756. else if (m_GameScore[i] < 0L) ScoreKind = SCORE_TYPE_LOSE;
  757. else ScoreKind = SCORE_TYPE_DRAW;
  758. ScoreInfoArray[i].lScore = m_GameScore[i];
  759. ScoreInfoArray[i].cbType = ScoreKind;
  760. }
  761. m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray));
  762. GameEnd.bFinish = bFinish;
  763. GameEnd.playGameNum = m_gameConfig.wHadPlayCount;
  764. RepayRecord(INVALID_CHAIR, SUB_S_GAME_END_Poker, &GameEnd, sizeof(GameEnd));
  765. //发送结束信息
  766. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END_Poker, &GameEnd, sizeof(GameEnd));
  767. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END_Poker, &GameEnd, sizeof(GameEnd));
  768. PrintCards((BYTE*)&GameEnd, sizeof(GameEnd));
  769. CString csStr;
  770. csStr.Format(_T("名次 [%d %d %d %d] 玩家单局输赢情况 [%d %d %d %d ] 本局积分 [%d %d %d %d] 贡献分[%d %d %d %d] 双扣[%d %d %d %d] 总积分[%d %d %d %d] bfinsh[%d] endType=[%d] 胜局[%d %d %d %d]"),
  771. GameEnd.cbRank[0], GameEnd.cbRank[1], GameEnd.cbRank[2], GameEnd.cbRank[3],
  772. GameEnd.cbWinorLose[0], GameEnd.cbWinorLose[1], GameEnd.cbWinorLose[2], GameEnd.cbWinorLose[3],
  773. GameEnd.nWanJiaScore[0], GameEnd.nWanJiaScore[1], GameEnd.nWanJiaScore[2], GameEnd.nWanJiaScore[3],
  774. GameEnd.GongxianScore[0], GameEnd.GongxianScore[1], GameEnd.GongxianScore[2], GameEnd.GongxianScore[3],
  775. GameEnd.AwardScore[0], GameEnd.AwardScore[1], GameEnd.AwardScore[2], GameEnd.AwardScore[3],
  776. GameEnd.cbWanJiaTotalScore[0], GameEnd.cbWanJiaTotalScore[1], GameEnd.cbWanJiaTotalScore[2], GameEnd.cbWanJiaTotalScore[3],
  777. GameEnd.bFinish,GameEnd.cbEndType,
  778. m_winLoseCount[0], m_winLoseCount[1], m_winLoseCount[2], m_winLoseCount[3]
  779. );
  780. OutputDebugString(csStr);
  781. //结束回放
  782. ConcludeGame(GS_MJ_FREE);
  783. if (bFinish)
  784. {
  785. DeletePrivateTable(true);
  786. }
  787. return true;
  788. }
  789. case GER_DISMISS: //游戏解散
  790. {
  791. //常规结束
  792. CMD_S_GameEnd_SK GameEnd = { 0 };
  793. GameEnd.cbEndType = 2;
  794. GameEnd.bFinish = 1;
  795. //玩家手牌//名次排行
  796. for (int i = 0; i < m_cbPlayerNum; i++)
  797. {
  798. GameEnd.cbCardCount[i] = m_cbCardDataCount[i];
  799. CopyMemory(GameEnd.cbCardData[i], m_cbCardData[i], m_cbCardDataCount[i]);
  800. }
  801. //特殊处理 游戏结束 排名
  802. BYTE outCrank[4] = { 0xff };
  803. RestartRank(m_wWinOrder, outCrank);
  804. for (BYTE i = 0; i < m_cbPlayerNum; i++)
  805. {
  806. //本局总积分
  807. m_GameScore[i] = m_lGameGongXianScore[i] + m_lGameAwardScore[i];
  808. //16局总积分
  809. m_lGameTatolScore[i] += m_GameScore[i];
  810. //结束消息
  811. //玩家排名
  812. GameEnd.cbRank[i] = outCrank[i];
  813. //输赢次数
  814. GameEnd.cbWinorLoseCount[i] = m_winLoseCount[i];
  815. //本局积分
  816. GameEnd.nWanJiaScore[i] = m_GameScore[i];
  817. //贡献分
  818. GameEnd.GongxianScore[i] = m_lGameGongXianScore[i];
  819. //奖金
  820. GameEnd.AwardScore[i] = m_lGameAwardScore[i];
  821. //16局总积分
  822. GameEnd.cbWanJiaTotalScore[i] = m_lGameTatolScore[i];
  823. }
  824. for (BYTE i = 0; i < m_cbPlayerNum; i++)
  825. {
  826. //流水
  827. m_HuPaiLiuShui[(m_gameConfig.wHadPlayCount - 1) * m_cbPlayerNum + i] = m_GameScore[i];
  828. }
  829. CopyMemory(GameEnd.lGameScoreDetail, m_HuPaiLiuShui, sizeof(m_HuPaiLiuShui));
  830. /*PrintCards(GameEnd.lGameScoreDetail, sizeof(GameEnd.lGameScoreDetail));*/
  831. GameEnd.playGameNum = m_gameConfig.wHadPlayCount;
  832. RepayRecord(INVALID_CHAIR, SUB_S_GAME_END_Poker, &GameEnd, sizeof(GameEnd));
  833. //发送结束信息
  834. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END_Poker, &GameEnd, sizeof(GameEnd));
  835. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END_Poker, &GameEnd, sizeof(GameEnd));
  836. if (m_pITableFrame->GetGameStatus() == GS_MJ_FREE)
  837. {
  838. DeletePrivateTable(true);
  839. return true;
  840. }
  841. //写入积分 稍后写
  842. tagScoreInfo ScoreInfoArray[GAME_PLAYER];
  843. ZeroMemory(&ScoreInfoArray, sizeof(ScoreInfoArray));
  844. for (WORD i = 0; i < m_cbPlayerNum; i++)
  845. {
  846. IServerUserItem *pUserItem = m_pITableFrame->GetTableUserItem(i);
  847. if (NULL == pUserItem) continue;
  848. BYTE ScoreKind;
  849. if (m_GameScore[i] > 0L) ScoreKind = SCORE_TYPE_WIN;
  850. else if (m_GameScore[i] < 0L) ScoreKind = SCORE_TYPE_LOSE;
  851. else ScoreKind = SCORE_TYPE_DRAW;
  852. ScoreInfoArray[i].lScore = m_GameScore[i];
  853. ScoreInfoArray[i].cbType = ScoreKind;
  854. }
  855. m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray));
  856. PrintCards((BYTE*)&GameEnd, sizeof(GameEnd));
  857. CString csStr;
  858. csStr.Format(_T("名次 [%d %d %d %d] 玩家单局输赢情况 [%d %d %d %d ] 本局积分 [%d %d %d %d] 贡献分[%d %d %d %d] 双扣[%d %d %d %d] 总积分[%d %d %d %d]"),
  859. GameEnd.cbRank[0], GameEnd.cbRank[1], GameEnd.cbRank[2], GameEnd.cbRank[3],
  860. GameEnd.cbWinorLose[0], GameEnd.cbWinorLose[1], GameEnd.cbWinorLose[2], GameEnd.cbWinorLose[3],
  861. GameEnd.nWanJiaScore[0], GameEnd.nWanJiaScore[1], GameEnd.nWanJiaScore[2], GameEnd.nWanJiaScore[3],
  862. GameEnd.GongxianScore[0], GameEnd.GongxianScore[1], GameEnd.GongxianScore[2], GameEnd.GongxianScore[3],
  863. GameEnd.AwardScore[0], GameEnd.AwardScore[1], GameEnd.AwardScore[2], GameEnd.AwardScore[3],
  864. GameEnd.cbWanJiaTotalScore[0], GameEnd.cbWanJiaTotalScore[1], GameEnd.cbWanJiaTotalScore[2], GameEnd.cbWanJiaTotalScore[3]
  865. );
  866. OutputDebugString(csStr);
  867. //结束回放
  868. ConcludeGame(GS_MJ_FREE);
  869. DeletePrivateTable(bSendState);
  870. return true;
  871. }
  872. case GER_NETWORK_ERROR: //网络错误
  873. case GER_USER_LEAVE: //用户强退
  874. {
  875. if (pIServerUserItem!=NULL)
  876. {
  877. DWORD dwUserID = pIServerUserItem->GetUserID();
  878. m_cbOffline[dwUserID] = 1;
  879. }
  880. return true;
  881. }
  882. }
  883. //错误断言
  884. ASSERT(FALSE);
  885. return false;
  886. }
  887. bool CTableFrameSinkPoker::OnTimerMessage(DWORD wTimerID, WPARAM wBindParam)
  888. {
  889. return true;
  890. }
  891. bool CTableFrameSinkPoker::OnDataBaseMessage(WORD wRequestID, VOID * pData, WORD wDataSize)
  892. {
  893. return true;
  894. }
  895. bool CTableFrameSinkPoker::OnUserScroeNotify(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason)
  896. {
  897. return true;
  898. }
  899. bool CTableFrameSinkPoker::RepayRecordStart()
  900. {
  901. m_bReplayRecordStart = true;
  902. /*for (GameRecordPacket grp : m_UserReplayRecord)
  903. {
  904. delete[] grp.pData;
  905. grp.pData = nullptr;
  906. }*/
  907. m_UserReplayRecord.clear();
  908. m_UserReplayRecord.shrink_to_fit();
  909. return true;
  910. }
  911. bool CTableFrameSinkPoker::RepayRecord(WORD wChairID, WORD wSubCmdId, void* pData, WORD wSize)
  912. {
  913. GameRecordPacket record;
  914. record.wSize = wSize;
  915. record.wChairID = wChairID;
  916. record.wSubCmdID = wSubCmdId;
  917. record.wMainCmdID = MDM_GF_GAME;
  918. /*record.pData = new char[wSize];
  919. CopyMemory(record.pData, pData, wSize);*/
  920. m_UserReplayRecord.push_back(record);
  921. return true;
  922. }
  923. bool CTableFrameSinkPoker::RepayRecordEnd()
  924. {
  925. TRACE("回放 RepayRecordEnd:m_bReplayRecordStart = %d \n", m_bReplayRecordStart);
  926. if (!m_bReplayRecordStart)
  927. return false;
  928. m_bReplayRecordStart = false;
  929. CMD_GR_ReplayRecordResp_Poker urr;
  930. ZeroMemory(&urr, sizeof(CMD_GR_ReplayRecordResp_Poker));
  931. urr.m_UUID = 0;
  932. urr.m_UserId = 0;
  933. urr.m_startTime = time(0);
  934. urr.m_endTime = time(0);
  935. urr.m_gameconfig = m_gameConfig;
  936. //urr.m_UserId = pIServerUserItem->GetUserID();
  937. for (int j = 0; j < m_cbPlayerNum; ++j)
  938. {
  939. IServerUserItem * pIServerUserItem = m_pITableFrame->GetTableUserItem(j);
  940. if ((pIServerUserItem == NULL) /*|| (pIServerUserItem->IsClientReady() == false)*/)
  941. continue;
  942. auto& chairInfo = urr.m_chairList[j];
  943. chairInfo.dwUserId = pIServerUserItem->GetUserID();
  944. chairInfo.wChairId = pIServerUserItem->GetChairID();
  945. lstrcpy(chairInfo.userName, pIServerUserItem->GetNickName());
  946. lstrcpy(chairInfo.headUrl, pIServerUserItem->GetUserInfo()->szHeadUrl);
  947. }
  948. urr.m_recordCount = m_UserReplayRecord.size();
  949. int GameRecordPacketSize = sizeof(GameRecordPacket) - sizeof(void*);//每条记录头长度
  950. int totalSize = sizeof(CMD_GR_ReplayRecordResp);//总记录头长度
  951. for (GameRecordPacket grp : m_UserReplayRecord)
  952. totalSize += (GameRecordPacketSize + grp.wSize);
  953. char* replyRecordData = new char[totalSize];
  954. ZeroMemory(replyRecordData, totalSize);
  955. CopyMemory(replyRecordData, &urr, sizeof(CMD_GR_ReplayRecordResp));
  956. int nOffset = sizeof(CMD_GR_ReplayRecordResp);
  957. for (GameRecordPacket &grp : m_UserReplayRecord)
  958. {
  959. CopyMemory(replyRecordData + nOffset, &grp, GameRecordPacketSize);
  960. nOffset += GameRecordPacketSize;
  961. /*CopyMemory(replyRecordData + nOffset, grp.pData, grp.wSize);*/
  962. /*nOffset += grp.wSize;*/
  963. /*delete[] grp.pData;
  964. grp.pData = NULL;*/
  965. }
  966. //m_UserReplayRecord.clear();
  967. //std::vector<GameRecordPacket>(m_UserReplayRecord).swap(m_UserReplayRecord);
  968. //FILE *fp = NULL;
  969. //fp = fopen("test.bin", "wb");
  970. //fwrite(replyRecordData, totalSize, 1, fp);
  971. //fclose(fp);
  972. m_pITableFrame->SaveReplayRecord(replyRecordData, totalSize);
  973. //delete replyRecordData;不能删除,已托管给SaveReplayRecord函数
  974. return true;
  975. }
  976. bool CTableFrameSinkPoker::OnUserOperate(WORD wChairID, CMD_C_OPERATE_CALLBACK_SK* pOperateCallback, BYTE cbType /*= 0*/)
  977. {
  978. m_cbTimeOutCount[wChairID] = 0;
  979. TRACE("用户操作 wChairID = %d 操作类型: %d \n", wChairID, pOperateCallback->wOperateType);
  980. m_cbUserOPerate_mask[wChairID] = pOperateCallback->wOperateType;
  981. switch (pOperateCallback->wOperateType)
  982. {
  983. case OPERATE_MASK_OUT_Poker: //出牌
  984. {
  985. BYTE cbCardCount = m_GameLogic.GetCardCount(pOperateCallback->cbCardData);
  986. BYTE LianxianInfo = pOperateCallback->LianxianInfo;
  987. return OnUserOutCard(wChairID, pOperateCallback->cbCardData, cbCardCount, pOperateCallback->cbCardType, pOperateCallback->cbJokerReplacePoker, LianxianInfo);
  988. }
  989. case OPERATE_MASK_NOOUT_Poker: //要不起
  990. case OPERATE_MASK_PASS_Poker: //不出
  991. {
  992. m_cbResponse[wChairID] = 1;
  993. /*
  994. struct CMD_S_Out_Broadcast_SK
  995. {
  996. WORD wOutCardUser; //出牌用户
  997. WORD cbOperateType; //操作类型
  998. WORD cbCardType; //出牌牌型
  999. BYTE cbJokerReplacePoker[4];//替换癞子的牌
  1000. BYTE cbOutCardData[27]; //出牌扑克
  1001. BYTE cbIsFreeOut; //是否自由出牌
  1002. BYTE cbIsTrusteeOut; //是否托管出牌
  1003. BYTE cbLeftCount; //剩余牌数
  1004. BYTE cbRanking; //当前名次
  1005. };
  1006. */
  1007. //出牌广播
  1008. CMD_S_Out_Broadcast_SK outCard = { 0 };
  1009. outCard.wOutCardUser = wChairID;
  1010. outCard.cbOperateType = pOperateCallback->wOperateType;
  1011. outCard.cbCardType = CT_ERROR;
  1012. CopyMemory(outCard.cbJokerReplacePoker, pOperateCallback->cbJokerReplacePoker, sizeof(pOperateCallback->cbJokerReplacePoker));
  1013. //CopyMemory(outCard.cbOutCardData, pOperateCallback->bCardData, 0);
  1014. outCard.cbIsFreeOut = FALSE;
  1015. outCard.cbIsTrusteeOut = 0;
  1016. outCard.cbLeftCount = m_cbCardDataCount[wChairID];
  1017. outCard.cbRanking[0] =m_wWinOrder[0];
  1018. outCard.cbRanking[1] = m_wWinOrder[1];
  1019. outCard.cbRanking[2] = m_wWinOrder[2];
  1020. outCard.cbRanking[3] = m_wWinOrder[3];
  1021. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OUT_BROADCAST_Poker, &outCard, sizeof(outCard));
  1022. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OUT_BROADCAST_Poker, &outCard, sizeof(outCard));
  1023. RepayRecord(INVALID_CHAIR, SUB_S_OUT_BROADCAST_Poker, &outCard, sizeof(outCard));
  1024. return NextOperate(wChairID);
  1025. }
  1026. case OPERATE_MASK_HINT_Poker: //提示
  1027. return OnUserHint(wChairID);
  1028. default:
  1029. CString tmp;
  1030. tmp.Format(_T("OnUserOperate 收到 %d "), pOperateCallback->wOperateType);
  1031. break;
  1032. }
  1033. return true;
  1034. }
  1035. //去花色排序
  1036. void CTableFrameSinkPoker::SortCard(BYTE cbCardData[], BYTE cbCardCount)
  1037. {
  1038. BYTE tmp = 0;
  1039. for (BYTE i = 0; i < cbCardCount; ++i)
  1040. {
  1041. cbCardData[i] &= 0x0f;
  1042. tmp = cbCardData[i];
  1043. cbCardData[i] = m_GameLogic.GetCardLogicValue(tmp);
  1044. }
  1045. sort(cbCardData, cbCardData + cbCardCount);
  1046. for (BYTE i = 0; i < cbCardCount; ++i)
  1047. {
  1048. tmp = cbCardData[i];
  1049. cbCardData[i] = m_GameLogic.GetCardValue(tmp);
  1050. }
  1051. }
  1052. bool CTableFrameSinkPoker::IsTeShuCard(BYTE cbCardData[], BYTE cbCount, BomoType& BomoInfo, WORD&WinScore)
  1053. {
  1054. BYTE cbLevel;
  1055. BYTE CardType=m_GameLogic.GetCardType(cbCardData, cbCount, cbLevel, BomoInfo);
  1056. if ((CardType == 7 && cbCount >= 5) ||CardType>7)
  1057. {
  1058. BYTE tmpXian =0;
  1059. if (CardType==7)
  1060. {
  1061. tmpXian = cbCount;
  1062. }
  1063. else
  1064. {
  1065. tmpXian = BomoInfo.Level;
  1066. }
  1067. //计算分数
  1068. switch (tmpXian)
  1069. {
  1070. case 5:
  1071. WinScore = 1*(m_cbPlayerNum-1);
  1072. break;
  1073. case 6:
  1074. case 7:
  1075. case 8:
  1076. case 9:
  1077. case 10:
  1078. case 11:
  1079. case 12:
  1080. case 13:
  1081. WinScore = pow(2, tmpXian-5)*3;
  1082. break;
  1083. default:
  1084. break;
  1085. }
  1086. return TRUE;
  1087. }
  1088. return false;
  1089. }
  1090. BOOL CTableFrameSinkPoker::IsWinByChairID(BYTE wChairID)
  1091. {
  1092. for (int i = 0; i < m_cbPlayerNum;i++)
  1093. {
  1094. if (m_wWinOrder[i] == wChairID)
  1095. {
  1096. return TRUE;
  1097. }
  1098. }
  1099. return FALSE;
  1100. }
  1101. void CTableFrameSinkPoker::WithByteAnalyzeCardFlags(BYTE lianxianinfo,BomoType &BomoInfo)
  1102. {
  1103. //第一位 0 标示付 1 表示连
  1104. //2-4 标示 几付 /几连
  1105. //最后4位 表示 几线
  1106. BOOL IsLian = lianxianinfo >> 7;
  1107. BYTE fuOrLian = (lianxianinfo & 0x70) >> 4;
  1108. BYTE xian = (lianxianinfo & 15) >> 1;
  1109. if (lianxianinfo>0)
  1110. {
  1111. BomoInfo.BomoTypes = IsLian == 0? BomoTypeXian : BomoTypeLian;
  1112. if (IsLian)
  1113. {
  1114. BomoInfo.tong = xian;
  1115. BomoInfo.lian = fuOrLian;
  1116. }
  1117. else
  1118. {
  1119. BomoInfo.fu = fuOrLian;
  1120. BomoInfo.xian = xian;
  1121. }
  1122. m_GameLogic.SetBomoLevel(BomoInfo);
  1123. }
  1124. }
  1125. void CTableFrameSinkPoker::SetCardFlags(BOOL IsLian, BYTE fuOrLian, BYTE xian)
  1126. {
  1127. //第一位 0 标示付 1 表示连
  1128. //2-4 标示 几付 /几连
  1129. //最后4位 表示 几线
  1130. BYTE lianxinfo;
  1131. lianxinfo = IsLian << 7;
  1132. lianxinfo |= fuOrLian << 4;
  1133. lianxinfo |= xian << 1;
  1134. BomoType BomoInfo;
  1135. WithByteAnalyzeCardFlags(lianxinfo, BomoInfo);
  1136. }
  1137. //托管出牌 全部发要不起
  1138. bool CTableFrameSinkPoker::TrusteeOut(WORD wChairID)
  1139. {
  1140. if (BeOutCardFree(wChairID)){
  1141. BYTE cbCardData[1];
  1142. BYTE cbCardCount = 1;
  1143. cbCardData[0] = m_cbCardData[wChairID][0];
  1144. BYTE Joker[4] = { 0 };
  1145. return OnUserOutCard(wChairID, cbCardData, cbCardCount, CT_SINGLE, Joker,0);
  1146. }
  1147. else
  1148. {
  1149. //出牌广播
  1150. CMD_S_Out_Broadcast_SK OutCard = { 0 };
  1151. OutCard.wOutCardUser = wChairID;
  1152. OutCard.cbOperateType = OPERATE_MASK_NOOUT_Poker;
  1153. OutCard.cbIsTrusteeOut = 1;
  1154. OutCard.cbLeftCount = m_cbCardDataCount[wChairID];
  1155. m_pITableFrame->SendTableData(INVALID_CHAIR, OPERATE_MASK_NOOUT_Poker, &OutCard, sizeof(OutCard));
  1156. m_pITableFrame->SendLookonData(INVALID_CHAIR, OPERATE_MASK_NOOUT_Poker, &OutCard, sizeof(OutCard));
  1157. RepayRecord(INVALID_CHAIR, OPERATE_MASK_NOOUT_Poker, &OutCard, sizeof(OutCard));
  1158. return NextOperate(wChairID);
  1159. }
  1160. }
  1161. bool CTableFrameSinkPoker::SendTeamfrindCards(WORD MyWchairID)
  1162. {
  1163. //myWchirID 标示 把我的牌 发给我的队友
  1164. WORD myTeamFrindChirID = (MyWchairID + 2 )% GAME_PLAYER;
  1165. if (IsWinByChairID(myTeamFrindChirID))
  1166. {
  1167. //队友手牌
  1168. // struct CMD_S_TEAMMATE_HANDCARD
  1169. // {
  1170. // WORD wTeammateChairID; //队友座位
  1171. // BYTE cbCardData[27]; //队友手牌
  1172. // };
  1173. CMD_S_TEAMMATE_HANDCARD st = { 0 };
  1174. st.wTeammateChairID = myTeamFrindChirID;
  1175. CopyMemory(st.cbCardData, m_cbCardData[MyWchairID], m_cbCardDataCount[MyWchairID]);
  1176. m_pITableFrame->SendTableData(myTeamFrindChirID, SUB_S_TEAMMATE_HANDCARD_Poker, &st, sizeof(st));
  1177. //RepayRecord(myTeamFrindChirID, SUB_S_TEAMMATE_HANDCARD_Poker, &st, sizeof(st));
  1178. }
  1179. return true;
  1180. }
  1181. bool CTableFrameSinkPoker::RestartRank(const BYTE cbRank[4], BYTE outRandToEnd[4])
  1182. {
  1183. memset(outRandToEnd, 0xff, 4);
  1184. for (int i = 0; i < 4;i++)
  1185. {
  1186. for (int j = 0; j < 4;j++)
  1187. {
  1188. if (cbRank[j]==i)
  1189. {
  1190. outRandToEnd[i] = j+1;
  1191. }
  1192. }
  1193. }
  1194. return 0;
  1195. }
  1196. BOOL CTableFrameSinkPoker::DeleteListOutCardRecord(DWORD wChairID)
  1197. {
  1198. list<OutCard>::iterator it;
  1199. for (it = m_listOutCard.begin(); it != m_listOutCard.end();)
  1200. {
  1201. if (it->wOutCardUser == wChairID)
  1202. it = m_listOutCard.erase(it); //返回下一个有效的迭代器,无需+1
  1203. else
  1204. ++it;
  1205. }
  1206. return TRUE;
  1207. }
  1208. void CTableFrameSinkPoker::ReadGameData()
  1209. {
  1210. CString strFileName;
  1211. strFileName = _T("Table.dat");
  1212. if (!PathFileExists(_T("Table.dat")))
  1213. {
  1214. return;
  1215. }
  1216. HANDLE hFile = CreateFile(strFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, NULL, NULL);
  1217. if (hFile != INVALID_HANDLE_VALUE)
  1218. {
  1219. DWORD dwRead;
  1220. DWORD dwFileSize;
  1221. DWORD fileSize = GetFileSize(hFile, &dwFileSize);
  1222. if (fileSize != 108)
  1223. {
  1224. CloseHandle(hFile);
  1225. return;
  1226. }
  1227. SetFilePointer(hFile, 0, 0, FILE_BEGIN);
  1228. ReadFile(hFile, m_cbRepertoryCard, 108, &dwRead, NULL);
  1229. CloseHandle(hFile);
  1230. }
  1231. }
  1232. BOOL CTableFrameSinkPoker::IsHaveBoomCountScore(BYTE wCharid, BYTE cbCardCount, WORD & WinScore)
  1233. {
  1234. int nFu = m_BoomCountInfo[wCharid][cbCardCount - 4];
  1235. int nXian = cbCardCount;
  1236. if (nFu<3)
  1237. {
  1238. return FALSE;
  1239. }
  1240. if (nFu==3&&nXian<=5)
  1241. {
  1242. return FALSE;
  1243. }
  1244. int tmpXian = 0;
  1245. switch (nXian)
  1246. {
  1247. case 4:
  1248. tmpXian = nFu + 1;
  1249. break;
  1250. case 5:
  1251. tmpXian = nFu + 4;
  1252. break;
  1253. case 6:
  1254. case 7:
  1255. case 8:
  1256. case 9:{
  1257. tmpXian = nFu + nXian;
  1258. break;
  1259. }
  1260. default:
  1261. break;
  1262. }
  1263. //计算分数
  1264. switch (tmpXian)
  1265. {
  1266. case 5:
  1267. WinScore = 1 * (m_cbPlayerNum - 1);
  1268. break;
  1269. case 6:
  1270. case 7:
  1271. case 8:
  1272. case 9:
  1273. case 10:
  1274. case 11:
  1275. case 12:
  1276. case 13:
  1277. WinScore = pow(2, tmpXian - 5) * 3;
  1278. break;
  1279. default:
  1280. break;
  1281. }
  1282. return TRUE;
  1283. }
  1284. bool CTableFrameSinkPoker::OnUserOutCard(WORD wChairID, BYTE bCardData[], BYTE bCardCount, BYTE cbCardType, BYTE cbJokerReplacePoker[4],BYTE LianxianInfo)
  1285. {
  1286. m_lastLianxianInfo = LianxianInfo;
  1287. // OutputDebugString(_T("OnUserOutCard "));
  1288. CopyMemory(m_cbJokerReplacePoker[wChairID], cbJokerReplacePoker, sizeof(cbJokerReplacePoker));
  1289. // PrintCards(cbJokerReplacePoker,sizeof(cbJokerReplacePoker));
  1290. //效验状态
  1291. if (wChairID != m_wCurrentUser)
  1292. {
  1293. OutputDebugString(L"当前玩家和出牌玩家不是一个 返回失败");
  1294. return false;
  1295. }
  1296. //生成出牌数据(不带花色)
  1297. OutCard struOutCard = { 0 };
  1298. struOutCard.wOutCardUser = wChairID;
  1299. memcpy(struOutCard.cbOutCardData, bCardData, bCardCount*sizeof(BYTE));
  1300. SortCard(struOutCard.cbOutCardData, bCardCount);
  1301. struOutCard.cbOutCardCount = bCardCount;
  1302. struOutCard.cbOutCardType = cbCardType;
  1303. //变幻扑克
  1304. //[10040] 1b,1b,0b,1c,0c,0c,3d,0d,0d,4e,4f,4f,
  1305. PrintCards(bCardData, bCardCount);
  1306. PrintCards(cbJokerReplacePoker, 4);//[10040] 0b,0c,0d,00,
  1307. //将王牌替换
  1308. BYTE cbMagicCardData[MAX_COUNT_Poker] = { 0 };
  1309. CopyMemory(cbMagicCardData, bCardData, bCardCount);
  1310. m_GameLogic.ReplaceWangCards(bCardData, bCardCount, cbJokerReplacePoker, cbMagicCardData);
  1311. //m_GameLogic.MagicCardData(bCardData, bCardCount, cbMagicCardData);
  1312. PrintCards(cbMagicCardData, bCardCount);
  1313. //[10040] 1b,1b,0b,1c,0c,0c,3d,0d,0d,4e,4f,4f,
  1314. //判断是否为自由出牌
  1315. BYTE cbIsFreeOut = BeOutCardFree(wChairID);
  1316. ////出牌判断 目前前端已经判断 稍后重构这部分判断
  1317. if (m_cbTurnCardCount != 0 && cbIsFreeOut == false)
  1318. {
  1319. //对比扑克
  1320. if (m_GameLogic.CompareCard(m_cbMagicCardData, cbMagicCardData, m_cbTurnCardCount, bCardCount) == false)
  1321. {
  1322. ASSERT(FALSE);
  1323. OutputDebugString(L"扑克比较 失败,出牌玩家的牌没有上家大 返回失败");
  1324. return false;
  1325. }
  1326. }
  1327. //类型判断
  1328. BYTE cbStarLevel;
  1329. BomoType bomoinof;
  1330. BYTE bCardType = m_GameLogic.GetCardType(cbMagicCardData, bCardCount, cbStarLevel, bomoinof);
  1331. if (bCardType == 7 && bCardCount == 4)
  1332. {
  1333. m_BomoCouut[wChairID]++;
  1334. }
  1335. if (bCardType == CT_BOMB&&bCardCount>=4)
  1336. {
  1337. m_BoomCountInfo[wChairID][bCardCount - 4]++;
  1338. }
  1339. if (bCardType>=10)
  1340. {
  1341. bCardType = 10;
  1342. }
  1343. //删除扑克
  1344. if (m_GameLogic.RemoveCard(bCardData, bCardCount, m_cbCardData[wChairID], m_cbCardDataCount[wChairID]) == false)
  1345. {
  1346. OutputDebugString(_T("删除扑克失败失败"));
  1347. ASSERT(FALSE);
  1348. return false;
  1349. }
  1350. //出牌记录
  1351. memset(&m_struOutCard, 0, sizeof(OutCard));
  1352. memcpy(&m_struOutCard, &struOutCard, sizeof(OutCard));
  1353. memcpy(struOutCard.cbOutCardData, bCardData, bCardCount*sizeof(BYTE));
  1354. m_listOutCard.push_back(struOutCard);
  1355. //设置变量
  1356. m_cbTurnCardCount = bCardCount;
  1357. m_cbCardDataCount[wChairID] -= bCardCount;
  1358. CopyMemory(m_cbTurnCardData, bCardData, sizeof(BYTE)*bCardCount);
  1359. CopyMemory(m_cbMagicCardData, cbMagicCardData, sizeof(BYTE)*bCardCount);
  1360. /*
  1361. struct CMD_S_Out_Broadcast_SK
  1362. {
  1363. WORD wOutCardUser; //出牌用户
  1364. WORD cbOperateType; //操作类型
  1365. WORD cbCardType; //出牌牌型
  1366. BYTE cbJokerReplacePoker[4];//替换癞子的牌
  1367. BYTE cbOutCardData[27]; //出牌扑克
  1368. BYTE cbIsFreeOut; //是否自由出牌
  1369. BYTE cbIsTrusteeOut; //是否托管出牌
  1370. BYTE cbLeftCount; //剩余牌数
  1371. BYTE cbRanking; //当前名次
  1372. }; */
  1373. if (m_cbCardDataCount[wChairID] == 0){
  1374. //设置用户
  1375. m_wWinOrder[m_wWinCount++] = wChairID;
  1376. m_wTurnWiner = wChairID;
  1377. }
  1378. m_cbResponse[wChairID] = 2;
  1379. CMD_S_Out_Broadcast_SK outCard = { 0 };
  1380. outCard.wOutCardUser = wChairID;
  1381. outCard.cbOperateType = OPERATE_MASK_OUT_Poker;
  1382. outCard.cbCardType = bCardType;
  1383. CopyMemory(outCard.cbJokerReplacePoker, cbJokerReplacePoker, sizeof(cbJokerReplacePoker));
  1384. CopyMemory(outCard.cbOutCardData, bCardData, bCardCount*sizeof(BYTE));
  1385. outCard.cbIsFreeOut = cbIsFreeOut;
  1386. outCard.cbIsTrusteeOut = 0;
  1387. outCard.cbLeftCount = m_cbCardDataCount[wChairID];
  1388. outCard.cbRanking[0] = m_wWinOrder[0];
  1389. outCard.cbRanking[1] = m_wWinOrder[1];
  1390. outCard.cbRanking[2] = m_wWinOrder[2];
  1391. outCard.cbRanking[3] = m_wWinOrder[3];
  1392. outCard.LianXianInfo = LianxianInfo;
  1393. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OUT_BROADCAST_Poker, &outCard, sizeof(outCard));
  1394. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OUT_BROADCAST_Poker, &outCard, sizeof(outCard));
  1395. RepayRecord(INVALID_CHAIR, SUB_S_OUT_BROADCAST_Poker, &outCard, sizeof(outCard));
  1396. PrintCards((const BYTE*)&outCard, sizeof(CMD_S_Out_Broadcast_SK));
  1397. //胜利判断
  1398. if (m_cbCardDataCount[wChairID] == 0)
  1399. {
  1400. //用户统计
  1401. if (m_cbCardDataCount[(wChairID + 2) % GAME_PLAYER] == 0)
  1402. m_wCurrentUser = INVALID_CHAIR;
  1403. //把队友的牌发给我
  1404. BYTE TeamFrindChairid = (wChairID + 2) % GAME_PLAYER;
  1405. SendTeamfrindCards(TeamFrindChairid);
  1406. //m_cbResponse[wChairID] = 0;
  1407. }
  1408. else
  1409. {
  1410. SendTeamfrindCards(wChairID);
  1411. }
  1412. if (m_gameConfig.HaveBoomScore)
  1413. {
  1414. //判断是否是大牌
  1415. BomoType BomoInfo;
  1416. WORD WinScore = 0;
  1417. if (IsTeShuCard(cbMagicCardData, bCardCount, BomoInfo, WinScore))
  1418. {
  1419. if (bCardType==CT_BOMB)
  1420. {
  1421. IsHaveBoomCountScore(wChairID, bCardCount, WinScore);
  1422. }
  1423. OutputDebugString(_T("特殊牌"));
  1424. PrintCards(cbMagicCardData, bCardCount);
  1425. CMD_S_JiangJin jiangjin;
  1426. jiangjin.wOperateUser = wChairID;
  1427. ZeroMemory(jiangjin.cbCardData, MAX_COUNT_Poker);
  1428. CopyMemory(jiangjin.cbCardData, bCardData, bCardCount);
  1429. cbCardType = bCardType;
  1430. m_BomoCouut[wChairID]++;
  1431. //这个tmp 应该是计算出来的
  1432. int tmpScore = WinScore;
  1433. if (m_BomoCouut[wChairID] >= 4)
  1434. {
  1435. tmpScore += (m_BomoCouut[wChairID] - 3) * 3;
  1436. CString strInfo;
  1437. strInfo.Format(_T("tmpScore =%d m_BomoCouut[wChairID] =%d"), tmpScore, m_BomoCouut[wChairID]);
  1438. OutputDebugString(strInfo);
  1439. }
  1440. jiangjin.Scores[wChairID] = tmpScore;
  1441. m_lGameGongXianScore[wChairID] += tmpScore;
  1442. jiangjin.TureScores[wChairID] = m_lGameGongXianScore[wChairID];
  1443. for (int i = 0; i < m_cbPlayerNum; i++)
  1444. {
  1445. if (wChairID == i)
  1446. {
  1447. continue;
  1448. }
  1449. jiangjin.Scores[i] = 0 - tmpScore / 3;
  1450. m_lGameGongXianScore[i] += jiangjin.Scores[i];
  1451. jiangjin.TureScores[i] = m_lGameGongXianScore[i];
  1452. CString strInfo;
  1453. strInfo.Format(_T("ID=%d jiangjin.Scores =%d m_lGameGongXianScore =%d\r\n"), i, jiangjin.Scores[i], m_lGameGongXianScore[i]);
  1454. OutputDebugString(strInfo);
  1455. }
  1456. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_JiangJin_Poker, &jiangjin, sizeof(jiangjin));
  1457. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_JiangJin_Poker, &jiangjin, sizeof(jiangjin));
  1458. RepayRecord(INVALID_CHAIR, SUB_S_GAME_JiangJin_Poker, &jiangjin, sizeof(jiangjin));
  1459. }
  1460. else if (bCardType == 7 && bCardCount == 4 && m_BomoCouut[wChairID] >= 4)
  1461. {
  1462. int tmpScore = 0;
  1463. if (m_BomoCouut[wChairID] >= 4)
  1464. {
  1465. tmpScore += (m_BomoCouut[wChairID] - 3) * 3;
  1466. }
  1467. if (bCardType == CT_BOMB)
  1468. {
  1469. WORD WinScore = 0;
  1470. IsHaveBoomCountScore(wChairID, bCardCount, WinScore);
  1471. tmpScore += WinScore;
  1472. }
  1473. CMD_S_JiangJin jiangjin;
  1474. jiangjin.wOperateUser = wChairID;
  1475. ZeroMemory(jiangjin.cbCardData, MAX_COUNT_Poker);
  1476. CopyMemory(jiangjin.cbCardData, bCardData, bCardCount);
  1477. jiangjin.Scores[wChairID] = tmpScore;
  1478. m_lGameGongXianScore[wChairID] += tmpScore;
  1479. jiangjin.TureScores[wChairID] = m_lGameGongXianScore[wChairID];
  1480. for (int i = 0; i < m_cbPlayerNum; i++)
  1481. {
  1482. if (wChairID == i)
  1483. {
  1484. continue;
  1485. }
  1486. jiangjin.Scores[i] = 0 - tmpScore / 3;
  1487. m_lGameGongXianScore[i] += jiangjin.Scores[i];
  1488. jiangjin.TureScores[i] = m_lGameGongXianScore[i];
  1489. }
  1490. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_JiangJin_Poker, &jiangjin, sizeof(jiangjin));
  1491. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_JiangJin_Poker, &jiangjin, sizeof(jiangjin));
  1492. RepayRecord(INVALID_CHAIR, SUB_S_GAME_JiangJin_Poker, &jiangjin, sizeof(jiangjin));
  1493. // OutputDebugString(_T("普通"));
  1494. // PrintCards(cbMagicCardData, bCardCount);
  1495. }
  1496. }
  1497. //结束判断
  1498. if (m_wCurrentUser == INVALID_CHAIR)
  1499. {
  1500. OnEventGameConclude(wChairID, NULL, GER_NORMAL);
  1501. return true;
  1502. }
  1503. return NextOperate(wChairID);
  1504. }
  1505. bool CTableFrameSinkPoker::BeOutCardFree(WORD wChairID)
  1506. {
  1507. for (BYTE i = 0; i < GAME_PLAYER; ++i)
  1508. {
  1509. if (i == wChairID) continue;
  1510. if (m_cbResponse[i] == 2)
  1511. return false;
  1512. }
  1513. ZeroMemory(m_cbResponse, sizeof(m_cbResponse));
  1514. MyZeroMemory(m_cbUserOPerate_mask);
  1515. return true;
  1516. }
  1517. bool CTableFrameSinkPoker::NextOperate(WORD wChairID)
  1518. {
  1519. //切换用户
  1520. PrintCards(m_cbResponse, 4);
  1521. do
  1522. {
  1523. //设置用户
  1524. m_wCurrentUser = (m_wCurrentUser + 1) % GAME_PLAYER;
  1525. //完成判断
  1526. if (m_wCurrentUser == m_wTurnWiner)
  1527. {
  1528. //设置变量
  1529. //m_cbTurnCardCount = 0;
  1530. if (BeOutCardFree(m_wCurrentUser))
  1531. {
  1532. //接风处理
  1533. if (m_cbCardDataCount[m_wTurnWiner] == 0)
  1534. {
  1535. m_wCurrentUser = (m_wTurnWiner + 2) % GAME_PLAYER;
  1536. }
  1537. m_wTurnWiner = INVALID_CHAIR;
  1538. ZeroMemory(m_cbResponse, sizeof(m_cbResponse));
  1539. MyZeroMemory(m_cbUserOPerate_mask);
  1540. break;
  1541. }
  1542. else
  1543. {
  1544. m_cbResponse[m_wTurnWiner] = 0;
  1545. m_cbUserOPerate_mask[m_wTurnWiner] = 0;
  1546. m_wTurnWiner = INVALID_CHAIR;
  1547. }
  1548. }
  1549. //继续处理
  1550. if (m_cbCardDataCount[m_wCurrentUser] != 0){
  1551. break;
  1552. }
  1553. else
  1554. {
  1555. if (m_cbResponse[m_wCurrentUser] == 2 && m_wWinCount==2)
  1556. {
  1557. m_cbResponse[m_wCurrentUser] = 0;
  1558. }
  1559. }
  1560. } while (true);
  1561. /*
  1562. struct CMD_S_Operate_SK
  1563. {
  1564. WORD wOperateUser; //操作用户
  1565. WORD wOperateType; //操作掩码
  1566. BYTE cbOptTime; //操作时间(秒)
  1567. BYTE cbIsFreeOut; //是否自由出牌
  1568. };
  1569. */
  1570. PrintCards(m_cbResponse, 4);//1 0 2 1
  1571. CMD_S_Operate_SK Operate = { 0 };
  1572. Operate.wOperateUser = m_wCurrentUser;
  1573. if (!BeOutCardFree(m_wCurrentUser))
  1574. {
  1575. Operate.cbIsFreeOut = 0;
  1576. m_cbHintNum = 0;
  1577. m_cbCurrentHintNum = 0;
  1578. mHistList.clear();
  1579. if (m_GameLogic.bCanOutCard(m_cbMagicCardData, m_cbTurnCardCount, m_cbCardData[m_wCurrentUser], m_cbCardDataCount[m_wCurrentUser],mHistList))
  1580. {
  1581. //要得起
  1582. Operate.wOperateType = OPERATE_MASK_OUT_Poker | OPERATE_MASK_HINT_Poker | OPERATE_MASK_PASS_Poker;
  1583. }
  1584. else
  1585. {
  1586. //要不起
  1587. Operate.wOperateType = OPERATE_MASK_NOOUT_Poker ;
  1588. }
  1589. m_cbHintNum = mHistList.size();
  1590. DeleteListOutCardRecord(m_wCurrentUser);
  1591. }
  1592. else
  1593. {//自由
  1594. mHistList.clear();
  1595. m_GameLogic.FindAllHit(m_cbCardData[m_wCurrentUser], m_cbCardDataCount[m_wCurrentUser], mHistList);
  1596. m_cbHintNum = mHistList.size();
  1597. Operate.cbIsFreeOut = 1;
  1598. Operate.wOperateType = OPERATE_MASK_OUT_Poker | OPERATE_MASK_HINT_Poker;
  1599. // CString strOut;
  1600. // strOut.Format(_T("有玩家自由 清空替换牌WID =%d"), m_wCurrentUser);
  1601. // OutputDebugString(strOut);
  1602. PrintCards(m_cbJokerReplacePoker[0], 16);
  1603. ZeroMemory(m_cbJokerReplacePoker, sizeof(m_cbJokerReplacePoker));
  1604. m_listOutCard.clear();
  1605. }
  1606. //清空当前玩家出过的牌
  1607. m_wCurrentOperate = Operate.wOperateType;
  1608. Operate.cbOptTime = GAME_TIMEOUT;
  1609. Operate.LianXianInfo = m_lastLianxianInfo;
  1610. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_Poker, &Operate, sizeof(Operate));
  1611. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_Poker, &Operate, sizeof(Operate));
  1612. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_Poker, &Operate, sizeof(Operate));
  1613. //if (wChairID == m_wTurnWiner&&m_cbResponse[wChairID]!=0)
  1614. //{
  1615. // m_cbResponse[wChairID] = 0;
  1616. //}
  1617. return true;
  1618. }
  1619. void CTableFrameSinkPoker::PrintCards(const BYTE cbCardData[], short cbCount)
  1620. {
  1621. CString strPrint;
  1622. for (int i = 0; i < cbCount;i++)
  1623. {
  1624. CString str;
  1625. str.Format(_T("%02x,"),cbCardData[i]);
  1626. strPrint += str;
  1627. }
  1628. CString tmp1;
  1629. tmp1.Format(L" 字节数=%d", cbCount);
  1630. strPrint += tmp1;
  1631. strPrint.Append(_T("\r\n"));
  1632. OutputDebugString(strPrint);
  1633. }
  1634. void CTableFrameSinkPoker::FindCardOwner(BOOL &bSwitchChair)
  1635. {
  1636. /*
  1637. 开始计算变换位置
  1638. */
  1639. bSwitchChair = false;
  1640. WORD wSourceID[] = { INVALID_CHAIR, INVALID_CHAIR };
  1641. if (m_wBankerUser == INVALID_CHAIR)
  1642. {
  1643. //寻找庄家用户
  1644. for (WORD userIndex = 0; userIndex < m_cbPlayerNum; userIndex++)
  1645. {
  1646. for (BYTE j = 0; j < MAX_COUNT_Poker; j++)
  1647. {
  1648. if (m_cbCardData[userIndex][j] == m_cbStartRandCard)
  1649. {
  1650. m_wBankerUser = userIndex;
  1651. break;
  1652. }
  1653. }
  1654. if (m_wBankerUser != INVALID_CHAIR)
  1655. break;
  1656. }
  1657. ASSERT(m_wBankerUser != INVALID_CHAIR);
  1658. //wGetRandCardID[0] = m_wBankerUser;
  1659. //寻找对家 分2中情况 1:庄家全有 2 任意一家有
  1660. for (WORD UserIndex = 0; UserIndex < m_cbPlayerNum; UserIndex++)
  1661. {
  1662. BYTE TmpCardPosition[2] = { 0 };
  1663. if (UserIndex == m_wBankerUser)
  1664. {
  1665. if (m_GameLogic.FindHaveCardCount(m_cbCardData[UserIndex], m_cbCardDataCount[UserIndex], m_cbStartRandCard, TmpCardPosition) == 2)
  1666. {
  1667. break;
  1668. }
  1669. }
  1670. if (m_GameLogic.FindHaveCardCount(m_cbCardData[UserIndex], m_cbCardDataCount[UserIndex], m_cbStartRandCard, TmpCardPosition) == 1)
  1671. {
  1672. //2中情况 拥有该牌的玩家 坐在庄家对边 和没做在庄家对面
  1673. if (UserIndex != m_wBankerUser&&UserIndex != (m_wBankerUser + 2) % m_cbPlayerNum)
  1674. {
  1675. //拥有一样的牌的玩家,并没有坐在庄家对面
  1676. m_wSourceID[0] = UserIndex;
  1677. m_wSourceID[1] = (m_wBankerUser + 2) % m_cbPlayerNum;
  1678. //对家找到了
  1679. bSwitchChair = true;
  1680. }
  1681. if (UserIndex != m_wBankerUser&&UserIndex == (m_wBankerUser + 2) % m_cbPlayerNum)
  1682. {
  1683. //拥有一样的牌的玩家,坐在对面了
  1684. //对家找到了
  1685. }
  1686. }
  1687. if (bSwitchChair == TRUE)
  1688. {
  1689. break;
  1690. }
  1691. }
  1692. }
  1693. // CString str;
  1694. // str.Format(_T("变换完毕 是否变换=%d 变换玩家的ID=%d %d CardData=0x%x"), bSwitchChair, wSourceID[0], wSourceID[1], m_cbStartRandCard);
  1695. // OutputDebugString(str);
  1696. }