OSDN Git Service

8b35274165f6f97a225e24816cb26181d4d7fc27
[deeangband/Deeangband-new.git] / Deeangband / Creature.cpp
1 /*!
2  * @file Creature.cpp
3  * @brief \83Q\81[\83\80\92\86\82Ì\83N\83\8a\81[\83`\83\83\81[\82ð\92è\8b`\82·\82é
4  * @date 2013/12/10
5  * @author Deskull
6  * 2013 Sikabane Works.
7  */
8
9 #include "stdafx.h"
10 #include "Creature.h"
11
12 #include "GameSurface.h"
13 #include "GameLogger.h"
14 #include "GameWorld.h"
15
16 #include "Field.h"
17 #include "Floor.h"
18 #include "Item.h"
19 #include "Square.h"
20
21 namespace Deeangband
22 {
23
24         SOUL Creature::soulLevel[CREATURE_MAX_LEVEL] =
25         {
26                 // 0    // \83\8d\83X\83g\88æ
27                 50,      // Lv1\83f\83t\83H\83\8b\83g\8aî\8f\80\83\\83E\83\8b
28                 100, // Lv2\93\9e\92B\83\\83E\83\8b
29                 130, // :
30                 180,
31                 260,
32                 360,
33                 480,
34                 630,
35                 880,
36                 1280, // Lv10\93\9e\92B\83\\83E\83\8b
37                 1700,
38                 2200,
39                 2800,
40                 3600,
41                 4600,
42                 6100,
43                 8800,
44                 10600,
45                 12600,
46                 15000, // Lv20\93\9e\92B\83\\83E\83\8b
47                 18000,
48                 24000,
49                 35000,
50                 50000,
51                 75000,
52                 100000,
53                 150000,
54                 200000,
55                 275000,
56                 350000, // Lv30\93\9e\92B\83\\83E\83\8b
57                 450000,
58                 550000,
59                 700000,
60                 1000000,
61                 1500000,
62                 2100000,
63                 2700000,
64                 3600000,
65                 4700000,
66                 6000000, // Lv40\93\9e\92B\83\\83E\83\8b
67                 7500000,
68                 9000000,
69                 11500000,
70                 14500000,
71                 19000000,
72                 26000000,
73                 33000000,
74                 45000000,
75                 60000000,
76                 90000000, // Lv50\93\9e\92B\83\\83E\83\8b
77                 150000000,
78                 230000000,
79                 400000000,
80                 620000000,
81                 880000000,
82                 1150000000,
83                 1500000000,
84                 3200000000,
85                 6400000000,
86                 11100000000, // Lv60\93\9e\92B\83\\83E\83\8b
87         };
88
89         Creature::Creature(std::map<TAG, std::shared_ptr<Species>>::iterator speciesIt)
90                 : GameInstance(), HaveSymbol(), HaveHp(), HaveGameTime(), HavePosition(), HaveInventory(), HaveSize()
91         {
92                 WipeData();
93                 SetSpeciesData(&(*speciesIt->second));
94         }
95
96         Creature::Creature(std::map<TAG, std::shared_ptr<Species>>::iterator& speciesIt, std::map<ID, std::shared_ptr<Field>>::iterator& fieldIt, MAP_LENGTH x, MAP_LENGTH y)
97                 : GameInstance(), HaveSymbol(), HaveHp(), HaveGameTime(), HavePosition(fieldIt, x, y), HaveInventory(), HaveSize()
98         {
99                 WipeData();
100                 sightList.resize((this->sightRange * 2 + 1)*(this->sightRange * 2 + 1));
101                 fieldIt->second->GetSight(sightList, this->sightRange, x, y);
102                 SetSpeciesData(speciesIt->second.get());
103         }
104
105         Creature::Creature(void)
106         {
107                 WipeData();
108         }
109
110         Creature::~Creature(void)
111         {
112         }
113
114         void Creature::SetSpeciesData(Species *speciesPtr)
115         {
116                 std::normal_distribution<> distHeight(speciesPtr->GetHeight(), GameConstants::HeightStandardDeviation);
117                 std::normal_distribution<> distWeight(speciesPtr->GetWeight(), GameConstants::WeightStandardDeviation);
118                 this->name = speciesPtr->GetName();
119                 this->symbol = speciesPtr->GetSymbol();
120                 this->symbolColor = speciesPtr->GetSymbolColor();
121                 this->currentSoul = this->maxSoul = speciesPtr->GetBaseSoul();
122                 this->currentFeed = speciesPtr->GetBaseFeed() * 3 / 4;
123                 this->maxFeed = speciesPtr->GetBaseFeed();
124                 this->weight = distWeight(Dice::mt);
125                 this->height = distHeight(Dice::mt);
126                 this->campTag = TAG_VARIABLE;
127                 this->firstRace = speciesPtr->GetFirstRaceTag();
128                 this->secondRace = speciesPtr->GetSecondtRaceTag();
129         }
130
131         void Creature::WipeData(void)
132         {
133                 GameInstance::WipeData();
134                 HaveSymbol::WipeData();
135                 HaveSize::WipeData();
136                 this->currentMp = this->maxMp = this->maxMaxMp = 10;
137                 this->currentSoul = this->maxSoul = Creature::soulLevel[0];
138                 this->currentDiscipilne.SetPoint(0, 0, 0, 0, 0);
139                 this->firstRace = "";
140                 this->secondRace = "";
141                 this->height = 160.0f;
142                 this->weight = 50.0f;
143                 this->divineLevel = -1;
144                 savings.Set(10, 10, 10);
145                 this->currentFeed = this->maxFeed = 20000;
146
147                 currentStatus.Set(8, 8, 8, 8, 8, 8);
148                 maxStatus.Set(8, 8, 8, 8, 8, 8);
149                 maxMaxStatus.Set(20, 20, 20, 20, 20, 20);
150
151                 sightRange = BASE_SIGHT_RANGE;
152
153                 this->calcHPTable();
154                 this->currentHp = this->maxHp = this->GetNorMaxHP();
155
156                 this->skillExpList.clear();
157
158                 this->turn = 0;
159                 this->campTag = TAG_VARIABLE;
160
161                 //this->fieldID = -1;
162                 //this->position.Set(0, 0);
163
164                 this->skillExpList.clear();
165
166                 this->symbol = '@';
167                 this->symbolColor.SetColor(255, 255, 255, 255);
168                 this->fieldID = 0;
169         }
170
171         bool Creature::IsAlive(void)
172         {
173                 return this->currentHp > 0 && this->currentSoul > 0;
174         }
175
176         bool Creature::TakeEffect(Effect *effectPtr, POWER amount)
177         {
178                 if(!effectPtr) this->CalcHP(-amount);
179                 return false;
180         }
181
182         void Creature::die(void)
183         {
184         }
185
186         void Creature::calcHPTable(void)
187         {
188                 int lev;
189                 HP hitDice = this->GetSize();
190                 HP minLine = hitDice * (CREATURE_MAX_LEVEL + 4) * 70 / 100;
191                 HP maxLine = hitDice * (CREATURE_MAX_LEVEL + 4) * 130 / 100;
192
193                 if(hitDice <= 0) hitDice = 1;
194
195                 do
196                 {
197                         this->hpTable[0] = hitDice + Dice::Cast(3, hitDice);
198                         for(lev = 0; lev < CREATURE_MAX_LEVEL - 1; lev++)
199                         {
200                                 this->hpTable[lev + 1] = this->hpTable[lev] + Dice::Rand1(hitDice);
201                         }
202                 }
203                 while(this->hpTable[CREATURE_MAX_LEVEL - 1] < minLine && this->hpTable[CREATURE_MAX_LEVEL - 1] > maxLine);
204         }
205
206         void Creature::calcMP(MP amount)
207         {
208                 this->currentMp += amount;
209                 if(this->currentMp > this->maxMp) this->currentMp = this->maxMp;
210                 if(this->currentMp < 0) this->currentMp = 0;
211         }
212
213         void Creature::setMP(MP amount)
214         {
215                 this->currentMp += amount;
216                 if(this->currentMp > this->maxMp) this->currentMp = this->maxMp;
217                 if(this->currentMp < 0) this->currentMp = 0;
218         }
219
220         LEVEL Creature::GetLevel(void)
221         {
222                 LEVEL level;
223                 if(this->currentSoul <= 0) return 0;
224                 if(this->currentSoul < Creature::soulLevel[1]) return 1;
225                 for(level = 2; level < CREATURE_MAX_LEVEL; level++)
226                 {
227                         if(Creature::soulLevel[level - 1] > this->currentSoul) return level;
228                 }
229                 return level;
230         }
231
232         HP Creature::GetNorMaxHP(void)
233         {
234                 return this->hpTable[this->GetLevel()];
235         }
236
237         MP Creature::GetCurMP(void)
238         {
239                 return this->currentMp;
240         }
241
242         MP Creature::GetMaxMP(void)
243         {
244                 return this->maxMp;
245         }
246
247         MP Creature::GetNorMaxMP(void)
248         {
249                 return this->maxMaxMp;
250         }
251
252         AC Creature::GetArmorSaving(void)
253         {
254                 return this->savings.GetArmor();
255         }
256
257         EV Creature::GetEvasionSaving(void)
258         {
259                 return this->savings.GetEvasion();
260         }
261
262         VO Creature::GetVolitionSaving(void)
263         {
264                 return this->savings.GetVolition();
265         }
266
267         SOUL Creature::GetCurrentSoul(void)
268         {
269                 return this->currentSoul;
270         }
271
272         SOUL Creature::GetMaxSoul(void)
273         {
274                 return this->maxSoul;
275         }
276
277         BASE_STATUS Creature::GetCurrentStatus(CREATURE_STATUS stat)
278         {
279                 return currentStatus.Get(stat);
280         }
281
282         BASE_STATUS Creature::GetMaxStatus(CREATURE_STATUS stat)
283         {
284                 return maxStatus.Get(stat);
285         }
286
287         BASE_STATUS Creature::GetMaxMAXStatus(CREATURE_STATUS stat)
288         {
289                 return maxMaxStatus.Get(stat);
290         }
291
292         DISCIPLINE_POINT Creature::GetDiscipilnePoint(DISCIPLINE_TYPE typ)
293         {
294                 return this->currentDiscipilne.GetPoint(typ);
295         }
296
297         DISCIPLINE_POINT Creature::GetDiscipilneRank(DISCIPLINE_TYPE typ)
298         {
299                 return this->currentDiscipilne.GetRank(typ);
300         }
301
302         void Creature::GainSoul(SOUL amount)
303         {
304                 SOUL diff;
305                 if(this->currentSoul < this->maxSoul)
306                 {
307                         diff = this->maxSoul - this->currentSoul;
308                         if(diff < amount)
309                         {
310                                 this->maxSoul += diff / 20;
311                                 this->currentSoul = this->maxSoul;
312                                 amount -= diff;
313                         }
314                         else
315                         {
316                                 this->maxSoul += amount / 20;
317                                 this->currentSoul += amount;
318                                 amount = 0;
319                         }
320                 }
321                 this->currentSoul += amount;
322                 this->maxSoul += amount;
323         }
324
325         void Creature::LostSoul(SOUL amount)
326         {
327                 this->currentSoul -= amount;
328                 this->maxSoul -= amount / 20;
329                 if(this->currentSoul < 1) this->die();
330         }
331
332         LEVEL Creature::GetDivineLevel(void)
333         {
334                 return this->divineLevel;
335         }
336
337         FEED Creature::GetCurrentFeedPoint(void)
338         {
339                 return this->currentFeed;
340         }
341
342         FEED Creature::GetMaxFeedPoint(void)
343         {
344                 return this->maxFeed;
345         }
346
347         PLAY_EXIT_CODE Creature::TurnProcess(void)
348         {
349                 Deeangband::GAME_COMMAND commandID;
350                 commandID = GameElement::GameSurfacePtr->GetCommand(GameElement::GameWorldPtr->GetPlayerCreature());
351                 return DoGameCommand(commandID);
352         }
353
354         PLAY_EXIT_CODE Creature::TimeProcess(void)
355         {
356                 this->currentFeed -= 10;
357                 return PLAY_EXIT_NONE;
358         }
359
360         TURN Creature::GetTurn(void)
361         {
362                 return this->turn;
363         }
364
365         SKILL_EXP Creature::GetSkillExp(TAG tag)
366         {
367                 if(this->skillExpList.count(tag)) return this->skillExpList[tag];
368                 else return 0;
369         }
370
371         TAG Creature::GetCampTag(void)
372         {
373                 return this->campTag;
374         }
375
376         bool Creature::Melee(Creature *targetPtr)
377         {
378                 this->TakeEffect(NULL, Dice::Cast(1, 6));
379                 targetPtr->TakeEffect(NULL, Dice::Cast(1, 6));
380                 return true;
381         }
382
383         bool Creature::PickUpItem(std::map<ID, std::shared_ptr<Item>>::iterator itemIt)
384         {
385                 return true;
386         }
387
388         bool Creature::DropItem(std::map<ID, std::shared_ptr<Item>>::iterator itemIt)
389         {
390                 return true;
391         }
392
393         bool Creature::EatItem(std::map<ID, std::shared_ptr<Item>>::iterator itemIt)
394         {
395                 return true;
396         }
397
398         bool Creature::QuaffItem(std::map<ID, std::shared_ptr<Item>>::iterator itemIt)
399         {
400                 return true;
401         }
402
403         bool Creature::ActivateItem(std::map<ID, std::shared_ptr<Item>>::iterator itemIt)
404         {
405                 return true;
406         }
407
408         bool Creature::ThrowItem(std::map<ID, std::shared_ptr<Item>>::iterator itemIt)
409         {
410                 return true;
411         }
412
413         bool Creature::ReadItem(std::map<ID, std::shared_ptr<Item>>::iterator itemIt)
414         {
415                 return true;
416         }
417
418         bool Creature::CanEnterPosition(Floor *floorPtr)
419         {
420                 //! @note \88Ú\93®\90æ\82Ì\8fî\95ñ\82ª\96³\8cø(NULL)\82È\82ç\82ΠFALSE          
421                 if(!floorPtr) return false;
422                 //! @note \88Ú\93®\90æ\82ª\95Ç\92n\8c`\82È\82ç\82ΠFALSE
423                 if(floorPtr->IsWall()) return false;
424                 return true;
425         }
426
427         void Creature::UpdateFieldLore(void)
428         {
429                 MAP_LENGTH x, y, cx, cy;
430                 std::vector<Coordinates> rangeVec;
431                 std::vector<Coordinates>::iterator rangeIt;
432                 if(fieldPtr == NULL) return;
433
434                 cx = this->position.GetX();
435                 cy = this->position.GetY();
436
437                 fieldPtr->GetSight(this->sightList, this->sightRange, cx, cy);
438                 for(y = -this->sightRange; y < this->sightRange; y++)
439                 {
440                         for(x = -this->sightRange; x < this->sightRange; x++)
441                         {
442                                 if(this->sightList[(y + this->sightRange) * (this->sightRange * 2 + 1) + x + this->sightRange]) this->GetLore()->PutFieldLore(0, cx + x, cy + y); 
443                         }
444                 }
445         }
446
447         void Creature::XMLSave(std::string filename)
448         {
449                 std::ofstream ofs(filename);
450                 assert(ofs);
451                 boost::archive::xml_oarchive oa(ofs);
452                 oa << boost::serialization::make_nvp("Creature", *this);
453         }
454
455         bool Creature::InSight(MAP_LENGTH x, MAP_LENGTH y)
456         {
457                 MAP_LENGTH rx = x - this->position.GetX();
458                 MAP_LENGTH ry = y - this->position.GetY();
459                 if(rx > this->sightRange || ry > this->sightRange || rx < -this->sightRange || ry < -this->sightRange)
460                 {
461                         return false;
462                 }
463
464                 if(x < 0 || y < 0 || x >= fieldPtr->GetWidth() || y >= fieldPtr->GetHeight())
465                 {
466                         return false;
467                 }
468
469                 return this->sightList[(ry + this->sightRange) * (this->sightRange * 2 + 1) + rx + this->sightRange];
470         }
471
472         ACTION_RESULT Creature::Walk(DIRECTION direction)
473         {
474                 Coordinates nextPoint = this->position + Direction::DirectionVector[direction];
475                 Square *nextSquarePtr = fieldPtr->GetSquare(nextPoint);
476                 Floor *floorPtr;
477                 Creature *targetPtr;
478
479                 if(!nextSquarePtr)
480                 {
481                         GameElement::GameSurfacePtr->GameMessage("\8e\9e\8bó\82Ì\95Ç\82É\8ds\82­\8eè\82ð\91j\82Ü\82ê\82Ä\82¢\82é\81B");
482                         return AR_FAILURE;
483                 }
484
485                 //! @note \88Ú\93®\90æ\82É\95Ê\82Ì\83N\83\8a\81[\83`\83\83\81[\82ª\91\8dÝ\82·\82é\82È\82ç\82Î\94\92\95º\8f\88\97\9d\82É\88Ú\8ds\82µ\82Ä FALSE
486                 targetPtr = GameElement::GameWorldPtr->GetCreatureFromPosition(this->GetFieldID(), &nextPoint);
487                 if(targetPtr)
488                 {
489                         this->Melee(targetPtr);
490                         GameElement::GameLoggerPtr->CreaturesCombated(this->GetName(), targetPtr->GetName());
491                         return AR_FAILURE;
492                 }
493
494                 floorPtr = nextSquarePtr->GetFloorPtr();
495                 if(!this->CanEnterPosition(floorPtr))
496                 {
497                         GameElement::GameSurfacePtr->GameMessage("\8ds\82­\8eè\82ð\91j\82Ü\82ê\82Ä\82¢\82é\81B");
498                         return AR_FAILURE;
499                 }
500
501                 this->position = nextPoint;
502                 this->UpdateFieldLore();
503                 GameElement::GameSurfacePtr->GameMessage("");
504                 return AR_SUCCESS;
505         }
506
507         ACTION_RESULT Creature::Open(DIRECTION direction)
508         {
509                 // TODO
510                 return AR_SUCCESS;
511         }
512
513         ACTION_RESULT Creature::Close(DIRECTION direction)
514         {
515                 // TODO
516                 return AR_SUCCESS;
517         }
518
519         ACTION_RESULT Creature::Disarm(DIRECTION direction)
520         {
521                 // TODO
522                 return AR_SUCCESS;
523         }
524
525         PLAY_EXIT_CODE Creature::DoGameCommand(GAME_COMMAND command)
526         {
527                 CREATURE_IT playerIt = GameElement::GameWorldPtr->GetPlayerCreature();
528
529                 switch(command)
530                 {
531                 case GAME_COMMAND_VIEW_PLAYER_STATUS:
532                         GameElement::GameSurfacePtr->ViewCreatureStatus(GameElement::GameWorldPtr->GetPlayerCreature()->second.get());
533                         break;
534                 case GAME_COMMAND_DEBUG_XML_SAVE:
535                         GameElement::GameWorldPtr->XMLSave();
536                         GameElement::GameSurfacePtr->SystemMessage("XML\82É\95Û\91\82µ\82Ü\82µ\82½\81B");
537                         break;
538                 case GAME_COMMAND_DEBUG_XML_LOAD:
539                         GameElement::GameSurfacePtr->Draw(playerIt);
540                         GameElement::GameWorldPtr->XMLLoad();
541                         GameElement::GameSurfacePtr->SystemMessage("XML\82©\82ç\8cÄ\82Ñ\8fo\82µ\82Ü\82µ\82½\81B");
542                         break;
543                 case GAME_COMMAND_EXIT:
544                         return PLAY_EXIT_QUIT;
545                         break;
546                 case GAME_COMMAND_NORTH:
547                         playerIt->second.get()->Walk(DIRECTION_NORTH);
548                         break;
549                 case GAME_COMMAND_NORTH_EAST:
550                         playerIt->second.get()->Walk(DIRECTION_NORTH_EAST);
551                         break;
552                 case GAME_COMMAND_EAST:
553                         playerIt->second.get()->Walk(DIRECTION_EAST);
554                         break;
555                 case GAME_COMMAND_SOUTH_EAST:
556                         playerIt->second.get()->Walk(DIRECTION_SOUTH_EAST);
557                         break;
558                 case GAME_COMMAND_SOUTH:
559                         playerIt->second.get()->Walk(DIRECTION_SOUTH);
560                         break;
561                 case GAME_COMMAND_SOUTH_WEST:
562                         playerIt->second.get()->Walk(DIRECTION_SOUTH_WEST);
563                         break;
564                 case GAME_COMMAND_WEST:
565                         playerIt->second.get()->Walk(DIRECTION_WEST);
566                         break;
567                 case GAME_COMMAND_NORTH_WEST:
568                         playerIt->second.get()->Walk(DIRECTION_NORTH_WEST);
569                         break;
570                 }
571                 return PLAY_EXIT_NONE;
572         }
573
574
575 }