Skill.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /***********************************************************************
  2. *
  3. * SPACE TRADER 1.2.0
  4. *
  5. * Skill.c
  6. *
  7. * Copyright (C) 2000-2002 Pieter Spronck, All Rights Reserved
  8. *
  9. * Additional coding by Sam Anderson (rulez2@home.com)
  10. * Additional coding by Samuel Goldstein (palm@fogbound.net)
  11. *
  12. * Some code of Matt Lee's Dope Wars program has been used.
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  27. *
  28. * You can contact the author at space_trader@hotmail.com
  29. *
  30. * For those who are familiar with the classic game Elite: many of the
  31. * ideas in Space Trader are heavily inspired by Elite.
  32. *
  33. **********************************************************************/
  34. // *************************************************************************
  35. // Skill.c - Functions in this module:
  36. //
  37. // char TraderSkill( SHIP* _Sh );
  38. // void RecalculateBuyPrices(Byte SystemID);
  39. // void IncreaseRandomSkill();
  40. // char FighterSkill( SHIP* _Sh );
  41. // char PilotSkill( SHIP* _Sh );
  42. // char EngineerSkill( SHIP* _Sh );
  43. // char AdaptDifficulty( char _Level );
  44. // void RecalculateSellPrices();
  45. // char RandomSkill( void )
  46. // Boolean HasGadget( SHIP* Sh, char Gg )
  47. // Byte NthLowestSkill( SHIP* Sh, Byte n )
  48. //
  49. // Modifications:
  50. // mm/dd/yy - description - author
  51. // *************************************************************************
  52. #include "external.h"
  53. // *************************************************************************
  54. // NthLowest Skill. Returns skill with the nth lowest score
  55. // (i.e., 2 is the second worst skill). If there is a tie, it will return
  56. // in the order of Pilot, Fighter, Trader, Engineer.
  57. // *************************************************************************
  58. Byte NthLowestSkill( SHIP* Sh, Byte n )
  59. {
  60. Byte i = 0, lower = 1, retVal;
  61. Boolean looping = true;
  62. while (looping)
  63. {
  64. retVal = 0;
  65. if (Mercenary[Sh->Crew[0]].Pilot == i)
  66. {
  67. if (lower == n)
  68. {
  69. looping = false;
  70. retVal = PILOTSKILL;
  71. }
  72. lower++;
  73. }
  74. if (Mercenary[Sh->Crew[0]].Fighter == i)
  75. {
  76. if (lower == n)
  77. {
  78. looping = false;
  79. retVal = FIGHTERSKILL;
  80. }
  81. lower++;
  82. }
  83. if (Mercenary[Sh->Crew[0]].Trader == i)
  84. {
  85. if (lower == n)
  86. {
  87. looping = false;
  88. retVal = TRADERSKILL;
  89. }
  90. lower++;
  91. }
  92. if (Mercenary[Sh->Crew[0]].Engineer == i)
  93. {
  94. if (lower == n)
  95. {
  96. looping = false;
  97. retVal = ENGINEERSKILL;
  98. }
  99. lower++;
  100. }
  101. i++;
  102. }
  103. return retVal;
  104. }
  105. // *************************************************************************
  106. // Trader skill
  107. // *************************************************************************
  108. char TraderSkill( SHIP* Sh )
  109. {
  110. int i;
  111. char MaxSkill;
  112. MaxSkill = Mercenary[Sh->Crew[0]].Trader;
  113. for (i=1; i<MAXCREW; ++i)
  114. {
  115. if (Sh->Crew[i] < 0)
  116. break;
  117. if (Mercenary[Sh->Crew[i]].Trader > MaxSkill)
  118. MaxSkill = Mercenary[Sh->Crew[i]].Trader;
  119. }
  120. if (JarekStatus >= 2)
  121. ++MaxSkill;
  122. return AdaptDifficulty( MaxSkill );
  123. }
  124. // *************************************************************************
  125. // After changing the trader skill, buying prices must be recalculated.
  126. // Revised to be callable on an arbitrary Solar System
  127. // *************************************************************************
  128. void RecalculateBuyPrices( Byte SystemID )
  129. {
  130. int i;
  131. for (i=0; i<MAXTRADEITEM; ++i)
  132. {
  133. if (SolarSystem[SystemID].TechLevel < Tradeitem[i].TechProduction)
  134. BuyPrice[i] = 0;
  135. else if (((i == NARCOTICS) && (!Politics[SolarSystem[SystemID].Politics].DrugsOK)) ||
  136. ((i == FIREARMS) && (!Politics[SolarSystem[SystemID].Politics].FirearmsOK)))
  137. BuyPrice[i] = 0;
  138. else
  139. {
  140. if (PoliceRecordScore < DUBIOUSSCORE)
  141. BuyPrice[i] = (SellPrice[i] * 100) / 90;
  142. else
  143. BuyPrice[i] = SellPrice[i];
  144. // BuyPrice = SellPrice + 1 to 12% (depending on trader skill (minimum is 1, max 12))
  145. BuyPrice[i] = (BuyPrice[i] * (103 + (MAXSKILL - TraderSkill( &Ship ))) / 100);
  146. if (BuyPrice[i] <= SellPrice[i])
  147. BuyPrice[i] = SellPrice[i] + 1;
  148. }
  149. }
  150. }
  151. // *************************************************************************
  152. // Increase one of the skills of the commander
  153. // *************************************************************************
  154. void IncreaseRandomSkill( void )
  155. {
  156. Boolean Redo;
  157. int d, oldtraderskill;
  158. if (COMMANDER.Pilot >= MAXSKILL && COMMANDER.Trader >= MAXSKILL &&
  159. COMMANDER.Fighter >= MAXSKILL && COMMANDER.Engineer >= MAXSKILL)
  160. return;
  161. oldtraderskill = TraderSkill( &Ship );
  162. Redo = true;
  163. while (Redo)
  164. {
  165. d = (GetRandom( MAXSKILLTYPE ));
  166. if ((d == 0 && COMMANDER.Pilot < MAXSKILL) ||
  167. (d == 1 && COMMANDER.Fighter < MAXSKILL) ||
  168. (d == 2 && COMMANDER.Trader < MAXSKILL) ||
  169. (d == 3 && COMMANDER.Engineer < MAXSKILL))
  170. Redo = false;
  171. }
  172. if (d == 0)
  173. COMMANDER.Pilot += 1;
  174. else if (d == 1)
  175. COMMANDER.Fighter += 1;
  176. else if (d == 2)
  177. {
  178. COMMANDER.Trader += 1;
  179. if (oldtraderskill != TraderSkill( &Ship ))
  180. RecalculateBuyPrices(COMMANDER.CurSystem);
  181. }
  182. else
  183. COMMANDER.Engineer += 1;
  184. }
  185. // *************************************************************************
  186. // Decrease one of the skills of the commander
  187. // *************************************************************************
  188. void DecreaseRandomSkill( int amount )
  189. {
  190. Boolean Redo;
  191. int d, oldtraderskill;
  192. if (COMMANDER.Pilot >= MAXSKILL && COMMANDER.Trader >= MAXSKILL &&
  193. COMMANDER.Fighter >= MAXSKILL && COMMANDER.Engineer >= MAXSKILL)
  194. return;
  195. oldtraderskill = TraderSkill( &Ship );
  196. Redo = true;
  197. while (Redo)
  198. {
  199. d = (GetRandom( MAXSKILLTYPE ));
  200. if ((d == 0 && COMMANDER.Pilot > amount) ||
  201. (d == 1 && COMMANDER.Fighter > amount) ||
  202. (d == 2 && COMMANDER.Trader > amount) ||
  203. (d == 3 && COMMANDER.Engineer > amount))
  204. Redo = false;
  205. }
  206. if (d == 0)
  207. COMMANDER.Pilot -= amount;
  208. else if (d == 1)
  209. COMMANDER.Fighter -= amount;
  210. else if (d == 2)
  211. {
  212. COMMANDER.Trader -= amount;
  213. if (oldtraderskill != TraderSkill( &Ship ))
  214. RecalculateBuyPrices(COMMANDER.CurSystem);
  215. }
  216. else
  217. COMMANDER.Engineer -= amount;
  218. }
  219. // *************************************************************************
  220. // Randomly tweak one of the skills of the commander
  221. // *************************************************************************
  222. void TonicTweakRandomSkill( void )
  223. {
  224. int oldPilot, oldFighter, oldTrader, oldEngineer;
  225. oldPilot = COMMANDER.Pilot;
  226. oldFighter = COMMANDER.Fighter;
  227. oldTrader = COMMANDER.Trader;
  228. oldEngineer = COMMANDER.Engineer;
  229. if (Difficulty < HARD)
  230. {
  231. // add one to a random skill, subtract one from a random skill
  232. while ( oldPilot == COMMANDER.Pilot &&
  233. oldFighter == COMMANDER.Fighter &&
  234. oldTrader == COMMANDER.Trader &&
  235. oldEngineer == COMMANDER.Engineer)
  236. {
  237. IncreaseRandomSkill();
  238. DecreaseRandomSkill(1);
  239. }
  240. }
  241. else
  242. {
  243. // add one to two random skills, subtract three from one random skill
  244. IncreaseRandomSkill();
  245. IncreaseRandomSkill();
  246. DecreaseRandomSkill(3);
  247. }
  248. }
  249. // *************************************************************************
  250. // Fighter skill
  251. // *************************************************************************
  252. char FighterSkill( SHIP* Sh )
  253. {
  254. int i;
  255. char MaxSkill;
  256. MaxSkill = Mercenary[Sh->Crew[0]].Fighter;
  257. for (i=1; i<MAXCREW; ++i)
  258. {
  259. if (Sh->Crew[i] < 0)
  260. break;
  261. if (Mercenary[Sh->Crew[i]].Fighter > MaxSkill)
  262. MaxSkill = Mercenary[Sh->Crew[i]].Fighter;
  263. }
  264. if (HasGadget( Sh, TARGETINGSYSTEM ))
  265. MaxSkill += SKILLBONUS;
  266. return AdaptDifficulty( MaxSkill );
  267. }
  268. // *************************************************************************
  269. // Pilot skill
  270. // *************************************************************************
  271. char PilotSkill( SHIP* Sh )
  272. {
  273. int i;
  274. char MaxSkill;
  275. MaxSkill = Mercenary[Sh->Crew[0]].Pilot;
  276. for (i=1; i<MAXCREW; ++i)
  277. {
  278. if (Sh->Crew[i] < 0)
  279. break;
  280. if (Mercenary[Sh->Crew[i]].Pilot > MaxSkill)
  281. MaxSkill = Mercenary[Sh->Crew[i]].Pilot;
  282. }
  283. if (HasGadget( Sh, NAVIGATINGSYSTEM ))
  284. MaxSkill += SKILLBONUS;
  285. if (HasGadget( Sh, CLOAKINGDEVICE ))
  286. MaxSkill += CLOAKBONUS;
  287. return AdaptDifficulty( MaxSkill );
  288. }
  289. // *************************************************************************
  290. // Engineer skill
  291. // *************************************************************************
  292. char EngineerSkill( SHIP* Sh )
  293. {
  294. int i;
  295. char MaxSkill;
  296. MaxSkill = Mercenary[Sh->Crew[0]].Engineer;
  297. for (i=1; i<MAXCREW; ++i)
  298. {
  299. if (Sh->Crew[i] < 0)
  300. break;
  301. if (Mercenary[Sh->Crew[i]].Engineer > MaxSkill)
  302. MaxSkill = Mercenary[Sh->Crew[i]].Engineer;
  303. }
  304. if (HasGadget( Sh, AUTOREPAIRSYSTEM ))
  305. MaxSkill += SKILLBONUS;
  306. return AdaptDifficulty( MaxSkill );
  307. }
  308. // *************************************************************************
  309. // Adapt a skill to the difficulty level
  310. // *************************************************************************
  311. char AdaptDifficulty( char Level )
  312. {
  313. if (Difficulty == BEGINNER || Difficulty == EASY)
  314. return (Level+1);
  315. else if (Difficulty == IMPOSSIBLE)
  316. return max( 1, Level-1 );
  317. else
  318. return Level;
  319. }
  320. // *************************************************************************
  321. // After erasure of police record, selling prices must be recalculated
  322. // *************************************************************************
  323. void RecalculateSellPrices( void )
  324. {
  325. int i;
  326. for (i=0; i<MAXTRADEITEM; ++i)
  327. SellPrice[i] = (SellPrice[i] * 100) / 90;
  328. }
  329. // *************************************************************************
  330. // Random mercenary skill
  331. // *************************************************************************
  332. char RandomSkill( void )
  333. {
  334. return 1 + GetRandom( 5 ) + GetRandom( 6 );
  335. }
  336. // *************************************************************************
  337. // Determines whether a certain gadget is on board
  338. // *************************************************************************
  339. Boolean HasGadget( SHIP* Sh, char Gg )
  340. {
  341. int i;
  342. for (i=0; i<MAXGADGET; ++i)
  343. {
  344. if (Sh->Gadget[i] < 0)
  345. continue;
  346. if (Sh->Gadget[i] == Gg)
  347. return true;
  348. }
  349. return false;
  350. }
  351. // *************************************************************************
  352. // Determines whether a certain shield type is on board
  353. // *************************************************************************
  354. Boolean HasShield( SHIP* Sh, char Gg )
  355. {
  356. int i;
  357. for (i=0; i<MAXSHIELD; ++i)
  358. {
  359. if (Sh->Shield[i] < 0)
  360. continue;
  361. if (Sh->Shield[i] == Gg)
  362. return true;
  363. }
  364. return false;
  365. }
  366. // *************************************************************************
  367. // Determines whether a certain weapon type is on board. If exactCompare is
  368. // false, then better weapons will also return TRUE
  369. // *************************************************************************
  370. Boolean HasWeapon( SHIP* Sh, char Gg, Boolean exactCompare )
  371. {
  372. int i;
  373. for (i=0; i<MAXWEAPON; ++i)
  374. {
  375. if (Sh->Weapon[i] < 0)
  376. continue;
  377. if ((Sh->Weapon[i] == Gg) || (Sh->Weapon[i] > Gg && !exactCompare))
  378. return true;
  379. }
  380. return false;
  381. }