|
@@ -1,212 +0,0 @@
|
|
-using System;
|
|
|
|
-using System.Collections.Generic;
|
|
|
|
-using System.Linq;
|
|
|
|
-using System.Threading;
|
|
|
|
-using System.Threading.Tasks;
|
|
|
|
-using MafiaTelegramBot.Controllers;
|
|
|
|
-using MafiaTelegramBot.CustomCollections.Extensions;
|
|
|
|
-using MafiaTelegramBot.Game.GameRoles;
|
|
|
|
-using MafiaTelegramBot.Models;
|
|
|
|
-using MafiaTelegramBot.Resources;
|
|
|
|
-using Telegram.Bot.Types.ReplyMarkups;
|
|
|
|
-
|
|
|
|
-namespace MafiaTelegramBot.Game.GameRooms
|
|
|
|
-{
|
|
|
|
- public abstract class GameRoom
|
|
|
|
- {
|
|
|
|
- protected bool IsRunning;
|
|
|
|
- public int MaxPlayers = 10;
|
|
|
|
- private int _minPlayers = Constants.PLAYER_LIMITS_MIN;
|
|
|
|
- public bool IsPrivate { get; init; }
|
|
|
|
- public abstract bool IsExtended { get; protected set; }
|
|
|
|
- public bool TimerEnabled { get; set; } = true;
|
|
|
|
- public string RoomName { get; init; } = "NoNameRoom";
|
|
|
|
- public Player Owner { get; init; } = new();
|
|
|
|
-
|
|
|
|
- private readonly Queue<Player> _turnOrder = new();
|
|
|
|
-
|
|
|
|
- public readonly Dictionary<long, Player> Players = new();
|
|
|
|
-
|
|
|
|
- public readonly Dictionary<Roles, int> Settings = new()
|
|
|
|
- {
|
|
|
|
- {Roles.Mafia, 0},
|
|
|
|
- {Roles.Cop, 0},
|
|
|
|
- {Roles.Villager, 0},
|
|
|
|
- {Roles.Doctor, 0},
|
|
|
|
- {Roles.Don, 0},
|
|
|
|
- {Roles.Hooker, 0},
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- public void Start()
|
|
|
|
- {
|
|
|
|
- new Task(async () =>
|
|
|
|
- {
|
|
|
|
- IsRunning = true;
|
|
|
|
- await FirstNight();
|
|
|
|
- await FirstDay();
|
|
|
|
- await GameCycle();
|
|
|
|
- await EndOfGame();
|
|
|
|
- }).Start();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public async Task<ResultCode> Prepare()
|
|
|
|
- {
|
|
|
|
- var resultCode = CanStartGame();
|
|
|
|
- if (resultCode != ResultCode.CodeOk) return resultCode;
|
|
|
|
- await ReadSettings();
|
|
|
|
- await GenerateTurnOrder();
|
|
|
|
- await AssignRoles();
|
|
|
|
- return resultCode;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private async Task FirstDay()
|
|
|
|
- {
|
|
|
|
- await NotifyPlayersAbout(-1, strings.first_day_message);
|
|
|
|
- await Task.Run(async() =>
|
|
|
|
- {
|
|
|
|
- var turnsCount = Players.Count;
|
|
|
|
- Player firstPlayer = null;
|
|
|
|
- for (var i = 0; i < turnsCount; ++i)
|
|
|
|
- {
|
|
|
|
- var player = _turnOrder.Dequeue();
|
|
|
|
- await NotifyPlayersAbout(player.Id, $"{strings.now_turn} {player.NickName}");
|
|
|
|
- await Bot.SendWithMarkdown2(player.ChatId, strings.your_turn);
|
|
|
|
- player.IsSpeaker = true;
|
|
|
|
- Thread.Sleep(60*1000);
|
|
|
|
- player.IsSpeaker = false;
|
|
|
|
- await Bot.SendWithMarkdown2(player.ChatId, strings.your_turn_ended);
|
|
|
|
- if (i != 0) _turnOrder.Enqueue(player);
|
|
|
|
- else firstPlayer = player;
|
|
|
|
- }
|
|
|
|
- _turnOrder.Enqueue(firstPlayer);
|
|
|
|
- });
|
|
|
|
- await NotifyPlayersAbout(-1, strings.city_falls_asleep);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private async Task FirstNight()
|
|
|
|
- {
|
|
|
|
- await Task.Run(async() =>
|
|
|
|
- {
|
|
|
|
- await NotifyPlayersAbout(-1, strings.city_falls_asleep);
|
|
|
|
- var mafia = Players.Values.Where(player => player.CurrentRole.RoleKey is Roles.Mafia).ToArray();
|
|
|
|
- var don = Players.Values.FirstOrDefault(player => player.CurrentRole.RoleKey is Roles.Don);
|
|
|
|
- var message = strings.your_teammates;
|
|
|
|
- if (don != null) message += $" \\({don.TurnOrder}\\) {don.NickName} - {roles.Don}";
|
|
|
|
- message = mafia.Aggregate(message, (current, player) => current + $" \\({player.TurnOrder}\\) {player.NickName}");
|
|
|
|
- if (don != null) await Bot.SendWithMarkdown2(don.ChatId, message);
|
|
|
|
- foreach (var player in mafia)
|
|
|
|
- await Bot.SendWithMarkdown2(player.ChatId, message);
|
|
|
|
- Thread.Sleep(10*1000);
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- private async Task GameCycle()
|
|
|
|
- {
|
|
|
|
- await Task.Run(() =>
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- private async Task EndOfGame()
|
|
|
|
- {
|
|
|
|
- await Task.Run(async () =>
|
|
|
|
- {
|
|
|
|
- foreach (var (_, player) in Players)
|
|
|
|
- {
|
|
|
|
- player.CurrentRole = Role.GetNewRoleInstance(Roles.None);
|
|
|
|
- player.IsPlaying = false;
|
|
|
|
- }
|
|
|
|
- IsRunning = false;
|
|
|
|
- _turnOrder.Clear();
|
|
|
|
- if (!Players.ContainsKey(Owner.Id) || Players.Count == 0) new Task(async() =>
|
|
|
|
- await RoomController.DissolveRoom(RoomEncrypter.GetCode(RoomName))).Start();
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- await Bot.SendWithMarkdown2(Owner.ChatId, strings.thanks_for_game, Keyboards.OwnerGameMenu);
|
|
|
|
- await NotifyPlayersAbout(Owner.Id, strings.thanks_for_game, Keyboards.PlayerGameMenu);
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- protected abstract Task ReadSettings();
|
|
|
|
-
|
|
|
|
- private ResultCode CanStartGame()
|
|
|
|
- {
|
|
|
|
- if (Players.Count < _minPlayers) return ResultCode.TooFewPlayers;
|
|
|
|
- if (Players.Count > MaxPlayers) return ResultCode.TooManyPlayers;
|
|
|
|
- return IsRunning ? ResultCode.GameAlreadyRunning : ResultCode.CodeOk;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public async Task<List<Player>> GetPlayers()
|
|
|
|
- {
|
|
|
|
- return await Task.Run(() =>
|
|
|
|
- {
|
|
|
|
- var players = Players.Values.ToList();
|
|
|
|
- players.Remove(Owner);
|
|
|
|
- return players;
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private async Task AssignRoles()
|
|
|
|
- {
|
|
|
|
- await Task.Run(() =>
|
|
|
|
- {
|
|
|
|
- var random = new Random();
|
|
|
|
- var roles = new List<Roles>();
|
|
|
|
- foreach (var (key, value) in Settings) roles.AddTimes(key, value);
|
|
|
|
- for (var i = 0; i < _turnOrder.Count; ++i)
|
|
|
|
- {
|
|
|
|
- var user = _turnOrder.Dequeue();
|
|
|
|
- var value = random.Next(roles.Count);
|
|
|
|
- var next = roles.GetAndRemove(value);
|
|
|
|
- user.CurrentRole = Role.GetNewRoleInstance(next);
|
|
|
|
- _turnOrder.Enqueue(user);
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private async Task GenerateTurnOrder()
|
|
|
|
- {
|
|
|
|
- await Task.Run(() =>
|
|
|
|
- {
|
|
|
|
- var random = new Random();
|
|
|
|
- var playersCopy = Players.Values.ToList();
|
|
|
|
- while (playersCopy.Count != 0)
|
|
|
|
- {
|
|
|
|
- var player = playersCopy.GetAndRemove(random.Next(playersCopy.Count));
|
|
|
|
- _turnOrder.Enqueue(player);
|
|
|
|
- player.TurnOrder = _turnOrder.Count;
|
|
|
|
- player.IsPlaying = true;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public bool IsFilled()
|
|
|
|
- {
|
|
|
|
- return Players.Count == MaxPlayers;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public async Task NotifyPlayersAbout(long ignoredUserId, string message, IReplyMarkup keyboard = null)
|
|
|
|
- {
|
|
|
|
- foreach (var player in Players.Values.Where(player => ignoredUserId != player.Id))
|
|
|
|
- {
|
|
|
|
- await Bot.SendWithMarkdown2(player.ChatId, message, keyboard);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public async Task NotifyPlayersAboutGameStarted()
|
|
|
|
- {
|
|
|
|
- foreach (var player in Players.Values)
|
|
|
|
- {
|
|
|
|
- var message =
|
|
|
|
- $"{strings.your_role}: _*{player.GetRoleName()}*_\n" +
|
|
|
|
- $"{strings.your_turn_order}: _*{player.TurnOrder}*_\n"+
|
|
|
|
- $"{strings.bot_starting_game}";
|
|
|
|
- await Bot.SendWithMarkdown2(player.ChatId, message, Keyboards.InGamePlayerMenu);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|