2 #include <jumpnrun/levels.h>
3 #include <jumpnrun/items.h>
4 #include <jumpnrun/tiles.h>
5 #include <jumpnrun/enemies.h>
8 #include <boost/spirit/include/qi_symbols.hpp>
9 #include <boost/algorithm/string/trim.hpp>
25 #define PATH_PREFIX "../badge/jumpnrun/levels/"
31 ("tube_top_left" , JUMPNRUN_TILE_TYPE_TUBE_TOP_LEFT
)
32 ("tube_top_right", JUMPNRUN_TILE_TYPE_TUBE_TOP_RIGHT
)
33 ("tube_left" , JUMPNRUN_TILE_TYPE_TUBE_LEFT
)
34 ("tube_right" , JUMPNRUN_TILE_TYPE_TUBE_RIGHT
)
35 ("brick" , JUMPNRUN_TILE_TYPE_BRICK
)
36 ("square" , JUMPNRUN_TILE_TYPE_SQUARE
)
37 ("spike_up" , JUMPNRUN_TILE_TYPE_SPIKE_UP
)
38 ("spike_right" , JUMPNRUN_TILE_TYPE_SPIKE_RIGHT
)
39 ("spike_down" , JUMPNRUN_TILE_TYPE_SPIKE_DOWN
)
40 ("spike_left" , JUMPNRUN_TILE_TYPE_SPIKE_LEFT
)
44 ("doc" , JUMPNRUN_ITEM_TYPE_DOCUMENT
)
45 ("checkpoint" , JUMPNRUN_ITEM_TYPE_CHECKPOINT
)
46 ("key" , JUMPNRUN_ITEM_TYPE_KEY
)
47 ("doc_encrypted", JUMPNRUN_ITEM_TYPE_ENCRYPTED_DOCUMENT
)
51 ("cat" , JUMPNRUN_ENEMY_TYPE_CAT
)
52 ("mushroom" , JUMPNRUN_ENEMY_TYPE_MUSHROOM
)
53 ("bunny" , JUMPNRUN_ENEMY_TYPE_BUNNY
)
54 ("kaninchen" , JUMPNRUN_ENEMY_TYPE_BUNNY
) // legacy
55 ("snake" , JUMPNRUN_ENEMY_TYPE_SNAKE
)
56 ("spiral" , JUMPNRUN_ENEMY_TYPE_SPIRAL
)
57 ("rotor" , JUMPNRUN_ENEMY_TYPE_ROTOR
)
58 ("dog" , JUMPNRUN_ENEMY_TYPE_DOG
)
59 ("giraffe" , JUMPNRUN_ENEMY_TYPE_GIRAFFE
)
60 ("bird" , JUMPNRUN_ENEMY_TYPE_BIRD
)
61 ("bird_straight", JUMPNRUN_ENEMY_TYPE_BIRD_STRAIGHT
)
62 ("bird_dip" , JUMPNRUN_ENEMY_TYPE_BIRD_DIP
)
66 boost::spirit::qi::symbols
<char, unsigned> tiles
;
67 boost::spirit::qi::symbols
<char, unsigned> items
;
68 boost::spirit::qi::symbols
<char, unsigned> enemies
;
71 struct level_name_map
{
73 std::ifstream
in("levels.txt");
76 throw std::logic_error("levels.txt konnte nicht geƶffnet werden.");
80 while(std::getline(in
, name
)) {
81 if(boost::trim_copy(name
) != "") {
82 names
.push_back(name
);
87 std::vector
<std::string
> names
;
92 level(std::string
const &name
)
94 level_lines(LEVEL_LINE_COUNT
)
96 std::ifstream
in((PATH_PREFIX
+ name
+ ".lv").c_str());
99 throw std::invalid_argument("Could not open file: " + name
+ ".lv");
102 for(std::size_t i
= 0; i
< level_lines
.size(); ++i
) {
103 std::getline(in
, level_lines
[i
]);
107 std::string type_prefix
;
108 std::map
<char, std::string
> *objmap
= 0;
110 while(std::getline(in
, line
)) {
112 if(line
== "[tiles]") {
113 objmap
= &tile_types
;
114 } else if(line
== "[items]") {
115 objmap
= &item_types
;
116 } else if(line
== "[enemies]") {
117 objmap
= &enemy_types
;
118 } else if(line
== "[parameters]") {
119 objmap
= &level_params
;
121 throw std::invalid_argument("Unkown type: " + line
);
123 } else if(boost::trim_right_copy(line
) != "") {
126 std::istringstream
parser(line
);
128 if(parser
>> c
>> tok
) {
133 throw std::invalid_argument("Line not parseable: " + line
);
139 std::size_t length() const {
140 std::size_t level_length
= 0;
142 for(std::size_t i
= 0; i
< level_lines
.size(); ++i
) {
143 level_length
= std::max(level_length
, level_lines
[i
].size());
149 unsigned find_type(boost::spirit::qi::symbols
<char, unsigned> const &types
, std::string
const &type
, std::string
const &error
) const {
150 unsigned const *p
= types
.find(type
);
151 if(!p
) throw std::invalid_argument(error
+ type
);
155 std::size_t count_things(std::map
<char, std::string
> const &objmap
) const {
156 std::size_t len
= length();
159 for(std::size_t x
= 0; x
< len
; ++x
) {
160 for(std::size_t y
= 0; y
< level_lines
.size(); ++y
) {
161 if(x
< level_lines
[y
].size()) {
162 auto iter
= objmap
.find(level_lines
[y
][x
]);
164 if(iter
!= objmap
.end()) {
174 std::size_t count_tiles () const { return count_things(tile_types
); }
175 std::size_t count_items () const { return count_things(item_types
); }
176 std::size_t count_enemies() const { return count_things(enemy_types
); }
178 void dump_things(std::ostream
&dest
, std::map
<char, std::string
> const &objmap
, boost::spirit::qi::symbols
<char, unsigned> const &types
, std::string
const &error
) const {
179 std::size_t len
= length();
181 for(std::size_t x
= 0; x
< len
; ++x
) {
182 for(std::size_t y
= 0; y
< level_lines
.size(); ++y
) {
183 if(level_lines
[y
].size() < x
) continue;
185 auto iter
= objmap
.find(level_lines
[y
][x
]);
187 if(iter
!= objmap
.end()) {
188 unsigned char buf
[3];
189 buf
[0] = static_cast<uint8_t>(y
) << 4 | static_cast<uint8_t>(x
>> 8);
190 buf
[1] = static_cast<uint8_t>(x
);
191 buf
[2] = static_cast<uint8_t>(find_type(types
, iter
->second
, error
));
193 dest
.write(static_cast<char const*>(static_cast<void*>(&buf
[0])), sizeof(buf
));
199 void dump_tiles (std::ostream
&dest
) const { dump_things(dest
, tile_types
, desc
.tiles
, "Unbekannter Tile-Typ: "); }
200 void dump_items (std::ostream
&dest
) const { dump_things(dest
, item_types
, desc
.items
, "Unbekannter Item-Typ: "); }
201 void dump_enemies(std::ostream
&dest
) const { dump_things(dest
, enemy_types
, desc
.enemies
, "Unbekannter Enemy-Typ: "); }
203 std::pair
<std::size_t, std::size_t> starting_position() const {
204 std::pair
<std::size_t, std::size_t> player_pos(0, 0);
206 for(std::size_t y
= 0; y
< level_lines
.size(); ++y
) {
207 std::size_t x
= level_lines
[y
].find('P');
209 if(x
!= std::string::npos
) {
210 player_pos
.first
= x
;
211 player_pos
.second
= y
;
219 void generate_header(jumpnrun_level
*dest
) const {
220 dest
->header
.tile_count
= count_tiles ();
221 dest
->header
.item_count
= count_items ();
222 dest
->header
.enemy_count
= count_enemies();
225 void dump(std::ostream
&dest
) const {
226 jumpnrun_level dummy
;
228 generate_header(&dummy
);
230 static_cast<uint16_t>(dummy
.header
. tile_count
),
231 static_cast<uint16_t>(dummy
.header
. item_count
),
232 static_cast<uint16_t>(dummy
.header
.enemy_count
)
235 std::pair
<std::size_t, std::size_t> player_pos
= starting_position();
238 static_cast<uint16_t>(player_pos
.first
),
239 static_cast<uint16_t>(player_pos
.second
)
244 std::map
<char, std::string
>::const_iterator iter
= level_params
.find('L');
245 if(iter
!= level_params
.end()) {
247 std::istringstream
parser(iter
->second
);
249 lives
= static_cast<uint8_t>(x
);
254 dest
.write(static_cast<char const *>(static_cast<void const *>(head
)), sizeof(head
));
255 dest
.write(static_cast<char const *>(static_cast<void const *>(spos
)), sizeof(spos
));
256 dest
.write(static_cast<char const *>(static_cast<void const *>(&lives
)), sizeof(lives
));
265 std::vector
<std::string
> level_lines
;
266 std::map
<char, std::string
> tile_types
;
267 std::map
<char, std::string
> item_types
;
268 std::map
<char, std::string
> enemy_types
;
269 std::map
<char, std::string
> level_params
;
273 void jumpnrun_level_dump(size_t level
) {
274 std::string name
= jnrcpp::level_names
.names
[level
];
275 jnrcpp::level
lv(name
);
276 std::ofstream
out((PATH_PREFIX
+ name
+ ".lvl").c_str());
281 void jumpnrun_levels_dump(void) {
282 for(size_t i
= 0; i
< jnrcpp::level_names
.names
.size(); ++i
) {
283 jumpnrun_level_dump(i
);
288 jumpnrun_levels_dump();