LOGIC.CPP 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. ** Command & Conquer(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: F:\projects\c&c\vcs\code\logic.cpv 2.17 16 Oct 1995 16:50:52 JOE_BOSTIC $ */
  19. /***********************************************************************************************
  20. *** 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 ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : LOGIC.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : September 27, 1993 *
  30. * *
  31. * Last Update : December 23, 1994 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * LogicClass::AI -- Handles AI logic processing for game objects. *
  36. * LogicClass::Debug_Dump -- Displays logic class status to the mono screen. *
  37. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  38. #include "function.h"
  39. #include "logic.h"
  40. static unsigned FramesPerSecond=0;
  41. #ifdef CHEAT_KEYS
  42. static unsigned TotalFrames;
  43. static unsigned FPSDivider = 1;
  44. static unsigned AverageFramesPerSecond;
  45. /***********************************************************************************************
  46. * LogicClass::Debug_Dump -- Displays logic class status to the mono screen. *
  47. * *
  48. * This is a debugging support routine. It displays the current state of the logic class *
  49. * to the monochrome monitor. It assumes that it is being called once per second. *
  50. * *
  51. * INPUT: none *
  52. * *
  53. * OUTPUT: none *
  54. * *
  55. * WARNINGS: Call this routine only once per second. *
  56. * *
  57. * HISTORY: *
  58. * 05/31/1994 JLB : Created. *
  59. *=============================================================================================*/
  60. void LogicClass::Debug_Dump(MonoClass *mono) const
  61. {
  62. #define RECORDCOUNT 40
  63. #define RECORDHEIGHT 21
  64. static struct {
  65. int Graphic;
  66. } _record[RECORDCOUNT];
  67. static int _framecounter = 0;
  68. TotalFrames+= FramesPerSecond;
  69. AverageFramesPerSecond = TotalFrames/FPSDivider++;
  70. mono->Set_Cursor(21, 9);
  71. mono->Print(
  72. "ÚÄÄÄÄÄÄÄÄÄÄÂÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r"
  73. "³Units.....³ ³Frame Rate: Avg: Frame: ³\r"
  74. "³Infantry..³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´\r"
  75. "³Aircraft..³ ³ ³\r"
  76. "³Buildings.³ ³ ³\r"
  77. "³Terrain...³ Ã ´\r"
  78. "³Bullets...³ ³ ³\r"
  79. "³Anims.....³ ³ ³\r"
  80. "³Teams.....³ Ã Ä´\r"
  81. "³Triggers..³ ³ ³\r"
  82. "³Factories.³ ³ ³\r"
  83. "³ ³ Ã ´\r"
  84. "³ ³ ³ ³\r"
  85. "ÀÄÄÄÄÄÄÄÄÄÄÁÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄ´Spare CPU TimeÃÄÄÄÄÄÄÄÄÄÄÄÄÙ\r");
  86. _framecounter++;
  87. mono->Set_Cursor(70, 10);mono->Printf("%ld", Frame);
  88. if (ScenarioInit) {
  89. mono->Set_Cursor(21, 9);mono->Printf("%d", ScenarioInit);
  90. }
  91. mono->Set_Cursor(33, 10);mono->Printf("%3d", Units.Count());
  92. mono->Set_Cursor(33, 11);mono->Printf("%3d", Infantry.Count());
  93. mono->Set_Cursor(33, 12);mono->Printf("%3d", Aircraft.Count());
  94. mono->Set_Cursor(33, 13);mono->Printf("%3d", Buildings.Count());
  95. mono->Set_Cursor(33, 14);mono->Printf("%3d", Terrains.Count());
  96. mono->Set_Cursor(33, 15);mono->Printf("%3d", Bullets.Count());
  97. mono->Set_Cursor(33, 16);mono->Printf("%3d", Anims.Count());
  98. mono->Set_Cursor(33, 17);mono->Printf("%3d", Teams.Count());
  99. mono->Set_Cursor(33, 18);mono->Printf("%3d", Triggers.Count());
  100. mono->Set_Cursor(33, 19);mono->Printf("%3d", Factories.Count());
  101. mono->Set_Cursor(48, 10);mono->Printf("%d", FramesPerSecond);
  102. mono->Set_Cursor(58, 10);mono->Printf("%d", AverageFramesPerSecond);
  103. /*
  104. ** Advance to the next recorded performance record. If the record buffer
  105. ** is full then throw out the oldest record.
  106. */
  107. memcpy(&_record[0], &_record[1], sizeof(_record[0])*(RECORDCOUNT-1));
  108. /*
  109. ** Fill in the data for the current frame's performance record.
  110. */
  111. SpareTicks = MIN((long)SpareTicks, (long)TIMER_SECOND);
  112. _record[RECORDCOUNT-1].Graphic = Fixed_To_Cardinal(RECORDHEIGHT, Cardinal_To_Fixed(TIMER_SECOND, SpareTicks));
  113. /*
  114. ** Draw the bars across the performance record screen.
  115. */
  116. for (int column = 0; column < RECORDCOUNT; column++) {
  117. for (int row = 1; row < RECORDHEIGHT; row += 2) {
  118. static char _barchar[4] = {' ', 220, 0, 219};
  119. char str[2];
  120. int index = 0;
  121. index |= (_record[column].Graphic >= row) ? 0x01 : 0x00;
  122. index |= (_record[column].Graphic >= row+1) ? 0x02: 0x00;
  123. str[1] = '\0';
  124. str[0] = _barchar[index];
  125. mono->Text_Print(str, 37+column, 21-(row/2));
  126. }
  127. }
  128. SpareTicks = 0;
  129. FramesPerSecond = 0;
  130. }
  131. #endif
  132. /***********************************************************************************************
  133. * LogicClass::AI -- Handles AI logic processing for game objects. *
  134. * *
  135. * This routine is used to perform the AI processing for all game objects. This includes *
  136. * all houses, factories, objects, and teams. *
  137. * *
  138. * INPUT: none *
  139. * *
  140. * OUTPUT: none *
  141. * *
  142. * WARNINGS: none *
  143. * *
  144. * HISTORY: *
  145. * 05/29/1994 JLB : Created. *
  146. * 12/17/1994 JLB : Must perform one complete pass rather than bailing early. *
  147. * 12/23/1994 JLB : Esures that no object gets skipped if it was deleted. *
  148. *=============================================================================================*/
  149. void LogicClass::AI(void)
  150. {
  151. int index;
  152. FramesPerSecond++;
  153. /*
  154. ** Crate regeneration is handled here.
  155. */
  156. if (GameToPlay != GAME_NORMAL && CrateMaker && CrateTimer.Expired()) {
  157. Map.Place_Random_Crate();
  158. CrateTimer = TICKS_PER_MINUTE * Random_Pick(7, 15);
  159. }
  160. /*
  161. ** Team AI is processed.
  162. */
  163. for (index = 0; index < Teams.Count(); index++) {
  164. Teams.Ptr(index)->AI();
  165. }
  166. // Heap_Dump_Check( "After Team AI" );
  167. /*
  168. ** AI for all sentient objects is processed.
  169. */
  170. for (index = 0; index < Count(); index++) {
  171. ObjectClass * obj = (*this)[index];
  172. obj->AI();
  173. /*
  174. ** If the object was destroyed in the process of performing its AI, then
  175. ** adjust the index so that no object gets skipped.
  176. */
  177. if (obj != (*this)[index]) {
  178. // if (!obj->IsActive) {
  179. index--;
  180. }
  181. }
  182. // Heap_Dump_Check( "After Object AI" );
  183. /*
  184. ** A second pass through the sentient objects is required so that the appropriate scan
  185. ** bits will be set for the owner house.
  186. */
  187. for (index = 0; index < Units.Count(); index++) {
  188. UnitClass const * unit = Units.Ptr(index);
  189. if (unit->IsLocked && (GameToPlay != GAME_NORMAL || !unit->House->IsHuman || unit->IsDiscoveredByPlayer)) {
  190. unit->House->NewUScan |= (1L << unit->Class->Type);
  191. if (!unit->IsInLimbo) unit->House->NewActiveUScan |= (1L << unit->Class->Type);
  192. }
  193. }
  194. for (index = 0; index < Infantry.Count(); index++) {
  195. InfantryClass const * infantry = Infantry.Ptr(index);
  196. if (infantry->IsLocked && (GameToPlay != GAME_NORMAL || !infantry->House->IsHuman || infantry->IsDiscoveredByPlayer)) {
  197. infantry->House->NewIScan |= (1L << infantry->Class->Type);
  198. if (!infantry->IsInLimbo) infantry->House->NewActiveIScan |= (1L << infantry->Class->Type);
  199. }
  200. }
  201. for (index = 0; index < Aircraft.Count(); index++) {
  202. AircraftClass const * aircraft = Aircraft.Ptr(index);
  203. if (aircraft->IsLocked && (GameToPlay != GAME_NORMAL || !aircraft->House->IsHuman || aircraft->IsDiscoveredByPlayer)) {
  204. aircraft->House->NewAScan |= (1L << aircraft->Class->Type);
  205. if (!aircraft->IsInLimbo) aircraft->House->NewActiveAScan |= (1L << aircraft->Class->Type);
  206. }
  207. }
  208. for (index = 0; index < Buildings.Count(); index++) {
  209. BuildingClass const * building = Buildings.Ptr(index);
  210. if (building->IsLocked && (GameToPlay != GAME_NORMAL || !building->House->IsHuman || building->IsDiscoveredByPlayer)) {
  211. building->House->NewBScan |= (1L << building->Class->Type);
  212. if (!building->IsInLimbo) building->House->NewActiveBScan |= (1L << building->Class->Type);
  213. }
  214. }
  215. // Heap_Dump_Check( "After Object AI 2" );
  216. /*
  217. ** Map related logic is performed.
  218. */
  219. Map.Logic();
  220. // Heap_Dump_Check( "After Map.Logic" );
  221. /*
  222. ** Factory processing is performed.
  223. */
  224. for (index = 0; index < Factories.Count(); index++) {
  225. Factories.Ptr(index)->AI();
  226. }
  227. // Heap_Dump_Check( "After Factory AI" );
  228. /*
  229. ** House processing is performed.
  230. */
  231. for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
  232. HouseClass * hptr = HouseClass::As_Pointer(house);
  233. if (hptr && hptr->IsActive) {
  234. hptr->AI();
  235. }
  236. }
  237. // Heap_Dump_Check( "After House AI" );
  238. }