diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index bd86303..3847ffe 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -8,7 +8,8 @@ "doudizhu": { "ai_hand_faceup": "Hand Face-Up", - "ai_prediction": "AI Prediction", + "ai_prediction": "Prediction", + "card_recorder": "Card Recorder", "play_as_landlord": "Play As Landlord", "play_as_peasant": "Play As Peasant", "landlord_up": "Landlord Up", diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json index cda6781..661ae2d 100644 --- a/src/locales/zh/translation.json +++ b/src/locales/zh/translation.json @@ -7,8 +7,9 @@ "reset": "重置", "doudizhu": { - "ai_hand_faceup": "显示手牌", - "ai_prediction": "显示预测", + "ai_hand_faceup": "明牌", + "ai_prediction": "预测", + "card_recorder": "记牌器", "play_as_landlord": "扮演地主", "play_as_peasant": "扮演农民", "landlord_up": "地主上家", diff --git a/src/utils/index.js b/src/utils/index.js index 9c87dea..74e016d 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -45,6 +45,36 @@ export function deepCopy(toCopy) { return JSON.parse(JSON.stringify(toCopy)); } +export function translateDouzeroCardData(card) { + let rankClass; + let suitClass = ''; + let rankText; + let suitText = ''; + // translate rank + if (card === 'D') { + rankClass = 'big'; + rankText = '+'; + suitClass = 'joker'; + suitText = 'Joker'; + } else if (card === 'X') { + rankClass = 'little'; + rankText = '-'; + suitClass = 'joker'; + suitText = 'Joker'; + } else { + rankClass = card.charAt(0) === 'T' ? `10` : card.charAt(0).toLowerCase(); + rankClass = `rank-${rankClass}`; + rankText = 'H'; + } + // translate suitClass + if (card !== 'X' && card !== 'D') { + suitClass = suitMap.get('H'); + suitText = suitMapSymbol.get('H'); + } + + return [rankClass, suitClass, rankText, suitText]; +} + export function translateCardData(card) { let rankClass; let suitClass = ''; @@ -110,6 +140,8 @@ export function card2SuiteAndRank(card) { } } +export const fullDouzeroDeck = ['3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A', '2', 'X', 'D'] + export const fullDoudizhuDeck = [ 'RJ', 'BJ', diff --git a/src/view/PvEView/PvEDoudizhuDemoView.js b/src/view/PvEView/PvEDoudizhuDemoView.js index 9a796a9..f528ffd 100644 --- a/src/view/PvEView/PvEDoudizhuDemoView.js +++ b/src/view/PvEView/PvEDoudizhuDemoView.js @@ -23,6 +23,7 @@ import { card2SuiteAndRank, computeHandCardsWidth, deepCopy, + fullDouzeroDeck, fullDoudizhuDeck, isDoudizhuBomb, shuffleArray, @@ -67,6 +68,7 @@ let legalActions = { turn: -1, actions: [] }; let hintIdx = -1; let gameEndDialogTitle = ''; let syncGameStatus = localStorage.getItem('LOCALE') ? 'ready' : 'localeSelection'; +let cardRecorder = {}; function PvEDoudizhuDemoView() { const { t, i18n } = useTranslation(); @@ -87,6 +89,7 @@ function PvEDoudizhuDemoView() { const [predictionRes, setPredictionRes] = useState({ prediction: [], hands: [] }); const [hideRivalHand, setHideRivalHand] = useState(true); const [hidePredictionArea, setHidePredictionArea] = useState(true); + const [showCardRecorder, setShowCardRecorder] = useState(true); const [locale, setLocale] = useState(localStorage.getItem('LOCALE') || 'en'); const [statisticRows, setStatisticRows] = useState([]); @@ -350,6 +353,23 @@ function PvEDoudizhuDemoView() { setIsGameEndDialogOpen(true); }, 2000); } else { + // update card recorder + if(showCardRecorder) { + + const cardArr = cardArr2DouzeroFormat( + sortDoudizhuCards( + gameState.hands[(gameState.currentPlayer + 1) % 4].concat( + gameState.hands[(gameState.currentPlayer + 2) % 4], + gameState.hands[(gameState.currentPlayer + 3) % 4], + ), + true, + ), + ) + fullDouzeroDeck.forEach((card) => { + cardRecorder[card] = cardArr.split('').reduce((acc, ch) => ch === 'card' ? acc + 1: acc, 0) + }) + } + setConsiderationTime(initConsiderationTime); // manually trigger timer if consideration time equals initConsiderationTime if (initConsiderationTime === considerationTime) gameStateTimer(); @@ -518,6 +538,10 @@ function PvEDoudizhuDemoView() { setHidePredictionArea(!hidePredictionArea); }; + const toggleShowCardRecorder = () => { + setShowCardRecorder(!showCardRecorder); + }; + const handleSelectedCards = (cards) => { let newSelectedCards = selectedCards.slice(); cards.forEach((card) => { @@ -679,7 +703,7 @@ function PvEDoudizhuDemoView() { }); setSelectedCards([]); // user selected hand card setPredictionRes({ prediction: [], hands: [] }); - setHideRivalHand(hideRivalHand); + setHideRivalHand(true); setGameStatus('ready'); syncGameStatus = 'ready'; @@ -844,6 +868,27 @@ function PvEDoudizhuDemoView() { } }; + const computeCardRecorderCards = (cards) => { + return ( +
+ +
+ ); + }; + const computeProbabilityItem = (idx) => { if (gameStatus !== 'ready') { if (hidePredictionArea) { @@ -880,6 +925,29 @@ function PvEDoudizhuDemoView() { } }; + const computeCardRecorder = () => { + if (gameStatus !== 'ready') { + if (!showCardRecorder) { + return ( +
+
+ {t('hidden')} +
+
+ ); + } + return ( +
+
+ {computeCardRecorderCards(cardRecorder)} +
+
+ ); + } else { + return {t('waiting...')}; + } + }; + const gameSpeedMarks = [ { value: 0, @@ -1053,7 +1121,7 @@ function PvEDoudizhuDemoView() {
{computeProbabilityItem(0)}
{computeProbabilityItem(1)}
{computeProbabilityItem(2)}
-
{computeProbabilityItem(3)}
+
{computeCardRecorder()}
@@ -1079,6 +1147,14 @@ function PvEDoudizhuDemoView() { } label={t('doudizhu.ai_prediction')} /> + + } + label={t('doudizhu.card_recorder')} + />