home · contact · privacy
Some cleaning up and comments added to outsourcing misc library stuff into control...
[plomrogue] / src / misc.c
1 /* misc.c */
2
3 #include "misc.h"
4 #include <stdio.h> /* for rename() */
5 #include <unistd.h> /* for unlink(), acess() */
6 #include <stdlib.h> /* for calloc(), free() */
7 #include <string.h> /* for strlen(), strcmp(), memcpy() */
8 #include <stdint.h> /* for uint8_t */
9 #include "windows.h" /* for suspend_win(), append_win(), reset_pad_offset(),
10                       * resize_active_win(), struct Win, struct WinMeta
11                       */
12 #include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian]() */
13 #include "map_objects.h" /* for struct Monster, write_map_objects(), */
14 #include "map_object_actions.h" /* for is_passable(), move_monster() */
15 #include "map.h" /* for Map struct */
16 #include "main.h" /* for World struct */
17 #include "yx_uint16.h" /* for yx_uint16 */
18 #include "rrand.h" /* for rrand(), rrand_seed() */
19 #include "rexit.h" /* for exit_err() */
20
21
22 extern void textfile_sizes(FILE * file, uint16_t * linemax_p,
23                            uint16_t * n_lines_p)
24 {
25     uint16_t n_lines = 0;
26     int c = 0;
27     uint16_t linemax = 0;
28     uint16_t c_count = 0;
29     while (EOF != c)
30     {
31         c_count++;
32         c = getc(file);
33         if ('\n' == c)
34         {
35             if (c_count > linemax)
36             {
37                 linemax = c_count + 1;
38             }
39             c_count = 0;
40             if (n_lines_p)
41             {
42                 n_lines++;
43             }
44         }
45     }
46     fseek(file, 0, SEEK_SET);
47     * linemax_p = linemax;
48     if (n_lines_p)
49     {
50         * n_lines_p = n_lines;
51     }
52 }
53
54
55
56 extern void update_log(struct World * world, char * text)
57 {
58     static char * last_msg;
59     if (0 == last_msg)
60     {
61         last_msg = calloc(1, sizeof(char));
62     }
63     char * new_text;
64     uint16_t len_old = strlen(world->log);
65     if (0 == strcmp(last_msg, text))
66     {
67         uint16_t len_whole = len_old + 1;
68         new_text = calloc(len_whole + 1, sizeof(char));
69         memcpy(new_text, world->log, len_old);
70         memcpy(new_text + len_old, ".", 1);
71     }
72     else
73     {
74         uint16_t len_new = strlen(text);
75         uint16_t len_whole = len_old + len_new + 1;
76         new_text = calloc(len_whole, sizeof(char));
77         memcpy(new_text, world->log, len_old);
78         memcpy(new_text + len_old, text, len_new);
79         last_msg = calloc(len_new + 1, sizeof(char));
80         memcpy(last_msg, text, len_new);
81     }
82     free(world->log);
83     world->log = new_text;
84 }
85
86
87
88 extern uint16_t center_offset(uint16_t pos, uint16_t mapsize,
89                               uint16_t framesize)
90 {
91     uint16_t offset = 0;
92     if (mapsize > framesize)
93     {
94         if (pos > framesize / 2)
95         {
96             if (pos < mapsize - (framesize / 2))
97             {
98                 offset = pos - (framesize / 2);
99             }
100             else
101             {
102                 offset = mapsize - framesize;
103             }
104         }
105     }
106     return offset;
107 }
108
109
110
111 extern void turn_over(struct World * world, char action)
112 {
113     char * err_open  = "Trouble in turn_over() with fopen() "
114                        "opening file 'record_tmp' for appending.";
115     char * err_write = "Trouble in turn_over() with write_uint8() "
116                        "writing to opened file 'record_tmp'.";
117     char * err_close = "Trouble in turn_over() with fclose() "
118                        "closing opened file 'record'.";
119     char * err_unl   = "Trouble in turn_over() with unlink() "
120                        "unlinking old file 'record'.";
121     char * err_move  = "Trouble in turn_over() with rename() "
122                        "renaming file 'record_tmp' to 'record'.";
123     char * recordfile_tmp = "record_tmp";
124     char * recordfile     = "record";
125     if (1 == world->interactive)
126     {
127         FILE * file_old = fopen(recordfile, "r");
128         FILE * file_new = fopen(recordfile_tmp, "w");
129         exit_err(0 == file_old, world, err_open);
130         char c = fgetc(file_old);
131         while (EOF != c)
132         {
133             exit_err(write_uint8(c, file_new), world, err_write);
134             c = fgetc(file_old);
135         }
136         exit_err(fclose(file_old), world, err_close);
137         exit_err(write_uint8(action, file_new), world, err_write);
138         err_close = "Trouble in turn_over() with fclose() "
139                     "closing opened file 'record_tmp'.";
140         exit_err(fclose(file_new), world, err_close);
141         exit_err(unlink(recordfile), world, err_unl);
142         exit_err(rename(recordfile_tmp, recordfile), world, err_move);
143     }
144     world->turn++;
145     rrand_seed(world->seed * world->turn);
146     struct Monster * monster;
147     for (monster = world->monster;
148          monster != 0;
149          monster = monster->map_obj.next)
150     {
151         move_monster(world, monster);
152     }
153 }
154
155
156
157 extern void save_game(struct World * world)
158 {
159     char * err_open  = "Trouble in save_game() with fopen() "
160                        "opening file 'savefile_tmp' for writing.";
161     char * err_write = "Trouble in save_game() "
162                        "writing to opened file 'savefile_tmp'.";
163     char * err_close = "Trouble in save_game() with fclose() "
164                        "closing opened file 'savefile_tmp'.";
165     char * err_unl   = "Trouble in save_game() with unlink() "
166                        "unlinking old 'savefile' file.";
167     char * err_move  = "Trouble in save_game() with rename() "
168                        "renaming 'file savefile_tmp' to 'savefile'.";
169     char * savefile_tmp = "savefile_tmp";
170     char * savefile     = "savefile";
171     FILE * file = fopen(savefile_tmp, "w");
172     exit_err(0 == file, world, err_open);
173     if (   write_uint32_bigendian(world->seed, file)
174         || write_uint32_bigendian(world->turn, file)
175         || write_uint16_bigendian(world->score, file)
176         || write_uint16_bigendian(world->player->pos.y + 1, file)
177         || write_uint16_bigendian(world->player->pos.x + 1, file)
178         || write_uint8(world->player->hitpoints, file)
179         || write_map_objects(world, world->monster, file)
180         || write_map_objects(world, world->item, file))
181     {
182         exit_err(1, world, err_write);
183     }
184     exit_err(fclose(file), world, err_close);
185     if (!access(savefile, F_OK))
186     {
187         exit_err(unlink(savefile), world, err_unl);
188     }
189     exit_err(rename(savefile_tmp, savefile), world, err_move);
190 }
191
192
193
194 extern uint8_t toggle_window(struct WinMeta * win_meta, struct Win * win)
195 {
196     if (0 != win->frame.curses_win)
197     {
198         return suspend_win(win_meta, win);
199     }
200     else
201     {
202         return append_win(win_meta, win);
203     }
204 }
205
206
207
208 extern void scroll_pad(struct WinMeta * win_meta, char dir)
209 {
210     if      ('+' == dir)
211     {
212         reset_pad_offset(win_meta, win_meta->pad_offset + 1);
213     }
214     else if ('-' == dir)
215     {
216         reset_pad_offset(win_meta, win_meta->pad_offset - 1);
217     }
218 }
219
220
221
222 extern uint8_t growshrink_active_window(struct WinMeta * win_meta, char change)
223 {
224     if (0 != win_meta->active)
225     {
226         struct yx_uint16 size = win_meta->active->frame.size;
227         if      (change == '-')
228         {
229             size.y--;
230         }
231         else if (change == '+')
232         {
233             size.y++;
234         }
235         else if (change == '_')
236         {
237             size.x--;
238         }
239         else if (change == '*')
240         {
241             size.x++;
242         }
243         return resize_active_win (win_meta, size);
244     }
245     return 0;
246 }
247
248
249
250 extern struct yx_uint16 find_passable_pos(struct Map * map)
251 {
252     struct yx_uint16 pos;
253     for (pos.y = pos.x = 0; 0 == is_passable(map, pos);)
254     {
255         pos.y = rrand() % map->size.y;
256         pos.x = rrand() % map->size.x;
257     }
258     return pos;
259 }