forked from amidos2006/Mario-AI-Framework
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathMarioLevelModel.java
More file actions
317 lines (292 loc) · 9.79 KB
/
Copy pathMarioLevelModel.java
File metadata and controls
317 lines (292 loc) · 9.79 KB
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
package engine.core;
public class MarioLevelModel {
//start and end of the level
public static final char MARIO_START = 'M';
public static final char MARIO_EXIT = 'F';
public static final char EMPTY = '-';
//game tiles symbols
public static final char GROUND = 'X';
public static final char PYRAMID_BLOCK = '#';
public static final char NORMAL_BRICK = 'S';
public static final char COIN_BRICK = 'C';
public static final char LIFE_BRICK = 'L';
public static final char SPECIAL_BRICK = 'U';
public static final char SPECIAL_QUESTION_BLOCK = '@';
public static final char COIN_QUESTION_BLOCK = '!';
public static final char COIN_HIDDEN_BLOCK = '2';
public static final char LIFE_HIDDEN_BLOCK = '1';
public static final char USED_BLOCK = 'D';
public static final char COIN = 'o';
public static final char PIPE = 't';
public static final char PIPE_FLOWER = 'T';
public static final char BULLET_BILL = '*';
public static final char PLATFORM_BACKGROUND = '|';
public static final char PLATFORM = '%';
//enemies that can be in the level
public static final char GOOMBA = 'g';
public static final char GOOMBA_WINGED = 'G';
public static final char RED_KOOPA = 'r';
public static final char RED_KOOPA_WINGED = 'R';
public static final char GREEN_KOOPA = 'k';
public static final char GREEN_KOOPA_WINGED = 'K';
public static final char SPIKY = 'y';
public static final char SPIKY_WINGED = 'Y';
/**
* Get array of level tiles that can spawn enemies
*
* @return tiles that spawn enemies
*/
public static char[] getEnemyTiles() {
return new char[]{BULLET_BILL, PIPE_FLOWER};
}
/**
* list of tiles that can be bumped by the player
*
* @return list of tiles that can be bumped by the player
*/
public static char[] getBumpableTiles() {
return new char[]{NORMAL_BRICK, COIN_BRICK, LIFE_BRICK, SPECIAL_BRICK,
SPECIAL_QUESTION_BLOCK, COIN_QUESTION_BLOCK};
}
/**
* list all the tiles that can block the player movement
*
* @return array of all tiles that block player movement
*/
public static char[] getBlockTiles() {
return new char[]{GROUND, PYRAMID_BLOCK, USED_BLOCK,
NORMAL_BRICK, COIN_BRICK, LIFE_BRICK, SPECIAL_BRICK,
SPECIAL_QUESTION_BLOCK, COIN_QUESTION_BLOCK,
PIPE, PIPE_FLOWER, BULLET_BILL};
}
/**
* tiles that block the player and not interactive
*
* @return list of all solid tiles that don't interact
*/
public static char[] getBlockNonSpecialTiles() {
return new char[]{GROUND, PYRAMID_BLOCK, USED_BLOCK, PIPE};
}
/**
* list of all tiles that won't block the player movement
*
* @return list of all non blocking tiles
*/
public static char[] getNonBlockingTiles() {
return new char[]{COIN, COIN_HIDDEN_BLOCK, LIFE_HIDDEN_BLOCK, PLATFORM_BACKGROUND};
}
/**
* Get a list of all scene tiles that could produce something collected by the player
*
* @return list of all collectible scene tiles
*/
public static char[] getCollectablesTiles() {
return new char[]{COIN,
COIN_BRICK, LIFE_BRICK, SPECIAL_BRICK,
SPECIAL_QUESTION_BLOCK, COIN_QUESTION_BLOCK,
COIN_HIDDEN_BLOCK, LIFE_HIDDEN_BLOCK};
}
/**
* Get the correct version of the enemy char
*
* @param enemy the enemy character
* @param winged boolean to indicate if its a winged enemy
* @return correct character based on winged
*/
public static char getWingedEnemyVersion(char enemy, boolean winged) {
if (!winged) {
if (enemy == GOOMBA_WINGED) {
return GOOMBA;
}
if (enemy == GREEN_KOOPA_WINGED) {
return GREEN_KOOPA;
}
if (enemy == RED_KOOPA_WINGED) {
return RED_KOOPA;
}
if (enemy == SPIKY_WINGED) {
return SPIKY;
}
return enemy;
}
if (enemy == GOOMBA) {
return GOOMBA_WINGED;
}
if (enemy == GREEN_KOOPA) {
return GREEN_KOOPA_WINGED;
}
if (enemy == RED_KOOPA) {
return RED_KOOPA_WINGED;
}
if (enemy == SPIKY) {
return SPIKY_WINGED;
}
return enemy;
}
/**
* a list of all enemy characters
*
* @return array of all enemy characters
*/
public static char[] getEnemyCharacters() {
return new char[]{GOOMBA, GOOMBA_WINGED, RED_KOOPA, RED_KOOPA_WINGED,
GREEN_KOOPA, GREEN_KOOPA_WINGED, SPIKY, SPIKY_WINGED};
}
/**
* list of all enemy character based on wings
*
* @param wings true if the list contain winged enemies and false otherwise
* @return an array of all wings enemy or not winged
*/
public static char[] getEnemyCharacters(boolean wings) {
if (wings) {
return new char[]{GOOMBA_WINGED, RED_KOOPA_WINGED, GREEN_KOOPA_WINGED, SPIKY_WINGED};
}
return new char[]{GOOMBA, RED_KOOPA, GREEN_KOOPA, SPIKY};
}
/**
* map object for helping
*/
private char[][] map;
/**
* create the Level Model
*
* @param levelWidth the width of the level
* @param levelHeight the height of the level
*/
public MarioLevelModel(int levelWidth, int levelHeight) {
this.map = new char[levelWidth][levelHeight];
}
/**
* create a similar clone to the current map
*/
public MarioLevelModel clone() {
MarioLevelModel model = new MarioLevelModel(this.getWidth(), this.getHeight());
for (int x = 0; x < model.getWidth(); x++) {
for (int y = 0; y < model.getHeight(); y++) {
model.map[x][y] = this.map[x][y];
}
}
return model;
}
/**
* get map width
*
* @return map width
*/
public int getWidth() {
return this.map.length;
}
/**
* get map height
*
* @return map height
*/
public int getHeight() {
return this.map[0].length;
}
/**
* get the value of the tile in certain location
*
* @param x x tile position
* @param y y tile position
* @return the tile value
*/
public char getBlock(int x, int y) {
int currentX = x;
int currentY = y;
if (x < 0) currentX = 0;
if (y < 0) currentY = 0;
if (x > this.map.length - 1) currentX = this.map.length - 1;
if (y > this.map[0].length - 1) currentY = this.map[0].length - 1;
return this.map[currentX][currentY];
}
/**
* set a tile on the map with certain value
*
* @param x the x tile position
* @param y the y tile position
* @param value the tile value to be set
*/
public void setBlock(int x, int y, char value) {
if (x < 0 || y < 0 || x > this.map.length - 1 || y > this.map[0].length - 1) return;
this.map[x][y] = value;
}
/**
* set a rectangle area of the map with a certain tile value
*
* @param startX the x tile position of the left upper corner
* @param startY the y tile position of the left upper corner
* @param width the width of the rectangle
* @param height the height of the rectangle
* @param value the tile value
*/
public void setRectangle(int startX, int startY, int width, int height, char value) {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
this.setBlock(startX + x, startY + y, value);
}
}
}
/**
* Copy the string level to the current map
*
* @param level the input string level
*/
public void copyFromString(String level) {
this.copyFromString(0, 0, 0, 0, this.getWidth(), this.getHeight(), level);
}
/**
* Copy portion from string to the current map
*
* @param targetX the x of the target location
* @param targetY the y of the target location
* @param sourceX the x from the level string
* @param sourceY the y from the level string
* @param width the width of the copied portion
* @param height the height of the copied protion
* @param level the level string
*/
public void copyFromString(int targetX, int targetY, int sourceX, int sourceY, int width, int height, String level) {
String[] lines = level.split("\n");
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int maxWidth = lines[0].length();
int maxHeight = lines.length;
this.setBlock(x + targetX, y + targetY, lines[Math.min(y + sourceY, maxHeight - 1)].charAt(Math.min(x + sourceX, maxWidth - 1)));
}
}
}
/**
* clear the whole map
*/
public void clearMap() {
this.setRectangle(0, 0, this.getWidth(), this.getHeight(), EMPTY);
}
/**
* get the string value of the map
*
* @return the map in form of string
*/
public String getMap() {
String result = "";
for (int y = 0; y < map[0].length; y++) {
for (int x = 0; x < map.length; x++) {
result += map[x][y];
}
result += "\n";
}
return result;
}
/**
* test the current level using a specific agent
*
* @param agent agent to test the level
* @param timer amount of time allowed to test that level
* @return statistical results about the level
*/
public MarioResult testALevelWithAgent(MarioAgent agent, int timer) {
MarioGame game = new MarioGame();
return game.runGame(agent, this.getMap(), timer);
}
}