diff --git a/libopenage/pathfinding/cost_field.cpp b/libopenage/pathfinding/cost_field.cpp index 12889663eb..9850c45d13 100644 --- a/libopenage/pathfinding/cost_field.cpp +++ b/libopenage/pathfinding/cost_field.cpp @@ -14,9 +14,10 @@ namespace openage::path { CostField::CostField(size_t size) : size{size}, valid_until{time::TIME_MIN}, - cells(this->size * this->size, COST_MIN) { - log::log(DBG << "Created cost field with size " << this->size << "x" << this->size); -} + cells(this->size * this->size, COST_MIN), + cost_stamps(this->size * this->size, std::nullopt) { + log::log(DBG << "Created cost field with size " << this->size << "x" << this->size); + } size_t CostField::get_size() const { return this->size; @@ -56,6 +57,33 @@ void CostField::set_costs(std::vector &&cells, const time::time_t &valid this->valid_until = valid_until; } +bool CostField::stamp(size_t idx, cost_t cost, const time::time_t &stamped_at) { + if (this->cost_stamps[idx].has_value()) { + return false; + } + + cost_t original_cost = this->get_cost(idx); + this->cost_stamps[idx] = cost_stamp_t{ + original_cost, + stamped_at, + }; + + this->set_cost(idx, cost, stamped_at); + return true; +} + +bool CostField::unstamp(size_t idx, const time::time_t &unstamped_at) { + if (not this->cost_stamps[idx].has_value() or unstamped_at < this->cost_stamps[idx]->stamp_time) { + return false; + } + + cost_t original_cost = cost_stamps[idx]->original_cost; + + this->set_cost(idx, original_cost, unstamped_at); + this->cost_stamps[idx].reset(); + return true; +} + bool CostField::is_dirty(const time::time_t &time) const { return time >= this->valid_until; } diff --git a/libopenage/pathfinding/cost_field.h b/libopenage/pathfinding/cost_field.h index c03b494a84..eb72780076 100644 --- a/libopenage/pathfinding/cost_field.h +++ b/libopenage/pathfinding/cost_field.h @@ -4,6 +4,7 @@ #include #include +#include #include "pathfinding/types.h" #include "time/time.h" @@ -106,6 +107,27 @@ class CostField { */ void set_costs(std::vector &&cells, const time::time_t &changed); + /** + * Stamp a cost field cell at a given time. + * + * @param idx Index of the cell. + * @param cost Cost to set. + * @param stamped_at Time at which the cost cell is to be stamped. + * + * @return True if the cell was successfully stamped, false if the cell was already stamped. + */ + bool stamp(size_t idx, cost_t cost, const time::time_t &stamped_at); + + /** + * Unstamp a cost field cell at a given time. + * + * @param idx Index of the cell. + * @param unstamped_at Time at which the cost cell is to be unstamped. + * + * @return True if the cell was successfully unstamped, false if the cell was already not stamped. + */ + bool unstamp(size_t idx, const time::time_t &unstamped_at); + /** * Check if the cost field is dirty at the specified time. * @@ -135,6 +157,11 @@ class CostField { * Cost field values. */ std::vector cells; + + /** + * Cost stamp vector. + */ + std::vector> cost_stamps; }; } // namespace path diff --git a/libopenage/pathfinding/types.h b/libopenage/pathfinding/types.h index 3229010a91..86f7ad6d69 100644 --- a/libopenage/pathfinding/types.h +++ b/libopenage/pathfinding/types.h @@ -1,4 +1,4 @@ -// Copyright 2024-2024 the openage authors. See copying.md for legal info. +// Copyright 2024-2025 the openage authors. See copying.md for legal info. #pragma once @@ -7,6 +7,7 @@ #include #include +#include "time/time.h" namespace openage::path { @@ -124,4 +125,19 @@ using cache_key_t = std::pair; */ using field_cache_t = std::pair, std::shared_ptr>; +/** + * Cost stamp for a given cost field cell. + */ +struct cost_stamp_t { + /** + * Original cost of the stamped cell. + */ + cost_t original_cost; + + /** + * Time the cost field cell was stamped. + */ + time::time_t stamp_time; +}; + } // namespace openage::path