-
Notifications
You must be signed in to change notification settings - Fork 0
/
WorldModel.java
230 lines (197 loc) · 5.52 KB
/
WorldModel.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import processing.core.PImage;
import java.util.*;
final class WorldModel
{
private int numRows;
private int numCols;
private Background[][] background;
private WorldEntity[][] occupancy;
private Set<WorldEntity> entities;
private static final int ORE_REACH = 1;
public WorldModel(int numRows, int numCols, Background defaultBackground)
{
this.numRows = numRows;
this.numCols = numCols;
this.background = new Background[numRows][numCols];
this.occupancy = new WorldEntity[numRows][numCols];
this.entities = new HashSet<>();
for (int row = 0; row < numRows; row++)
{
Arrays.fill(this.getBackground()[row], defaultBackground);
}
}
private static Optional<WorldEntity> nearestEntity(List<WorldEntity> entities,
Point pos)
{
if (entities.isEmpty())
{
return Optional.empty();
}
else
{
WorldEntity nearest = entities.get(0);
int nearestDistance = nearest.getPosition().distanceSquared(pos);
for (WorldEntity other : entities)
{
int otherDistance = other.getPosition().distanceSquared(pos);
if (otherDistance < nearestDistance)
{
nearest = other;
nearestDistance = otherDistance;
}
}
return Optional.of(nearest);
}
}
public void setBackground(Point pos,
Background background)
{
if (withinBounds(pos))
{
setBackgroundCell(pos, background);
}
}
public Optional<PImage> getBackgroundImage(Point pos)
{
if (withinBounds(pos))
{
return Optional.of(getBackgroundCell(pos).getCurrentImage());
}
else
{
return Optional.empty();
}
}
private void removeEntityAt(Point pos)
{
if (withinBounds(pos)
&& getOccupancyCell(pos) != null)
{
WorldEntity entity = getOccupancyCell(pos);
/* this moves the entity just outside of the grid for
debugging purposes */
entity.setPosition(new Point(-1, -1));
getEntities().remove(entity);
setOccupancyCell(pos, null);
}
}
public void removeEntity(WorldEntity entity)
{
this.removeEntityAt(entity.getPosition());
}
public void moveEntity(WorldEntity entity, Point pos)
{
Point oldPos = entity.getPosition();
if (withinBounds(pos) && !pos.equals(oldPos))
{
setOccupancyCell(oldPos, null);
this.removeEntityAt(pos);
setOccupancyCell(pos, entity);
entity.setPosition(pos);
}
}
/*
Assumes that there is no entity currently occupying the
intended destination cell.
*/
public void addEntity(WorldEntity entity)
{
if (withinBounds(entity.getPosition()))
{
setOccupancyCell(entity.getPosition(), entity);
getEntities().add(entity);
}
}
public Optional<WorldEntity> findNearest(Point pos, String className)
{
List<WorldEntity> ofType = new LinkedList<>();
for (WorldEntity entity : getEntities())
{
if (entity.getClass().getName().equals(className))
{
ofType.add(entity);
}
}
return nearestEntity(ofType, pos);
}
public boolean isOccupied(Point pos)
{
return withinBounds(pos) &&
getOccupancyCell(pos) != null;
}
private boolean withinBounds(Point pos)
{
return pos.getY() >= 0 && pos.getY() < getNumRows() &&
pos.getX() >= 0 && pos.getX() < getNumCols();
}
public void tryAddEntity(WorldEntity entity)
{
if (this.isOccupied(entity.getPosition()))
{
// arguably the wrong type of exception, but we are not
// defining our own exceptions yet
throw new IllegalArgumentException("position occupied");
}
this.addEntity(entity);
}
public Optional<WorldEntity> getOccupant(Point pos)
{
if (this.isOccupied(pos))
{
return Optional.of(getOccupancyCell(pos));
}
else
{
return Optional.empty();
}
}
private WorldEntity getOccupancyCell(Point pos)
{
return getOccupancy()[pos.getY()][pos.getX()];
}
private void setOccupancyCell(Point pos,
WorldEntity entity)
{
getOccupancy()[pos.getY()][pos.getX()] = entity;
}
private Background getBackgroundCell(Point pos)
{
return getBackground()[pos.getY()][pos.getX()];
}
private void setBackgroundCell(Point pos,
Background background)
{
this.getBackground()[pos.getY()][pos.getX()] = background;
}
public Optional<Point> findOpenAround(Point pos)
{
for (int dy = -ORE_REACH; dy <= ORE_REACH; dy++)
{
for (int dx = -ORE_REACH; dx <= ORE_REACH; dx++)
{
Point newPt = new Point(pos.getX() + dx, pos.getY() + dy);
if (this.withinBounds(newPt) &&
!this.isOccupied(newPt))
{
return Optional.of(newPt);
}
}
}
return Optional.empty();
}
public int getNumRows() {
return numRows;
}
public int getNumCols() {
return numCols;
}
private Background[][] getBackground() {
return background;
}
private WorldEntity[][] getOccupancy() {
return occupancy;
}
public Set<WorldEntity> getEntities() {
return entities;
}
}