OWEATHER.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. // Filename : OWEATHER.CPP
  21. // Description : class Weather
  22. // Ownership : Gilbert
  23. #include <OWEATHER.h>
  24. #include <ALL.h>
  25. #include <math.h>
  26. #include <OWORLDMT.h>
  27. //---------- Define constant -----------//
  28. #define RAIN_CLOUD 1
  29. #define LIGHTNING_CLOUD 2
  30. #define WINDY 4
  31. #define HOT_WAVE 8
  32. #define COLD_WAVE 0x10
  33. #define M_PI 3.14159265359
  34. //-------- Begin of function Lightning::rand_seed ----------//
  35. unsigned Weather::rand_seed(unsigned max)
  36. {
  37. #define MULTIPLIER 0x015a4e35L
  38. #define INCREMENT 1
  39. seed = MULTIPLIER * seed + INCREMENT;
  40. return seed % max;
  41. }
  42. //-------- End of function Lightning::rand_seed ----------//
  43. //---------- Begin of function Weather::init_date ----------//
  44. //
  45. void Weather::init_date(short year, short month, short day, short latitude, int quakeFreq)
  46. {
  47. // ----------- initialize random seed
  48. seed = 2*year+1;
  49. (void) rand_seed(10);
  50. // ----------- calculate season_phase from month, day ------------//
  51. season_phase = (short) ( month * 30.4 + day);
  52. season_phase = (season_phase + 365 - 98) % 365; // 7th Mar becomes 0
  53. // ----------- random number to earthquake -----------//
  54. quake_frequency = quakeFreq;
  55. day_to_quake = quakeFreq + rand_seed(quakeFreq);
  56. // ----------- determine avg_temp and temp_amp from latitude
  57. double angle = latitude * M_PI / 180.0;
  58. avg_temp = (short)( 35.0 - fabs(latitude / 90.0 * 40.0));
  59. temp_amp = (short)( 17.0 * sin(angle)); // negative for South Hemisphere
  60. // ----------- determine cloud ----------- //
  61. cur_cloud_str = rand_seed(4);
  62. cur_cloud_len = 5 + rand_seed(5);
  63. cur_cloud_type = 0;
  64. // ----------- determine wind ---------------//
  65. wind_dir = rand_seed(360);
  66. wind_spd = 10;
  67. high_wind_day = 0;
  68. windy_speed = 0;
  69. tornado_count = 1;
  70. }
  71. //---------- End of function Weather::init_date ----------//
  72. //---------- Begin of function Weather::next_day ----------//
  73. //
  74. void Weather::next_day()
  75. {
  76. season_phase = (season_phase + 1 )% 365;
  77. //---------- update/determine earthquake day ---------//
  78. if( day_to_quake)
  79. {
  80. day_to_quake--;
  81. if ( is_quake() )
  82. {
  83. // generate quake_x, quake_y
  84. quake_x = rand_seed(0x10000) * MAX_MAP_WIDTH / 0x10000;
  85. quake_y = rand_seed(0x10000) * MAX_MAP_HEIGHT / 0x10000;
  86. }
  87. }
  88. else
  89. day_to_quake = quake_frequency + rand_seed(quake_frequency);
  90. //---------- update wind ----------//
  91. wind_dir = (wind_dir + rand_seed(5) ) % 360;
  92. wind_spd += rand_seed(9) - 4 - (high_wind_day/16);
  93. if( wind_spd < -10)
  94. wind_spd = -10;
  95. if( wind_spd > 110)
  96. wind_spd = 110;
  97. if( wind_spd >= 20 )
  98. {
  99. high_wind_day++;
  100. }
  101. else
  102. {
  103. high_wind_day--;
  104. }
  105. //---------- generate cloud --------//
  106. if( cur_cloud_len > 0)
  107. {
  108. cur_cloud_len--;
  109. }
  110. else
  111. {
  112. short t = base_temp();
  113. short maxCloudStr;
  114. if( t >= 30)
  115. maxCloudStr = 10;
  116. else if( t <= 18)
  117. maxCloudStr = 4;
  118. else
  119. maxCloudStr = (t -18)/2 + 4;
  120. cur_cloud_str = rand_seed(maxCloudStr+4)-3; // range : -2 to maxCloudStr
  121. if(cur_cloud_str < 0)
  122. cur_cloud_str = 0;
  123. cur_cloud_len = 2 + rand_seed(3) + rand_seed(3);
  124. cur_cloud_type = 0;
  125. // ------- summer weather
  126. if( cur_cloud_str > 4)
  127. {
  128. if( (char) rand_seed(10) < cur_cloud_str )
  129. cur_cloud_type |= RAIN_CLOUD;
  130. if( cur_cloud_str >= 6 && (char) rand_seed(10) < cur_cloud_str-4)
  131. cur_cloud_type |= WINDY;
  132. }
  133. if( cur_cloud_str <= 1 && t >= 30 && rand_seed(10) <= 1)
  134. {
  135. cur_cloud_type |= HOT_WAVE;
  136. }
  137. // ------- winter weather
  138. if( t < 15)
  139. {
  140. if( rand_seed(20) < 2 )
  141. cur_cloud_type |= COLD_WAVE;
  142. if( t >= 10 && rand_seed(10) < 3)
  143. cur_cloud_type |= WINDY;
  144. if( t < 10 && rand_seed(10) < 7)
  145. cur_cloud_type |= WINDY;
  146. }
  147. if( cur_cloud_type & WINDY)
  148. windy_speed = 10 + cur_cloud_str * 5 + rand_seed(2*cur_cloud_str+1);
  149. else
  150. {
  151. windy_speed = 0;
  152. if( cur_cloud_str > 4 && (char)rand_seed(50) < cur_cloud_str + 2 )
  153. cur_cloud_type |= LIGHTNING_CLOUD;
  154. }
  155. // ---- double the time of snow ------ //
  156. if( snow_scale() )
  157. cur_cloud_len += cur_cloud_len;
  158. }
  159. // -------- update tornado_count, at least 20 days between two tornadoes -------//
  160. if( tornado_count > 20 && base_temp() >= 30 && wind_speed() >= 40
  161. && rand_seed(10)==0 )
  162. {
  163. tornado_count = 0; // today has a tornado
  164. }
  165. else
  166. {
  167. tornado_count++;
  168. }
  169. }
  170. //---------- End of function Weather::next_day ----------//
  171. //---------- Begin of function Weather::base_temp ----------//
  172. //
  173. short Weather::base_temp()
  174. {
  175. return( (short)(avg_temp + temp_amp * sin(season_phase / 365.0
  176. * 2 * M_PI) ));
  177. }
  178. //---------- End of function Weather::base_temp ----------//
  179. //---------- Begin of function Weather::cloud ----------//
  180. //
  181. short Weather::cloud()
  182. {
  183. if( cur_cloud_str < 0)
  184. return 0;
  185. if( cur_cloud_str > 10)
  186. return 10;
  187. return cur_cloud_str;
  188. }
  189. //---------- End of function Weather::cloud ----------//
  190. //---------- Begin of function Weather::temp_c ----------//
  191. //
  192. short Weather::temp_c()
  193. {
  194. return base_temp() - (cur_cloud_str < 1 ? 0 : (cur_cloud_str < 4 ? 2:4)) +
  195. (cur_cloud_type & HOT_WAVE ? 8:0) - (cur_cloud_type & COLD_WAVE ? 10:0);
  196. }
  197. //---------- End of function Weather::temp_c ----------//
  198. //---------- Begin of function Weather::temp_f ----------//
  199. //
  200. short Weather::temp_f()
  201. {
  202. return ((short) (base_temp() / 5.0 * 9.0 + 32.0 ));
  203. }
  204. //---------- End of function Weather::temp_f ----------//
  205. //---------- Begin of function Weather::wind_speed ----------//
  206. //
  207. short Weather::wind_speed()
  208. {
  209. if( this == &weather && magic_weather.wind_day > 0)
  210. return magic_weather.wind_speed();
  211. short w = wind_spd + windy_speed;
  212. if(w < 0)
  213. return 0;
  214. if(w > 100)
  215. return 100;
  216. return w;
  217. }
  218. //---------- End of function Weather::wind_speed ----------//
  219. //---------- Begin of function Weather::wind_direct ----------//
  220. //
  221. short Weather::wind_direct()
  222. {
  223. if( this == &weather && magic_weather.wind_day > 0)
  224. return magic_weather.wind_direct();
  225. return wind_dir;
  226. }
  227. //---------- End of function Weather::wind_direct ----------//
  228. //---------- Begin of function Weather::wind_direct_rad ----------//
  229. //
  230. double Weather::wind_direct_rad()
  231. {
  232. if( this == &weather && magic_weather.wind_day > 0)
  233. return magic_weather.wind_direct_rad();
  234. return wind_dir * M_PI / 180.0;
  235. }
  236. //---------- End of function Weather::wind_direct ----------//
  237. //---------- Begin of function Weather::rain_scale ----------//
  238. //
  239. short Weather::rain_scale()
  240. {
  241. if( this == &weather && magic_weather.rain_day > 0)
  242. return magic_weather.rain_scale();
  243. return cur_cloud_str > 4 ? cur_cloud_str * 2 -8 : 0;
  244. }
  245. //---------- End of function Weather::rain_scale ----------//
  246. //---------- Begin of function Weather::snow_scale ----------//
  247. //
  248. short Weather::snow_scale()
  249. {
  250. short t = temp_c();
  251. if( t > 0)
  252. return 0;
  253. if( t <= -15)
  254. {
  255. if( t <= -30)
  256. return 8;
  257. if( t <= -25)
  258. return 7;
  259. if( t <= -20)
  260. return 6;
  261. return 5;
  262. }
  263. else
  264. {
  265. if(t <= -10)
  266. return 4;
  267. if( t <= -5)
  268. return 3;
  269. if( t <= -2)
  270. return 2;
  271. return 1;
  272. }
  273. }
  274. //---------- End of function Weather::snow_scale ----------//
  275. //---------- Begin of function Weather::is_lightning ----------//
  276. //
  277. char Weather::is_lightning()
  278. {
  279. if( magic_weather.lightning_day > 0 )
  280. return LIGHTNING_CLOUD;
  281. return( cur_cloud_type & LIGHTNING_CLOUD );
  282. }
  283. //---------- End of function Weather::is_lightning ----------//
  284. //---------- Begin of function Weather::is_quake ----------//
  285. //
  286. char Weather::is_quake()
  287. {
  288. return( day_to_quake == 0);
  289. }
  290. //---------- End of function Weather::is_quake ----------//
  291. //---------- Begin of function Weather::desc ---------//
  292. //
  293. WeatherType Weather::desc()
  294. {
  295. int w = WEATHER_SUNNY;
  296. if( rain_scale() > 0 )
  297. w |= WEATHER_RAIN;
  298. if( is_lightning() )
  299. w |= WEATHER_LIGHTNING;
  300. if( snow_scale() > 0 )
  301. w |= WEATHER_SNOW;
  302. else if( cur_cloud_type & COLD_WAVE)
  303. w |= WEATHER_COLD_WAVE;
  304. if( cur_cloud_type & HOT_WAVE)
  305. w |= WEATHER_HOT_WAVE;
  306. if( cur_cloud_type & WINDY)
  307. w |= WEATHER_WINDY;
  308. if( w == WEATHER_SUNNY && cloud() >= 4)
  309. w |= WEATHER_CLOUDY;
  310. return (WeatherType)w;
  311. }
  312. //---------- End of function Weather::desc ---------//
  313. //---------- Begin of function Weather::has_tornado -------//
  314. char Weather::has_tornado()
  315. {
  316. return tornado_count == 0;
  317. }
  318. //---------- End of function Weather::has_tornado -------//
  319. //---------- Begin of function Weather::tornado_x_loc -------//
  320. //
  321. // return where a new tornado should create
  322. //
  323. short Weather::tornado_x_loc(short maxXLoc, short)
  324. {
  325. short dir = (wind_direct() + 180) % 360;
  326. err_when(dir < 0 || dir > 360);
  327. if( dir < 45)
  328. {
  329. // north side
  330. return maxXLoc*(dir+45)/90;
  331. }
  332. else if( dir < 135)
  333. {
  334. // east side
  335. return maxXLoc-1;
  336. }
  337. else if( dir < 225)
  338. {
  339. // south side
  340. return maxXLoc*(224-dir)/90;
  341. }
  342. else if( dir < 315)
  343. {
  344. // west side
  345. return 0;
  346. }
  347. else
  348. {
  349. // north side
  350. return maxXLoc*(dir-315)/90;
  351. }
  352. }
  353. //---------- End of function Weather::tornado_x_loc -------//
  354. //---------- Begin of function Weather::tornado_y_loc -------//
  355. short Weather::tornado_y_loc(short , short maxYLoc)
  356. {
  357. short dir = (wind_direct() + 180) % 360;
  358. err_when(dir < 0 || dir > 360);
  359. if( dir < 45)
  360. {
  361. // north side
  362. return 0;
  363. }
  364. else if( dir < 135)
  365. {
  366. // east side
  367. return maxYLoc*(dir-45)/90;
  368. }
  369. else if( dir < 225)
  370. {
  371. // south side
  372. return maxYLoc -1;
  373. }
  374. else if( dir < 315)
  375. {
  376. // west side
  377. return maxYLoc*(314-dir)/90;
  378. }
  379. else
  380. {
  381. // north side
  382. return 0;
  383. }
  384. }
  385. //---------- End of function Weather::tornado_y_loc -------//
  386. //---------- Begin of function Weather::quake_rate -------//
  387. short Weather::quake_rate(short x, short y)
  388. {
  389. err_when( !is_quake() );
  390. short dist = max( abs(x - quake_x), abs(y - quake_y) );
  391. short damage = 100 - dist / 2;
  392. return damage > 0 ? damage : 0;
  393. }
  394. //---------- End of function Weather::quake_rate -------//
  395. //--------- Begin of function MagicWeather::init ----------//
  396. void MagicWeather::init()
  397. {
  398. rain_day = 0;
  399. wind_day = 0;
  400. }
  401. //--------- End function MagicWeather::init ----------//
  402. //--------- Begin of function MagicWeather::next_day ----------//
  403. void MagicWeather::next_day()
  404. {
  405. if( rain_day > 0 )
  406. --rain_day;
  407. if( wind_day > 0 )
  408. --wind_day;
  409. if( lightning_day > 0 )
  410. --lightning_day;
  411. }
  412. //--------- End function MagicWeather::next_day ----------//
  413. //--------- Begin of function MagicWeather::cast_rain ----------//
  414. void MagicWeather::cast_rain(short duration, char rainScale)
  415. {
  416. // override last cast_rain
  417. rain_day = duration;
  418. rain_str = rainScale;
  419. }
  420. //--------- End of function MagicWeather::cast_rain ----------//
  421. //--------- Begin of function MagicWeather::cast_wind ----------//
  422. void MagicWeather::cast_wind(short duration, short speed, short direction)
  423. {
  424. // override last cast_wind
  425. wind_day = duration;
  426. wind_spd = speed;
  427. wind_dir = direction;
  428. }
  429. //--------- End of function MagicWeather::cast_wind ----------//
  430. //--------- Begin of function MagicWeather::cast_lightning ----------//
  431. void MagicWeather::cast_lightning(short duration)
  432. {
  433. // override last cast_lightning
  434. lightning_day = duration;
  435. }
  436. //--------- End of function MagicWeather::cast_lightning ----------//
  437. //--------- Begin of function MagicWeather::wind_speed ----------//
  438. short MagicWeather::wind_speed()
  439. {
  440. return wind_spd;
  441. }
  442. //--------- End of function MagicWeather::wind_speed ----------//
  443. //--------- Begin of function MagicWeather::wind_direct ----------//
  444. short MagicWeather::wind_direct()
  445. {
  446. return wind_dir;
  447. }
  448. //--------- End of function MagicWeather::wind_direct ----------//
  449. //--------- Begin of function MagicWeather::wind_direct_rad ----------//
  450. double MagicWeather::wind_direct_rad()
  451. {
  452. return wind_dir * M_PI / 180.0;
  453. }
  454. //--------- End of function MagicWeather::wind_direct_rad ----------//
  455. //--------- Begin of function MagicWeather::rain_scale ----------//
  456. short MagicWeather::rain_scale()
  457. {
  458. return rain_str;
  459. }
  460. //--------- End of function MagicWeather::rain_scale ----------//