Skip to content

Commit ef90cea

Browse files
committed
gamestate: Add activity node type for branching on value.
1 parent 8c80dbd commit ef90cea

File tree

7 files changed

+218
-10
lines changed

7 files changed

+218
-10
lines changed

doc/code/game_simulation/activity.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,12 @@ you can use available [BPMN tools](https://bpmn.io/) to draw activity node graph
4848
## Node Types
4949

5050

51-
| Type | Inputs | Outputs | Description |
52-
| ---------------- | ------ | ------- | ------------------------- |
53-
| `START` | 0 | 1 | Start of activity |
54-
| `END` | 1 | 0 | End of activity |
55-
| `TASK_SYSTEM` | 1 | 1 | Run built-in system |
56-
| `TASK_CUSTOM` | 1 | 1 | Run custom function |
57-
| `XOR_EVENT_GATE` | 1 | 1+ | Wait for event and branch |
58-
| `XOR_GATE` | 1 | 1+ | Branch on condition |
51+
| Type | Inputs | Outputs | Description |
52+
| ----------------- | ------ | ------- | ------------------------- |
53+
| `START` | 0 | 1 | Start of activity |
54+
| `END` | 1 | 0 | End of activity |
55+
| `TASK_SYSTEM` | 1 | 1 | Run built-in system |
56+
| `TASK_CUSTOM` | 1 | 1 | Run custom function |
57+
| `XOR_EVENT_GATE` | 1 | 1+ | Wait for event and branch |
58+
| `XOR_GATE` | 1 | 1+ | Branch on condition |
59+
| `XOR_SWITCH_GATE` | 1 | 1+ | Branch on value |

libopenage/gamestate/activity/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_sources(libopenage
99
types.cpp
1010
xor_event_gate.cpp
1111
xor_gate.cpp
12+
xor_switch_gate.cpp
1213
)
1314

1415
add_subdirectory("event")

libopenage/gamestate/activity/types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ enum class node_t {
1313
END,
1414
XOR_EVENT_GATE,
1515
XOR_GATE,
16+
XOR_SWITCH_GATE,
1617
TASK_CUSTOM,
1718
TASK_SYSTEM,
1819
};

libopenage/gamestate/activity/xor_event_gate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class XorEventGate : public Node {
6161
* @param label Human-readable label (optional).
6262
*/
6363
XorEventGate(node_id_t id,
64-
node_label_t label = "EventGateWay");
64+
node_label_t label = "ExclusiveEventGateway");
6565

6666
/**
6767
* Create a new exclusive event gateway.

libopenage/gamestate/activity/xor_gate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace activity {
2424
/**
2525
* Function that determines if an output node is chosen.
2626
*
27-
* @param time Current game time.
27+
* @param time Current simulation time.
2828
* @param entity Entity that is executing the activity.
2929
*
3030
* @return true if the output node is chosen, false otherwise.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2024-2024 the openage authors. See copying.md for legal info.
2+
3+
#include "xor_switch_gate.h"
4+
5+
6+
namespace openage::gamestate::activity {
7+
8+
XorSwitchGate::XorSwitchGate(node_id_t id,
9+
node_label_t label) :
10+
Node{id, label} {}
11+
12+
XorSwitchGate::XorSwitchGate(node_id_t id,
13+
node_label_t label,
14+
const lookup_function_t &lookup_func,
15+
const lookup_dict_t &lookup_dict,
16+
const std::shared_ptr<Node> &default_node) :
17+
Node{id, label},
18+
lookup_func{lookup_func},
19+
lookup_dict{lookup_dict},
20+
default_node{default_node} {}
21+
22+
void XorSwitchGate::set_output(const std::shared_ptr<Node> &output,
23+
const lookup_key_t &key) {
24+
this->outputs.emplace(output->get_id(), output);
25+
this->lookup_dict.emplace(key, output);
26+
}
27+
28+
const XorSwitchGate::lookup_function_t &XorSwitchGate::get_lookup_func() const {
29+
return this->lookup_func;
30+
}
31+
32+
void XorSwitchGate::set_lookup_func(const lookup_function_t &lookup_func) {
33+
this->lookup_func = lookup_func;
34+
}
35+
36+
const XorSwitchGate::lookup_dict_t &XorSwitchGate::get_lookup_dict() const {
37+
return this->lookup_dict;
38+
}
39+
40+
const std::shared_ptr<Node> &XorSwitchGate::get_default() const {
41+
return this->default_node;
42+
}
43+
44+
void XorSwitchGate::set_default(const std::shared_ptr<Node> &node) {
45+
if (this->default_node != nullptr) {
46+
throw Error{MSG(err) << this->str() << " already has a default node"};
47+
}
48+
49+
this->outputs.emplace(node->get_id(), node);
50+
this->default_node = node;
51+
}
52+
53+
} // namespace openage::gamestate::activity
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Copyright 2024-2024 the openage authors. See copying.md for legal info.
2+
3+
#pragma once
4+
5+
#include <concepts>
6+
#include <functional>
7+
#include <memory>
8+
#include <string>
9+
#include <unordered_map>
10+
#include <vector>
11+
12+
#include "gamestate/activity/node.h"
13+
#include "gamestate/activity/types.h"
14+
#include "time/time.h"
15+
16+
17+
namespace openage::gamestate {
18+
class GameEntity;
19+
20+
namespace activity {
21+
22+
/**
23+
* Chooses one of its output nodes based on enum values.
24+
*
25+
* In comparison to the XOR gate, this node type does not tie individual
26+
* conditions to each node. Instead, it operates on a single function that
27+
* returns a key for a lookup dict. The lookup dict maps these keys to output
28+
* node ID.
29+
*
30+
* This type of gate is easier to use for simpler branch switches based on
31+
* similar conditions, e.g. a branching based on the value of an enum.
32+
*/
33+
class XorSwitchGate : public Node {
34+
public:
35+
/**
36+
* Type used as lookup key for the lookup dict.
37+
*/
38+
using lookup_key_t = int;
39+
40+
/**
41+
* Function that retrieves a lookup key for the lookup dict from
42+
* the current state of an entity.
43+
*
44+
* @param time Current simulation time.
45+
* @param entity Entity that is executing the activity.
46+
*
47+
* @return Lookup key.
48+
*/
49+
using lookup_function_t = std::function<lookup_key_t(const time::time_t &,
50+
const std::shared_ptr<gamestate::GameEntity> &)>;
51+
52+
/**
53+
* Lookup dict that maps lookup keys to output node IDs.
54+
*/
55+
using lookup_dict_t = std::unordered_map<lookup_key_t, std::shared_ptr<Node>>;
56+
57+
/**
58+
* Creates a new XOR switch gate node.
59+
*
60+
* @param id Unique identifier of the node.
61+
* @param label Human-readable label of the node (optional).
62+
*/
63+
XorSwitchGate(node_id_t id,
64+
node_label_t label = "ExclusiveSwitchGateway");
65+
66+
/**
67+
* Creates a new XOR switch gate node.
68+
*
69+
* @param id Unique identifier of the node.
70+
* @param label Human-readable label of the node.
71+
* @param lookup_func Function that looks up the key to the lookup dict.
72+
* @param lookup_dict Initial lookup dict that maps lookup keys to output node IDs.
73+
* @param default_node Default output node. Chosen if no lookup entry is defined.
74+
*/
75+
XorSwitchGate(node_id_t id,
76+
node_label_t label,
77+
const lookup_function_t &lookup_func,
78+
const lookup_dict_t &lookup_dict,
79+
const std::shared_ptr<Node> &default_node);
80+
81+
virtual ~XorSwitchGate() = default;
82+
83+
inline node_t get_type() const override {
84+
return node_t::XOR_SWITCH_GATE;
85+
}
86+
87+
/**
88+
* Set the output node for a given lookup key.
89+
*
90+
* @param output Output node.
91+
* @param key Enumeration value.
92+
*/
93+
void set_output(const std::shared_ptr<Node> &output,
94+
const lookup_key_t &key);
95+
96+
/**
97+
* Get the lookup function for determining the output nodes.
98+
*
99+
* @return Lookup function.
100+
*/
101+
const lookup_function_t &get_lookup_func() const;
102+
103+
/**
104+
* Set the lookup function for determining the output nodes.
105+
*
106+
* @param lookup_func Lookup function.
107+
*/
108+
void set_lookup_func(const lookup_function_t &lookup_func);
109+
110+
/**
111+
* Get the lookup dict for the output nodes.
112+
*
113+
* @return Lookup dict.
114+
*/
115+
const lookup_dict_t &get_lookup_dict() const;
116+
117+
/**
118+
* Get the default output node.
119+
*
120+
* @return Default output node.
121+
*/
122+
const std::shared_ptr<Node> &get_default() const;
123+
124+
/**
125+
* Set the the default output node.
126+
*
127+
* This node is chosen if the lookup dict does not contain an entry for the
128+
* lookup key returned by the lookup function.
129+
*
130+
* @param node Default output node.
131+
*/
132+
void set_default(const std::shared_ptr<Node> &node);
133+
134+
private:
135+
/**
136+
* Determines the lookup key for the lookup dict from the current state.
137+
*/
138+
lookup_function_t lookup_func;
139+
140+
/**
141+
* Maps lookup keys to output node IDs.
142+
*/
143+
lookup_dict_t lookup_dict;
144+
145+
/**
146+
* Default output node. Chosen if no lookup entry is defined.
147+
*/
148+
std::shared_ptr<Node> default_node;
149+
};
150+
151+
} // namespace activity
152+
} // namespace openage::gamestate

0 commit comments

Comments
 (0)