2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
19 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include <glib/gi18n.h>
30 #include "cave/caveset.hpp"
31 #include "misc/logger.hpp"
32 #include "misc/autogfreeptr.hpp"
33 #include "cave/caverendered.hpp"
34 #include "fileops/bdcffsave.hpp"
36 /* list of possible extensions which can be opened */
37 const char *gd_caveset_extensions
[] = {"*.gds", "*.bd", "*.bdr", "*.brc", "*.vsf", "*.mem", NULL
};
40 PropertyDescription
const CaveSet::descriptor
[] = {
42 {"", GD_TAB
, 0, N_("Caveset data")},
43 {"Name", GD_TYPE_STRING
, 0, N_("Name"), GetterBase::create_new(&CaveSet::name
), N_("Name of the game")},
44 {"Description", GD_TYPE_STRING
, 0, N_("Description"), GetterBase::create_new(&CaveSet::description
), N_("Some words about the game")},
45 {"Author", GD_TYPE_STRING
, 0, N_("Author"), GetterBase::create_new(&CaveSet::author
), N_("Name of author")},
46 {"Date", GD_TYPE_STRING
, 0, N_("Date"), GetterBase::create_new(&CaveSet::date
), N_("Date of creation")},
47 {"WWW", GD_TYPE_STRING
, 0, N_("WWW"), GetterBase::create_new(&CaveSet::www
), N_("Web page or e-mail address")},
48 {"Difficulty", GD_TYPE_STRING
, 0, N_("Difficulty"), GetterBase::create_new(&CaveSet::difficulty
), N_("Difficulty (informative)")},
50 {"Charset", GD_TYPE_STRING
, 0, N_("Character set"), GetterBase::create_new(&CaveSet::charset
), N_("Theme used for displaying the game.")},
51 {"Fontset", GD_TYPE_STRING
, 0, N_("Font set"), GetterBase::create_new(&CaveSet::fontset
), N_("Font used during the game.")},
53 {"Lives", GD_TYPE_INT
, 0, N_("Initial lives"), GetterBase::create_new(&CaveSet::initial_lives
), N_("Number of lives you get at game start."), 3, 99},
54 {"Lives", GD_TYPE_INT
, 0, N_("Maximum lives"), GetterBase::create_new(&CaveSet::maximum_lives
), N_("Maximum number of lives you can have by collecting bonus points."), 3, 99},
55 {"BonusLife", GD_TYPE_INT
, 0, N_("Bonus life score"), GetterBase::create_new(&CaveSet::bonus_life_score
), N_("Number of points to collect for a bonus life."), 100, 5000},
57 {"", GD_TAB
, 0, N_("Story")},
58 {"Story", GD_TYPE_LONGSTRING
, 0, NULL
, GetterBase::create_new(&CaveSet::story
), N_("Long description of the game.")},
59 {"", GD_TAB
, 0, N_("Remark")},
60 {"Remark", GD_TYPE_LONGSTRING
, 0, NULL
, GetterBase::create_new(&CaveSet::remark
), N_("Remark (informative).")},
62 {"TitleScreen", GD_TYPE_LONGSTRING
, GD_DONT_SHOW_IN_EDITOR
, N_("Title screen"), GetterBase::create_new(&CaveSet::title_screen
), N_("Title screen image")},
63 {"TitleScreenScroll", GD_TYPE_LONGSTRING
, GD_DONT_SHOW_IN_EDITOR
, N_("Title screen, scrolling"), GetterBase::create_new(&CaveSet::title_screen_scroll
), N_("Scrolling background for title screen image")},
70 /* some bdcff defaults */
73 bonus_life_score
= 500;
77 /* calculates an adler checksum, for which it uses all
78 elements of all cave-rendereds. */
79 unsigned CaveSet::checksum() const {
80 unsigned a
= 1, b
= 0;
81 for (unsigned int i
= 0; i
< caves
.size(); ++i
) {
82 CaveRendered
rendered(*caves
.at(i
), 0, 0); /* level=1, seed=0 */
83 gd_cave_adler_checksum_more(rendered
, a
, b
);
90 /********************************************************************************
92 * Misc caveset functions
96 /* return index of first selectable cave */
97 int CaveSet::first_selectable_cave_index() const {
98 for (unsigned int i
= 0; i
< caves
.size(); ++i
) {
99 if (caves
.at(i
)->selectable
)
103 gd_warning("no selectable cave in caveset!");
104 /* and return the first one. */
109 void CaveSet::set_name_from_filename(const char *filename
) {
110 /* make up a caveset name from the filename. */
111 AutoGFreePtr
<char> name_str(g_path_get_basename(filename
));
112 /* convert underscores to spaces, remove extension */
114 while ((c
= strchr(name_str
, '_')) != NULL
)
116 if ((c
= strrchr(name_str
, '.')) != NULL
)
122 /// Save caveset in BDCFF to the file.
123 /// @param filename The name of the file to write to.
124 /// @return true, if successful; false, if error.
125 void CaveSet::save_to_file(const char *filename
) {
126 std::ofstream outfile
;
127 outfile
.open(filename
);
129 throw std::runtime_error(_("Could not open file for writing."));
130 std::list
<std::string
> saved
;
131 save_to_bdcff(*this, saved
);
132 for (std::list
<std::string
>::const_iterator it
= saved
.begin(); it
!= saved
.end(); ++it
)
133 outfile
<< *it
<< std::endl
;
136 throw std::runtime_error(_("Error writing to file."));
137 /* remember savename and that now it is not edited */
138 this->filename
= filename
;
139 this->edited
= false;
143 /// Check if there are any replays in the caveset.
144 /// @return True, if at least one of the caves has a replay.
145 bool CaveSet::has_replays() const {
147 for (unsigned int i
= 0; i
< caves
.size(); ++i
) {
148 if (!caves
.at(i
)->replays
.empty())
152 /* no replays at all */
157 /// Check if there are any caves which have different difficulty levels.
158 /// @return True, if at least one of the caves has different difficulty levels set.
159 bool CaveSet::has_levels() const {
161 for (unsigned int i
= 0; i
< caves
.size(); ++i
) {
162 if (caves
.at(i
)->has_levels())
165 /* no levels at all */
170 /// Return the index of a cave.
172 /// @param cave The cave to look for
173 /// @return The index in the container, or -1 if not found
174 int CaveSet::cave_index(CaveStored
const *cave
) const {
175 for (unsigned int i
= 0; i
< caves
.size(); ++i
)
176 if (caves
.at(i
) == cave
)
179 return -1; /* if not found */