FACE.CPP 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /CounterStrike/FACE.CPP 1 3/03/97 10:24a Joe_bostic $ */
  15. /***********************************************************************************************
  16. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : FACE.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : 03/08/96 *
  26. * *
  27. * Last Update : March 8, 1996 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * Desired_Facing8 -- Determines facing from one coordinate to another. *
  32. * Desired_Facing256 -- Determines facing from one coordinate to another. *
  33. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  34. #include "function.h"
  35. /***********************************************************************************************
  36. * Desired_Facing8 -- Determines facing from one coordinate to another. *
  37. * *
  38. * This routine will find the facing (compass direction) from one location to another. *
  39. * Typical use of this is in find path and other 'monster' movement logic. *
  40. * *
  41. * INPUT: x1,y1 -- X and Y coordinates for the source location. The coordinate 0,0 is *
  42. * presumed to be the northwest corner of the map. *
  43. * *
  44. * x2,y2 -- X and Y coordinates for the destination (target) location. *
  45. * *
  46. * OUTPUT: Returns with the facing from the first coordinate to the second coordinate. The *
  47. * value returned will range from 0 being North, increasing clockwise until reaching *
  48. * 255 which is just shy of North in a Westerly direction. *
  49. * *
  50. * WARNINGS: This routine is only accurate to the 8 primary compass directions. It is much *
  51. * faster than the Desired_Facing256() function so it should be used where speed *
  52. * is more important than accuracy. *
  53. * *
  54. * HISTORY: *
  55. * 03/08/1996 JLB : Created. *
  56. *=============================================================================================*/
  57. DirType Desired_Facing8(int x1, int y1, int x2, int y2)
  58. {
  59. int index = 0; // Facing composite value.
  60. /*
  61. ** Figure the absolute X difference. This determines
  62. ** if the facing is leftward or not.
  63. */
  64. int xdiff = x2-x1;
  65. if (xdiff < 0) {
  66. index |= 0x00C0;
  67. xdiff = -xdiff;
  68. }
  69. /*
  70. ** Figure the absolute Y difference. This determines
  71. ** if the facing is downward or not. This also clarifies
  72. ** exactly which quadrant the facing lies.
  73. */
  74. int ydiff = y1-y2;
  75. if (ydiff < 0) {
  76. index ^= 0x0040;
  77. ydiff = -ydiff;
  78. }
  79. /*
  80. ** Determine which of the two direction offsets it bigger. The
  81. ** offset direction that is bigger (X or Y) will indicate which
  82. ** orthogonal direction the facing is closer to.
  83. */
  84. unsigned bigger;
  85. unsigned smaller;
  86. if (xdiff < ydiff) {
  87. smaller = xdiff;
  88. bigger = ydiff;
  89. } else {
  90. smaller = ydiff;
  91. bigger = xdiff;
  92. }
  93. /*
  94. ** If on the diagonal, then incorporate this into the facing
  95. ** and then bail. The facing is known.
  96. */
  97. if (((bigger+1)/2) <= smaller) {
  98. index += 0x0020;
  99. return(DirType(index));
  100. }
  101. /*
  102. ** Determine if the facing is closer to the Y axis or
  103. ** the X axis.
  104. */
  105. int adder = (index & 0x0040);
  106. if (xdiff == bigger) {
  107. adder ^= 0x0040;
  108. }
  109. index += adder;
  110. return(DirType(index));
  111. }
  112. /***********************************************************************************************
  113. * Desired_Facing256 -- Determines facing from one coordinate to another. *
  114. * *
  115. * This routine will figure the facing from the source coordinate toward the destination *
  116. * coordinate. Typically, this routine is used for movement and other 'monster' logic. It *
  117. * is more accurate than the corresponding Desired_Facing8() function, but is slower. *
  118. * *
  119. * INPUT: srcx, srcy -- The source coordinate to determine the facing from. *
  120. * *
  121. * dstx, dsty -- The destination (or target) coordinate to determine the facing *
  122. * toward. *
  123. * *
  124. * OUTPUT: Returns with the facing from the source coordinate toward the destination *
  125. * coordinate with 0 being North increasing in a clockwise direction. 64 is East, *
  126. * 128 is South, etc. *
  127. * *
  128. * WARNINGS: The coordinate 0,0 is presumed to be in the Northwest corner of the map. *
  129. * Although this routine is fast, it is not as fast as Desired_Facing8(). *
  130. * *
  131. * HISTORY: *
  132. * 03/08/1996 JLB : Created. *
  133. *=============================================================================================*/
  134. DirType Desired_Facing256(int srcx, int srcy, int dstx, int dsty)
  135. {
  136. int composite=0; // Facing built from intermediate calculations.
  137. /*
  138. ** Fetch the absolute X difference. This also gives a clue as
  139. ** to which hemisphere the direction lies.
  140. */
  141. int xdiff = dstx - srcx;
  142. if (xdiff < 0) {
  143. composite |= 0x00C0;
  144. xdiff = -xdiff;
  145. }
  146. /*
  147. ** Fetch the absolute Y difference. This clarifies the exact
  148. ** quadrant that the direction lies.
  149. */
  150. int ydiff = srcy - dsty;
  151. if (ydiff < 0) {
  152. composite ^= 0x0040;
  153. ydiff = -ydiff;
  154. }
  155. /*
  156. ** Bail early if the coordinates are the same. This check also
  157. ** has the added bonus of ensuring that checking for division
  158. ** by zero is not needed in the following section.
  159. */
  160. if (xdiff == 0 && ydiff == 0) return(DirType(0xFF));
  161. /*
  162. ** Determine which of the two direction offsets it bigger. The
  163. ** offset direction that is bigger (X or Y) will indicate which
  164. ** orthogonal direction the facing is closer to.
  165. */
  166. unsigned bigger;
  167. unsigned smaller;
  168. if (xdiff < ydiff) {
  169. smaller = xdiff;
  170. bigger = ydiff;
  171. } else {
  172. smaller = ydiff;
  173. bigger = xdiff;
  174. }
  175. /*
  176. ** Now that the quadrant is known, we need to determine how far
  177. ** from the orthogonal directions, the facing lies. This value
  178. ** is calculated as a ratio from 0 (matches orthogonal) to 31
  179. ** (matches diagonal).
  180. */
  181. //lint -e414 Division by zero cannot occur here.
  182. int frac = (smaller * 32U) / bigger;
  183. /*
  184. ** Given the quadrant and knowing whether the facing is closer
  185. ** to the X or Y axis, we must make an adjustment toward the
  186. ** subsequent quadrant if necessary.
  187. */
  188. int adder = (composite & 0x0040);
  189. if (xdiff > ydiff) {
  190. adder ^= 0x0040;
  191. }
  192. if (adder) {
  193. frac = (adder - frac)-1;
  194. }
  195. /*
  196. ** Integrate the fraction value into the quadrant.
  197. */
  198. composite += frac;
  199. /*
  200. ** Return with the final facing value.
  201. */
  202. return(DirType(composite & 0x00FF));
  203. }