add hint to doudizhu demo; add citation info
This commit is contained in:
parent
8381c01d38
commit
076ead97f2
|
@ -24,3 +24,26 @@ code {
|
||||||
.el-message {
|
.el-message {
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.citation {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
-webkit-user-select: text;
|
||||||
|
-ms-user-select: text;
|
||||||
|
user-select: text;
|
||||||
|
|
||||||
|
a {
|
||||||
|
&:visited {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #212529;
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
border: solid 1px #e9e9e9;
|
||||||
|
}
|
||||||
|
}
|
|
@ -224,6 +224,18 @@ class DoudizhuGameBoard extends React.Component {
|
||||||
>
|
>
|
||||||
Deselect
|
Deselect
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
disabled={this.props.isHintDisabled}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.props.handleMainPlayerAct('hint');
|
||||||
|
}}
|
||||||
|
style={{ marginRight: '2em' }}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
Hint
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
disabled={this.props.isPassDisabled}
|
disabled={this.props.isPassDisabled}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
|
|
@ -59,6 +59,7 @@ let playedCardsLandlord = [];
|
||||||
let playedCardsLandlordDown = [];
|
let playedCardsLandlordDown = [];
|
||||||
let playedCardsLandlordUp = [];
|
let playedCardsLandlordUp = [];
|
||||||
let legalActions = { turn: -1, actions: [] };
|
let legalActions = { turn: -1, actions: [] };
|
||||||
|
let hintIdx = -1;
|
||||||
let gameEndDialogTitle = '';
|
let gameEndDialogTitle = '';
|
||||||
let statisticRows = [];
|
let statisticRows = [];
|
||||||
let syncGameStatus = 'ready';
|
let syncGameStatus = 'ready';
|
||||||
|
@ -77,6 +78,7 @@ function PvEDoudizhuDemoView() {
|
||||||
});
|
});
|
||||||
const [selectedCards, setSelectedCards] = useState([]); // user selected hand card
|
const [selectedCards, setSelectedCards] = useState([]); // user selected hand card
|
||||||
const [isPassDisabled, setIsPassDisabled] = useState(true);
|
const [isPassDisabled, setIsPassDisabled] = useState(true);
|
||||||
|
const [isHintDisabled, setIsHintDisabled] = useState(true);
|
||||||
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);
|
||||||
|
@ -117,6 +119,7 @@ function PvEDoudizhuDemoView() {
|
||||||
|
|
||||||
// if next player is user, get legal actions
|
// if next player is user, get legal actions
|
||||||
if ((gameState.currentPlayer + 1) % 3 === mainPlayerId) {
|
if ((gameState.currentPlayer + 1) % 3 === mainPlayerId) {
|
||||||
|
hintIdx = -1;
|
||||||
const player_hand_cards = cardArr2DouzeroFormat(gameState.hands[mainPlayerId].slice().reverse());
|
const player_hand_cards = cardArr2DouzeroFormat(gameState.hands[mainPlayerId].slice().reverse());
|
||||||
let rival_move = '';
|
let rival_move = '';
|
||||||
if (playingCard.length === 0) {
|
if (playingCard.length === 0) {
|
||||||
|
@ -134,7 +137,7 @@ function PvEDoudizhuDemoView() {
|
||||||
turn: gameState.turn + 1,
|
turn: gameState.turn + 1,
|
||||||
actions: data.legal_action.split(','),
|
actions: data.legal_action.split(','),
|
||||||
};
|
};
|
||||||
|
setIsHintDisabled(data.legal_action === '');
|
||||||
setIsPassDisabled(playingCard.length === 0 && gameHistory[gameHistory.length - 1].length === 0);
|
setIsPassDisabled(playingCard.length === 0 && gameHistory[gameHistory.length - 1].length === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,6 +564,7 @@ function PvEDoudizhuDemoView() {
|
||||||
setConsiderationTime(initConsiderationTime);
|
setConsiderationTime(initConsiderationTime);
|
||||||
setToggleFade('');
|
setToggleFade('');
|
||||||
setIsPassDisabled(true);
|
setIsPassDisabled(true);
|
||||||
|
setIsHintDisabled(true);
|
||||||
setGameState({
|
setGameState({
|
||||||
hands: [[], [], []],
|
hands: [[], [], []],
|
||||||
latestAction: [[], [], []],
|
latestAction: [[], [], []],
|
||||||
|
@ -598,6 +602,7 @@ function PvEDoudizhuDemoView() {
|
||||||
turn: 0,
|
turn: 0,
|
||||||
actions: data.legal_action.split(','),
|
actions: data.legal_action.split(','),
|
||||||
};
|
};
|
||||||
|
setIsHintDisabled(data.legal_action === '');
|
||||||
}
|
}
|
||||||
|
|
||||||
setGameState(newGameState);
|
setGameState(newGameState);
|
||||||
|
@ -658,6 +663,33 @@ function PvEDoudizhuDemoView() {
|
||||||
setSelectedCards([]);
|
setSelectedCards([]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'hint': {
|
||||||
|
if (gameState.turn === legalActions.turn) {
|
||||||
|
setSelectedCards([]);
|
||||||
|
hintIdx++;
|
||||||
|
if (hintIdx >= legalActions.actions.length) {
|
||||||
|
hintIdx = 0;
|
||||||
|
}
|
||||||
|
const hintRanks = legalActions.actions[hintIdx].split('');
|
||||||
|
let hintCards = [];
|
||||||
|
gameState.hands[gameState.currentPlayer].forEach((card) => {
|
||||||
|
const { rank } = card2SuiteAndRank(card);
|
||||||
|
const idx = hintRanks.indexOf(rank);
|
||||||
|
if (idx >= 0) {
|
||||||
|
hintRanks.splice(idx, 1);
|
||||||
|
hintCards.push(card);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setSelectedCards(hintCards);
|
||||||
|
} else {
|
||||||
|
Message({
|
||||||
|
message: 'Legal Action not received or turn info inconsistant',
|
||||||
|
type: 'error',
|
||||||
|
showClose: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -827,7 +859,7 @@ function PvEDoudizhuDemoView() {
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{statisticRows.map((row) => (
|
{statisticRows.map((row) => (
|
||||||
<TableRow key={row.name}>
|
<TableRow key={'statistic-row-' + row.role}>
|
||||||
<TableCell component="th" scope="row">
|
<TableCell component="th" scope="row">
|
||||||
{row.role}
|
{row.role}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
@ -866,9 +898,10 @@ 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
|
||||||
showCardBack={hideRivalHand}
|
showCardBack={gameStatus === 'playing' && hideRivalHand}
|
||||||
handleSelectRole={handleSelectRole}
|
handleSelectRole={handleSelectRole}
|
||||||
isPassDisabled={isPassDisabled}
|
isPassDisabled={isPassDisabled}
|
||||||
|
isHintDisabled={isHintDisabled}
|
||||||
gamePlayable={true}
|
gamePlayable={true}
|
||||||
playerInfo={playerInfo}
|
playerInfo={playerInfo}
|
||||||
hands={gameState.hands}
|
hands={gameState.hands}
|
||||||
|
@ -1001,6 +1034,19 @@ function PvEDoudizhuDemoView() {
|
||||||
</Layout.Row>
|
</Layout.Row>
|
||||||
</Paper>
|
</Paper>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="citation">
|
||||||
|
This demo is based on <a href="https://github.com/datamllab/rlcard">RLCard</a> and{' '}
|
||||||
|
<a href="https://github.com/daochenzha/douzero">DouZero</a>. If you find these projects useful,
|
||||||
|
please cite:
|
||||||
|
<pre>
|
||||||
|
{`@article{zha2019rlcard,
|
||||||
|
title={RLCard: A Toolkit for Reinforcement Learning in Card Games},
|
||||||
|
author={Zha, Daochen and Lai, Kwei-Herng and Cao, Yuanpu and Huang, Songyi and Wei, Ruzhe and Guo, Junyu and Hu, Xia},
|
||||||
|
journal={arXiv preprint arXiv:1910.04376},
|
||||||
|
year={2019}
|
||||||
|
}`}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue