-
Notifications
You must be signed in to change notification settings - Fork 0
/
actor.cpp
213 lines (176 loc) · 6.71 KB
/
actor.cpp
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
#include "actor.h"
#include "bag.h"
#include "default_weapon.h"
#include "game.h"
#include "game_commands.h"
#include "vampire_factory.h"
#include "troll.h"
#include "vampire.h"
#include "wizard.h"
#include <cstdlib>
#include <iostream>
#include <map>
#include <sstream>
namespace da_game {
int Actor::instances;
Actor::Actor() : id(instances) {
instances++;
current_weapon = new DefaultWeapon(); // So everyone can try to fight,
// Rember to delete this in inherited classes constructors
container = new Bag(); // FIXME
current_room = 0;
Game::add_actor(*this);
}
Actor::~Actor() {
if (current_weapon->weight() == 0 && current_weapon->volume() == 0) {
// In case its the default weapon, we dont want them laying around
// TODO fix this with a cast perhaps?
delete current_weapon;
}
// science the actor exists no more we drop everything in the current room
std::vector<Object *>::iterator it;
for (it = container->get_objects()->begin(); it != container->get_objects()->end(); ++it) {
current_room->drop(*it);
}
container->get_objects()->clear();
current_room->drop(container);
current_room->leave(*this);
Game::remove_actor(*this);
}
bool Actor::pick_up(Object * object){
return container->add(*object);
}
bool Actor::drop(Object * object) {
return container->remove(*object);
}
/**
* Takes this actor to the environment that the given exit leads
* to. However the exit must not be locked.
*
* @param exit_name The name of the exit to go through
*/
void Actor::go(std::string exit_name) {
Exit * exit = current_room->get_exit(exit_name);
if (exit == 0) {
std::cerr << "No such exit: " << exit_name << std::endl;
return;
}
if (exit->is_locked()) {
std::cerr << "Exit is locked -- unlock it in order to get through" << std::endl;
return;
}
Environment * new_room = exit->get_outfall();
if (new_room == 0) {
std::cerr << "That exit leads nowhere..." << std::endl;
return;
}
// if everything is in order, let the actor follow the exit
current_room->leave(*this);
current_room = new_room;
current_room->enter(*this);
std::cerr << get_name() << " entered " << exit_name << std::endl;
}
void Actor::fight(Actor & opponent) {
GameCommands::fight(*this, opponent);
}
Weapon * Actor::weapon() {
if (current_weapon == 0) {
std::cerr << "FEEEL HÄR. Actor::weapon() in actor.cpp" << std::endl;
}
return current_weapon;
}
void Actor::save(std::fstream & save) {
save << "ACT" << id << ":" << get_type() << ":" << get_name() << ":";
save << "current_room=" << current_room->id;
save << ",container=" << container->id;
save << ",hp=" << hp;
save << ",strength=" << strength;
if (serialize().length() > 0) {
save << "," << serialize();
}
// redundant
save << ":OBJ" << container->id;
save << std::endl;
container->save(save);
}
/**
* Loads an actor object from the specified string.
*
* @param line A line describing the object to load
* @return A pointer to a the created instance
*/
Actor * Actor::load(const std::string line, const std::map<std::string, Environment *> & envs,
const std::map<std::string, Object *> & objs) {
std::istringstream input(line);
std::vector<std::string> tokens;
std::string token;
while (std::getline(input, token, ':')) {
tokens.push_back(token);
}
// extract properties
std::map<std::string, std::string> properties;
std::istringstream pss(tokens[3]);
while (std::getline(pss, token, ',')) {
size_t eq_sign = token.find('=');
properties.insert(std::pair<std::string, std::string>(token.substr(0, eq_sign), token.substr(eq_sign+1)));
}
// find type
std::string & type = tokens[1];
std::map<std::string, std::string>::iterator prop_it;
std::map<std::string, Environment *>::const_iterator env_it;
std::map<std::string, Object *>::iterator obj_it;
std::string current_room_id = properties.find("current_room")->second;
Environment * current_room = envs.find(current_room_id)->second;
int hp = str2int(properties.find("hp")->second);
int strength = str2int(properties.find("strength")->second);
Actor * actor = NULL;
if (type == "Human") {
// abstract!
}
else if (type == "Player") {
bool has_heart = str2int(properties.find("has_heart")->second) != 0;
int max_health = str2int(properties.find("max_health")->second);
actor = new Player(current_room, hp, strength, has_heart, max_health);
}
else if (type == "Wizard") {
bool has_heart = str2int(properties.find("has_heart")->second) != 0;
int max_health = str2int(properties.find("max_health")->second);
int magic = str2int(properties.find("magic")->second);
int max_magic = str2int(properties.find("max_magic")->second);
actor = new Wizard(current_room, hp, strength, has_heart, max_health, magic, max_magic);
}
else if (type == "Troll") {
actor = new Troll(current_room, hp, strength);
}
else if (type == "Vampire") {
actor = new Vampire(current_room, hp, strength);
}
else if (type == "VampireFactory") {
int frequency = str2int(properties.find("frequency")->second);
actor = new VampireFactory(current_room, frequency);
}
else {
std::cerr << "Unrecognized actor type: " << type << std::endl;
}
// set general Actor properties, not already set
std::string container_id = properties.find("container")->second;
Object * cont_obj = objs.find(container_id)->second;
Container * cont;
if ((cont = dynamic_cast<Container *>(cont_obj))) {
actor->container = cont;
}
return actor;
}
/**
* Quickly converts the specified string to an integer.
*
* @param str The string to convert
* @return The converted integer
*/
int Actor::str2int(std::string str) {
std::istringstream iss(str);
int number;
iss >> number;
return number;
}
}