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

# User Rev Content
1 elmex 1.1 /*
2 root 1.26 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.21 *
4 root 1.26 * 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 pippijn 1.21 *
8 root 1.26 * Crossfire TRT is free software: you can redistribute it and/or modify
9 pippijn 1.21 * it under the terms of the GNU General Public License as published by
10 root 1.26 * the Free Software Foundation, either version 3 of the License, or
11 pippijn 1.21 * (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 root 1.26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 pippijn 1.21 * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19 root 1.26 * 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 pippijn 1.21 */
23 elmex 1.1
24     #include <global.h>
25     #include <random_map.h>
26 pippijn 1.6 #include <dirent.h>
27     #include <sys/stat.h>
28     #include <unistd.h>
29     #include "../include/autoconf.h"
30 elmex 1.1
31 root 1.25 // NAME_MAX may not be defined on POSIX systems
32     #ifndef NAME_MAX
33     # define NAME_MAX 255
34     #endif
35    
36 root 1.3 static int
37     pointer_strcmp (const void *p1, const void *p2)
38 elmex 1.1 {
39 root 1.3 const char *s1 = *(const char **) p1;
40     const char *s2 = *(const char **) p2;
41 elmex 1.1
42 root 1.3 return (strcmp (s1, s2));
43 elmex 1.1 }
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 root 1.3 int
60     load_dir (const char *dir, char ***namelist, int skip_dirs)
61 elmex 1.1 {
62 root 1.3 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 root 1.23 if (!dp)
70 root 1.3 return -1;
71    
72 root 1.23 while ((d = readdir (dp)))
73 root 1.3 {
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 root 1.23 continue;
80 root 1.2 }
81    
82 root 1.3 if (entries == entry_size)
83     {
84     entry_size += 10;
85     rn = (char **) realloc (rn, sizeof (char *) * entry_size);
86 root 1.2 }
87 root 1.7 rn[entries] = strdup (d->d_name);
88 root 1.3 entries++;
89 elmex 1.1
90     }
91 root 1.3 (void) closedir (dp);
92 elmex 1.1
93 root 1.3 qsort (rn, entries, sizeof (char *), pointer_strcmp);
94 elmex 1.1
95 root 1.3 *namelist = rn;
96     return entries;
97 elmex 1.1 }
98    
99 root 1.5 maptile *
100 root 1.3 find_style (const char *dirname, const char *stylename, int difficulty)
101     {
102 root 1.18 char style_file_path[1024];
103     char style_file_full_path[1024];
104 root 1.5 maptile *style_map = NULL;
105 root 1.3 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 root 1.23 sprintf (style_file_full_path, "%s/maps%s.map", settings.datadir, style_file_path);
116 root 1.14
117 root 1.3 if (stat (style_file_full_path, &file_stat) == 0 && !S_ISDIR (file_stat.st_mode))
118 root 1.19 style_map = maptile::find_sync (style_file_path);
119 root 1.13
120 root 1.17 if (!style_map) /* maybe we were given a directory! */
121 elmex 1.1 {
122 root 1.3 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 root 1.2 }
139    
140 root 1.3 if (n <= 0)
141     return 0; /* nothing to load. Bye. */
142 root 1.2
143 root 1.3 /* 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 root 1.13 style_map = 0;
152 root 1.3 else
153     {
154     strcat (style_file_path, "/");
155 root 1.22 strcat (style_file_path, namelist[rndm (n)]);
156 root 1.19 style_map = maptile::find_sync (style_file_path);
157 root 1.2 }
158     }
159 root 1.3 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 root 1.22 style_map = find_style (style_file_path, namelist[rndm (n)], difficulty);
174 root 1.3 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 root 1.2 }
187     }
188     }
189 root 1.15
190 root 1.3 /* 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 root 1.19 style_map = maptile::find_sync (style_file_path);
195 root 1.2 }
196 root 1.13
197 root 1.3 for (i = 0; i < n; i++)
198     free (namelist[i]);
199 root 1.13
200 root 1.3 free (namelist);
201 elmex 1.1 }
202 root 1.13
203 root 1.15 if (style_map)
204 root 1.19 {
205     style_map->load_sync ();
206     style_map->deactivate ();
207     }
208 root 1.15
209 elmex 1.1 return style_map;
210     }