1 /***********************************************************************
2  *
3  * Copyright (C) 2009, 2013, 2014 Graeme Gott <graeme@gottcode.org>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  ***********************************************************************/
19 
20 #ifndef PATTERN_H
21 #define PATTERN_H
22 
23 #include "wordlist.h"
24 class Word;
25 
26 #include <QHash>
27 #include <QList>
28 #include <QMutex>
29 #include <QPoint>
30 #include <QSize>
31 #include <QStringList>
32 #include <QThread>
33 
34 #include <random>
35 
36 class Pattern : public QThread {
37 	Q_OBJECT
38 
39 	public:
40 		virtual ~Pattern();
41 
42 		static Pattern* create(WordList* words, int type);
43 
types()44 		static int types() {
45 			return 6;
46 		}
47 
size()48 		QSize size() const {
49 			return m_size;
50 		}
51 
counts()52 		virtual QList<int> counts() const {
53 			return QList<int>() << 4 << 8 << 12 << 16;
54 		}
55 
name()56 		virtual QString name() const {
57 			return QString();
58 		}
59 
minimumLength()60 		virtual int minimumLength() const {
61 			return 5;
62 		}
63 
maximumLength()64 		int maximumLength() const {
65 			return m_words->maximumLength();
66 		}
67 
solution()68 		QList<Word*> solution() const {
69 			return m_solution;
70 		}
71 
seed()72 		unsigned int seed() const {
73 			return m_seed;
74 		}
75 
words()76 		const WordList* words() const {
77 			return m_words;
78 		}
79 
wordCount()80 		int wordCount() const {
81 			return counts().indexOf(m_count);
82 		}
83 
wordLength()84 		int wordLength() const {
85 			return m_length;
86 		}
87 
88 		void setCount(int count);
89 		void setLength(int length);
90 		void setSeed(unsigned int seed);
91 
92 	signals:
93 		void generated();
94 
95 	protected:
96 		Pattern(WordList* words);
97 
98 		Word* addRandomWord(Qt::Orientation orientation);
99 		QChar at(const QPoint& pos) const;
100 		virtual void run();
101 
randomInt(unsigned int max)102 		unsigned int randomInt(unsigned int max) {
103 			std::uniform_int_distribution<unsigned int> gen(0, max - 1);
104 			return gen(m_random);
105 		}
106 
107 	protected:
108 		QPoint m_current;
109 
110 	private:
111 		void cleanUp();
112 
steps()113 		virtual int steps() const {
114 			return 2;
115 		}
116 
117 		virtual Word* addWord(int step);
118 
119 	private:
120 		WordList* m_words;
121 		int m_count;
122 		int m_length;
123 		unsigned int m_seed;
124 		QSize m_size;
125 		QList<Word*> m_solution;
126 		bool m_cancelled;
127 		QMutex m_cancelled_mutex;
128 		std::mt19937 m_random;
129 };
130 
131 //-----------------------------------------------------------------------------
132 
133 class ChainPattern : public Pattern {
134 	Q_OBJECT
135 
136 	public:
ChainPattern(WordList * words)137 		ChainPattern(WordList* words) : Pattern(words) {
138 		}
139 
counts()140 		QList<int> counts() const {
141 			return QList<int>() << 4 << 9 << 14 << 19;
142 		}
143 
name()144 		QString name() const {
145 			return tr("Chain");
146 		}
147 
148 	private:
steps()149 		int steps() const {
150 			return 5;
151 		}
152 
153 		Word* addWord(int step);
154 };
155 
156 //-----------------------------------------------------------------------------
157 
158 class FencePattern : public Pattern {
159 	Q_OBJECT
160 
161 	public:
FencePattern(WordList * words)162 		FencePattern(WordList* words) : Pattern(words) {
163 		}
164 
counts()165 		QList<int> counts() const {
166 			return QList<int>() << 4 << 7 << 13 << 16;
167 		}
168 
name()169 		QString name() const {
170 			return tr("Fence");
171 		}
172 
173 	private:
steps()174 		int steps() const {
175 			return 6;
176 		}
177 
178 		Word* addWord(int step);
179 };
180 
181 //-----------------------------------------------------------------------------
182 
183 class RingsPattern : public Pattern {
184 	Q_OBJECT
185 
186 	public:
RingsPattern(WordList * words)187 		RingsPattern(WordList* words) : Pattern(words) {
188 		}
189 
minimumLength()190 		int minimumLength() const {
191 			return 7;
192 		}
193 
name()194 		QString name() const {
195 			return tr("Rings");
196 		}
197 
198 	private:
steps()199 		int steps() const {
200 			return 4;
201 		}
202 
203 		Word* addWord(int step);
204 };
205 
206 //-----------------------------------------------------------------------------
207 
208 class StairsPattern : public Pattern {
209 	Q_OBJECT
210 
211 	public:
StairsPattern(WordList * words)212 		StairsPattern(WordList* words) : Pattern(words) {
213 		}
214 
name()215 		QString name() const {
216 			return tr("Stairs");
217 		}
218 
219 	private:
220 		Word* addWord(int step);
221 };
222 
223 //-----------------------------------------------------------------------------
224 
225 class TwistyPattern : public Pattern {
226 	Q_OBJECT
227 
228 	public:
TwistyPattern(WordList * words)229 		TwistyPattern(WordList* words) : Pattern(words) {
230 		}
231 
name()232 		QString name() const {
233 			return tr("Twisty");
234 		}
235 
236 	private:
237 		Word* addWord(int step);
238 		Word* stepOne();
239 		Word* stepTwo();
240 };
241 
242 //-----------------------------------------------------------------------------
243 
244 class WavePattern : public Pattern {
245 	Q_OBJECT
246 
247 	public:
WavePattern(WordList * words)248 		WavePattern(WordList* words) : Pattern(words) {
249 		}
250 
counts()251 		QList<int> counts() const {
252 			return QList<int>() << 5 << 9 << 13 << 17;
253 		}
254 
name()255 		QString name() const {
256 			return tr("Wave");
257 		}
258 
259 	private:
steps()260 		int steps() const {
261 			return 4;
262 		}
263 
264 		Word* addWord(int step);
265 };
266 
267 #endif
268