1 /*
2 	SPDX-FileCopyrightText: 2009-2017 Graeme Gott <graeme@gottcode.org>
3 
4 	SPDX-License-Identifier: GPL-3.0-or-later
5 */
6 
7 #ifndef TANGLET_GENERATOR_H
8 #define TANGLET_GENERATOR_H
9 
10 #include "trie.h"
11 
12 #include <QHash>
13 #include <QList>
14 #include <QPoint>
15 #include <QRandomGenerator>
16 #include <QStringList>
17 #include <QThread>
18 
19 #include <atomic>
20 
21 /**
22  * @brief The Generator class builds and solves a game layout.
23  */
24 class Generator : public QThread
25 {
26 	Q_OBJECT
27 
28 public:
29 	/**
30 	 * Constructs a generator instance.
31 	 * @param parent the QObject that manages the generator
32 	 */
33 	explicit Generator(QObject* parent = nullptr);
34 
35 	/**
36 	 * Aborts the current game generation.
37 	 */
38 	void cancel();
39 
40 	/**
41 	 * Creates and solves the game layout.
42 	 * @param density how many words are in the layout
43 	 * @param size how big the layout is
44 	 * @param minimum the shortest word allowed
45 	 * @param timer the game mode used to determine the maximum amount of words
46 	 * @param letters an already built layout to solve instead of create
47 	 */
48 	void create(int density, int size, int minimum, int timer, const QStringList& letters);
49 
50 	/**
51 	 * Fetch the dice for a given board size.
52 	 * @param size board size
53 	 * @return list of dice
54 	 */
dice(int size)55 	QList<QStringList> dice(int size) const
56 	{
57 		return (size == 4) ? m_dice : m_dice_large;
58 	}
59 
60 	/**
61 	 * @return the dictionary site to look up word definitions
62 	 */
dictionary()63 	QString dictionary() const
64 	{
65 		return m_dictionary_url;
66 	}
67 
68 	/**
69 	 * @return current error message
70 	 */
error()71 	QString error() const
72 	{
73 		return m_error;
74 	}
75 
76 	/**
77 	 * @return layout of the board as a single list of letters
78 	 */
letters()79 	QStringList letters() const
80 	{
81 		return m_letters;
82 	}
83 
84 	/**
85 	 * @return maximum score possible of current layout
86 	 */
maxScore()87 	int maxScore() const
88 	{
89 		return m_max_score;
90 	}
91 
92 	/**
93 	 * @return length of the shortest word allowed
94 	 */
minimum()95 	int minimum() const
96 	{
97 		return m_minimum;
98 	}
99 
100 	/**
101 	 * @return map of the findable words and their locations on the board
102 	 */
solutions()103 	QHash<QString, QList<QList<QPoint>>> solutions() const
104 	{
105 		return m_solutions;
106 	}
107 
108 	/**
109 	 * @return optimized word list
110 	 */
trie()111 	const Trie* trie() const
112 	{
113 		return &m_words;
114 	}
115 
116 	/**
117 	 * @return size of generated board
118 	 */
size()119 	int size() const
120 	{
121 		return m_size;
122 	}
123 
124 	/**
125 	 * @return timer used when generating board
126 	 */
timer()127 	int timer() const
128 	{
129 		return m_timer;
130 	}
131 
132 signals:
133 	/**
134 	 * Emitted when the word list is being optimized for fast access.
135 	 */
136 	void optimizingStarted();
137 
138 	/**
139 	 * Emitted when the word list has been optimized.
140 	 */
141 	void optimizingFinished();
142 
143 private:
144 	/**
145 	 * Loads the dice and words.
146 	 */
147 	void update();
148 
149 	/**
150 	 * Sets the current error.
151 	 * @param error message to inform player something has gone wrong
152 	 */
153 	void setError(const QString& error);
154 
155 protected:
156 	/**
157 	 * Builds the game layout in a thread.
158 	 */
159 	void run() override;
160 
161 private:
162 	QString m_dice_path; /**< where to load the dice */
163 	QString m_words_path; /**< where to load the word list */
164 	QString m_dictionary_url; /**< where to look up word definitions */
165 	QList<QStringList> m_dice; /**< the dice used to generate a normal board */
166 	QList<QStringList> m_dice_large; /**< the dice used to generate a large board */
167 	QRandomGenerator m_random; /**< the random number generator */
168 	Trie m_words; /**< the word list optimized for solving */
169 	QString m_error; /**< error encountered while loading dice and words */
170 
171 	int m_density; /**< how many words to target */
172 	int m_size; /**< how many letters wide to make the board */
173 	int m_minimum; /**< the shortest word allowed */
174 	int m_timer; /**< the timer mode for the generated board */
175 	int m_max_words; /**< the maximum number of words used to generate maximum score */
176 	int m_max_score; /**< the maximum score found on generated board */
177 
178 	QStringList m_letters; /**< the generated layout */
179 	QHash<QString, QList<QList<QPoint>>> m_solutions; /**< the available words and their locations */
180 
181 	std::atomic<bool> m_canceled; /**< if the generation has been aborted by player */
182 };
183 
184 #endif // TANGLET_GENERATOR_H
185