[Qt chess game] 07_ The beginning of man-machine game algorithm

Posted by mac007 on Sat, 29 Jan 2022 23:40:38 +0100

01 - brief introduction of man-machine game algorithm

   previously, we introduced in detail the packaging of chessboard class, the packaging of chess sub class and the implementation of chess walking algorithm of various types of chess pieces. With the foreshadowing in front, we can take the first step of computer intelligent chess.
  the computer should realize the man-machine game, and the chess game is divided into three steps:
   (1) the computer obtains all accessible paths of the chess pieces;
   (2) calculate the optimal path to the computer from all the paths that can be taken by the chess pieces;
   (3) computer realizes chess.

02 - relevant members and methods

  before writing code, look in advance to see what classes and members have been added. Create a new QVector container to save the attribute information of chess pieces and facilitate the calculation of the optimal path to the computer. The specific contents are as follows:

#ifndef STEP_H
#define STEP_H
#include <QObject>
class Step : public QObject
{
    Q_OBJECT
public:
   int moveID;     //ID of walking chess piece
   int killID;     //Kill the ID of the chess piece
   int rowFrom;    //Starting line coordinates
   int colFrom;    //Starting column coordinates
   int rowTo;      //Target line coordinates
   int colTo;      //Target position column coordinates

signals:
public slots:
};
#endif // STEP_H

  also in chessarea H add computer to realize man-machine game and chess related methods and slot functions:

   // Get all chess paths and store them in steps
   void getAllPossibleMove(QVector<Step *>& steps);
   void fakeMove(Step* step);   	// The chess piece pretended to take a step
   void unfakeMove(Step* step);     // The pawn pretended to move back
   Step* getBestMove();             // Get the best chess path
   int   calcScore();               // Assessment situation score

private slots:

   void computerMove(bool run);  // Computer chess

   //Implement signal and slot () on widget constructor
   connect(chessarea, SIGNAL(sendCompute(bool)), chessarea, SLOT(computerMove(bool)));

03 - get the path that computer chess pieces can take

   traverse all computer (black) pieces in front, traverse all positions of the piece on the chessboard, input each position information into the canMove function, and the "Step" returned by the canMove function returns true is stored in the container Step.

/**
 *
 *  @brief :Get the best mobile path of the computer
 *
 *  @param : nothing
 *
 *  @return: The attribute of the optimal chess piece information (original coordinate, target coordinate, ID, target ID)
 *
 **/
Step *ChessArea::getBestMove()
{
     QVector<Step *> steps;

    // Get all chess paths of the computer
    getAllPossibleMove(steps);

    // Initialization specific gravity
    int maxScore = -100000;
    Step* ret;
    for(QVector<Step*>::iterator it=steps.begin(); it!=steps.end(); ++it)
    {
        Step* step= *it;

        //Try walking
        fakeMove(step);

        //Assessment situation score
        int score = calcScore();


        //Come back again
        unfakeMove(step);
        //Take the highest score
        if(score > maxScore)
        {
            maxScore = score;

            ret = step;
        }
    }

    return ret;

}

   about fakeMove function and unfakeMove function

/**
 *
 *  @brief : The chess piece pretends to move and takes a step
 *
 *  @param : steps : Save the attributes of the moving chess piece information (original coordinates, target coordinates, ID, target ID)
 *
 *  @return: nothing
 *
 **/
void ChessArea::fakeMove(Step *step)
{
    //Kill the chess pieces
    killStone(step->killID);

    if(step->killID != -1)
    {
         myChess[step->killID].row = -1;
         myChess[step->killID].col = -1;
    }

    myChess[step->moveID].row = step->rowTo;
    myChess[step->moveID].col = step->colTo;
}

/**
 *
 *  @brief : The chess piece pretends to move back one step
 *
 *  @param : steps : Save the attributes of the moving chess piece information (original coordinates, target coordinates, ID, target ID)
 *
 *  @return: nothing
 *
 **/
void ChessArea::unfakeMove(Step *step)
{
    //Resurrection chess piece
    reliveStone(step->killID);

    if(step->killID != -1)
    {
         myChess[step->killID].row = step->rowTo;
         myChess[step->killID].col = step->colTo;
    }

    myChess[step->moveID].row = step->rowFrom;
    myChess[step->moveID].col = step->colFrom;

}

   chess game scoring algorithm: first assign weights to all chess pieces. According to the importance of chess pieces, they will be the most important chess pieces. Therefore, the weight is the highest and set to 1500; Next to the car, set it to 100; Horse and gun are the second, set to 50; Soldiers are set as 20, and scholars and phase are the least important, set as 10. Traverse all the pieces of the Red Square and accumulate the weight of the living pieces of the Red Square to a total score; Traverse all the pieces on the black side and add up the weight of the living pieces on the black side to a total score. The default computer is black, so the returned situation score should be calculated from the perspective of black, and return the total score of black chess - the total score of red flag. The following is the function implementation:

/**
 *
 *  @brief : Get the score of the chess game
 *
 *  @param : nothing
 *
 *  @return: nothing
 *
 **/
int ChessArea::calcScore()
{
    //Enumerated cars = 0 horses = 1 gun = 2 soldiers = 3 generals = 4 Shi = 5 phases = 6
       static int chessScore[]={100, 80, 80, 20, 1500, 10, 10};
       int redTotalScore   = 0;
       int blackTotalScore = 0;

       //Calculate the total score of red chess
       for(int i=0; i<16; i++)
       {
           //If the piece is dead, skip accumulation
           if(myChess[i].isDead)
               continue;

           redTotalScore += chessScore[myChess[i].chessType];
       }


       //Calculate the total score of black chess
       for(int i=16; i<32; i++)
       {
           //If the piece is dead, skip accumulation
           if(myChess[i].isDead)
               continue;

           blackTotalScore += chessScore[myChess[i].chessType];
       }


       //Return the total score of black chess - the total score of red chess
       return blackTotalScore - redTotalScore;
}

04 - computer chess

  humans take the red flag and computers take the black chess. When the human walks the red flag, directly move the mouse to finish the chess piece, and then trigger the signal. It's the black side's turn to walk the chess piece. The computer calls getBestMove function to calculate the optimal path of walking the chess piece, and then obtains the optimal Step to move the chess piece directly.

/**
 *
 *  @brief : Computer chess (slot function)
 *
 *  @param : Boolean type, signaled by
 *
 *  @return: nothing
 *
 **/
void ChessArea::computerMove(bool run)
{

    if(run == false)
    {
        if(this->bRedTurn)
            return;
        else
        {

            Step* step = getBestMove();

            // Move chess pieces
            moveChess(step->moveID, step->killID, step->rowTo, step->colTo);

            bRedTurn = true;
            // It's human's turn to play chess
            emit redTrueGo(bRedTurn);
        }
    }
    else
    {
        qDebug() << "computer move failed";
        return;
    }
}

05 - Summary

   here, we can already realize the preliminary man-machine game, but at this time, the computer is not very smart. It can only "take one step and watch one step". In the next issue, we will explain the advanced version of man-machine game algorithm, so that the computer can "take one step and watch three steps" when playing chess.

  • 01_ Introduction to developing chess games
  • 02_ Drawing chess board
  • 03_ Chess pieces placement
  • 04_ Rules of chess - car, gun and player
  • 05_ Rules of chess - elephant, horse, general and soldier
  • 06_ Chess game rules
  • 07_ The beginning of man-machine game algorithm
  • 08_ Higher order algorithm of man-machine game
  • 09_ Cross compiling and Porting Linux system

Topics: Qt