PageRenderTime 75ms CodeModel.GetById 14ms RepoModel.GetById 9ms app.codeStats 0ms

/JTacticalSim.Console/Render/ConsoleRenderer.cs

https://github.com/Queztionmark/JTacticalSim
C# | 1031 lines | 767 code | 192 blank | 72 comment | 77 complexity | e0a499314a783d0187023bc553f7c015 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Concurrent;
  4. using System.Configuration;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using JTacticalSim.API;
  9. using JTacticalSim.API.Component;
  10. using JTacticalSim.API.DTO;
  11. using JTacticalSim.API.Game;
  12. using JTacticalSim.Utility;
  13. namespace JTacticalSim.Console
  14. {
  15. public class ConsoleRenderer : BaseRenderer
  16. {
  17. protected const int ROWSPACING = 8; // Total number of rows per board row
  18. protected const int COLUMNSPACING = 20; // Total spaces per column
  19. protected const int TILEOFFSET = (COLUMNSPACING - COLUMNOFFSET);
  20. protected const int COLUMNHEADEROFFSET = 3; // Number of spaces in a column or row header [R-1 e.g.]
  21. protected const int COLUMNOFFSET = 4; // Number of spaces from the end of the base geog area to the next column
  22. protected const int FLAGWIDTH = 2; // Number of spaces from the beginning of the column to base geog area (where the flag goes)
  23. protected const int BASEGEOGWIDTH = COLUMNSPACING - (COLUMNOFFSET + FLAGWIDTH); // Width of the base geog area to be filled with color - MUST BE EVEN NUMBER
  24. protected const int TILEWIDTH = TILEOFFSET - COLUMNHEADEROFFSET;
  25. protected const int WESTMARGINOFFSET = COLUMNHEADEROFFSET + 2;
  26. protected const int WESTMARGIN = 2;
  27. protected ConsoleColor NodeSelectedColor = ConsoleColor.White;
  28. protected ConsoleColor NodeAvailableForMoveColor = ConsoleColor.Yellow;
  29. protected ConsoleColor UnitSelectedColor = ConsoleColor.White;
  30. protected ConsoleColor BoardBoundaryBGColor = ConsoleColor.DarkGray;
  31. protected ConsoleColor BoardBoundaryFGColor = ConsoleColor.Black;
  32. protected ConsoleColor WestFactionColor = ConsoleColor.DarkYellow;
  33. protected ConsoleColor EastFactionColor = ConsoleColor.Red;
  34. protected ConsoleColor LandBGColor = ConsoleColor.DarkGreen;
  35. protected ConsoleColor WaterBGColor = ConsoleColor.Cyan;
  36. private IGame _theGame { get; set; }
  37. public ConsoleRenderer(IGame theGame)
  38. {
  39. _theGame = theGame;
  40. }
  41. public override void LoadContent()
  42. {
  43. // Do nothing - no graphics content for console
  44. }
  45. public override void UnloadContent()
  46. {
  47. // Do nothing - no graphics content for console
  48. }
  49. // Handle errors
  50. public override void HandleErrorUI(string Message, Exception ex)
  51. {
  52. var display = new StringBuilder("{0} : ".F(Message));
  53. if (ex != null)
  54. display.AppendLine(ex.Message);
  55. DisplayError(display.ToString());
  56. }
  57. public void DisplayError(string error)
  58. {
  59. System.Console.ForegroundColor = ConsoleColor.Red;
  60. System.Console.Write(error);
  61. System.Console.WriteLine();
  62. System.Console.ResetColor();
  63. }
  64. // Screens
  65. public override void RenderBoard()
  66. {
  67. System.Console.Clear();
  68. CreateTitleRow("Main Board");
  69. CreateHeaderRow(2, false);
  70. CreateRows();
  71. CreateFooterRow(false);
  72. CreatePlayerSummaryRow();
  73. CreateFooterRow(true);
  74. System.Console.WriteLine("\n");
  75. }
  76. public override void RenderReinforcementScreen()
  77. {
  78. System.Console.Clear();
  79. CreateTitleRow("Reinforcements");
  80. CreateHeaderRow(0, true);
  81. System.Console.Write("\n");
  82. CreateUnitInfoRows();
  83. CreateFooterRow(true);
  84. CreatePlayerSummaryRow();
  85. CreateFooterRow(true);
  86. System.Console.WriteLine("\n");
  87. }
  88. public override void RenderTitleScreen()
  89. {
  90. System.Console.Clear();
  91. CreateHeaderRow(0, true);
  92. System.Console.Write("\n");
  93. ListScenarios();
  94. System.Console.Write("\n");
  95. ListSavedGames();
  96. CreateFooterRow(true);
  97. System.Console.Write("\n");
  98. }
  99. // Board
  100. public override void RenderNode(INode node)
  101. {
  102. if (node.IsWestOuterBoundary)
  103. {
  104. CreateWestVertBoundFiller();
  105. MoveCursor(WESTMARGIN);
  106. }
  107. node.GetTopTile().Render();
  108. if (node.IsEastOuterBoundary)
  109. {
  110. CreateEastVertBoundFiller();
  111. }
  112. }
  113. public override void RenderTile(ITile tile)
  114. {
  115. // Here in the console renderer, we have to kinda fudge this.
  116. // The data has to be rendered line by line so there's no real concept of
  117. // 'rendering a node or tile'
  118. RenderTileDemographics(tile);
  119. }
  120. /// <summary>
  121. /// Only pertinent to console rendering
  122. /// </summary>
  123. /// <param name="tile"></param>
  124. private void RenderTileDemographics(ITile tile)
  125. {
  126. System.Console.Write(" "); // Flag area...
  127. // For tracking spacers. Start with the 2 spaces for the flag area above^
  128. int i = 2;
  129. // ~~~~~~~~~~ Geography/Terrain
  130. if (tile.ConsoleRenderHelper.hasMountains)
  131. {
  132. var drawMe = tile.AllGeography.Where(d => d.IsDemographicClass("Mountains")).Select(d => d.DemographicClass.TextDisplay).Single();
  133. DrawDemographics(drawMe, ConsoleColor.DarkYellow, ConsoleColor.Black);
  134. i += drawMe.Length;
  135. }
  136. if (tile.ConsoleRenderHelper.hasHills)
  137. {
  138. var drawMe = tile.AllGeography.Where(d => d.IsDemographicClass("Hills")).Select(d => d.DemographicClass.TextDisplay).Single();
  139. DrawDemographics(drawMe, ConsoleColor.DarkYellow, ConsoleColor.Black);
  140. i += drawMe.Length;
  141. }
  142. if (tile.ConsoleRenderHelper.hasLakes)
  143. {
  144. var drawMe = tile.AllGeography.Where(d => d.IsDemographicClass("Lake")).Select(d => d.DemographicClass.TextDisplay).Single();
  145. DrawDemographics(drawMe, ConsoleColor.Blue, ConsoleColor.Black);
  146. i += drawMe.Length;
  147. }
  148. DrawDemographics(" ", ConsoleColor.Black, ConsoleColor.Black);
  149. i++;
  150. // ~~~~~~~~~~~ Flora
  151. if (tile.ConsoleRenderHelper.hasForests)
  152. {
  153. var drawMe = tile.Flora.Where(d => d.IsDemographicClass("Forested")).Select(d => d.DemographicClass.TextDisplay).Single();
  154. DrawDemographics(drawMe, ConsoleColor.Green, ConsoleColor.Black);
  155. i += drawMe.Length;
  156. }
  157. if (tile.ConsoleRenderHelper.hasTrees)
  158. {
  159. var drawMe = tile.Flora.Where(d => d.IsDemographicClass("Trees")).Select(d => d.DemographicClass.TextDisplay).Single();
  160. DrawDemographics(drawMe, ConsoleColor.Green, ConsoleColor.Black);
  161. i += drawMe.Length;
  162. }
  163. if (tile.ConsoleRenderHelper.hasMarsh)
  164. {
  165. var drawMe = tile.Flora.Where(d => d.IsDemographicClass("Marsh")).Select(d => d.DemographicClass.TextDisplay).Single();
  166. DrawDemographics(drawMe, ConsoleColor.Green, ConsoleColor.Black);
  167. i += drawMe.Length;
  168. }
  169. DrawDemographics(" ", ConsoleColor.Black, ConsoleColor.Black);
  170. i++;
  171. // ~~~~~~~~~~ Infrastructure
  172. if (tile.ConsoleRenderHelper.hasCities)
  173. {
  174. var drawMe = tile.Infrastructure.Where(d => d.IsDemographicClass("Urban")).Select(d => d.DemographicClass.TextDisplay).Single();
  175. DrawDemographics(drawMe, ConsoleColor.DarkGray, ConsoleColor.Black);
  176. i += drawMe.Length;
  177. }
  178. if (tile.ConsoleRenderHelper.hasRoad)
  179. {
  180. var drawMe = tile.Infrastructure.Where(d => d.IsDemographicClass("Road")).Select(d => d.DemographicClass.TextDisplay).Single();
  181. DrawDemographics(drawMe, ConsoleColor.DarkGray, ConsoleColor.Black);
  182. i += drawMe.Length;
  183. }
  184. if (tile.ConsoleRenderHelper.hasBridge)
  185. {
  186. var drawMe = tile.Infrastructure.Where(d => d.IsDemographicClass("Bridge")).Select(d => d.DemographicClass.TextDisplay).Single();
  187. DrawDemographics(drawMe, ConsoleColor.DarkGray, ConsoleColor.Black);
  188. i += drawMe.Length;
  189. }
  190. if (tile.ConsoleRenderHelper.hasTracks)
  191. {
  192. var drawMe = tile.Infrastructure.Where(d => d.IsDemographicClass("TrainTrack")).Select(d => d.DemographicClass.TextDisplay).Single();
  193. DrawDemographics(drawMe, ConsoleColor.DarkGray, ConsoleColor.Black);
  194. i += drawMe.Length;
  195. }
  196. // Make the tiles uniform length
  197. for (int count = 0; count < COLUMNSPACING - i; count++)
  198. {
  199. System.Console.Write(" ");
  200. }
  201. System.Console.ResetColor();
  202. }
  203. /// <summary>
  204. /// Only pertinent to console rendering
  205. /// </summary>
  206. /// <param name="nodes"></param>
  207. private void RenderTopTileBaseGeog(IEnumerable<INode> nodes)
  208. {
  209. // Render all the node items
  210. foreach (var n in nodes)
  211. {
  212. if (n.IsWestOuterBoundary)
  213. {
  214. System.Console.Write("\n");
  215. CreateRowHeader(n);
  216. }
  217. DrawTileBaseGeog(n.DefaultTile(), false);
  218. if (n.IsEastOuterBoundary)
  219. {
  220. MoveCursor(COLUMNSPACING - TILEOFFSET);
  221. CreateRowHeader(n);
  222. }
  223. }
  224. }
  225. /// <summary>
  226. /// Only pertinent to console rendering
  227. /// </summary>
  228. /// <param name="nodes"></param>
  229. private void RenderBottomTileBaseGeog(IEnumerable<INode> nodes)
  230. {
  231. // Render all the node items
  232. foreach (var n in nodes)
  233. {
  234. if (n.IsWestOuterBoundary)
  235. {
  236. CreateWestVertBoundFiller();
  237. }
  238. //n.GetTopTile().Render();
  239. DrawTileBaseGeog(n.DefaultTile(), true);
  240. if (n.IsEastOuterBoundary)
  241. {
  242. MoveCursor(COLUMNSPACING - TILEOFFSET);
  243. CreateEastVertBoundFiller();
  244. }
  245. }
  246. }
  247. public override int RenderUnitStackInfo(IUnitStack stack)
  248. {
  249. var allVisibleUnits = stack.GetAllUnits();
  250. var allTransportedUnits = stack.GetAllUnits().Where(u => u.IsBeingTransported());
  251. var sb = new StringBuilder("({0})".F(allVisibleUnits.Count));
  252. if (allTransportedUnits.Any())
  253. sb.Append(" ({0} - trn)".F(allTransportedUnits.Count()));
  254. System.Console.ForegroundColor = (stack.Faction.ID == 0) ? WestFactionColor : EastFactionColor;
  255. System.Console.Write(sb.ToString());
  256. System.Console.ResetColor();
  257. return sb.Length;
  258. }
  259. public override void DisplayPlayerInfo(IPlayer player)
  260. {
  261. System.Console.WriteLine(player.TextInfo());
  262. if (player.UnplacedReinforcements.Any())
  263. {
  264. System.Console.WriteLine("Unplaced Reinforcement Units :");
  265. player.UnplacedReinforcements.ForEach(u => {u.DisplayName(); System.Console.WriteLine();});
  266. }
  267. }
  268. public override void DisplayNodeInfo(INode node)
  269. {
  270. System.Console.WriteLine(node.TextInfo());
  271. if (node.GetTopTile() != null)
  272. {
  273. node.GetTopTile().DisplayInfo();
  274. }
  275. }
  276. public override void DisplayTileInfo(ITile tile)
  277. {
  278. System.Console.WriteLine(tile.TextInfo());
  279. }
  280. public override void DisplayLegend()
  281. {
  282. StringBuilder sb = new StringBuilder();
  283. sb.AppendLine(string.Empty);
  284. var demoClasses = _theGame.JTSServices.GenericComponentService.GetAll<IDemographicClass, IDemographicClassDTO>()
  285. .Where(d => !String.IsNullOrWhiteSpace(d.TextDisplay)).ToList();
  286. var unitGroupTypes = _theGame.JTSServices.GenericComponentService.GetAll<IUnitGroupType, IUnitGroupTypeDTO>()
  287. .Where(ugt => !String.IsNullOrWhiteSpace(ugt.TextDisplay)).ToList();
  288. var unitTypes = _theGame.JTSServices.GenericComponentService.GetAll<IUnitType, IUnitTypeDTO>()
  289. .Where(ut => !String.IsNullOrWhiteSpace(ut.TextDisplay)).ToList();
  290. var unitClasses = _theGame.JTSServices.GenericComponentService.GetAll<IUnitClass, IUnitClassDTO>()
  291. .Where(uc => !String.IsNullOrWhiteSpace(uc.TextDisplay)).ToList();
  292. if (demoClasses.Any())
  293. {
  294. sb.AppendLine("Demographic Classes : ");
  295. sb.AppendLine(string.Empty);
  296. demoClasses.ForEach(d => sb.AppendLine(" {0} : {1}".F(d.TextDisplay, d.Name)));
  297. }
  298. sb.AppendLine(string.Empty);
  299. if (unitGroupTypes.Any())
  300. {
  301. sb.AppendLine("Unit Group Types : ");
  302. sb.AppendLine(string.Empty);
  303. unitGroupTypes.ForEach(d => sb.AppendLine(" {0} : {1}".F(d.TextDisplay, d.Name)));
  304. }
  305. sb.AppendLine(string.Empty);
  306. if (unitTypes.Any())
  307. {
  308. sb.AppendLine("Unit Types : ");
  309. sb.AppendLine(string.Empty);
  310. unitTypes.ForEach(d => sb.AppendLine(" {0} : {1}".F(d.TextDisplay, d.Name)));
  311. }
  312. sb.AppendLine(string.Empty);
  313. if (unitClasses.Any())
  314. {
  315. sb.AppendLine("Unit Classes : ");
  316. sb.AppendLine(string.Empty);
  317. unitClasses.ForEach(d => sb.AppendLine(" {0} : {1}".F(d.TextDisplay, d.Name)));
  318. }
  319. sb.AppendLine(string.Empty);
  320. System.Console.WriteLine(sb.ToString());
  321. }
  322. // Units
  323. public override void DisplayUnits(List<IUnit> units)
  324. {
  325. if (!units.Any())
  326. return;
  327. System.Console.WriteLine("Units : ");
  328. foreach (IUnit u in units)
  329. {
  330. System.Console.WriteLine("----------------------------------------------- |");
  331. u.DisplayInfo();
  332. }
  333. }
  334. public override void DisplayUnitInfo(IUnit unit)
  335. {
  336. System.Console.WriteLine(unit.TextInfo());
  337. }
  338. public override void RenderUnit(IUnit unit)
  339. {
  340. RenderUnitName(unit);
  341. }
  342. public override void RenderUnitName(IUnit unit)
  343. {
  344. if (!unit.IsVisible())
  345. return;
  346. var IsSelectedUnit = (_theGame.GameBoard.SelectedUnits != null && _theGame.GameBoard.SelectedUnits.Any()) &&
  347. (_theGame.GameBoard.SelectedUnits.Any(m => m.Equals(unit)));
  348. System.Console.ForegroundColor = (unit.Faction.ID == 0) ? WestFactionColor : EastFactionColor;
  349. if (IsSelectedUnit) System.Console.ForegroundColor = UnitSelectedColor;
  350. if (!String.IsNullOrEmpty(unit.UnitInfo.UnitGroupType.TextDisplay))
  351. {
  352. System.Console.Write("{0} ", unit.UnitInfo.UnitGroupType.TextDisplay);
  353. }
  354. System.Console.Write("{0}{1} {2}", unit.UnitInfo.UnitClass.TextDisplay,
  355. unit.UnitInfo.UnitType.TextDisplay,
  356. unit.Name);
  357. System.Console.ResetColor();
  358. }
  359. // Battle
  360. public override void RenderBattle(IBattle battle)
  361. {
  362. System.Console.Clear();
  363. System.Console.WriteLine(" ------------------------- COMBAT --------------------------");
  364. // Show the attackers and defenders....
  365. _theGame.CurrentBattle.Attackers.ForEach(u =>
  366. {
  367. System.Console.WriteLine();
  368. u.Render();
  369. });
  370. System.Console.WriteLine(" ");
  371. System.Console.WriteLine(" ");
  372. System.Console.WriteLine(" - VS - ");
  373. _theGame.CurrentBattle.Defenders.ForEach(u =>
  374. {
  375. System.Console.WriteLine();
  376. u.Render();
  377. });
  378. System.Console.WriteLine(" ");
  379. System.Console.WriteLine(" ");
  380. }
  381. public override void RenderBattleRound(IRound round)
  382. {
  383. if (!round.Skirmishes.Any()) return;
  384. System.Console.WriteLine(" ");
  385. System.Console.WriteLine(" ----------------------------------------------- Start Round");
  386. System.Console.WriteLine(" ");
  387. round.Skirmishes.ForEach(sk =>
  388. {
  389. sk.Render();
  390. });
  391. System.Console.WriteLine(" ");
  392. System.Console.WriteLine(" ----------------------------------------------- End Round");
  393. }
  394. public override void RenderBattleSkirmish(ISkirmish skirmish)
  395. {
  396. System.Console.WriteLine("Combat Type : {0}".F(skirmish.Type.ToString()));
  397. System.Console.WriteLine(" ");
  398. if (skirmish.Type == SkirmishType.FULL)
  399. {
  400. // Full skirmish
  401. skirmish.Attacker.Render();
  402. System.Console.Write(" is attacking ");
  403. skirmish.Defender.Render();
  404. }
  405. else
  406. {
  407. // Special defence skirmish
  408. skirmish.Defender.Render();
  409. System.Console.Write(" is defending against ");
  410. skirmish.Attacker.Render();
  411. }
  412. System.Console.WriteLine(".............. {0}".F(skirmish.GetSkirmishResults().Message));
  413. System.Console.WriteLine(" ");
  414. }
  415. public override void RenderBattleOutcome(IBattle battle)
  416. {
  417. System.Console.WriteLine(" ");
  418. System.Console.WriteLine("Battle outcome is {0}.".F(_theGame.CurrentBattle.VictoryCondition.ToString()));
  419. System.Console.WriteLine(" ");
  420. System.Console.WriteLine(" ");
  421. System.Console.WriteLine("Hit Enter key to continue...");
  422. System.Console.ReadLine();
  423. }
  424. public override void RenderBattleRetreat(IBattle battle)
  425. {
  426. var round = battle.CurrentRound;
  427. round.Render();
  428. // Handle retreat
  429. // No retreat for forced engagements
  430. if (battle.VictoryCondition == BattleVictoryCondition.NO_VICTOR && battle.BattleType != BattleType.FORCED_ENGAGEMENT)
  431. {
  432. System.Console.WriteLine(" ");
  433. System.Console.WriteLine(" ");
  434. System.Console.Write("Retreat? ");
  435. if (CommandLineUtil.ConsoleUtils.GetYesNoInputAsBool())
  436. {
  437. battle.VictoryCondition = BattleVictoryCondition.RETREAT;
  438. }
  439. System.Console.WriteLine(" ");
  440. }
  441. }
  442. // Reinforcements
  443. #region Event Handlers
  444. public override void On_BoardPostRender(EventArgs e)
  445. {
  446. //_theGameGameBoard.ClearSelectedItems();
  447. }
  448. public override void On_BoardPreRender(EventArgs e)
  449. {}
  450. #endregion
  451. #region DrawUtilities
  452. // Title
  453. private void ListScenarios()
  454. {
  455. var scenarios = _theGame.JTSServices.GenericComponentService.GetAll<IScenario, IScenarioDTO>();
  456. System.Console.Write("\n\t");
  457. DrawLine();
  458. System.Console.ForegroundColor = ConsoleColor.Cyan;
  459. System.Console.WriteLine("\n\n\tAvailable Scenarios : \n");
  460. System.Console.ResetColor();
  461. scenarios.ForEach(s =>
  462. {
  463. System.Console.Write("\t\t* {0}", s.Name);
  464. System.Console.Write("\n");
  465. });
  466. System.Console.Write("\n");
  467. }
  468. private void ListSavedGames()
  469. {
  470. System.Console.Write("\n");
  471. // Display the currently loaded game
  472. if (_theGame.SavedGame != null)
  473. {
  474. System.Console.ForegroundColor = ConsoleColor.Cyan;
  475. System.Console.Write("\tCurrent Game : ");
  476. System.Console.ResetColor();
  477. System.Console.Write(_theGame.SavedGame.Name);
  478. }
  479. else
  480. {
  481. System.Console.ForegroundColor = ConsoleColor.Cyan;
  482. System.Console.Write("\tNo game loaded. Select a game from below.");
  483. System.Console.ResetColor();
  484. }
  485. var savedGames = _theGame.JTSServices.GenericComponentService.GetAll<ISavedGame, ISavedGameDTO>();
  486. System.Console.Write("\n\t");
  487. DrawLine();
  488. System.Console.ForegroundColor = ConsoleColor.Cyan;
  489. System.Console.WriteLine("\n\n\tSaved Games : \n");
  490. System.Console.ResetColor();
  491. savedGames.ForEach(sg =>
  492. {
  493. System.Console.Write("\t\t* {0}", sg.Name);
  494. System.Console.Write("\n");
  495. });
  496. System.Console.Write("\n");
  497. }
  498. // Reinforcements
  499. private void CreateUnitInfoRows()
  500. {
  501. // Get unit types
  502. var unitTypes = _theGame.JTSServices.GenericComponentService.GetAll<IUnitType, IUnitTypeDTO>();
  503. System.Console.Write("\n");
  504. unitTypes.ForEach(ut =>
  505. {
  506. System.Console.ForegroundColor = ConsoleColor.Cyan;
  507. System.Console.Write("\t{0}", ut.Name);
  508. System.Console.ResetColor();
  509. System.Console.WriteLine(" ({0})", ut.Description);
  510. CreateAvailableUnitClassRow(ut);
  511. System.Console.Write("\n");
  512. });
  513. }
  514. private void CreateAvailableUnitClassRow(IUnitType ut)
  515. {
  516. // Get available unit classes
  517. var ids = _theGame.JTSServices.DataService.LookupAllowableUnitClassesByUnitBaseType(ut.BaseType.ID);
  518. var unitClasses = _theGame.JTSServices.UnitService.GetUnitClassesByIDs(ids).Result;
  519. System.Console.Write("\t");
  520. foreach (var uc in unitClasses)
  521. {
  522. System.Console.ForegroundColor = ConsoleColor.DarkGray;
  523. var totalCost = _theGame.JTSServices.RulesService.CalculateTotalRPByUnitTypeUnitClass(ut, uc);
  524. System.Console.Write("{0}: {1}rp ".F(uc.Name, totalCost));
  525. System.Console.ForegroundColor = ConsoleColor.DarkYellow;
  526. System.Console.Write("| ");
  527. System.Console.ResetColor();
  528. }
  529. System.Console.Write("\n");
  530. System.Console.ResetColor();
  531. }
  532. // Board/Main
  533. private void CreateTitleRow(string screen)
  534. {
  535. System.Console.Write("\n");
  536. System.Console.ForegroundColor = ConsoleColor.DarkYellow;
  537. System.Console.Write("[[ JTacticalSim : {0} - {1} ]] {2} - {3}",
  538. _theGame.SavedGame.Name,
  539. _theGame.SavedGame.Scenario.Name,
  540. _theGame.GameBoard.DefaultAttributes.Title,
  541. screen);
  542. System.Console.ResetColor();
  543. System.Console.Write("\n");
  544. }
  545. private void CreateColumnHeaders(bool blank)
  546. {
  547. System.Console.BackgroundColor = BoardBoundaryBGColor;
  548. System.Console.ForegroundColor = BoardBoundaryFGColor;
  549. // Draw to first header
  550. MoveCursor(WESTMARGINOFFSET);
  551. for (int i = 0; i < _theGame.GameBoard.DefaultAttributes.Width ; i++)
  552. {
  553. string headerText = (blank) ? " " : "C-{0}".F(i);
  554. System.Console.Write(headerText);
  555. MoveCursor(COLUMNSPACING - COLUMNHEADEROFFSET);
  556. }
  557. //extend over east header column
  558. MoveCursor(COLUMNHEADEROFFSET);
  559. System.Console.ResetColor();
  560. }
  561. private void CreateRowHeader(INode node)
  562. {
  563. System.Console.BackgroundColor = BoardBoundaryBGColor;
  564. System.Console.ForegroundColor = BoardBoundaryFGColor;
  565. System.Console.Write("R-{0}", node.Location.Y.ToString());
  566. System.Console.ResetColor();
  567. }
  568. private void CreateHeaderRow(int vertBoundFiller = 2, bool blank = false)
  569. {
  570. System.Console.Write("\n");
  571. CreateColumnHeaders(blank);
  572. CreateVertBoundFiller(vertBoundFiller);
  573. }
  574. private void CreateFooterRow(bool blank = false)
  575. {
  576. System.Console.Write("\n");
  577. CreateColumnHeaders(blank);
  578. }
  579. private void CreatePlayerSummaryRow()
  580. {
  581. System.Console.Write("\n");
  582. System.Console.BackgroundColor = BoardBoundaryBGColor;
  583. System.Console.ForegroundColor = BoardBoundaryFGColor;
  584. // Draw to first header
  585. System.Console.Write(" ");
  586. System.Console.ResetColor();
  587. System.Console.Write(" ");
  588. System.Console.Write("Player: {0}\t\tCountry: {1} ".F(_theGame.CurrentTurn.Player.Name, _theGame.CurrentTurn.Player.Country.Name));
  589. DrawFlag(_theGame.CurrentTurn.Player.Country.Faction);
  590. System.Console.Write("\t\tReinforcement Points: {0}".F(_theGame.CurrentTurn.Player.ReinforcementPoints.ToString()));
  591. System.Console.ResetColor();
  592. }
  593. private void CreateRows()
  594. {
  595. var rowDict = new ConcurrentDictionary<int, List<INode>>();
  596. var allNodes = _theGame.JTSServices.NodeService.GetAllNodes();
  597. foreach (INode n in allNodes)
  598. {
  599. if (!rowDict.ContainsKey(n.Location.Y))
  600. rowDict.GetOrAdd(n.Location.Y, new List<INode>{n});
  601. else
  602. rowDict[n.Location.Y].Add(n);
  603. }
  604. foreach(var kvp in rowDict)
  605. {
  606. // We need to sort the row first to make sure it's in column order
  607. var sortedRow = kvp.Value.OrderBy(n => n.Location.X).ToList();
  608. CreateRow(sortedRow, kvp.Key);
  609. }
  610. }
  611. private void CreateRow(List<INode> nodes, int row)
  612. {
  613. // Holds the total stacks in the entire row
  614. // We only render the top unit for each stack
  615. var componentStacksInRow = new List<IUnitStack>();
  616. // Add in the stack info row for each stack
  617. int rowCount = (GetMaximumRowStackCount(nodes));
  618. // Make sure the stack orders are correct
  619. nodes.ForEach(n =>
  620. {
  621. var tile = n.DefaultTile();
  622. n.DefaultTile().ResetComponentStackDisplayOrder();
  623. componentStacksInRow.AddRange(tile.GetAllComponentStacks().Where(cs => (cs.DisplayOrder != 0 && cs.GetAllUnits().Any())));
  624. });
  625. // take care of displaying the concepts of hybrid demographics for the console renderer - kinda weird
  626. RenderTopTileBaseGeog(nodes);
  627. RenderBottomTileBaseGeog(nodes);
  628. nodes.ForEach(n =>
  629. {
  630. n.Render();
  631. });
  632. // Empty space before units
  633. CreateVertBoundFiller(1);
  634. //Render TileBaseDemographics by top and bottom rows
  635. //Render Unit Stacks with headers, unit row by unit row
  636. for (int i = 1; i < rowCount + 1; i++)
  637. {
  638. var stacks = componentStacksInRow.Where(cs => cs.DisplayOrder == i).ToList();
  639. CreateStackHeaderRow(stacks);
  640. CreateUnitRow(stacks);
  641. }
  642. //Keep the rows uniform size
  643. CreateVertBoundFiller(ROWSPACING - (rowCount + 2));
  644. }
  645. private void CreateStackHeaderRow(IEnumerable<IUnitStack> unitStacks)
  646. {
  647. int lastStackColPosition = 0;
  648. int lastStackDisplayLength = 0;
  649. int i = 0;
  650. CreateWestVertBoundFiller();
  651. foreach (var us in unitStacks)
  652. {
  653. if (!us.HasVisibleComponents) continue;
  654. //Secret sauce
  655. var leftModifier = (i == 0) ? 1 : 0;
  656. var leftColOffset = (i == 0) ? (COLUMNSPACING - WESTMARGIN) : 0;
  657. //Determine spaces to move cursor
  658. MoveCursor((((us.Location.X + leftModifier) - lastStackColPosition) * COLUMNSPACING) - (lastStackDisplayLength + leftColOffset));
  659. lastStackDisplayLength = us.Render();
  660. lastStackColPosition = us.Location.X;
  661. i++;
  662. }
  663. // 2 * i allows for the moving of the unit names to line up after the flag
  664. MoveCursor(((_theGame.GameBoard.DefaultAttributes.Width - lastStackColPosition) * COLUMNSPACING) - lastStackDisplayLength);
  665. CreateEastVertBoundFiller();
  666. }
  667. private void CreateUnitRow(IEnumerable<IUnitStack> unitStacks)
  668. {
  669. int lastUnitColPosition = 0;
  670. int lastUnitDisplayLength = 0;
  671. int i = 0;
  672. CreateWestVertBoundFiller();
  673. foreach (var us in unitStacks)
  674. {
  675. // No visible units
  676. if (!us.HasVisibleComponents) continue;
  677. // The unit to render
  678. var unit = us.GetFirstVisibleUnit();
  679. //Secret sauce
  680. var leftModifier = (i == 0) ? 1 : 0;
  681. var leftColOffset = (i == 0) ? (COLUMNSPACING - WESTMARGIN) : 0;
  682. //Determine spaces to move cursor
  683. MoveCursor((((us.Location.X + leftModifier) - lastUnitColPosition) * COLUMNSPACING) - (lastUnitDisplayLength + leftColOffset));
  684. unit.Render();
  685. lastUnitColPosition = unit.Location.X;
  686. lastUnitDisplayLength = unit.TotalDisplayLength + 2; //Account for the dash and the space;
  687. i++;
  688. }
  689. // 2 * i allows for the moving of the unit names to line up after the flag
  690. MoveCursor(((_theGame.GameBoard.DefaultAttributes.Width - lastUnitColPosition) * COLUMNSPACING) - lastUnitDisplayLength);
  691. CreateEastVertBoundFiller();
  692. }
  693. private void CreateVertBoundFiller(int rowCount)
  694. {
  695. for (int i = 0; i < rowCount ; i++)
  696. {
  697. CreateWestVertBoundFiller();
  698. MoveCursor((_theGame.GameBoard.DefaultAttributes.Width * COLUMNSPACING) + WESTMARGIN);
  699. CreateEastVertBoundFiller();
  700. }
  701. }
  702. private void CreateWestVertBoundFiller()
  703. {
  704. System.Console.BackgroundColor = BoardBoundaryBGColor;
  705. System.Console.Write("\n ");
  706. System.Console.ResetColor();
  707. }
  708. private void CreateEastVertBoundFiller()
  709. {
  710. System.Console.BackgroundColor = BoardBoundaryBGColor;
  711. System.Console.Write(" ");
  712. System.Console.ResetColor();
  713. }
  714. private void DrawFlag(IFaction faction)
  715. {
  716. // Put a faction colored space before the tile draws (Flag)
  717. System.Console.BackgroundColor = (faction.ID == 0) ? WestFactionColor : EastFactionColor;
  718. System.Console.Write(" ");
  719. System.Console.ResetColor();
  720. System.Console.Write(" ");
  721. }
  722. private void DrawVictoryPoints(string victoryPoints)
  723. {
  724. System.Console.BackgroundColor = ConsoleColor.Black;
  725. System.Console.ForegroundColor = ConsoleColor.Red;
  726. System.Console.Write(victoryPoints);
  727. System.Console.ResetColor();
  728. System.Console.Write(" ");
  729. }
  730. /// <summary>
  731. /// Used to offset the return value for the row-end
  732. /// </summary>
  733. /// <param name="nodes"></param>
  734. /// <returns></returns>
  735. private int GetMaximumRowStackCount(IEnumerable<INode> nodes)
  736. {
  737. return nodes.Aggregate(0, (current, n) => (n.DefaultTile().VisibleStackCount() > current) ? n.DefaultTile().VisibleStackCount() : current);
  738. }
  739. private void MoveCursor(int spaces)
  740. {
  741. for (var i = 0; i < spaces; i++)
  742. {
  743. System.Console.Write(" ");
  744. }
  745. }
  746. private void DrawDemographics(string demographicDisplay, ConsoleColor itemColor, ConsoleColor tileColor)
  747. {
  748. System.Console.ForegroundColor = itemColor;
  749. System.Console.BackgroundColor = tileColor;
  750. System.Console.Write("{0}", demographicDisplay);
  751. System.Console.ResetColor();
  752. }
  753. private void DrawTileBaseGeog(ITile tile, bool IsBottomRow)
  754. {
  755. INode node = _theGame.JTSServices.NodeService.GetNodeAt(tile.Location);
  756. var IsCurrentNode = (_theGame.GameBoard.SelectedNode == null) ? false : (_theGame.GameBoard.SelectedNode.Equals(node));
  757. var IsMovementAvailableNode = _theGame.GameBoard.AvailableMovementNodes.Any(n => n.Equals(node));
  758. // If this is the first node in the row, the offset is the size of the column (row header) otherwise the tile
  759. int offset = (node.IsWestOuterBoundary) ? WESTMARGIN : (COLUMNSPACING - TILEOFFSET);
  760. // Advance to next column
  761. MoveCursor(offset);
  762. if (IsBottomRow)
  763. {
  764. DrawVictoryPoints((tile.VictoryPoints > 0) ? tile.VictoryPoints.ToString() : " ");
  765. }
  766. else
  767. {
  768. DrawFlag(node.Faction);
  769. }
  770. if (tile.ConsoleRenderHelper.hasShoreLineNorth)
  771. {
  772. var geogBGColor = (IsBottomRow) ? WaterBGColor : LandBGColor;
  773. System.Console.BackgroundColor = (IsCurrentNode) ? NodeSelectedColor : geogBGColor;
  774. if (IsMovementAvailableNode) System.Console.BackgroundColor = NodeAvailableForMoveColor;
  775. MoveCursor(BASEGEOGWIDTH);
  776. System.Console.ResetColor();
  777. return;
  778. }
  779. if (tile.ConsoleRenderHelper.hasShoreLineSouth)
  780. {
  781. var geogBGColor = (IsBottomRow) ? WaterBGColor : LandBGColor;
  782. System.Console.BackgroundColor = (IsCurrentNode) ? NodeSelectedColor : geogBGColor;
  783. if (IsMovementAvailableNode) System.Console.BackgroundColor = NodeAvailableForMoveColor;
  784. MoveCursor(BASEGEOGWIDTH);
  785. System.Console.ResetColor();
  786. return;
  787. }
  788. if (tile.ConsoleRenderHelper.hasShoreLineWest)
  789. {
  790. var geogBGColor = LandBGColor;
  791. System.Console.BackgroundColor = (IsCurrentNode) ? NodeSelectedColor : geogBGColor;
  792. if (IsMovementAvailableNode) System.Console.BackgroundColor = NodeAvailableForMoveColor;
  793. MoveCursor(BASEGEOGWIDTH / 2);
  794. geogBGColor = LandBGColor;
  795. System.Console.BackgroundColor = (IsCurrentNode) ? NodeSelectedColor : geogBGColor;
  796. if (IsMovementAvailableNode) System.Console.BackgroundColor = NodeAvailableForMoveColor;
  797. MoveCursor(BASEGEOGWIDTH / 2);
  798. System.Console.ResetColor();
  799. return;
  800. }
  801. if (tile.ConsoleRenderHelper.hasShoreLineEast)
  802. {
  803. var geogBGColor = WaterBGColor;
  804. System.Console.BackgroundColor = (IsCurrentNode) ? NodeSelectedColor : geogBGColor;
  805. if (IsMovementAvailableNode) System.Console.BackgroundColor = NodeAvailableForMoveColor;
  806. MoveCursor(BASEGEOGWIDTH / 2);
  807. geogBGColor = LandBGColor;
  808. System.Console.BackgroundColor = (IsCurrentNode) ? NodeSelectedColor : geogBGColor;
  809. if (IsMovementAvailableNode) System.Console.BackgroundColor = NodeAvailableForMoveColor;
  810. MoveCursor(BASEGEOGWIDTH / 2);
  811. System.Console.ResetColor();
  812. return;
  813. }
  814. if (tile.ConsoleRenderHelper.IsRiver)
  815. {
  816. var geogBGColor = WaterBGColor;
  817. System.Console.BackgroundColor = (IsCurrentNode) ? NodeSelectedColor : geogBGColor;
  818. if (IsMovementAvailableNode) System.Console.BackgroundColor = NodeAvailableForMoveColor;
  819. MoveCursor(BASEGEOGWIDTH);
  820. System.Console.ResetColor();
  821. return;
  822. }
  823. if (!tile.ConsoleRenderHelper.IsRiver)
  824. {
  825. var geogBGColor = LandBGColor;
  826. System.Console.BackgroundColor = (IsCurrentNode) ? NodeSelectedColor : geogBGColor;
  827. if (IsMovementAvailableNode) System.Console.BackgroundColor = NodeAvailableForMoveColor;
  828. MoveCursor(BASEGEOGWIDTH);
  829. System.Console.ResetColor();
  830. return;
  831. }
  832. }
  833. private void DrawLine()
  834. {
  835. System.Console.Write("________________________________________________________");
  836. }
  837. #endregion
  838. }
  839. }