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