Skip to content
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

Configurable Activities #1609

Merged
merged 44 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
78bebc5
convert: Load nyan data API v0.4.1.
heinezen Dec 4, 2023
b7e693a
convert: Basic activity for units.
heinezen Dec 7, 2023
b62266d
convert: Export new API version as modpack.
heinezen Dec 10, 2023
33a53f3
convert: Activity ability.
heinezen Dec 10, 2023
884a15f
gamestate: Docstrings for activity.
heinezen Dec 17, 2023
33ced29
gamestate: API interface for nyan activities.
heinezen Dec 17, 2023
943e67a
gamestate: Create activity from nyan data.
heinezen Dec 17, 2023
eba3c96
gamestate: Rename activity node files.
heinezen Dec 18, 2023
a9e7d44
gamestate: Refactor XorGate to use one condition per node.
heinezen Dec 18, 2023
c586d7f
gamestate: Adjust activity demo for new condition.
heinezen Dec 18, 2023
c960ab8
gamestate: Remove old condition functionality.
heinezen Dec 18, 2023
b381dc5
gamestate: Refactor XorEventGate to use one event primer per node.
heinezen Dec 18, 2023
7de149d
gamestate: Adjust activity demo for new event primers.
heinezen Dec 19, 2023
6118211
gamestate: Use new event priming functionality.
heinezen Dec 19, 2023
26d04bb
gamestate: Remove unused functions.
heinezen Dec 19, 2023
64dfb07
gamestate: Add breakout event to default actvity graph.
heinezen Dec 19, 2023
7e9dbd1
gamestate: Predefined activity event functions.
heinezen Dec 20, 2023
3027ce9
gamestate: Get event primer from API definition.
heinezen Dec 20, 2023
ca4f15e
gamestate: Create connections between nodes in activity graph.
heinezen Dec 20, 2023
24d83c0
gamestate: Set default node separately from other outputs.
heinezen Dec 23, 2023
a07f7d2
refactor: Move event primers into activity subfolders.
heinezen Dec 23, 2023
7c12205
gamestate: Add built-in condition functions to activity system.
heinezen Dec 23, 2023
831a4f8
gamestate: Use built-in condition for example activity.
heinezen Dec 23, 2023
97460f0
gamestate: Fix command not returned by reference.
heinezen Dec 23, 2023
8db9807
gamestate: Detect condition from API objects.
heinezen Dec 24, 2023
31018e3
gamestate: Detect system task from API objects.
heinezen Dec 24, 2023
53ece80
gamestate: Fix reading from nyan activity condition API object.
heinezen Dec 24, 2023
537830a
gamestate: Fix wrong member ID lookup.
heinezen Dec 24, 2023
30a6234
gamestate: Fix lookup of activity conditions/events.
heinezen Dec 24, 2023
bc1f82d
curve: Fix queue behaviour when popping elements.
heinezen Dec 24, 2023
c269a67
convert: Fix game entity activity not idling after move.
heinezen Dec 24, 2023
c2244c4
convert: Import aliases for nyan API activities.
heinezen Dec 24, 2023
d035829
convert: Warn when alias cannot be added to import tree.
heinezen Dec 24, 2023
c31e861
doc: Replace activity example in docs with current default activity.
heinezen Dec 24, 2023
737e2b2
gamestate: Cache created activities.
heinezen Dec 24, 2023
2457ed8
gamestate: Make command queue getter non-const.
heinezen Dec 25, 2023
ab12e98
time: Constants for min, max, zero.
heinezen Dec 25, 2023
26b2f97
curve: Replace time numeric limit with constants.
heinezen Dec 25, 2023
6f0117b
event: Replace time numeric limit with constants.
heinezen Dec 25, 2023
1f54b5d
pong: Replace time numeric limit with constants.
heinezen Dec 25, 2023
0e7178f
gamestate: Replace time numeric limit with constants.
heinezen Dec 25, 2023
73b97d4
curve: Search queue from the end instead from begin.
heinezen Dec 25, 2023
6d41917
gamestate: Remove unused variable.
heinezen Dec 25, 2023
ec381df
convert: Clarify modpack version/versionstr difference.
heinezen Jan 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/code/game_simulation/images/activity_graph.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions libopenage/curve/base_curve.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class BaseCurve : public event::EventEntity {
* the keyframes of \p other.
*/
void sync(const BaseCurve<T> &other,
const time::time_t &start = std::numeric_limits<time::time_t>::min());
const time::time_t &start = time::TIME_MIN);

/**
* Copy keyframes from another curve (with a different element type) to this curve.
Expand All @@ -134,7 +134,7 @@ class BaseCurve : public event::EventEntity {
template <typename O>
void sync(const BaseCurve<O> &other,
const std::function<T(const O &)> &converter,
const time::time_t &start = std::numeric_limits<time::time_t>::min());
const time::time_t &start = time::TIME_MIN);

/**
* Get the identifier of this curve.
Expand Down Expand Up @@ -270,7 +270,7 @@ std::string BaseCurve<T>::str() const {

template <typename T>
void BaseCurve<T>::check_integrity() const {
time::time_t last_time = std::numeric_limits<time::time_t>::min();
time::time_t last_time = time::TIME_MIN;
for (const auto &keyframe : this->container) {
if (keyframe.time < last_time) {
throw Error{MSG(err) << "curve is broken after t=" << last_time << ": " << this->str()};
Expand Down
4 changes: 2 additions & 2 deletions libopenage/curve/iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class CurveIterator {
explicit CurveIterator(const container_t *c) :
base{},
container{c},
from{-std::numeric_limits<time::time_t>::max()},
to{+std::numeric_limits<time::time_t>::max()} {}
from{-time::TIME_MAX},
to{+time::TIME_MAX} {}

protected:
/**
Expand Down
2 changes: 1 addition & 1 deletion libopenage/curve/keyframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Keyframe {
time{time},
value{value} {}

const time::time_t time = std::numeric_limits<time::time_t>::min();
const time::time_t time = time::TIME_MIN;
T value = T{};
};

Expand Down
8 changes: 4 additions & 4 deletions libopenage/curve/keyframe_container.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ class KeyframeContainer {
* the keyframes of \p other.
*/
iterator sync(const KeyframeContainer<T> &other,
const time::time_t &start = std::numeric_limits<time::time_t>::min());
const time::time_t &start = time::TIME_MIN);

/**
* Copy keyframes from another container (with a different element type) to this container.
Expand All @@ -298,7 +298,7 @@ class KeyframeContainer {
template <typename O>
iterator sync(const KeyframeContainer<O> &other,
const std::function<T(const O &)> &converter,
const time::time_t &start = std::numeric_limits<time::time_t>::min());
const time::time_t &start = time::TIME_MIN);

/**
* Debugging method to be used from gdb to understand bugs better.
Expand Down Expand Up @@ -328,15 +328,15 @@ template <typename T>
KeyframeContainer<T>::KeyframeContainer() {
// Create a default element at -Inf, that can always be dereferenced - so
// there will by definition never be a element that cannot be dereferenced
this->container.push_back(keyframe_t(std::numeric_limits<time::time_t>::min(), T()));
this->container.push_back(keyframe_t(time::TIME_MIN, T()));
}


template <typename T>
KeyframeContainer<T>::KeyframeContainer(const T &defaultval) {
// Create a default element at -Inf, that can always be dereferenced - so
// there will by definition never be a element that cannot be dereferenced
this->container.push_back(keyframe_t(std::numeric_limits<time::time_t>::min(), defaultval));
this->container.push_back(keyframe_t(time::TIME_MIN, defaultval));
}


Expand Down
12 changes: 6 additions & 6 deletions libopenage/curve/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ class UnorderedMap {
at(const time::time_t &, const key_t &) const;

MapFilterIterator<key_t, val_t, UnorderedMap>
begin(const time::time_t &e = std::numeric_limits<time::time_t>::max()) const;
begin(const time::time_t &e = time::TIME_MAX) const;

MapFilterIterator<key_t, val_t, UnorderedMap>
end(const time::time_t &e = std::numeric_limits<time::time_t>::max()) const;
end(const time::time_t &e = time::TIME_MAX) const;

MapFilterIterator<key_t, val_t, UnorderedMap>
insert(const time::time_t &birth, const key_t &, const val_t &);
Expand Down Expand Up @@ -100,7 +100,7 @@ UnorderedMap<key_t, val_t>::at(const time::time_t &time,
e,
this,
time,
std::numeric_limits<time::time_t>::max());
time::TIME_MAX);
}
else {
return {};
Expand All @@ -114,7 +114,7 @@ UnorderedMap<key_t, val_t>::begin(const time::time_t &time) const {
this->container.begin(),
this,
time,
std::numeric_limits<time::time_t>::max());
time::TIME_MAX);
}

template <typename key_t, typename val_t>
Expand All @@ -123,7 +123,7 @@ UnorderedMap<key_t, val_t>::end(const time::time_t &time) const {
return MapFilterIterator<key_t, val_t, UnorderedMap<key_t, val_t>>(
this->container.end(),
this,
-std::numeric_limits<time::time_t>::max(),
-time::TIME_MAX,
time);
}

Expand All @@ -149,7 +149,7 @@ UnorderedMap<key_t, val_t>::insert(const time::time_t &alive,
const val_t &value) {
return this->insert(
alive,
std::numeric_limits<time::time_t>::max(),
time::TIME_MAX,
key,
value);
}
Expand Down
97 changes: 72 additions & 25 deletions libopenage/curve/queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class Queue : public event::EventEntity {
EventEntity{loop},
_id{id},
_idstr{idstr},
last_front{this->container.begin()} {}
last_pop{time::TIME_ZERO} {}

// prevent accidental copy of queue
Queue(const Queue &) = delete;
Expand All @@ -69,12 +69,13 @@ class Queue : public event::EventEntity {
const T &front(const time::time_t &time) const;

/**
* Get the first element in the queue at the given time.
* Get the first element in the queue at the given time and remove it from
* the queue.
*
* @param time The time to get the element at.
* @param value Queue element.
*/
const T &pop_front(const time::time_t &time);
const T pop_front(const time::time_t &time);

/**
* Check if the queue is empty at a given time.
Expand All @@ -92,7 +93,7 @@ class Queue : public event::EventEntity {
* @return Iterator to the first element.
*/
QueueFilterIterator<T, Queue<T>> begin(
const time::time_t &t = -std::numeric_limits<time::time_t>::max()) const;
const time::time_t &t = -time::TIME_MAX) const;

/**
* Get an iterator to the last element in the queue at the given time.
Expand All @@ -101,7 +102,7 @@ class Queue : public event::EventEntity {
* @return Iterator to the last element.
*/
QueueFilterIterator<T, Queue<T>> end(
const time::time_t &t = std::numeric_limits<time::time_t>::max()) const;
const time::time_t &t = time::TIME_MAX) const;

/**
* Get an iterator to elements that are in the queue between two time frames.
Expand All @@ -111,8 +112,8 @@ class Queue : public event::EventEntity {
* @return Iterator to the first element in the time frame.
*/
QueueFilterIterator<T, Queue<T>> between(
const time::time_t &begin = std::numeric_limits<time::time_t>::max(),
const time::time_t &end = std::numeric_limits<time::time_t>::max()) const;
const time::time_t &begin = time::TIME_MAX,
const time::time_t &end = time::TIME_MAX) const;

/**
* Erase an element from the queue.
Expand Down Expand Up @@ -183,24 +184,72 @@ class Queue : public event::EventEntity {
*/
container_t container;

iterator last_front;
/**
* The time of the last access to the queue.
*/
time::time_t last_pop;
};


template <typename T>
const T &Queue<T>::front(const time::time_t &t) const {
return this->begin(t).value();
const T &Queue<T>::front(const time::time_t &time) const {
if (this->empty(time)) [[unlikely]] {
throw Error{MSG(err) << "Tried accessing front at "
<< time << " but queue is empty."};
}

// search for the last element before the given time
auto it = this->container.end();
--it;
while (it->time() > time and it != this->container.begin()) {
--it;
}

return it->value;
}

template <class T>
bool Queue<T>::empty(const time::time_t &time) const {
return this->last_front == this->begin(time).get_base();
const T Queue<T>::pop_front(const time::time_t &time) {
if (this->empty(time)) [[unlikely]] {
throw Error{MSG(err) << "Tried accessing front at "
<< time << " but queue is empty."};
}

// search for the last element before the given time
auto it = this->container.end();
--it;
while (it->time() > time and it != this->container.begin()) {
--it;
}

// get the last element inserted before the given time
auto val = std::move(it->value);

// get the time span between current time and the next element
auto to = (++it)->time();
--it;
auto from = time;

// erase the element
// TODO: We should be able to reinsert elements
auto filter_iterator = QueueFilterIterator<T, Queue<T>>(it, this, to, from);
this->erase(filter_iterator);

this->last_pop = time;

return val;
}

template <class T>
inline const T &Queue<T>::pop_front(const time::time_t &time) {
this->last_front = this->begin(time).get_base();
return this->front(time);
bool Queue<T>::empty(const time::time_t &time) const {
if (this->container.empty()) {
return true;
}

// search for the first element that is after the given time
auto begin = this->begin(time).get_base();

return begin == this->container.begin() and begin->time() > time;
}

template <typename T>
Expand All @@ -211,7 +260,7 @@ QueueFilterIterator<T, Queue<T>> Queue<T>::begin(const time::time_t &t) const {
it,
this,
t,
std::numeric_limits<time::time_t>::max());
time::TIME_MAX);
}
}

Expand All @@ -225,20 +274,19 @@ QueueFilterIterator<T, Queue<T>> Queue<T>::end(const time::time_t &t) const {
container.end(),
this,
t,
std::numeric_limits<time::time_t>::max());
time::TIME_MAX);
}


template <typename T>
QueueFilterIterator<T, Queue<T>> Queue<T>::between(
const time::time_t &begin,
const time::time_t &end) const {
QueueFilterIterator<T, Queue<T>> Queue<T>::between(const time::time_t &begin,
const time::time_t &end) const {
auto it = QueueFilterIterator<T, Queue<T>>(
container.begin(),
this,
begin,
end);
if (!container.empty() && !it.valid()) {
if (not it.valid()) {
++it;
}
return it;
Expand All @@ -253,9 +301,8 @@ void Queue<T>::erase(const CurveIterator<T, Queue<T>> &it) {


template <typename T>
QueueFilterIterator<T, Queue<T>> Queue<T>::insert(
const time::time_t &time,
const T &e) {
QueueFilterIterator<T, Queue<T>> Queue<T>::insert(const time::time_t &time,
const T &e) {
const_iterator insertion_point = this->container.end();
for (auto it = this->container.begin(); it != this->container.end(); ++it) {
if (time < it->time()) {
Expand All @@ -272,7 +319,7 @@ QueueFilterIterator<T, Queue<T>> Queue<T>::insert(
insertion_point,
this,
time,
std::numeric_limits<time::time_t>::max());
time::TIME_MAX);

if (!ct.valid()) {
++ct;
Expand Down
40 changes: 39 additions & 1 deletion libopenage/curve/tests/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,25 @@ void test_queue() {
auto loop = std::make_shared<event::EventLoop>();

Queue<int> q{loop, 0};
q.insert(0, 1);

TESTEQUALS(q.empty(0), true);
TESTEQUALS(q.empty(1), true);
TESTEQUALS(q.empty(100001), true);

q.insert(2, 2);
q.insert(4, 3);
q.insert(10, 4);
q.insert(100001, 5);
q.insert(100001, 6);

TESTEQUALS(q.empty(0), true);
TESTEQUALS(q.empty(1), true);
TESTEQUALS(q.empty(2), false);
TESTEQUALS(q.empty(100001), false);
TESTEQUALS(q.empty(100002), false);

q.insert(0, 1);

TESTEQUALS(*q.begin(0), 1);
TESTEQUALS(*q.begin(1), 2);
TESTEQUALS(*q.begin(2), 2);
Expand All @@ -164,6 +178,17 @@ void test_queue() {
TESTEQUALS(*q.begin(12), 5);
TESTEQUALS(*q.begin(100000), 5);

TESTEQUALS(q.front(0), 1);
TESTEQUALS(q.front(1), 1);
TESTEQUALS(q.front(2), 2);
TESTEQUALS(q.front(3), 2);
TESTEQUALS(q.front(4), 3);
TESTEQUALS(q.front(5), 3);
TESTEQUALS(q.front(10), 4);
TESTEQUALS(q.front(12), 4);
TESTEQUALS(q.front(100000), 4);
TESTEQUALS(q.front(100001), 6);

{
std::unordered_set<int> reference = {1, 2, 3};
for (auto it = q.between(0, 6); it != q.end(); ++it) {
Expand Down Expand Up @@ -204,6 +229,19 @@ void test_queue() {
}
TESTEQUALS(reference.empty(), true);
}


TESTEQUALS(q.pop_front(0), 1);
TESTEQUALS(q.empty(0), true);

TESTEQUALS(q.pop_front(12), 4);
TESTEQUALS(q.empty(12), false);

TESTEQUALS(q.pop_front(12), 3);
TESTEQUALS(q.empty(12), false);

TESTEQUALS(q.pop_front(12), 2);
TESTEQUALS(q.empty(12), true);
}


Expand Down
Loading