Skip to content
34 changes: 31 additions & 3 deletions libopenage/pathfinding/cost_field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -56,6 +57,33 @@ void CostField::set_costs(std::vector<cost_t> &&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;
}
Expand Down
27 changes: 27 additions & 0 deletions libopenage/pathfinding/cost_field.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <cstddef>
#include <vector>
#include <optional>

#include "pathfinding/types.h"
#include "time/time.h"
Expand Down Expand Up @@ -106,6 +107,27 @@ class CostField {
*/
void set_costs(std::vector<cost_t> &&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.
*
Expand Down Expand Up @@ -135,6 +157,11 @@ class CostField {
* Cost field values.
*/
std::vector<cost_t> cells;

/**
* Cost stamp vector.
*/
std::vector<std::optional<cost_stamp_t>> cost_stamps;
};

} // namespace path
Expand Down
18 changes: 17 additions & 1 deletion libopenage/pathfinding/types.h
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -7,6 +7,7 @@
#include <memory>
#include <utility>

#include "time/time.h"

namespace openage::path {

Expand Down Expand Up @@ -124,4 +125,19 @@ using cache_key_t = std::pair<portal_id_t, sector_id_t>;
*/
using field_cache_t = std::pair<std::shared_ptr<IntegrationField>, std::shared_ptr<FlowField>>;

/**
* 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
Loading