public static async Task <bool> ValidateTradeRequestAsync(ICommandContext context, SQLiteDatabase db, GotchiTradeRequest tradeRequest) { // The request is invalid if: // - Either user involved in the trade has gotten a new gotchi since the trade was initiated // - Either gotchi has died since the trade was initiated // - The request has expired if (tradeRequest.IsExpired || tradeRequest.OfferedGotchi is null || tradeRequest.ReceivedGotchi is null) { return(false); } IUser user1 = await context.Guild.GetUserAsync(tradeRequest.OfferedGotchi.OwnerId); Gotchi gotchi1 = user1 is null ? null : await db.GetGotchiAsync(user1.ToCreator()); if (gotchi1 is null || !gotchi1.IsAlive || gotchi1.Id != tradeRequest.OfferedGotchi.Id) { return(false); } IUser user2 = await context.Guild.GetUserAsync(tradeRequest.ReceivedGotchi.OwnerId); Gotchi gotchi2 = user2 is null ? null : await db.GetGotchiAsync(user2.ToCreator()); if (gotchi2 is null || !gotchi1.IsAlive || gotchi2.Id != tradeRequest.ReceivedGotchi.Id) { return(false); } return(true); }
private static async Task _calculateDescriptionBasedBaseStats(Gotchi gotchi, GotchiStats stats) { Species species = await SpeciesUtils.GetSpeciesAsync(gotchi.SpeciesId); int weight = 20; if (Regex.IsMatch(species.Description, "photosynthesi(s|izes)", RegexOptions.IgnoreCase)) { stats.MaxHp += weight; } if (Regex.IsMatch(species.Description, "spikes?|claws?|teeth|jaws|fangs", RegexOptions.IgnoreCase)) { stats.Atk += weight; } if (Regex.IsMatch(species.Description, "shell|carapace|exoskeleton", RegexOptions.IgnoreCase)) { stats.Def += weight; } foreach (Match m in Regex.Matches(species.Description, "flies|fly|quick|fast|agile|nimble", RegexOptions.IgnoreCase)) { stats.Spd += weight; } foreach (Match m in Regex.Matches(species.Description, "slow|heavy", RegexOptions.IgnoreCase)) { stats.Spd -= weight; } }
public static async Task <Gotchi> GetGotchiAsync(IUser user) { GotchiUserInfo userData = await GetUserInfoAsync(user); // Get this user's primary Gotchi. Gotchi gotchi = await GetGotchiAsync(userData.PrimaryGotchiId); // If this user's primary gotchi doesn't exist (either it was never set or no longer exists), pick a primary gotchi from their current gotchis. if (gotchi is null) { Gotchi[] gotchis = await GetGotchisAsync(userData.UserId); if (gotchis.Count() > 0) { gotchi = gotchis[0]; userData.PrimaryGotchiId = gotchi.Id; await UpdateUserInfoAsync(userData); } } return(gotchi); }
public GotchiStats GetGotchiStats(Gotchi gotchi) { if (gotchi.Id == player1.Gotchi.Gotchi.Id) { return(player1.Gotchi.Stats); } else if (gotchi.Id == player2.Gotchi.Gotchi.Id) { return(player2.Gotchi.Stats); } return(null); }
public GotchiMoveSet GetGotchiMoveset(Gotchi gotchi) { if (gotchi.Id == player1.Gotchi.Gotchi.Id) { return(player1.Gotchi.Moves); } else if (gotchi.Id == player2.Gotchi.Gotchi.Id) { return(player2.Gotchi.Moves); } return(null); }
private double _getExpEarned(Gotchi gotchi, Gotchi opponent, bool won) { double exp = 0.0; exp = (opponent.Id == player1.Gotchi.Gotchi.Id ? player1.Gotchi.Stats.Level : player2.Gotchi.Stats.Level) * 10.0; if (!won) { exp *= .5; } return(exp); }
public static GotchiTradeRequest GetTradeRequest(Gotchi recievedGotchi) { // Returns the trade request that this user is a partner in. // If the partner has changed gotchis since the request was initiated, the request is invalid and thus not returned. foreach (GotchiTradeRequest request in _trade_requests) { if (request.ReceivedGotchi.OwnerId == recievedGotchi.OwnerId && request.ReceivedGotchi.Id == recievedGotchi.Id) { return(request); } } return(null); }
public async Task <GotchiMoveSet> GetMoveSetAsync(SQLiteDatabase database, Gotchi gotchi) { IEnumerable <GotchiMove> learnSet = await GetLearnSetAsync(database, gotchi); GotchiMoveSet set = new GotchiMoveSet(); Random rng = new Random((int)gotchi.SpeciesId); set.AddRange(learnSet .Skip(Math.Max(0, learnSet.Count() - GotchiMoveSet.MoveLimit)) .OrderBy(x => rng.Next())); set.Moves.Sort((lhs, rhs) => lhs.Name.CompareTo(rhs.Name)); return(set); }
public async Task <GotchiType[]> GetTypesAsync(Gotchi gotchi) { List <GotchiType> types = new List <GotchiType>(); foreach (GotchiType type in await GetTypesAsync()) { if (await new GotchiRequirementsChecker { Requires = type.Requires }.CheckAsync(gotchi)) { types.Add(type); } } return(types.ToArray()); }
private async Task <bool> _checkRolesAsync(Gotchi gotchi, GotchiRequirements requirements) { try { IEnumerable <IRole> roles = await database.GetRolesAsync(gotchi.SpeciesId); foreach (Role role in roles) { if (Regex.IsMatch(role.Name, requirements.RolePattern, RegexOptions.IgnoreCase)) { return(true); } } } catch (Exception) { } return(false); }
public static async Task ExecuteTradeRequestAsync(ICommandContext context, SQLiteDatabase db, GotchiTradeRequest tradeRequest) { // Get both users and their gotchis. IUser user1 = await context.Guild.GetUserAsync(tradeRequest.OfferedGotchi.OwnerId); Gotchi gotchi1 = await db.GetGotchiAsync(user1.ToCreator()); GotchiUserInfo userInfo1 = await db.GetUserInfoAsync(user1.ToCreator()); IUser user2 = await context.Guild.GetUserAsync(tradeRequest.ReceivedGotchi.OwnerId); Gotchi gotchi2 = await db.GetGotchiAsync(user2.ToCreator()); GotchiUserInfo userInfo2 = await db.GetUserInfoAsync(user2.ToCreator()); // Swap the owners of the gotchis. using (SQLiteCommand cmd = new SQLiteCommand("UPDATE Gotchi SET owner_id = $owner_id WHERE id = $id")) { cmd.Parameters.AddWithValue("$owner_id", user1.Id); cmd.Parameters.AddWithValue("$id", gotchi2.Id); await db.ExecuteNonQueryAsync(cmd); } userInfo1.PrimaryGotchiId = gotchi2.Id; await db.UpdateUserInfoAsync(userInfo1); using (SQLiteCommand cmd = new SQLiteCommand("UPDATE Gotchi SET owner_id = $owner_id WHERE id = $id")) { cmd.Parameters.AddWithValue("$owner_id", user2.Id); cmd.Parameters.AddWithValue("$id", gotchi1.Id); await db.ExecuteNonQueryAsync(cmd); } userInfo2.PrimaryGotchiId = gotchi1.Id; await db.UpdateUserInfoAsync(userInfo2); // Remove all existing trade requests involving either user. _trade_requests.RemoveAll(x => x.OfferedGotchi.OwnerId == user1.Id || x.ReceivedGotchi.OwnerId == user2.Id); }
public async Task <GotchiStats> GetStatsAsync(Gotchi gotchi) { GotchiStats result = await GetBaseStatsAsync(gotchi); result.Experience = gotchi.Experience; // Calculate final stats based on level and base stats. // #todo Implement IVs/EVs int level = result.Level; result.MaxHp = _calculateHp(result.MaxHp, 0, 0, level); result.Atk = _calculateStat(result.Atk, 0, 0, level); result.Def = _calculateStat(result.Def, 0, 0, level); result.Spd = _calculateStat(result.Spd, 0, 0, level); result.Hp = result.MaxHp; return(await Task.FromResult(result)); }
public async Task <bool> CheckAsync(Gotchi gotchi) { List <GotchiRequirements> requirements = new List <GotchiRequirements> { Requires }; if (Requires != null) { requirements.AddRange(Requires.OrValue); } foreach (GotchiRequirements requirement in requirements) { if (!await CheckAsync(gotchi, requirement)) { return(false); } } return(true); }
private async Task <bool> _checkTypesAsync(Gotchi gotchi, GotchiRequirements requirements) { try { // Get the types assigned to this gotchi. GotchiType[] types = await Global.GotchiContext.TypeRegistry.GetTypesAsync(database, gotchi); // Compare each type using the type pattern provided. // #todo Types can also have aliases (AliasPattern). For now, we'll just try to match against the type pattern as well. foreach (GotchiType type in types) { if (Regex.IsMatch(type.Name, requirements.TypePattern, RegexOptions.IgnoreCase) || Regex.IsMatch(type.AliasPattern, requirements.TypePattern, RegexOptions.IgnoreCase)) { return(true); } } } catch (Exception) { } return(false); }
public async Task <GotchiMove[]> GetLearnSetAsync(Gotchi gotchi) { List <GotchiMove> moves = new List <GotchiMove>(); //// all gotchis can use hit regardless of species //GotchiMove universalMove = await _getMoveAsync("hit"); //if (universalMove != null) // moves.Add(universalMove); foreach (GotchiMove move in Registry.Values) { if (await new GotchiRequirementsChecker { Requires = move.Requires }.CheckAsync(gotchi)) { moves.Add(move.Clone()); } } return(moves.ToArray()); }
public async Task <bool> CheckAsync(Gotchi gotchi, GotchiRequirements requirements) { if (requirements is null) { return(true); } if (requirements.AlwaysFailValue) { return(false); } if (!_checkLevels(gotchi, requirements)) { return(false); } if (!string.IsNullOrEmpty(requirements.RolePattern) && !await _checkRolesAsync(gotchi, requirements)) { return(false); } if (!string.IsNullOrEmpty(requirements.TypePattern) && !await _checkTypesAsync(gotchi, requirements)) { return(false); } ISpecies species = await database.GetSpeciesAsync(gotchi.SpeciesId); if (!string.IsNullOrEmpty(requirements.DescriptionPattern) && !_checkDescription(species, requirements)) { return(false); } return(true); }
private bool _checkLevels(Gotchi gotchi, GotchiRequirements requirements) { int level = GotchiExperienceCalculator.GetLevel(ExperienceGroup.Default, gotchi.Experience); return(level >= requirements.MinimumLevelValue && level <= requirements.MaximumLevelValue); }
public bool IsCpuGotchi(Gotchi gotchi) { return(gotchi.OwnerId == WildGotchiUserId); }
public static async Task <bool> EvolveAndUpdateGotchiAsync(Gotchi gotchi) { return(await EvolveAndUpdateGotchiAsync(gotchi, string.Empty)); }
public static int GetLevel(ExperienceGroup experienceGroup, Gotchi gotchi) { return(GetLevel(experienceGroup, gotchi.Experience)); }
public static async Task <bool> EvolveAndUpdateGotchiAsync(Gotchi gotchi, string desiredEvo) { bool evolved = false; if (string.IsNullOrEmpty(desiredEvo)) { // Find all descendatants of this species. using (SQLiteCommand cmd = new SQLiteCommand("SELECT species_id FROM Ancestors WHERE ancestor_id=$ancestor_id;")) { List <long> descendant_ids = new List <long>(); cmd.Parameters.AddWithValue("$ancestor_id", gotchi.SpeciesId); using (DataTable rows = await Database.GetRowsAsync(cmd)) foreach (DataRow row in rows.Rows) { descendant_ids.Add(row.Field <long>("species_id")); } // Pick an ID at random. if (descendant_ids.Count > 0) { gotchi.SpeciesId = descendant_ids[BotUtils.RandomInteger(descendant_ids.Count)]; evolved = true; } } } else { // Get the desired evo. Species[] sp = await BotUtils.GetSpeciesFromDb("", desiredEvo); if (sp is null || sp.Length != 1) { return(false); } // Ensure that the species evolves into the desired evo. using (SQLiteCommand cmd = new SQLiteCommand("SELECT COUNT(*) FROM Ancestors WHERE ancestor_id = $ancestor_id AND species_id = $species_id")) { cmd.Parameters.AddWithValue("$ancestor_id", gotchi.SpeciesId); cmd.Parameters.AddWithValue("$species_id", sp[0].Id); if (await Database.GetScalar <long>(cmd) <= 0) { return(false); } gotchi.SpeciesId = sp[0].Id; evolved = true; } } // Update the gotchi in the database. using (SQLiteCommand cmd = new SQLiteCommand("UPDATE Gotchi SET species_id=$species_id, evolved_ts=$evolved_ts WHERE id=$id;")) { cmd.Parameters.AddWithValue("$species_id", gotchi.SpeciesId); // The "last evolved" timestamp is now only updated in the event the gotchi evolves (in order to make the "IsEvolved" check work correctly). // Note that this means that the background service will attempt to evolve the gotchi at every iteration (unless it evolves by leveling). if (evolved) { cmd.Parameters.AddWithValue("$evolved_ts", DateTimeOffset.UtcNow.ToUnixTimeSeconds()); } cmd.Parameters.AddWithValue("$id", gotchi.Id); await Database.ExecuteNonQuery(cmd); } return(evolved); }
public static async Task SetViewedTimestampAsync(Gotchi gotchi, long viewedTimestamp) { await SetViewedTimestampAsync(gotchi.Id, viewedTimestamp); }
public static async Task <GotchiTradeRequestResult> MakeTradeRequestAsync(ICommandContext context, SQLiteDatabase db, Gotchi offeredGotchi, Gotchi recievedGotchi) { // If either gotchi passed in is null, the request is invalid. if (offeredGotchi is null || recievedGotchi is null) { return(GotchiTradeRequestResult.Invalid); } // If the user has made previous trade requests, remove them. _trade_requests.RemoveAll(x => x.OfferedGotchi.OwnerId == offeredGotchi.OwnerId); // If their partner already has an open trade request that hasn't been accepted, don't allow a new trade request to be made. // This is so users cannot make a new trade request right before one is accepted and snipe the trade. GotchiTradeRequest request = GetTradeRequest(recievedGotchi); if (!(request is null)) { if (request.IsExpired) { _trade_requests.RemoveAll(x => x.ReceivedGotchi.OwnerId == recievedGotchi.OwnerId); } else { return(GotchiTradeRequestResult.RequestPending); } } request = new GotchiTradeRequest { OfferedGotchi = offeredGotchi, ReceivedGotchi = recievedGotchi }; if (!await ValidateTradeRequestAsync(context, db, request)) { return(GotchiTradeRequestResult.Invalid); } _trade_requests.Add(request); return(GotchiTradeRequestResult.Success); }
public async Task <GotchiStats> GetBaseStatsAsync(Gotchi gotchi) { GotchiStats result = new GotchiStats(); int denominator = 0; GotchiType[] gotchiTypes = await Context.TypeRegistry.GetTypesAsync(gotchi); if (gotchiTypes.Count() > 0) { // Include the average of all types of this species. result.MaxHp = gotchiTypes.Sum(x => x.BaseHp); result.Atk = gotchiTypes.Sum(x => x.BaseAtk); result.Def = gotchiTypes.Sum(x => x.BaseDef); result.Spd = gotchiTypes.Sum(x => x.BaseSpd); denominator += gotchiTypes.Count(); } long[] ancestor_ids = await SpeciesUtils.GetAncestorIdsAsync(gotchi.SpeciesId); // Factor in the base stats of this species' ancestor (which will, in turn, factor in all other ancestors). if (ancestor_ids.Count() > 0) { GotchiStats ancestor_stats = await GetBaseStatsAsync(new Gotchi { SpeciesId = ancestor_ids.Last() }); result.MaxHp += ancestor_stats.MaxHp; result.Atk += ancestor_stats.Atk; result.Def += ancestor_stats.Def; result.Spd += ancestor_stats.Spd; denominator += 1; } // Add 20 points if this species has an ancestor (this effect will be compounded by the previous loop). if (ancestor_ids.Count() > 0) { result.MaxHp += 20; result.Atk += 20; result.Def += 20; result.Spd += 20; } // Get the average of each base stat. denominator = Math.Max(denominator, 1); result.MaxHp /= denominator; result.Atk /= denominator; result.Def /= denominator; result.Spd /= denominator; // Add 0.5 points for every week the gotchi has been alive. int age_bonus = (int)(0.5 * (gotchi.Age / 7)); result.MaxHp += age_bonus; result.Atk += age_bonus; result.Def += age_bonus; result.Spd += age_bonus; // Add or remove stats based on the species' description. await _calculateDescriptionBasedBaseStats(gotchi, result); return(result); }
public static async Task RegisterBattleAsync(ICommandContext context, Gotchi gotchi1, Gotchi gotchi2) { // Initialize the battle state. GotchiBattleState state = new GotchiBattleState { // Initialize Player 1 (which must be a human player). player1 = new PlayerState { Gotchi = new BattleGotchi { Gotchi = gotchi1, Moves = await Global.GotchiContext.MoveRegistry.GetMoveSetAsync(gotchi1), Stats = await new GotchiStatsCalculator(Global.GotchiContext).GetStatsAsync(gotchi1), Types = await Global.GotchiContext.TypeRegistry.GetTypesAsync(gotchi1) } } }; if (gotchi2 != null) { // Initialize Player 2 (which may be a human player, or a CPU). state.player2 = new PlayerState { Gotchi = new BattleGotchi { Gotchi = gotchi2, Moves = await Global.GotchiContext.MoveRegistry.GetMoveSetAsync(gotchi2), Stats = await new GotchiStatsCalculator(Global.GotchiContext).GetStatsAsync(gotchi2), Types = await Global.GotchiContext.TypeRegistry.GetTypesAsync(gotchi2) } }; } else { // Otherwise, generate an opponent for the user. await state._generateOpponentAsync(); // If the opponent is null (no species available as opponents), abort. if (state.player2.Gotchi.Gotchi is null) { await BotUtils.ReplyAsync_Info(context, "There are no opponents available."); return; } // Since the user is battling a CPU, accept the battle immediately. state.accepted = true; } state.player1.Gotchi.Context = Global.GotchiContext; state.player2.Gotchi.Context = Global.GotchiContext; // Register the battle state in the battle state collection. _battle_states[gotchi1.OwnerId] = state; if (state.player2.Gotchi.Gotchi.OwnerId != WildGotchiUserId) { _battle_states[state.player2.Gotchi.Gotchi.OwnerId] = state; } // Set the initial message displayed when the battle starts. StringBuilder sb = new StringBuilder(); sb.AppendLine("The battle has begun!"); sb.AppendLine(); sb.AppendLine(string.Format("Pick a move with `{0}gotchi move`.\nSee your gotchi's moveset with `{0}gotchi moveset`.", Bot.OurFoodChainBot.Instance.Config.Prefix)); state.battleText = sb.ToString(); // If the user is battling a CPU, show the battle state immediately. // Otherwise, it will be shown when the other user accepts the battle challenge. if (state.IsBattlingCpu()) { await ShowBattleStateAsync(context, state); } }