Skip to content

Pathfinder history #1748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open

Conversation

jere8184
Copy link
Contributor

@jere8184 jere8184 commented Jan 26, 2025

fixes: #1680

/**
* Array curve recording cell cost history,
*/
curve::Array<cost_t, CHUNK_SIZE> cell_cost_history;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should cell_cost_history be exposed? A simple getter that returns a constant ref to the curve?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that would be enough I think.

Copy link
Member

@heinezen heinezen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the long wait, I was very busy with work 😅 Now that I have some time, I added a few suggestions to the code.

Comment on lines 110 to 128
void set_insert_range(const time::time_t &t, auto begin_it, auto end_it) {
ENSURE(std::distance(begin_it, end_it) <= Size,
"trying to insert more values than there are postions: max allowed = " << Size);
index_t i = 0;
std::for_each(begin_it, end_it, [&](const T &val) { this->set_insert(t, i++, val); });
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea. Would it also make sense to make index configurable? Then we could even replace slices of the array.

@@ -105,6 +106,14 @@ class Array : event::EventEntity {
*/
std::pair<time::time_t, T> next_frame(const time::time_t &t, const index_t index) const;


void set_insert_range(const time::time_t &t, auto begin_it, auto end_it) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, would be nice if the method gets documented :)

}

bool CostField::stamp(size_t idx, cost_t cost, const time::time_t &stamped_at) {
if (this->cost_stamps[idx].has_value()) return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please always make if clauses multi-line for consistent code style.

Suggested change
if (this->cost_stamps[idx].has_value()) return false;
if (this->cost_stamps[idx].has_value()) {
return false;
}

}

bool CostField::unstamp(size_t idx, const time::time_t &unstamped_at) {
if (!this->cost_stamps[idx].has_value() || unstamped_at < this->cost_stamps[idx]->stamp_time) return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here and not/and/or should be used as operators for better readability.

Suggested change
if (!this->cost_stamps[idx].has_value() || unstamped_at < this->cost_stamps[idx]->stamp_time) return false;
if (not this->cost_stamps[idx].has_value() or unstamped_at < this->cost_stamps[idx]->stamp_time) {
return false;
}

@@ -14,6 +16,8 @@ namespace coord {
struct tile_delta;
} // namespace coord

const unsigned int CHUNK_SIZE = 100;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value should probably not be hardcoded because then the cost field size is not configurable anymore. I think we either need to make CostField a templated class or wait for the implementation of curve::Vector in #1677 . Both approaches would have pros and cons.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which way do you think we should go?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do templates first then

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alot of classes contain a cost_field, plus cost_field itself is constructed with a size_t, should we also templatise the encapsulating classes and get rid of the constructor parameter?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I think that's a good idea. I don't remember the size ever changing and see no reason why it would change.

Copy link
Contributor Author

@jere8184 jere8184 May 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good, didnt mean to request another review btw

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sry I couldn't help but take a look 😅

/**
* Array curve recording cell cost history,
*/
curve::Array<cost_t, CHUNK_SIZE> cell_cost_history;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that would be enough I think.

Comment on lines 128 to 134
/**
* Cost stamp for a given cost field cell.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A small explanation of stamping for people who don't know what that is would be nice here. I added a suggesion below.

Suggested change
/**
* Cost stamp for a given cost field cell.
*/
/**
* Cost stamp for a cell on a cost field.
*
* Stamps are used when cell costs are temporarily overwritten, e.g. when placing a game object
* as an obstacle over terrain. Once the obstacle is removed, the cell can be reset to its original
* value recorded by the stamp.
*/

@heinezen heinezen added the area: simulation Involved in the game mechanics and simulation label Apr 8, 2025
@heinezen heinezen added improvement Enhancement of an existing component lang: c++ Done in C++ code labels Apr 8, 2025
@heinezen heinezen moved this from 📋 Backlog to 👀 In review in openage game simulation Apr 8, 2025
@jere8184 jere8184 force-pushed the pathfinder_history branch from 63c919d to b390440 Compare May 25, 2025 18:08
@jere8184 jere8184 requested a review from heinezen May 25, 2025 19:22
Comment on lines +46 to +47
Array(const std::shared_ptr<event::EventLoop> &loop = nullptr,
size_t id = 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a good idea, since it will lead to errors when the curve is used for events without initializing the loop.

@@ -135,7 +168,111 @@ class CostField {
* Cost field values.
*/
std::vector<cost_t> cells;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can now also be an array of size N.

/**
* Cost stamp vector.
*/
std::vector<std::optional<cost_stamp_t>> cost_stamps;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

};

template <size_t N>
CostField<N>::CostField(size_t size) :
size{size},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

size is no longer necessary due to templating

@@ -19,6 +28,8 @@ namespace path {
/**
* Cost field in the flow-field pathfinding algorithm.
*/

template <size_t N>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should actually use N for more than curve::Array. Otherwise you have a mismatch, e.g. of the size of cells and cell_cost_history.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also N should be side length like size passed to the constructor. If you don't do this, then this allows non-square fields which would break pathfinding.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make more sense to have a curve::Vector here than an Array? size is not a compile time constant in Grid/Sector.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WillemKauf That's what my comment in #1748 (comment) is related to ^^

@@ -32,7 +32,7 @@ void path_demo_0(const util::Path &path) {
auto field_length = 10;

// Cost field with some obstacles
auto cost_field = std::make_shared<CostField>(field_length);
auto cost_field = std::make_shared<CostField<100>>(field_length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should define this size as a constant somewhere in the header file.

@@ -203,7 +203,7 @@ void RenderManager0::run() {
this->window->close();
}

void RenderManager0::show_cost_field(const std::shared_ptr<path::CostField> &field) {
void RenderManager0::show_cost_field(const std::shared_ptr<path::CostField<100>> &field) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use constant from header file here

@@ -551,7 +551,7 @@ void RenderManager0::init_passes() {
renderer->get_display_target());
}

renderer::resources::MeshData RenderManager0::get_cost_field_mesh(const std::shared_ptr<CostField> &field,
renderer::resources::MeshData RenderManager0::get_cost_field_mesh(const std::shared_ptr<CostField<100>> &field,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use constant from header file here

@@ -37,7 +37,7 @@ const integrated_t &IntegrationField::get_cell(size_t idx) const {
return this->cells.at(idx);
}

std::vector<size_t> IntegrationField::integrate_los(const std::shared_ptr<CostField> &cost_field,
std::vector<size_t> IntegrationField::integrate_los(const std::shared_ptr<CostField<100>> &cost_field,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing it like this will result in IntegrationField only being compatible with cost fields of size 100. This would not only make the pathfinder less flexible, it also defeats the point of templating CostField. If you template the size of cost field, you must template the size of IntegrationField (and FlowField, Sector, etc.) as well!

@github-project-automation github-project-automation bot moved this from 👀 In review to 🔖 TODO in openage game simulation May 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: simulation Involved in the game mechanics and simulation improvement Enhancement of an existing component lang: c++ Done in C++ code
Projects
Status: 🔖 TODO
Development

Successfully merging this pull request may close these issues.

Record history of cost changes in pathfinder
4 participants