4 #include <stdlib.h> /* for atoi(), exit(), EXIT_FAILURE, calloc() */
5 #include <stdio.h> /* for FILE typedef, F_OK */
6 #include <ncurses.h> /* for initscr(), noecho(), curs_set(), keypad(), raw() */
7 #include <time.h> /* for time() */
8 #include <unistd.h> /* for getopt(), optarg */
9 #include "windows.h" /* for structs WinMeta, Win, init_win(), init_win_meta(),
12 #include "draw_wins.h" /* for draw_keys_win(), draw_map_win(), draw_info_win(),
15 #include "keybindings.h" /* for initkeybindings(), get_action_key() */
16 #include "readwrite.h" /* for read_uint16_bigendian, read_uint32_bigendian,
17 * write_uint32_bigendian
19 #include "map_objects.h" /* for structs Monster, Item, Player,
20 * init_map_object_defs(), read_map_objects(),
23 #include "map_object_actions.h" /* for player_wait(), move_player() */
24 #include "map.h" /* for struct Map, init_map() */
25 #include "misc.h" /* for update_log(), toggle_window(), exit_game(),
26 * find_passable_pos(), meta_keys(), save_game()
28 #include "yx_uint16.h" /* for dir enum */
29 #include "rrand.h" /* for rrand(), rrand_seed() */
31 int main(int argc, char *argv[])
35 /* Read in startup options (i.e. replay option and replay start turn). */
38 world.interactive = 1;
39 while ((opt = getopt(argc, argv, "s::")) != -1)
44 world.interactive = 0;
47 start_turn = atoi(optarg);
54 /* Initialize log, player, monster/item definitions and monsters/items. */
55 world.log = calloc(1, sizeof(char));
56 update_log (&world, " ");
59 world.player = &player;
62 init_map_object_defs(&world, "defs");
64 /* For interactive mode, try to load world state from savefile. */
66 if (1 == world.interactive && 0 == access("savefile", F_OK))
68 file = fopen("savefile", "r");
69 world.seed = read_uint32_bigendian(file);
70 world.turn = read_uint32_bigendian(file);
71 player.pos.y = read_uint16_bigendian(file) - 1;
72 player.pos.x = read_uint16_bigendian(file) - 1;
73 player.hitpoints = fgetc(file);
74 read_map_objects(&world, &world.monster, file);
75 read_map_objects(&world, &world.item, file);
79 /* For non-interactive mode, try to load world state from record file. */
83 if (0 == world.interactive)
85 file = fopen("record", "r");
86 world.seed = read_uint32_bigendian(file);
89 /* For interactive-mode in newly started world, generate a start seed
90 * from the current time.
94 file = fopen("record", "w");
95 world.seed = time(NULL);
96 write_uint32_bigendian(world.seed, file);
101 /* Generate map from seed and, if newly generated world, start positions of
104 rrand_seed(world.seed);
105 struct Map map = init_map();
109 player.pos = find_passable_pos(&map);
111 foo = build_map_objects(&world, &world.monster, 1, 1 + rrand() % 27);
112 foo = build_map_objects(&world, foo, 2, 1 + rrand() % 9);
113 build_map_objects(&world, foo, 3, 1 + rrand() % 3);
114 foo = build_map_objects(&world, &world.item, 4, 1 + rrand() % 3);
115 build_map_objects(&world, foo, 5, 1 + rrand() % 3);
118 /* Initialize window system and windows. */
119 WINDOW * screen = initscr();
122 keypad(screen, TRUE);
124 init_keybindings(&world);
125 struct WinMeta win_meta = init_win_meta(screen);
126 struct Win win_keys = init_win(&win_meta, "Keys", 0, 29, &world, draw_keys_win);
127 struct Win win_info = init_win(&win_meta, "Info", 2, 20, &world, draw_info_win);
128 uint16_t height_logwin = win_meta.padframe.size.y - (2 + win_info.frame.size.y);
129 struct Win win_log = init_win(&win_meta, "Log",
130 height_logwin, 20, &world, draw_log_win);
131 uint16_t width_mapwin = win_meta.padframe.size.x - win_keys.frame.size.x
132 - win_log.frame.size.x - 2;
133 struct Win win_map = init_win(&win_meta, "Map",
134 0, width_mapwin, &world, draw_map_win);
135 toggle_window(&win_meta, &win_keys);
136 toggle_window(&win_meta, &win_map);
137 toggle_window(&win_meta, &win_info);
138 toggle_window(&win_meta, &win_log);
142 unsigned char quit_called = 0;
143 unsigned char await_actions = 1;
144 if (0 == world.interactive)
149 if (start_turn == world.turn)
155 draw_all_wins (&win_meta);
158 if (1 == await_actions
159 && (world.turn < start_turn
160 || key == get_action_key(world.keybindings,
161 "wait / next turn")) )
169 else if (0 == action)
171 player_wait (&world);
173 else if (NORTH == action)
175 move_player(&world, NORTH);
177 else if (EAST == action)
179 move_player(&world, EAST);
181 else if (SOUTH == action)
183 move_player(&world, SOUTH);
185 else if (WEST == action)
187 move_player(&world, WEST);
192 quit_called = meta_keys(key, &world, &win_meta, &win_keys,
193 &win_map, &win_info, &win_log);
194 if (1 == quit_called)
196 exit_game(&world, &map);
202 /* Interactive mode. */
205 uint32_t last_turn = 0;
208 if (last_turn != world.turn)
211 last_turn = world.turn;
213 if (1 == await_actions && 0 == player.hitpoints)
217 draw_all_wins (&win_meta);
219 if (1 == await_actions
220 && key == get_action_key(world.keybindings,
223 move_player(&world, NORTH);
225 else if (1 == await_actions
226 && key == get_action_key(world.keybindings,
229 move_player(&world, EAST);
231 else if (1 == await_actions
232 && key == get_action_key(world.keybindings,
235 move_player(&world, SOUTH);
237 else if (1 == await_actions
238 && key == get_action_key(world.keybindings,
241 move_player(&world, WEST);
243 else if (1 == await_actions
244 && key == get_action_key(world.keybindings,
247 player_wait (&world);
251 quit_called = meta_keys(key, &world, &win_meta, &win_keys,
252 &win_map, &win_info, &win_log);
253 if (1 == quit_called)
255 exit_game(&world, &map);