-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMagic-Mirror.cpp
More file actions
359 lines (297 loc) · 11.7 KB
/
Magic-Mirror.cpp
File metadata and controls
359 lines (297 loc) · 11.7 KB
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
// Comments in /**/ are fluff and may be skipped. Comments in // are game rules. Comments in //! TODO: are tasks you have to do
/* The Magic Kingdom was a place of prosperity and happiness, until one day the Magic Mirror was stolen! Today only
* Ruins are left, and below them, the Dungeon. It is said, that the Magic Mirror is at the very bottom, protected by
* Monsters and the Wicked Curse. You live in a Town nearby, working as a Monkey of Coding. One day you walk past the
* Ruins and find a curious Black Key: */
#include <cassert>
#include <iostream>
#include <stdexcept>
#include <type_traits>
namespace Ruins {
struct Black_Key {};
} // namespace Ruins
/* As you pick up the key you have a vision of delving down the Dungeon, fighting Monsters at compile time and at
* runtime. You will return the Magic Mirror! But just being near the Wicked Curse saps your strength. */
// You are not allowed to use compiler flags such as -Dprivate=public to remove the challenge.
namespace Town {
struct Blacksmith;
} // namespace Town
namespace Ruins {
struct Dire_Wolf;
}
class Spider_Den;
/* You know the entrance to the ruins is guarded by a Dire Wolf, so you will need a weapon. */
class Inventory {
friend struct Town::Blacksmith;
friend struct Layer;
class Money {
friend struct Layer;
Money() {}
};
};
namespace Town {
struct Blacksmith {
struct Back_Entrance {};
private:
struct Storage_Key {};
struct Master_Sword {};
struct Training_Sword {};
struct Wooden_Shield {};
friend struct Ruins::Dire_Wolf;
friend class ::Spider_Den;
public:
static Master_Sword buy_Master_Sword(Inventory::Money) {
return {};
}
static Training_Sword steal_Training_Sword(Back_Entrance) {
return {};
}
static Wooden_Shield steal_Wooden_Shield(Storage_Key) {
return {};
}
};
} // namespace Town
/* Too bad you don't have any Money to buy that Master Sword, but the Back Entrance is unlocked, so you can sneak in the
* back and steal the Training Sword! */
//! TODO: Define a variable named training_sword of type Town::Blacksmith::Training_Sword inside main
/* You will also need a shield. You know the Blacksmith keeps one under a Trap Door, but that is locked and you don't
* have the key. Can you pick the lock? */
//! TODO: Define a variable named wooden_shield of type Town::Blacksmith::Wooden_Shield inside main
/* With the Training Sword you can go fight off the Dire Wolf guarding the
* Entrance to the Ruins */
class Necromancer;
namespace Ruins {
struct Dire_Wolf {
private:
struct Ruin_Entrance {};
public:
static void slay_wolf(int, int);
static Ruin_Entrance slay_wolf(Town::Blacksmith::Training_Sword, Town::Blacksmith::Wooden_Shield) {
return {};
}
friend class ::Necromancer;
};
} // namespace Ruins
//! TODO: Define a variable named ruin_entrance of type Ruins::Dire_Wolf::Ruin_Entrance inside main using variable
//! training_sword from above
/* After slaying the wolf easy enough, you enter the Ruins. Inside you see a Necromancer, wearing the Key of Life. You
* know you cannot beat the Necromancer. But maybe you can trick him. Mimic his evil magic so he believes that you are a
* fellow Necromancer and just take it! */
class Foul_Magic {};
class Necromancer : Foul_Magic {
friend class Thiefs;
class Key_of_Life {
Key_of_Life() {}
friend Necromancer;
};
public:
auto take(Foul_Magic *foul_magic, Ruins::Dire_Wolf::Ruin_Entrance) {
if (not foul_magic or foul_magic != this) {
throw std::runtime_error{"You are not a real Necromancer!"};
}
return Key_of_Life{};
}
};
//! TODO: Define a variable named necromancer_key of type Necromancer::Key_of_Life inside main.
/* After taking the Key of Life you go towards the Dungeon. But before you can enter, you find yourself surrounded by a
* group of Thieves. "We are here on orders of the Thieves Guild. Our spies report that you have a talent for magically
* getting through locks." They continue "You were commissioned to produce a Skeleton Key that works on any lock. Also
* we will be taking that Key of Life." They explain that you are not forced to comply and are free to choose death
* instead. You think it might be better to do it. */
class Thiefs {
class Secret_Location {
struct Unknown_Key {};
class Treasure {
struct Coins {
Coins(Coins &&) = default;
private:
Coins() {}
Coins(const Coins &) = delete;
friend class Treasure;
} coins;
Treasure() {}
friend class Thiefs;
friend class Thiefs_Shop;
};
static Treasure rob(Unknown_Key) {
return {};
}
friend class Thiefs;
friend class Thiefs_Shop;
};
friend class Thiefs_Shop;
public:
template <class Skeleton_Key>
static auto comply(Necromancer::Key_of_Life, Skeleton_Key key) {
auto treasure = Secret_Location::rob(key);
return std::move(treasure.coins);
}
};
//! TODO: Define a variable named coins of type Thiefs::Secret_Location::Treasure::Coins inside main.
/* That worked out well! Have some Coins as your reward. Let nobody say the Thieves Guild does not pay its employees.
* We'll keep the rest safe. Since this worked so well, let's rob the Mages Guild! They are not so easy though. We tried
* to use the Skeleton Key and it failed. But we learned that there are 2 checks made by the Lock: A Physical Check that
* we already know to beat, and a Magical Check that defies our thief's tools. We ... convinced ... one of the mages to
* give us a hand in breaking the Seal. Unfortunately we don't know how to apply it. That's where you come in. Of course
* the Seal Breaker is not free, it'll cost you ... */
class Mages_Guild {
class Seal_Breaker {
Seal_Breaker() {}
friend class Thiefs_Shop;
// friend Mages_Tower;
};
struct Physical_Check {};
struct Magic_Check {
Magic_Check(Seal_Breaker) {}
};
struct Artefact {};
static Artefact access(Physical_Check, Magic_Check) {
return {};
}
friend class Thiefs_Shop;
friend struct Layer;
};
class Thiefs_Shop {
public:
static Mages_Guild::Seal_Breaker buy(Thiefs::Secret_Location::Treasure::Coins &&coins) {
(void)coins; /* gone is your money */
return {};
}
template <class Seal_Breaker_Key>
static auto rob_Mages_Guild(Seal_Breaker_Key key) {
return Mages_Guild::access(key, key);
}
};
/* The thief gives you a last hint:
* "Before he die... I mean left us, the mage said you need some Seal Force Incantation Night Arcane Enchantment on the
* key. No idea what that means." */
//! TODO: Define a variable named Artefact of type Mages_Guild::Artefact inside main.
/* "What a waste!" the Thief exclaims. "This thing does nothing. You can have it. I'm done with you!" You take the
* Artefact and venture forth into the Dungeon.
* As you explore the Dungeon, find 2 corridors, each containing a real Dragon! You can see that each Dragon guards a
* key and you can almost reach it, but Magic keeps preventing you from reaching them. You must find a way to break
* through! */
struct Adamantite_Dragon_Layer {
friend struct Layer;
private:
class Adamantite_Key {
Adamantite_Key() {}
friend Adamantite_Dragon_Layer::Adamantite_Key break_magic();
};
Adamantite_Dragon_Layer() = delete;
friend Adamantite_Key break_magic() {
return {};
}
};
//! TODO: Define a variable named adamantite_key of type Adamantite_Dragon_Layer::Adamantite_Key inside main.
class Magic {
friend struct Amethyst_Dragon_Layer;
friend struct Layer;
class Amethyst_Key {
Amethyst_Key() {}
friend Magic::Amethyst_Key break_magic(void *);
};
};
struct Amethyst_Dragon_Layer final {
private:
Amethyst_Dragon_Layer() = delete;
friend Magic::Amethyst_Key break_magic(void *) {
return {};
}
};
//! TODO: Define a variable named amethyst_key of type Magic::Amethyst_Key inside main.
/* Now that you have obtained all the keys, it is time to claim your price! You can now go back to the Blacksmith in
* Town and buy the Master Sword! */
struct Layer {
static Inventory::Money loot_the_layer(Mages_Guild::Artefact, Adamantite_Dragon_Layer::Adamantite_Key,
Magic::Amethyst_Key) {
return {};
}
};
/* Using the Master Sword you push on. On your way you see a curious object. It seems like a piece of wood, but when you
* look a second time it's a leaf, and after deliberately looking away and back it's a rock. At least you think it is,
* there are many rocks here and you are not sure which one is the shape changer.
*/
struct Polymorph {};
class Change_Magic {
private:
Change_Magic() {}
friend Change_Magic take_polymorph(Polymorph);
};
Change_Magic take_polymorph(Polymorph) {
return {};
}
/* Them tricksy Polymorphs are hiding, grab them while you see them! */
template <class T>
void take_polymorph(T);
extern int Polymorph;
//! TODO: Define a variable named change_magic of type Change_Magic in main.
/* Now that you acquired a Polymorph you can dispel its power to gain Enchant Magic. */
class Enchant_Magic {
private:
Enchant_Magic(){};
friend Enchant_Magic dispel_polymorph(Change_Magic);
};
Enchant_Magic dispel_polymorph(Change_Magic) {
return {};
}
/* But at the last moment the polymorph tries to confuse your spell with a decoy! */
void dispel_polymorph(Change_Magic, int = 0);
//! TODO: Define a variable named enchant_magic of type Enchant_Magic in main.
/* You fight your way through a Spider Den. After cutting down spider webs for a while you see candle light. Inside the
* Spider Den you find an old confused looking man. "I'm making strings! Help me make strings!" "Standard strings are
* stupid! You can't tell how long they are just by looking at them! Enchant my strings so that I can!" How often do you
* meet a weird old guy in a Spider Den wanting to make strings? May as well help. */
class Spider_Den {
class Old_Man {
class Magic_Lamp {
Magic_Lamp() {}
friend Old_Man;
public:
operator int() {
std::cout << "Congratulations! You beat the demo! Now go buy the DLC with microtransactions.\n";
return {};
}
} static magic_lamp;
public:
template <class Enchantment>
Magic_Lamp &enchant_strings(Enchant_Magic) {
static_assert(Enchantment::get_length("Some string") == sizeof("Some string"),
"I need to be able to see the length of my string!");
static_assert(Enchantment::get_length("Some more string") == sizeof("Some more string"),
"I need to be able to see the length of my string!");
assert(Enchantment::get_length(std::string{"Some string"}.c_str()) == sizeof("Some string"));
assert(Enchantment::get_length(std::string{"Some more string"}.c_str()) == sizeof("Some more string"));
return magic_lamp;
}
} static old_man;
public:
template <class Master_Sword>
static Old_Man &free() {
static_assert(std::is_same<Master_Sword, Town::Blacksmith::Master_Sword>::value,
"Your sword fails to cut the spider webs");
return old_man;
}
};
Spider_Den::Old_Man Spider_Den::old_man;
Spider_Den::Old_Man::Magic_Lamp Spider_Den::Old_Man::magic_lamp;
//! TODO: Define a variable named magic_lamp of type Spider_Den::Old_Man::Magic_Lamp inside main and return it.
// You are not allowed to change anything above this line:
//-----------------------------------------------------------------------------
int main() {
//! TODO: uncomment the below lines and make them compile and run
//auto training_sword = //Town::Blacksmith::Training_Sword
//auto wooden_shield = //Town::Blacksmith::Wooden_Shield
//auto ruin_entrance = //Ruins::Dire_Wolf::Ruin_Entrance
//auto necromancer_key = //Necromancer::Key_of_Life
//auto coins = //Thiefs::Secret_Location::Treasure::Coins
//auto artefact = //Mages_Guild::Artefact
//auto adamantite_key = //Adamantite_Dragon_Layer::Adamantite_Key
//auto amethyst_key = //Magic::Amethyst_Key
//auto money = //Inventory::Money
//auto master_sword = //Town::Blacksmith::Master_Sword
//auto change_magic = //Change_Magic
//auto enchant_magic = //Enchant_Magic
//auto magic_lamp = //Spider_Den::Old_Man::Magic_Lamp
//return magic_lamp;
}