20130313
[gdash.git] / src / cave / object / caveobjectrandomfill.cpp
blob49fb640d08d32ef900d29fccb7a33a281434881b
1 /*
2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "config.h"
19 #include "cave/object/caveobjectrandomfill.hpp"
20 #include "cave/elementproperties.hpp"
22 #include <glib/gi18n.h>
24 #include "fileops/bdcffhelper.hpp"
25 #include "cave/caverendered.hpp"
26 #include "misc/printf.hpp"
27 #include "misc/util.hpp"
29 std::string CaveRandomFill::get_bdcff() const
31 const char *type=c64_random?"RandomFillC64":"RandomFill";
32 BdcffFormat f(type);
34 f << p1 << p2;
35 f << seed[0] << seed[1] << seed[2] << seed[3] << seed[4];
36 f << initial_fill;
37 if (random_fill_probability_1!=0)
38 f << random_fill_1 << random_fill_probability_1;
39 if (random_fill_probability_2!=0)
40 f << random_fill_2 << random_fill_probability_2;
41 if (random_fill_probability_3!=0)
42 f << random_fill_3 << random_fill_probability_3;
43 if (random_fill_probability_4!=0)
44 f << random_fill_4 << random_fill_probability_4;
45 if (replace_only!=O_NONE)
46 f << replace_only;
48 return f;
51 CaveRandomFill* CaveRandomFill::clone_from_bdcff(const std::string &name, std::istream &is) const
53 Coordinate p1, p2;
54 int seed[5];
55 GdElementEnum initial_fill, replace_only;
56 GdElementEnum random_fill[4]={O_DIRT, O_DIRT, O_DIRT, O_DIRT};
57 int random_prob[4]={0,0,0,0};
58 int j;
59 std::string s1, s2;
61 if (!(is >> p1 >> p2 >> seed[0] >> seed[1] >> seed[2] >> seed[3] >> seed[4] >> initial_fill))
62 return NULL;
63 j=0;
64 /* now come fill element&probability pairs. read as we find two words */
65 while (j<4 && (is >> s1 >> s2)) {
66 std::istringstream is1(s1), is2(s2);
67 // read two strings - they must be fill & prob
68 if (!(is1>>random_fill[j]))
69 return NULL;
70 if (!(is2>>random_prob[j]))
71 return NULL;
72 s1="";
73 s2="";
74 j++;
76 if (s1!="") {
77 std::istringstream is(s1);
78 // one string left - must be a replace only element
79 if (!(is>>replace_only))
80 return NULL;
82 else
83 replace_only=O_NONE;
85 CaveRandomFill *r=new CaveRandomFill(p1, p2);
86 r->set_replace_only(replace_only);
87 r->set_seed(seed[0], seed[1], seed[2], seed[3], seed[4]);
88 r->set_random_fill(initial_fill, random_fill[0], random_fill[1], random_fill[2], random_fill[3]);
89 r->set_random_prob(random_prob[0], random_prob[1], random_prob[2], random_prob[3]);
90 r->set_c64_random(gd_str_ascii_caseequal(name, "RandomFillC64"));
91 return r;
95 CaveRandomFill::CaveRandomFill(Coordinate _p1, Coordinate _p2)
96 : CaveRectangular(GD_RANDOM_FILL, _p1, _p2),
97 replace_only(O_NONE),
98 c64_random(false)
100 initial_fill=O_SPACE;
101 random_fill_1=O_DIRT;
102 random_fill_probability_1=0;
103 random_fill_2=O_DIRT;
104 random_fill_probability_2=0;
105 random_fill_3=O_DIRT;
106 random_fill_probability_3=0;
107 random_fill_4=O_DIRT;
108 random_fill_probability_4=0;
109 for (int j=0; j<5; j++)
110 seed[j]=-1;
113 void CaveRandomFill::set_random_fill(GdElementEnum initial, GdElementEnum e1, GdElementEnum e2, GdElementEnum e3, GdElementEnum e4)
115 initial_fill=initial;
116 random_fill_1=e1;
117 random_fill_2=e2;
118 random_fill_3=e3;
119 random_fill_4=e4;
122 void CaveRandomFill::set_random_prob(int i1, int i2, int i3, int i4)
124 random_fill_probability_1=i1;
125 random_fill_probability_2=i2;
126 random_fill_probability_3=i3;
127 random_fill_probability_4=i4;
130 void CaveRandomFill::set_seed(int s1, int s2, int s3, int s4, int s5)
132 seed[0]=s1;
133 seed[1]=s2;
134 seed[2]=s3;
135 seed[3]=s4;
136 seed[4]=s5;
139 void CaveRandomFill::draw(CaveRendered &cave) const
141 /* -1 means that it should be different every time played. */
142 guint32 s;
143 if (seed[cave.rendered_on]==-1)
144 s=cave.random.rand_int();
145 else
146 s=seed[cave.rendered_on];
148 RandomGenerator rand;
149 rand.set_seed(s);
150 /* for c64 random, use the 2*8 lsb. */
151 C64RandomGenerator c64rand;
152 c64rand.set_seed(s);
154 /* change coordinates if not in correct order */
155 int x1=p1.x;
156 int y1=p1.y;
157 int x2=p2.x;
158 int y2=p2.y;
159 if (y1>y2)
160 std::swap(y1, y2);
161 if (x1>x2)
162 std::swap(x1, x2);
164 for (int y=y1; y<=y2; y++)
165 for (int x=x1; x<=x2; x++) {
166 int randm;
168 if (c64_random) /* use c64 random generator */
169 randm=c64rand.random();
170 else /* use the much better glib random generator */
171 randm=rand.rand_int_range(0, 256);
173 GdElementEnum element=initial_fill;
174 if (randm<random_fill_probability_1)
175 element=random_fill_1;
176 if (randm<random_fill_probability_2)
177 element=random_fill_2;
178 if (randm<random_fill_probability_3)
179 element=random_fill_3;
180 if (randm<random_fill_probability_4)
181 element=random_fill_4;
182 if (replace_only==O_NONE || cave.map(x, y)==replace_only)
183 cave.store_rc(x, y, element, this);
187 PropertyDescription const CaveRandomFill::descriptor[] = {
188 {"", GD_TAB, 0, N_("Random Fill")},
189 {"", GD_TYPE_BOOLEAN_LEVELS, 0, N_("Levels"), GetterBase::create_new(&CaveRandomFill::seen_on), N_("Levels on which this object is visible.")},
190 {"", GD_TYPE_COORDINATE, 0, N_("Start corner"), GetterBase::create_new(&CaveRandomFill::p1), N_("Specifies one of the corners of the object."), 0, 127},
191 {"", GD_TYPE_COORDINATE, 0, N_("End corner"), GetterBase::create_new(&CaveRandomFill::p2), N_("Specifies one of the corners of the object."), 0, 127},
192 {"", GD_TYPE_ELEMENT, 0, N_("Replace only"), GetterBase::create_new(&CaveRandomFill::replace_only), N_("If this setting is set to 'no element' but another one, only that will be replaced when drawing the fill, and other elements will not be overwritten. Otherwise the whole block is filled.")},
193 {"", GD_TAB, 0, N_("Generator")},
194 {"", GD_TYPE_BOOLEAN, 0, N_("C64 random"), GetterBase::create_new(&CaveRandomFill::c64_random), N_("Controls if the C64 random generator is used for the fill, or a more advanced one. By using the C64 generator, you can recreate the patterns of the original game.")},
195 {"", GD_TYPE_INT_LEVELS, 0, N_("Random seed"), GetterBase::create_new(&CaveRandomFill::seed), N_("Random seed value controls the predictable random number generator, which fills the cave initially. If set to -1, cave is totally random every time it is played."), -1, GD_CAVE_SEED_MAX},
196 {"", GD_TYPE_ELEMENT, 0, N_("Initial fill"), GetterBase::create_new(&CaveRandomFill::initial_fill), 0},
197 {"", GD_TYPE_INT, 0, N_("Probability 1"), GetterBase::create_new(&CaveRandomFill::random_fill_probability_1), 0, 0, 255},
198 {"", GD_TYPE_ELEMENT, 0, N_("Random fill 1"), GetterBase::create_new(&CaveRandomFill::random_fill_1), 0},
199 {"", GD_TYPE_INT, 0, N_("Probability 2"), GetterBase::create_new(&CaveRandomFill::random_fill_probability_2), 0, 0, 255},
200 {"", GD_TYPE_ELEMENT, 0, N_("Random fill 2"), GetterBase::create_new(&CaveRandomFill::random_fill_2), 0},
201 {"", GD_TYPE_INT, 0, N_("Probability 3"), GetterBase::create_new(&CaveRandomFill::random_fill_probability_3), 0, 0, 255},
202 {"", GD_TYPE_ELEMENT, 0, N_("Random fill 3"), GetterBase::create_new(&CaveRandomFill::random_fill_3), 0},
203 {"", GD_TYPE_INT, 0, N_("Probability 4"), GetterBase::create_new(&CaveRandomFill::random_fill_probability_4), 0, 0, 255},
204 {"", GD_TYPE_ELEMENT, 0, N_("Random fill 4"), GetterBase::create_new(&CaveRandomFill::random_fill_4), 0},
205 {NULL},
208 PropertyDescription const* CaveRandomFill::get_description_array() const
210 return descriptor;
213 std::string CaveRandomFill::get_description_markup() const
215 if (replace_only==O_NONE)
216 return SPrintf(_("Random fill from %d,%d to %d,%d"))
217 % p1.x % p1.y % p2.x % p2.y;
218 else
219 return SPrintf(_("Random fill from %d,%d to %d,%d, replacing %s"))
220 % p1.x % p1.y % p2.x % p2.y % gd_element_properties[replace_only].lowercase_name;