1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2017-2020, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17#pragma once
18
19#include "C4Id.h"
20#include "C4Sector.h"
21#include "C4Shape.h"
22#include "C4Value.h"
23#include "C4Aul.h"
24
25// Condition map
26enum C4FindObjectCondID
27{
28 C4FO_Not = 1,
29 C4FO_And = 2,
30 C4FO_Or = 3,
31 C4FO_Exclude = 5,
32 C4FO_InRect = 10,
33 C4FO_AtPoint = 11,
34 C4FO_AtRect = 12,
35 C4FO_OnLine = 13,
36 C4FO_Distance = 14,
37 C4FO_ID = 20,
38 C4FO_OCF = 21,
39 C4FO_Category = 22,
40 C4FO_Action = 30,
41 C4FO_ActionTarget = 31,
42 C4FO_Container = 40,
43 C4FO_AnyContainer = 41,
44 C4FO_Owner = 50,
45 C4FO_Controller = 51,
46 C4FO_Func = 60,
47 C4FO_Layer = 70,
48};
49
50// Sort map - using same values as C4FindObjectCondID!
51enum C4SortObjectCondID
52{
53 C4SO_First = 100, // no sort condition smaller than this
54 C4SO_Reverse = 101, // reverse sort order
55 C4SO_Multiple = 102, // multiple sorts; high priority first; lower priorities if higher prio returned equal
56 C4SO_Distance = 110, // nearest first
57 C4SO_Random = 120, // random first
58 C4SO_Speed = 130, // slowest first
59 C4SO_Mass = 140, // lightest first
60 C4SO_Value = 150, // cheapest first
61 C4SO_Func = 160, // least return values first
62 C4SO_Last = 200, // no sort condition larger than this
63};
64
65// Base class
66class C4FindObject
67{
68 friend class C4FindObjectNot;
69 friend class C4FindObjectAnd;
70 friend class C4FindObjectOr;
71
72 class C4SortObject *pSort;
73
74public:
75 C4FindObject() : pSort(nullptr) {}
76 virtual ~C4FindObject();
77
78 static C4FindObject *CreateByValue(const C4Value &Data, C4SortObject **ppSortObj = nullptr); // createFindObject or SortObject - if ppSortObj==nullptr, SortObject is not allowed
79
80 int32_t Count(const C4ObjectList &Objs); // Counts objects for which the condition is true
81 C4Object *Find(const C4ObjectList &Objs); // Returns first object for which the condition is true
82 C4ValueArray *FindMany(const C4ObjectList &Objs); // Returns all objects for which the condition is true
83
84 int32_t Count(const C4ObjectList &Objs, const C4LSectors &Sct); // Counts objects for which the condition is true
85 C4Object *Find(const C4ObjectList &Objs, const C4LSectors &Sct); // Returns first object for which the condition is true
86 C4ValueArray *FindMany(const C4ObjectList &Objs, const C4LSectors &Sct); // Returns all objects for which the condition is true
87
88 void SetSort(C4SortObject *pToSort);
89
90protected:
91 // Overridables
92 virtual bool Check(C4Object *pObj) = 0;
93 virtual C4Rect *GetBounds() { return nullptr; }
94 virtual bool UseShapes() { return false; }
95 virtual bool IsImpossible() { return false; }
96 virtual bool IsEnsured() { return false; }
97
98private:
99 void CheckObjectStatus(std::vector<C4Object *> &objects);
100 void CheckObjectStatusAfterSort(std::vector<C4Object *> &objects);
101};
102
103// Combinators
104class C4FindObjectNot : public C4FindObject
105{
106public:
107 C4FindObjectNot(C4FindObject *pCond)
108 : pCond(pCond) {}
109 virtual ~C4FindObjectNot();
110
111private:
112 C4FindObject *pCond;
113
114protected:
115 virtual bool Check(C4Object *pObj) override;
116 virtual bool IsImpossible() override { return pCond->IsEnsured(); }
117 virtual bool IsEnsured() override { return pCond->IsImpossible(); }
118};
119
120class C4FindObjectAnd : public C4FindObject
121{
122public:
123 C4FindObjectAnd(int32_t iCnt, C4FindObject **ppConds, bool fFreeArray = true);
124 virtual ~C4FindObjectAnd();
125
126private:
127 int32_t iCnt;
128 C4FindObject **ppConds; bool fFreeArray; bool fUseShapes;
129 C4Rect Bounds; bool fHasBounds;
130
131protected:
132 virtual bool Check(C4Object *pObj) override;
133 virtual C4Rect *GetBounds() override { return fHasBounds ? &Bounds : nullptr; }
134 virtual bool UseShapes() override { return fUseShapes; }
135 virtual bool IsEnsured() override { return !iCnt; }
136 virtual bool IsImpossible() override;
137};
138
139class C4FindObjectOr : public C4FindObject
140{
141public:
142 C4FindObjectOr(int32_t iCnt, C4FindObject **ppConds);
143 virtual ~C4FindObjectOr();
144
145private:
146 int32_t iCnt;
147 C4FindObject **ppConds;
148 C4Rect Bounds; bool fHasBounds;
149
150protected:
151 virtual bool Check(C4Object *pObj) override;
152 virtual C4Rect *GetBounds() override { return fHasBounds ? &Bounds : nullptr; }
153 virtual bool IsEnsured() override;
154 virtual bool IsImpossible() override { return !iCnt; }
155};
156
157// Primitive conditions
158class C4FindObjectExclude : public C4FindObject
159{
160public:
161 C4FindObjectExclude(C4Object *pExclude)
162 : pExclude(pExclude) {}
163
164private:
165 C4Object *pExclude;
166
167protected:
168 virtual bool Check(C4Object *pObj) override;
169};
170
171class C4FindObjectID : public C4FindObject
172{
173public:
174 C4FindObjectID(C4ID id)
175 : id(id) {}
176
177private:
178 C4ID id;
179
180protected:
181 virtual bool Check(C4Object *pObj) override;
182 virtual bool IsImpossible() override;
183};
184
185class C4FindObjectInRect : public C4FindObject
186{
187public:
188 C4FindObjectInRect(const C4Rect &rect)
189 : rect(rect) {}
190
191private:
192 C4Rect rect;
193
194protected:
195 virtual bool Check(C4Object *pObj) override;
196 virtual C4Rect *GetBounds() override { return &rect; }
197 virtual bool IsImpossible() override;
198};
199
200class C4FindObjectAtPoint : public C4FindObject
201{
202public:
203 C4FindObjectAtPoint(int32_t x, int32_t y)
204 : bounds(x, y, 1, 1) {}
205
206private:
207 C4Rect bounds;
208
209protected:
210 virtual bool Check(C4Object *pObj) override;
211 virtual C4Rect *GetBounds() override { return &bounds; }
212 virtual bool UseShapes() override { return true; }
213};
214
215class C4FindObjectAtRect : public C4FindObject
216{
217public:
218 C4FindObjectAtRect(int32_t x, int32_t y, int32_t wdt, int32_t hgt)
219 : bounds(x, y, wdt, hgt) {}
220
221private:
222 C4Rect bounds;
223
224protected:
225 virtual bool Check(C4Object *pObj) override;
226 virtual C4Rect *GetBounds() override { return &bounds; }
227 virtual bool UseShapes() override { return true; }
228};
229
230class C4FindObjectOnLine : public C4FindObject
231{
232public:
233 C4FindObjectOnLine(int32_t x, int32_t y, int32_t x2, int32_t y2)
234 : x(x), y(y), x2(x2), y2(y2), bounds(x, y, 1, 1)
235 {
236 bounds.Add(r2: C4Rect(x2, y2, 1, 1));
237 }
238
239private:
240 int32_t x, y, x2, y2;
241 C4Rect bounds;
242
243protected:
244 virtual bool Check(C4Object *pObj) override;
245 virtual C4Rect *GetBounds() override { return &bounds; }
246 virtual bool UseShapes() override { return true; }
247};
248
249class C4FindObjectDistance : public C4FindObject
250{
251public:
252 C4FindObjectDistance(int32_t x, int32_t y, int32_t r)
253 : x(x), y(y), r2(r * r), bounds(x - r, y - r, 2 * r + 1, 2 * r + 1) {}
254
255private:
256 int32_t x, y, r2;
257 C4Rect bounds;
258
259protected:
260 virtual bool Check(C4Object *pObj) override;
261 virtual C4Rect *GetBounds() override { return &bounds; }
262};
263
264class C4FindObjectOCF : public C4FindObject
265{
266public:
267 C4FindObjectOCF(int32_t ocf)
268 : ocf(ocf) {}
269
270private:
271 int32_t ocf;
272
273protected:
274 virtual bool Check(C4Object *pObj) override;
275 virtual bool IsImpossible() override;
276};
277
278class C4FindObjectCategory : public C4FindObject
279{
280public:
281 C4FindObjectCategory(int32_t iCategory)
282 : iCategory(iCategory) {}
283
284private:
285 int32_t iCategory;
286
287protected:
288 virtual bool Check(C4Object *pObj) override;
289 virtual bool IsEnsured() override;
290};
291
292class C4FindObjectAction : public C4FindObject
293{
294public:
295 C4FindObjectAction(const char *szAction)
296 : szAction(szAction) {}
297
298private:
299 const char *szAction;
300
301protected:
302 virtual bool Check(C4Object *pObj) override;
303};
304
305class C4FindObjectActionTarget : public C4FindObject
306{
307public:
308 C4FindObjectActionTarget(C4Object *pActionTarget, int index)
309 : pActionTarget(pActionTarget), index(index) {}
310
311private:
312 C4Object *pActionTarget;
313 int index;
314
315protected:
316 virtual bool Check(C4Object *pObj) override;
317};
318
319class C4FindObjectContainer : public C4FindObject
320{
321public:
322 C4FindObjectContainer(C4Object *pContainer)
323 : pContainer(pContainer) {}
324
325private:
326 C4Object *pContainer;
327
328protected:
329 virtual bool Check(C4Object *pObj) override;
330};
331
332class C4FindObjectAnyContainer : public C4FindObject
333{
334public:
335 C4FindObjectAnyContainer() {}
336
337protected:
338 virtual bool Check(C4Object *pObj) override;
339};
340
341class C4FindObjectOwner : public C4FindObject
342{
343public:
344 C4FindObjectOwner(int32_t iOwner)
345 : iOwner(iOwner) {}
346
347private:
348 int32_t iOwner;
349
350protected:
351 virtual bool Check(C4Object *pObj) override;
352 virtual bool IsImpossible() override;
353};
354
355class C4FindObjectFunc : public C4FindObject
356{
357public:
358 C4FindObjectFunc(const char *szFunc);
359 void SetPar(int i, const C4Value &val);
360
361private:
362 C4AulFunc *pFunc;
363 C4AulParSet Pars;
364
365protected:
366 virtual bool Check(C4Object *pObj) override;
367 virtual bool IsImpossible() override;
368};
369
370class C4FindObjectLayer : public C4FindObject
371{
372public:
373 C4FindObjectLayer(C4Object *pLayer) : pLayer(pLayer) {}
374
375private:
376 C4Object *pLayer;
377
378protected:
379 virtual bool Check(C4Object *pObj) override;
380 virtual bool IsImpossible() override;
381};
382
383class C4FindObjectController : public C4FindObject
384{
385public:
386 C4FindObjectController(int32_t controller)
387 : controller(controller) {}
388
389private:
390 int32_t controller;
391
392protected:
393 virtual bool Check(C4Object *pObj) override;
394 virtual bool IsImpossible() override;
395};
396
397// result sorting
398class C4SortObject
399{
400public:
401 C4SortObject() {}
402 virtual ~C4SortObject() {}
403
404public:
405 // Overridables
406 virtual int32_t Compare(C4Object *pObj1, C4Object *pObj2) = 0; // return value <0 if obj1 is to be sorted before obj2
407
408 virtual bool PrepareCache([[maybe_unused]] std::vector<C4Object *> &objects) { return false; }
409 virtual int32_t CompareCache(int32_t iObj1, int32_t iObj2, C4Object *pObj1, C4Object *pObj2) { return Compare(pObj1, pObj2); }
410
411public:
412 static C4SortObject *CreateByValue(const C4Value &Data);
413 static C4SortObject *CreateByValue(C4ValueInt iType, const C4ValueArray &Data);
414
415 void SortObjects(std::vector<C4Object *> &result);
416};
417
418class C4SortObjectByValue : public C4SortObject
419{
420public:
421 C4SortObjectByValue();
422 ~C4SortObjectByValue() override = default;
423
424private:
425 std::vector<std::int32_t> values;
426
427public:
428 // Overridables
429 virtual int32_t Compare(C4Object *pObj1, C4Object *pObj2) override;
430 virtual int32_t CompareGetValue(C4Object *pOf) = 0;
431
432 virtual bool PrepareCache(std::vector<C4Object *> &objects) override;
433 virtual int32_t CompareCache(int32_t iObj1, int32_t iObj2, C4Object *pObj1, C4Object *pObj2) override;
434};
435
436class C4SortObjectReverse : public C4SortObject // reverse sort
437{
438public:
439 C4SortObjectReverse(C4SortObject *pSort)
440 : C4SortObject(), pSort(pSort) {}
441 virtual ~C4SortObjectReverse();
442
443private:
444 C4SortObject *pSort;
445
446protected:
447 int32_t Compare(C4Object *pObj1, C4Object *pObj2) override;
448
449 virtual bool PrepareCache(std::vector<C4Object *> &objects) override;
450 virtual int32_t CompareCache(int32_t iObj1, int32_t iObj2, C4Object *pObj1, C4Object *pObj2) override;
451};
452
453class C4SortObjectMultiple : public C4SortObject // apply next sort if previous compares to equality
454{
455public:
456 C4SortObjectMultiple(int32_t iCnt, C4SortObject **ppSorts, bool fFreeArray = true)
457 : C4SortObject(), iCnt(iCnt), ppSorts(ppSorts), fFreeArray(fFreeArray) {}
458 virtual ~C4SortObjectMultiple();
459
460private:
461 bool fFreeArray;
462 int32_t iCnt;
463 C4SortObject **ppSorts;
464
465protected:
466 int32_t Compare(C4Object *pObj1, C4Object *pObj2) override;
467
468 virtual bool PrepareCache(std::vector<C4Object *> &objects) override;
469 virtual int32_t CompareCache(int32_t iObj1, int32_t iObj2, C4Object *pObj1, C4Object *pObj2) override;
470};
471
472class C4SortObjectDistance : public C4SortObjectByValue // sort by distance from point x/y
473{
474public:
475 C4SortObjectDistance(int iX, int iY)
476 : C4SortObjectByValue(), iX(iX), iY(iY) {}
477
478private:
479 int iX, iY;
480
481protected:
482 int32_t CompareGetValue(C4Object *pFor) override;
483};
484
485class C4SortObjectRandom : public C4SortObjectByValue // randomize order
486{
487public:
488 C4SortObjectRandom() : C4SortObjectByValue() {}
489
490protected:
491 int32_t CompareGetValue(C4Object *pFor) override;
492};
493
494class C4SortObjectSpeed : public C4SortObjectByValue // sort by object xdir/ydir
495{
496public:
497 C4SortObjectSpeed() : C4SortObjectByValue() {}
498
499protected:
500 int32_t CompareGetValue(C4Object *pFor) override;
501};
502
503class C4SortObjectMass : public C4SortObjectByValue // sort by mass
504{
505public:
506 C4SortObjectMass() : C4SortObjectByValue() {}
507
508protected:
509 int32_t CompareGetValue(C4Object *pFor) override;
510};
511
512class C4SortObjectValue : public C4SortObjectByValue // sort by value
513{
514public:
515 C4SortObjectValue() : C4SortObjectByValue() {}
516
517protected:
518 int32_t CompareGetValue(C4Object *pFor) override;
519};
520
521class C4SortObjectFunc : public C4SortObjectByValue // sort by script function
522{
523public:
524 C4SortObjectFunc(const char *szFunc);
525 void SetPar(int i, const C4Value &val);
526
527private:
528 C4AulFunc *pFunc;
529 C4AulParSet Pars;
530
531protected:
532 int32_t CompareGetValue(C4Object *pFor) override;
533};
534