📄 player.cpp
字号:
} // Draw another tile as it's a kong gpGeneral->DrawTile(m_Hand.m_TileSets[i].first, DRAW_LOCATION(loc - 2), 390, PLAYER_SHOWN); } else if (m_Hand.m_TileSets[i].type & HT_CLOSEDKONG) { for (j = 0; j < 3; j++) { gpGeneral->EraseArea(DRAW_LOCATION(loc), 380, TILE_WIDTH, 100); gpGeneral->DrawTile(m_Hand.m_TileSets[i].first, DRAW_LOCATION(loc), 410, WALL_CONCEALED); loc++; } // Draw another tile as it's a kong gpGeneral->DrawTile(m_Hand.m_TileSets[i].first, DRAW_LOCATION(loc - 2), 390, PLAYER_SHOWN); } else if (m_Hand.m_TileSets[i].type & HT_OPENPUNG) { for (j = 0; j < 3; j++) { gpGeneral->EraseArea(DRAW_LOCATION(loc), 380, TILE_WIDTH, 100); gpGeneral->DrawTile(m_Hand.m_TileSets[i].first, DRAW_LOCATION(loc), 410, PLAYER_SHOWN); loc++; } } else if (m_Hand.m_TileSets[i].type & HT_OPENCHOW) { CTile t = m_Hand.m_TileSets[i].first; for (j = 0; j < 3; j++) { gpGeneral->EraseArea(DRAW_LOCATION(loc), 380, TILE_WIDTH, 100); gpGeneral->DrawTile(t, DRAW_LOCATION(loc), 410, PLAYER_SHOWN); loc++; t = t() + 1; } } else { assert(false); // this should NOT happen } } } c[0] += loc; for (i = 0; i < m_Hand.m_iNumTiles; i++) { if ((m_Hand.m_Tiles[i].flags & HT_OPEN) && !(m_Hand.m_Tiles[i].flags & HT_RON)) { continue; } gpGeneral->EraseArea(DRAW_LOCATION(loc), 380, TILE_WIDTH, 100); gpGeneral->DrawTile(m_Hand.m_Tiles[i].tile, DRAW_LOCATION(loc), shown ? 396 : 380, shown ? PLAYER_SHOWN : PLAYER_CONCEALED); gpGeneral->DrawUTF8Text(c, DRAW_LOCATION(loc) + 15, 455); c[0]++; loc++; } if (c[0] <= 'N') { gpGeneral->EraseArea(DRAW_LOCATION(13), 380, TILE_WIDTH, 100); gpGeneral->DrawUTF8Text("N", DRAW_LOCATION(13) + 15, 455); } gpGeneral->UpdateScreen(0, 380, 640, 100);}int CPlayer::KeyToIndex(SDLKey key){ int d = key - SDLK_a, i, loc = 0; if (d < 0 || d > 14) return -1; // this isn't a letter key thru A-N for (i = 0; i < m_Hand.m_iNumTileSets; i++) { if ((m_Hand.m_TileSets[i].type & HT_OPEN) && !(m_Hand.m_TileSets[i].type & HT_RON)) loc += 3; } for (i = 0; i < m_Hand.m_iNumTiles; i++) { if ((m_Hand.m_Tiles[i].flags & HT_OPEN) && !(m_Hand.m_Tiles[i].flags & HT_RON)) continue; if (loc == d) return i; loc++; } return -1;}void CPlayer::FirstChance(){ SDLKey key; int index, changed = 0; gpGeneral->DrawMessage(msg("hint_firstchance")); do { key = gpGeneral->ReadKey(); index = KeyToIndex(key); if (index < 0 || index >= 13 || (changed & (1 << index))) continue; changed |= (1 << index); CTile::ReturnTile(m_Hand.m_Tiles[index].tile); m_Hand.m_Tiles[index].tile = CTile::RandomTile(); gpGeneral->PlaySound(SND_SOUND3); gpGeneral->EraseArea(DRAW_LOCATION(index), 380, TILE_WIDTH, TILE_HEIGHT_CONCEALED); gpGeneral->DrawTile(m_Hand.m_Tiles[index].tile, DRAW_LOCATION(index), 396, WALL_CONCEALED); gpGeneral->UpdateScreen(DRAW_LOCATION(index), 380, TILE_WIDTH, TILE_HEIGHT_CONCEALED); } while (key != SDLK_RETURN); gpGeneral->DrawMessage(NULL); gpGeneral->PlaySound(SND_DISCARD1); DrawHand(); m_Hand.Sort(); gpGeneral->UpdateScreen(0, 380, 640, 100); UTIL_Delay(800); gpGeneral->PlaySound(SND_DISCARD1); gpGeneral->EraseArea(0, 380, 640, TILE_HEIGHT_CONCEALED); gpGeneral->DrawTiles(NULL, 13, 20, 396, WALL_CONCEALED); gpGeneral->UpdateScreen(0, 380, 640, 100); UTIL_Delay(1000); gpGeneral->PlaySound(SND_DISCARD1); DrawHand(); gpGeneral->UpdateScreen(0, 380, 640, 100);}// return true if player wins the round with this chance.bool CPlayer::LastChance(){ CTile waiting[13], wall[10]; int n = m_Hand.GetWaitingTile(waiting), i, t, flags = 0, chance; if (n <= 0) { return false; // not ready hand } gpGeneral->PlaySound(SND_DING); // play a hint sound t = RandomLong(1, 3); for (i = 0; i < t; i++) { int s = RandomLong(0, n - 1); wall[i] = (CTile::FetchTile(waiting[s]) ? waiting[s] : CTile::RandomTile()); } for (; i < 10; i++) { wall[i] = CTile::RandomTile(); } // shuffle the wall for (i = 0; i < 10; i++) { CTile tmp = wall[i]; t = RandomLong(0, 9); wall[i] = wall[t]; wall[t] = tmp; } gpGeneral->EraseArea(0, 265, 640, 363 - 265); gpGeneral->DrawTiles(NULL, 10, 20, 265, WALL_CONCEALED); for (i = 0; i < 10; i++) { char sz[] = "A"; sz[0] += (char)i; gpGeneral->DrawUTF8Text(sz, 20 + TILE_WIDTH * i + 15, 325); } gpGeneral->UpdateScreen(0, 265, 640, 480 - 265); for (chance = 0; chance < 3; chance++) { SDLKey k = gpGeneral->ReadKey(); t = k - SDLK_a; if (t < 0 || t >= 10 || (flags & (1 << t))) { chance--; continue; } flags |= (1 << t); i = 20 + TILE_WIDTH * t; gpGeneral->PlaySound(SND_SOUND4); gpGeneral->DrawTile(wall[t], i, 265, WALL_SHOWN); gpGeneral->UpdateScreen(i, 265, TILE_WIDTH, TILE_HEIGHT_SHOWN); CHand tmp = m_Hand; m_Hand.AddTile(wall[t]); if (m_Hand.GoMahjong()) { CalcResult(); UTIL_Delay(1000); return true; } m_Hand = tmp; } UTIL_Delay(500); gpGeneral->DrawTiles(wall, 10, 20, 265, WALL_SHOWN); gpGeneral->UpdateScreen(20, 265, TILE_WIDTH * 10, TILE_HEIGHT_SHOWN); UTIL_Delay(500); return false;}void CPlayer::DrawDiscarded(){ int i, x, y; for (i = 0; i < 10 && i < m_iNumDiscarded; i++) { gpGeneral->DrawTile(m_Discarded[i].tile, DRAW_LOCATION(i), 265, WALL_SHOWN); if (m_Discarded[i].flags & DT_REACH) { bool locked = false; if (SDL_MUSTLOCK(gpScreen)) { SDL_LockSurface(gpScreen); locked = true; } for (x = DRAW_LOCATION(i); x < DRAW_LOCATION(i) + TILE_WIDTH; x++) { for (y = 265; y < 265 + TILE_HEIGHT_SHOWN; y++) { unsigned char r, g, b; UTIL_GetPixel(gpScreen, x, y, &r, &g, &b); if (g >= 255 - 35) { g = 255; } else { g += 35; } UTIL_PutPixel(gpScreen, x, y, r, g, b); } } if (locked) { SDL_UnlockSurface(gpScreen); } } } gpGeneral->EraseArea(DRAW_LOCATION(i), 265, TILE_WIDTH * (10 - i), TILE_HEIGHT_SHOWN); for (i = 0; i < 10 && i < m_iNumDiscarded - 10; i++) { gpGeneral->DrawTile(m_Discarded[i + 10].tile, DRAW_LOCATION(i), 303, WALL_SHOWN); if (m_Discarded[i + 10].flags & DT_REACH) { bool locked = false; if (SDL_MUSTLOCK(gpScreen)) { SDL_LockSurface(gpScreen); locked = true; } for (x = DRAW_LOCATION(i); x < DRAW_LOCATION(i) + TILE_WIDTH; x++) { for (y = 303; y < 303 + TILE_HEIGHT_SHOWN; y++) { unsigned char r, g, b; UTIL_GetPixel(gpScreen, x, y, &r, &g, &b); if (g >= 255 - 35) { g = 255; } else { g += 35; } UTIL_PutPixel(gpScreen, x, y, r, g, b); } } if (locked) { SDL_UnlockSurface(gpScreen); } } } gpGeneral->EraseArea(DRAW_LOCATION(i), 325, TILE_WIDTH * (10 - i), TILE_HEIGHT_SHOWN - 22); if (m_fReach) { gpGeneral->DrawDotBar(DRAW_LOCATION(10) + 5, 270); } else { gpGeneral->EraseArea(DRAW_LOCATION(10) + 5, 270, 20, 85); } gpGeneral->UpdateScreen(DRAW_LOCATION(0), 265, TILE_WIDTH * 11, TILE_HEIGHT_SHOWN * 2 - 22);}playeraction CPlayer::Action(actionstate state){ switch (state) { case AS_DRAW: return ActionDraw(); break; case AS_DISCARD: return ActionDiscard(); break; default: assert(false); break; } return PA_NONE;}playeraction CPlayer::ActionDraw(){ int act = PA_DRAW, i; if (m_Hand.m_iNumTileSets <= 0 && !m_fReach && !(m_iState & PS_KONGED) && m_iNumSanGenRush > 0 && --m_iCountSanGenRush <= 0) { if (SanGenRush() && m_iNumSanGenRush > 0) { m_iCountSanGenRush = RandomLong(2, 7); m_iNumSanGenRush -= 3; } } while (1) { SDLKey key; DrawAction((playeraction)act); if ((m_iState & PS_KONGED) || (m_iNumDiscarded == 0 && m_pOpponent->m_iNumDiscarded == 0) || (m_fAutoDraw && m_fReach && !ActionIsValid(AS_DRAW, PA_MAHJONG))) { UTIL_Delay(500); key = SDLK_n; } else { key = gpGeneral->ReadKey(); } switch (key) { case SDLK_y: if ((m_iState & (PS_ASKED | PS_KONGED)) == 0) gpGame->DonDen(); if (m_Hand.m_iNumTileSets <= 0 && !m_fReach && !(m_iState & PS_KONGED) && m_iNumSanGenRush > 0 && --m_iCountSanGenRush <= 0) { if (SanGenRush() && m_iNumSanGenRush > 0) { m_iCountSanGenRush = RandomLong(2, 7); m_iNumSanGenRush -= 3; } } continue; case SDLK_n: if (IsRoundDraw()) { return PA_NONE; } for (i = 0; i < m_Hand.m_iNumTiles; i++) { m_Hand.m_Tiles[i].flags &= ~HT_JUSTGOT; } if (gpGame->m_fReachBonus && m_fReach) { gpGame->m_fReachBonus = false; CTile t[13]; int count; count = m_Hand.GetWaitingTile(t); assert(count > 0); i = RandomLong(0, count - 1); if (CTile::FetchTile(t[i])) { m_Hand.AddTile(t[i], HT_JUSTGOT); } else { m_Hand.AddRandomTile(HT_JUSTGOT); gpGame->m_fReachBonus = true; } } else { m_Hand.AddRandomTile(HT_JUSTGOT); } m_iState &= (PS_CALLREACH | PS_KONGED | PS_NOTDISCARDED); return PA_DRAW; break; case SDLK_UP: case SDLK_KP8: case SDLK_RIGHT: do { act++; if (act >= PA_COUNT) { act = PA_NONE + 1; } } while (!ActionIsValid(AS_DRAW, (playeraction)act)); break; case SDLK_DOWN: case SDLK_KP2: case SDLK_LEFT: do { act--; if (act <= PA_NONE) { act = PA_COUNT - 1; } } while (!ActionIsValid(AS_DRAW, (playeraction)act)); break; case SDLK_SPACE: case SDLK_RETURN: case SDLK_KP_ENTER: switch (act) { case PA_DRAW: if (IsRoundDraw()) { return PA_NONE; } for (i = 0; i < m_Hand.m_iNumTiles; i++) { m_Hand.m_Tiles[i].flags &= ~HT_JUSTGOT; } m_Hand.AddRandomTile(HT_JUSTGOT); m_iState &= (PS_CALLREACH | PS_KONGED | PS_NOTDISCARDED); return PA_DRAW; case PA_PUNG: if (m_Hand.Pung(m_pOpponent->LastDiscardedTile())) { m_pOpponent->m_iNumDiscarded--; m_iState |= PS_ASKED; return PA_PUNG; } break; case PA_CHOW: if (ActionChow() != PA_NONE) { m_iState |= PS_ASKED; return PA_CHOW; } break; case PA_KONG: if (m_Hand.Kong(m_pOpponent->LastDiscardedTile(), true)) { m_pOpponent->m_iNumDiscarded--; m_iState |= (PS_KONGED | PS_ASKED); return PA_KONG; } break; case PA_MAHJONG: m_Hand.AddTile(m_pOpponent->LastDiscardedTile()); return PA_MAHJONG; break; } break; } } return PA_NONE;}playeraction CPlayer::ActionDiscard(){ int act = PA_DISCARD; bool reach = false; while (1) { DrawAction((playeraction)act); SDLKey key; if (m_fReach && m_fAutoDraw && !ActionIsValid(AS_DISCARD, PA_MAHJONG) && !ActionIsValid(AS_DISCARD, PA_KONG)) { UTIL_Delay(500); key = SDLK_n; } else { key = gpGeneral->ReadKey(); } int index; switch (key) { case SDLK_y: if (!reach && ((m_iState & (PS_ASKED | PS_KONGED)) == 0)) gpGame->DonDen(); continue; case SDLK_UP: case SDLK_KP8: case SDLK_RIGHT: if (!reach) { do {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -