/*
This file is part of urlg.
urlg is free software: you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version. urlg is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details. You should have
received a copy of the GNU General Public License along with urlg. If not, see
.
*/
#include
#include
#include
#include
#include
#include "../config.h"
#include "cavegen.h"
#include "common.h"
#include "display.h"
#include "entity.h"
#include "ht.h"
bool entity_set_pos(struct entity *e, struct point p, struct map *map)
{
if (e->solid) {
if (p.y < 0 || p.x < 0 || p.y >= map->height || p.x >= map->width) {
return false;
}
if (map->map[p.y * map->width + p.x] == WALL) {
return false;
}
}
e->p = p;
return true;
}
bool game_update(
display_t *disp, enum action action, ht_t *entities, struct map *map
)
{
struct entity *player = ht_find(entities, "player");
struct entity *camera = ht_find(entities, "camera");
struct point newp = player->p;
struct point newp_cam = camera->p;
switch (action) {
case ACTION_EXIT : return true;
case ACTION_UP :
--newp.y;
--newp_cam.y;
display_message(disp, "moving up");
break;
case ACTION_DOWN :
++newp.y;
++newp_cam.y;
display_message(disp, "moving down");
break;
case ACTION_LEFT :
--newp.x;
--newp_cam.x;
display_message(disp, "moving left");
break;
case ACTION_RIGHT :
++newp.x;
++newp_cam.x;
display_message(disp, "moving right");
break;
case ACTION_STAIR_DOWN :
if (map->map[player->p.y * map->width + player->p.x] == DOWN_STAIR) {
free(map->map);
create_cave(map);
newp = map->entry_point;
newp_cam.x = map->entry_point.x - MAIN_PANEL_WIDTH / 2 + 1;
newp_cam.y = map->entry_point.y - MAIN_PANEL_HEIGHT / 2 + 1;
display_message(disp, "moving down stairs");
} else {
display_message(disp, "no stairs to go down");
}
break;
case ACTION_STAIR_UP :
if (map->map[player->p.y * WIDTH + player->p.x] == UP_STAIR) {
display_message(disp, "moving up stairs");
return true;
} else {
display_message(disp, "no stairs to go up");
}
break;
default : display_message(disp, "unrecognized command"); break;
}
if (entity_set_pos(player, newp, map))
entity_set_pos(camera, newp_cam, map);
return false;
}
void print_version(void)
{
printf("%s\n", PACKAGE_STRING);
printf("Copyright (C) 2024 Jacob Janzen\n");
printf("This is free software; see the source for copying conditions.\n");
printf(
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
);
printf("PARTICULAR PURPOSE.\n");
}
int main(int argc, char **argv)
{
int option_index = 0;
int ch;
int version_flag = 0;
struct option longopts[] = {
{"version", no_argument, &version_flag, 'v'},
};
while ((ch = getopt_long(argc, argv, ":v", longopts, &option_index)) != -1
) {
switch (ch) {
case 'v' : version_flag = 1; break;
case 0 : break;
default : break;
}
}
if (version_flag) {
print_version();
return EXIT_SUCCESS;
}
unsigned int seed = time(NULL);
srand(seed);
display_t *disp = display_init();
if (!disp) {
return EXIT_FAILURE;
}
// create the map
struct map map;
create_cave(&map);
// create the entity map
ht_t *entities = ht_create(1);
// create the camera
struct entity camera;
camera.disp_ch = " ";
camera.solid = false;
camera.visible = false;
ht_insert(entities, "camera", &camera);
// create the player
struct entity player;
player.disp_ch = "@";
player.solid = true;
player.visible = true;
ht_insert(entities, "player", &player);
// set starting point
struct point cam_p = {
.x = map.entry_point.x - MAIN_PANEL_WIDTH / 2 + 1,
.y = map.entry_point.y - MAIN_PANEL_HEIGHT / 2 + 1,
};
entity_set_pos(&player, map.entry_point, &map);
entity_set_pos(&camera, cam_p, &map);
// start displaying things
display_map(disp, &map, entities);
display_instructions(disp);
display_status(disp, &player);
display_message(disp, "");
bool done = false;
while (!done) {
enum action action = display_process_input();
done = game_update(disp, action, entities, &map);
display_map(disp, &map, entities);
}
free(map.map);
ht_destroy(entities);
display_destroy(disp);
endwin();
return 0;
}