123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- 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 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 FirstNight()
- {
-
- await Task.Run(() => { });
- }
- 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);
- IsRunning = false;
- _turnOrder.Clear();
- Thread.Sleep(10000);//TODO just for tests
- 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;
- }
- });
- }
- 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);
- }
- }
- }
- }
|