-
-
Notifications
You must be signed in to change notification settings - Fork 991
/
game_end_exceptions.hpp
233 lines (189 loc) · 5.21 KB
/
game_end_exceptions.hpp
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
Copyright (C) 2006 - 2015 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
wesnoth playturn Copyright (C) 2003 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program 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 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file
* Contains the exception interfaces used to signal
* completion of a scenario, campaign or turn.
*/
#ifndef GAME_END_EXCEPTIONS_HPP_INCLUDED
#define GAME_END_EXCEPTIONS_HPP_INCLUDED
#include "lua_jailbreak_exception.hpp"
#include "config.hpp"
#include "make_enum.hpp"
#include <string>
#include <exception>
#include <boost/optional.hpp>
#include <boost/variant/variant.hpp>
MAKE_ENUM(LEVEL_RESULT,
(VICTORY, "victory")
(DEFEAT, "defeat")
(QUIT, "quit")
(OBSERVER_END, "observer_end")
)
MAKE_ENUM_STREAM_OPS1(LEVEL_RESULT)
/**
* Exception used to escape form the ai code in case of [end_turn].
*/
class ai_end_turn_exception
: public tlua_jailbreak_exception, public std::exception
{
public:
ai_end_turn_exception()
: tlua_jailbreak_exception()
, std::exception()
{
}
const char * what() const throw() { return "ai_end_turn_exception"; }
private:
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(ai_end_turn_exception)
};
/**
* Struct used to transmit info caught from an end_turn_exception.
*/
struct restart_turn_struct {
};
/**
* Exception used to signal the end of a player turn.
*/
class restart_turn_exception
: public tlua_jailbreak_exception, public std::exception
{
public:
restart_turn_exception()
: tlua_jailbreak_exception()
, std::exception()
{
}
const char * what() const throw() { return "restart_turn_exception"; }
restart_turn_struct to_struct()
{
return restart_turn_struct();
}
private:
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(restart_turn_exception)
};
/**
* Struct used to transmit info caught from an end_turn_exception.
*/
struct end_level_struct {
bool is_quit;
};
/**
* Exception used to signal the end of a scenario.
*/
class end_level_exception
: public tlua_jailbreak_exception
, public std::exception
{
public:
end_level_exception(bool isquit = false)
: tlua_jailbreak_exception()
, std::exception()
, is_quit(isquit)
{
}
bool is_quit;
end_level_struct to_struct() {
end_level_struct els = {is_quit};
return els;
}
const char * what() const throw() { return "end_level_exception"; }
private:
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(end_level_exception)
};
/**
* The two end_*_exceptions are caught and transformed to this signaling object
*/
typedef boost::optional<boost::variant<restart_turn_struct, end_level_struct> > possible_end_play_signal;
#define HANDLE_END_PLAY_SIGNAL( X )\
do\
{\
try {\
X;\
} catch (end_level_exception & e) {\
return possible_end_play_signal(e.to_struct());\
} catch (restart_turn_exception & e) {\
return possible_end_play_signal(e.to_struct());\
}\
}\
while(0)
#define PROPOGATE_END_PLAY_SIGNAL( X )\
do\
{\
possible_end_play_signal temp;\
temp = X;\
if (temp) {\
return temp;\
}\
}\
while(0)
#define HANDLE_AND_PROPOGATE_END_PLAY_SIGNAL( X )\
do\
{\
possible_end_play_signal temp;\
HANDLE_END_PLAY_SIGNAL( temp = X );\
if (temp) {\
return temp;\
}\
}\
while(0)
enum END_PLAY_SIGNAL_TYPE {END_TURN, END_LEVEL};
class get_signal_type : public boost::static_visitor<END_PLAY_SIGNAL_TYPE> {
public:
END_PLAY_SIGNAL_TYPE operator()(restart_turn_struct &) const
{
return END_TURN;
}
END_PLAY_SIGNAL_TYPE operator()(end_level_struct& ) const
{
return END_LEVEL;
}
};
/**
* The non-persistent part of end_level_data
*/
struct transient_end_level{
transient_end_level();
bool carryover_report; /**< Should a summary of the scenario outcome be displayed? */
bool linger_mode; /**< Should linger mode be invoked? */
std::string custom_endlevel_music; /**< Custom short music played at the end. */
bool reveal_map; /**< Should we reveal map when game is ended? (Multiplayer only) */
};
/**
* Additional information on the game outcome which can be provided by WML.
*/
struct end_level_data
{
end_level_data();
bool prescenario_save; /**< Should a prescenario be created the next game? */
bool replay_save; /**< Should a replay save be made? */
bool proceed_to_next_level; /**< whether to proceed to the next scenario, equals (res == VICTORY) in sp. We need to save this in saves during linger mode. > */
transient_end_level transient;
bool is_victory;
void write(config& cfg) const;
void read(const config& cfg);
config to_config() const
{
config r;
write(r);
return r;
}
};
inline void throw_quit_game_exception()
{
// Distinguish 'Quit' from 'Regular' end_level_exceptions to solve the following problem:
// If a player quits the game during an event after an [endlevel] occurs, the game won't
// Quit but continue with the [endlevel] instead.
throw end_level_exception(true);
}
#endif /* ! GAME_END_EXCEPTIONS_HPP_INCLUDED */