📄 player.cpp
字号:
//// Copyright (c) 2005, Wei Mingzhi <whistler@openoffice.org>// All Rights Reserved.//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License as// published by the Free Software Foundation; either version 2 of// the License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA// 02110-1301, USA//#include "main.h"CBasePlayer::CBasePlayer():m_iNumDiscarded(0),m_iScore(0),m_iState(0){ memset(&m_Result, 0, sizeof(m_Result)); m_fTuiDaoHu = (atoi(cfg.Get("GAME", "TuiDaoHu", "0")) > 0);}CBasePlayer::~CBasePlayer(){}// Return true if player has discarded the specified tile.bool CBasePlayer::HasDiscarded(const CTile &t){ for (int i = 0; i < m_iNumDiscarded; i++) { if (m_Discarded[i].tile == t) { return true; } } return false;}void CBasePlayer::NewRound(){ m_iNumDiscarded = 0; m_Hand.NewHand(); m_fReach = false; m_iState = PS_NOTDISCARDED; memset(&m_Result, 0, sizeof(m_Result));}void CBasePlayer::GetHand(){ m_Hand.NewHand(); for (int i = 0; i < 13; i++) { m_Hand.AddRandomTile(0); }}void CBasePlayer::GetBonusHand(){ int count = 0, i, num = RandomLong(9, 12); CTile t[13], tmp; CTile maj[13] = {"1C", "9C", "1B", "9B", "1D", "9D", "EW", "SW", "WW", "NW", "WD", "GD", "RD"}; CTile wind[4] = {"EW", "SW", "WW", "NW"}; CTile elem[3] = {"RD", "GD", "WD"}; i = RandomLong(1, 7); switch (i) { case 1: // one suit { t[0] = CTile::RandomTile(); count = 1; int suit = t[0].GetSuit(); for (i = 0; i < num; i++) { int v = RandomLong(1, 9); tmp = CTile(suit | v); if (CTile::FetchTile(tmp)) { t[count++] = tmp; } } break; } case 2: // all majors while (count < num) { tmp = maj[RandomLong(0, 13 - 1)]; for (int j = 0, c = RandomLong(1, 100) > 75 ? 2 : 3; j < c; j++) { int a = 0; if (CTile::RemainingTile(tmp) > 1) { CTile::FetchTile(tmp); t[count++] = tmp; a++; } if (count >= num) { break; } } } break; case 3: // all num majors while (count < num) { tmp = maj[RandomLong(0, 6 - 1)]; for (int j = 0, c = RandomLong(1, 100) > 75 ? 2 : 3; j < c; j++) { int a = 0; if (CTile::RemainingTile(tmp) > 1) { CTile::FetchTile(tmp); t[count++] = tmp; a++; } if (count >= num) { break; } } } break; case 4: // thirteen wonders for (i = 0; i < num; i++) { if (RandomLong(0, 100) > 90) { continue; } if (CTile::FetchTile(maj[i])) { t[count++] = maj[i]; } } break; case 5: // four winds for (i = 0; i < 12; i++) { if (RandomLong(0, 100) > 90) { continue; } if (CTile::FetchTile(wind[i / 3])) { t[count++] = wind[i / 3]; } } break; case 6: // three elements for (i = 0; i < 9; i++) { if (RandomLong(0, 100) > 80) { continue; } if (CTile::FetchTile(elem[i / 3])) { t[count++] = elem[i / 3]; } } break; case 7: // nine lanteens num = (TILESUIT_CHAR << RandomLong(0, 2)); for (i = 0; i < 13; i++) { if (RandomLong(0, 100) > 90) { continue; } int v = ((i < 3) ? 1 : ((i > 9) ? 9 : i - 1)); tmp = CTile(num | v); if (CTile::FetchTile(tmp)) { t[count++] = tmp; } } break; } // fill the remaining places with random tiles for (i = count; i < 13; i++) { t[i] = CTile::RandomTile(); } // shuffle the tiles for (i = 0; i < 13; i++) { int b = RandomLong(0, 13 - 1); tmp = t[i]; t[i] = t[b]; t[b] = tmp; } // add tiles to hand for (i = 0; i < 13; i++) { m_Hand.AddTile(t[i], 0); }}bool CBasePlayer::HasYakuman(){ return (m_Result.tenhou || m_Result.renhou || m_Result.chihou || m_Result.tuisou || m_Result.chinraotou || m_Result.ryuisou || m_Result.daisangen || m_Result.daisusi || m_Result.syosusi || m_Result.suankou || m_Result.surenkou || m_Result.kokusi || m_Result.cyurenpotou || m_Result.sukantu);}int CBasePlayer::HasFan(){ if (HasYakuman()) return 13; int fan = 0; bool concealed = m_Hand.IsConcealed(); fan += m_Result.reach; fan += m_Result.pinfu; fan += m_Result.ippatu; fan += m_Result.double_reach; fan += m_Result.tanyao; fan += m_Result.tumo; fan += m_Result.ryanpeikou * 3; fan += m_Result.iipeikou; fan += m_Result.sansiki * (concealed ? 2 : 1); fan += m_Result.sansiki_doukoku * 2; fan += m_Result.toitoi * 2; fan += m_Result.sanankou * 2; fan += m_Result.sanrenkou * 2; fan += m_Result.junchan * (concealed ? 3 : 2); fan += m_Result.chanta * (concealed ? 2 : 1); fan += m_Result.ittu * (concealed ? 2 : 1); fan += m_Result.chinitu * (concealed ? 6 : 5); fan += m_Result.honitu * (concealed ? 3 : 2); fan += m_Result.chitoitu * 2; fan += m_Result.honraotou * 2; fan += m_Result.syosangen * 2; fan += m_Result.haitei; fan += m_Result.houtei; fan += m_Result.rinshan; fan += m_Result.fanpai; fan += m_Result.dora; fan += m_Result.sankantu * 2; fan += m_Result.nofan; return fan;}void CBasePlayer::CalcResult(){ memset(&m_Result, 0, sizeof(m_Result)); m_Result.concealed = m_Hand.IsConcealed(); CalcFu(); CalcResult_tenhou(); CalcResult_renhou(); CalcResult_tuisou(); CalcResult_chinraotou(); CalcResult_ryuisou(); CalcResult_daisangen(); CalcResult_daisusi(); CalcResult_suankou(); CalcResult_surenkou(); CalcResult_kokusi(); CalcResult_cyurenpotou(); CalcResult_sukantu(); CalcResult_chitoitu(); if (!HasYakuman()) { CalcResult_reach(); CalcResult_ippatu(); CalcResult_double_reach(); CalcResult_tanyao(); CalcResult_ryanpeikou(); CalcResult_sansiki(); CalcResult_sansiki_doukoku(); CalcResult_toitoi(); CalcResult_honraotou(); CalcResult_junchan(); CalcResult_ittu(); CalcResult_chinitu(); CalcResult_honitu(); CalcResult_haitei(); CalcResult_rinshan(); CalcResult_fanpai(); CalcResult_dora(); } if (atoi(cfg.Get("GAME", "TuiDaoHu", "0")) > 1 && !HasFan()) { m_Result.nofan = 1; } CalcScore();}void CBasePlayer::CalcResult_tenhou(){ if ((m_iState & PS_NOTDISCARDED) && m_iTurn == TURN_EAST) { m_Result.tenhou = 1; }}void CBasePlayer::CalcResult_renhou(){ if ((m_iState & PS_NOTDISCARDED) && m_iTurn != TURN_EAST) { if (m_Result.selfdrawn) { m_Result.chihou = 1; return; } m_Result.renhou = 1; }}void CBasePlayer::CalcResult_tuisou(){ for (int i = 0; i < m_Hand.m_iNumTiles; i++) { if (!(m_Hand.m_Tiles[i].tile.GetSuit() & (TILESUIT_WIND | TILESUIT_DRAGON))) return; // fail! } m_Result.tuisou = 1; // success!}void CBasePlayer::CalcResult_chinraotou(){ for (int i = 0; i < m_Hand.m_iNumTiles; i++) { if (!m_Hand.m_Tiles[i].tile.IsNumMajor()) return; // fail! } m_Result.chinraotou = 1; // success!}void CBasePlayer::CalcResult_ryuisou(){ for (int i = 0; i < m_Hand.m_iNumTiles; i++) { const CTile &t = m_Hand.m_Tiles[i].tile; if (t == CTile("GD")) continue; if (t.GetSuit() != TILESUIT_BAMBOO) return; // fail! if (t.GetValue() != 2 || t.GetValue() != 3 || t.GetValue() != 4 || t.GetValue() != 6 || t.GetValue() != 8) return; // fail! } m_Result.ryuisou = 1; // success!}void CBasePlayer::CalcResult_daisangen(){ int a[3] = {0, 0, 0}, i; bool pair = false; for (i = 0; i < m_Hand.m_iNumTileSets; i++) { if (m_Hand.m_TileSets[i].first.GetSuit() == TILESUIT_DRAGON) { if (m_Hand.m_TileSets[i].type & HT_PAIR) { if (pair) return; // fail; two pairs is not possible pair = true; } assert(m_Hand.m_TileSets[i].first.GetValue() - 1 <= 2); a[m_Hand.m_TileSets[i].first.GetValue() - 1]++; } } if (a[0] && a[1] && a[2]) { if (!pair) m_Result.daisangen = 1; else m_Result.syosangen = 1; }}void CBasePlayer::CalcResult_daisusi(){ int a[4] = {0, 0, 0, 0}, i; bool pair = false; for (i = 0; i < m_Hand.m_iNumTileSets; i++) { if (m_Hand.m_TileSets[i].first.GetSuit() == TILESUIT_WIND) { if (m_Hand.m_TileSets[i].type & HT_PAIR) { if (pair) return; // fail; two pairs are not possible pair = true; } assert(m_Hand.m_TileSets[i].first.GetValue() - 1 <= 3); a[m_Hand.m_TileSets[i].first.GetValue() - 1]++; } } if (a[0] && a[1] && a[2] && a[3]) { if (!pair) { m_Result.daisusi = 1; } else { m_Result.syosusi = 1; } }}void CBasePlayer::CalcResult_suankou(){ int count = 0, i; for (i = 0; i < m_Hand.m_iNumTileSets; i++) { if (m_Hand.m_TileSets[i].type & (HT_CLOSEDKONG | HT_CLOSEDPUNG)) count++; } if (count >= 4) m_Result.suankou = 1; else if (count >= 3) m_Result.sanankou = 1;}void CBasePlayer::CalcResult_surenkou(){ int i, j; for (i = 0; i < m_Hand.m_iNumTileSets; i++) { if (m_Hand.m_TileSets[i].type & (HT_CLOSEDKONG | HT_CLOSEDPUNG | HT_OPENKONG | HT_OPENPUNG)) { int a[3] = {0, 0, 0}; const CTile &t1 = m_Hand.m_TileSets[i].first; if (t1.GetValue() >= 7 || (t1.GetSuit() & (TILESUIT_WIND | TILESUIT_DRAGON))) continue; for (j = 0; j < m_Hand.m_iNumTileSets; j++) { if (m_Hand.m_TileSets[j].type & (HT_CLOSEDKONG | HT_CLOSEDPUNG | HT_OPENKONG | HT_OPENPUNG)) { const CTile &t2 = m_Hand.m_TileSets[j].first; if (t1.GetSuit() != t2.GetSuit()) continue; int d = t2.GetValue() - t1.GetValue(); if (d < 1 || d > 3) continue; a[d - 1]++; } } if (a[0] && a[1] && a[2]) { m_Result.surenkou = 1; // success! return; } else if (a[0] && a[1]) { m_Result.sanrenkou = 1; return; } } }}void CBasePlayer::CalcResult_kokusi(){ if (m_Hand.m_Tiles[0].flags & HT_THIRTEENWONDERS) { m_Result.kokusi = 1; for (int i = 0; i < m_Hand.m_iNumTiles; i++) { if (m_Hand.m_Tiles[i].flags & HT_JUSTGOT) { m_Result.selfdrawn = true; } } }}void CBasePlayer::CalcResult_cyurenpotou(){ if (!m_Result.concealed) { return; // fail!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -