OW_WALL.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  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 : OW_WALL.CPP
  21. // Description : class World for building wall
  22. // Ownership : Gilbert
  23. #include <OWORLD.h>
  24. #include <OMATRIX.h>
  25. #include <WALLTILE.h>
  26. #include <OWALLRES.h>
  27. #include <OTOWN.h>
  28. #include <OREMOTE.h>
  29. #include <ONATIONA.h>
  30. #define WALL_GROWTH_RATE 6
  31. //--------------- begin of function World::can_build_area ----------//
  32. int World::can_build_area(short x1, short y1, short x2, short y2)
  33. {
  34. int x,y;
  35. err_when(x1 > x2 || y1 > y2);
  36. for(y = y1; y <= y2; ++y)
  37. for( x = x1; x <= x2; ++x)
  38. if( ! get_loc(x,y)->can_build_wall())
  39. return FALSE;
  40. return TRUE;
  41. }
  42. //--------------- end of function World::can_build_area ----------//
  43. //--------------- begin of function World::build_wall ----------//
  44. void World::build_wall(int townRecno, short initHp)
  45. {
  46. Town* townPtr = town_array[townRecno];
  47. int xLoc1 = max(0, townPtr->loc_x1-WALL_SPACE_LOC);
  48. int yLoc1 = max(0, townPtr->loc_y1-WALL_SPACE_LOC);
  49. int xLoc2 = min(MAX_WORLD_X_LOC-1, townPtr->loc_x2+WALL_SPACE_LOC);
  50. int yLoc2 = min(MAX_WORLD_Y_LOC-1, townPtr->loc_y2+WALL_SPACE_LOC);
  51. //--------------- build city wall -------------//
  52. build_wall_section(xLoc1, yLoc1, xLoc2, yLoc2, townRecno, initHp);
  53. }
  54. //--------------- end of function World::build_wall ----------//
  55. //--------------- begin of function World::build_wall_section ----------//
  56. void World::build_wall_section(short x1, short y1, short x2, short y2,
  57. short townRecno, short initHp)
  58. {
  59. //--------- build west wall -----------//
  60. Location *locPtr;
  61. short westWallFirst;
  62. for( westWallFirst = y1; westWallFirst < y2; ++westWallFirst)
  63. {
  64. if( get_loc(x1,westWallFirst)->can_build_wall() )
  65. {
  66. //--------- find place for the west gate ---------//
  67. if( x1 >= GATE_WIDTH-1 && y2-y1 >= GATE_LENGTH)
  68. {
  69. //----- try from the middle, and then butterfly outward ---//
  70. short increment = 0;
  71. short trial, westGateY;
  72. for( trial=y2-y1-GATE_LENGTH, westGateY=y1+(trial+1)/2;
  73. trial > 0; --trial, westGateY += increment)
  74. {
  75. if(can_build_area(x1-GATE_WIDTH+1, westGateY,
  76. x1, westGateY+GATE_LENGTH-1) )
  77. {
  78. //-------- put west gate --------- //
  79. build_west_gate(x1-GATE_WIDTH+1, westGateY, townRecno, initHp);
  80. break;
  81. }
  82. increment = -increment;
  83. if( increment >= 0)
  84. ++increment;
  85. else
  86. --increment;
  87. }
  88. //---------- put other wall ----------//
  89. build_west_wall(x1, y1, y2, townRecno, initHp);
  90. //--------- open west gate ----------//
  91. open_west_gate(x1, westGateY, townRecno);
  92. }
  93. else
  94. {
  95. //-------- x1 too small for gate -------//
  96. get_loc(x1,westWallFirst)->set_wall(NTOWER, townRecno, initHp);
  97. get_loc(x1,westWallFirst)->set_fire_src(-50);
  98. }
  99. break;
  100. }
  101. }
  102. //--------- build east wall -----------
  103. short eastWallFirst;
  104. for( eastWallFirst = y1; eastWallFirst < y2; ++eastWallFirst)
  105. {
  106. if( get_loc(x2, eastWallFirst)->can_build_wall())
  107. {
  108. //---------- find place for the gate --------- //
  109. if( x2 <= max_x_loc - GATE_WIDTH +1 && y2-y1 >= GATE_LENGTH)
  110. {
  111. //---- try from the middle, and then butterfly outward ----//
  112. short increment = 0;
  113. short trial, eastGateY;
  114. for( trial=y2-y1-GATE_LENGTH, eastGateY=y1+(trial+1)/2;
  115. trial > 0; --trial, eastGateY += increment)
  116. {
  117. if(can_build_area(x2, eastGateY, x2+GATE_WIDTH-1, eastGateY+GATE_LENGTH-1) )
  118. {
  119. //----------- put east gate ----------//
  120. build_east_gate(x2, eastGateY, townRecno, initHp);
  121. break;
  122. }
  123. increment = -increment;
  124. if( increment >= 0)
  125. ++increment;
  126. else
  127. --increment;
  128. }
  129. //-------- put other wall ---------//
  130. build_east_wall(x2, y1, y2, townRecno, initHp);
  131. //--------- open east gate ----------//
  132. open_east_gate(x2, eastGateY, townRecno);
  133. }
  134. else
  135. {
  136. //------- x2 too big for gate ---------//
  137. get_loc(x2,eastWallFirst)->set_wall(NETOWER, townRecno, initHp);
  138. get_loc(x2,eastWallFirst)->set_fire_src(-50);
  139. }
  140. break;
  141. }
  142. }
  143. //--------- build north wall -----------//
  144. short northWallFirst;
  145. for( northWallFirst = x1; northWallFirst < x2; ++northWallFirst)
  146. {
  147. if( (locPtr = get_loc(northWallFirst, y1))->can_build_wall() ||
  148. ( locPtr->is_wall() && locPtr->wall_town_recno() == townRecno) )
  149. {
  150. //-------- find place for the north gate --------//
  151. if( y1 >= GATE_WIDTH-1 && x2-x1 >= GATE_LENGTH)
  152. {
  153. //------- try from the middle, and then butterfly outward -------//
  154. short increment = 0;
  155. short trial, northGateX;
  156. for( trial=x2-x1-GATE_LENGTH, northGateX=x1+(trial+1)/2;
  157. trial > 0; --trial, northGateX += increment)
  158. {
  159. if(can_build_area(northGateX, y1-GATE_WIDTH+1,
  160. northGateX+GATE_LENGTH-1, y1) )
  161. {
  162. //--------------- put north gate ----------------//
  163. build_north_gate(northGateX, y1-GATE_WIDTH+1, townRecno, initHp);
  164. break;
  165. }
  166. increment = -increment;
  167. if( increment >= 0)
  168. ++increment;
  169. else
  170. --increment;
  171. }
  172. //----------- put other wall --------------//
  173. build_north_wall(x1, x2, y1, townRecno, initHp);
  174. //--------- open north gate ----------//
  175. open_north_gate(northGateX, y1, townRecno);
  176. }
  177. else
  178. {
  179. //------------ y1 too small for gate -----------//
  180. if(locPtr->can_build_wall() )
  181. {
  182. locPtr->set_wall(NTOWER, townRecno, initHp);
  183. locPtr->set_fire_src(-50);
  184. }
  185. }
  186. break;
  187. }
  188. }
  189. //--------- build south wall -----------
  190. short southWallFirst;
  191. for( southWallFirst = x1; southWallFirst < x2; ++southWallFirst)
  192. {
  193. if( (locPtr = get_loc(southWallFirst, y2))->can_build_wall() ||
  194. ( locPtr->is_wall() && locPtr->wall_town_recno() == townRecno) )
  195. {
  196. //---------- find place for the south gate ----------//
  197. if( y2 <= max_y_loc-GATE_WIDTH+1 && x2-x1 >= GATE_LENGTH)
  198. {
  199. //----- try from the middle, and then butterfly outward ----//
  200. short increment = 0;
  201. short trial, southGateX;
  202. for( trial=x2-x1-GATE_LENGTH, southGateX=x1+(trial+1)/2;
  203. trial > 0; --trial, southGateX += increment)
  204. {
  205. if(can_build_area(southGateX, y2,
  206. southGateX+GATE_LENGTH-1, y2+GATE_WIDTH-1) )
  207. {
  208. //----------- put south gate -------------//
  209. build_south_gate(southGateX, y2, townRecno, initHp);
  210. break;
  211. }
  212. increment = -increment;
  213. if( increment >= 0)
  214. ++increment;
  215. else
  216. --increment;
  217. }
  218. //----------- put other wall -------------//
  219. build_south_wall(x1, x2, y2, townRecno, initHp);
  220. //--------- open north gate ----------//
  221. open_south_gate(southGateX, y2, townRecno);
  222. }
  223. else
  224. {
  225. //---------- y2 too big for gate ----------//
  226. if(locPtr->can_build_wall() )
  227. {
  228. locPtr->set_wall(STOWER, townRecno, initHp);
  229. locPtr->set_fire_src(-50);
  230. }
  231. }
  232. break;
  233. }
  234. }
  235. }
  236. //--------------- end of function World::build_wall_section ----------//
  237. //--------------- begin of function World::build_west_gate ----------//
  238. void World::build_west_gate(short x1, short y1, short townRecno, short initHp)
  239. {
  240. //--------- put two gate towers -----------//
  241. Location *locPtr = get_loc(x1,y1);
  242. locPtr->set_wall(WGATE_NTOWER_NW, townRecno, initHp);
  243. (locPtr+1)->set_wall(WGATE_NTOWER_NE, townRecno, initHp);
  244. locPtr->set_fire_src(-50);
  245. (locPtr+1)->set_fire_src(-50);
  246. locPtr = get_loc(x1, y1+1);
  247. locPtr->set_wall(WGATE_NTOWER_SW, townRecno, initHp);
  248. (locPtr+1)->set_wall(WGATE_NTOWER_SE, townRecno, initHp);
  249. locPtr->set_fire_src(-50);
  250. (locPtr+1)->set_fire_src(-50);
  251. locPtr = get_loc(x1,y1+GATE_LENGTH-2);
  252. locPtr->set_wall(WGATE_STOWER_NW, townRecno, initHp);
  253. (locPtr+1)->set_wall(WGATE_STOWER_NE, townRecno, initHp);
  254. locPtr->set_fire_src(-50);
  255. (locPtr+1)->set_fire_src(-50);
  256. locPtr = get_loc(x1, y1+GATE_LENGTH-1);
  257. locPtr->set_wall(WGATE_STOWER_SW, townRecno, initHp);
  258. (locPtr+1)->set_wall(WGATE_STOWER_SE, townRecno, initHp);
  259. locPtr->set_fire_src(-50);
  260. (locPtr+1)->set_fire_src(-50);
  261. //---------- put gate -----------//
  262. char gateId = WGATE_BASE;
  263. for(short y = 2; y < GATE_LENGTH-2; ++y)
  264. {
  265. locPtr = get_loc(x1, y1+y);
  266. for(short x = 0; x < GATE_WIDTH; ++x, ++locPtr)
  267. {
  268. locPtr->set_wall(gateId++, townRecno, initHp);
  269. locPtr->set_fire_src(-50);
  270. }
  271. }
  272. }
  273. //--------------- end of function World::build_west_gate ----------//
  274. //--------------- begin of function World::build_west_wall ----------//
  275. void World::build_west_wall(short x1, short y1, short y2, short townRecno,
  276. short initHp)
  277. {
  278. //---------- find segments of buildable terrain ---------//
  279. short startY = y1, endY = y1;
  280. while(startY <= y2)
  281. {
  282. for( ; startY <= y2 && !get_loc(x1,startY)->can_build_wall(); ++startY);
  283. if( startY <= y2) // a place is found
  284. {
  285. //-------- found segment end -----------//
  286. for( endY = startY+1; endY <= y2 && get_loc(x1,endY)->can_build_wall() ;++endY);
  287. --endY;
  288. if( startY == endY)
  289. {
  290. //------- equal square, draw a single tower --------//
  291. get_loc(x1, startY)->set_wall(SINGLE_TOWER, townRecno, initHp);
  292. get_loc(x1, startY)->set_fire_src(-50);
  293. }
  294. else
  295. {
  296. short startSquare = NTOWER;
  297. short endSquare = STOWER;
  298. // if startY-1 is a wall, hence a gate, start with a wall with shadow
  299. if( startY > y1 && get_loc(x1, startY-1)->is_wall() )
  300. {
  301. startSquare = NSWALL_SHADOW;
  302. }
  303. // if endY+1 is a wall, hence a gate, start with a wall
  304. if( endY < y2 && get_loc(x1, endY+1)->is_wall() )
  305. {
  306. endSquare = NSWALL;
  307. }
  308. for( short y = startY; y < endY; ++y)
  309. {
  310. get_loc(x1, y)->set_wall(startSquare, townRecno, initHp);
  311. get_loc(x1, y)->set_fire_src(-50);
  312. switch(startSquare)
  313. {
  314. case NTOWER:
  315. startSquare = NSWALL_SHADOW;
  316. break;
  317. case NSWALL_SHADOW:
  318. startSquare = NSWALL;
  319. break;
  320. // otherwise unchange
  321. }
  322. }
  323. get_loc(x1, endY)->set_wall(endSquare, townRecno, initHp);
  324. get_loc(x1, endY)->set_fire_src(-50);
  325. }
  326. startY = endY +1;
  327. }
  328. }
  329. }
  330. //--------------- end of function World::build_west_wall ----------//
  331. //--------------- begin of function World::open_west_gate ----------//
  332. void World::open_west_gate(short x2, short y1, short townRecno)
  333. {
  334. //------ check if any west gate tile is built ---------//
  335. Location *locPtr = get_loc(x2,y1+2);
  336. if( locPtr->is_wall() && locPtr->wall_id() == WGATE_N &&
  337. locPtr->wall_town_recno() == townRecno)
  338. {
  339. for(short y = 3; y < GATE_LENGTH-3; ++y)
  340. for(short x = 0; x < GATE_WIDTH; ++x)
  341. get_loc(x2-x, y1+y)->remove_wall();
  342. }
  343. }
  344. //--------------- end of function World::open_west_gate ----------//
  345. //--------------- begin of function World::build_east_gate ----------//
  346. void World::build_east_gate(short x1, short y1, short townRecno, short initHp)
  347. {
  348. //---------- put two gate towers ----------//
  349. Location *locPtr = get_loc(x1,y1);
  350. locPtr->set_wall(EGATE_NTOWER_NW, townRecno, initHp);
  351. (locPtr+1)->set_wall(EGATE_NTOWER_NE, townRecno, initHp);
  352. locPtr->set_fire_src(-50);
  353. (locPtr+1)->set_fire_src(-50);
  354. locPtr = get_loc(x1, y1+1);
  355. locPtr->set_wall(EGATE_NTOWER_SW, townRecno, initHp);
  356. (locPtr+1)->set_wall(EGATE_NTOWER_SE, townRecno, initHp);
  357. locPtr->set_fire_src(-50);
  358. (locPtr+1)->set_fire_src(-50);
  359. locPtr = get_loc(x1,y1+GATE_LENGTH-2);
  360. locPtr->set_wall(EGATE_STOWER_NW, townRecno, initHp);
  361. (locPtr+1)->set_wall(EGATE_STOWER_NE, townRecno, initHp);
  362. locPtr->set_fire_src(-50);
  363. (locPtr+1)->set_fire_src(-50);
  364. locPtr = get_loc(x1, y1+GATE_LENGTH-1);
  365. locPtr->set_wall(EGATE_STOWER_SW, townRecno, initHp);
  366. (locPtr+1)->set_wall(EGATE_STOWER_SE, townRecno, initHp);
  367. locPtr->set_fire_src(-50);
  368. (locPtr+1)->set_fire_src(-50);
  369. //------------- put gate ----------------//
  370. char gateId = EGATE_BASE;
  371. for(short y = 2; y < GATE_LENGTH-2; ++y)
  372. {
  373. locPtr = get_loc(x1, y+y1);
  374. for(short x = 0; x < GATE_WIDTH; ++x, ++locPtr)
  375. {
  376. locPtr->set_wall(gateId++, townRecno, initHp);
  377. locPtr->set_fire_src(-50);
  378. }
  379. }
  380. }
  381. //--------------- end of function World::build_east_gate ----------//
  382. //--------------- begin of function World::build_east_wall ----------//
  383. void World::build_east_wall(short x1, short y1, short y2, short townRecno,
  384. short initHp)
  385. {
  386. //--------- find segments of buildable terrain ---------//
  387. short startY = y1, endY = y1;
  388. while(startY <= y2)
  389. {
  390. for( ; startY <= y2 && !get_loc(x1,startY)->can_build_wall(); ++startY);
  391. if( startY <= y2) // a place is found
  392. {
  393. //-------- found segment end -------------//
  394. for( endY = startY+1; endY <= y2 && get_loc(x1,endY)->can_build_wall() ;++endY);
  395. --endY;
  396. if( startY == endY)
  397. {
  398. //----------- equal square, draw a single tower --------//
  399. get_loc(x1, startY)->set_wall(SINGLE_TOWER, townRecno, initHp);
  400. get_loc(x1, startY)->set_fire_src(-50);
  401. }
  402. else
  403. {
  404. short startSquare = NTOWER;
  405. short endSquare = STOWER;
  406. // if startY-1 is a wall, hence a gate, start with a wall with shadow
  407. if( startY > y1 && get_loc(x1, startY-1)->is_wall() )
  408. {
  409. startSquare = NSWALL_SHADOW;
  410. }
  411. // if endY+1 is a wall, hence a gate, start with a wall
  412. if( endY < y2 && get_loc(x1, endY+1)->is_wall() )
  413. {
  414. endSquare = NSWALL;
  415. }
  416. for( short y = startY; y < endY; ++y)
  417. {
  418. get_loc(x1, y)->set_wall(startSquare, townRecno, initHp);
  419. get_loc(x1, y)->set_fire_src(-50);
  420. switch(startSquare)
  421. {
  422. case NTOWER:
  423. startSquare = NSWALL_SHADOW;
  424. break;
  425. case NSWALL_SHADOW:
  426. startSquare = NSWALL;
  427. break;
  428. // otherwise unchange
  429. }
  430. }
  431. get_loc(x1, endY)->set_wall(endSquare, townRecno, initHp);
  432. get_loc(x1, endY)->set_fire_src(-50);
  433. }
  434. startY = endY +1;
  435. }
  436. }
  437. }
  438. //--------------- end of function World::build_east_wall ----------//
  439. //--------------- begin of function World::open_east_gate ----------//
  440. void World::open_east_gate(short x1, short y1, short townRecno)
  441. {
  442. //------ check if any east gate tile is built ---------//
  443. Location *locPtr = get_loc(x1,y1+2);
  444. if( locPtr->is_wall() && locPtr->wall_id() == EGATE_N &&
  445. locPtr->wall_town_recno() == townRecno)
  446. {
  447. for(short y = 3; y < GATE_LENGTH-3; ++y)
  448. for(short x = 0; x < GATE_WIDTH; ++x)
  449. get_loc(x1+x, y1+y)->remove_wall();
  450. }
  451. }
  452. //--------------- end of function World::open_east_gate ----------//
  453. //--------------- begin of function World::build_north_gate ----------//
  454. void World::build_north_gate(short x1, short y1, short townRecno,
  455. short initHp)
  456. {
  457. //---------- put two gate towers -----------//
  458. Location *locPtr = get_loc(x1,y1);
  459. locPtr->set_wall(NGATE_WTOWER_NW, townRecno, initHp);
  460. (locPtr+1)->set_wall(NGATE_WTOWER_NE, townRecno, initHp);
  461. locPtr->set_fire_src(-50);
  462. (locPtr+1)->set_fire_src(-50);
  463. locPtr = get_loc(x1+GATE_LENGTH-2, y1);
  464. locPtr->set_wall(NGATE_ETOWER_NW, townRecno, initHp);
  465. (locPtr+1)->set_wall(NGATE_ETOWER_NE, townRecno, initHp);
  466. locPtr->set_fire_src(-50);
  467. (locPtr+1)->set_fire_src(-50);
  468. locPtr = get_loc(x1,y1+1);
  469. locPtr->set_wall(NGATE_WTOWER_SW, townRecno, initHp);
  470. (locPtr+1)->set_wall(NGATE_WTOWER_SE, townRecno, initHp);
  471. locPtr->set_fire_src(-50);
  472. (locPtr+1)->set_fire_src(-50);
  473. locPtr = get_loc(x1+GATE_LENGTH-2, y1+1);
  474. locPtr->set_wall(NGATE_ETOWER_SW, townRecno, initHp);
  475. (locPtr+1)->set_wall(NGATE_ETOWER_SE, townRecno, initHp);
  476. locPtr->set_fire_src(-50);
  477. (locPtr+1)->set_fire_src(-50);
  478. //------------ put gate -------------//
  479. char gateId = NGATE_BASE;
  480. for(short y = 0; y < GATE_WIDTH; ++y)
  481. {
  482. locPtr = get_loc(x1+2, y1+y);
  483. for(short x = 2; x < GATE_LENGTH-2; ++x, ++locPtr)
  484. {
  485. locPtr->set_wall(gateId++, townRecno, initHp);
  486. locPtr->set_fire_src(-50);
  487. }
  488. }
  489. }
  490. //--------------- end of function World::build_north_gate ----------//
  491. //--------------- begin of function World::build_north_wall ----------//
  492. void World::build_north_wall(short x1, short x2, short y1, short townRecno,
  493. short initHp)
  494. {
  495. //---------- find segments of buildable terrain ---------//
  496. short startX = x1, endX = x1;
  497. while(startX <= x2)
  498. {
  499. for( ; startX <= x2 && !get_loc(startX, y1)->can_build_wall(); ++startX);
  500. if( startX <= x2) // a place is found
  501. {
  502. //--------- found segment end ----------//
  503. for( endX = startX+1; endX <= x2 && get_loc(endX, y1)->can_build_wall() ;++endX);
  504. --endX;
  505. if( startX == endX)
  506. {
  507. //---------- equal square, draw a single tower ---------//
  508. get_loc(startX, y1)->set_wall(SINGLE_TOWER, townRecno, initHp);
  509. get_loc(startX, y1)->set_fire_src(-50);
  510. }
  511. else
  512. {
  513. short startSquare = WTOWER;
  514. short endSquare = ETOWER;
  515. // if startX-1 is a wall, hence a gate, start with a wall with shadow
  516. if( startX > x1 && get_loc(startX-1, y1)->is_wall() )
  517. {
  518. startSquare = EWWALL_SHADOW;
  519. // if startX-1 is a NTOWER (corner) , change it to NWTOWER
  520. Location *leftLoc;
  521. if( (leftLoc = get_loc(startX-1, y1))->wall_id() == NTOWER
  522. && leftLoc->wall_town_recno() == townRecno )
  523. {
  524. leftLoc->remove_wall();
  525. leftLoc->set_wall(NWTOWER, townRecno, initHp);
  526. }
  527. }
  528. // if endX+1 is a wall, hence a gate, start with a wall
  529. if( endX < x2 && get_loc(endX+1, y1)->is_wall() )
  530. {
  531. endSquare = EWWALL;
  532. // if endX+1 is a NTOWER (corner) , change it to NETOWER
  533. Location *rightLoc;
  534. if( (rightLoc = get_loc(endX+1,y1))->wall_id() == NTOWER
  535. && rightLoc->wall_town_recno() == townRecno)
  536. {
  537. rightLoc->remove_wall();
  538. rightLoc->set_wall(NETOWER, townRecno, initHp);
  539. }
  540. }
  541. for( short x = startX; x < endX; ++x)
  542. {
  543. get_loc(x, y1)->set_wall(startSquare, townRecno, initHp);
  544. get_loc(x, y1)->set_fire_src(-50);
  545. switch(startSquare)
  546. {
  547. case WTOWER:
  548. startSquare = EWWALL_SHADOW;
  549. break;
  550. case EWWALL_SHADOW:
  551. startSquare = EWWALL;
  552. break;
  553. // otherwise unchange
  554. }
  555. }
  556. get_loc(endX, y1)->set_wall(endSquare, townRecno, initHp);
  557. get_loc(endX, y1)->set_fire_src(-50);
  558. }
  559. startX = endX +1;
  560. }
  561. }
  562. }
  563. //--------------- end of function World::build_north_wall ----------//
  564. //--------------- begin of function World::open_north_gate ----------//
  565. void World::open_north_gate(short x1, short y2, short townRecno)
  566. {
  567. //------ check if any north gate tile is built ---------//
  568. Location *locPtr = get_loc(x1+2,y2);
  569. if( locPtr->is_wall() && locPtr->wall_id() == NGATE_W &&
  570. locPtr->wall_town_recno() == townRecno)
  571. {
  572. for(short x = 3; x < GATE_LENGTH-3; ++x)
  573. for(short y = 0; y < GATE_WIDTH; ++y)
  574. get_loc(x1+x, y2-y)->remove_wall();
  575. }
  576. }
  577. //--------------- end of function World::open_north_gate ----------//
  578. //--------------- begin of function World::build_south_gate ----------//
  579. void World::build_south_gate(short x1, short y1, short townRecno, short initHp)
  580. {
  581. //---------- put two gate towers ----------//
  582. Location *locPtr = get_loc(x1,y1);
  583. locPtr->set_wall(SGATE_WTOWER_NW, townRecno, initHp);
  584. (locPtr+1)->set_wall(SGATE_WTOWER_NE, townRecno, initHp);
  585. locPtr->set_fire_src(-50);
  586. (locPtr+1)->set_fire_src(-50);
  587. locPtr = get_loc(x1+GATE_LENGTH-2, y1);
  588. locPtr->set_wall(SGATE_ETOWER_NW, townRecno, initHp);
  589. (locPtr+1)->set_wall(SGATE_ETOWER_NE, townRecno, initHp);
  590. locPtr->set_fire_src(-50);
  591. (locPtr+1)->set_fire_src(-50);
  592. locPtr = get_loc(x1,y1+1);
  593. locPtr->set_wall(SGATE_WTOWER_SW, townRecno, initHp);
  594. (locPtr+1)->set_wall(SGATE_WTOWER_SE, townRecno, initHp);
  595. locPtr->set_fire_src(-50);
  596. (locPtr+1)->set_fire_src(-50);
  597. locPtr = get_loc(x1+GATE_LENGTH-2, y1+1);
  598. locPtr->set_wall(SGATE_ETOWER_SW, townRecno, initHp);
  599. (locPtr+1)->set_wall(SGATE_ETOWER_SE, townRecno, initHp);
  600. locPtr->set_fire_src(-50);
  601. (locPtr+1)->set_fire_src(-50);
  602. //------------ put gate --------------//
  603. char gateId = SGATE_BASE;
  604. for(short y = 0; y < GATE_WIDTH; ++y)
  605. {
  606. locPtr = get_loc(x1+2, y1+y);
  607. for(short x = 2; x < GATE_LENGTH-2; ++x, ++locPtr)
  608. {
  609. locPtr->set_wall(gateId++, townRecno, initHp);
  610. locPtr->set_fire_src(-50);
  611. }
  612. }
  613. }
  614. //--------------- end of function World::build_south_gate ----------//
  615. //--------------- begin of function World::build_south_wall ----------//
  616. void World::build_south_wall(short x1, short x2, short y1, short townRecno,
  617. short initHp)
  618. {
  619. //----------- find segments of buildable terrain -------------//
  620. short startX = x1, endX = x1;
  621. while(startX <= x2)
  622. {
  623. for( ; startX <= x2 && !get_loc(startX, y1)->can_build_wall(); ++startX);
  624. if( startX <= x2) // a place is found
  625. {
  626. //---------- found segment end ---------//
  627. for( endX = startX+1; endX <= x2 && get_loc(endX, y1)->can_build_wall() ;++endX);
  628. --endX;
  629. if( startX == endX)
  630. {
  631. //--------- equal square, draw a single tower --------//
  632. get_loc(startX, y1)->set_wall(SINGLE_TOWER, townRecno, initHp);
  633. get_loc(startX, y1)->set_fire_src(-50);
  634. }
  635. else
  636. {
  637. short startSquare = WTOWER;
  638. short endSquare = ETOWER;
  639. // if startX-1 is a wall, hence a gate, start with a wall with shadow
  640. if( startX > x1 && get_loc(startX-1, y1)->is_wall() )
  641. {
  642. startSquare = EWWALL_SHADOW;
  643. // if startX-1 is a STOWER (corner) , change it to SWTOWER
  644. Location *leftLoc;
  645. if( (leftLoc = get_loc(startX-1, y1))->wall_id() == STOWER
  646. && leftLoc->wall_town_recno() == townRecno )
  647. {
  648. leftLoc->remove_wall();
  649. leftLoc->set_wall(SWTOWER, townRecno, initHp);
  650. }
  651. }
  652. // if endY+1 is a wall, hence a gate, start with a wall with shadow
  653. if( endX < x2 && get_loc(endX+1, y1)->is_wall() )
  654. {
  655. endSquare = EWWALL;
  656. // if endX+1 is a STOWER (corner) , change it to SETOWER
  657. Location *rightLoc;
  658. if( (rightLoc = get_loc(endX+1, y1))->wall_id() == STOWER
  659. && rightLoc->wall_town_recno() == townRecno)
  660. {
  661. rightLoc->remove_wall();
  662. rightLoc->set_wall(SETOWER, townRecno, initHp);
  663. }
  664. }
  665. for( short x = startX; x < endX; ++x)
  666. {
  667. get_loc(x, y1)->set_wall(startSquare, townRecno, initHp);
  668. get_loc(x, y1)->set_fire_src(-50);
  669. switch(startSquare)
  670. {
  671. case WTOWER:
  672. startSquare = EWWALL_SHADOW;
  673. break;
  674. case EWWALL_SHADOW:
  675. startSquare = EWWALL;
  676. break;
  677. // otherwise unchange
  678. }
  679. }
  680. get_loc(endX, y1)->set_wall(endSquare, townRecno, initHp);
  681. get_loc(endX, y1)->set_fire_src(-50);
  682. }
  683. startX = endX +1;
  684. }
  685. }
  686. }
  687. //--------------- end of function World::build_south_wall ----------//
  688. //--------------- begin of function World::open_south_gate ----------//
  689. void World::open_south_gate(short x1, short y1, short townRecno)
  690. {
  691. //------ check if any south gate tile is built ---------//
  692. Location *locPtr = get_loc(x1+2,y1);
  693. if( locPtr->is_wall() && locPtr->wall_id() == SGATE_W &&
  694. locPtr->wall_town_recno() == townRecno)
  695. {
  696. for(short x = 3; x < GATE_LENGTH-3; ++x)
  697. for(short y = 0; y < GATE_WIDTH; ++y)
  698. get_loc(x1+x, y1+y)->remove_wall();
  699. }
  700. }
  701. //--------------- end of function World::open_south_gate ----------//
  702. //--------------- begin of function World::form_wall -----------//
  703. //
  704. // adjust wall tile, return no. of tile changed
  705. //
  706. int World::form_wall(short x, short y, short maxRecur)
  707. {
  708. Location *locPtr = get_loc(x,y);
  709. if( !locPtr->is_wall() || maxRecur < 0)
  710. return 0;
  711. int wallTile = locPtr->wall_id();
  712. int blockChanged = 0;
  713. int flag = 0;
  714. if( y == 0 || get_loc(x,y-1)->is_wall()) // north square
  715. flag |= 1;
  716. if( x == max_x_loc-1 || get_loc(x+1,y)->is_wall() ) // east square
  717. flag |= 2;
  718. if( y == max_y_loc-1 || get_loc(x,y+1)->is_wall() ) // south square
  719. flag |= 4;
  720. if( x == 0 || get_loc(x-1,y)->is_wall() ) // west square
  721. flag |= 8;
  722. int newWallTile, newWallRubble;
  723. // ------- find new wall tile ---------//
  724. switch(flag)
  725. {
  726. case 0: // no surrounding square is wall
  727. newWallTile = SINGLE_TOWER;
  728. newWallRubble = TOWER_CON1;
  729. break;
  730. case 1: // only north square is wall
  731. newWallTile = STOWER;
  732. newWallRubble = TOWER_CON1;
  733. break;
  734. case 2: // only east
  735. newWallTile = WTOWER;
  736. newWallRubble = TOWER_CON1;
  737. break;
  738. case 3: // north and east
  739. newWallTile = SWTOWER;
  740. newWallRubble = TOWER_CON1;
  741. break;
  742. case 4: // south only
  743. newWallTile = NTOWER;
  744. newWallRubble = TOWER_CON1;
  745. break;
  746. case 5: // north and south
  747. newWallTile = NSWALL;
  748. if( y > 0 && get_loc(x,y-1)->is_wall() )
  749. {
  750. int northWallTile = get_loc(x,y-1)->wall_id();
  751. if( northWallTile != NSWALL && northWallTile != NSWALL_SHADOW &&
  752. !is_wall_rubble(northWallTile))
  753. newWallTile = NSWALL_SHADOW;
  754. }
  755. newWallRubble = NSWALL_CON1;
  756. break;
  757. case 6: // east and south
  758. newWallTile = NWTOWER;
  759. newWallRubble = TOWER_CON1;
  760. break;
  761. case 7: // east and north and south
  762. newWallTile = NWTOWER;
  763. newWallRubble = TOWER_CON1;
  764. break;
  765. case 8: // west only
  766. newWallTile = ETOWER;
  767. newWallRubble = TOWER_CON1;
  768. break;
  769. case 9: // west and north
  770. newWallTile = SETOWER;
  771. newWallRubble = TOWER_CON1;
  772. break;
  773. case 10: // west and east
  774. newWallTile = EWWALL;
  775. if( x > 0 && get_loc(x-1,y)->is_wall() )
  776. {
  777. int westWallTile = get_loc(x-1,y)->wall_id();
  778. if( westWallTile != EWWALL && westWallTile != EWWALL_SHADOW &&
  779. !is_wall_rubble(westWallTile) )
  780. newWallTile = EWWALL_SHADOW;
  781. }
  782. newWallRubble = EWWALL_CON1;
  783. break;
  784. case 11: // west and east and north
  785. newWallTile = ETOWER;
  786. newWallRubble = TOWER_CON1;
  787. break;
  788. case 12: // west and south
  789. newWallTile = NETOWER;
  790. newWallRubble = TOWER_CON1;
  791. break;
  792. case 13: // west and south and north
  793. newWallTile = NETOWER;
  794. newWallRubble = TOWER_CON1;
  795. break;
  796. case 14: // west and south and east
  797. newWallTile = NETOWER;
  798. newWallRubble = TOWER_CON1;
  799. break;
  800. case 15: // all four
  801. newWallTile = NETOWER;
  802. newWallRubble = TOWER_CON1;
  803. break;
  804. }
  805. // --- adjust newWallTile from wall_grade() ------//
  806. switch(get_loc(x,y)->wall_grade())
  807. {
  808. case 1:
  809. newWallTile = newWallRubble;
  810. break;
  811. case -1:
  812. newWallTile = newWallRubble + TOWER_DES1 - TOWER_CON1; // e.g. TOWER_CON1 -> TOWER_DES1
  813. break;
  814. case 2:
  815. newWallTile = newWallRubble + 1;
  816. break;
  817. case -2:
  818. newWallTile = newWallRubble + TOWER_DES2 - TOWER_CON1;
  819. break;
  820. case 3:
  821. newWallTile = newWallRubble + 2;
  822. break;
  823. case -3:
  824. newWallTile = newWallRubble + TOWER_DES3 - TOWER_CON1;
  825. break;
  826. case 4:
  827. case -4:
  828. // no change
  829. break;
  830. default:
  831. err_here();
  832. }
  833. // --- change wall tile, such as change to tower, add shadow ----//
  834. if( wallTile != newWallTile)
  835. {
  836. locPtr->chg_wall_id(newWallTile);
  837. blockChanged ++;
  838. }
  839. // change adjacent sqaure
  840. if( y > 0 && get_loc(x,y-1)->is_wall() )
  841. blockChanged += form_wall(x, y-1, maxRecur-1);
  842. if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
  843. blockChanged += form_wall(x, y+1, maxRecur-1);
  844. if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
  845. blockChanged += form_wall(x+1, y, maxRecur-1);
  846. if( x > 0 && get_loc(x-1,y)->is_wall() )
  847. blockChanged += form_wall(x-1, y, maxRecur-1);
  848. return blockChanged;
  849. }
  850. //--------------- end of function World::form_wall -----------//
  851. //--------------- begin of function World::correct_wall -----------//
  852. //
  853. // adjust adjacent wall tiles, return no. of tile changed
  854. //
  855. int World::correct_wall(short x, short y, short maxRecur)
  856. {
  857. if( maxRecur < 0)
  858. return 0;
  859. int blockChanged = 0;
  860. // change adjacent sqaure
  861. if( y > 0 && get_loc(x,y-1)->is_wall() )
  862. blockChanged += form_wall(x, y-1, maxRecur-1);
  863. if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
  864. blockChanged += form_wall(x, y+1, maxRecur-1);
  865. if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
  866. blockChanged += form_wall(x+1, y, maxRecur-1);
  867. if( x > 0 && get_loc(x-1,y)->is_wall() )
  868. blockChanged += form_wall(x-1, y, maxRecur-1);
  869. return blockChanged;
  870. }
  871. //---------- begin of function World::form_world_wall -----//
  872. void World::form_world_wall()
  873. {
  874. static int init_build_wall_seq = 0;
  875. #define SPACING 12
  876. static char build_wall_x_seq[SPACING*SPACING];
  877. static char build_wall_y_seq[SPACING*SPACING];
  878. static int next_build_wall_seq;
  879. int x, y;
  880. if(! init_build_wall_seq )
  881. {
  882. init_build_wall_seq = 1;
  883. DWORD seed = m.get_random_seed();
  884. // ------ initialize with linear sequence----- //
  885. for( y = 0; y < SPACING; ++y)
  886. {
  887. for( x = 0; x < SPACING; ++x)
  888. {
  889. build_wall_x_seq[y*SPACING+x] = x;
  890. build_wall_y_seq[y*SPACING+x] = y;
  891. }
  892. }
  893. m.set_random_seed(176682233); // hard code
  894. //------- shuffle randomly ----------//
  895. for(int t = SPACING * SPACING -1; t >= 0; --t)
  896. {
  897. int u = m.random(SPACING * SPACING);
  898. // ----- swap build_wall_x/y_seq[t] with [u]
  899. char tmp;
  900. tmp = build_wall_x_seq[t];
  901. build_wall_x_seq[t] = build_wall_x_seq[u];
  902. build_wall_x_seq[u] = tmp;
  903. tmp = build_wall_y_seq[t];
  904. build_wall_y_seq[t] = build_wall_y_seq[u];
  905. build_wall_y_seq[u] = tmp;
  906. }
  907. next_build_wall_seq = 0;
  908. m.set_random_seed(seed);
  909. }
  910. for(int trial = 7; trial > 0 ; --trial)
  911. {
  912. for(y = build_wall_y_seq[next_build_wall_seq]; y < max_y_loc; y+= SPACING)
  913. {
  914. for(x = build_wall_x_seq[next_build_wall_seq]; x < max_x_loc; x+= SPACING)
  915. {
  916. Location *locPtr = get_loc(x,y);
  917. // ######## begin Gilbert 7/3 ##########//
  918. if( locPtr->had_wall() )
  919. {
  920. locPtr->dec_wall_timeout();
  921. }
  922. else if( locPtr->is_wall())
  923. // ######## end Gilbert 7/3 ##########//
  924. {
  925. int prevGrade = locPtr->wall_grade();
  926. int newGrade;
  927. if( locPtr->inc_wall_hit_point(WALL_GROWTH_RATE) == 0)
  928. {
  929. locPtr->remove_wall();
  930. if( y > 0 && get_loc(x,y-1)->is_wall() )
  931. form_wall(x,y-1, 1);
  932. if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
  933. form_wall(x,y+1, 1);
  934. if( x > 0 && get_loc(x-1,y)->is_wall() )
  935. form_wall(x-1,y, 1);
  936. if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
  937. form_wall(x+1,y, 1);
  938. }
  939. else if( prevGrade != (newGrade=locPtr->wall_grade()) )
  940. {
  941. form_wall(x,y,2);
  942. }
  943. }
  944. }
  945. }
  946. next_build_wall_seq = (next_build_wall_seq+1) % (SPACING*SPACING);
  947. }
  948. }
  949. //---------- end of function World::form_world_wall -----//
  950. //------- Begin of function World::build_wall_tile -------//
  951. //
  952. // <int> xLoc, yLoc - the location on which the wall should be built
  953. // <int> nationRecno - recno of the builder nation
  954. //
  955. // see also ZoomMatrix->draw_build_marker
  956. //
  957. void World::build_wall_tile(int xLoc, int yLoc, short nationRecno, char remoteAction)
  958. {
  959. Location *locPtr = get_loc(xLoc, yLoc);
  960. if( can_build_wall(xLoc, yLoc, nationRecno))
  961. {
  962. if( !remoteAction && remote.is_enable() )
  963. {
  964. // packet structure : <nation recno> <xLoc> <yLoc>
  965. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_BUILD, 3*sizeof(short));
  966. shortPtr[0] = nationRecno;
  967. shortPtr[1] = xLoc;
  968. shortPtr[2] = yLoc;
  969. }
  970. else
  971. {
  972. locPtr->set_wall(TOWER_CON1,nationRecno, 1);
  973. locPtr->set_fire_src(-50);
  974. // nation_array[nationRecno]->add_expense( (float)BUILD_WALL_COST );
  975. }
  976. }
  977. else if( locPtr->is_wall_destructing() &&
  978. can_destruct_wall(xLoc, yLoc, nationRecno))
  979. {
  980. if( !remoteAction && remote.is_enable() )
  981. {
  982. // packet structure : <nation recno> <xLoc> <yLoc>
  983. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_BUILD, 3*sizeof(short));
  984. shortPtr[0] = nationRecno;
  985. shortPtr[1] = xLoc;
  986. shortPtr[2] = yLoc;
  987. }
  988. else
  989. {
  990. locPtr->set_wall_creating();
  991. // nation_array[nationRecno]->add_expense( (float)
  992. // BUILD_WALL_COST * (100-locPtr->wall_abs_hit_point()) / 100 );
  993. }
  994. }
  995. }
  996. //--------- End of function World::build_wall_tile ---------//
  997. //------- Begin of function World::destruct_wall_tile -------//
  998. //
  999. // <int> xLoc, yLoc - the location on which the wall should be destructed
  1000. // <int> nationRecno - recno of the destructer nation
  1001. //
  1002. // see also ZoomMatrix->draw_build_marker
  1003. //
  1004. void World::destruct_wall_tile(int xLoc, int yLoc, short nationRecno, char remoteAction)
  1005. {
  1006. Location *locPtr = get_loc(xLoc, yLoc);
  1007. if( locPtr->is_wall_creating() && can_destruct_wall(xLoc, yLoc, nationRecno) )
  1008. {
  1009. if( !remoteAction && remote.is_enable() )
  1010. {
  1011. // packet structure : <nation recno> <xLoc> <yLoc>
  1012. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_DESTRUCT, 3*sizeof(short));
  1013. shortPtr[0] = nationRecno;
  1014. shortPtr[1] = xLoc;
  1015. shortPtr[2] = yLoc;
  1016. }
  1017. else
  1018. {
  1019. locPtr->set_wall_destructing();
  1020. // nation_array[nationRecno]->add_expense( (float) DESTRUCT_WALL_COST );
  1021. }
  1022. }
  1023. }
  1024. //--------- End of function World::destruct_wall_tile ---------//