connect legal action api; add error messages for api request
This commit is contained in:
parent
14ce853ce9
commit
9e2e8dccf9
|
@ -1,60 +1,52 @@
|
|||
import Avatar from '@material-ui/core/Avatar';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Chip from '@material-ui/core/Chip';
|
||||
import React from 'react';
|
||||
import { translateCardData, millisecond2Second, computeHandCardsWidth } from '../../utils'
|
||||
|
||||
import '../../assets/doudizhu.scss';
|
||||
import Landlord_wName from '../../assets/images/Portrait/Landlord_wName.png';
|
||||
import Peasant_wName from '../../assets/images/Portrait/Peasant_wName.png';
|
||||
import PlaceHolderPlayer from '../../assets/images/Portrait/Player.png';
|
||||
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Chip from '@material-ui/core/Chip';
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import { computeHandCardsWidth, millisecond2Second, translateCardData } from '../../utils';
|
||||
|
||||
class DoudizhuGameBoard extends React.Component {
|
||||
computePlayerPortrait(playerId, playerIdx) {
|
||||
if (this.props.playerInfo.length > 0) {
|
||||
return this.props.playerInfo[playerIdx].role === "landlord" ?
|
||||
return this.props.playerInfo[playerIdx].role === 'landlord' ? (
|
||||
<div>
|
||||
<img src={Landlord_wName} alt={"Landlord"} height="70%" width="70%" />
|
||||
<Chip
|
||||
avatar={<Avatar>ID</Avatar>}
|
||||
label={playerId}
|
||||
clickable
|
||||
color="primary"
|
||||
/>
|
||||
<img src={Landlord_wName} alt={'Landlord'} height="70%" width="70%" />
|
||||
<Chip avatar={<Avatar>ID</Avatar>} label={playerId} clickable color="primary" />
|
||||
</div>
|
||||
:
|
||||
) : (
|
||||
<div>
|
||||
<img src={Peasant_wName} alt={"Peasant"} height="70%" width="70%" />
|
||||
<Chip
|
||||
avatar={<Avatar>ID</Avatar>}
|
||||
label={playerId}
|
||||
clickable
|
||||
color="primary"
|
||||
/>
|
||||
<img src={Peasant_wName} alt={'Peasant'} height="70%" width="70%" />
|
||||
<Chip avatar={<Avatar>ID</Avatar>} label={playerId} clickable color="primary" />
|
||||
</div>
|
||||
);
|
||||
} else
|
||||
return (
|
||||
<div>
|
||||
<img src={PlaceHolderPlayer} alt={"Player"} height="70%" width="70%" />
|
||||
<Chip
|
||||
avatar={<Avatar>ID</Avatar>}
|
||||
label={playerId}
|
||||
clickable
|
||||
color="primary"
|
||||
/>
|
||||
<img src={PlaceHolderPlayer} alt={'Player'} height="70%" width="70%" />
|
||||
<Chip avatar={<Avatar>ID</Avatar>} label={playerId} clickable color="primary" />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
computeSingleLineHand(cards, fadeClassName="", cardSelectable = false) {
|
||||
if(cards === "pass"){
|
||||
return <div className="non-card"><span>PASS</span></div>
|
||||
computeSingleLineHand(cards, fadeClassName = '', cardSelectable = false) {
|
||||
if (cards === 'pass') {
|
||||
return (
|
||||
<div className="non-card">
|
||||
<span>PASS</span>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={`playingCards loose ${fadeClassName} ${this.props.gamePlayable && cardSelectable ? 'selectable' : 'unselectable'}`}>
|
||||
<div
|
||||
className={`playingCards loose ${fadeClassName} ${
|
||||
this.props.gamePlayable && cardSelectable ? 'selectable' : 'unselectable'
|
||||
}`}
|
||||
>
|
||||
<ul className="hand" style={{ width: computeHandCardsWidth(cards.length, 12) }}>
|
||||
{cards.map(card=>{
|
||||
{cards.map((card) => {
|
||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
||||
let selected = false;
|
||||
if (this.props.gamePlayable && cardSelectable) {
|
||||
|
@ -64,7 +56,10 @@ class DoudizhuGameBoard extends React.Component {
|
|||
// todo: right click and move to select multiple cards
|
||||
return (
|
||||
<li key={`handCard-${card}`}>
|
||||
<label onClick={() => this.props.handleSelectedCards([card])} className={`card ${rankClass} ${suitClass} ${selected ? 'selected' : ''}`}>
|
||||
<label
|
||||
onClick={() => this.props.handleSelectedCards([card])}
|
||||
className={`card ${rankClass} ${suitClass} ${selected ? 'selected' : ''}`}
|
||||
>
|
||||
<span className="rank">{rankText}</span>
|
||||
<span className="suit">{suitText}</span>
|
||||
</label>
|
||||
|
@ -73,7 +68,7 @@ class DoudizhuGameBoard extends React.Component {
|
|||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +77,7 @@ class DoudizhuGameBoard extends React.Component {
|
|||
let downCards = [];
|
||||
if (cards.length > 10) {
|
||||
upCards = cards.slice(0, 10);
|
||||
downCards = cards.slice(10, );
|
||||
downCards = cards.slice(10);
|
||||
} else {
|
||||
upCards = cards;
|
||||
}
|
||||
|
@ -91,7 +86,7 @@ class DoudizhuGameBoard extends React.Component {
|
|||
<div className="player-hand-up">
|
||||
<div className="playingCards unselectable loose">
|
||||
<ul className="hand">
|
||||
{upCards.map(card => {
|
||||
{upCards.map((card) => {
|
||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
||||
return (
|
||||
<li key={`handCard-${card}`}>
|
||||
|
@ -108,7 +103,7 @@ class DoudizhuGameBoard extends React.Component {
|
|||
<div className="player-hand-down">
|
||||
<div className="playingCards unselectable loose">
|
||||
<ul className="hand">
|
||||
{downCards.map(card => {
|
||||
{downCards.map((card) => {
|
||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
||||
return (
|
||||
<li key={`handCard-${card}`}>
|
||||
|
@ -123,41 +118,69 @@ class DoudizhuGameBoard extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
playerDecisionArea(playerIdx) {
|
||||
let fadeClassName = "";
|
||||
if(this.props.toggleFade === "fade-out" && (playerIdx+2)%3 === this.props.currentPlayer)
|
||||
fadeClassName = "fade-out";
|
||||
else if(this.props.toggleFade === "fade-in" && (playerIdx+1)%3 === this.props.currentPlayer)
|
||||
fadeClassName = "scale-fade-in";
|
||||
let fadeClassName = '';
|
||||
if (this.props.toggleFade === 'fade-out' && (playerIdx + 2) % 3 === this.props.currentPlayer)
|
||||
fadeClassName = 'fade-out';
|
||||
else if (this.props.toggleFade === 'fade-in' && (playerIdx + 1) % 3 === this.props.currentPlayer)
|
||||
fadeClassName = 'scale-fade-in';
|
||||
if (this.props.currentPlayer === playerIdx) {
|
||||
if (this.props.mainPlayerId === this.props.playerInfo[this.props.currentPlayer].id) {
|
||||
return (
|
||||
<div className={"main-player-action-wrapper"}>
|
||||
<div style={{marginRight: '2em'}} className={"timer "+fadeClassName}>
|
||||
<div className={'main-player-action-wrapper'}>
|
||||
<div style={{ marginRight: '2em' }} className={'timer ' + fadeClassName}>
|
||||
<div className="timer-text">{millisecond2Second(this.props.considerationTime)}</div>
|
||||
</div>
|
||||
<Button onClick={() => {this.props.handleMainPlayerAct('deselect')}} style={{marginRight: '2em'}} variant="contained" color="primary">Deselect</Button>
|
||||
<Button onClick={() => {this.props.handleMainPlayerAct('pass');}} style={{marginRight: '2em'}} variant="contained" color="primary">Pass</Button>
|
||||
<Button onClick={() => {this.props.handleMainPlayerAct('play');}} variant="contained" color="primary">Play</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
this.props.handleMainPlayerAct('deselect');
|
||||
}}
|
||||
style={{ marginRight: '2em' }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
Deselect
|
||||
</Button>
|
||||
<Button
|
||||
disabled={this.props.isPassDisabled}
|
||||
onClick={() => {
|
||||
this.props.handleMainPlayerAct('pass');
|
||||
}}
|
||||
style={{ marginRight: '2em' }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
Pass
|
||||
</Button>
|
||||
<Button
|
||||
disabled={this.props.selectedCards.length === 0}
|
||||
onClick={() => {
|
||||
this.props.handleMainPlayerAct('play');
|
||||
}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
Play
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={"timer "+fadeClassName}>
|
||||
<div className={'timer ' + fadeClassName}>
|
||||
<div className="timer-text">{millisecond2Second(this.props.considerationTime)}</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return this.computeSingleLineHand(this.props.latestAction[playerIdx], fadeClassName)
|
||||
return this.computeSingleLineHand(this.props.latestAction[playerIdx], fadeClassName);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if(prevProps.turn !== this.props.turn && this.props.turn !== 0 && this.props.gameStatus === "playing"){
|
||||
if (prevProps.turn !== this.props.turn && this.props.turn !== 0 && this.props.gameStatus === 'playing') {
|
||||
// new turn starts
|
||||
this.props.runNewTurn(prevProps);
|
||||
}
|
||||
|
@ -166,7 +189,7 @@ class DoudizhuGameBoard extends React.Component {
|
|||
render() {
|
||||
// compute the id as well as index in list for every player
|
||||
const bottomId = this.props.mainPlayerId;
|
||||
let found = this.props.playerInfo.find(element=>{
|
||||
let found = this.props.playerInfo.find((element) => {
|
||||
return element.id === bottomId;
|
||||
});
|
||||
const bottomIdx = found ? found.index : -1;
|
||||
|
@ -175,50 +198,56 @@ class DoudizhuGameBoard extends React.Component {
|
|||
let rightId = -1;
|
||||
let leftId = -1;
|
||||
if (rightIdx >= 0 && leftIdx >= 0) {
|
||||
found = this.props.playerInfo.find(element=>{
|
||||
found = this.props.playerInfo.find((element) => {
|
||||
return element.index === rightIdx;
|
||||
});
|
||||
if(found)
|
||||
rightId = found.id;
|
||||
found = this.props.playerInfo.find(element=>{
|
||||
if (found) rightId = found.id;
|
||||
found = this.props.playerInfo.find((element) => {
|
||||
return element.index === leftIdx;
|
||||
});
|
||||
if(found)
|
||||
leftId = found.id;
|
||||
if (found) leftId = found.id;
|
||||
}
|
||||
return (
|
||||
<div className="doudizhu-wrapper" style={{}}>
|
||||
<div id={"left-player"}>
|
||||
<div id={'left-player'}>
|
||||
<div className="player-main-area">
|
||||
<div className="player-info">
|
||||
{this.computePlayerPortrait(leftId, leftIdx)}
|
||||
<div className="player-info">{this.computePlayerPortrait(leftId, leftIdx)}</div>
|
||||
{leftIdx >= 0 ? (
|
||||
this.computeSideHand(this.props.hands[leftIdx])
|
||||
) : (
|
||||
<div className="player-hand-placeholder">
|
||||
<span>Waiting...</span>
|
||||
</div>
|
||||
{leftIdx >= 0 ? this.computeSideHand(this.props.hands[leftIdx]) : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
||||
)}
|
||||
</div>
|
||||
<div className="played-card-area">
|
||||
{leftIdx >= 0 ? this.playerDecisionArea(leftIdx) : ""}
|
||||
<div className="played-card-area">{leftIdx >= 0 ? this.playerDecisionArea(leftIdx) : ''}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id={"right-player"}>
|
||||
<div id={'right-player'}>
|
||||
<div className="player-main-area">
|
||||
<div className="player-info">
|
||||
{this.computePlayerPortrait(rightId, rightIdx)}
|
||||
<div className="player-info">{this.computePlayerPortrait(rightId, rightIdx)}</div>
|
||||
{rightIdx >= 0 ? (
|
||||
this.computeSideHand(this.props.hands[rightIdx])
|
||||
) : (
|
||||
<div className="player-hand-placeholder">
|
||||
<span>Waiting...</span>
|
||||
</div>
|
||||
{rightIdx >= 0 ? this.computeSideHand(this.props.hands[rightIdx]) : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
||||
)}
|
||||
</div>
|
||||
<div className="played-card-area">
|
||||
{rightIdx >= 0 ? this.playerDecisionArea(rightIdx) : ""}
|
||||
</div>
|
||||
</div>
|
||||
<div id={"bottom-player"}>
|
||||
<div className="played-card-area">
|
||||
{bottomIdx >= 0 ? this.playerDecisionArea(bottomIdx) : ""}
|
||||
<div className="played-card-area">{rightIdx >= 0 ? this.playerDecisionArea(rightIdx) : ''}</div>
|
||||
</div>
|
||||
<div id={'bottom-player'}>
|
||||
<div className="played-card-area">{bottomIdx >= 0 ? this.playerDecisionArea(bottomIdx) : ''}</div>
|
||||
<div className="player-main-area">
|
||||
<div className="player-info">
|
||||
{this.computePlayerPortrait(bottomId, bottomIdx)}
|
||||
<div className="player-info">{this.computePlayerPortrait(bottomId, bottomIdx)}</div>
|
||||
{bottomIdx >= 0 ? (
|
||||
<div className="player-hand">
|
||||
{this.computeSingleLineHand(this.props.hands[bottomIdx], '', true)}
|
||||
</div>
|
||||
{bottomIdx >= 0 ? <div className="player-hand">{this.computeSingleLineHand(this.props.hands[bottomIdx], '', true)}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
||||
) : (
|
||||
<div className="player-hand-placeholder">
|
||||
<span>Waiting...</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Paper from '@material-ui/core/Paper';
|
||||
import axios from 'axios';
|
||||
import { Layout } from 'element-react';
|
||||
import { Layout, Message } from 'element-react';
|
||||
import qs from 'query-string';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { DoudizhuGameBoard } from '../../components/GameBoard';
|
||||
|
@ -13,9 +13,10 @@ const initHands = [
|
|||
'RJ BJ D2 SA SK CK SJ HJ DJ CT DT C9 S8 H8 C8 D7 D5 H3 S3 D3',
|
||||
];
|
||||
|
||||
const initConsiderationTime = 2000;
|
||||
const considerationTimeDeduction = 200;
|
||||
const mainPlayerId = 0;
|
||||
const initConsiderationTime = 30000;
|
||||
const considerationTimeDeduction = 1000;
|
||||
const apiPlayDelay = 3000;
|
||||
const mainPlayerId = 0; // index of main player (for the sake of simplify code logic)
|
||||
const playerInfo = [
|
||||
{
|
||||
id: 0,
|
||||
|
@ -48,6 +49,7 @@ let lastMoveLandlordUp = [];
|
|||
let playedCardsLandlord = [];
|
||||
let playedCardsLandlordDown = [];
|
||||
let playedCardsLandlordUp = [];
|
||||
let legalActions = { turn: -1, actions: [] };
|
||||
|
||||
function PvEDoudizhuDemoView() {
|
||||
const [considerationTime, setConsiderationTime] = useState(initConsiderationTime);
|
||||
|
@ -60,6 +62,7 @@ function PvEDoudizhuDemoView() {
|
|||
turn: 0,
|
||||
});
|
||||
const [selectedCards, setSelectedCards] = useState([]); // user selected hand card
|
||||
const [isPassDisabled, setIsPassDisabled] = useState(true);
|
||||
|
||||
const cardStr2Arr = (cardStr) => {
|
||||
return cardStr === 'pass' || cardStr === '' ? 'pass' : cardStr.split(' ');
|
||||
|
@ -82,14 +85,42 @@ function PvEDoudizhuDemoView() {
|
|||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
const proceedNextTurn = (playingCard, rankOnly = true) => {
|
||||
const proceedNextTurn = async (playingCard, rankOnly = true) => {
|
||||
// if next player is user, get legal actions
|
||||
if ((gameState.currentPlayer + 1) % 3 === mainPlayerId) {
|
||||
const player_hand_cards = cardArr2DouzeroFormat(gameState.hands[mainPlayerId].slice().reverse());
|
||||
let rival_move = '';
|
||||
if (playingCard.length === 0) {
|
||||
rival_move = cardArr2DouzeroFormat(sortDoudizhuCards(gameHistory[gameHistory.length - 1], true));
|
||||
} else {
|
||||
rival_move = rankOnly ? playingCard.join('') : cardArr2DouzeroFormat(playingCard);
|
||||
}
|
||||
const requestBody = {
|
||||
player_hand_cards,
|
||||
rival_move,
|
||||
};
|
||||
const apiRes = await axios.post(`${douzeroDemoUrl}/legal`, qs.stringify(requestBody));
|
||||
console.log('legal', apiRes);
|
||||
const data = apiRes.data;
|
||||
legalActions = {
|
||||
turn: gameState.turn + 1,
|
||||
actions: data.legal_action.split(','),
|
||||
};
|
||||
|
||||
setIsPassDisabled(playingCard.length === 0 && gameHistory[gameHistory.length - 1].length === 0);
|
||||
}
|
||||
|
||||
// delay play for api player
|
||||
if (gameState.currentPlayer !== mainPlayerId && considerationTime > apiPlayDelay) {
|
||||
await timeout(apiPlayDelay);
|
||||
}
|
||||
|
||||
setToggleFade('fade-out');
|
||||
|
||||
let newGameState = deepCopy(gameState);
|
||||
|
||||
// todo: take played card out from hand, and generate playing cards with suite
|
||||
// take played card out from hand, and generate playing cards with suite
|
||||
const currentHand = newGameState.hands[gameState.currentPlayer];
|
||||
|
||||
let newHand;
|
||||
let newLatestAction = [];
|
||||
if (playingCard.length === 0) {
|
||||
|
@ -123,7 +154,6 @@ function PvEDoudizhuDemoView() {
|
|||
}
|
||||
|
||||
// update value records for douzero
|
||||
// debugger;
|
||||
const newHistoryRecord = newLatestAction === 'pass' ? [] : newLatestAction;
|
||||
switch (playerInfo[gameState.currentPlayer].douzeroPlayerPosition) {
|
||||
case 0:
|
||||
|
@ -153,18 +183,12 @@ function PvEDoudizhuDemoView() {
|
|||
}, 200);
|
||||
if (gameStateTimeout) {
|
||||
clearTimeout(gameStateTimeout);
|
||||
setConsiderationTime(initConsiderationTime);
|
||||
}
|
||||
setConsiderationTime(initConsiderationTime);
|
||||
};
|
||||
|
||||
const requestApiPlay = async () => {
|
||||
// mock delayed API play
|
||||
// await timeout(1200);
|
||||
// const apiRes = [
|
||||
// card2SuiteAndRank(
|
||||
// gameState.hands[gameState.currentPlayer][gameState.hands[gameState.currentPlayer].length - 1],
|
||||
// ).rank,
|
||||
// ];
|
||||
// gather information for api request
|
||||
const player_position = playerInfo[gameState.currentPlayer].douzeroPlayerPosition;
|
||||
const player_hand_cards = cardArr2DouzeroFormat(gameState.hands[gameState.currentPlayer].slice().reverse());
|
||||
const num_cards_left_landlord =
|
||||
|
@ -217,10 +241,37 @@ function PvEDoudizhuDemoView() {
|
|||
const apiRes = await axios.post(`${douzeroDemoUrl}/predict`, qs.stringify(requestBody));
|
||||
console.log(apiRes.data);
|
||||
const data = apiRes.data;
|
||||
|
||||
if (data.status !== 0) {
|
||||
if (data.status === -1) {
|
||||
// todo: check if no legal action can be made
|
||||
proceedNextTurn([]);
|
||||
// check if no legal action can be made
|
||||
const player_hand_cards = cardArr2DouzeroFormat(
|
||||
gameState.hands[gameState.currentPlayer].slice().reverse(),
|
||||
);
|
||||
let rival_move = '';
|
||||
if (gameHistory[gameHistory.length - 1].length > 0) {
|
||||
rival_move = cardArr2DouzeroFormat(
|
||||
sortDoudizhuCards(gameHistory[gameHistory.length - 1], true),
|
||||
);
|
||||
} else if (gameHistory.length > 2 && gameHistory[gameHistory.length - 2].length > 0) {
|
||||
rival_move = cardArr2DouzeroFormat(
|
||||
sortDoudizhuCards(gameHistory[gameHistory.length - 2], true),
|
||||
);
|
||||
}
|
||||
const requestBody = {
|
||||
player_hand_cards,
|
||||
rival_move,
|
||||
};
|
||||
const apiRes = await axios.post(`${douzeroDemoUrl}/legal`, qs.stringify(requestBody));
|
||||
console.log('api player legal', apiRes);
|
||||
if (apiRes.data.legal_action === '') proceedNextTurn([]);
|
||||
else {
|
||||
Message({
|
||||
message: 'Error receiving prediction result, please try refresh the page',
|
||||
type: 'error',
|
||||
showClose: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
console.log(data.status, data.message);
|
||||
} else {
|
||||
|
@ -242,7 +293,11 @@ function PvEDoudizhuDemoView() {
|
|||
proceedNextTurn(bestAction.split(''));
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
Message({
|
||||
message: 'Error receiving prediction result, please try refresh the page',
|
||||
type: 'error',
|
||||
showClose: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -294,20 +349,37 @@ function PvEDoudizhuDemoView() {
|
|||
if (gameState.currentPlayer) {
|
||||
// if current player is not user, request for API player
|
||||
if (gameState.currentPlayer !== mainPlayerId) {
|
||||
// debugger;
|
||||
requestApiPlay();
|
||||
}
|
||||
}
|
||||
}, [gameState.currentPlayer]);
|
||||
|
||||
const runNewTurn = () => {
|
||||
// gameStateTimer();
|
||||
};
|
||||
const runNewTurn = () => {};
|
||||
|
||||
const handleMainPlayerAct = (type) => {
|
||||
switch (type) {
|
||||
case 'play': {
|
||||
// check if cards to play is in legal action list
|
||||
if (gameState.turn === legalActions.turn) {
|
||||
if (
|
||||
legalActions.actions.indexOf(cardArr2DouzeroFormat(sortDoudizhuCards(selectedCards, true))) >= 0
|
||||
) {
|
||||
proceedNextTurn(selectedCards, false);
|
||||
} else {
|
||||
Message({
|
||||
message: 'Selected cards are not legal action',
|
||||
type: 'warning',
|
||||
showClose: true,
|
||||
});
|
||||
setSelectedCards([]);
|
||||
}
|
||||
} else {
|
||||
Message({
|
||||
message: 'Legal Action not received or turn info inconsistant',
|
||||
type: 'error',
|
||||
showClose: true,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'pass': {
|
||||
|
@ -330,6 +402,7 @@ function PvEDoudizhuDemoView() {
|
|||
<div style={{ height: '100%' }}>
|
||||
<Paper className={'doudizhu-gameboard-paper'} elevation={3}>
|
||||
<DoudizhuGameBoard
|
||||
isPassDisabled={isPassDisabled}
|
||||
gamePlayable={true}
|
||||
playerInfo={playerInfo}
|
||||
hands={gameState.hands}
|
||||
|
|
Loading…
Reference in New Issue