ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/quadland.C
Revision: 1.5
Committed: Mon May 2 16:55:38 2011 UTC (13 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.4: +52 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 *
6 * Deliantra is free software: you can redistribute it and/or modify it under
7 * the terms of the Affero GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the Affero GNU General Public License
17 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * The authors can be reached via e-mail to <support@deliantra.net>
21 */
22
23 #include <global.h>
24
25 #include "noise.h"
26
27 /////////////////////////////////////////////////////////////////////////////
28
29 void
30 move_into_wall (object *ob, object *wall)
31 {
32 bool visible = !wall->invisible && !ob->flag [FLAG_BLIND];
33
34 if (wall->flag [FLAG_IS_QUAD] && visible)
35 {
36 maptile *m = wall->map;
37 printf ("hi\n");//D
38
39 if (m->tile_path [TILE_UP])
40 if (maptile *up = m->tile_available (TILE_UP))
41 {
42 if (ob->blocked (up, ob->x, ob->y))
43 ob->failmsg (format ("Ouch, you hit your head while climbing the %s! H<Didn't you see the ceiling?>", query_name (wall)));
44 //TODO: reduce health
45 else if (ob->blocked (up, wall->x, wall->y))
46 ob->failmsg (format ("You try to climb up, but the %s is too high for you!", query_name (wall)));
47 //TODO: reduce health
48 else
49 {
50 ob->statusmsg (format ("You successfully climb up the %s.", query_name (wall)));
51 // here we assume that ob is a player...
52 ob->enter_map (up, wall->x, wall->y);
53 }
54 }
55 else
56 ob->failmsg (format ("You try to climb the %s, but you fall down! H<Try again.>", query_name (wall)));
57 else
58 ob->failmsg (format ("You fail to climb up the %s! H<You cannot climb up here.>", query_name (wall)));
59
60
61 return;
62 }
63
64 if (ob->contr->ns->bumpmsg)
65 {
66 ob->play_sound (sound_find ("bump_wall"));
67
68 ob->statusmsg (visible
69 ? format ("You bump into the %s.", query_name (wall))
70 : "You bump into something."
71 );
72 }
73 }
74
75 /////////////////////////////////////////////////////////////////////////////
76
77 #define FANCY_GRAPHICS 0
78
79 static void
80 gen_quadspace (maptile *m, int mx, int my, int x, int y, int z)
81 {
82 vec2d P = vec2d (x, y);
83
84 const int deep_sea_z = -200;
85
86 static frac2d gen(13);
87
88 static frac2d vec_gen1 (6, 2, 0.5, 1);
89 static frac2d vec_gen2 (6, 2, 0.5, 2);
90
91 const float continent_scale = 0.00008;
92
93 vec2d perturb_pos = pow (P, 1.4) * 1e-5;
94
95 vec2d perturb (
96 vec_gen1.fBm (perturb_pos),
97 vec_gen2.fBm (perturb_pos)
98 );
99
100 float perturb_perturb = 1 - (P[1] - P[0]) * (1. / 25000 / 2);
101 perturb_perturb = perturb_perturb * perturb_perturb * 0.4;
102 perturb *= perturb_perturb;
103
104 vec2d P_continent = P * continent_scale + perturb;
105
106 static frac2d continent_gen (13, 2.13, 0.5);
107 float continent = continent_gen.fBm (P_continent) + 0.05f;
108
109 float x_gradient = P[0] * (1. / 25000);
110 float y_gradient = P[1] * (1. / 25000);
111 float xy_gradient = (P[0] + P[1]) * (0.5 / 25000);
112
113 const float N = (25000 - 1) * continent_scale;
114
115 // we clip a large border on the perturbed shape, to get irregular coastline
116 // and then clip a smaller border around the real shape
117 continent = border_blend (-1.f, continent, P_continent , N, 400 * continent_scale);
118 continent = border_blend (-1.f, continent, P * continent_scale + perturb * 0.1, N, 100 * continent_scale);
119
120 enum {
121 T_NONE,
122 T_OCEAN,
123 T_RIVER,
124 T_VALLEY,
125 T_MOUNTAIN,
126 T_UNDERGROUND,
127 T_ACQUIFER,
128 } t = T_NONE;
129
130 vec3d c;
131 int h0 = 0; // "water level"
132 int h = 1000000; // height form heightmap
133
134 // the continent increases in height from 0 to ~700 levels in the absence of anything else
135 // thats about one step every 7 maps.
136 int base_height = blend (0, 300, xy_gradient, 0.2f, 0.9f);
137 int river_height = base_height * 9 / 10;
138
139 // add this to rivers to "dry them out"
140 float dry_out = max (0.f, lerp (xy_gradient, 0.7f, 1.f, 0.f, 0.3f));
141
142 static frac2d river_gen (2);
143 float river1 = abs (river_gen.fBm (P * 0.001 + perturb * 4)) + dry_out;
144 float river2 = river_gen.ridgedmultifractal (P * 0.04, 0.8, 10) - y_gradient * 0.2 - 0.16 - dry_out;
145
146 float valley = river1 - 0.2f;
147
148 static frac2d mountain_gen (8, 2.14, 0.5);
149 float mountain = mountain_gen.ridgedmultifractal (P * 0.004);
150
151 //TODO: mountains should not lower the height, should they?
152 t = valley < 0 ? T_VALLEY : T_MOUNTAIN;
153 c = blend0 (vec3d (0, 0.8, 0), vec3d (0.8, 0, 0), valley, 0.1f);
154 h = blend0 (base_height + continent * 300, base_height + mountain * xy_gradient * 400, valley, 0.1f);
155
156 if (river1 < 0.01f)
157 {
158 // main rivers - they cut deeply into the mountains (base_height * 0.9f)
159 t = T_RIVER;
160 c = vec3d (0.2, 0.2, 1);
161 h0 = river_height;
162 min_it (h, river_height + lerp<float> (river1, 0.f, 0.01f, -20, -1));
163 }
164
165 if (river2 > 0)
166 {
167 t = T_RIVER;
168 c = vec3d (0.2, 0.2, 1);
169 h0 = river_height;
170 min_it (h, river_height + lerp<float> (river1, 0.f, 0.01f, -5, -1));
171 }
172
173 if (continent < 0)
174 {
175 t = T_OCEAN;
176 min_it (h, min (continent * 200, -1));
177 c = vec3d (0, 0, 1);
178 }
179
180 // now we have the base height, and base terrain
181
182 #if FANCY_GRAPHICS
183 z = h; // show the surface, not the given z layer
184 #endif
185
186 max_it (h0, h);
187
188 // everything below the surface is underground, or a variant
189 if (z < h)
190 {
191 t = T_UNDERGROUND;
192 }
193
194 // put acquifers a bit below the surface, to reduce them leaking out (will still happen)
195 if (z < h - 3)
196 {
197 static frac3d acquifer_gen (4);
198 float acquifer = acquifer_gen.ridgedmultifractal (vec3d (x * 0.001, y * 0.001, z * 0.01), 1.003, 2);
199
200 if (acquifer > 0.48)
201 {
202 t = T_ACQUIFER;
203 c = vec3d (1,1,1);
204 }
205 }
206
207 // TODO: caves
208 // TODO: chees areas
209 // TODO: minerals
210 // TODO: monsters
211
212 #if FANCY_GRAPHICS
213 float v = clamp (lerp<float> (h, deep_sea_z, 800, 0.f, 1.f), 0.f, 1.f);
214 c *= v;
215
216 putc (clamp<int> (255 * c[0], 0, 255), stdout);
217 putc (clamp<int> (255 * c[1], 0, 255), stdout);
218 putc (clamp<int> (255 * c[2], 0, 255), stdout);
219 #else
220 shstr arch_floor = shstr ("quad_open_space");
221 shstr arch_wall;
222
223 switch (t)
224 {
225 case T_OCEAN:
226 if (z < h0)
227 arch_wall = shstr ("quad_water_wall");
228 else
229 arch_floor = shstr ("quad_ocean_floor");
230 break;
231
232 case T_RIVER:
233 if (z < h0)
234 arch_wall = shstr ("quad_water_wall");
235 else
236 arch_floor = shstr ("quad_water_floor");
237 break;
238
239 case T_VALLEY:
240 if (z == h)
241 arch_floor = shstr ("quad_dirt_floor");
242 break;
243
244 case T_MOUNTAIN:
245 if (z == h)
246 arch_floor = shstr ("quad_stone_floor");
247 break;
248
249 case T_UNDERGROUND:
250 // todo, use a fractal
251 if (z < h - 10)
252 {
253 arch_floor = shstr ("quad_dirt_floor");
254 arch_wall = shstr ("quad_dirt_wall");
255 }
256 else
257 {
258 arch_floor = shstr ("quad_stone_floor");
259 arch_wall = shstr ("quad_stone_wall");
260 }
261 break;
262
263 case T_ACQUIFER:
264 arch_wall = shstr ("quad_water_wall");
265 break;
266
267 default:
268 abort ();
269 }
270
271 if (arch_floor)
272 m->insert (archetype::get (arch_floor), mx, my);
273
274 if (arch_wall)
275 m->insert (archetype::get (arch_wall ), mx, my);
276 #endif
277 }
278
279 void
280 gen_quadmap (maptile *m, int x, int y, int z)
281 {
282 assert (m->width == 50);
283 assert (m->height == 50);
284
285 for (int mx = 0; mx < 50; ++mx)
286 for (int my = 0; my < 50; ++my)
287 gen_quadspace (m, mx, my, x + mx, y + my, z);
288 }
289
290 /////////////////////////////////////////////////////////////////////////////
291
292 void noise_test ();
293 void noise_test ()
294 {
295 #if 1
296 int Nw = 700;
297
298 printf ("P6 %d %d 255\n", Nw * 3, Nw * 2);
299 // pmake&&server/deliantra-server >x&&convert -depth 8 -size 512xx512 gray:x x.ppm&& cv x.ppm
300 for (int y = 0; y < Nw; ++y)
301 {
302 if (!(y&63))fprintf (stderr, "y %d\n", y * 50 / Nw);//D
303
304 for (int x = 0; x < Nw; ++x) gen_quadspace (0, 0, 0, x * 25000 / Nw, y * 25000 / Nw, 0);
305
306 for (int x = 0; x < Nw; ++x) gen_quadspace (0, 0, 0, x + 400, y, 0);
307 for (int x = 0; x < Nw; ++x) gen_quadspace (0, 0, 0, x + 22000, y + 2000, 0);
308 }
309 for (int y = 0; y < Nw; ++y)
310 {
311 if (!(y&63))fprintf (stderr, "y %d\n", y * 50 / Nw+50);//D
312
313 for (int x = 0; x < Nw; ++x) gen_quadspace (0, 0, 0, x + 1000, y + 22000, 0);
314 for (int x = 0; x < Nw; ++x) gen_quadspace (0, 0, 0, x + 12500, y + 12500, 0);
315 for (int x = 0; x < Nw; ++x) gen_quadspace (0, 0, 0, x + 22000, y + 22500, 0);
316 }
317
318 //putc (127 * gen.noise (vec2d (x * 0.01, y * 0.01)) + 128, stdout);
319 //putc (256 * gen.terrain2 (x * 0.004, y * 0.004, 8), stdout);
320 //putc (256 * gen.fBm (vec2d(x * 0.01, y * 0.01), 16), stdout);
321 //putc (256 * gen.turbulence (vec2d (x * 0.004 - 1, y * 0.004 - 1), 10), stdout);
322 //putc (256 * gen.heterofractal (vec2d (x * 0.008, y * 0.008), 8, 0.9), stdout);
323 //putc (256 * gen.hybridfractal (vec2d (x * 0.01, y * 0.01), 8, -.4, -4), stdout);
324 //putc (256 * gen.fBm (vec2d (x * 0.002, y * 0.002), 2), stdout);
325 //putc (127.49 * gen.billowfractal (vec2d (x * 0.01, y * 0.01), 9) + 128, stdout);
326 #elif 1
327 int N = 25000;
328
329 printf ("P6 %d %d 255\n", N, N);
330 for (int y = 0; y < N; ++y)
331 {
332 if (!(y&63))fprintf (stderr, "y %d\n", y);//D
333
334 for (int x = 0; x < N; ++x) gen_quadspace (0, 0, 0, x, y, 0);
335 }
336 #else
337 int N = 200;
338
339 //printf ("P6 %d %d 255\n", N, N);
340 // pmake&&server/deliantra-server >x&&convert -depth 8 -size 512xx512 gray:x x.ppm&& cv x.ppm
341 for (int z = 0; z < N; ++z)
342 {
343 if (!(z&7))fprintf (stderr, "z %d\n", z);//D
344 for (int y = 0; y < N; ++y)
345 for (int x = 0; x < N; ++x)
346 {
347 #if 0
348 float v = gen3.ridgedmultifractal (vec3d (x * 0.001 + 0.2, y * 0.001 + 0.2, z * 0.01 + 0.2), 1.03, 2) * 2;
349
350 if (z < 64)
351 v = v * (z * z) / (64 * 64);
352
353 if (v <= 0.9)
354 continue;
355 #endif
356 static frac3d gen3 (10);
357 //float v = gen3.turbulence (vec3d (x * 0.01, y * 0.01, z * 0.01));
358 float v = gen3.ridgedmultifractal (vec3d (x * 0.001, y * 0.001, z * 0.001), 1.003, 2);
359
360 if (v <= 0.48) continue;
361
362 float r[4];
363 int i[4];
364
365 r[0] = x;
366 r[1] = y;
367 r[2] = z;
368 r[3] = v;
369
370 memcpy (i, r, 16);
371
372 i[0] = htonl (i[0]);
373 i[1] = htonl (i[1]);
374 i[2] = htonl (i[2]);
375 i[3] = htonl (i[3]);
376
377 fwrite (i, 4*4, 1, stdout);
378 }
379 }
380 #endif
381
382 exit (0);
383 }