1 #pragma once
2 
3 #include "actor.h"
4 #include "coord-circle.h"
5 #include "los-type.h"
6 
7 #include <vector>
8 
9 using std::vector;
10 
11 class rectangle_iterator : public iterator<forward_iterator_tag, coord_def>
12 {
13 public:
14     rectangle_iterator(const coord_def& corner1, const coord_def& corner2);
15     rectangle_iterator(const coord_def& center, int halfside,
16                        bool clip_to_map = false);
17     explicit rectangle_iterator(int x_border_dist, int y_border_dist = -1);
18     operator bool() const PURE;
19     coord_def operator *() const PURE;
20     const coord_def* operator->() const PURE;
21 
22     void operator ++ ();
23     void operator ++ (int);
24 private:
25     coord_def current, topleft, bottomright;
26 };
27 
28 /**
29  * @class random_rectangle_iterator
30  * Iterator over coordinates in a rectangular region in a
31  * random order. This interator does not favour any given
32  * direction, but is slower than rectangle_iterator.
33  *
34  * When this iterator has returned all elements, it will just
35  * return the top left corner forever.
36  */
37 class random_rectangle_iterator : public iterator<forward_iterator_tag,
38                                                   coord_def>
39 {
40 public:
41     random_rectangle_iterator(const coord_def& corner1,
42                               const coord_def& corner2);
43     explicit random_rectangle_iterator(int x_border_dist,
44                                        int y_border_dist = -1);
45     operator bool() const PURE;
46     coord_def operator *() const PURE;
47     const coord_def* operator->() const PURE;
48 
49     void operator ++ ();
50     void operator ++ (int);
51 private:
52     coord_def top_left;
53     vector<coord_def> remaining;
54     int current;
55 };
56 
57 /**
58  * @class radius_iterator
59  * Iterator over coordinates in a circular region.
60  *
61  * The region can be a circle of any r²; furthermore, the cells can
62  * be restricted to lie within LOS from the center (of any type)
63  * centered at the same point), and to exclude the center.
64  */
65 class radius_iterator : public iterator<forward_iterator_tag, coord_def>
66 {
67 public:
68     radius_iterator(const coord_def center, int radius, circle_type ctype,
69                     bool exclude_center = false);
70     radius_iterator(const coord_def center, int radius, circle_type ctype,
71                     los_type los, bool exclude_center = false);
72     radius_iterator(const coord_def center, los_type los,
73                     bool exclude_center = false);
74 
75     operator bool() const PURE;
76     coord_def operator *() const PURE;
77     const coord_def *operator->() const PURE;
78 
79     void operator ++ ();
80     void operator ++ (int);
81 
82 private:
83     enum costate { RI_DONE, RI_START, RI_SE, RI_NE, RI_SW, RI_NW };
84     int x, y, cost_x, cost_y, credit, credit_x, credit_y, base_cost, inc_cost;
85     bool is_square;
86 
87     costate state;
88     coord_def center;
89     los_type los;
90     coord_def current;    // storage for operator->
91 };
92 
93 /**
94  * @class vision_iterator
95  * Iterator over coordinates in view of a certain actor.
96  *
97  * Uses the actor's see_cell method, which includes checks for scrying-like
98  * effects as well as respecting the los_type
99  */
100 class vision_iterator : public radius_iterator
101 {
102 public:
vision_iterator(const actor & _who)103     explicit vision_iterator(const actor& _who) :
104         radius_iterator(_who.pos(), LOS_NONE), who(_who) {};
105 
106     void operator ++ ();
107     void operator ++ (int);
108 private:
109     const actor& who;
110 };
111 
112 class adjacent_iterator : public iterator<forward_iterator_tag, coord_def>
113 {
114 public:
115     adjacent_iterator(const coord_def pos, bool _exclude_center = true)
center(pos)116         : center(pos), i(_exclude_center ? 8 : 9) {++(*this);};
117 
118     operator bool() const PURE;
119     coord_def operator *() const PURE;
120     const coord_def *operator->() const PURE;
121 
122     void operator ++ ();
123     void operator ++ (int);
124 private:
125     coord_def center;
126     coord_def val;
127     int i;
128 };
129 
130 class orth_adjacent_iterator : public radius_iterator
131 {
132 public:
133     explicit orth_adjacent_iterator(const coord_def& pos,
134                                     bool _exclude_center = true) :
135     radius_iterator(pos, 1, C_POINTY, _exclude_center) {}
136 };
137 
138 /* @class distance_iterator
139  * Iterates over coordinates in integer ranges.
140  *
141  * Unlike other iterators, it tries hard to not favourite any
142  * particular direction (unless fair = false, when it saves some CPU).
143  */
144 class distance_iterator : public iterator<forward_iterator_tag, coord_def>
145 {
146 public:
147     distance_iterator(const coord_def& _center,
148                     bool _fair = true,
149                     bool exclude_center = true,
150                     int _max_radius = GDM);
151     operator bool() const PURE;
152     coord_def operator *() const PURE;
153     const coord_def *operator->() const PURE;
154 
155     const distance_iterator &operator ++();
156     void operator ++(int);
157     int radius() const;
158 private:
159     coord_def center, current;
160     vector<coord_def> lists[3], *vcur, *vnear, *vfar;
161     int r, max_radius;
162     int threshold;
163     unsigned int icur, iend;
164     bool fair;
165     bool advance();
166     void push_neigh(coord_def from, int dx, int dy);
167 };
168 
169 // If this becomes performance-critical, reimplement it as adjacent_iterator
170 // with a permutation array.
171 class fair_adjacent_iterator : public distance_iterator
172 {
173 public:
174     fair_adjacent_iterator(coord_def _center, bool _exclude_center = true)
175         : distance_iterator(_center, true, _exclude_center, 1) {}
176 };
177 
178 # ifdef DEBUG_TESTS
179 void coordit_tests();
180 # endif
181