qtgui: parent the agent injector/brain viewer correctly, and fix some onSelect functi...
[openc2e.git] / Map.cpp
blob0ae86b31f07795067179219395cf6b7e5254a8c6
1 /*
2 * Map.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Tue May 25 2004.
6 * Copyright (c) 2004 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
20 #include "Map.h"
21 #include "openc2e.h"
22 #include "Room.h"
23 #include "MetaRoom.h"
24 #include <iostream>
26 void Map::Reset() {
27 for (std::vector<MetaRoom *>::iterator i = metarooms.begin(); i != metarooms.end(); i++) {
28 delete *i;
30 metarooms.clear();
31 // todo: metarooms should be responsible for deleting rooms, so use the following instead of clear:
32 // assert(rooms.empty());
33 rooms.clear();
36 void Map::SetMapDimensions(unsigned int w, unsigned int h) {
37 // todo: check for outlying metarooms
38 width = w;
39 height = h;
42 int Map::addMetaRoom(MetaRoom *m) {
43 // todo: check if it's outlying
44 while (getMetaRoom(metaroom_base))
45 metaroom_base++;
46 m->id = metaroom_base++;
47 metarooms.push_back(m);
48 return m->id;
51 MetaRoom *Map::getMetaRoom(unsigned int room) {
52 for (std::vector<MetaRoom *>::iterator i = metarooms.begin(); i != metarooms.end(); i++)
53 if ((*i)->id == room)
54 return *i;
55 return 0;
58 shared_ptr<Room> Map::getRoom(unsigned int r) {
59 for (std::vector<shared_ptr<Room> >::iterator i = rooms.begin(); i != rooms.end(); i++)
60 if ((*i)->id == r)
61 return *i;
62 return shared_ptr<Room>();
65 unsigned int Map::getMetaRoomCount() {
66 return metarooms.size();
69 unsigned int Map::getRoomCount() {
70 return rooms.size();
73 void Map::tick() {
74 // Three passes..
75 for (std::vector<MetaRoom *>::iterator m = metarooms.begin(); m != metarooms.end(); m++)
76 for (std::vector<shared_ptr<Room> >::iterator i = (*m)->rooms.begin(); i != (*m)->rooms.end(); i++)
77 (*i)->tick();
78 for (std::vector<MetaRoom *>::iterator m = metarooms.begin(); m != metarooms.end(); m++)
79 for (std::vector<shared_ptr<Room> >::iterator i = (*m)->rooms.begin(); i != (*m)->rooms.end(); i++)
80 (*i)->postTick();
81 for (std::vector<MetaRoom *>::iterator m = metarooms.begin(); m != metarooms.end(); m++)
82 for (std::vector<shared_ptr<Room> >::iterator i = (*m)->rooms.begin(); i != (*m)->rooms.end(); i++)
83 (*i)->resetTick();
86 MetaRoom *Map::metaRoomAt(unsigned int _x, unsigned int _y) {
87 for (std::vector<MetaRoom *>::iterator i = metarooms.begin(); i != metarooms.end(); i++) {
88 MetaRoom *r = *i;
89 if ((_x >= r->x()) && (_y >= r->y()))
90 if ((_x <= (r->x() + r->width())) && (_y <= (r->y() + r->height())))
91 return r;
93 return 0;
96 shared_ptr<Room> Map::roomAt(float _x, float _y) {
97 MetaRoom *m = metaRoomAt((unsigned int)_x, (unsigned int)_y); // TODO: good casts?
98 if (!m) return shared_ptr<Room>();
99 return m->roomAt(_x, _y);
102 std::vector<shared_ptr<Room> > Map::roomsAt(float _x, float _y) {
103 MetaRoom *m = metaRoomAt((unsigned int)_x, (unsigned int)_y); // TODO: good casts?
104 if (!m) return std::vector<shared_ptr<Room> >();
105 return m->roomsAt(_x, _y);
108 bool Map::collideLineWithRoomSystem(Point src, Point dest, shared_ptr<Room> &room, Point &where, Line &wall, unsigned int &walldir, int perm) {
109 shared_ptr<Room> newRoom;
111 where = src;
113 while (true) {
114 if (!collideLineWithRoomBoundaries(where, dest, room, newRoom, where, wall, walldir, perm))
115 return false; // failure
116 if (!newRoom)
117 return true; // collision
118 if (where == dest)
119 return false; // got there
121 assert(newRoom != room); // tsk
123 room = newRoom;
128 * poss. optimisation: skip checking the rest of the lines if our distance is 0?
130 bool Map::collideLineWithRoomBoundaries(Point src, Point dest, shared_ptr<Room> room, shared_ptr<Room> &newroom, Point &where, Line &wall, unsigned int &walldir, int perm) {
131 assert(room);
132 // TODO: this assert fails. why? 'where' is presumably outside the dest room sometimes.. mmh
133 //assert(room->containsPoint(src.x, src.y));
134 if (src == dest) return false;
136 newroom.reset();
138 /* if (room->containsPoint(dest.x, dest.y)) {
139 where = dest;
140 return false;
143 float distance = 100000000.0f; // TODO: lots.
144 bool foundsomething = false;
145 bool previousroom = (newroom);
146 Point oldpoint = where;
147 Line movement(src, dest);
149 Line x[4] = { room->left, room->right, room->top, room->bot };
150 for (unsigned int i = 0; i < 4; i++) {
151 /*if (previousroom)
152 if (x[i].containsPoint(oldpoint)) continue; */
154 Point temppoint;
155 if (x[i].intersect(movement, temppoint)) {
156 if (!movement.containsPoint(temppoint)) {
157 std::cout << "physics bug: intersect wasn't on movement line at (" << temppoint.x << ", " << temppoint.y << ")" << std::endl;
158 std::cout << "room line: (" << x[i].getStart().x << ", " << x[i].getStart().y << ") to ";
159 std::cout << "(" << x[i].getEnd().x << ", " << x[i].getEnd().y << ")" << std::endl;
160 std::cout << "movement line: (" << src.x << ", " << src.y << ") to ";
161 std::cout << "(" << dest.x << ", " << dest.y << ")" << std::endl;
162 return false; // go away
164 assert(movement.containsPoint(temppoint));
166 //if (temppoint == src) return false; // for debug use: sneakily fail all movement between rooms
168 // see if this is nearer than any previous points we've found
169 double distx = temppoint.x - src.x;
170 double disty = temppoint.y - src.y;
171 double d = distx*distx + disty*disty;
172 if (d > distance)
173 continue;
175 // work out which room is next along our movement vector
176 // TODO: this code utterly sucks, doesn't work properly
177 float newx, newy;
178 /*if (temppoint == src) { // TODO: this is not an accurate check!! likely cause of falling through PERM
179 // we might be on a PERM line! check backwards.
180 newx = temppoint.x + (src.x <= dest.x ? (src.x == dest.x ? 0.0 : -0.5) : 0.5);
181 newy = temppoint.y + (src.y <= dest.y ? (src.y == dest.y ? 0.0 : -0.5) : 0.5);
182 } else {*/
183 newx = temppoint.x + (src.x <= dest.x ? (src.x == dest.x ? 0.0 : 0.5) : -0.5);
184 newy = temppoint.y + (src.y <= dest.y ? (src.y == dest.y ? 0.0 : 0.5) : -0.5);
187 if (room->containsPoint(newx, newy)) { // if a little along our movement vector is still in our room, forget it
188 /*std::cout << "physics debug: next room is original room at (" << temppoint.x << ", " << temppoint.y << ")" << std::endl;
189 std::cout << "room line: (" << x[i].getStart().x << ", " << x[i].getStart().y << ") to ";
190 std::cout << "(" << x[i].getEnd().x << ", " << x[i].getEnd().y << ")" << std::endl;
191 std::cout << "movement line: (" << movement.getStart().x << ", " << movement.getStart().y << ") to ";
192 std::cout << "(" << movement.getEnd().x << ", " << movement.getEnd().y << ")" << std::endl;
193 return false;*/
194 continue; // continue, bad collision
197 shared_ptr<Room> nextroom;
198 bool foundroom = false;
200 for (std::map<boost::weak_ptr<Room>,RoomDoor *>::iterator r = room->doors.begin(); r != room->doors.end(); r++) {
201 shared_ptr<Room> otherroom = r->first.lock();
202 assert(otherroom);
203 assert(r->second);
204 if (otherroom->containsPoint(newx, newy)) {
205 // this is our next room!
206 foundroom = true;
207 // if boundary perm is going to let us through..
208 if (perm <= r->second->perm) // TODO: right?
209 nextroom = otherroom;
210 break;
214 if (!foundroom && !nextroom)
215 nextroom = roomAt(newx, newy);
217 /*if (temppoint == src) { // if we're just doing the backwards PERM check
218 if (!foundroom || nextroom != 0) {
219 // either there's no previous room or PERM let us into the previous room..
220 // ..so forget this collision
221 break;
225 shared_ptr<Room> z = roomAt(temppoint.x, temppoint.y); // TODO: evil performance-killing debug check
226 if (!z) {
227 // TODO: commented out this error message for sake of fuzzie's sanity, but it's still an issue
228 /*std::cout << "physics bug: fell out of room system at (" << where.x << ", " << where.y << ")" << std::endl;
229 std::cout << "room line: (" << x[i].getStart().x << ", " << x[i].getStart().y << ") to ";
230 std::cout << "(" << x[i].getEnd().x << ", " << x[i].getEnd().y << ")" << std::endl;
231 std::cout << "movement line: (" << movement.getStart().x << ", " << movement.getStart().y << ") to ";
232 std::cout << "(" << movement.getEnd().x << ", " << movement.getEnd().y << ")" << std::endl;*/
233 return false; // go away
236 // it is nearer and not the same room, so make it our priority
237 distance = d;
238 foundsomething = true;
239 where = temppoint;
240 wall = x[i];
241 walldir = i;
242 newroom = nextroom;
246 if (!foundsomething) {
247 if (room->containsPoint(dest.x, dest.y)) {
248 where = dest;
249 } else {
250 where = src; // TODO: can't we assume this anyway?
251 // TODO: commented out this error message for sake of fuzzie's sanity, but it's still an issue
252 /*std::cout << "physics bug: didn't collide with a line, nor stay in the current room!" << std::endl;
253 std::cout << "movement line: (" << movement.getStart().x << ", " << movement.getStart().y << ") to ";
254 std::cout << "(" << movement.getEnd().x << ", " << movement.getEnd().y << ")" << std::endl;*/
256 return false;
259 return true;
262 /* vim: set noet: */