Skip to content
Snippets Groups Projects
Commit 1e1f2358 authored by Jake Feddersen's avatar Jake Feddersen
Browse files

Finish splitting up code

parent fbe98337
No related branches found
No related tags found
No related merge requests found
#ifndef DISTANCE_MAP_H
#define DISTANCE_MAP_H
#include <limits.h>
#include "heap.h"
#include "dungeon.h"
typedef struct dijkstra_path {
heap_node_t *hn;
uint8_t pos[2];
int32_t cost;
} dijkstra_path_t;
static int32_t dijkstra_path_cmp(const void *key, const void *with) {
return ((dijkstra_path_t *) key)->cost - ((dijkstra_path_t *) with)->cost;
}
/**
* Dijkstra's Algorithm - Find the shortest paths in the dungeon to the player position
* hardness_limit - the smallest hardness value that the monsters cannot pass through
*
* Algorithm is modified from Dr. Sheaffer's Dijkstra code using his provided heap.
*/
static void dijkstra_from_player(dungeon_t *d, uint32_t dist[MAP_HEIGHT][MAP_WIDTH], int hardness_limit)
{
// Initialize the vairables
static dijkstra_path_t path[MAP_HEIGHT][MAP_WIDTH], *p;
static uint32_t initialized = 0;
heap_t h;
uint32_t x, y;
// Initialize the positions of each path node
if (!initialized) {
for (y = 0; y < MAP_HEIGHT; y++) {
for (x = 0; x < MAP_WIDTH; x++) {
path[y][x].pos[0] = y;
path[y][x].pos[1] = x;
}
}
initialized = 1;
}
// Initialize the path cost for each node
for (y = 0; y < MAP_HEIGHT; y++) {
for (x = 0; x < MAP_WIDTH; x++) {
path[y][x].cost = INT_MAX;
}
}
// The player position gets cost 0
path[d->player_pos.y][d->player_pos.x].cost = 0;
// Initialize the heap
heap_init(&h, dijkstra_path_cmp, NULL);
// Initialize all of the heap pointers
// Also initialize the distance map
for (y = 0; y < MAP_HEIGHT; y++) {
for (x = 0; x < MAP_WIDTH; x++) {
dist[y][x] = INT_MAX;
if (d->hardness[y][x] < hardness_limit) {
path[y][x].hn = heap_insert(&h, &path[y][x]);
} else {
path[y][x].hn = NULL;
}
}
}
// Main Dijkstra's Algorithm implementation
while ((p = heap_remove_min(&h))) {
// Visit the current node, and set its distance
p->hn = NULL;
dist[p->pos[0]][p->pos[1]] = p->cost;
// If this node is at infinity distance, don't visit its neighbors; it is disconnected
if (p->cost == INT_MAX) {
continue;
}
// Iterate through all neighbors
for (y = p->pos[0] - 1; y < p->pos[0] + 2; y++) {
for (x = p->pos[1] - 1; x < p->pos[1] + 2; x++) {
if (y == p->pos[0] && x == p->pos[1]) continue;
if ((path[y][x].hn) && (path[y][x].cost > p->cost + 1 + (d->hardness[p->pos[0]][p->pos[1]] / 85))) {
path[y][x].cost = p->cost + 1 + (d->hardness[p->pos[0]][p->pos[1]] / 85);
heap_decrease_key_no_replace(&h, path[y][x].hn);
}
}
}
}
}
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include "dungeon.h"
#include "draw_dungeon.h"
#include "distance_map.h"
#include "save_load.h"
#include "heap.h"
#include "util.h"
typedef struct dijkstra_path {
heap_node_t *hn;
uint8_t pos[2];
int32_t cost;
} dijkstra_path_t;
static int32_t dijkstra_path_cmp(const void *key, const void *with) {
return ((dijkstra_path_t *) key)->cost - ((dijkstra_path_t *) with)->cost;
}
/**
* Dijkstra's Algorithm - Find the shortest paths in the dungeon to the player position
* hardness_limit - the smallest hardness value that the monsters cannot pass through
*
* Algorithm is modified from Dr. Sheaffer's Dijkstra code using his provided heap.
*/
static void dijkstra_from_player(dungeon_t *d, uint32_t dist[MAP_HEIGHT][MAP_WIDTH], int hardness_limit);
int main(int argc, char* argv[]) {
int i;
int load = 0;
int save = 0;
args_t args;
parse_args(argc, argv, &args);
if (args.dbg) {
print_args(&args);
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--save")) {
save = 1;
}
if (!strcmp(argv[i], "--load")) {
load = 1;
}
}
srand(time(NULL));
srand(args.seed);
dungeon_t d;
if (load) {
if (args.load) {
load_dungeon(&d);
} else {
gen_random_dungeon(&d);
}
if (save) {
if (args.save) {
save_dungeon(&d);
}
......@@ -73,74 +45,3 @@ int main(int argc, char* argv[]) {
free_dungeon(&d);
}
static void dijkstra_from_player(dungeon_t *d, uint32_t dist[MAP_HEIGHT][MAP_WIDTH], int hardness_limit)
{
// Initialize the vairables
static dijkstra_path_t path[MAP_HEIGHT][MAP_WIDTH], *p;
static uint32_t initialized = 0;
heap_t h;
uint32_t x, y;
// Initialize the positions of each path node
if (!initialized) {
for (y = 0; y < MAP_HEIGHT; y++) {
for (x = 0; x < MAP_WIDTH; x++) {
path[y][x].pos[0] = y;
path[y][x].pos[1] = x;
}
}
initialized = 1;
}
// Initialize the path cost for each node
for (y = 0; y < MAP_HEIGHT; y++) {
for (x = 0; x < MAP_WIDTH; x++) {
path[y][x].cost = INT_MAX;
}
}
// The player position gets cost 0
path[d->player_pos.y][d->player_pos.x].cost = 0;
// Initialize the heap
heap_init(&h, dijkstra_path_cmp, NULL);
// Initialize all of the heap pointers
// Also initialize the distance map
for (y = 0; y < MAP_HEIGHT; y++) {
for (x = 0; x < MAP_WIDTH; x++) {
dist[y][x] = INT_MAX;
if (d->hardness[y][x] < hardness_limit) {
path[y][x].hn = heap_insert(&h, &path[y][x]);
} else {
path[y][x].hn = NULL;
}
}
}
// Main Dijkstra's Algorithm implementation
while ((p = heap_remove_min(&h))) {
// Visit the current node, and set its distance
p->hn = NULL;
dist[p->pos[0]][p->pos[1]] = p->cost;
// If this node is at infinity distance, don't visit its neighbors; it is disconnected
if (p->cost == INT_MAX) {
continue;
}
// Iterate through all neighbors
for (y = p->pos[0] - 1; y < p->pos[0] + 2; y++) {
for (x = p->pos[1] - 1; x < p->pos[1] + 2; x++) {
if (y == p->pos[0] && x == p->pos[1]) continue;
if ((path[y][x].hn) && (path[y][x].cost > p->cost + 1 + (d->hardness[p->pos[0]][p->pos[1]] / 85))) {
path[y][x].cost = p->cost + 1 + (d->hardness[p->pos[0]][p->pos[1]] / 85);
heap_decrease_key_no_replace(&h, path[y][x].hn);
}
}
}
}
}
......@@ -52,12 +52,25 @@ void parse_args(int argc, char *argv[], args_t *args) {
}
} else if (!strcmp(argv[i], "--dbg")) {
args->dbg = 1;
} else if (!strcmp(argv[i], "-h")) {
valid = 0;
} else {
valid = 0;
}
}
if (!valid) {
fprintf(stderr, "Usage: %s [--load --save --dbg --seed=<seed> --nummon=<number of monsters>]\n", argv[0]);
fprintf(stderr, "Usage: %s [--load --save --dbg --seed=<seed> --nummon=<monsters to spawn>]\n", argv[0]);
fprintf(stderr, " --load: \tInstead of generating a random dungeon, loads the saved dungeon\n\t\tfile from ~/.rlg327/dungeon\n");
fprintf(stderr, " --save: \tSaves the dungeon to ~/.rlg327/dungeon\n");
fprintf(stderr, " --seed: \tSeeds the random number generator to the given value. If not\n\t\tspecified, time(NULL) is used as the seed\n");
fprintf(stderr, " --nummon:\tSets the number of monsters to generate in the dungeon. If not\n\t\tspecified, the default is 10. Automatically capped at the number\n\t\tof empty spaces in the dungeon\n");
fprintf(stderr, " --dbg: \tEnables debug output\n");
fprintf(stderr, " -h: \tPrints this help information and exits\n");
exit(1);
}
}
void print_args(args_t *args) {
printf("Program Arguments:\n\tLoad: %d\n\tSave: %d\n\tSeed: %d\n\tMonsters: %d\n", args->load, args->save, args->seed, args->nummon);
}
......@@ -38,4 +38,6 @@ typedef struct {
*/
void parse_args(int argc, char *argv[], args_t *args);
void print_args(args_t *args);
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment