aboutsummaryrefslogtreecommitdiff
path: root/frontend/generate_dungeon.cpp
blob: 6393abb62d35b32794078fc7973d230c93a140f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <algorithm>
#include <memory>

#include "backend/Dungeon.h"
#include "backend/RNG.h"
#include "backend/print.h"
#include "backend/Exception.h"

#include "rl.h"
#include "generate_dungeon.h"
#include "GameData.h"

using namespace std;

static vector<Direction> shuffled_directions() {
	vector<Direction> out = { NORTH, EAST, SOUTH, WEST };
	shuffle(out.begin(), out.end(), RNG::get_engine());
	return out;
}

unique_ptr<Dungeon> generate_dungeon() {
	unique_ptr<Dungeon> dungeon = make_unique<Dungeon>();
	GameData & gd = GameData::get_instance();

	lprtf("Hoeveel locaties moet de kerker hebben?\n");
	unsigned location_count = 1;
	try {
		string filename = rl();
		location_count = stoul(filename);
	} catch (...) {
		throw Exception("geen geldig aantal ingevoerd");
	}
	if (location_count < 1)
		throw Exception("meer dan 1 locatie nodig");

	vector<string> locations = gd.random_locations(location_count);
	struct TempData {
		Location * location;
		int edges[4] = { -1, -1, -1, -1 };
	};
	vector<TempData> temp_map;
	temp_map.resize(location_count);

	size_t index = 0;
	RNG & rng = RNG::get();
	for (const string & name : locations) {
		Location * location = gd.create_location(name);

		if (index % 3 == 0) {
			location->add_enemy(gd.create_enemy(gd.random_enemy()));
		}

		for (const string & object : gd.random_objects(rng.rand_int(Range<int> { 0, 3 }))) {
			location->add_visible_object(gd.create_object(object));
		}

		for (const string & object : gd.random_objects(rng.rand_int(Range<int> { 0, 2 }))) {
			location->add_hidden_object(gd.create_object(object));
		}

		auto & temp = temp_map[index];
		temp.location = location;
		for (Direction direction : shuffled_directions()) {
			// skip over already connected edges
			if (temp.edges[direction] >= 0) continue;

			// find another random location that is NOT here
			int connection = rng.rand_int(location_count - 1);
			if (connection == index) connection++;

			// make a bidirectional connection
			temp.edges[direction] = connection;
			temp_map[temp.edges[direction]].edges[-direction] = index;

			if (rng.rand_double() < 0.8) break;
		}

		dungeon->add_location(location);
		index++;
	}

	for (auto & temp : temp_map) {
		for (Direction direction : DIRECTIONS) {
			unsigned id = temp.edges[direction];
			if (temp.edges[direction] < 0) continue;
			temp.location->set_exit(direction, temp_map[id].location);
		}
	}

	return dungeon;
}