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