File indexing completed on 2022-09-27 13:19:28

0001 /*
0002     SPDX-FileCopyrightText: 2006 Matthew Williams <matt@milliams.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef AICONTROLLER_H
0008 #define AICONTROLLER_H
0009 
0010 #include <QList>
0011 
0012 namespace KSquares
0013 {
0014 enum Direction {HORIZONTAL, VERTICAL};
0015 }
0016 
0017 /**
0018  * @short AI Controller for KSquares
0019  *
0020  * When playing a game of squares there are a number of stages the game goes through:
0021  * @li The random line placement stage. Where players are just placing lines while trying to not complete the third side of any squares
0022  * @li Next players will try to only draw the third side of a square if it will only give the opponent the minimum amount of points
0023  * @li The more advanced player will, at the end of a large run of squares leave a small area at the end, forcing the opponent to take only that small section, leaving another large area open to him.
0024  * @li The even more advanced player will fight for control over the game. This means that he will count the chains forming in the last phase of the "random line" game phase and thus make sure that he will be the one who gets the first long chain. This works like a Nim game somehow.
0025  * Currently, the first three points are implemented.
0026  *
0027  * @author Matt Williams <matt@milliams.com>
0028  * @author Tom Vincent Peters <kde@vincent-peters.de>
0029  */
0030 
0031 class aiController
0032 {
0033 public:
0034     /**
0035      * Create a new AI controller
0036      *
0037      * @param newPlayerId ID of the player
0038      * @param newLines list of the lines which are drawn
0039      * @param newSquareOwners list of squares and their owners
0040      * @param newWidth height of the current gameboard
0041      * @param newHeight width of the current gameboard
0042      */
0043     aiController(int newPlayerId, const QList<bool> &newLines, const QList<int> &newSquareOwners, int newWidth, int newHeight);
0044 
0045     ~aiController();
0046 
0047     /**
0048      * Choses where to draw the line:
0049      * Creates a list of all the squares which are surrounded by 3 lines and if the list isn't empty, randomly picks one of them.
0050      * Otherwise, creates a list of all the squares which are surrounded by 1 or 2 lines and if the list isn't empty, randomly chooses one of them.
0051      * Otherwise, randomly chooses a square which is surrounded by three lines.
0052      *
0053      * @return The index of the line from "QVector<bool> lines"
0054      */
0055     int chooseLine() const;
0056     /**
0057      * Finds lines that can be filled without causing squares to be surrounded by 3 lines as a result.
0058      * @param safeMovesLeft number of safe moves that can be performed after those returned by the function are drawn (note: the number is valid only for a certain sequence, for other sequences they could either be more or less)
0059      *
0060      * @return the list of lines that can be safely drawn
0061      */
0062     QList<int> autoFill(int safeMovesLeft);
0063 
0064 protected:
0065     /**
0066      * @return list of moves that are safe (squares surrounded by 2 lines are avoided)
0067      */
0068     QList<int> safeMoves() const;
0069     /**
0070      * @param choiceList list of indices (of lines) which have squares next to them with two lines drawn (relates to @ref lines )
0071      *
0072      * @return list of indices (of lines) which would be the least damaging in the short term
0073      */
0074     QList<int> chooseLeastDamaging(const QList<int> &choiceList) const;
0075     /**
0076      * @param squareIndex the index of the square (relates to @ref squareOwners )
0077      * @param linesList the linesList you want to work from
0078      *
0079      * @return the number of lines currently drawn around a specific square
0080      */
0081     int countBorderLines(int squareIndex, const bool *linesList) const;
0082     /**
0083      * @param sidesOfSquare output parameter: the indices of the four lines surrounding the square
0084      * @param squareIndex the index of the square (relates to @ref squareOwners )
0085      * @param linesList the linesList you want to work from
0086      *
0087      * @return the number of lines currently drawn around a specific square
0088      */
0089     int countBorderLines(int *sidesOfSquare, int squareIndex, const bool *linesList) const;
0090     /**
0091      * @param lineIndex the index of the line (relates to @ref lines )
0092      *
0093      * @return the (one or two) squares abutting a line
0094      */
0095     QList<int> squaresFromLine(int lineIndex) const;
0096     /**
0097      * @param sidesOfSquare output parameter: the indices of the four lines surrounding the square
0098      * @param squareIndex the index of the square (relates to @ref squareOwners )
0099      */
0100     void linesFromSquare(int *sidesOfSquare, int squareIndex) const;
0101     /**
0102      * @param lineIndex the index of the line (relates to @ref lines )
0103      *
0104      * @return the direction of the line
0105      */
0106     KSquares::Direction lineDirection(int lineIndex) const;
0107 
0108     /// List of the owners of each square
0109     QList<int> squareOwners;
0110     /// List of which lines are complete
0111     int linesSize;
0112     bool *lines;
0113     /// The ID of the player this AI belongs to
0114     int playerId;
0115     /// Width of the game board
0116     int width;
0117     /// Height of the game board
0118     int height;
0119 };
0120 
0121 #endif // KSQUARES_H