/** * <summary>Generates a deterministic RNG seed based on the game date and ID.</summary> * <remarks> * In order to keep the seeds as deterministic as possible, each type * has a separately generated RNG seed. Each seed is created by left * shifting the year number by a small amount, bitwise ORing another * number (A), and then bitwise XORing the entire result by the player's * game ID, giving a unique seed for each month/biweek/week on each * playthrough. * * For monthly events, the number (A) is a number 0-3 representing * the season number. For biweekly events, the number (A) is a number * 0-8 representing which half of which month we're in. For weekly events, * the number (A) is a number 0-16 representing which week of which month * we're in. * * Note that while the seed for monthly events does not include the week * number, the seed for weekly events includes the month. The first is * to ensure that the monthly seed remains consistent throughout the * month. The second is to prevent the same four weekly events from * occuring throughout the entire year. The biweekly seed includes the * month for the same reason. * * The game ID is retrieved via the expression * <code>StardewValley.Game1.uniqueIDForThisGame</code> * </remarks> * * <param name="type">The type of event being generated.</param> * <param name="date">The date of generation.</param> * <returns>A deterministicly generated RNG seed.</returns> */ private int GetRNGSeed(EventType type, SDate date) { int year = date.Year; int gameID = (int)StardewValley.Game1.uniqueIDForThisGame; int month = date.SeasonAsInt(); // range: 0-3 (2 bits) int biweek = date.Week() / 2; // range: 0-1 (1 bit) int week = date.Week(); // range: 0-3 (2 bits) switch (type) { case EventType.Monthly: return(((year << 2) | month) ^ gameID); case EventType.Biweekly: return(((year << 3) | (month << 1) | biweek) ^ gameID); case EventType.Weekly: return(((year << 4) | (month << 2) | week) ^ gameID); default: return(0); // TODO: Some kind of error? } }