home · contact · privacy
Use stdint.h typedefs for ints.
[plomrogue] / roguelike.c
1 #include <stdlib.h>
2 #include <stdint.h>
3 #include <ncurses.h>
4 #include <string.h>
5 #include "windows.h"
6 #include "draw_wins.h"
7 #include "roguelike.h"
8 #include "keybindings.h"
9
10 void toggle_window (struct WinMeta * win_meta, struct Win * win) {
11 // Toggle display of window win.
12   if (0 != win->curses)
13     suspend_window(win_meta, win);
14   else
15     append_window(win_meta, win); }
16
17 void growshrink_active_window (struct WinMeta * win_meta, char change) {
18 // Grow or shrink active window horizontally or vertically by one cell size.
19   if (0 != win_meta->active) {
20     uint16_t height = win_meta->active->height;
21     uint16_t width = win_meta->active->width;
22     if      (change == '-')
23       height--;
24     else if (change == '+')
25       height++;
26     else if (change == '_')
27       width--;
28     else if (change == '*')
29       width++;
30     resize_active_window (win_meta, height, width); } }
31
32 struct Map init_map () {
33 // Initialize map with some experimental start values.
34   struct Map map;
35   map.width = 96;
36   map.height = 32;
37   map.offset_x = 0;
38   map.offset_y = 0;
39   map.cells = malloc(map.width * map.height);
40   uint16_t x, y, ran;
41   char terrain;
42   for (y = 0; y < map.height; y++)
43     for (x = 0; x < map.width; x++) {
44       terrain = '.';
45       ran = rand();
46       if (   0 == ran % ((x*x) / 3 + 1)
47           || 0 == ran % ((y*y) / 3 + 1)
48           || 0 == ran % ((map.width - x - 1) * (map.width - x - 1) / 3 + 1)
49           || 0 == ran %((map.height - y - 1) * (map.height - y - 1) / 3 + 1))
50         terrain = ' ';
51       map.cells[(y * map.width) + x] = terrain; }
52   return map; }
53
54 void map_scroll (struct Map * map, char dir) {
55 // Scroll map into direction dir if possible by changing the offset.
56   if      ('n' == dir && map->offset_y > 0)
57     map->offset_y--;
58   else if ('s' == dir)
59     map->offset_y++;
60   else if ('w' == dir && map->offset_x > 0)
61     map->offset_x--;
62   else if ('e' == dir)
63     map->offset_x++; }
64
65 void next_turn (struct World * world) {
66 // Increment turn and move enemy.
67   world->turn++;
68   char d = rand() % 5;
69   char ty = world->monster->y;
70   char tx = world->monster->x;
71   if (1 == d)
72     ty++;
73   else if (2 == d)
74     ty--;
75   else if (3 == d)
76     tx++;
77   else if (4 == d)
78     tx--;
79   if (tx == world->player->x && ty == world->player->y)
80     update_log(world, "\nThe monster hits you.");
81   else if (is_passable(world, tx, ty)) {
82     world->monster->y = ty;
83     world->monster->x = tx; } }
84
85 void update_log (struct World * world, char * text) {
86 // Update log with new text to be appended.
87   char * new_text;
88   uint16_t len_old = strlen(world->log);
89   uint16_t len_new = strlen(text);
90   uint16_t len_whole = len_old + len_new + 1;
91   new_text = calloc(len_whole, sizeof(char));
92   memcpy(new_text, world->log, len_old);
93   memcpy(new_text + len_old, text, len_new);
94   free(world->log);
95   world->log = new_text; }
96
97 char is_passable (struct World * world, uint16_t x, uint16_t y) {
98 // Check if coordinate on (or beyond) map is accessible to movement.
99   char passable = 0;
100   if (0 <= x && x < world->map->width && 0 <= y && y < world->map->height)
101     if ('.' == world->map->cells[y * world->map->width + x])
102       passable = 1;
103   return passable; }
104
105 void move_player (struct World * world, char d) {
106 // Move player in direction d, increment turn counter and update log.
107   static char prev = 0;
108   char success = 0;
109   char * dir;
110   char ty = world->player->y;
111   char tx = world->player->x;
112   if ('s' == d) {
113     dir = "south";
114     ty++; }
115   if ('n' == d) {
116     dir = "north";
117     ty--; }
118   if ('w' == d) {
119     dir = "west";
120     tx--; }
121   if ('e' == d) {
122     dir = "east";
123     tx++; }
124   if (ty == world->monster->y && tx == world->monster->x)
125     success = 2;
126   else if (is_passable(world, tx, ty)) {
127     success = 1;
128     world->player->y = ty;
129     world->player->x = tx; }
130   if (success * d == prev)
131     update_log (world, ".");
132   else {
133     if (2 == success)
134       update_log (world, "\nYou hit the monster.");
135     else {
136       char * msg = calloc(25, sizeof(char));
137       char * msg_content = "You fail to move";
138       if (1 == success)
139         msg_content = "You move";
140       sprintf(msg, "\n%s %s.", msg_content, dir);
141       update_log (world, msg);
142       free(msg); } }
143   prev = success * d;
144   next_turn (world); }
145
146 void player_wait(struct World * world) {
147 // Make player wait one turn.
148   next_turn (world);
149   update_log (world, "\nYou wait."); }
150
151 int main () {
152   struct World world;
153   init_keybindings(&world);
154   world.turn = 0;
155   world.log = calloc(1, sizeof(char));
156   update_log (&world, "Start!");
157   struct Map map = init_map();
158   world.map = &map;
159   struct Player player;
160   player.y = 16;
161   player.x = 16;
162   world.player = &player;
163   struct Monster monster;
164   monster.y = 16;
165   monster.x = 80;
166   world.monster = &monster;
167
168   WINDOW * screen = initscr();
169   noecho();
170   curs_set(0);
171   keypad(screen, TRUE);
172   raw();
173   struct WinMeta win_meta = init_win_meta(screen);
174   struct Win win_keys = init_window(&win_meta, "Keys", &world, draw_keys_win);
175   struct Win win_map = init_window(&win_meta, "Map", &world, draw_map_win);
176   struct Win win_info = init_window(&win_meta, "Info", &world, draw_info_win);
177   struct Win win_log = init_window(&win_meta, "Log", &world, draw_log_win);
178
179   int key;
180   while (1) {
181     draw_all_windows (&win_meta);
182     key = getch();
183     if      (key == get_action_key(world.keybindings, "quit"))
184       break;
185     else if (key == get_action_key(world.keybindings, "scroll pad right"))
186       scroll_pad (&win_meta, '+');
187     else if (key == get_action_key(world.keybindings, "scroll pad left"))
188       scroll_pad (&win_meta, '-');
189     else if (key == get_action_key(world.keybindings, "toggle keys window"))
190       toggle_window(&win_meta, &win_keys);
191     else if (key == get_action_key(world.keybindings, "toggle map window"))
192       toggle_window(&win_meta, &win_map);
193     else if (key == get_action_key(world.keybindings, "toggle info window"))
194       toggle_window(&win_meta, &win_info);
195     else if (key == get_action_key(world.keybindings, "toggle log window"))
196       toggle_window(&win_meta, &win_log);
197     else if (key == get_action_key(world.keybindings, "cycle forwards"))
198       cycle_active_window(&win_meta, 'n');
199     else if (key == get_action_key(world.keybindings, "cycle backwards"))
200       cycle_active_window(&win_meta, 'p');
201     else if (key == get_action_key(world.keybindings, "shift forwards"))
202       shift_active_window(&win_meta, 'f');
203     else if (key == get_action_key(world.keybindings, "shift backwards"))
204       shift_active_window(&win_meta, 'b');
205     else if (key == get_action_key(world.keybindings, "grow horizontally"))
206       growshrink_active_window(&win_meta, '*');
207     else if (key == get_action_key(world.keybindings, "shrink horizontally"))
208       growshrink_active_window(&win_meta, '_');
209     else if (key == get_action_key(world.keybindings, "grow vertically"))
210       growshrink_active_window(&win_meta, '+');
211     else if (key == get_action_key(world.keybindings, "shrink vertically"))
212       growshrink_active_window(&win_meta, '-');
213     else if (key == get_action_key(world.keybindings, "save keys"))
214       save_keybindings(&world);
215     else if (key == get_action_key(world.keybindings, "keys nav up"))
216       keyswin_move_selection (&world, 'u');
217     else if (key == get_action_key(world.keybindings, "keys nav down"))
218       keyswin_move_selection (&world, 'd');
219     else if (key == get_action_key(world.keybindings, "keys mod"))
220       keyswin_mod_key (&world, &win_meta);
221     else if (key == get_action_key(world.keybindings, "map up"))
222       map_scroll (&map, 'n');
223     else if (key == get_action_key(world.keybindings, "map down"))
224       map_scroll (&map, 's');
225     else if (key == get_action_key(world.keybindings, "map right"))
226       map_scroll (&map, 'e');
227     else if (key == get_action_key(world.keybindings, "map left"))
228       map_scroll (&map, 'w');
229     else if (key == get_action_key(world.keybindings, "player down"))
230       move_player(&world, 's');
231     else if (key == get_action_key(world.keybindings, "player up"))
232       move_player(&world, 'n');
233     else if (key == get_action_key(world.keybindings, "player right"))
234       move_player(&world, 'e');
235     else if (key == get_action_key(world.keybindings, "player left"))
236       move_player(&world, 'w');
237     else if (key == get_action_key(world.keybindings, "wait") )
238       player_wait (&world); }
239
240   free(map.cells);
241   for (key = 0; key <= world.keyswindata->max; key++)
242     free(world.keybindings[key].name);
243   free(world.keybindings);
244   free(world.keyswindata);
245   free(world.log);
246
247   endwin();
248   return 0; }