OSDN Git Service

467100d2517ab132c3ea00d1cc5503c9ceb9e460
[deeangband/Deeangband-new.git] / Deeangband / Field.cpp
1 /*!
2 * @file Field.cpp
3 * @brief \83Q\81[\83\80\92\86\82Ì\83t\83\8d\83A\82ð\92è\8b`\82·\82é
4 * @date 2013/12/11
5 * @author Deskull
6 * 2013 Sikabane Works.
7 */
8
9 #include "stdafx.h"
10 #include "Field.h"
11
12 namespace Deeangband
13 {
14
15         Field::Field(std::map<TAG, boost::shared_ptr<Dungeon>>::iterator dungeonIt, DEPTH depth) : GameInstance()
16         {
17                 Dungeon *dungeonPtr = &(*dungeonIt->second);
18                 int x, y;
19                 this->dungeonTag = dungeonIt->first;
20                 this->width = dungeonPtr->GetBaseSize().GetX();
21                 this->height = dungeonPtr->GetBaseSize().GetY();
22                 this->generated = false;
23                 this->dungeonPtr = dungeonIt->second.get();
24
25                 if(depth > dungeonPtr->GetMaxDepth() || depth > dungeonPtr->GetMinDepth()) return;
26
27                 squares.resize(this->height);
28                 for(y = 0; y < height; y++)
29                 {
30                         for(x = 0; x < width; x++)
31                         {
32                                 squares[y].push_back(boost::shared_ptr<Square>(new Square()));
33                                 if(Dice::Cast(1, 4) == 5) squares[y][x]->SetFloorTag(dungeonPtr->GetInnerWallFloorTag());
34                                 else squares[y][x]->SetFloorTag(dungeonPtr->GetFloorFloorTag());
35                         }
36                 }
37
38                 this->UpdateSight();
39
40                 this->createRectRoom(13, 13, 20, 33);
41
42                 creatures.resize(0);
43                 doors.resize(0);
44                 traps.resize(0);
45                 items.resize(0);
46
47                 this->generated = true;
48         }
49
50         Field::Field()
51         {
52                 WipeData();
53         }
54
55         Field::~Field()
56         {
57                 WipeData();
58         }
59
60         void Field::WipeData(void)
61         {
62                 this->width = 0;
63                 this->height = 0;
64                 this->dungeonTag = "";
65                 creatures.resize(0);
66                 doors.resize(0);
67                 traps.resize(0);
68                 items.resize(0);
69         }
70
71         MAP_LENGTH Field::GetWidth(void)
72         {
73                 return width;
74         }
75
76         MAP_LENGTH Field::GetHeight(void)
77         {
78                 return height;
79         }
80
81         bool Field::SetSize(MAP_LENGTH width, MAP_LENGTH height)
82         {
83                 this->width = width;
84                 this->height = height;
85                 return true;
86         }
87
88         Square *Field::GetSquare(MAP_LENGTH x, MAP_LENGTH y)
89         {
90                 //! @note \83t\83B\81[\83\8b\83h\82Ì\94Í\88Í\8aO\82Ì\8dÀ\95W\82Ì\8fê\8d\87false\82ð\95Ô\82·\81B
91                 if(x < 0 || y < 0 || x >= this->width || y >= this->height) return NULL;
92                 return squares[y][x].get();
93         }
94
95         Square *Field::GetSquare(Coordinates &coord)
96         {
97                 return this->GetSquare(coord.GetX(), coord.GetY());
98         }
99
100         bool Field::GenerateTrap(std::map<TAG, boost::shared_ptr<TrapBase>>::iterator trapBaseIt, Coordinates *position)
101         {
102                 traps.emplace(traps.end(), boost::make_shared<Trap>(trapBaseIt, position));
103                 return true;
104         }
105
106         void Field::UpdateSight(void)
107         {
108                 int x, y;
109                 int updateSizeX = this->width * 2 + 1;
110                 int updateSizeY = this->height * 2 + 1;
111                 this->SightPass.resize(updateSizeX * updateSizeY);
112                 this->PhysicalPass.resize(updateSizeX * updateSizeY);
113
114                 for(x = 0; x < updateSizeX * updateSizeY; x++)
115                 {
116                         this->SightPass[x] = false;
117                         this->PhysicalPass[x] = false;
118                 }
119
120                 for(y = 1; y < updateSizeY; y += 2)
121                 {
122                         for(x = 1; x < updateSizeX; x += 2)
123                         {
124                                 this->SightPass[y * updateSizeX + x] = !this->GetSquare(x / 2, y / 2)->IsWall();
125                                 this->PhysicalPass[y * updateSizeX + x] = !this->GetSquare(x / 2, y / 2)->IsWall();
126                         }
127                 }
128
129
130                 for(y = 0; y < this->height * 2 + 1; y += 2)
131                 {
132                         for(x = 0; x < this->width * 2 + 1; x += 2)
133                         {
134                                 if(!this->GetSquare(x / 2 - 1, y / 2 - 1) || !this->GetSquare(x / 2 - 1, y / 2) || !this->GetSquare(x / 2, y / 2 - 1) || !this->GetSquare(x / 2, y / 2))
135                                 {
136                                         this->SightPass[y * updateSizeX + x] = false;
137                                         this->PhysicalPass[y * updateSizeX + x] = false;
138                                 }
139                                 else if((!this->GetSquare(x / 2 - 1, y / 2 - 1)->IsWall() && !this->GetSquare(x / 2, y / 2 )->IsWall()) || (!this->GetSquare(x / 2, y / 2 - 1)->IsWall() && !this->GetSquare(x / 2 - 1, y / 2)->IsWall()))
140                                 {
141                                         this->SightPass[y * updateSizeX + x] = true;
142                                         this->PhysicalPass[y * updateSizeX + x] = true;
143                                 }
144                                 else
145                                 {
146                                         this->SightPass[y * updateSizeX + x] = false;
147                                         this->PhysicalPass[y * updateSizeX + x] = false;
148                                 }
149                         }
150                 }
151
152                 for(y = 0; y < this->height * 2 + 1; y += 2)
153                 {
154                         for(x = 1; x < this->width * 2 + 1; x += 2)
155                         {
156                                 if(!this->GetSquare(x / 2, y / 2 - 1) || !this->GetSquare(x / 2, y / 2))
157                                 {
158                                         this->SightPass[y * updateSizeX + x] = false;
159                                         this->PhysicalPass[y * updateSizeX + x] = false;
160                                 }
161                                 else if(this->GetSquare(x / 2, y / 2 - 1)->IsWall() || this->GetSquare(x / 2, y / 2)->IsWall())
162                                 {
163                                         this->SightPass[y * updateSizeX + x] = false;
164                                         this->PhysicalPass[y * updateSizeX + x] = false;
165                                 }
166                                 else
167                                 {
168                                         this->SightPass[y * updateSizeX + x] = true;
169                                         this->PhysicalPass[y * updateSizeX + x] = true;
170                                 }
171                         }
172                 }
173
174                 for(y = 1; y < updateSizeY; y += 2)
175                 {
176                         for(x = 0; x < updateSizeX; x += 2)
177                         {
178                                 if(!this->GetSquare(x / 2 - 1, y / 2) || !this->GetSquare(x / 2, y / 2))
179                                 {
180                                         this->SightPass[y * updateSizeX + x] = false;
181                                         this->PhysicalPass[y * updateSizeX + x] = false;
182                                 }
183                                 else if(this->GetSquare(x / 2 - 1, y / 2)->IsWall() || this->GetSquare(x / 2, y / 2)->IsWall())
184                                 {
185                                         this->SightPass[y * updateSizeX + x] = false;
186                                         this->PhysicalPass[y * updateSizeX+ x] = false;
187                                 }
188                                 else
189                                 {
190                                         this->SightPass[y * updateSizeX + x] = true;
191                                         this->PhysicalPass[y * updateSizeX + x] = true;
192                                 }
193                         }
194                 }
195
196         }
197
198         void Field::createRectRoom(MAP_LENGTH sx, MAP_LENGTH sy,  MAP_LENGTH ex, MAP_LENGTH ey)
199         {
200                 Square *squarePtr;
201                 std::vector<boost::shared_ptr<Coordinates>> wallVec;
202
203                 MAP_LENGTH x, y;
204                 wallVec.clear();
205
206                 for(y = sy + 1; y < ey; y++)
207                 {
208                         for(x = sx + 1; x < ex; x++)
209                         {
210                                 squarePtr = this->GetSquare(x, y);
211                                 if(squarePtr)
212                                 {
213                                         squarePtr->SetFloorTag(dungeonPtr->GetFloorFloorTag());
214                                 }
215                         }
216                 }
217                 
218                 for(y = sy; y <= ey; y++)
219                 {
220                         squarePtr = this->GetSquare(sx, y);
221                         squarePtr->SetFloorTag(dungeonPtr->GetInnerWallFloorTag());
222                         squarePtr = this->GetSquare(ex, y);
223                         squarePtr->SetFloorTag(dungeonPtr->GetInnerWallFloorTag());
224                         wallVec.push_back(boost::make_shared<Coordinates>(sx, y));
225                         wallVec.push_back(boost::make_shared<Coordinates>(ex, y));
226                 }
227
228                 for(x = sx + 1; x < ex; x++)
229                 {
230                         squarePtr = this->GetSquare(x, sy);
231                         squarePtr->SetFloorTag(dungeonPtr->GetInnerWallFloorTag());
232                         squarePtr = this->GetSquare(x, ey);
233                         squarePtr->SetFloorTag(dungeonPtr->GetInnerWallFloorTag());
234                         wallVec.push_back(boost::make_shared<Coordinates>(x, sy));
235                         wallVec.push_back(boost::make_shared<Coordinates>(x, ey));
236                 }
237
238                 this->GetSquare(*wallVec[Dice::Rand0(wallVec.size())].get())->SetFloorTag(dungeonPtr->GetFloorFloorTag());
239         }
240
241         void Field::createRectRoom(Coordinates& leftTop, Coordinates& rightBottom)
242         {
243                 this->createRectRoom(leftTop.GetX(), leftTop.GetY(), rightBottom.GetX(), rightBottom.GetY());
244         }
245
246         void Field::GetSight(std::vector<bool> &coordVec, MAP_LENGTH size, MAP_LENGTH baseX, MAP_LENGTH baseY)
247         {
248                 MAP_LENGTH x, y, s;
249                 int sideWidth = size * 2 + 1;
250                 int allocSize = sideWidth * sideWidth;
251                 std::vector<Coordinates> lineVec;
252                 std::vector<Coordinates>::iterator lineIt;
253                 std::vector<Coordinates>::reverse_iterator lineRIt;
254
255                 for(s = 0 ; s < allocSize; s++) coordVec[s] = false;
256                 coordVec[size * sideWidth + size] = true;
257                 
258
259                 for(s = size; s >= 1; s--)
260                 {
261                         for(x = baseX - s; x <= baseX + s; x++)
262                         {
263                                 int tx = x;
264                                 int ty1 = baseY - s;
265                                 int ty2 = baseY + s;
266
267                                 if(tx >= 0 && ty1 >= 0 && tx < this->width && ty1 < this->height)
268                                 {
269                                         if(!coordVec[(ty1 - baseY + size) * sideWidth + tx - baseX + size])
270                                         {
271                                                 Coordinates::LineOfSight(lineVec, baseX, baseY, tx, ty1);
272                                                 if(lineVec[0].GetX() == baseX && lineVec[0].GetY() == baseY)
273                                                 {
274                                                         for(lineIt = ++lineVec.begin(); lineIt < lineVec.end(); lineIt++)
275                                                         {
276                                                                 int lsx = lineIt->GetX() - baseX + size;
277                                                                 int lsy = lineIt->GetY() - baseY + size;
278                                                                 coordVec[lsy * sideWidth + lsx] = true;
279                                                                 if(!this->GetSquare(lineIt->GetX(), lineIt->GetY()) || this->GetSquare(lineIt->GetX(), lineIt->GetY())->IsWall()) break;
280                                                                 if(Coordinates::Distance(baseX, baseY, lineIt->GetX(), lineIt->GetY()) > s) break;
281                                                         }
282                                                 }
283                                                 else
284                                                 {
285                                                         for(lineRIt = ++lineVec.rbegin(); lineRIt < lineVec.rend(); lineRIt++)
286                                                         {
287                                                                 int lsx = lineRIt->GetX() - baseX + size;
288                                                                 int lsy = lineRIt->GetY() - baseY + size;
289                                                                 coordVec[lsy * sideWidth + lsx] = true;
290                                                                 if(!this->GetSquare(lineRIt->GetX(), lineRIt->GetY()) || this->GetSquare(lineRIt->GetX(), lineRIt->GetY())->IsWall()) break;
291                                                                 if(Coordinates::Distance(baseX, baseY, lineRIt->GetX(), lineRIt->GetY()) > s) break;
292                                                         }
293                                                 }
294                                         }
295                                 }
296
297                                 lineVec.clear();
298
299                                 if(tx >= 0 && ty2 >= 0 && tx < this->width && ty2 < this->height)
300                                 {
301                                         if(!coordVec[(ty2 - baseY + size) * sideWidth + tx - baseX + size])
302                                         {
303                                                 Coordinates::LineOfSight(lineVec, baseX, baseY, tx, ty2);
304                                                 if(lineVec[0].GetX() == baseX && lineVec[0].GetY() == baseY)
305                                                 {
306                                                         for(lineIt = ++lineVec.begin()++; lineIt < lineVec.end(); lineIt++)
307                                                         {
308                                                                 int lsx = lineIt->GetX() - baseX + size;
309                                                                 int lsy = lineIt->GetY() - baseY + size;
310                                                                 coordVec[lsy * sideWidth + lsx] = true;
311                                                                 if(!this->GetSquare(lineIt->GetX(), lineIt->GetY()) || this->GetSquare(lineIt->GetX(), lineIt->GetY())->IsWall()) break;
312                                                                 if(Coordinates::Distance(baseX, baseY, lineIt->GetX(), lineIt->GetY()) > s) break;
313                                                         }
314                                                 }
315                                                 else
316                                                 {
317                                                         for(lineRIt = ++lineVec.rbegin()++; lineRIt < lineVec.rend(); lineRIt++)
318                                                         {
319                                                                 int lsx = lineRIt->GetX() - baseX + size;
320                                                                 int lsy = lineRIt->GetY() - baseY + size;
321                                                                 coordVec[lsy * sideWidth + lsx] = true;
322                                                                 if(!this->GetSquare(lineRIt->GetX(), lineRIt->GetY()) || this->GetSquare(lineRIt->GetX(), lineRIt->GetY())->IsWall()) break;
323                                                                 if(Coordinates::Distance(baseX, baseY, lineRIt->GetX(), lineRIt->GetY()) > s) break;
324                                                         }
325                                                 }
326                                         }
327                                 }
328
329                                 lineVec.clear();
330
331                         }
332
333                         for(y = baseY - s; y <= baseY + s; y++)
334                         {
335                                 int tx1 = baseX - s;
336                                 int tx2 = baseX + s;
337                                 int ty = y;
338
339                                 if(tx1 >= 0 && ty >= 0 && tx1 < this->width && ty < this->height)
340                                 {
341                                         if(!coordVec[(ty - baseY + size) * sideWidth + tx1 - baseX + size])
342                                         {
343                                                 Coordinates::LineOfSight(lineVec, baseX, baseY, tx1, ty);
344                                                 if(lineVec[0].GetX() == baseX && lineVec[0].GetY() == baseY)
345                                                 {
346                                                         for(lineIt = ++lineVec.begin(); lineIt < lineVec.end(); lineIt++)
347                                                         {
348                                                                 int lsx = lineIt->GetX() - baseX + size;
349                                                                 int lsy = lineIt->GetY() - baseY + size;
350                                                                 coordVec[lsy * sideWidth + lsx] = true;
351                                                                 if(!this->GetSquare(lineIt->GetX(), lineIt->GetY()) || this->GetSquare(lineIt->GetX(), lineIt->GetY())->IsWall()) break;
352                                                                 if(Coordinates::Distance(baseX, baseY, lineIt->GetX(), lineIt->GetY()) > s) break;
353                                                         }
354                                                 }
355                                                 else
356                                                 {
357                                                         for(lineRIt = ++lineVec.rbegin(); lineRIt < lineVec.rend(); lineRIt++)
358                                                         {
359                                                                 int lsx = lineRIt->GetX() - baseX + size;
360                                                                 int lsy = lineRIt->GetY() - baseY + size;
361                                                                 coordVec[lsy * sideWidth + lsx] = true;
362                                                                 if(!this->GetSquare(lineRIt->GetX(), lineRIt->GetY()) || this->GetSquare(lineRIt->GetX(), lineRIt->GetY())->IsWall()) break;
363                                                                 if(Coordinates::Distance(baseX, baseY, lineRIt->GetX(), lineRIt->GetY()) > s) break;
364                                                         }       
365                                                 }
366                                         }
367                                 }
368
369                                 lineVec.clear();
370
371                                 if(tx2 >= 0 && ty >= 0 && tx2 < this->width && ty < this->height)
372                                 {
373                                         if(!coordVec[(ty - baseY + size) * sideWidth + tx2 - baseX + size])
374                                         {
375                                                 Coordinates::LineOfSight(lineVec, baseX, baseY, tx2, ty);
376                                                 if(lineVec[0].GetX() == baseX && lineVec[0].GetY() == baseY)
377                                                 {
378                                                         for(lineIt = ++lineVec.begin(); lineIt < lineVec.end(); lineIt++)
379                                                         {
380                                                                 int lsx = lineIt->GetX() - baseX + size;
381                                                                 int lsy = lineIt->GetY() - baseY + size;
382                                                                 coordVec[lsy * sideWidth + lsx] = true;
383                                                                 if(!this->GetSquare(lineIt->GetX(), lineIt->GetY()) || this->GetSquare(lineIt->GetX(), lineIt->GetY())->IsWall()) break;
384                                                                 if(Coordinates::Distance(baseX, baseY, lineIt->GetX(), lineIt->GetY()) > s) break;
385                                                         }
386                                                 }
387                                                 else
388                                                 {
389                                                         for(lineRIt = ++lineVec.rbegin(); lineRIt < lineVec.rend(); lineRIt++)
390                                                         {
391                                                                 int lsx = lineRIt->GetX() - baseX + size;
392                                                                 int lsy = lineRIt->GetY() - baseY + size;
393                                                                 coordVec[lsy * sideWidth + lsx] = true;
394                                                                 if(!this->GetSquare(lineRIt->GetX(), lineRIt->GetY()) || this->GetSquare(lineRIt->GetX(), lineRIt->GetY())->IsWall()) break;
395                                                                 if(Coordinates::Distance(baseX, baseY, lineRIt->GetX(), lineRIt->GetY()) > s) break;
396                                                         }       
397                                                 }
398                                         }
399                                 }
400
401                                 lineVec.clear();
402
403                         }
404
405                 }
406         }
407
408         bool Field::HaveSight(int bx, int by, int tx, int ty)
409         {
410                 std::vector<Coordinates> coordVec;
411                 std::vector<Coordinates>::iterator coordIt;
412
413                 if(bx < 0 || by < 0 || tx < 0 || ty < 0) return false;
414                 if(bx >= this->width || by >= this->height || tx >= this->width || ty >= this->height) return false;
415
416                 Coordinates::LineOfSight(coordVec, bx, by, tx, ty);
417                 for(coordIt = coordVec.begin(); coordIt != coordVec.end(); coordIt++)
418                 {
419                         if(bx == coordIt->GetX() && by == coordIt->GetY()) continue;
420                         if(tx == coordIt->GetX() && ty == coordIt->GetY()) continue;
421                         if(this->GetSquare(coordIt->GetX(), coordIt->GetY())->GetFloorTag() == "VANILLA_PERMANENT_WALL") return false;
422                 }
423                 return true;
424         }
425
426         bool Field::GetSightPass(int x, int y)
427         {
428                 return SightPass[y * (this->width * 2 + 1) + x];
429         }
430
431 }