File: Test.h

package info (click to toggle)
endless-sky 0.10.16-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 414,608 kB
  • sloc: cpp: 73,435; python: 893; xml: 666; sh: 271; makefile: 28
file content (141 lines) | stat: -rw-r--r-- 4,410 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* Test.h
Copyright (c) 2019-2020 by Peter van der Meer

Endless Sky is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later version.

Endless Sky is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include "../Command.h"
#include "../ConditionAssignments.h"
#include "../ConditionSet.h"

#include <SDL2/SDL.h>

#include <map>
#include <set>
#include <string>
#include <vector>

class DataNode;
class Planet;
class PlayerInfo;
class System;
class TestContext;
class UI;



// Class representing a single test.
class Test {
public:
	// Status indicators for the test that we selected (if any).
	enum class Status {ACTIVE, PARTIAL, BROKEN, KNOWN_FAILURE, MISSING_FEATURE};

	// A tag type to denote a failing test that is not an error, such as a
	// "known failure" test failing.
	struct known_failure_tag {};


public:
	// Class representing a single step in a test
	class TestStep {
	public:
		// The different types of teststeps.
		enum class Type {
			// Step that assigns a value to a condition. Does not cause the game to step.
			APPLY,
			// Step that verifies if a certain condition is true. Does not cause the game to step.
			ASSERT,
			// Branch with a label to jump to when the condition in child is true.
			// When a second label is given, then the second is to jump to on false.
			// Does not cause the game to step, except when no step was done since last BRANCH or GOTO.
			BRANCH,
			// Step that calls another test to handle some generic common actions.
			CALL,
			// Step that prints a debug-message to the output.
			DEBUG,
			// Step that adds game-data, either in the config-directories or in the game directly.
			INJECT,
			// Step that performs input (key, mouse, command). Does cause the game to step (to process the inputs).
			INPUT,
			// Label to jump to (similar as is done in conversations). Does not cause the game to step.
			LABEL,
			// Instructs the game to set navigation / travel plan to a target system
			NAVIGATE,
		};



	public:
		explicit TestStep(Type stepType);
		void LoadInput(const DataNode &node);


	public:
		Type stepType = Type::ASSERT;
		std::string nameOrLabel;
		// Variables for travelpan/navigate steps.
		std::vector<const System *> travelPlan;
		const Planet *travelDestination = nullptr;
		// For applying condition changes.
		ConditionAssignments assignConditions;
		// For branching based on conditions or checking asserts (similar to Conversations).
		ConditionSet checkConditions;
		// Labels to jump to in case of branches. We could optimize during
		// load to look up the step numbers (and provide integer step numbers
		// here), but we can also use the textual information during error/
		// debug printing, so keeping the strings for now.
		std::string jumpOnTrueTarget;
		std::string jumpOnFalseTarget;

		// Input variables.
		Command command;
		std::set<std::string> inputKeys;
		Uint16 modKeys = 0;

		// Mouse/Pointer input variables.
		int XValue = 0;
		int YValue = 0;
		bool clickLeft = false;
		bool clickMiddle = false;
		bool clickRight = false;
	};


public:
	const std::string &Name() const;
	Status GetStatus() const;
	const std::string &StatusText() const;
	std::set<std::string> RelevantConditions() const;

	// Check the game status and perform the next test action.
	void Step(TestContext &context, PlayerInfo &player, Command &commandToGive) const;

	void Load(const DataNode &node, const ConditionsStore *playerConditions);


private:
	void LoadSequence(const DataNode &node, const ConditionsStore *playerConditions);

	// Fail the test using the given message as reason.
	void Fail(const TestContext &context, const PlayerInfo &player, const std::string &testFailReason) const;
	void UnexpectedSuccessResult() const;


private:
	std::string name;
	Status status = Status::ACTIVE;
	// Jump-table that specifies which labels map to which teststeps.
	std::map<std::string, unsigned int> jumpTable;
	std::vector<TestStep> steps;
};