home · contact · privacy
Simplified interface of (build/read/write)_map_objects() by making them decide by...
[plomrogue] / src / map_objects.c
1 /* map_objects.c */
2
3 #include "map_objects.h"
4 #include <stdlib.h> /* for malloc(), calloc(), free(), atoi() */
5 #include <stdio.h> /* for FILE typedef */
6 #include <string.h> /* for strchr(), strlen(), memcpy()  */
7 #include "readwrite.h" /* for all the map object (def) loading/saving */
8 #include "misc.h" /* for textfile_sizes(), find_passable_pos() */
9 #include "main.h" /* for World struct */
10
11
12
13 /* Return pointer to newly allocated map object struct of size "size". If first
14  * in map object chain ("first" pointing to !0), point "start" to it.
15  */
16 static struct MapObj * get_next_map_obj(void * start, char * first,
17                                         size_t size, struct MapObj * map_obj);
18
19
20
21 /* Map-object-type-specific helpers to (build|write|read)_map_objects(). */
22 static void build_map_objects_itemdata(struct MapObjDef * map_obj_def,
23                                        void * start);
24 static void build_map_objects_monsterdata(struct MapObjDef * map_obj_def,
25                                           void * start);
26 static void write_map_objects_monsterdata(void * start, FILE * file);
27 static void read_map_objects_monsterdata( void * start, FILE * file);
28
29
30
31 static struct MapObj * get_next_map_obj(void * start, char * first,
32                                         size_t size, struct MapObj * map_obj)
33 {
34     if (* first)
35     {
36         struct MapObj * * z = start;
37         map_obj = malloc(size);
38         * z = map_obj;
39         * first = 0;
40     }
41     else
42     {
43         map_obj->next = malloc(size);
44         map_obj = map_obj->next;
45     }
46     return map_obj;
47 }
48
49
50
51 static void build_map_objects_itemdata(struct MapObjDef * map_obj_def,
52                                        void * start)
53 {
54   struct Item * i = (struct Item *) start;
55   i->map_obj.type = map_obj_def->id;
56 }
57
58
59
60 static void build_map_objects_monsterdata(struct MapObjDef * map_obj_def,
61                                           void * start)
62 {
63     struct Monster * m = (struct Monster *) start;
64     m->map_obj.type = map_obj_def->id;
65     struct MonsterDef * md = (struct MonsterDef *) map_obj_def;
66     m->hitpoints = md->hitpoints_start;
67 }
68
69
70
71 static void write_map_objects_monsterdata(void * start, FILE * file)
72 {
73     struct Monster * m = (struct Monster *) start;
74     fputc(m->hitpoints, file);
75 }
76
77
78
79 static void read_map_objects_monsterdata (void * start, FILE * file)
80 {
81     struct Monster * m = (struct Monster *) start;
82     m->hitpoints = fgetc(file);
83 }
84
85
86
87 extern void init_map_object_defs(struct World * world, char * filename)
88 {
89     world->item_def    = 0;
90     world->monster_def = 0;
91     FILE * file = fopen(filename, "r");
92     uint16_t linemax;
93     textfile_sizes (file, &linemax, NULL);
94     struct MapObjDef  mod;
95     struct ItemDef    id;
96     struct MonsterDef md;
97     struct ItemDef    * * p_p_id  = &world->item_def;
98     struct MonsterDef * * p_p_md  = &world->monster_def;
99     char * defline = malloc(linemax);
100     char * line_p;
101     while (fgets(defline, linemax, file))
102     {
103         mod.next    = 0;
104         mod.id      = atoi(defline);
105         line_p      = strchr(defline, ' ') + 1;
106         mod.m_or_i  = * line_p;
107         mod.mapchar = * (line_p + 2);
108         if ('i' == mod.m_or_i)
109         {
110             line_p = line_p + 5;
111         }
112         else
113         {
114             md.hitpoints_start = atoi   (line_p + 4);
115             line_p             = strchr (line_p + 4, ' ') + 1;
116         }
117         mod.desc = calloc (strlen (line_p), sizeof(char));
118         memcpy (mod.desc, line_p, strlen(line_p) - 1);
119         if ('i' == mod.m_or_i)
120         {
121             id.map_obj_def = mod;
122             * p_p_id       = malloc(sizeof(struct ItemDef));
123             * * p_p_id     = id;
124             p_p_id         = (struct ItemDef    * *) * p_p_id;
125         }
126         else
127         {
128             md.map_obj_def = mod;
129             * p_p_md       = malloc(sizeof(struct MonsterDef));
130             * * p_p_md     = md;
131             p_p_md         = (struct MonsterDef * *) * p_p_md;
132         }
133     }
134     free(defline);
135     fclose(file);
136 };
137
138
139
140 extern void write_map_objects(struct World * world, void * start, FILE * file)
141 {
142     struct MapObj * map_obj;
143     struct MapObjDef * mod;
144     for (map_obj = start; map_obj != 0; map_obj = map_obj->next)
145     {
146         fputc(map_obj->type, file);
147         write_uint16_bigendian(map_obj->pos.y + 1, file);
148         write_uint16_bigendian(map_obj->pos.x + 1, file);
149         mod = get_map_obj_def(world, map_obj->type);
150         if ('m' == mod->m_or_i)
151         {
152             write_map_objects_monsterdata(map_obj, file);
153         }
154     }
155     write_uint16_bigendian(0, file);
156 }
157
158
159
160 extern void read_map_objects(struct World * world, void * start, FILE * file)
161 {
162     struct MapObj * map_obj;
163     struct MapObjDef * mod;
164     size_t size;
165     char type;
166     char first = 1;
167     long pos;
168     while (1)
169     {
170         pos = ftell(file);
171         if (0 == read_uint16_bigendian(file))
172         {
173             break;
174         }
175         fseek(file, pos, SEEK_SET);
176         type = fgetc(file);
177         mod = get_map_obj_def(world, type);
178         if ('m' == mod->m_or_i)
179         {
180             size = sizeof(struct Monster);
181         }
182         else
183         {
184             size = sizeof(struct Item);
185         }
186         map_obj = get_next_map_obj(start, &first, size, map_obj);
187         map_obj->type = type;
188         map_obj->pos.y = read_uint16_bigendian(file) - 1;
189         map_obj->pos.x = read_uint16_bigendian(file) - 1;
190         if ('m' == mod->m_or_i)
191         {
192             read_map_objects_monsterdata(map_obj, file);
193         }
194     }
195     if (!first)
196     {
197         map_obj->next = 0;
198     }
199 }
200
201
202
203 extern void * build_map_objects(struct World * world, void * start, char def_id,
204                                 unsigned char n)
205 {
206     unsigned char i;
207     struct MapObj * mo;
208     char first = 1;
209     struct MapObjDef * mod = get_map_obj_def(world, def_id);
210     size_t size = 0;
211     if ('i' == mod->m_or_i)
212     {
213         size = sizeof(struct Item);
214     }
215     else
216     {
217         size = sizeof(struct Monster);
218     }
219     for (i = 0; i < n; i++)
220     {
221         mo = get_next_map_obj(start, &first, size, mo);
222         mo->pos = find_passable_pos(world->map);
223         if ('i' == mod->m_or_i)
224         {
225             build_map_objects_itemdata(mod, mo);
226         }
227         else
228         {
229             build_map_objects_monsterdata(mod, mo);
230         }
231
232     }
233     if (!first)
234     {
235         mo->next = 0;
236     }
237     return &mo->next;
238 }
239
240
241
242 extern struct MapObjDef * get_map_obj_def (struct World * world, char def_id)
243 {
244     struct MapObjDef * d = NULL;
245     for (d = (struct MapObjDef *) world->monster_def;
246          d->id != def_id && 0 != d->next;
247          d = d->next);
248     if (d->id != def_id)
249     {
250         for (d = (struct MapObjDef *) world->item_def;
251              d->id != def_id && 0 != d->next;
252              d = d->next);
253     }
254     return d;
255 }