10 #include "roguelike.h"
11 #include "keybindings.h"
13 uint16_t rrand(char use_seed, uint32_t new_seed) {
14 // Pseudo-random number generator (LGC algorithm). Use instead of rand() to ensure portable predictability.
15 static uint32_t seed = 0;
18 seed = ((seed * 1103515245) + 12345) % 2147483648; // Values as recommended by POSIX.1-2001 (see rand(3)).
19 return (seed / 65536); } // Ignore least significant 16 bits (they are less random).
21 uint32_t load_seed() {
22 // Load seed integer from seed file.
24 const uint16_t nchar = UCHAR_MAX + 1;
25 FILE * file = fopen("seed", "r");
26 unsigned char a = fgetc(file);
27 unsigned char b = fgetc(file);
28 unsigned char c = fgetc(file);
29 unsigned char d = fgetc(file);
30 seed = (a * nchar * nchar * nchar) + (b * nchar * nchar) + (c * nchar) + d;
34 void save_seed(uint32_t seed) {
35 // Save seed integer to seed file.
36 const uint16_t nchar = UCHAR_MAX + 1;
37 unsigned char a = seed / (nchar * nchar * nchar);
38 unsigned char b = (seed - (a * nchar * nchar * nchar)) / (nchar * nchar);
39 unsigned char c = (seed - ((a * nchar * nchar * nchar) + (b * nchar * nchar))) / nchar;
40 unsigned char d = seed % nchar;
41 FILE * file = fopen("seed", "w");
48 void toggle_window (struct WinMeta * win_meta, struct Win * win) {
49 // Toggle display of window win.
51 suspend_window(win_meta, win);
53 append_window(win_meta, win); }
55 void growshrink_active_window (struct WinMeta * win_meta, char change) {
56 // Grow or shrink active window horizontally or vertically by one cell size.
57 if (0 != win_meta->active) {
58 uint16_t height = win_meta->active->height;
59 uint16_t width = win_meta->active->width;
62 else if (change == '+')
64 else if (change == '_')
66 else if (change == '*')
68 resize_active_window (win_meta, height, width); } }
70 struct Map init_map (uint32_t seed) {
71 // Initialize map with some experimental start values.
78 map.cells = malloc(map.width * map.height);
81 for (y = 0; y < map.height; y++)
82 for (x = 0; x < map.width; x++) {
85 if ( 0 == ran % ((x*x) / 3 + 1)
86 || 0 == ran % ((y*y) / 3 + 1)
87 || 0 == ran % ((map.width - x - 1) * (map.width - x - 1) / 3 + 1)
88 || 0 == ran %((map.height - y - 1) * (map.height - y - 1) / 3 + 1))
90 map.cells[(y * map.width) + x] = terrain; }
93 void map_scroll (struct Map * map, char dir) {
94 // Scroll map into direction dir if possible by changing the offset.
95 if ('n' == dir && map->offset_y > 0)
99 else if ('w' == dir && map->offset_x > 0)
104 void next_turn (struct World * world) {
105 // Increment turn and move enemy.
107 char d = rrand(0, 0) % 5;
108 uint16_t ty = world->monster->y;
109 uint16_t tx = world->monster->x;
118 if (tx == world->player->x && ty == world->player->y)
119 update_log(world, "\nThe monster hits you.");
120 else if (is_passable(world, tx, ty)) {
121 world->monster->y = ty;
122 world->monster->x = tx; } }
124 void update_log (struct World * world, char * text) {
125 // Update log with new text to be appended.
127 uint16_t len_old = strlen(world->log);
128 uint16_t len_new = strlen(text);
129 uint16_t len_whole = len_old + len_new + 1;
130 new_text = calloc(len_whole, sizeof(char));
131 memcpy(new_text, world->log, len_old);
132 memcpy(new_text + len_old, text, len_new);
134 world->log = new_text; }
136 char is_passable (struct World * world, uint16_t x, uint16_t y) {
137 // Check if coordinate on (or beyond) map is accessible to movement.
139 if (0 <= x && x < world->map->width && 0 <= y && y < world->map->height)
140 if ('.' == world->map->cells[y * world->map->width + x])
144 void move_player (struct World * world, char d) {
145 // Move player in direction d, increment turn counter and update log.
146 static char prev = 0;
149 uint16_t ty = world->player->y;
150 uint16_t tx = world->player->x;
163 if (ty == world->monster->y && tx == world->monster->x)
165 else if (is_passable(world, tx, ty)) {
167 world->player->y = ty;
168 world->player->x = tx; }
169 if (success * d == prev)
170 update_log (world, ".");
173 update_log (world, "\nYou hit the monster.");
175 char * msg = calloc(25, sizeof(char));
176 char * msg_content = "You fail to move";
178 msg_content = "You move";
179 sprintf(msg, "\n%s %s.", msg_content, dir);
180 update_log (world, msg);
185 void player_wait (struct World * world) {
186 // Make player wait one turn.
188 update_log (world, "\nYou wait."); }
190 int main (int argc, char *argv[]) {
191 uint32_t seed = time(NULL);
193 while ((opt = getopt(argc, argv, "l")) != -1) {
199 exit(EXIT_FAILURE); } }
202 init_keybindings(&world);
204 world.log = calloc(1, sizeof(char));
205 update_log (&world, "Start!");
206 struct Map map = init_map(seed);
208 struct Player player;
211 world.player = &player;
212 struct Monster monster;
215 world.monster = &monster;
217 WINDOW * screen = initscr();
220 keypad(screen, TRUE);
222 struct WinMeta win_meta = init_win_meta(screen);
223 struct Win win_keys = init_window(&win_meta, "Keys", &world, draw_keys_win);
224 struct Win win_map = init_window(&win_meta, "Map", &world, draw_map_win);
225 struct Win win_info = init_window(&win_meta, "Info", &world, draw_info_win);
226 struct Win win_log = init_window(&win_meta, "Log", &world, draw_log_win);
230 draw_all_windows (&win_meta);
232 if (key == get_action_key(world.keybindings, "quit"))
234 else if (key == get_action_key(world.keybindings, "scroll pad right"))
235 scroll_pad (&win_meta, '+');
236 else if (key == get_action_key(world.keybindings, "scroll pad left"))
237 scroll_pad (&win_meta, '-');
238 else if (key == get_action_key(world.keybindings, "toggle keys window"))
239 toggle_window(&win_meta, &win_keys);
240 else if (key == get_action_key(world.keybindings, "toggle map window"))
241 toggle_window(&win_meta, &win_map);
242 else if (key == get_action_key(world.keybindings, "toggle info window"))
243 toggle_window(&win_meta, &win_info);
244 else if (key == get_action_key(world.keybindings, "toggle log window"))
245 toggle_window(&win_meta, &win_log);
246 else if (key == get_action_key(world.keybindings, "cycle forwards"))
247 cycle_active_window(&win_meta, 'n');
248 else if (key == get_action_key(world.keybindings, "cycle backwards"))
249 cycle_active_window(&win_meta, 'p');
250 else if (key == get_action_key(world.keybindings, "shift forwards"))
251 shift_active_window(&win_meta, 'f');
252 else if (key == get_action_key(world.keybindings, "shift backwards"))
253 shift_active_window(&win_meta, 'b');
254 else if (key == get_action_key(world.keybindings, "grow horizontally"))
255 growshrink_active_window(&win_meta, '*');
256 else if (key == get_action_key(world.keybindings, "shrink horizontally"))
257 growshrink_active_window(&win_meta, '_');
258 else if (key == get_action_key(world.keybindings, "grow vertically"))
259 growshrink_active_window(&win_meta, '+');
260 else if (key == get_action_key(world.keybindings, "shrink vertically"))
261 growshrink_active_window(&win_meta, '-');
262 else if (key == get_action_key(world.keybindings, "save keys"))
263 save_keybindings(&world);
264 else if (key == get_action_key(world.keybindings, "keys nav up"))
265 keyswin_move_selection (&world, 'u');
266 else if (key == get_action_key(world.keybindings, "keys nav down"))
267 keyswin_move_selection (&world, 'd');
268 else if (key == get_action_key(world.keybindings, "keys mod"))
269 keyswin_mod_key (&world, &win_meta);
270 else if (key == get_action_key(world.keybindings, "save seed"))
272 else if (key == get_action_key(world.keybindings, "map up"))
273 map_scroll (&map, 'n');
274 else if (key == get_action_key(world.keybindings, "map down"))
275 map_scroll (&map, 's');
276 else if (key == get_action_key(world.keybindings, "map right"))
277 map_scroll (&map, 'e');
278 else if (key == get_action_key(world.keybindings, "map left"))
279 map_scroll (&map, 'w');
280 else if (key == get_action_key(world.keybindings, "player down"))
281 move_player(&world, 's');
282 else if (key == get_action_key(world.keybindings, "player up"))
283 move_player(&world, 'n');
284 else if (key == get_action_key(world.keybindings, "player right"))
285 move_player(&world, 'e');
286 else if (key == get_action_key(world.keybindings, "player left"))
287 move_player(&world, 'w');
288 else if (key == get_action_key(world.keybindings, "wait") )
289 player_wait (&world); }
292 for (key = 0; key <= world.keyswindata->max; key++)
293 free(world.keybindings[key].name);
294 free(world.keybindings);
295 free(world.keyswindata);