Pokered Save Editor 2
Pokemon Red & Blue save file editor - Qt 6 C++/QML
Loading...
Searching...
No Matches
mapsearch.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Twilight
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15*/
16
22
23#include <QDebug>
24#include <QQmlEngine>
25
26#include <pse-common/random.h>
27#include <pse-common/utility.h>
28
29#include "./mapsearch.h"
30#include "../mapsdb.h"
32#include "../tileset.h"
33#include "../spriteSet.h"
34
36{
37 qmlRegister();
38 startOver();
39}
40
42{
43 if(results.size() == 0)
44 return nullptr;
45
46 return results.at(Random::inst()->rangeExclusive(0, results.size()));
47}
48
50{
51 results.clear();
52
53 // Copy elements over to begin search
54 for(auto entry : MapsDB::inst()->getStore())
55 {
56 results.append(entry);
57 }
58
59 return this;
60}
61
63{
64 for(auto entry : QVector<MapDBEntry*>(results))
65 if(entry->name == val ||
66 entry->modernName == val)
67 results.removeOne(entry);
68
69 return this;
70}
71
73{
74 for(auto entry : QVector<MapDBEntry*>(results))
75 if(!(entry->ind < val))
76 results.removeOne(entry);
77
78 return this;
79}
80
82{
83 for(auto entry : QVector<MapDBEntry*>(results))
84 if(!(entry->ind > val))
85 results.removeOne(entry);
86
87 return this;
88}
89
91{
92 for(auto entry : QVector<MapDBEntry*>(results))
93 if(entry->width < 0 || !(entry->width > val))
94 results.removeOne(entry);
95
96 return this;
97}
98
100{
101 for(auto entry : QVector<MapDBEntry*>(results))
102 if(entry->height < 0 || !(entry->height < val))
103 results.removeOne(entry);
104
105 return this;
106}
107
109{
110 for(auto entry : QVector<MapDBEntry*>(results))
111 if(entry->width < 0 || !(entry->width > val))
112 results.removeOne(entry);
113
114 return this;
115}
116
118{
119 for(auto entry : QVector<MapDBEntry*>(results))
120 if(entry->width < 0 || !(entry->width < val))
121 results.removeOne(entry);
122
123 return this;
124}
125
127{
128 for(auto entry : QVector<MapDBEntry*>(results))
129 if(entry->width < 0 || entry->height < 0 ||
130 !((entry->width * entry->height) > val))
131 results.removeOne(entry);
132
133 return this;
134}
135
137{
138 for(auto entry : QVector<MapDBEntry*>(results))
139 if(entry->width < 0 || entry->height < 0 ||
140 !((entry->width * entry->height) < val))
141 results.removeOne(entry);
142
143 return this;
144}
145
147{
148 for(auto entry : QVector<MapDBEntry*>(results))
149 if(entry->toTileset == nullptr ||
150 (!(entry->toTileset->name == val) ||
151 !(entry->toTileset->nameAlias == val)))
152 results.removeOne(entry);
153
154 return this;
155}
156
158{
159 for(auto entry : QVector<MapDBEntry*>(results))
160 if(entry->toTileset == nullptr ||
161 (!(entry->toTileset->name != val) &&
162 !(entry->toTileset->nameAlias != val)))
163 results.removeOne(entry);
164
165 return this;
166}
167
169{
170 for(auto entry : QVector<MapDBEntry*>(results)) {
171 // A map with no tileset can't match a type; drop it and move on. Without the
172 // `continue` the next line dereferenced the null toTileset -> crash (hit by
173 // AreaWarps::randomize -> isType("Cave")). notType() already guards this way.
174 if(entry->toTileset == nullptr) {
175 results.removeOne(entry);
176 continue;
177 }
178
179 if(entry->toTileset->type != val && entry->toTileset->typeAlias != val)
180 results.removeOne(entry);
181 }
182
183 return this;
184}
185
187{
188 for(auto entry : QVector<MapDBEntry*>(results)) {
189 if(entry->toTileset == nullptr)
190 continue;
191
192 if(entry->toTileset->type == val || entry->toTileset->typeAlias == val)
193 results.removeOne(entry);
194 }
195
196 return this;
197}
198
200{
201 for(auto entry : QVector<MapDBEntry*>(results))
202 if(entry->connect.isEmpty())
203 results.removeOne(entry);
204
205 return this;
206}
207
209{
210 for(auto entry : QVector<MapDBEntry*>(results))
211 if(!entry->connect.isEmpty())
212 results.removeOne(entry);
213
214 return this;
215}
216
218{
219 for(auto entry : QVector<MapDBEntry*>(results))
220 if(entry->warpOut.isEmpty())
221 results.removeOne(entry);
222
223 return this;
224}
225
227{
228 for(auto entry : QVector<MapDBEntry*>(results))
229 if(!entry->warpOut.isEmpty())
230 results.removeOne(entry);
231
232 return this;
233}
234
236{
237 for(auto entry : QVector<MapDBEntry*>(results))
238 if(entry->warpIn.isEmpty())
239 results.removeOne(entry);
240
241 return this;
242}
243
245{
246 for(auto entry : QVector<MapDBEntry*>(results))
247 if(!entry->warpIn.isEmpty())
248 results.removeOne(entry);
249
250 return this;
251}
252
254{
255 for(auto entry : QVector<MapDBEntry*>(results))
256 if(entry->signs.isEmpty())
257 results.removeOne(entry);
258
259 return this;
260}
261
263{
264 for(auto entry : QVector<MapDBEntry*>(results))
265 if(!entry->signs.isEmpty())
266 results.removeOne(entry);
267
268 return this;
269}
270
272{
273 for(auto entry : QVector<MapDBEntry*>(results))
274 if(entry->sprites.isEmpty())
275 results.removeOne(entry);
276
277 return this;
278}
279
281{
282 for(auto entry : QVector<MapDBEntry*>(results))
283 if(!entry->sprites.isEmpty())
284 results.removeOne(entry);
285
286 return this;
287}
288
290{
291 // spriteSet is an index where -1 means "none" (NOT 0). The old `!entry->spriteSet`
292 // test only caught index 0, so it mis-classified -1 ("none") as "has". Use the
293 // sentinel directly.
294 for(auto entry : QVector<MapDBEntry*>(results))
295 if(entry->spriteSet < 0)
296 results.removeOne(entry);
297
298 return this;
299}
300
302{
303 for(auto entry : QVector<MapDBEntry*>(results))
304 if(entry->spriteSet >= 0)
305 results.removeOne(entry);
306
307 return this;
308}
309
311{
312 // Keep maps whose (resolved) sprite set is dynamic. Guard both the -1 sentinel
313 // and a null toSpriteSet -- the old code dereferenced toSpriteSet whenever
314 // spriteSet != 0, crashing on every map with no sprite set (spriteSet == -1).
315 for(auto entry : QVector<MapDBEntry*>(results))
316 if(entry->spriteSet < 0 || entry->toSpriteSet == nullptr ||
317 !entry->toSpriteSet->isDynamic())
318 results.removeOne(entry);
319
320 return this;
321}
322
324{
325 // Keep maps that carry a (resolved) NON-dynamic sprite set -- the complement of
326 // hasDynamicSpriteSet() among maps that actually have a sprite set. Same -1 +
327 // null guard as above (preserves the original "must have a sprite set" intent).
328 for(auto entry : QVector<MapDBEntry*>(results))
329 if(entry->spriteSet < 0 || entry->toSpriteSet == nullptr ||
330 entry->toSpriteSet->isDynamic())
331 results.removeOne(entry);
332
333 return this;
334}
335
337{
338 for(auto entry : QVector<MapDBEntry*>(results))
339 if(entry->monRate < 0 || entry->monRate == 0)
340 results.removeOne(entry);
341
342 return this;
343}
344
346{
347 for(auto entry : QVector<MapDBEntry*>(results))
348 if(entry->monRate < 0 || entry->monRate > 0)
349 results.removeOne(entry);
350
351 return this;
352}
353
355{
356 for(auto entry : QVector<MapDBEntry*>(results))
357 if(entry->incomplete == "")
358 results.removeOne(entry);
359
360 return this;
361}
362
364{
365 for(auto entry : QVector<MapDBEntry*>(results))
366 if(entry->incomplete != "")
367 results.removeOne(entry);
368
369 return this;
370}
371
373{
374 for(auto entry : QVector<MapDBEntry*>(results))
375 if(!entry->glitch)
376 results.removeOne(entry);
377
378 return this;
379}
380
382{
383 for(auto entry : QVector<MapDBEntry*>(results)) {
384 if(entry->glitch)
385 results.removeOne(entry);
386 }
387
388 return this;
389}
390
392{
393 for(auto entry : QVector<MapDBEntry*>(results))
394 if(!entry->special)
395 results.removeOne(entry);
396
397 return this;
398}
399
401{
402 for(auto entry : QVector<MapDBEntry*>(results))
403 if(entry->special)
404 results.removeOne(entry);
405
406 return this;
407}
408
410{
411 return notGlitch()->notSpecial()->notIncomplete()->
412 hasWarpsIn()->hasWarpsOut()->notNamed("Silph Co Elevator");
413}
414
416{
417 return indexLt(11);
418}
419
421{
422 return indexGt(10);
423}
424
425const QVector<MapDBEntry*> MapSearch::getMaps() const
426{
427 return results;
428}
429
431{
432 return results.size();
433}
434
435const MapDBEntry* MapSearch::mapAt(const int ind) const
436{
437 if(ind >= results.size())
438 return nullptr;
439
440 return results.at(ind);
441}
442
443void MapSearch::qmlProtect(const QQmlEngine* const engine) const
444{
445 Utility::qmlProtectUtil(this, engine);
446}
447
448void MapSearch::qmlRegister() const
449{
450 static bool registered = false;
451 if(registered)
452 return;
453
454 qmlRegisterUncreatableType<MapSearch>("PSE.DB.MapSearch", 1, 0, "MapSearch", "Can't instantiate in QML");
455 registered = true;
456}
MapSearch * indexGt(int val)
Keep maps with index > val.
Definition mapsearch.cpp:81
MapSearch * startOver()
Reset to all maps. Returns this.
Definition mapsearch.cpp:49
MapSearch * isGood()
Keep only "good" maps (criteria listed above).
MapSearch * noWarpsIn()
MapSearch * hasMons()
MapSearch * hasConnections()
MapDBEntry * pickRandom()
A random map from the current results (backs pickRandom).
Definition mapsearch.cpp:41
MapSearch * noSprites()
MapSearch * widthGt(int val)
Keep maps wider than val.
Definition mapsearch.cpp:90
MapSearch * areaLt(int val)
Keep maps with area < val.
MapSearch * hasSpriteSet()
MapSearch * hasTileset(QString val)
Keep maps using tileset val.
MapSearch * hasWarpsIn()
MapSearch * heightLt(int val)
Keep maps shorter than val.
MapSearch * noSpriteSet()
MapSearch * heightGt(int val)
Keep maps taller than val.
const QVector< MapDBEntry * > getMaps() const
The current result set.
MapSearch * widthLt(int val)
Keep maps narrower than val.
Definition mapsearch.cpp:99
MapSearch()
Start with all maps in the result set.
Definition mapsearch.cpp:35
MapSearch * notType(QString val)
Drop maps of tileset-type val.
MapSearch * hasSprites()
MapSearch * noMons()
int getMapCount() const
Result count (backs mapCount).
MapSearch * hasDynamicSpriteSet()
void qmlProtect(const QQmlEngine *const engine) const
Pin to C++ ownership.
MapSearch * hasWarpsOut()
MapSearch * isIncomplete()
MapSearch * areaGt(int val)
Keep maps with area > val.
MapSearch * isType(QString val)
Keep maps of tileset-type val.
MapSearch * isGlitch()
MapSearch * noDynamicSpriteSet()
MapSearch * noWarpsOut()
MapSearch * notTileset(QString val)
Drop maps using tileset val.
MapSearch * notCity()
MapSearch * notIncomplete()
MapSearch * notGlitch()
MapSearch * notNamed(QString val)
Drop the map named val.
Definition mapsearch.cpp:62
MapSearch * noConnections()
MapSearch * hasSigns()
MapSearch * noSigns()
MapSearch * indexLt(int val)
Keep maps with index < val.
Definition mapsearch.cpp:72
MapSearch * notSpecial()
const MapDBEntry * mapAt(const int ind) const
Result ind (for QML).
MapSearch * isSpsecial()
MapSearch * isCity()
static MapsDB * inst()
< Number of maps.
Definition mapsdb.cpp:35
static Random * inst()
< Convenience 50% coin flip (integer path), readable from QML.
Definition random.cpp:31
static void qmlProtectUtil(const QObject *const obj, const QQmlEngine *const engine)
Pin obj to C++ ownership so the QML engine never garbage-collects it.
Definition utility.cpp:63
One map's complete static definition – the root of the MapDBEntry family.
Definition mapdbentry.h:56