ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/style.C
Revision: 1.26
Committed: Sun Jul 1 05:00:19 2007 UTC (17 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2, rel-2_3
Changes since 1.25: +10 -11 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 #include <global.h>
25 #include <random_map.h>
26 #include <dirent.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include "../include/autoconf.h"
30
31 // NAME_MAX may not be defined on POSIX systems
32 #ifndef NAME_MAX
33 # define NAME_MAX 255
34 #endif
35
36 static int
37 pointer_strcmp (const void *p1, const void *p2)
38 {
39 const char *s1 = *(const char **) p1;
40 const char *s2 = *(const char **) p2;
41
42 return (strcmp (s1, s2));
43 }
44
45 /* This is our own version of scandir/select_regular_files/sort.
46 * To support having subdirectories in styles, we need to know
47 * if in fact the directory we read is a subdirectory. However,
48 * we can't get that through the normal dirent entry. So
49 * instead, we do our own where we do have the full directory
50 * path so can do stat calls to see if in fact it is a directory.
51 * dir is the name of the director to scan.
52 * namelist is the array of file names returned. IT needs to be
53 * freed by the caller.
54 * skip_dirs controls our behavioru - if nonzero, we don't
55 * skip any subdirectories - if zero, we store those away,
56 * since there are cases where we want to choose a random
57 * directory.
58 */
59 int
60 load_dir (const char *dir, char ***namelist, int skip_dirs)
61 {
62 DIR *dp;
63 struct dirent *d;
64 int entries = 0, entry_size = 0;
65 char name[NAME_MAX + 1], **rn = NULL;
66 struct stat sb;
67
68 dp = opendir (dir);
69 if (!dp)
70 return -1;
71
72 while ((d = readdir (dp)))
73 {
74 sprintf (name, "%s/%s", dir, d->d_name);
75 if (skip_dirs)
76 {
77 stat (name, &sb);
78 if (S_ISDIR (sb.st_mode))
79 continue;
80 }
81
82 if (entries == entry_size)
83 {
84 entry_size += 10;
85 rn = (char **) realloc (rn, sizeof (char *) * entry_size);
86 }
87 rn[entries] = strdup (d->d_name);
88 entries++;
89
90 }
91 (void) closedir (dp);
92
93 qsort (rn, entries, sizeof (char *), pointer_strcmp);
94
95 *namelist = rn;
96 return entries;
97 }
98
99 maptile *
100 find_style (const char *dirname, const char *stylename, int difficulty)
101 {
102 char style_file_path[1024];
103 char style_file_full_path[1024];
104 maptile *style_map = NULL;
105 struct stat file_stat;
106 int i, only_subdirs = 0;
107
108 /* if stylename exists, set style_file_path to that file. */
109 if (stylename && strlen (stylename) > 0)
110 sprintf (style_file_path, "%s/%s", dirname, stylename);
111 else /* otherwise, just use the dirname. We'll pick a random stylefile. */
112 sprintf (style_file_path, "%s", dirname);
113
114 /* is what we were given a directory, or a file? */
115 sprintf (style_file_full_path, "%s/maps%s.map", settings.datadir, style_file_path);
116
117 if (stat (style_file_full_path, &file_stat) == 0 && !S_ISDIR (file_stat.st_mode))
118 style_map = maptile::find_sync (style_file_path);
119
120 if (!style_map) /* maybe we were given a directory! */
121 {
122 char **namelist;
123 int n;
124 char style_dir_full_path[256];
125
126 /* get the names of all the files in that directory */
127 sprintf (style_dir_full_path, "%s/maps%s", settings.datadir, style_file_path);
128
129 /* First, skip subdirectories. If we don't find anything, then try again
130 * without skipping subdirs.
131 */
132 n = load_dir (style_dir_full_path, &namelist, 1);
133
134 if (n <= 0)
135 {
136 n = load_dir (style_dir_full_path, &namelist, 0);
137 only_subdirs = 1;
138 }
139
140 if (n <= 0)
141 return 0; /* nothing to load. Bye. */
142
143 /* Picks a random map. Note that if this is all directories,
144 * we know it won't be able to load, so save a few ticks.
145 * the door handling checks for this failure and handles
146 * it properly.
147 */
148 if (difficulty == -1)
149 { /* pick a random style from this dir. */
150 if (only_subdirs)
151 style_map = 0;
152 else
153 {
154 strcat (style_file_path, "/");
155 strcat (style_file_path, namelist[rndm (n)]);
156 style_map = maptile::find_sync (style_file_path);
157 }
158 }
159 else
160 { /* find the map closest in difficulty */
161 int min_dist = 32000, min_index = -1;
162
163 for (i = 0; i < n; i++)
164 {
165 int dist;
166 char *mfile_name = strrchr (namelist[i], '_') + 1;
167
168 if ((mfile_name - 1) == NULL)
169 { /* since there isn't a sequence, */
170 int q;
171
172 /*pick one at random to recurse */
173 style_map = find_style (style_file_path, namelist[rndm (n)], difficulty);
174 for (q = 0; q < n; q++)
175 free (namelist[q]);
176 free (namelist);
177 return style_map;
178 }
179 else
180 {
181 dist = abs (difficulty - atoi (mfile_name));
182 if (dist < min_dist)
183 {
184 min_dist = dist;
185 min_index = i;
186 }
187 }
188 }
189
190 /* presumably now we've found the "best" match for the
191 difficulty. */
192 strcat (style_file_path, "/");
193 strcat (style_file_path, namelist[min_index]);
194 style_map = maptile::find_sync (style_file_path);
195 }
196
197 for (i = 0; i < n; i++)
198 free (namelist[i]);
199
200 free (namelist);
201 }
202
203 if (style_map)
204 {
205 style_map->load_sync ();
206 style_map->deactivate ();
207 }
208
209 return style_map;
210 }