OBATTLE.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  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 : OBATTLE.CPP
  21. //Description : Battle Object
  22. #include <OSYS.h>
  23. #include <OWORLD.h>
  24. #include <OPOWER.h>
  25. #include <OCONFIG.h>
  26. #include <OSPY.h>
  27. #include <OMOUSE.h>
  28. #include <OMUSIC.h>
  29. #include <OSITE.h>
  30. #include <ORACERES.h>
  31. #include <OGODRES.h>
  32. #include <OTECHRES.h>
  33. #include <OCONFIG.h>
  34. #include <OREMOTE.h>
  35. #include <OTOWN.h>
  36. #include <OFIRM.h>
  37. #include <ONEWS.h>
  38. #include <ONATION.h>
  39. #include <OMONSRES.h>
  40. #include <OWALLRES.h>
  41. #include <OINFO.h>
  42. #include <OUNITALL.h>
  43. #include <OGAME.h>
  44. #include <OBATTLE.h>
  45. #include <OMOUSECR.h>
  46. //---------- define static functions -------------//
  47. static int is_space(int xLoc1, int yLoc1, int xLoc2, int yLoc2, char mobileType);
  48. //-------- Begin of function Battle::init --------//
  49. //
  50. void Battle::init()
  51. {
  52. }
  53. //-------- End of function Battle::init --------//
  54. //-------- Begin of function Battle::deinit --------//
  55. //
  56. void Battle::deinit()
  57. {
  58. }
  59. //-------- End of function Battle::deinit --------//
  60. //-------- Begin of function Battle::run --------//
  61. //
  62. // <int> mpGame - whether this is a multiplayer game or not.
  63. //
  64. void Battle::run(NewNationPara *mpGame, int mpPlayerCount)
  65. {
  66. int oldCursor = mouse_cursor.get_icon();
  67. mouse_cursor.set_icon(CURSOR_WAITING);
  68. #ifdef DEBUG
  69. debug_sim_game_type = (m.is_file_exist("sim.sys")) ? 2 : 0;
  70. if(debug_sim_game_type)
  71. {
  72. run_sim();
  73. return;
  74. }
  75. #endif
  76. // ####### begin Gilbert 24/10 #######//
  77. //-- random seed is initalized at connecting multiplayer --//
  78. //if( !mpGame )
  79. // info.init_random_seed(0);
  80. // ####### end Gilbert 24/10 #######//
  81. //----------- save the current seed for generating map -----------//
  82. #ifdef DEBUG2
  83. File seedFile;
  84. char *chPtr = m.format(m.get_random_seed());
  85. seedFile.file_create("mapseed.rs");
  86. seedFile.file_write(chPtr, strlen(chPtr));
  87. seedFile.file_close();
  88. #endif
  89. world.generate_map();
  90. //------- create player nation --------//
  91. if( !mpGame )
  92. {
  93. // if config.race_id == 0, select a random race, but don't call m.random
  94. int nationRecno = nation_array.new_nation( NATION_OWN,
  95. config.race_id ? config.race_id : 1+m.get_time() % MAX_RACE,
  96. config.player_nation_color );
  97. nation_array.set_human_name( nationRecno, config.player_name );
  98. }
  99. else
  100. {
  101. for( int i = 0; i < mpPlayerCount; ++i )
  102. {
  103. int nationRecno = nation_array.new_nation(mpGame[i]);
  104. if( nationRecno != mpGame[i].nation_recno )
  105. err.run( "Unexpected nation recno created" );
  106. nation_array.set_human_name( nationRecno, mpGame[i].player_name );
  107. }
  108. }
  109. //--------- create ai nations --------//
  110. if( mpGame )
  111. {
  112. int aiToCreate = config.ai_nation_count;
  113. if( aiToCreate + mpPlayerCount > MAX_NATION )
  114. aiToCreate = MAX_NATION - mpPlayerCount;
  115. err_when( aiToCreate < 0 );
  116. create_ai_nation(aiToCreate);
  117. }
  118. else
  119. {
  120. create_ai_nation(config.ai_nation_count);
  121. }
  122. //------ create pregame objects ------//
  123. create_pregame_object();
  124. //------- update nation statistic -------//
  125. nation_array.update_statistic();
  126. //--- highlight the player's town in the beginning of the game ---//
  127. Town* townPtr;
  128. for( int i=1 ; i<=town_array.size() ; i++ )
  129. {
  130. townPtr = town_array[i];
  131. if( townPtr->nation_recno == nation_array.player_recno )
  132. {
  133. world.go_loc( townPtr->loc_x1, townPtr->loc_y1 );
  134. break;
  135. }
  136. }
  137. //---- reset config parameter ----//
  138. sys.set_speed(12); // set the speed to normal.
  139. //---- reset cheats ----//
  140. config.fast_build = 0;
  141. config.king_undie_flag = sys.testing_session && !mpGame;
  142. config.blacken_map = 1;
  143. config.disable_ai_flag = 0;
  144. if( sys.testing_session )
  145. config.show_unit_path = 3;
  146. // ######## begin Gilbert 11/11 #######//
  147. // enable tech and god, useful for multi-player
  148. #if(0)
  149. for( i = 1; i < nation_array.size(); ++i )
  150. {
  151. if( !nation_array.is_deleted(i) && !nation_array[i]->is_ai() )
  152. {
  153. tech_res.inc_all_tech_level(i);
  154. god_res.enable_know_all(i);
  155. }
  156. }
  157. #endif
  158. // ######## end Gilbert 11/11 #######//
  159. //------- enable/disable sound effects -------//
  160. #ifdef AMPLUS
  161. int songId = (~nation_array)->race_id <= 7 ? (~nation_array)->race_id+1 : music.random_bgm_track();
  162. music.play(songId, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
  163. #else
  164. music.play((~nation_array)->race_id +1, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
  165. #endif
  166. mouse_cursor.restore_icon(oldCursor);
  167. //--- give the control to the system main loop, start the game now ---//
  168. sys.run();
  169. }
  170. //--------- End of function Battle::run ---------//
  171. //-------- Begin of function Battle::run_sim --------//
  172. // run simulation
  173. //
  174. #ifdef DEBUG
  175. void Battle::run_sim()
  176. {
  177. err_when(!debug_sim_game_type);
  178. info.disp_panel();
  179. //info.init_random_seed(0);
  180. //info.init_random_seed(869451513); // for testing marine
  181. info.init_random_seed(869639665); // for testing marine
  182. //info.init_random_seed(866608391);
  183. //info.init_random_seed(866621716);
  184. //info.init_random_seed(867299236);
  185. world.generate_map();
  186. //--------- refresh world ---------//
  187. world.refresh();
  188. vga.blt_buf(0, 0, VGA_WIDTH-1, VGA_HEIGHT-1);
  189. world.paint();
  190. //------- create player nation --------//
  191. // if config.race_id == 0, select a random race, but don't call m.random
  192. nation_array.new_nation( NATION_OWN,
  193. config.race_id ? config.race_id : 1+m.get_time() % MAX_RACE,
  194. config.player_nation_color );
  195. //--------- create ai nations --------//
  196. create_ai_nation(config.ai_nation_count);
  197. //------ create pregame objects ------//
  198. create_pregame_object();
  199. //--- highlight the player's town in the beginning of the game ---//
  200. Town* townPtr;
  201. for( int i=1 ; i<=town_array.size() ; i++ )
  202. {
  203. townPtr = town_array[i];
  204. if( townPtr->nation_recno == nation_array.player_recno )
  205. {
  206. world.go_loc( townPtr->loc_x1, townPtr->loc_y1 );
  207. break;
  208. }
  209. }
  210. //-*************** create units, objects *****************-//
  211. int maxNationCount = 2;
  212. int unitId = UNIT_DRAGON;
  213. int nationCount;
  214. SpriteInfo *spriteInfo;
  215. char teraMask;
  216. int unitRecno, x, y, xLoc, yLoc;
  217. //--------- create dragon ---------//
  218. spriteInfo = sprite_res[unit_res[unitId]->sprite_id];
  219. teraMask = UnitRes::mobile_type_to_mask(unit_res[unitId]->mobile_type);
  220. for(nationCount=1; nationCount<=maxNationCount; nationCount++)
  221. {
  222. xLoc = 0;
  223. yLoc = min(20*nationCount, 180);
  224. for(int createCount=0; createCount<10; createCount++, xLoc+=4) // createCount<50
  225. {
  226. for(y=0; y<4; y+=2)
  227. {
  228. for(x=0; x<4; x+=2)
  229. {
  230. unitRecno = unit_array.add_unit(unitId, nationCount, RANK_SOLDIER, 100, xLoc+x, yLoc+y);
  231. unit_array[unitRecno]->set_combat_level(100);
  232. ((UnitGod*)unit_array[unitRecno])->god_id = 1;
  233. }
  234. }
  235. }
  236. }
  237. //--------- create marine units ---------//
  238. unitId = UNIT_CARAVEL;
  239. spriteInfo = sprite_res[unit_res[unitId]->sprite_id];
  240. teraMask = UnitRes::mobile_type_to_mask(unit_res[unitId]->mobile_type);
  241. for(nationCount=1; nationCount<=maxNationCount; nationCount++)
  242. {
  243. for(int t=0; t<30; t++)
  244. {
  245. xLoc=0;
  246. yLoc=0;
  247. if(world.locate_space_random(xLoc, yLoc, MAX_WORLD_X_LOC-1,
  248. MAX_WORLD_Y_LOC-1, spriteInfo->loc_width*4, spriteInfo->loc_height*4,
  249. MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC, 0, 0, teraMask))
  250. {
  251. if(xLoc%2)
  252. xLoc++;
  253. if(yLoc%2)
  254. yLoc++;
  255. for(y=0; y<2; y++)
  256. {
  257. for(x=0; x<2; x++)
  258. {
  259. //world.get_loc(startXLoc, startYLoc)->can_move(unit_res[unit_id]->mobile_type)
  260. unitRecno = unit_array.add_unit(unitId, nationCount, RANK_SOLDIER, 100, xLoc+x*2, yLoc+y*2);
  261. unit_array[unitRecno]->set_combat_level(100);
  262. }
  263. }
  264. }
  265. }
  266. }
  267. //--------- create land units ---------//
  268. for(nationCount=1; nationCount<=maxNationCount; nationCount++)
  269. {
  270. for(unitId=UNIT_NORMAN; unitId<=UNIT_JAPANESE; unitId++)
  271. {
  272. spriteInfo = sprite_res[unit_res[unitId]->sprite_id];
  273. teraMask = UnitRes::mobile_type_to_mask(unit_res[unitId]->mobile_type);
  274. for(int t=0; t<5; t++)
  275. {
  276. xLoc=0;
  277. yLoc=0;
  278. if(world.locate_space_random(xLoc, yLoc, MAX_WORLD_X_LOC-1,
  279. MAX_WORLD_Y_LOC-1, spriteInfo->loc_width*2, spriteInfo->loc_height*2,
  280. MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC, 0, 0, teraMask))
  281. {
  282. for(y=0; y<2; y++)
  283. {
  284. for(x=0; x<2; x++)
  285. {
  286. //world.get_loc(startXLoc, startYLoc)->can_move(unit_res[unit_id]->mobile_type)
  287. unitRecno = unit_array.add_unit(unitId, nationCount, RANK_SOLDIER, 100, xLoc+x, yLoc+y);
  288. unit_array[unitRecno]->set_combat_level(100);
  289. }
  290. }
  291. }
  292. }
  293. }
  294. }
  295. //-- enable power after the game objets has been initialized --//
  296. power.enable(); // enable power, which handle mouse inputs
  297. //--- give the control to the system main loop, start the game now ---//
  298. sys.run();
  299. }
  300. #endif
  301. //--------- End of function Battle::run_sim ---------//
  302. //-------- Begin of function Battle::create_ai_nation --------//
  303. //
  304. // Create AI nations.
  305. //
  306. void Battle::create_ai_nation(int aiNationCount)
  307. {
  308. int raceId;
  309. for( int i=0 ; i<aiNationCount ; i++ )
  310. {
  311. err_when( nation_array.size() == MAX_NATION );
  312. if( config.random_start_up )
  313. raceId = m.random(MAX_RACE)+1;
  314. else
  315. raceId = nation_array.random_unused_race();
  316. err_when( raceId < 1 || raceId > MAX_RACE );
  317. int nationRecno;
  318. nationRecno = nation_array.new_nation( NATION_AI, raceId, nation_array.random_unused_color() ); // 2nd parameter = the race id., 3rd parameters = color scheme id.
  319. }
  320. }
  321. //--------- End of function Battle::create_ai_nation ---------//
  322. //-------- Begin of function Battle::create_pregame_object --------//
  323. //
  324. // Initialize pre-game objects - towns, sites, independent towns.
  325. //
  326. void Battle::create_pregame_object()
  327. {
  328. #define CREATE_UNIT_AREA_WIDTH 16
  329. #define CREATE_UNIT_AREA_HEIGHT 16
  330. // ###### begin Gilbert 24/10 ######//
  331. const int dispProgress = 1;
  332. const int maxGenMapSteps = 100;
  333. const int newWorldSection = 1;
  334. vga_front.unlock_buf();
  335. int curGenMapSteps = 0;
  336. if( dispProgress )
  337. {
  338. vga_front.lock_buf();
  339. game.disp_gen_map_status( curGenMapSteps, maxGenMapSteps, newWorldSection);
  340. vga_front.unlock_buf();
  341. }
  342. // ###### end Gilbert 24/10 ######//
  343. //------- create nation and units --------//
  344. int nationRecno, unitId, rankId, xLoc, yLoc, townRecno;
  345. int kingUnitRecno;
  346. int noSpaceFlag=0;
  347. Nation* nationPtr;
  348. for( nationRecno=1 ; nationRecno<=nation_array.size() ; nationRecno++ )
  349. {
  350. if( nation_array.is_deleted(nationRecno) )
  351. continue;
  352. nationPtr = nation_array[nationRecno];
  353. //--------- create town -----------//
  354. townRecno = create_town( nationRecno, nationPtr->race_id, xLoc, yLoc );
  355. if( !townRecno )
  356. {
  357. noSpaceFlag = 1;
  358. break;
  359. }
  360. //------- create military camp -------//
  361. Town* townPtr = town_array[townRecno];
  362. int firmRecno = firm_array.build_firm(townPtr->loc_x1+6, townPtr->loc_y1,
  363. nationRecno, FIRM_CAMP, race_res[nationPtr->race_id]->code);
  364. if( !firmRecno )
  365. {
  366. noSpaceFlag = 1;
  367. break;
  368. }
  369. firm_array[firmRecno]->complete_construction();
  370. //--------- create units ----------//
  371. unitId = race_res[nationPtr->race_id]->basic_unit_id;
  372. kingUnitRecno = create_unit(townRecno, unitId, RANK_KING);
  373. if( kingUnitRecno )
  374. {
  375. nation_array[nationRecno]->set_king(kingUnitRecno, 1); // 1-this is the first king of the nation
  376. firm_array[firmRecno]->assign_overseer(kingUnitRecno); // assign the king as the overseer of the command base
  377. }
  378. else
  379. {
  380. noSpaceFlag = 1;
  381. break;
  382. }
  383. //----- create skilled units if config.random_start_up is 1 -----//
  384. if( config.random_start_up )
  385. {
  386. int createCount = (50-townPtr->population)/3; // the less population the villager has the more mobile units will be created
  387. for( int i=0 ; i<createCount ; i++ )
  388. {
  389. if( m.random(2)==0 )
  390. unitId = race_res[nationPtr->race_id]->basic_unit_id;
  391. else
  392. unitId = race_res[ m.random(MAX_RACE)+1 ]->basic_unit_id;
  393. if( m.random(3)==0 )
  394. rankId = RANK_GENERAL;
  395. else
  396. rankId = RANK_SOLDIER;
  397. if( !create_unit(townRecno, unitId, rankId) )
  398. break;
  399. }
  400. }
  401. //------ create mines near towns in the beginning -----//
  402. if( config.start_up_has_mine_nearby && !nationPtr->is_ai() )
  403. site_array.create_raw_site(0, townRecno);
  404. }
  405. //--- if there is no space for creating new town/firm or unit, delete the unprocessed nations ---//
  406. if( noSpaceFlag )
  407. {
  408. for( ; nationRecno<=nation_array.size() ; nationRecno++ )
  409. nation_array.del_nation(nationRecno); // no space for creating a town for the nation, so we have to delete the nation
  410. }
  411. // ###### begin Gilbert 24/10 ########//
  412. curGenMapSteps += 10; // 10
  413. if( dispProgress )
  414. {
  415. vga_front.lock_buf();
  416. game.disp_gen_map_status( curGenMapSteps, maxGenMapSteps, newWorldSection);
  417. vga_front.unlock_buf();
  418. }
  419. // ###### end Gilbert 24/10 ######//
  420. //---- init the type of active monsters in this game ----//
  421. monster_res.init_active_monster();
  422. // ###### begin Gilbert 24/10 ########//
  423. curGenMapSteps += 5; // 15
  424. if( dispProgress )
  425. {
  426. vga_front.lock_buf();
  427. game.disp_gen_map_status( curGenMapSteps, maxGenMapSteps, newWorldSection);
  428. vga_front.unlock_buf();
  429. }
  430. // ###### end Gilbert 24/10 ######//
  431. //------ create independent towns -------//
  432. //### begin alex 27/8 ###//
  433. int startUpIndependentTown = config.start_up_independent_town;
  434. //int startUpRawSite = config.start_up_raw_site;
  435. int startUpMonsterFirm = 10;
  436. int i, j, raceId;
  437. site_array.generate_raw_site(config.start_up_raw_site);
  438. // ###### begin Gilbert 24/10 ########//
  439. curGenMapSteps += 10; // 25
  440. if( dispProgress )
  441. {
  442. vga_front.lock_buf();
  443. game.disp_gen_map_status( curGenMapSteps, maxGenMapSteps, newWorldSection);
  444. vga_front.unlock_buf();
  445. }
  446. int targetStep = maxGenMapSteps;
  447. // ###### end Gilbert 24/10 ######//
  448. int maxLoopCount = startUpIndependentTown + startUpMonsterFirm;
  449. for(j=0, i=1; j<maxLoopCount; j++, i++)
  450. {
  451. if(startUpIndependentTown)
  452. {
  453. //------ create independent towns -------//
  454. raceId = i%MAX_RACE+1;
  455. if(!create_town( 0, raceId, xLoc, yLoc ) )
  456. {
  457. startUpIndependentTown = 0;
  458. break;
  459. }
  460. // ##### begin Gilbert 24/10 #######//
  461. else
  462. startUpIndependentTown--;
  463. // ###### end Gilbert 24/10 ########//
  464. }
  465. if(startUpMonsterFirm)
  466. {
  467. //------- create mosnters --------//
  468. if(config.monster_type != OPTION_MONSTER_NONE)
  469. {
  470. monster_res.generate(1);
  471. startUpMonsterFirm--;
  472. }
  473. else
  474. startUpMonsterFirm = 0;
  475. }
  476. if(!(startUpIndependentTown+startUpMonsterFirm))
  477. break;
  478. // ###### begin Gilbert 24/10 ########//
  479. if( dispProgress )
  480. {
  481. vga_front.lock_buf();
  482. game.disp_gen_map_status( curGenMapSteps + j*(targetStep-curGenMapSteps)/maxLoopCount, maxGenMapSteps, newWorldSection);
  483. vga_front.unlock_buf();
  484. }
  485. // ###### end Gilbert 24/10 ######//
  486. }
  487. //#### end alex 27/8 ####//
  488. // ###### begin Gilbert 24/10 ########//
  489. // finish
  490. curGenMapSteps = targetStep; // 100
  491. if( dispProgress )
  492. {
  493. vga_front.lock_buf();
  494. game.disp_gen_map_status( curGenMapSteps, maxGenMapSteps, newWorldSection);
  495. vga_front.unlock_buf();
  496. }
  497. // ###### end Gilbert 24/10 ######//
  498. vga_front.lock_buf();
  499. }
  500. //--------- End of function Battle::create_pregame_object ---------//
  501. //-------- Begin of function Battle::run_loaded --------//
  502. //
  503. void Battle::run_loaded()
  504. {
  505. //-------- play music ---------//
  506. char kingRace = 0;
  507. if( !nation_array.is_deleted(nation_array.player_recno) )
  508. {
  509. if( !unit_array.is_deleted((~nation_array)->king_unit_recno) )
  510. // if there is king in the nation take his race
  511. kingRace = unit_array[(~nation_array)->king_unit_recno]->race_id;
  512. else
  513. // if king is killed, get the original nation
  514. kingRace = (~nation_array)->race_id;
  515. }
  516. #ifdef AMPLUS
  517. int songId = kingRace <= 7 ? kingRace+1 : music.random_bgm_track();
  518. music.play(songId, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
  519. #else
  520. music.play( kingRace+1, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
  521. #endif
  522. //--- give the control to the system main loop, start the game now ---//
  523. sys.run(1);
  524. }
  525. //--------- End of function Battle::run_loaded ---------//
  526. //-------- Begin of function Battle::run_test --------//
  527. //
  528. void Battle::run_test()
  529. {
  530. info.disp_panel();
  531. info.init_random_seed(153542);
  532. world.generate_map();
  533. //--------- refresh world ---------//
  534. world.refresh();
  535. vga.blt_buf(0, 0, VGA_WIDTH-1, VGA_HEIGHT-1);
  536. world.paint();
  537. //-------- create nation and units --------//
  538. nation_array.new_nation( NATION_OWN, 1, 1 ); // 2nd parameter = the race id. 3rd parameters = color scheme id.
  539. nation_array.new_nation( NATION_AI , 2, 2 ); // 2nd parameter = the race id. 3rd parameters = color scheme id.
  540. tech_res.inc_all_tech_level(1); // set all tech of nation 1 to level 1
  541. tech_res.inc_all_tech_level(2); // set all tech of nation 2 to level 1
  542. create_test_unit(1);
  543. create_test_unit(2);
  544. //-- enable power after the game objets has been initialized --//
  545. power.enable(); // enable power, which handle mouse inputs
  546. //--- give the control to the system main loop, start the game now ---//
  547. sys.run();
  548. }
  549. //--------- End of function Battle::run_test ---------//
  550. //-------- Begin of function Battle::create_test_unit --------//
  551. //
  552. void Battle::create_test_unit(int nationRecno)
  553. {
  554. int x, y, unitId, xLoc, yLoc;
  555. SpriteInfo* spriteInfo;
  556. for( unitId=1 ; unitId<=MAX_UNIT_TYPE ; unitId++ )
  557. {
  558. if( unitId == UNIT_CARAVAN ) // caravan cannot be created independently without market places
  559. continue;
  560. xLoc=0;
  561. yLoc=0;
  562. spriteInfo = sprite_res[ unit_res[unitId]->sprite_id ];
  563. char teraMask = UnitRes::mobile_type_to_mask(unit_res[unitId]->mobile_type);
  564. if( world.locate_space_random(xLoc, yLoc, MAX_WORLD_X_LOC-1,
  565. MAX_WORLD_Y_LOC-1, spriteInfo->loc_width*4, spriteInfo->loc_height*4,
  566. MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC, 0, 0, teraMask) )
  567. {
  568. for( y=spriteInfo->loc_height ; y<spriteInfo->loc_height*4 ; y+=spriteInfo->loc_height*2 )
  569. {
  570. for( x=spriteInfo->loc_width ; x<spriteInfo->loc_width*4 ; x+=spriteInfo->loc_width*2 )
  571. {
  572. // force the location to be even number
  573. int unitRecno = unit_array.add_unit( unitId, nationRecno, RANK_SOLDIER, 100, (xLoc+x)& ~1, (yLoc+y) & ~1 );
  574. unit_array[unitRecno]->set_combat_level(100);
  575. }
  576. }
  577. }
  578. }
  579. }
  580. //--------- End of function Battle::create_test_unit ---------//
  581. //-------- Begin of function Battle::create_town --------//
  582. //
  583. // <int> nationRecno = the nation recno of the town
  584. // <int> raceId = the race id. of the town
  585. //
  586. // <int&> xLoc = for the starting location of the town
  587. // <int&> yLoc = for the starting location of the town
  588. //
  589. // return: <int> townRecno - >0 the recno of the town created
  590. // ==0 no town created
  591. //
  592. int Battle::create_town(int nationRecno, int raceId, int& xLoc, int& yLoc)
  593. {
  594. //------- locate for a space to build the town ------//
  595. if( !town_array.think_town_loc(MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC, xLoc, yLoc) )
  596. return 0;
  597. //--------------- create town ---------------//
  598. int townRecno = town_array.add_town(nationRecno, raceId, xLoc, yLoc);
  599. Town* townPtr = town_array[townRecno];
  600. //--------- no. of mixed races ---------//
  601. if( nationRecno )
  602. {
  603. int initPop;
  604. if( config.random_start_up )
  605. initPop = 25 + m.random(26); // 25 to 50
  606. else
  607. initPop = 40;
  608. Town* townPtr = town_array[townRecno];
  609. townPtr->init_pop( raceId, initPop, 100, 0, 1 ); // 100-startup loyalty, last 1-first initialization at the beginning of the game
  610. }
  611. else
  612. {
  613. int mixedRaceCount;
  614. if( nationRecno )
  615. mixedRaceCount = 1;
  616. else
  617. mixedRaceCount= m.random(3)+1; // 1 to 3 mixed races
  618. int curPop, totalPop=0, townResistance;
  619. for( int i=0 ; i<mixedRaceCount ; i++ )
  620. {
  621. if(totalPop>=MAX_TOWN_POPULATION)
  622. break;
  623. townResistance = town_array.independent_town_resistance();
  624. if( i==0 )
  625. {
  626. curPop = 15/mixedRaceCount + m.random(15/mixedRaceCount);
  627. if(curPop>=MAX_TOWN_POPULATION)
  628. curPop = MAX_TOWN_POPULATION;
  629. err_when(curPop==0);
  630. townPtr->init_pop( raceId, curPop, townResistance, 0, 1 ); // last 1-first initialization at the beginning of the game
  631. totalPop += curPop;
  632. }
  633. else
  634. {
  635. curPop = 10/mixedRaceCount + m.random(10/mixedRaceCount);
  636. if(curPop>=MAX_TOWN_POPULATION-totalPop)
  637. curPop = MAX_TOWN_POPULATION-totalPop;
  638. err_when(curPop==0);
  639. townPtr->init_pop( m.random(MAX_RACE)+1, curPop, townResistance, 0, 1 );
  640. totalPop += curPop;
  641. }
  642. }
  643. }
  644. //---------- set town layout -----------//
  645. townPtr->auto_set_layout();
  646. return townRecno;
  647. }
  648. //--------- End of function Battle::create_town ---------//
  649. //-------- Begin of function Battle::create_unit --------//
  650. //
  651. // Add a specific no. of units within a given area
  652. //
  653. // <int> townRecno - create units around this town.
  654. // <int> unitId - id. of the units to be added
  655. // <int> rankId - rank id. of the unit
  656. //
  657. // return: <int> recno of the unit created.
  658. //
  659. int Battle::create_unit(int townRecno, int unitId, int rankId)
  660. {
  661. SpriteInfo* spriteInfo = sprite_res[ unit_res[unitId]->sprite_id ];
  662. Town* townPtr = town_array[townRecno];
  663. //------ locate space for the unit ------//
  664. int xLoc = townPtr->loc_x1;
  665. int yLoc = townPtr->loc_y1;
  666. if( !world.locate_space( xLoc, yLoc, xLoc+STD_TOWN_LOC_WIDTH-1, yLoc+STD_TOWN_LOC_HEIGHT-1,
  667. spriteInfo->loc_width, spriteInfo->loc_height ) )
  668. {
  669. return 0;
  670. }
  671. //---------- create the unit --------//
  672. int unitLoyalty = 80 + m.random(20);
  673. int unitRecno = unit_array.add_unit( unitId, townPtr->nation_recno, rankId, unitLoyalty, xLoc, yLoc );
  674. if( !unitRecno )
  675. return 0;
  676. Unit* unitPtr = unit_array[unitRecno];
  677. //----------- set skill -------------//
  678. switch( rankId )
  679. {
  680. case RANK_KING:
  681. unitPtr->skill.set_skill(SKILL_LEADING);
  682. unitPtr->skill.skill_level = 100;
  683. unitPtr->set_combat_level(100);
  684. break;
  685. case RANK_GENERAL:
  686. unitPtr->skill.set_skill(SKILL_LEADING);
  687. unitPtr->skill.skill_level = 40 + m.random(50); // 40 to 90
  688. unitPtr->set_combat_level(30 + m.random(70)); // 30 to 100
  689. break;
  690. case RANK_SOLDIER:
  691. {
  692. int skillId = m.random(MAX_TRAINABLE_SKILL)+1;
  693. int spyFlag = 0;
  694. if( skillId == SKILL_SPYING )
  695. {
  696. spyFlag = 1;
  697. unitPtr->set_combat_level(10+m.random(10));
  698. }
  699. else
  700. {
  701. unitPtr->skill.skill_id = skillId;
  702. unitPtr->skill.skill_level = 30+m.random(70);
  703. if( skillId == SKILL_LEADING )
  704. unitPtr->set_combat_level(30+m.random(70));
  705. else
  706. unitPtr->set_combat_level(10+m.random(10));
  707. if( m.random(5)==0 )
  708. spyFlag = 1;
  709. }
  710. if( spyFlag )
  711. {
  712. int spySkill = 20 + m.random(80); // 20 to 100
  713. unitPtr->spy_recno = spy_array.add_spy(unitRecno, spySkill);
  714. }
  715. break;
  716. }
  717. default:
  718. err_here();
  719. }
  720. return unitRecno;
  721. }
  722. //--------- End of function Battle::create_unit ---------//
  723. //-------- Begin of static function is_space --------//
  724. //
  725. // Check whether all locations in the given area are space
  726. //
  727. // return : <int> 1 - all are space
  728. // 0 - not all are space
  729. //
  730. static int is_space(int xLoc1, int yLoc1, int xLoc2, int yLoc2, char mobileType)
  731. {
  732. int xLoc, yLoc;
  733. Location* locPtr;
  734. for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
  735. {
  736. locPtr = world.get_loc(xLoc1, yLoc);
  737. for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ )
  738. {
  739. if( !locPtr->can_move(mobileType) )
  740. return 0;
  741. }
  742. }
  743. return 1;
  744. }
  745. //--------- End of static function is_space ---------//