简体   繁体   中英

How can I get inside my event handler without manually clicking the screen to stimulate an event?

I'm using cm-chessboard to create a chess opening trainer game. I will be controlling one side and eventually I will get the computer to move specific openings.

cm-chessboard has an examples page, and I started of with this example which is closest to my final idea. At the moment, the computer moves randomly from the set of possible moves.

The example from github is only ever played from white's side. I have tweaked the code to allow for black to play. However, when the game starts and I am playing black, I have to click a black piece to stimulate an event which causes white to make its first move, and we play on from there. This is because white always goes first.

Here is my code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Chess Opening Trainer</title>
    <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"/>
    <link rel="stylesheet" href="/cm-chessboard/styles/cm-chessboard.css"/> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.2/chess.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>

<div class="board" id="board" style="width: 800px; max-width: 800px"></div>

<div id="output"></div>

<script type="module">


    var side = 'black'

    if (side == 'white'){var colour = 'w'}else{var colour = 'b'}

    

    import {INPUT_EVENT_TYPE, COLOR, Chessboard, MARKER_TYPE} from "/cm-chessboard/src/cm-chessboard/Chessboard.js"
    import {BORDER_TYPE} from "/cm-chessboard/src/cm-chessboard/Chessboard.js"


    const chess = new Chess() //Creates a new Chess() object. Add a FEN string as an argument to start from a FEN.

    var oneTimeBool = true;

    function inputHandler(event) {

        console.log("event", event)
        event.chessboard.removeMarkers(undefined, MARKER_TYPE.dot)

        //Do this only once
        if (oneTimeBool == true && side == 'black'){
            event.chessboard.disableMoveInput()
            event.chessboard.setPosition(chess.fen())
            const possibleMoves = chess.moves({verbose: true})
                if (possibleMoves.length > 0) {
                    const randomIndex = Math.floor(Math.random() * possibleMoves.length)
                    const randomMove = possibleMoves[randomIndex]
                    setTimeout(() => { // smoother with 500ms delay
                        chess.move({from: randomMove.from, to: randomMove.to})
                        event.chessboard.enableMoveInput(inputHandler, colour)
                        event.chessboard.setPosition(chess.fen())
                    }, 500)
                }

            oneTimeBool = false;
        }

        //Before move. Clicking about, and showing dot for possible moves and such.
        if (event.type === INPUT_EVENT_TYPE.moveStart) {
            const moves = chess.moves({square: event.square, verbose: true});
            for (const move of moves) {
                event.chessboard.addMarker(move.to, MARKER_TYPE.dot)
            }
            return moves.length > 0

        //Here is once a move has been attempted    
        } else if (event.type === INPUT_EVENT_TYPE.moveDone) {
            const move = {from: event.squareFrom, to: event.squareTo} //gets which move was attempted from event
            const result = chess.move(move) //gets result of move
            
            if (result) { //if result is anyting then we processed
                event.chessboard.disableMoveInput()
                event.chessboard.setPosition(chess.fen())
                const possibleMoves = chess.moves({verbose: true})
                if (possibleMoves.length > 0) {
                    const randomIndex = Math.floor(Math.random() * possibleMoves.length)
                    const randomMove = possibleMoves[randomIndex]
                    setTimeout(() => { // smoother with 500ms delay
                        chess.move({from: randomMove.from, to: randomMove.to})
                        event.chessboard.enableMoveInput(inputHandler, colour)
                        event.chessboard.setPosition(chess.fen())
                    }, 500)
                }
            } else { //If result returns null, then we will loop back to the begining of the function to have another go with new dots.
                console.warn("invalid move", move)
            }
            return result
        }
    }

    const board = new Chessboard(document.getElementById("board"), {
        position: chess.fen(),
        sprite: {url: "/cm-chessboard/assets/images/chessboard-sprite-staunty.svg"},
        style: {moveMarker: MARKER_TYPE.square, hoverMarker: undefined},
        orientation: colour
    })
    board.enableMoveInput(inputHandler, colour)


</script>
</body>
</html>

It's pretty bad, I know. I'm sure there's much more elegant ways to do this.

My problem is that when board.enableMoveInput(inputHandler_black, COLOR.black) calls the inputhandler_black function, the function waits for an event in order to begin. When I play as white and inputHandler_white is called, this is fine because I have to make the first move anyway. When I play as black, I want the computer to automatically play the move without me having to click a random black piece to get it to start.

Anyone know how can I do that? Is there a way to force it into the function somehow without manually creating an event with the mouse?

This code piece makes the move against the player, so you should run this piece initially (right after chessboard initialize) when the player is black.

const possibleMoves = chess.moves({verbose: true})
if (possibleMoves.length > 0) {
    const randomIndex = Math.floor(Math.random() * possibleMoves.length)
    const randomMove = possibleMoves[randomIndex]
    setTimeout(() => { // smoother with 500ms delay
        chess.move({from: randomMove.from, to: randomMove.to})
        board.enableMoveInput(inputHandler, COLOR.black)
        board.setPosition(chess.fen())
    }, 500)
}

Here is the whole code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Chess Opening Trainer</title>
    <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"/>
    <link rel="stylesheet" href="/cm-chessboard/styles/cm-chessboard.css"/> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.2/chess.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>

<div class="board" id="board" style="width: 800px; max-width: 800px"></div>

<div id="output"></div>

<script type="module">

    import {INPUT_EVENT_TYPE, COLOR, Chessboard, MARKER_TYPE} from "/cm-chessboard/src/cm-chessboard/Chessboard.js"
    import {BORDER_TYPE} from "/cm-chessboard/src/cm-chessboard/Chessboard.js"

    const side = 'black' //select which side to play as
    const chess = new Chess() //Creates a new Chess() object. Add a FEN string as an argument to start from a FEN.

    function inputHandler(event) {
        console.log("event", event)
        event.chessboard.removeMarkers(undefined, MARKER_TYPE.dot)

        //Before move. Clicking about, and showing dot for possible moves and such.
        if (event.type === INPUT_EVENT_TYPE.moveStart) {
            const moves = chess.moves({square: event.square, verbose: true});
            for (const move of moves) {
                event.chessboard.addMarker(move.to, MARKER_TYPE.dot)
            }
            return moves.length > 0

        //Here is once a move has been attempted    
        } else if (event.type === INPUT_EVENT_TYPE.moveDone) {
            const move = {from: event.squareFrom, to: event.squareTo} //gets which move was attempted from event
            const result = chess.move(move) //gets result of move
            
            if (result) { //if result is anyting then we processed
                event.chessboard.disableMoveInput()
                event.chessboard.setPosition(chess.fen())
                const possibleMoves = chess.moves({verbose: true})
                if (possibleMoves.length > 0) {
                    const randomIndex = Math.floor(Math.random() * possibleMoves.length)
                    const randomMove = possibleMoves[randomIndex]
                    setTimeout(() => { // smoother with 500ms delay
                        chess.move({from: randomMove.from, to: randomMove.to})
                        if(side === 'white') {
                            event.chessboard.enableMoveInput(inputHandler, COLOR.white)
                        }
                        else {
                            event.chessboard.enableMoveInput(inputHandler, COLOR.black)
                        }
                        event.chessboard.setPosition(chess.fen())
                    }, 500)
                }
            } else { //If result returns null, then we will loop back to the begining of the function to have another go with new dots.
                console.warn("invalid move", move)
            }
            return result
        }
    }


    if (side == 'white'){
        const board = new Chessboard(document.getElementById("board"), {
            position: chess.fen(),
            sprite: {url: "/cm-chessboard/assets/images/chessboard-sprite-staunty.svg"},
            style: {moveMarker: MARKER_TYPE.square, hoverMarker: undefined},
            orientation: COLOR.white
        })
        board.enableMoveInput(inputHandler, COLOR.white)
    }
    else{
        const board = new Chessboard(document.getElementById("board"), {
            position: chess.fen(),
            sprite: {url: "/cm-chessboard/assets/images/chessboard-sprite-staunty.svg"},
            style: {moveMarker: MARKER_TYPE.square, hoverMarker: undefined},
            orientation: COLOR.black
        })
        const possibleMoves = chess.moves({verbose: true})
        if (possibleMoves.length > 0) {
            const randomIndex = Math.floor(Math.random() * possibleMoves.length)
            const randomMove = possibleMoves[randomIndex]
            setTimeout(() => { // smoother with 500ms delay
                chess.move({from: randomMove.from, to: randomMove.to})
                board.enableMoveInput(inputHandler, COLOR.black)
                board.setPosition(chess.fen())
            }, 500)
        }
        console.log(board)
    }

</script>
</body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM