Starlight-30036225 / ChessTCP

FILLMELATER
0 stars 0 forks source link

Turn system #24

Closed Starlight-30036225 closed 7 months ago

Starlight-30036225 commented 7 months ago

Currently either player can make a move with any piece whenever they want, with no respect for turns or timing. I need to implement a turn system

Starlight-30036225 commented 7 months ago

The first thing to be done for the creation of this system is to stop players from making moves if it isn't their turn. So on the server side i will keep track of which player is currently in focus(its their turn) and if the requested move comes from this player, allow it, otherwise ignore.

I will want this check to be optional for testing purposes, but in the final version this needs to be permanent.

Starlight-30036225 commented 7 months ago
private void HandleMove(ConnectionHandler Handler){
        String Composite = Handler.readNextString();

        if (testmode && Handler != focusedPlayer) {return;}

        //gets the start location of the move/piece location
        int Piecex = Character.getNumericValue(Composite.charAt(0));
        int Piecey = Character.getNumericValue(Composite.charAt(1));
        //gets the end location of the move
        int Movex = Character.getNumericValue(Composite.charAt(2));
        int Movey = Character.getNumericValue(Composite.charAt(3));

This check should stop players from taking moves out of their turn

it is important this gatekeeping happens after the move string is read so it can be cleared from the buffer.

Starlight-30036225 commented 7 months ago

Now I need to assign one of the clients to this variable.

Whichever player connects first should be fine for now.

Starlight-30036225 commented 7 months ago
    protected void SendWelcomeMessage(ConnectionHandler CH) {
        if (focusedPlayer == null) {
            focusedPlayer = CH;
        }

        CH.sendMessage(PacketHeader.BOARD_STATE, game.LoadNotationFromMap());
    }

This code is run when a player connects to the server, the first player will be focused.

I will now swap the focused player after a successful move Problem here is I dont have a reference to the other player to swap with. So I need to create a secondary reference.

        if (focusedPlayer == null) {
            focusedPlayer = CH;
        }
        else if(unfocusedPlayer == null){
            focusedPlayer = CH;
        }

        CH.sendMessage(PacketHeader.BOARD_STATE, game.LoadNotationFromMap());
    }

Updating the assignment here inadvertantly creates a simple spectator. Any client connected after the first two will still be in the player pool but never allowed to make a move.

Starlight-30036225 commented 7 months ago
        ConnectionHandler temp = focusedPlayer;
        focusedPlayer = unfocusedPlayer;
        unfocusedPlayer = temp;

This should toggle the players after a successful move.

Lets test it.

Starlight-30036225 commented 7 months ago

image White player makes a move

image white player tries to make another move

image Move fails

image

Black player makes a move

image

Black player tries to make another move image

Move fails

Success

Starlight-30036225 commented 7 months ago

Now I need to work on colours being assigned. As currently, I am having to assign colours to the two boards manually.

I rewrote most of the code from this issue to make this work.

I realised that swapping between two pointers was pretty redundant, I could just use a boolean and a conditional operator.

    @Override
    protected void SendWelcomeMessage(ConnectionHandler CH) {

        if (!testmode) {
            if (WhitePlayer == null) {
                WhitePlayer = CH;
                CH.sendMessage(PacketHeader.WELCOME, "WHITE");
            } else if (BlackPlayer == null) {
                BlackPlayer = CH;
                CH.sendMessage(PacketHeader.WELCOME, "BLACK");
            }
        }
        CH.sendMessage(PacketHeader.BOARD_STATE, game.LoadNotationFromMap());

    }

This snippet assigns the new pointers to incoming connections, and sends the player a welcome packet, notifying them of their colour.

This change also greatly simplifies the changes made in the move function

        if (!testmode && Handler !=
                (white? WhitePlayer :BlackPlayer)) {return;}

               ...
                ...

        if (testmode) {return;}
        white = !white;

Now on the client side, I need to allow it to receive a new packet header. As expected, the player client detatches the string from the packet header and passes it onto the player master via this function:


    public void receiveWelcomePack(String WelcomePack) {
        switch (WelcomePack.substring(0, 5)) {
            case "WHITE" -> Board.White = true;
            case "BLACK" -> Board.White = false;
            default -> {
            }
        }
        Board.printMap();

    }
Starlight-30036225 commented 7 months ago

The next step is preventing players from making moves with pieces of a different colour. This should be easy enough.

After the piece location is calculated, Ill add a check to see if the colour is correct.

        if (game.board[Piecex][Piecey] == null ||
                (!testmode && game.board[Piecex][Piecey].white != white)) {return;} //Piece is invalid or wrong colour