1 /***************************************************************************
2  *   Copyright (C) 2009 by Andrey Afletdinov <fheroes2@gmail.com>          *
3  *                                                                         *
4  *   Part of the Free Heroes2 Engine:                                      *
5  *   http://sourceforge.net/projects/fheroes2                              *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 
23 #include "week.h"
24 #include "rand.h"
25 #include "serialize.h"
26 #include "tools.h"
27 #include "translations.h"
28 #include "world.h"
29 
30 namespace
31 {
WeekRand(const World & worldInstance,const size_t seed)32     WeekName WeekRand( const World & worldInstance, const size_t seed )
33     {
34         return ( 0 == ( worldInstance.CountWeek() + 1 ) % 3 ) ? WeekName::MONSTERS : Rand::GetWithSeed( WeekName::ANT, WeekName::CONDOR, static_cast<uint32_t>( seed ) );
35     }
36 
MonthRand(const World & worldInstance,const size_t seed)37     WeekName MonthRand( const World & worldInstance, const size_t seed )
38     {
39         return ( 0 == ( worldInstance.GetMonth() + 1 ) % 3 ) ? WeekName::MONSTERS
40                                                              : Rand::GetWithSeed( WeekName::PLAGUE, WeekName::CONDOR, static_cast<uint32_t>( seed ) );
41     }
42 
RandomMonsterWeekOf(const size_t seed)43     Monster::monster_t RandomMonsterWeekOf( const size_t seed )
44     {
45         switch ( Rand::GetWithSeed( 1, 47, static_cast<uint32_t>( seed ) ) ) {
46         case 1:
47             return Monster::PEASANT;
48         case 2:
49             return Monster::ARCHER;
50         case 3:
51             return Monster::RANGER;
52         case 4:
53             return Monster::PIKEMAN;
54         case 5:
55             return Monster::VETERAN_PIKEMAN;
56         case 6:
57             return Monster::SWORDSMAN;
58         case 7:
59             return Monster::MASTER_SWORDSMAN;
60         case 8:
61             return Monster::CAVALRY;
62         case 9:
63             return Monster::CHAMPION;
64         case 10:
65             return Monster::GOBLIN;
66         case 11:
67             return Monster::ORC;
68         case 12:
69             return Monster::ORC_CHIEF;
70         case 13:
71             return Monster::WOLF;
72         case 14:
73             return Monster::OGRE;
74         case 15:
75             return Monster::OGRE_LORD;
76         case 16:
77             return Monster::TROLL;
78         case 17:
79             return Monster::WAR_TROLL;
80         case 18:
81             return Monster::SPRITE;
82         case 19:
83             return Monster::DWARF;
84         case 20:
85             return Monster::BATTLE_DWARF;
86         case 21:
87             return Monster::ELF;
88         case 22:
89             return Monster::GRAND_ELF;
90         case 23:
91             return Monster::DRUID;
92         case 24:
93             return Monster::GREATER_DRUID;
94         case 25:
95             return Monster::UNICORN;
96         case 26:
97             return Monster::CENTAUR;
98         case 27:
99             return Monster::GARGOYLE;
100         case 28:
101             return Monster::GRIFFIN;
102         case 29:
103             return Monster::MINOTAUR;
104         case 30:
105             return Monster::MINOTAUR_KING;
106         case 31:
107             return Monster::HYDRA;
108         case 32:
109             return Monster::HALFLING;
110         case 33:
111             return Monster::BOAR;
112         case 34:
113             return Monster::IRON_GOLEM;
114         case 35:
115             return Monster::STEEL_GOLEM;
116         case 36:
117             return Monster::ROC;
118         case 37:
119             return Monster::MAGE;
120         case 38:
121             return Monster::ARCHMAGE;
122         case 39:
123             return Monster::SKELETON;
124         case 40:
125             return Monster::ZOMBIE;
126         case 41:
127             return Monster::MUTANT_ZOMBIE;
128         case 42:
129             return Monster::MUMMY;
130         case 43:
131             return Monster::ROYAL_MUMMY;
132         case 44:
133             return Monster::VAMPIRE;
134         case 45:
135             return Monster::VAMPIRE_LORD;
136         case 46:
137             return Monster::LICH;
138         case 47:
139             return Monster::POWER_LICH;
140         default:
141             assert( 0 );
142             return Monster::UNKNOWN;
143         }
144     }
145 
RandomMonsterMonthOf(const size_t seed)146     Monster::monster_t RandomMonsterMonthOf( const size_t seed )
147     {
148         switch ( Rand::GetWithSeed( 1, 30, static_cast<uint32_t>( seed ) ) ) {
149         case 1:
150             return Monster::PEASANT;
151         case 2:
152             return Monster::ARCHER;
153         case 3:
154             return Monster::PIKEMAN;
155         case 4:
156             return Monster::SWORDSMAN;
157         case 5:
158             return Monster::CAVALRY;
159         case 6:
160             return Monster::GOBLIN;
161         case 7:
162             return Monster::ORC;
163         case 8:
164             return Monster::WOLF;
165         case 9:
166             return Monster::OGRE;
167         case 10:
168             return Monster::TROLL;
169         case 11:
170             return Monster::SPRITE;
171         case 12:
172             return Monster::DWARF;
173         case 13:
174             return Monster::ELF;
175         case 14:
176             return Monster::DRUID;
177         case 15:
178             return Monster::UNICORN;
179         case 16:
180             return Monster::CENTAUR;
181         case 17:
182             return Monster::GARGOYLE;
183         case 18:
184             return Monster::GRIFFIN;
185         case 19:
186             return Monster::MINOTAUR;
187         case 20:
188             return Monster::HYDRA;
189         case 21:
190             return Monster::HALFLING;
191         case 22:
192             return Monster::BOAR;
193         case 23:
194             return Monster::IRON_GOLEM;
195         case 24:
196             return Monster::ROC;
197         case 25:
198             return Monster::MAGE;
199         case 26:
200             return Monster::SKELETON;
201         case 27:
202             return Monster::ZOMBIE;
203         case 28:
204             return Monster::MUMMY;
205         case 29:
206             return Monster::VAMPIRE;
207         case 30:
208             return Monster::LICH;
209         default:
210             assert( 0 );
211             return Monster::UNKNOWN;
212         }
213     }
214 }
215 
GetName(void) const216 const char * Week::GetName( void ) const
217 {
218     switch ( _week ) {
219     case WeekName::PLAGUE:
220         return _( "week|PLAGUE" );
221     case WeekName::ANT:
222         return _( "week|Ant" );
223     case WeekName::GRASSHOPPER:
224         return _( "week|Grasshopper" );
225     case WeekName::DRAGONFLY:
226         return _( "week|Dragonfly" );
227     case WeekName::SPIDER:
228         return _( "week|Spider" );
229     case WeekName::BUTTERFLY:
230         return _( "week|Butterfly" );
231     case WeekName::BUMBLEBEE:
232         return _( "week|Bumblebee" );
233     case WeekName::LOCUST:
234         return _( "week|Locust" );
235     case WeekName::EARTHWORM:
236         return _( "week|Earthworm" );
237     case WeekName::HORNET:
238         return _( "week|Hornet" );
239     case WeekName::BEETLE:
240         return _( "week|Beetle" );
241     case WeekName::SQUIRREL:
242         return _( "week|Squirrel" );
243     case WeekName::RABBIT:
244         return _( "week|Rabbit" );
245     case WeekName::GOPHER:
246         return _( "week|Gopher" );
247     case WeekName::BADGER:
248         return _( "week|Badger" );
249     case WeekName::EAGLE:
250         return _( "week|Eagle" );
251     case WeekName::WEASEL:
252         return _( "week|Weasel" );
253     case WeekName::RAVEN:
254         return _( "week|Raven" );
255     case WeekName::MONGOOSE:
256         return _( "week|Mongoose" );
257     case WeekName::AARDVARK:
258         return _( "week|Aardvark" );
259     case WeekName::LIZARD:
260         return _( "week|Lizard" );
261     case WeekName::TORTOISE:
262         return _( "week|Tortoise" );
263     case WeekName::HEDGEHOG:
264         return _( "week|Hedgehog" );
265     case WeekName::CONDOR:
266         return _( "week|Condor" );
267     case WeekName::MONSTERS:
268         return Monster( _monster ).GetName();
269     default:
270         break;
271     }
272 
273     return "Unnamed";
274 }
275 
RandomWeek(const World & worldInstance,const bool isNewMonth,const size_t weekSeed)276 Week Week::RandomWeek( const World & worldInstance, const bool isNewMonth, const size_t weekSeed )
277 {
278     size_t weekTypeSeed = weekSeed;
279     fheroes2::hashCombine( weekTypeSeed, 34582445 ); // random value to add salt
280 
281     const WeekName weekName = isNewMonth ? MonthRand( worldInstance, weekTypeSeed ) : WeekRand( worldInstance, weekTypeSeed );
282 
283     if ( weekName == WeekName::MONSTERS ) {
284         size_t monsterTypeSeed = weekSeed;
285         fheroes2::hashCombine( monsterTypeSeed, 284631 ); // random value to add salt
286         if ( isNewMonth ) {
287             return { weekName, RandomMonsterMonthOf( monsterTypeSeed ) };
288         }
289 
290         return { weekName, RandomMonsterWeekOf( monsterTypeSeed ) };
291     }
292 
293     return { weekName, Monster::UNKNOWN };
294 }
295 
operator >>(StreamBase & stream,Week & week)296 StreamBase & operator>>( StreamBase & stream, Week & week )
297 {
298     int32_t weekType;
299     int32_t monster;
300     StreamBase & sb = stream >> weekType >> monster;
301     week._week = static_cast<WeekName>( weekType );
302     week._monster = static_cast<Monster::monster_t>( monster );
303     return sb;
304 }
305 
operator <<(StreamBase & stream,const Week & week)306 StreamBase & operator<<( StreamBase & stream, const Week & week )
307 {
308     return stream << static_cast<int32_t>( week.GetType() ) << static_cast<int32_t>( week.GetMonster() );
309 }
310