-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerator.cpp
128 lines (112 loc) · 5.05 KB
/
generator.cpp
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "./generator.hpp"
#include <random>
// Simple terrain generator. I plan on making it a tool I can use in some side personal games. Still a work in progress
// though. Multistate
struct TerrainRuleset : CustomGridRuleset<Seeder> {
void apply(int currentCell, int *cellToUpdate, NeighboringCellStateCount &stateCount) override {
if (currentCell == State::DIRT && (stateCount[State::WATER] == 1 && stateCount[State::DIRT] > 4)) {
*cellToUpdate = State::GRASS;
} else if (currentCell == State::DIRT && (stateCount[State::GRASS] == 3 || stateCount[State::GRASS] == 4)) {
*cellToUpdate = State::GRASS;
} else if ((currentCell == State::DIRT || currentCell == State::GRASS) && stateCount[State::WATER] > 4) {
*cellToUpdate = State::WATER;
} else if ((currentCell == State::DIRT || currentCell == State::GRASS) && stateCount[State::WATER] == 1 &&
this->dependency->getDistributionOutput(*this->distribution) < 1) {
*cellToUpdate = State::WATER;
} else if (currentCell == State::WATER && stateCount[State::WATER] < 6 &&
stateCount[State::DIRT] + stateCount[State::GRASS] > 6 &&
this->dependency->getDistributionOutput(*this->distribution) < 5) {
*cellToUpdate = State::DIRT;
} else if (currentCell == State::DIRT && stateCount[State::STONE] >= 1 &&
this->dependency->getDistributionOutput(*this->distribution) < 3) {
*cellToUpdate = State::STONE;
} else {
*cellToUpdate = currentCell;
};
};
};
struct EnvironmentRuleset : CustomGridRuleset<Seeder> {
void apply(int currentCell, int *cellToUpdate, NeighboringCellStateCount &stateCount) override {
if (currentCell == State::GRASS && stateCount[State::GRASS] > 4) {
int outcome = this->dependency->getDistributionOutput(*this->distribution);
if (outcome < 10) {
*cellToUpdate = State::PLANT_TREE;
} else if (outcome > 10 && outcome < 20) {
*cellToUpdate = State::PLANT_BUSH;
} else if (outcome > 20 && outcome < 30) {
*cellToUpdate = State::PLANT_FLOWER;
} else {
*cellToUpdate = currentCell;
};
} else if (currentCell == State::STONE && stateCount[State::STONE] > 6 &&
this->dependency->getDistributionOutput(*this->distribution) < 20) {
*cellToUpdate = State::CRYSTAL;
} else {
*cellToUpdate = currentCell;
};
};
};
TerrainGenerator::TerrainGenerator() {
this->draw = nullptr;
this->setNeighborhoodPosition({{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}});
// Enum States - There is 8 states
for (int i = 0; i < 8; ++i) {
this->setState(i);
};
};
Grid TerrainGenerator::getGrid() {
return this->grid;
};
void TerrainGenerator::setGridDraw(void (*draw)(Grid &grid, int rows, int cols)) {
this->draw = draw;
};
void TerrainGenerator::seed(int num) {
this->seeder.setSeed(num);
};
int TerrainGenerator::seed() {
return this->seeder.setRandomSeed();
};
void TerrainGenerator::execute() {
this->prepopulate();
std::uniform_int_distribution<int> dist(0, 100);
for (int i = 0; i <= 500; ++i) {
if (this->draw != nullptr) {
this->draw(this->grid, this->grid.getRows(), this->grid.getCols());
};
if (i < 499) {
TerrainRuleset terrainRules;
terrainRules.inject(&this->seeder);
terrainRules.setDistribution(&dist);
// Pass #1 Terrain Generation
this->pass<Seeder>(terrainRules);
} else {
EnvironmentRuleset environmentRules;
environmentRules.inject(&this->seeder);
environmentRules.setDistribution(&dist);
// Do one step environment growth once the terrain has been generated.
// Pass #2 EnvironmentGeneration
this->pass<Seeder>(environmentRules);
};
};
};
void TerrainGenerator::prepopulate() {
std::uniform_int_distribution<int> rowDistRange = std::uniform_int_distribution<int>(0, this->grid.getRows());
std::uniform_int_distribution<int> colDistRange = std::uniform_int_distribution<int>(0, this->grid.getCols());
for (int i = 0; i <= 10; ++i) {
Position pos(this->seeder.getDistributionOutput(rowDistRange), this->seeder.getDistributionOutput(colDistRange));
if (pos.col > 1 && pos.col < this->grid.getCols() - 1 && pos.row > 1 && pos.row < this->grid.getRows() - 1) {
if (i < 6) {
this->grid.getContent()->at(pos.row).at(pos.col) = State::WATER;
this->grid.getContent()->at(pos.row).at(pos.col - 1) = State::WATER;
this->grid.getContent()->at(pos.row).at(pos.col + 1) = State::WATER;
this->grid.getContent()->at(pos.row - 1).at(pos.col - 1) = State::WATER;
this->grid.getContent()->at(pos.row - 1).at(pos.col + 1) = State::WATER;
this->grid.getContent()->at(pos.row + 1).at(pos.col - 1) = State::WATER;
this->grid.getContent()->at(pos.row + 1).at(pos.col + 1) = State::WATER;
} else {
this->grid.getContent()->at(pos.row).at(pos.col) = State::STONE;
this->grid.getContent()->at(pos.row).at(pos.col + 1) = State::STONE;
};
};
};
};