OSDN Git Service

日本語版
[nazghul-jp/nazghul-jp.git] / src / terrain.c
1 //
2 // nazghul - an old-school RPG engine
3 // Copyright (C) 2002, 2003 Gordon McNutt
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 2 of the License, or (at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13 // more details.
14 //
15 // You should have received a copy of the GNU General Public License along with
16 // this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
17 // Suite 330, Boston, MA 02111-1307 USA
18 //
19 // Gordon McNutt
20 // gmcnutt@users.sourceforge.net
21 //
22 #include "terrain.h"
23 #include "debug.h"
24 #include "sprite.h"
25 #include "common.h"
26 #include "object.h"
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <assert.h>
32
33 //int TERRAIN_MAGIC = 0xc01dbee3;
34
35 extern struct terrain *terrain_new(const char *tag, 
36                                    const char *name,
37                                    struct sprite *sprite,
38                                    int pclass, 
39                                    int alpha, 
40                                    int light)
41 {
42         struct terrain *terrain;
43
44         terrain = (struct terrain*)calloc(1, sizeof(*terrain));
45         assert(terrain);
46
47         terrain->magic         = TERRAIN_MAGIC;
48         terrain->tag           = strdup(tag);
49         terrain->name          = strdup(name);
50         terrain->sprite        = sprite;
51         terrain->pclass        = pclass;
52         terrain->alpha         = alpha;
53         terrain->light         = light;
54         return terrain;
55 }
56
57 void terrain_del(struct terrain *terrain)
58 {
59         if (terrain->tag) {
60                 free(terrain->tag);
61         }
62         if (terrain->name) {
63                 free(terrain->name);
64         }
65         if (terrain->effect) {
66                 closure_unref(terrain->effect);
67         }
68         free(terrain);
69 }
70
71 #define BOGUS_MAX_SIZE 255      // Hack, should get a constant from somewhere
72 // LONGEST_TERRAIN_GLYPH would be appropriate for glyph_str...
73
74 void palette_entry_print(FILE * fp, int indent,
75                          struct terrain_palette_entry *entry)
76 {
77         static char glyph_str[BOGUS_MAX_SIZE + 1];
78     static char   tag_str[BOGUS_MAX_SIZE + 1];
79         assert(fp);
80     assert(entry);
81     
82     snprintf(glyph_str, BOGUS_MAX_SIZE, "\"%s\"", entry->glyph);
83     snprintf(tag_str,   BOGUS_MAX_SIZE, "%s)",    entry->terrain->tag);
84     
85         INDENT;
86     fprintf(fp, "(list  %-6s %-20s  ;; \"%s\"\n", glyph_str, tag_str, entry->terrain->name);
87 } // palette_entry_print()
88
89 struct terrain_palette *terrain_palette_new(const char *tag)
90 {
91         struct terrain_palette *palette = new struct terrain_palette;
92         assert(palette);
93         memset(palette, 0, sizeof(struct terrain_palette));
94
95         list_init(&palette->lookup_head);
96         list_init(&palette->edit_head);
97         palette->tag = strdup(tag);
98         palette->widest_glyph = 0;
99         palette->num_entries = 0;
100
101         return palette;
102 }
103
104 struct terrain_palette_entry *
105 terrain_palette_entry_new(char *glyph, struct terrain *terrain)
106 {
107         struct terrain_palette_entry *entry;
108         entry = (struct terrain_palette_entry *)malloc(sizeof(*entry));
109         list_init(&entry->lookup_list);
110         list_init(&entry->edit_list);
111         entry->glyph = strdup(glyph);
112         assert(entry->glyph);
113         entry->terrain = terrain;
114         return entry;
115 }
116
117 void terrain_palette_entry_del(struct terrain_palette_entry *entry)
118 {
119         // For each entry free the glyph (because we strdup'd our own copy) but
120         // leave the terrain alone (it's a singleton and belongs to someone
121         // else).
122         free(entry->glyph);
123         free(entry);
124 }
125
126 void terrain_palette_del(struct terrain_palette *pal)
127 {
128         struct list *elem;
129
130         elem = pal->edit_head.next;
131         while (elem != &pal->edit_head) {
132                 struct terrain_palette_entry *entry;
133                 entry = outcast(elem, struct terrain_palette_entry, edit_list);
134                 elem = elem->next;
135                 terrain_palette_entry_del(entry);
136         }
137
138         if (pal->tag)
139                 free(pal->tag);
140         delete pal;
141 }
142
143 void terrain_palette_add(struct terrain_palette *pal, char *glyph, 
144                          struct terrain *ter)
145 {
146         struct terrain_palette_entry *entry;
147         int n = strlen(glyph);
148
149         entry = terrain_palette_entry_new(glyph, ter);
150         list_add_tail(&pal->lookup_head, &entry->lookup_list);
151         list_add_tail(&pal->edit_head, &entry->edit_list);
152         pal->num_entries++;
153         if (pal->widest_glyph < n)
154                 pal->widest_glyph = n;
155 }
156
157 struct terrain_palette_entry *palette_entry(struct terrain_palette *palette, int n)
158 {
159         struct list *elem;
160
161         assert(palette);
162         if (palette->num_entries < 1) {
163                 dbg("palette_terrain_for_glyph() num_entries == 0\n");
164                 return 0;
165         }
166         if (n < 0 || n >= palette->num_entries) {
167                 dbg("palette_terrain_for_glyph() called with out-of-bounds "\
168                     "arg n=%d\n", n);
169                 return 0;
170         }
171
172         elem = palette->edit_head.next;
173         while (n) {
174                 elem = elem->next;
175                 n--;
176         }
177
178         return outcast(elem, struct terrain_palette_entry, edit_list);
179 }
180
181 char *palette_glyph(struct terrain_palette *palette, int n)
182 {
183         struct terrain_palette_entry *entry;
184
185         entry = palette_entry(palette, n);
186         if (entry)
187                 return entry->glyph;
188         return 0;
189 }
190
191 struct terrain_palette_entry *
192 palette_entry_for_terrain(struct terrain_palette * pp, struct terrain * tt)
193 {
194         struct list *elem;
195         struct terrain_palette_entry *entry;
196
197         list_for_each(&pp->lookup_head, elem) {
198                 entry = outcast(elem, struct terrain_palette_entry, lookup_list);
199                 if (tt == entry->terrain)
200                         return entry;
201         }
202
203         return 0;  // Did not find the terrain
204 }
205
206 char * palette_glyph_for_terrain (struct terrain_palette * pp, struct terrain * tt)
207 {
208         struct terrain_palette_entry *entry;
209
210         entry = palette_entry_for_terrain(pp, tt);
211         if (entry)
212                 return entry->glyph;
213         return 0;  // Did not find the terrain
214 }
215
216 struct terrain *palette_terrain(struct terrain_palette *palette, int n)
217 {
218         struct terrain_palette_entry *entry;
219
220         entry = palette_entry(palette, n);
221         if (entry)
222                 return entry->terrain;
223         return 0;
224 }
225
226 struct terrain *palette_terrain_for_glyph(struct terrain_palette *palette,
227                                           char *glyph)
228 {
229         struct list *elem;
230         struct terrain_palette_entry *entry;
231
232         list_for_each(&palette->lookup_head, elem) {
233                 entry = outcast(elem, struct terrain_palette_entry, lookup_list);
234                 if (! strcmp(glyph, entry->glyph)) {
235                         /* Odds are good that we'll want this same terrain in
236                          * the near future, so move it to the front of the list
237                          * (if not already there) to improve performance during
238                          * startup. */
239                         if (elem != palette->lookup_head.next) {
240                                 list_remove(elem);
241                                 list_add(&palette->lookup_head, elem);
242                         }
243                         return entry->terrain;
244                 }
245         }
246
247         return 0;  // Did not find the terrain
248 }                               // palette_terrain_for_glyph()
249
250 struct terrain_palette * palette_contains_terrain (struct terrain_palette *pp, 
251                                                    struct terrain *tt)
252 {
253         // The current user of this function is 
254         // combat.c create_camping_map().
255         // It is used to find a palette (any palette)
256         // which contains a certain fill terrain.
257         // 
258         // For other uses, I wonder if returning the index 
259         // where it is found, or -1 for not found, 
260         // would be more useful?
261         struct terrain_palette_entry *entry;
262
263         entry = palette_entry_for_terrain(pp, tt);
264         if (entry)
265                 return pp;
266         return 0;  // Did not find the terrain
267 }
268
269 void palette_print(FILE * fp, int indent, struct terrain_palette *palette)
270 {
271         struct list *elem;
272         assert(fp);
273
274     // (kern-mk-palette 'pal_expanded
275     //     (list
276     //         ;; There are 999 entries in this palette
277     //         ;; The widest glyph is 4 characters
278     //         (list "__" t_deep)
279     //         (list ".." t_grass)
280     //     )
281     // )
282
283
284         INDENT;
285         fprintf(fp, "(kern-mk-palette '%s\n", palette->tag);
286         indent += INDENTATION_FACTOR;
287
288         INDENT;
289         fprintf(fp, "(list\n");
290         indent += INDENTATION_FACTOR;
291     INDENT;
292     fprintf(fp, ";; There are %d entries in this palette\n", palette->num_entries);
293     INDENT;
294     fprintf(fp, ";; The widest glyph is %d characters\n",   palette->widest_glyph);
295     
296     list_for_each(&palette->edit_head, elem) {
297         struct terrain_palette_entry *entry;
298         entry = outcast(elem, struct terrain_palette_entry, edit_list);
299                 palette_entry_print(fp, indent, entry);
300         }
301
302     fprintf(fp, "\n");
303
304     indent -= INDENTATION_FACTOR;
305     INDENT;
306     fprintf(fp, ")\n");
307
308     indent -= INDENTATION_FACTOR;
309     INDENT;
310     fprintf(fp, ") ;; palette %s\n", palette->tag);
311         fprintf(fp, "\n");
312 } // palette_print()