1 /*
2 	SPDX-FileCopyrightText: 2009-2021 Graeme Gott <graeme@gottcode.org>
3 
4 	SPDX-License-Identifier: GPL-3.0-or-later
5 */
6 
7 #ifndef TANGLET_BOARD_H
8 #define TANGLET_BOARD_H
9 
10 class Clock;
11 class Generator;
12 class Letter;
13 class View;
14 class WordCounts;
15 class WordTree;
16 
17 #include <QHash>
18 #include <QList>
19 #include <QPoint>
20 #include <QWidget>
21 class QLabel;
22 class QLineEdit;
23 class QSettings;
24 class QTabWidget;
25 class QToolButton;
26 
27 /**
28  * @brief The Board class controls the play area of the game, including the word lists and score area.
29  */
30 class Board : public QWidget
31 {
32 	Q_OBJECT
33 
34 public:
35 	/**
36 	 * Constructs a board instance.
37 	 * @param parent the QWidget that manages the board
38 	 */
39 	explicit Board(QWidget* parent = nullptr);
40 
41 	/**
42 	 * Destroys the board.
43 	 */
44 	~Board();
45 
46 	/**
47 	 * @return whether the current game has finished
48 	 */
49 	bool isFinished() const;
50 
51 	/**
52 	 * Cancels the current running game.
53 	 */
54 	void abort();
55 
56 	/**
57 	 * Creates a new game in a thread, replacing the contents of the game board.
58 	 * @param game the details to use to create a game
59 	 * @return @c true if the game is valid and will be started
60 	 */
61 	bool generate(const QSettings& game);
62 
63 	/**
64 	 * Pauses or resumes the game.
65 	 * @param pause pauses the game if @c true
66 	 */
67 	void setPaused(bool pause);
68 
69 	static QString sizeToString(int size);
70 
71 public slots:
72 	/**
73 	 * Sets the visibility of the missed words tab.
74 	 * @param show whether to show the missed words
75 	 */
76 	void setShowMissedWords(bool show);
77 
78 	/**
79 	 * Sets the visibility of the maximum score of the game and each word.
80 	 * @param show whether to show the maximum score
81 	 */
82 	void setShowMaximumScore(QAction* show);
83 
84 	/**
85 	 * Sets the visibility of the word counts for each length.
86 	 * @param show whether to show the word counts
87 	 */
88 	void setShowWordCounts(bool show);
89 
90 signals:
91 	/**
92 	 * Emitted when the game has been generated and is now playable.
93 	 */
94 	void started();
95 
96 	/**
97 	 * Emitted when the game has finished.
98 	 * @param score how many points the player earned
99 	 * @param max_score the maximum score available on the played board
100 	 */
101 	void finished(int score, int max_score);
102 
103 	/**
104 	 * Emitted when the word list is being optimized for fast access.
105 	 */
106 	void optimizingStarted();
107 
108 	/**
109 	 * Emitted when the word list has been optimized.
110 	 */
111 	void optimizingFinished();
112 
113 	/**
114 	 * Emitted when the game starts or finishes.
115 	 * @param available @c true if the game is running and can be paused
116 	 */
117 	void pauseAvailable(bool available);
118 
119 private slots:
120 	/**
121 	 * Fills the contents of the play area (letters, word lists, maximum scores) after the generator
122 	 * thread finishes. It also updates the current game in the settings so that it will resume on
123 	 * next launch.
124 	 */
125 	void gameStarted();
126 
127 	/**
128 	 * Clears the current guess from the board.
129 	 */
130 	void clearGuess();
131 
132 	/**
133 	 * Processes a guess for a word made by the player. If they are correct, the guess is added to
134 	 * the found word list and the current guess is cleared.
135 	 */
136 	void guess();
137 
138 	/**
139 	 * Updates the current guess when the player types in the line edit.
140 	 */
141 	void guessChanged();
142 
143 	/**
144 	 * Ends the current running game.
145 	 */
146 	void finish();
147 
148 	/**
149 	 * Shows the word list selection on the game board.
150 	 */
151 	void wordSelected();
152 
153 	/**
154 	 * Processes the player clicking on a letter on the game board.
155 	 * @param letter which letter the player clicked on
156 	 */
157 	void letterClicked(Letter* letter);
158 
159 	/**
160 	 * Displays a dialog listing the 30 words used to determine the maximum score in an Allotment game.
161 	 */
162 	void showMaximumWords();
163 
164 private:
165 	/**
166 	 * Highlight a word on the board.
167 	 * @param positions the locations of the letters to highlight
168 	 * @param color the color used to highlight the word
169 	 */
170 	void highlightWord(const QList<QPoint>& positions, const QColor& color);
171 
172 	/**
173 	 * Determine the state of the guess and then calls highlightWord(const QList<QPoint>&, const QColor&)
174 	 * to actually update the letters on the board.
175 	 */
176 	void highlightWord();
177 
178 	/**
179 	 * Removes all highlight colors on the board and sets the letters to white if the game is still
180 	 * running, or gray if the game is over.
181 	 */
182 	void clearHighlight();
183 
184 	/**
185 	 * Checks if a word has already been found before, and if so it selects it in the found word list.
186 	 */
187 	void selectGuess();
188 
189 	/**
190 	 * Calculates the current score by adding up the values in the found word list. It updates the
191 	 * display of the score as well as the display of the maximum scores for each word length.
192 	 * @return the value of the score
193 	 */
194 	int updateScore();
195 
196 	/**
197 	 * Processes the board and marks which cells can be clicked on to continue making a guess. If
198 	 * the game is over, it disables clicking on the letters.
199 	 */
200 	void updateClickableStatus();
201 
202 	/**
203 	 * Enables or disables the buttons next to the line edit based on the length of the current guess.
204 	 */
205 	void updateButtons();
206 
207 private:
208 	Clock* m_clock; /**< shows the time remaining in the game */
209 	View* m_view; /**< game area that shows the letters */
210 	QLabel* m_score; /**< shows how many points the player has earned */
211 	QVector<QVector<Letter*>> m_cells; /**< contains the letters that make up the board */
212 	QLineEdit* m_guess; /**< allows players to type a guess instead of click on it */
213 	QTabWidget* m_tabs; /**< tabs containing the word lists */
214 	WordTree* m_found; /**< list of found words */
215 	WordTree* m_missed; /**< list of missing words */
216 	WordCounts* m_counts; /**< displays counts of words */
217 	QToolButton* m_guess_button; /**< allows player to make a guess when typing */
218 	QToolButton* m_max_score_details; /**< displays the words used to make the maximum score with Allotment timer */
219 
220 	bool m_paused; /**< is the game currently paused */
221 	bool m_wrong; /**< is the clicked guess wrong (will color positions on board) */
222 	bool m_wrong_typed; /**< is the typed guess wrong (no positions on board to color) */
223 	int m_show_counts; /**< are maximum scores for each word length shown */
224 
225 	int m_size; /**< how many letters wide is the board */
226 	int m_minimum; /**< the shortest word allowed */
227 	int m_maximum; /**< the longest word possible */
228 	int m_max_score; /**< the maximum score available */
229 	QStringList m_letters; /**< the board layout */
230 	QHash<QString, QList<QList<QPoint>>> m_solutions; /**< all available words and their positions on the board */
231 	QList<QPoint> m_positions; /**< the currently selected positions */
232 
233 	Generator* m_generator; /**< builds the board layout */
234 };
235 
236 #endif // TANGLET_BOARD_H
237