ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/style.C
(Generate patch)

Comparing deliantra/server/random_maps/style.C (file contents):
Revision 1.2 by root, Tue Aug 29 08:01:36 2006 UTC vs.
Revision 1.5 by root, Sat Sep 16 22:24:13 2006 UTC

1/*
2 * static char *rcsid_style_c =
3 * "$Id: style.C,v 1.2 2006/08/29 08:01:36 root Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
21 16
22 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 20
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 22*/
28 23
29 24
30#include <global.h> 25#include <global.h>
31#include <random_map.h> 26#include <random_map.h>
32#ifndef WIN32 /* ---win32 exclude headers */ 27#ifndef WIN32 /* ---win32 exclude headers */
33#include <dirent.h> 28# include <dirent.h>
34#include <sys/stat.h> 29# include <sys/stat.h>
35#include <unistd.h> 30# include <unistd.h>
36#include "../include/autoconf.h" 31# include "../include/autoconf.h"
37#endif /* win32 */ 32#endif /* win32 */
38 33
39 34
35static int
40static int pointer_strcmp(const void *p1, const void *p2) 36pointer_strcmp (const void *p1, const void *p2)
41{ 37{
42 const char *s1 = *(const char **)p1; 38 const char *s1 = *(const char **) p1;
43 const char *s2 = *(const char **)p2; 39 const char *s2 = *(const char **) p2;
44 40
45 return(strcmp(s1, s2)); 41 return (strcmp (s1, s2));
46} 42}
47 43
48/* This is our own version of scandir/select_regular_files/sort. 44/* This is our own version of scandir/select_regular_files/sort.
49 * To support having subdirectories in styles, we need to know 45 * To support having subdirectories in styles, we need to know
50 * if in fact the directory we read is a subdirectory. However, 46 * if in fact the directory we read is a subdirectory. However,
57 * skip_dirs controls our behavioru - if nonzero, we don't 53 * skip_dirs controls our behavioru - if nonzero, we don't
58 * skip any subdirectories - if zero, we store those away, 54 * skip any subdirectories - if zero, we store those away,
59 * since there are cases where we want to choose a random 55 * since there are cases where we want to choose a random
60 * directory. 56 * directory.
61 */ 57 */
58int
62int load_dir (const char *dir, char ***namelist, int skip_dirs) 59load_dir (const char *dir, char ***namelist, int skip_dirs)
63{ 60{
64 DIR *dp; 61 DIR *dp;
65 struct dirent *d; 62 struct dirent *d;
66 int entries=0, entry_size=0; 63 int entries = 0, entry_size = 0;
67 char name[NAME_MAX+1], **rn=NULL; 64 char name[NAME_MAX + 1], **rn = NULL;
68 struct stat sb; 65 struct stat sb;
69 66
70 dp = opendir (dir); 67 dp = opendir (dir);
71 if (dp == NULL) 68 if (dp == NULL)
72 return -1; 69 return -1;
73 70
74 while ((d = readdir (dp)) != NULL) { 71 while ((d = readdir (dp)) != NULL)
72 {
75 sprintf(name, "%s/%s", dir, d->d_name); 73 sprintf (name, "%s/%s", dir, d->d_name);
76 if (skip_dirs) { 74 if (skip_dirs)
75 {
77 stat(name, &sb); 76 stat (name, &sb);
78 if (S_ISDIR(sb.st_mode)) { 77 if (S_ISDIR (sb.st_mode))
78 {
79 continue; 79 continue;
80 } 80 }
81 } 81 }
82 82
83 if (entries == entry_size) { 83 if (entries == entry_size)
84 {
84 entry_size+=10; 85 entry_size += 10;
85 rn = (char **) realloc(rn, sizeof(char*) * entry_size); 86 rn = (char **) realloc (rn, sizeof (char *) * entry_size);
86 } 87 }
87 rn[entries] = strdup_local(d->d_name); 88 rn[entries] = strdup_local (d->d_name);
88 entries++; 89 entries++;
89 90
90 } 91 }
91 (void) closedir (dp); 92 (void) closedir (dp);
92 93
93 qsort(rn, entries, sizeof(char*), pointer_strcmp); 94 qsort (rn, entries, sizeof (char *), pointer_strcmp);
94 95
95 *namelist = rn; 96 *namelist = rn;
96 return entries; 97 return entries;
97} 98}
98 99
99 100
100 101
101 102
102 103
103/* this function loads and returns the map requested. 104/* this function loads and returns the map requested.
104 * dirname, for example, is "/styles/wallstyles", stylename, is, 105 * dirname, for example, is "/styles/wallstyles", stylename, is,
105 * for example, "castle", difficulty is -1 when difficulty is 106 * for example, "castle", difficulty is -1 when difficulty is
106 * irrelevant to the style. If dirname is given, but stylename 107 * irrelevant to the style. If dirname is given, but stylename
107 * isn't, and difficult is -1, it returns a random style map. 108 * isn't, and difficult is -1, it returns a random style map.
108 * Otherwise, it tries to match the difficulty given with a style 109 * Otherwise, it tries to match the difficulty given with a style
109 * file, named style_name_# where # is an integer 110 * file, named style_name_# where # is an integer
110 */ 111 */
111 112
112/* remove extern, so visible to command_style_map_info function */ 113/* remove extern, so visible to command_style_map_info function */
113mapstruct *styles=NULL; 114maptile *styles = NULL;
114 115
115 116
117maptile *
116mapstruct *load_style_map(char *style_name) 118load_style_map (char *style_name)
117{ 119{
118 mapstruct *style_map; 120 maptile *style_map;
119 121
120 /* Given a file. See if its in memory */ 122 /* Given a file. See if its in memory */
121 for (style_map = styles; style_map!=NULL; style_map=style_map->next) { 123 for (style_map = styles; style_map != NULL; style_map = style_map->next)
124 {
122 if (!strcmp(style_name, style_map->path)) return style_map; 125 if (!strcmp (style_name, style_map->path))
126 return style_map;
123 } 127 }
124 style_map = load_original_map(style_name,MAP_STYLE); 128 style_map = load_original_map (style_name, MAP_STYLE);
125 /* Remove it from global list, put it on our local list */ 129 /* Remove it from global list, put it on our local list */
126 if (style_map) { 130 if (style_map)
131 {
127 mapstruct *tmp; 132 maptile *tmp;
128 133
129 if (style_map == first_map) 134 if (style_map == first_map)
130 first_map = style_map->next; 135 first_map = style_map->next;
131 else { 136 else
137 {
132 for (tmp = first_map; tmp && tmp->next != style_map; tmp = tmp->next); 138 for (tmp = first_map; tmp && tmp->next != style_map; tmp = tmp->next);
133 if(tmp) 139 if (tmp)
134 tmp->next = style_map->next; 140 tmp->next = style_map->next;
135 } 141 }
136 style_map->next = styles; 142 style_map->next = styles;
137 styles = style_map; 143 styles = style_map;
138 } 144 }
139 return style_map; 145 return style_map;
140} 146}
141 147
148maptile *
142mapstruct *find_style(const char *dirname,const char *stylename,int difficulty) { 149find_style (const char *dirname, const char *stylename, int difficulty)
150{
143 char style_file_path[256]; 151 char style_file_path[256];
144 char style_file_full_path[256]; 152 char style_file_full_path[256];
145 mapstruct *style_map = NULL; 153 maptile *style_map = NULL;
146 struct stat file_stat; 154 struct stat file_stat;
147 int i, only_subdirs=0; 155 int i, only_subdirs = 0;
148 156
149 /* if stylename exists, set style_file_path to that file.*/ 157 /* if stylename exists, set style_file_path to that file. */
150 if(stylename && strlen(stylename)>0) 158 if (stylename && strlen (stylename) > 0)
151 sprintf(style_file_path,"%s/%s",dirname,stylename); 159 sprintf (style_file_path, "%s/%s", dirname, stylename);
152 else /* otherwise, just use the dirname. We'll pick a random stylefile.*/ 160 else /* otherwise, just use the dirname. We'll pick a random stylefile. */
153 sprintf(style_file_path,"%s",dirname); 161 sprintf (style_file_path, "%s", dirname);
154 162
155 /* is what we were given a directory, or a file? */ 163 /* is what we were given a directory, or a file? */
156 sprintf(style_file_full_path,"%s/maps%s",settings.datadir,style_file_path); 164 sprintf (style_file_full_path, "%s/maps%s", settings.datadir, style_file_path);
157 if (stat(style_file_full_path, &file_stat) == 0 165 if (stat (style_file_full_path, &file_stat) == 0 && !S_ISDIR (file_stat.st_mode))
158 && !S_ISDIR(file_stat.st_mode)) { 166 {
159 style_map=load_style_map(style_file_path); 167 style_map = load_style_map (style_file_path);
160 } 168 }
161 if(style_map == NULL) /* maybe we were given a directory! */ 169 if (style_map == NULL) /* maybe we were given a directory! */
162 { 170 {
163 char **namelist; 171 char **namelist;
164 int n; 172 int n;
165 char style_dir_full_path[256]; 173 char style_dir_full_path[256];
166 174
167 /* get the names of all the files in that directory */ 175 /* get the names of all the files in that directory */
168 sprintf(style_dir_full_path,"%s/maps%s",settings.datadir,style_file_path); 176 sprintf (style_dir_full_path, "%s/maps%s", settings.datadir, style_file_path);
169 177
170 /* First, skip subdirectories. If we don't find anything, then try again 178 /* First, skip subdirectories. If we don't find anything, then try again
171 * without skipping subdirs. 179 * without skipping subdirs.
172 */ 180 */
173 n = load_dir(style_dir_full_path, &namelist, 1); 181 n = load_dir (style_dir_full_path, &namelist, 1);
174 182
175 if (n<=0) { 183 if (n <= 0)
184 {
176 n = load_dir(style_dir_full_path, &namelist, 0); 185 n = load_dir (style_dir_full_path, &namelist, 0);
177 only_subdirs=1; 186 only_subdirs = 1;
178 } 187 }
179 188
189 if (n <= 0)
180 if (n<=0) return 0; /* nothing to load. Bye. */ 190 return 0; /* nothing to load. Bye. */
181 191
182 /* Picks a random map. Note that if this is all directories, 192 /* Picks a random map. Note that if this is all directories,
183 * we know it won't be able to load, so save a few ticks. 193 * we know it won't be able to load, so save a few ticks.
184 * the door handling checks for this failure and handles 194 * the door handling checks for this failure and handles
185 * it properly. 195 * it properly.
186 */ 196 */
187 if(difficulty==-1) { /* pick a random style from this dir. */ 197 if (difficulty == -1)
198 { /* pick a random style from this dir. */
188 if (only_subdirs) 199 if (only_subdirs)
189 style_map=NULL; 200 style_map = NULL;
190 else { 201 else
202 {
191 strcat(style_file_path,"/"); 203 strcat (style_file_path, "/");
192 strcat(style_file_path,namelist[RANDOM()%n]); 204 strcat (style_file_path, namelist[RANDOM () % n]);
193 style_map = load_style_map(style_file_path); 205 style_map = load_style_map (style_file_path);
194 } 206 }
195 } 207 }
208 else
196 else { /* find the map closest in difficulty */ 209 { /* find the map closest in difficulty */
197 int min_dist=32000,min_index=-1; 210 int min_dist = 32000, min_index = -1;
198 211
199 for(i=0;i<n;i++) { 212 for (i = 0; i < n; i++)
213 {
200 int dist; 214 int dist;
201 char *mfile_name = strrchr(namelist[i],'_')+1; 215 char *mfile_name = strrchr (namelist[i], '_') + 1;
202 216
203 if((mfile_name-1) == NULL) { /* since there isn't a sequence, */ 217 if ((mfile_name - 1) == NULL)
218 { /* since there isn't a sequence, */
204 int q; 219 int q;
220
205 /*pick one at random to recurse */ 221 /*pick one at random to recurse */
206 style_map= find_style(style_file_path, 222 style_map = find_style (style_file_path, namelist[RANDOM () % n], difficulty);
207 namelist[RANDOM()%n],difficulty);
208 for (q=0; q<n; q++) 223 for (q = 0; q < n; q++)
209 free(namelist[q]); 224 free (namelist[q]);
210 free(namelist); 225 free (namelist);
211 return style_map; 226 return style_map;
227 }
212 } else { 228 else
229 {
213 dist = abs(difficulty-atoi(mfile_name)); 230 dist = abs (difficulty - atoi (mfile_name));
214 if(dist<min_dist) { 231 if (dist < min_dist)
232 {
215 min_dist = dist; 233 min_dist = dist;
216 min_index = i; 234 min_index = i;
217 } 235 }
218 } 236 }
219 } 237 }
220 /* presumably now we've found the "best" match for the 238 /* presumably now we've found the "best" match for the
221 difficulty. */ 239 difficulty. */
222 strcat(style_file_path,"/"); 240 strcat (style_file_path, "/");
223 strcat(style_file_path,namelist[min_index]); 241 strcat (style_file_path, namelist[min_index]);
224 style_map = load_style_map(style_file_path); 242 style_map = load_style_map (style_file_path);
225 } 243 }
226 for (i=0; i<n; i++) 244 for (i = 0; i < n; i++)
227 free(namelist[i]); 245 free (namelist[i]);
228 free(namelist); 246 free (namelist);
229 } 247 }
230 return style_map; 248 return style_map;
231 249
232} 250}
233 251
234 252
235/* picks a random object from a style map. 253/* picks a random object from a style map.
236 * Redone by MSW so it should be faster and not use static 254 * Redone by MSW so it should be faster and not use static
237 * variables to generate tables. 255 * variables to generate tables.
238 */ 256 */
257object *
239object *pick_random_object(mapstruct *style) { 258pick_random_object (maptile *style)
259{
240 int x,y, limit=0; 260 int x, y, limit = 0;
241 object *new_obj; 261 object *new_obj;
242 262
243 /* while returning a null object will result in a crash, that 263 /* while returning a null object will result in a crash, that
244 * is actually preferable to an infinite loop. That is because 264 * is actually preferable to an infinite loop. That is because
245 * most servers will automatically restart in case of crash. 265 * most servers will automatically restart in case of crash.
246 * Change the logic on getting the random space - shouldn't make 266 * Change the logic on getting the random space - shouldn't make
247 * any difference, but this seems clearer to me. 267 * any difference, but this seems clearer to me.
248 */ 268 */
269 do
249 do { 270 {
250 limit++; 271 limit++;
251 x = RANDOM() % MAP_WIDTH(style); 272 x = RANDOM () % MAP_WIDTH (style);
252 y = RANDOM() % MAP_HEIGHT(style); 273 y = RANDOM () % MAP_HEIGHT (style);
253 new_obj = get_map_ob(style,x,y); 274 new_obj = get_map_ob (style, x, y);
275 }
254 } while (new_obj == NULL && limit<1000); 276 while (new_obj == NULL && limit < 1000);
255 if (new_obj->head) return new_obj->head; 277 if (new_obj->head)
278 return new_obj->head;
279 else
256 else return new_obj; 280 return new_obj;
257} 281}
258
259 282
283
284void
260void free_style_maps(void) 285free_style_maps (void)
261{ 286{
262 mapstruct *next; 287 maptile *next;
263 int style_maps=0; 288 int style_maps = 0;
264 289
265 /* delete_map will try to free it from the linked list, 290 /* delete_map will try to free it from the linked list,
266 * but won't find it, so we need to do it ourselves 291 * but won't find it, so we need to do it ourselves
267 */ 292 */
268 while (styles) { 293 while (styles)
294 {
269 next = styles->next; 295 next = styles->next;
270 delete_map(styles); 296 delete_map (styles);
271 styles=next; 297 styles = next;
272 style_maps++; 298 style_maps++;
273 } 299 }
274 LOG(llevDebug,"free_style_maps: Freed %d maps\n", style_maps); 300 LOG (llevDebug, "free_style_maps: Freed %d maps\n", style_maps);
275} 301}
276

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines