/// <summary> /// Start tournament /// </summary> public void Start(IRandomGen random) { if (this.State != TournamentState.Open) { throw new DomainException(ErrorCode.TournamentStart, "Cannot start tournament"); } if (!this.CanStart) { throw new DomainException(ErrorCode.TournamentStart, "Cannot start tournament"); } if (this.HasGroupPhase) { this.State = TournamentState.Groups; this.CreateGroupPairings(random); } else { this.State = TournamentState.Knockout; this.CreateNextRoundPairings(this.Teams); } this.StartOfTournament = DateTime.UtcNow; }
private void DeterminePlayOrder(IRandomGen random) { // Desired outcome: // t1: p1 - 0 // t2: p1 - 1 // t1: p2 - 2 // t2: p2 - 3 var shuffledTeams = this.Teams.Shuffle(random).ToArray(); int teamIdx = 0; foreach (var shuffledTeam in shuffledTeams) { shuffledTeam.PlayOrder = teamIdx; int playerIdx = 0; foreach (var player in shuffledTeam.Players) { player.PlayOrder = teamIdx + playerIdx * this.Options.NumberOfTeams; ++playerIdx; } ++teamIdx; } }
public void StartNextRound(IRandomGen random, ILogger log) { ++this.Phase; if (this.State == TournamentState.Groups) { log.Log(LogLevel.Info, "Switch from Group to KO phase for tournament {0}", this.Name); this.State = TournamentState.Knockout; // Update losers var losingTeams = this.Groups.SelectMany(g => g.Losers); foreach (var losingTeam in losingTeams) { log.Log(LogLevel.Info, "Team {0} has lost", losingTeam.Name); losingTeam.State = TournamentTeamState.InActive; } // Create pairings for KO phase var koTeams = this.Groups.SelectMany(g => g.Winners).Shuffle(random); log.Log(LogLevel.Info, "Teams for KO phase: {0}", string.Join(", ", koTeams.Select(t => t.Name))); this.CreateNextRoundPairings(koTeams); } else { this.CreateNextRoundPairings(this.Pairings .Where(p => p.Phase == this.Phase - 1) .OrderBy(p => p.Order) .Select(p => p.Winner)); } }
/// <summary> /// Start the game /// </summary> public void Start(MapTemplate mapTemplate, IRandomGen random) { if (!this.CanStart) { throw new DomainException(ErrorCode.CannotStartGame, "Cannot start"); } this.StartedAt = DateTime.UtcNow; this.State = GameState.Active; TraceContext.Trace("Create Map from Template", () => Map.CreateFromTemplate(this, mapTemplate)); TraceContext.Trace("Distribute countries to teams", () => this.Map.Distribute(this.Teams, mapTemplate, this.Options.MapDistribution, random)); // Determine player order this.DeterminePlayOrder(random); // Set current player var currentTeam = this.Teams.RandomElement(random); var currentPlayer = currentTeam.Players.First(); this.CurrentPlayerId = currentPlayer.Id; // Record in history this.GameHistory.RecordStart(); this.TurnCounter = 1; this.ResetTurn(); this.EventQueue.Raise(new GameStartedEvent(this)); }
/** * <summary> * Constructor for LayeredExpansion which allows customization of the * upper and lower bounds for hex proportioning. * </summary> * <param name="hexExpander">HexExpander that will carry out expansion.</param> * <param name="validCoords">Coords that may be expanded in.</param> * <param name="lowerProportionBound">Lower bound of hex proportioning.</param> * <param name="upperProportionBound">Upper bound of hex proportioning.</param> */ public LayeredExpansion(IRandomGen rand, LayeredExpander layeredExpander, List <Coords> validCoords, double lowerProportionBound, double upperProportionBound) : this(rand, layeredExpander, validCoords) { LowerProportionBound = lowerProportionBound; UpperProportionBound = upperProportionBound; }
private BiomeList(IRandomGen rand) { _rand = rand; Biomes = new List <Biome>(); _defsStream = new FileStream("biome_defs.xml", FileMode.Open, FileAccess.Read, FileShare.Read); BiomeSetup(); }
public BiomeList(IRandomGen rand, Stream stream) { _rand = rand; Biomes = new List <Biome>(); _defsStream = stream; BiomeSetup(); }
private void CreateGamesForPairing(TournamentPairing pairing, IRandomGen random) { Debug.Assert(pairing.State == PairingState.None, "Pairing state is not correct"); var systemUser = this.unitOfWork.Users.FindByName("System"); for (int i = 0; i < pairing.NumberOfGames; ++i) { var game = gameService.Create( Enums.GameType.Tournament, systemUser, pairing.GenerateGameName(i), pairing.Tournament.GetMapTemplateForGame(random), pairing.Tournament.Options); game.TournamentPairingId = pairing.Id; pairing.Games.Add(game); var teamA = game.AddTeam(); foreach (var participant in pairing.TeamA.Participants) { teamA.AddPlayer(participant.User); } var teamB = game.AddTeam(); foreach (var participant in pairing.TeamB.Participants) { teamB.AddPlayer(participant.User); } game.Start(this.mapTemplateProvider.GetTemplate(game.MapTemplateName), random); } pairing.State = PairingState.Active; }
/** * <summary> * WorldGenerator constructor requires a HexMap, which will hold the * world that is about to be generated. * * Does some basic setup, like determining how many landmasses will * exist in the world and how many Hexes they should contain, but does * not perform any actual generation. * </summary> * <param name="map">HexMap to generate a world in.</param> */ public WorldGenerator(World world, IRandomGen rand) { _rand = rand; _world = world; int worldTotal = (_world.Map.Width * _world.Map.Height); double overallTotalDec = (double)worldTotal; int totalLandHexes = (int)(overallTotalDec * WORLD_RATIO); int remainingHexes = totalLandHexes; var landmasses = new List <Landmass>(); int numLandmasses = _rand.GenerateInt(1, MAX_LANDMASSES); for (int i = 0; i < numLandmasses; i++) { Landmass landmass = new Landmass(rand); int massHexes; if (i != numLandmasses - 1) { massHexes = _rand.GenerateInt(1, remainingHexes / 2); } else { massHexes = remainingHexes; } remainingHexes -= massHexes; landmass.TotalHexes = landmass.RemainingHexes = massHexes; landmasses.Add(landmass); } _world.Map.Landmasses = landmasses; }
public void CreateGamesForPairings(ILogger log, Tournament tournament, IRandomGen random) { foreach (var pairing in tournament.Pairings.Where( x => x.State == PairingState.None && x.Games.Count() != x.NumberOfGames)) { this.CreateGamesForPairing(pairing, random); } }
public static T RandomElement <T>(this IEnumerable <T> source, IRandomGen random) { var count = source.Count(); var idx = random.GetNext(0, count - 1); return(source.Skip(idx).Take(1).FirstOrDefault()); }
public RiverGen(IRandomGen rand, World world, Landmass landmass, int length) { _rand = rand; _world = world; _landmass = landmass; _allCoords = new HashSet <Coords>(); _requestedLength = length; }
private void CreateGamesForPairing(ILogger log, TournamentPairing pairing, IRandomGen random) { Debug.Assert(pairing.State == PairingState.None, "Pairing state is not correct"); var systemUser = this.unitOfWork.Users.FindByName("System"); for (int i = 0; i < pairing.NumberOfGames; ++i) { log.Log(LogLevel.Info, "Creating game {0}", i); string gameName = pairing.GenerateGameName(i); Game game; try { game = gameService.Create( Enums.GameType.Tournament, systemUser, gameName, null, pairing.Tournament.GetMapTemplateForGame(random), pairing.Tournament.Options); } catch (DomainException exception) when(exception.ErrorCode == ErrorCode.NameAlreadyTaken) { // Try again game = gameService.Create( Enums.GameType.Tournament, systemUser, gameName + Guid.NewGuid().ToString(), null, pairing.Tournament.GetMapTemplateForGame(random), pairing.Tournament.Options); } game.TournamentPairingId = pairing.Id; pairing.Games.Add(game); var teamA = game.AddTeam(); foreach (var participant in pairing.TeamA.Participants) { teamA.AddPlayer(participant.User); } var teamB = game.AddTeam(); foreach (var participant in pairing.TeamB.Participants) { teamB.AddPlayer(participant.User); } game.Start(this.mapTemplateProvider.GetTemplate(game.MapTemplateName), random); log.Log(LogLevel.Info, "Done."); } pairing.State = PairingState.Active; }
public PlayService(IUnitOfWork unitOfWork, IUserProvider userProvider, IVisibilityModifierFactory visibilityModifierFactory, IAttackService attackService, IMapTemplateProvider mapTemplateProvider, IRandomGen randomGen) : base(unitOfWork, userProvider, mapTemplateProvider, visibilityModifierFactory) { this.attackService = attackService; this.randomGen = randomGen; }
public string GetMapTemplateForGame(IRandomGen random) { if (!this.MapTemplates.Any()) { throw new DomainException(ErrorCode.LadderNoMapTemplates, "No map templates set for ladder"); } return(this.MapTemplates.Shuffle(random).First()); }
public Bot( Game game, MapTemplate mapTemplate, IAttackService attackService, IRandomGen randomGen) { this.game = game; this.mapTemplate = mapTemplate; this.attackService = attackService; this.randomGen = randomGen; }
public void CreateGamesForPairings(ILogger log, Tournament tournament, IRandomGen random) { log.Log(LogLevel.Info, "Creating games for {0}", tournament.Id); foreach (var pairing in tournament.Pairings.Where( x => x.State == PairingState.None && x.Games.Count() != x.NumberOfGames)) { log.Log(LogLevel.Info, "Creating games for pairing {0}", pairing.Id); this.CreateGamesForPairing(log, pairing, random); } }
// ------------ Methods ------------ /** * <summary> * Constructor for HexMap requires width (number of tiles in each row) * and height (number of tiles in each column). * </summary> * <param name="rand">The random number generator to be used by this object.</param> * <param name="width">Number of Hex objects in each row of the map.</param> * <param name="height">Number of Hex objects in each column of the map.</param> */ public HexMap(IRandomGen rand, int width, int height) { _rand = rand; _map = new Hex[width, height]; for (int i = 0; i < _map.GetLength(0); i++) { for (int j = 0; j < _map.GetLength(1); j++) { _map[i, j] = new Hex(); } } }
public Bot( ILogger log, Game game, MapTemplate mapTemplate, IAttackService attackService, IRandomGen randomGen) { this.log = log; this.game = game; this.mapTemplate = mapTemplate; this.attackService = attackService; this.randomGen = randomGen; }
public static IEnumerable <T> Shuffle <T>(this IEnumerable <T> source, IRandomGen rng) { if (source == null) { throw new ArgumentNullException("source"); } if (rng == null) { throw new ArgumentNullException("rng"); } return(source.ShuffleIterator(rng)); }
private static IEnumerable <T> ShuffleIterator <T>( this IEnumerable <T> source, IRandomGen rng) { var buffer = source.ToList(); for (int i = 0; i < buffer.Count; i++) { int j = rng.GetNext(i, buffer.Count - 1); yield return(buffer[j]); buffer[j] = buffer[i]; } }
private void DistributeCard(IRandomGen randomGen) { if (!this.CardDistributed) { this.CardDistributed = true; if (this.CurrentPlayer.Cards.Count() < this.Options.MaximumNumberOfCards) { var existingCards = new List <BonusCard>(this.CurrentPlayer.Cards); var cardToDistribute = randomGen.GetNext(0, 2); existingCards.Add((BonusCard)cardToDistribute); this.CurrentPlayer.Cards = existingCards.ToArray(); } } }
/// <summary> /// Checks if enough players for a match have queued up, then create games /// </summary> public void CheckAndCreateMatches(IRandomGen random) { Log.Info().Message("Entering CheckAndCreateMatches").Write(); lock (this.createGamesLock) { var ladders = this.unitOfWork.Ladders.GetActive().ToList(); foreach (var ladder in ladders) { Log.Debug().Message("Checking ladder {0} {1}", ladder.Id, ladder.Name).Write(); var numberOfRequiredPlayers = ladder.Options.NumberOfTeams * ladder.Options.NumberOfPlayersPerTeam; while (ladder.Queue.Count() >= numberOfRequiredPlayers) { Log.Debug().Message("Found enough players").Write(); var game = this.CreateGame(ladder, random); this.unitOfWork.Games.Add(game); ladder.Games.Add(game); // Add required players from queue to game var queueEntries = ladder.Queue.Take(numberOfRequiredPlayers).ToArray(); foreach (var queueEntry in queueEntries.Shuffle(random)) { Debug.Assert(queueEntry.User != null, "User not available for queue entry"); // Add user to game game.AddPlayer(queueEntry.User); // Remove user from queue ladder.Queue.Remove(queueEntry); this.unitOfWork.GetGenericRepository <LadderQueueEntry>().Remove(queueEntry); } game.Start(this.mapTemplateProvider.GetTemplate(game.MapTemplateName), random); this.eventAggregator.Raise(new LadderGameStartedEvent(ladder, game)); this.unitOfWork.Commit(); Log.Debug().Message("Created game {0}", game.Id).Write(); } } } }
/// <summary> /// Create a game for the given ladder /// </summary> protected virtual Games.Game CreateGame(Ladder ladder, IRandomGen random) { var systemUser = this.unitOfWork.Users.FindByName("System"); var mapTemplate = ladder.GetMapTemplateForGame(random); var game = gameService.Create( Enums.GameType.Ranking, systemUser, ladder.GetGameName(), mapTemplate, ladder.Options); game.Ladder = ladder; game.LadderId = ladder.Id; return(game); }
/// <summary> /// Check all tournaments to see whether rounds need to advanced, or the tournament ended /// </summary> public void CheckTournaments(ILogger log, IRandomGen random) { var tournaments = this.unitOfWork.Tournaments.Get(Tournament.ActiveStates); foreach (var tournament in tournaments) { try { log.Log(LogLevel.Info, "Synchronizing games for tournament {0}", tournament.Id); this.SynchronizeGamesToPairings(log, tournament); if (tournament.HasGroupPhase && tournament.State == TournamentState.Groups) { log.Log(LogLevel.Info, "Update group order for tournament {0}", tournament.Id); this.OrderGroupTeams(tournament); } // Advance rounds if (tournament.CanStartNextRound) { log.Log(LogLevel.Info, "Starting next round for tournament {0}", tournament.Id); tournament.StartNextRound(random, log); } else if (tournament.CanEnd) { log.Log(LogLevel.Info, "Ending tournament {0}", tournament.Id); tournament.End(); } this.CreateGamesForPairings(log, tournament, random); } catch (Exception ex) { log.Log(LogLevel.Error, "Error while handling tournament {0}: {1}", tournament.Id, ex); // Rethrow exception, we have to cancel the job throw; } } }
/// <summary> /// Create all pairings and games for all groups /// </summary> private void CreateGroupPairings(IRandomGen random) { // Create groups var shuffledTeams = this.Teams.Shuffle(random); var teamIterator = shuffledTeams.GetEnumerator(); for (int i = 0; i < this.NumberOfTeams / Tournament.GroupSize; ++i) { var group = new TournamentGroup(this, i + 1); for (int j = 0; j < Tournament.GroupSize; ++j) { teamIterator.MoveNext(); group.Teams.Add(teamIterator.Current); } this.Groups.Add(group); } // Create pairings so that each team plays against all others int order = 0; foreach (var group in this.Groups) { for (int i = 0; i < group.Teams.Count(); ++i) { for (int j = i + 1; j < group.Teams.Count(); ++j) { var teamA = group.Teams.ElementAt(i); var teamB = group.Teams.ElementAt(j); var pairing = this.CreatePairing(order++, teamA, teamB, this.NumberOfGroupGames); pairing.Group = group; pairing.GroupId = group.Id; group.Pairings.Add(pairing); } } } }
/// <summary> /// Check all open tournaments whether they can be started /// </summary> /// <returns>True if a tournament was started</returns> public bool CheckOpenTournaments(ILogger log, IRandomGen random) { bool tournamentStarted = false; var tournaments = this.unitOfWork.Tournaments.Get(TournamentState.Open); foreach (var tournament in tournaments) { if (tournament.CanStart) { log.Log(LogLevel.Info, "Starting tournament {0}", tournament.Id); tournament.Start(random); tournamentStarted = true; log.Log(LogLevel.Info, "Started."); } } return(tournamentStarted); }
/** * <summary> * Constructor for LayeredExpander takes the map to alter. * </summary> * <param name="map">The HexMap to update.</param> */ public LayeredExpander(IRandomGen rand, HexMap map) : base(rand, map) { _alreadyModified = new List <Coords>(); }
/// <summary>Initializes a new instance of the RandomGenerator /// class.</summary> /// <param name='valueIrg'>An IRandomGen object.</param> public RandomGenerator(IRandomGen valueIrg) { this.valueIrg = valueIrg; }
/** * <summary> * Constructor for LayeredExpansion takes a HexExpander to carry out the * expansion and a list of coords that are valid. Proportion bounds are * set to 0.0 for the lower and 1.0 for the upper. * </summary> * <param name="hexExpander">HexExpander that will carry out expansion.</param> * <param name="validCoords">Coords that may be expanded in.</param> */ public LayeredExpansion(IRandomGen rand, LayeredExpander layeredExpander, List <Coords> validCoords) { _rand = rand; Expander = layeredExpander; ValidCoords = validCoords; }
public void Attack( IAttackService attackService, IRandomGen randomGen, MapTemplate mapTemplate, string sourceCountryIdentifier, string destCountryIdentifier, int numberOfUnits) { this.RequireGameActive(); if (this.PlayState != PlayState.Attack) { throw new DomainException(ErrorCode.AttackingNotPossible, "Cannot attack, state incorrect"); } var sourceCountry = this.Map.GetCountry(sourceCountryIdentifier); var destCountry = this.Map.GetCountry(destCountryIdentifier); // Check connection if (!mapTemplate.AreConnected(sourceCountryIdentifier, destCountryIdentifier)) { throw new DomainException(ErrorCode.CountriesNotConnected, "There is no connection between those countries"); } // Check ownership if (sourceCountry.TeamId != this.CurrentPlayer.TeamId) { throw new DomainException(ErrorCode.OriginCountryNotOwnedByTeam, "Can only initiate actions from countries that belong to the same team"); } if (sourceCountry.PlayerId == destCountry.PlayerId) { throw new DomainException(ErrorCode.AttackOwnCountries, "Cannot attack own countries"); } if (numberOfUnits <= 0 || sourceCountry.Units - numberOfUnits < this.Options.MinUnitsPerCountry) { throw new DomainException(ErrorCode.NotEnoughUnits, "Cannot attack with that many units"); } var otherPlayer = this.GetPlayerById(destCountry.PlayerId); int attackerUnitsLost = 0; int defenderUnitsLost = 0; var result = attackService.Attack(numberOfUnits, destCountry.Units, out attackerUnitsLost, out defenderUnitsLost); if (result) { // Attack was successful destCountry.Units = numberOfUnits - attackerUnitsLost; this.Map.UpdateOwnership(otherPlayer, this.CurrentPlayer, destCountry); this.DistributeCard(randomGen); } else { // Attack failed destCountry.Units -= defenderUnitsLost; } // Reduce units in this country in any case sourceCountry.Units -= numberOfUnits; this.GameHistory.RecordAttack( this.CurrentPlayer, otherPlayer, sourceCountryIdentifier, destCountryIdentifier, numberOfUnits, attackerUnitsLost, defenderUnitsLost, result); // Reduce number of attacks left this.AttacksInCurrentTurn++; // Check for victory this.CheckForVictory(this.CurrentPlayer, otherPlayer); if (this.AttacksInCurrentTurn >= this.Options.AttacksPerTurn) { this.EndAttack(); } }
public SystemRandomWrapper(IRandomGen randomGen) { Contract.Requires<ArgumentNullException>(randomGen != null); _randomGen = randomGen; }
private void DistributeCard(IRandomGen randomGen) { if (!this.CardDistributed) { this.CardDistributed = true; if (this.CurrentPlayer.Cards.Count() < this.Options.MaximumNumberOfCards) { var existingCards = new List<BonusCard>(this.CurrentPlayer.Cards); var cardToDistribute = randomGen.GetNext(0, 2); existingCards.Add((BonusCard) cardToDistribute); this.CurrentPlayer.Cards = existingCards.ToArray(); } } }
public Landmass(IRandomGen rand) { _rand = rand; }
public AttackerRandomGen(IRandomGen randomGen) { this.randomGen = randomGen; }