9 #include "keybindings.h"
12 // Pseudo-random number generator (LGC algorithm). Use instead of rand() to ensure portable predictability.
13 static uint32_t seed = 0;
14 seed = ((seed * 1103515245) + 12345) % 2147483648; // Values as recommended by POSIX.1-2001 (see rand(3)).
15 return (seed / 65536); } // Ignore least significant 16 bits (they are less random).
17 void toggle_window (struct WinMeta * win_meta, struct Win * win) {
18 // Toggle display of window win.
20 suspend_window(win_meta, win);
22 append_window(win_meta, win); }
24 void growshrink_active_window (struct WinMeta * win_meta, char change) {
25 // Grow or shrink active window horizontally or vertically by one cell size.
26 if (0 != win_meta->active) {
27 uint16_t height = win_meta->active->height;
28 uint16_t width = win_meta->active->width;
31 else if (change == '+')
33 else if (change == '_')
35 else if (change == '*')
37 resize_active_window (win_meta, height, width); } }
39 struct Map init_map () {
40 // Initialize map with some experimental start values.
46 map.cells = malloc(map.width * map.height);
49 for (y = 0; y < map.height; y++)
50 for (x = 0; x < map.width; x++) {
53 if ( 0 == ran % ((x*x) / 3 + 1)
54 || 0 == ran % ((y*y) / 3 + 1)
55 || 0 == ran % ((map.width - x - 1) * (map.width - x - 1) / 3 + 1)
56 || 0 == ran %((map.height - y - 1) * (map.height - y - 1) / 3 + 1))
58 map.cells[(y * map.width) + x] = terrain; }
61 void map_scroll (struct Map * map, char dir) {
62 // Scroll map into direction dir if possible by changing the offset.
63 if ('n' == dir && map->offset_y > 0)
67 else if ('w' == dir && map->offset_x > 0)
72 void next_turn (struct World * world) {
73 // Increment turn and move enemy.
76 char ty = world->monster->y;
77 char tx = world->monster->x;
86 if (tx == world->player->x && ty == world->player->y)
87 update_log(world, "\nThe monster hits you.");
88 else if (is_passable(world, tx, ty)) {
89 world->monster->y = ty;
90 world->monster->x = tx; } }
92 void update_log (struct World * world, char * text) {
93 // Update log with new text to be appended.
95 uint16_t len_old = strlen(world->log);
96 uint16_t len_new = strlen(text);
97 uint16_t len_whole = len_old + len_new + 1;
98 new_text = calloc(len_whole, sizeof(char));
99 memcpy(new_text, world->log, len_old);
100 memcpy(new_text + len_old, text, len_new);
102 world->log = new_text; }
104 char is_passable (struct World * world, uint16_t x, uint16_t y) {
105 // Check if coordinate on (or beyond) map is accessible to movement.
107 if (0 <= x && x < world->map->width && 0 <= y && y < world->map->height)
108 if ('.' == world->map->cells[y * world->map->width + x])
112 void move_player (struct World * world, char d) {
113 // Move player in direction d, increment turn counter and update log.
114 static char prev = 0;
117 char ty = world->player->y;
118 char tx = world->player->x;
131 if (ty == world->monster->y && tx == world->monster->x)
133 else if (is_passable(world, tx, ty)) {
135 world->player->y = ty;
136 world->player->x = tx; }
137 if (success * d == prev)
138 update_log (world, ".");
141 update_log (world, "\nYou hit the monster.");
143 char * msg = calloc(25, sizeof(char));
144 char * msg_content = "You fail to move";
146 msg_content = "You move";
147 sprintf(msg, "\n%s %s.", msg_content, dir);
148 update_log (world, msg);
153 void player_wait (struct World * world) {
154 // Make player wait one turn.
156 update_log (world, "\nYou wait."); }
158 void save_map (struct Map * map) {
159 // Save map to file "map".
160 FILE * file = fopen("map", "w");
161 fputc(map->width / CHAR_MAX, file);
162 fputc(map->width % CHAR_MAX, file);
164 for (y = 0; y < map->height; y++)
165 for (x = 0; x < map->width; x++)
166 fputc(map->cells[y * map->width + x], file);
169 struct Map load_map () {
170 // Load map from file.
171 FILE * file = fopen("map", "r");
173 map.width = (fgetc(file) * CHAR_MAX) + fgetc(file);
174 long pos = ftell(file);
180 map.cells = malloc(i * sizeof(char));
181 map.height = i / map.width;
182 fseek(file, pos, SEEK_SET);
186 map.cells[i] = (char) c;
194 init_keybindings(&world);
196 world.log = calloc(1, sizeof(char));
197 update_log (&world, "Start!");
198 struct Map map = init_map();
200 struct Player player;
203 world.player = &player;
204 struct Monster monster;
207 world.monster = &monster;
209 WINDOW * screen = initscr();
212 keypad(screen, TRUE);
214 struct WinMeta win_meta = init_win_meta(screen);
215 struct Win win_keys = init_window(&win_meta, "Keys", &world, draw_keys_win);
216 struct Win win_map = init_window(&win_meta, "Map", &world, draw_map_win);
217 struct Win win_info = init_window(&win_meta, "Info", &world, draw_info_win);
218 struct Win win_log = init_window(&win_meta, "Log", &world, draw_log_win);
222 draw_all_windows (&win_meta);
224 if (key == get_action_key(world.keybindings, "quit"))
226 else if (key == get_action_key(world.keybindings, "scroll pad right"))
227 scroll_pad (&win_meta, '+');
228 else if (key == get_action_key(world.keybindings, "scroll pad left"))
229 scroll_pad (&win_meta, '-');
230 else if (key == get_action_key(world.keybindings, "toggle keys window"))
231 toggle_window(&win_meta, &win_keys);
232 else if (key == get_action_key(world.keybindings, "toggle map window"))
233 toggle_window(&win_meta, &win_map);
234 else if (key == get_action_key(world.keybindings, "toggle info window"))
235 toggle_window(&win_meta, &win_info);
236 else if (key == get_action_key(world.keybindings, "toggle log window"))
237 toggle_window(&win_meta, &win_log);
238 else if (key == get_action_key(world.keybindings, "cycle forwards"))
239 cycle_active_window(&win_meta, 'n');
240 else if (key == get_action_key(world.keybindings, "cycle backwards"))
241 cycle_active_window(&win_meta, 'p');
242 else if (key == get_action_key(world.keybindings, "shift forwards"))
243 shift_active_window(&win_meta, 'f');
244 else if (key == get_action_key(world.keybindings, "shift backwards"))
245 shift_active_window(&win_meta, 'b');
246 else if (key == get_action_key(world.keybindings, "grow horizontally"))
247 growshrink_active_window(&win_meta, '*');
248 else if (key == get_action_key(world.keybindings, "shrink horizontally"))
249 growshrink_active_window(&win_meta, '_');
250 else if (key == get_action_key(world.keybindings, "grow vertically"))
251 growshrink_active_window(&win_meta, '+');
252 else if (key == get_action_key(world.keybindings, "shrink vertically"))
253 growshrink_active_window(&win_meta, '-');
254 else if (key == get_action_key(world.keybindings, "save keys"))
255 save_keybindings(&world);
256 else if (key == get_action_key(world.keybindings, "keys nav up"))
257 keyswin_move_selection (&world, 'u');
258 else if (key == get_action_key(world.keybindings, "keys nav down"))
259 keyswin_move_selection (&world, 'd');
260 else if (key == get_action_key(world.keybindings, "keys mod"))
261 keyswin_mod_key (&world, &win_meta);
262 else if (key == get_action_key(world.keybindings, "load map"))
264 else if (key == get_action_key(world.keybindings, "save map"))
266 else if (key == get_action_key(world.keybindings, "map up"))
267 map_scroll (&map, 'n');
268 else if (key == get_action_key(world.keybindings, "map down"))
269 map_scroll (&map, 's');
270 else if (key == get_action_key(world.keybindings, "map right"))
271 map_scroll (&map, 'e');
272 else if (key == get_action_key(world.keybindings, "map left"))
273 map_scroll (&map, 'w');
274 else if (key == get_action_key(world.keybindings, "player down"))
275 move_player(&world, 's');
276 else if (key == get_action_key(world.keybindings, "player up"))
277 move_player(&world, 'n');
278 else if (key == get_action_key(world.keybindings, "player right"))
279 move_player(&world, 'e');
280 else if (key == get_action_key(world.keybindings, "player left"))
281 move_player(&world, 'w');
282 else if (key == get_action_key(world.keybindings, "wait") )
283 player_wait (&world); }
286 for (key = 0; key <= world.keyswindata->max; key++)
287 free(world.keybindings[key].name);
288 free(world.keybindings);
289 free(world.keyswindata);