中间状态,添加记牌器
This commit is contained in:
parent
a1fdb90abe
commit
c3fbd52383
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
"doudizhu": {
|
"doudizhu": {
|
||||||
"ai_hand_faceup": "Hand Face-Up",
|
"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_landlord": "Play As Landlord",
|
||||||
"play_as_peasant": "Play As Peasant",
|
"play_as_peasant": "Play As Peasant",
|
||||||
"landlord_up": "Landlord Up",
|
"landlord_up": "Landlord Up",
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
"reset": "重置",
|
"reset": "重置",
|
||||||
|
|
||||||
"doudizhu": {
|
"doudizhu": {
|
||||||
"ai_hand_faceup": "显示手牌",
|
"ai_hand_faceup": "明牌",
|
||||||
"ai_prediction": "显示预测",
|
"ai_prediction": "预测",
|
||||||
|
"card_recorder": "记牌器",
|
||||||
"play_as_landlord": "扮演地主",
|
"play_as_landlord": "扮演地主",
|
||||||
"play_as_peasant": "扮演农民",
|
"play_as_peasant": "扮演农民",
|
||||||
"landlord_up": "地主上家",
|
"landlord_up": "地主上家",
|
||||||
|
|
|
@ -45,6 +45,36 @@ export function deepCopy(toCopy) {
|
||||||
return JSON.parse(JSON.stringify(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) {
|
export function translateCardData(card) {
|
||||||
let rankClass;
|
let rankClass;
|
||||||
let suitClass = '';
|
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 = [
|
export const fullDoudizhuDeck = [
|
||||||
'RJ',
|
'RJ',
|
||||||
'BJ',
|
'BJ',
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
card2SuiteAndRank,
|
card2SuiteAndRank,
|
||||||
computeHandCardsWidth,
|
computeHandCardsWidth,
|
||||||
deepCopy,
|
deepCopy,
|
||||||
|
fullDouzeroDeck,
|
||||||
fullDoudizhuDeck,
|
fullDoudizhuDeck,
|
||||||
isDoudizhuBomb,
|
isDoudizhuBomb,
|
||||||
shuffleArray,
|
shuffleArray,
|
||||||
|
@ -67,6 +68,7 @@ let legalActions = { turn: -1, actions: [] };
|
||||||
let hintIdx = -1;
|
let hintIdx = -1;
|
||||||
let gameEndDialogTitle = '';
|
let gameEndDialogTitle = '';
|
||||||
let syncGameStatus = localStorage.getItem('LOCALE') ? 'ready' : 'localeSelection';
|
let syncGameStatus = localStorage.getItem('LOCALE') ? 'ready' : 'localeSelection';
|
||||||
|
let cardRecorder = {};
|
||||||
|
|
||||||
function PvEDoudizhuDemoView() {
|
function PvEDoudizhuDemoView() {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
@ -87,6 +89,7 @@ function PvEDoudizhuDemoView() {
|
||||||
const [predictionRes, setPredictionRes] = useState({ prediction: [], hands: [] });
|
const [predictionRes, setPredictionRes] = useState({ prediction: [], hands: [] });
|
||||||
const [hideRivalHand, setHideRivalHand] = useState(true);
|
const [hideRivalHand, setHideRivalHand] = useState(true);
|
||||||
const [hidePredictionArea, setHidePredictionArea] = useState(true);
|
const [hidePredictionArea, setHidePredictionArea] = useState(true);
|
||||||
|
const [showCardRecorder, setShowCardRecorder] = useState(true);
|
||||||
const [locale, setLocale] = useState(localStorage.getItem('LOCALE') || 'en');
|
const [locale, setLocale] = useState(localStorage.getItem('LOCALE') || 'en');
|
||||||
const [statisticRows, setStatisticRows] = useState([]);
|
const [statisticRows, setStatisticRows] = useState([]);
|
||||||
|
|
||||||
|
@ -350,6 +353,23 @@ function PvEDoudizhuDemoView() {
|
||||||
setIsGameEndDialogOpen(true);
|
setIsGameEndDialogOpen(true);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
} else {
|
} 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);
|
setConsiderationTime(initConsiderationTime);
|
||||||
// manually trigger timer if consideration time equals initConsiderationTime
|
// manually trigger timer if consideration time equals initConsiderationTime
|
||||||
if (initConsiderationTime === considerationTime) gameStateTimer();
|
if (initConsiderationTime === considerationTime) gameStateTimer();
|
||||||
|
@ -518,6 +538,10 @@ function PvEDoudizhuDemoView() {
|
||||||
setHidePredictionArea(!hidePredictionArea);
|
setHidePredictionArea(!hidePredictionArea);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleShowCardRecorder = () => {
|
||||||
|
setShowCardRecorder(!showCardRecorder);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSelectedCards = (cards) => {
|
const handleSelectedCards = (cards) => {
|
||||||
let newSelectedCards = selectedCards.slice();
|
let newSelectedCards = selectedCards.slice();
|
||||||
cards.forEach((card) => {
|
cards.forEach((card) => {
|
||||||
|
@ -679,7 +703,7 @@ function PvEDoudizhuDemoView() {
|
||||||
});
|
});
|
||||||
setSelectedCards([]); // user selected hand card
|
setSelectedCards([]); // user selected hand card
|
||||||
setPredictionRes({ prediction: [], hands: [] });
|
setPredictionRes({ prediction: [], hands: [] });
|
||||||
setHideRivalHand(hideRivalHand);
|
setHideRivalHand(true);
|
||||||
|
|
||||||
setGameStatus('ready');
|
setGameStatus('ready');
|
||||||
syncGameStatus = 'ready';
|
syncGameStatus = 'ready';
|
||||||
|
@ -844,6 +868,27 @@ function PvEDoudizhuDemoView() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const computeCardRecorderCards = (cards) => {
|
||||||
|
return (
|
||||||
|
<div className={'unselectable playingCards loose ' + toggleFade}>
|
||||||
|
<ul className="hand" style={{ width: computeHandCardsWidth(computedCards.length, 10) }}>
|
||||||
|
{cards.map((card) => {
|
||||||
|
const [rankClass, suitClass, rankText, suitText] = translateDouzeroCardData(card);
|
||||||
|
return (
|
||||||
|
<li key={`handCard-${card}`}>
|
||||||
|
<label className={`card ${rankClass} ${suitClass}`} href="/#">
|
||||||
|
<span className="rank">{rankText}</span>
|
||||||
|
<span className="suit">{suitText}</span>
|
||||||
|
<span className="count">{cards[card]}</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const computeProbabilityItem = (idx) => {
|
const computeProbabilityItem = (idx) => {
|
||||||
if (gameStatus !== 'ready') {
|
if (gameStatus !== 'ready') {
|
||||||
if (hidePredictionArea) {
|
if (hidePredictionArea) {
|
||||||
|
@ -880,6 +925,29 @@ function PvEDoudizhuDemoView() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const computeCardRecorder = () => {
|
||||||
|
if (gameStatus !== 'ready') {
|
||||||
|
if (!showCardRecorder) {
|
||||||
|
return (
|
||||||
|
<div className={'playing'}>
|
||||||
|
<div className={'non-card'}>
|
||||||
|
<span>{t('hidden')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={'playing'}>
|
||||||
|
<div className="probability-move">
|
||||||
|
{computeCardRecorderCards(cardRecorder)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <span className={'waiting'}>{t('waiting...')}</span>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const gameSpeedMarks = [
|
const gameSpeedMarks = [
|
||||||
{
|
{
|
||||||
value: 0,
|
value: 0,
|
||||||
|
@ -1053,7 +1121,7 @@ function PvEDoudizhuDemoView() {
|
||||||
<div className={'probability-item'}>{computeProbabilityItem(0)}</div>
|
<div className={'probability-item'}>{computeProbabilityItem(0)}</div>
|
||||||
<div className={'probability-item'}>{computeProbabilityItem(1)}</div>
|
<div className={'probability-item'}>{computeProbabilityItem(1)}</div>
|
||||||
<div className={'probability-item'}>{computeProbabilityItem(2)}</div>
|
<div className={'probability-item'}>{computeProbabilityItem(2)}</div>
|
||||||
<div className={'probability-item'}>{computeProbabilityItem(3)}</div>
|
<div className={'probability-item'}>{computeCardRecorder()}</div>
|
||||||
</div>
|
</div>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Layout.Col>
|
</Layout.Col>
|
||||||
|
@ -1079,6 +1147,14 @@ function PvEDoudizhuDemoView() {
|
||||||
}
|
}
|
||||||
label={t('doudizhu.ai_prediction')}
|
label={t('doudizhu.ai_prediction')}
|
||||||
/>
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
style={{ textAlign: 'center', height: '100%', display: 'inline-block' }}
|
||||||
|
className="switch-control"
|
||||||
|
control={
|
||||||
|
<Switch checked={!showCardRecorder} onChange={toggleShowCardRecorder} />
|
||||||
|
}
|
||||||
|
label={t('doudizhu.card_recorder')}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Layout.Col>
|
</Layout.Col>
|
||||||
<Layout.Col span="1" style={{ height: '100%', width: '1px' }}>
|
<Layout.Col span="1" style={{ height: '100%', width: '1px' }}>
|
||||||
|
|
Loading…
Reference in New Issue