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.1 by elmex, Sun Aug 13 17:16:03 2006 UTC vs.
Revision 1.20 by pippijn, Sat Jan 6 14:42:30 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines