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