GameRoom.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using MafiaTelegramBot.Controllers;
  7. using MafiaTelegramBot.CustomCollections.Extensions;
  8. using MafiaTelegramBot.Game.GameRoles;
  9. using MafiaTelegramBot.Models;
  10. using MafiaTelegramBot.Resources;
  11. using Telegram.Bot.Types.ReplyMarkups;
  12. namespace MafiaTelegramBot.Game.GameRooms
  13. {
  14. public abstract class GameRoom
  15. {
  16. protected bool IsRunning;
  17. public int MaxPlayers = 10;
  18. private int _minPlayers = Constants.PLAYER_LIMITS_MIN;
  19. public bool IsPrivate { get; init; }
  20. public abstract bool IsExtended { get; protected set; }
  21. public bool TimerEnabled { get; set; } = true;
  22. public string RoomName { get; init; } = "NoNameRoom";
  23. public Player Owner { get; init; } = new();
  24. private readonly Queue<Player> _turnOrder = new();
  25. public readonly Dictionary<long, Player> Players = new();
  26. public readonly Dictionary<Roles, int> Settings = new()
  27. {
  28. {Roles.Mafia, 0},
  29. {Roles.Cop, 0},
  30. {Roles.Villager, 0},
  31. {Roles.Doctor, 0},
  32. {Roles.Don, 0},
  33. {Roles.Hooker, 0},
  34. };
  35. public void Start()
  36. {
  37. new Task(async () =>
  38. {
  39. IsRunning = true;
  40. await FirstNight();
  41. await GameCycle();
  42. await EndOfGame();
  43. }).Start();
  44. }
  45. public async Task<ResultCode> Prepare()
  46. {
  47. var resultCode = CanStartGame();
  48. if (resultCode != ResultCode.CodeOk) return resultCode;
  49. await ReadSettings();
  50. await GenerateTurnOrder();
  51. await AssignRoles();
  52. return resultCode;
  53. }
  54. private async Task FirstNight()
  55. {
  56. await Task.Run(() => { });
  57. }
  58. private async Task GameCycle()
  59. {
  60. await Task.Run(() => { });
  61. }
  62. private async Task EndOfGame()
  63. {
  64. await Task.Run(async () =>
  65. {
  66. foreach (var (_, player) in Players)
  67. player.CurrentRole = Role.GetNewRoleInstance(Roles.None);
  68. IsRunning = false;
  69. _turnOrder.Clear();
  70. Thread.Sleep(10000);//TODO just for tests
  71. if (!Players.ContainsKey(Owner.Id) || Players.Count == 0) new Task(async() =>
  72. await RoomController.DissolveRoom(RoomEncrypter.GetCode(RoomName))).Start();
  73. else
  74. {
  75. await Bot.SendWithMarkdown2(Owner.ChatId, strings.thanks_for_game, Keyboards.OwnerGameMenu);
  76. await NotifyPlayersAbout(Owner.Id, strings.thanks_for_game, Keyboards.PlayerGameMenu);
  77. }
  78. });
  79. }
  80. protected abstract Task ReadSettings();
  81. private ResultCode CanStartGame()
  82. {
  83. if (Players.Count < _minPlayers) return ResultCode.TooFewPlayers;
  84. if (Players.Count > MaxPlayers) return ResultCode.TooManyPlayers;
  85. return IsRunning ? ResultCode.GameAlreadyRunning : ResultCode.CodeOk;
  86. }
  87. public async Task<List<Player>> GetPlayers()
  88. {
  89. return await Task.Run(() =>
  90. {
  91. var players = Players.Values.ToList();
  92. players.Remove(Owner);
  93. return players;
  94. });
  95. }
  96. private async Task AssignRoles()
  97. {
  98. await Task.Run(() =>
  99. {
  100. var random = new Random();
  101. var roles = new List<Roles>();
  102. foreach (var (key, value) in Settings) roles.AddTimes(key, value);
  103. for (var i = 0; i < _turnOrder.Count; ++i)
  104. {
  105. var user = _turnOrder.Dequeue();
  106. var value = random.Next(roles.Count);
  107. var next = roles.GetAndRemove(value);
  108. user.CurrentRole = Role.GetNewRoleInstance(next);
  109. _turnOrder.Enqueue(user);
  110. }
  111. });
  112. }
  113. private async Task GenerateTurnOrder()
  114. {
  115. await Task.Run(() =>
  116. {
  117. var random = new Random();
  118. var playersCopy = Players.Values.ToList();
  119. while (playersCopy.Count != 0)
  120. {
  121. var player = playersCopy.GetAndRemove(random.Next(playersCopy.Count));
  122. _turnOrder.Enqueue(player);
  123. player.TurnOrder = _turnOrder.Count;
  124. }
  125. });
  126. }
  127. public bool IsFilled()
  128. {
  129. return Players.Count == MaxPlayers;
  130. }
  131. public async Task NotifyPlayersAbout(long ignoredUserId, string message, IReplyMarkup keyboard = null)
  132. {
  133. foreach (var player in Players.Values.Where(player => ignoredUserId != player.Id))
  134. {
  135. await Bot.SendWithMarkdown2(player.ChatId, message, keyboard);
  136. }
  137. }
  138. public async Task NotifyPlayersAboutGameStarted()
  139. {
  140. foreach (var player in Players.Values)
  141. {
  142. var message =
  143. $"{strings.your_role}: _*{player.GetRoleName()}*_\n" +
  144. $"{strings.your_turn_order}: _*{player.TurnOrder}*_\n"+
  145. $"{strings.bot_starting_game}";
  146. await Bot.SendWithMarkdown2(player.ChatId, message, Keyboards.InGamePlayerMenu);
  147. }
  148. }
  149. }
  150. }