/// <summary> /// Report an update in tech level and any new components that have became /// available. /// </summary> private void TechLevelUp(TechLevel.ResearchField area, EmpireData empire) { TechLevel oldResearchLevel = empire.ResearchLevels.Clone(); empire.ResearchLevels[area]++; TechLevel newResearchLevel = empire.ResearchLevels; Message techAdvanceMessage = new Message( empire.Id, "Your race has advanced to Tech Level " + empire.ResearchLevels[area] + " in the " + area.ToString() + " field", "TechAdvance", null); serverState.AllMessages.Add(techAdvanceMessage); AllComponents allComponents = new AllComponents(); foreach (Component component in allComponents.GetAll.Values) { if (oldResearchLevel < component.RequiredTech && newResearchLevel >= component.RequiredTech) { empire.AvailableComponents.Add(component); Message newComponentMessage = null; if (component.Properties.ContainsKey("Scanner") && component.Type == ItemType.PlanetaryInstallations) { newComponentMessage = new Message( empire.Id, "All existing planetary scanners has been replaced by " + component.Name + " " + component.Type, "NewComponentMessage", null); foreach (Star star in empire.OwnedStars.Values) { if (star.Owner == empire.Id && star.ScannerType != string.Empty) { star.ScannerType = component.Name; } } } else { newComponentMessage = new Message( empire.Id, "You now have available the " + component.Name + " " + component.Type + " component", "NewComponentMessage", // TODO (priority 4) - Is this used? Is it documented somewhere? Why a string and not an enum? null); } serverState.AllMessages.Add(newComponentMessage); } } }
/// <Summary> /// Initializes a new instance of the ResearchDialog class. /// </Summary> public ResearchDialog(ClientData clientState) { InitializeComponent(); this.clientState = clientState; currentLevel = this.clientState.EmpireState.ResearchLevels; // Provide a convienient way of getting a button from it's name. buttons.Add("Energy", energyButton); buttons.Add("Weapons", weaponsButton); buttons.Add("Propulsion", propulsionButton); buttons.Add("Construction", constructionButton); buttons.Add("Electronics", electronicsButton); buttons.Add("Biotechnology", biotechButton); // Set the currently attained research levels energyLevel.Text = currentLevel[TechLevel.ResearchField.Energy].ToString(); weaponsLevel.Text = currentLevel[TechLevel.ResearchField.Weapons].ToString(); propulsionLevel.Text = currentLevel[TechLevel.ResearchField.Propulsion].ToString(); constructionLevel.Text = currentLevel[TechLevel.ResearchField.Construction].ToString(); electronicsLevel.Text = currentLevel[TechLevel.ResearchField.Electronics].ToString(); biotechLevel.Text = currentLevel[TechLevel.ResearchField.Biotechnology].ToString(); // Ensure that the correct RadioButton is checked to reflect the // current research selection and the budget up-down control is // initialized with the correct value. // Find the first research priority // TODO: Implement a proper hierarchy of research ("next research field") system. foreach (TechLevel.ResearchField area in Enum.GetValues(typeof(TechLevel.ResearchField))) { if (this.clientState.EmpireState.ResearchTopics[area] == 1) { targetArea = area; break; } } RadioButton button = buttons[Enum.GetName(typeof(TechLevel.ResearchField), targetArea)]; button.Checked = true; availableEnergy = CountEnergy(); availableResources.Text = this.availableEnergy.ToString(System.Globalization.CultureInfo.InvariantCulture); budgetPercentage.Value = this.clientState.EmpireState.ResearchBudget; dialoginitialized = true; ParameterChanged(null, null); }
/// <Summary> /// A new area has been selected for research. Make a note of where the research /// resources are now going to be spent. /// </Summary> /// <param name="sender">The source of the event.</param> /// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param> private void CheckChanged(object sender, EventArgs e) { if (dialoginitialized == false) { return; } RadioButton button = sender as RadioButton; if (button != null && button.Checked == true) { try { clientState.EmpireState.ResearchTopics[targetArea] = 0; targetArea = (TechLevel.ResearchField)Enum.Parse(typeof(TechLevel.ResearchField), button.Text, true); clientState.EmpireState.ResearchTopics[targetArea] = 1; } catch (System.ArgumentException) { Report.Error("ResearchDialog.cs : CheckChanged() - unrecognised field of research."); } } // Populate the expected research benefits list AllComponents allComponents = new AllComponents(); TechLevel oldResearchLevel = currentLevel; TechLevel newResearchLevel = new TechLevel(oldResearchLevel); newResearchLevel[targetArea] = oldResearchLevel[targetArea] + 1; researchBenefits.Items.Clear(); foreach (Nova.Common.Components.Component component in allComponents.GetAll.Values) { if (!oldResearchLevel.Meets(component.RequiredTech) && newResearchLevel.Meets(component.RequiredTech)) { string available = component.Name + " " + component.Type; researchBenefits.Items.Add(available); } } ParameterChanged(null, null); }
/// <summary> /// Contributes allocated research from the star. /// </summary> /// <param name="race">Star's owner race.</param> /// <param name="star">Star to process.</param> /// <remarks> /// Note that stars which contribute only leftovers are not accounted for. /// </remarks> private void ContributeAllocatedResearch(Star star) { if (star.Owner == Global.Nobody) { return; } EmpireData empire = serverState.AllEmpires[star.Owner]; TechLevel targetAreas = empire.ResearchTopics; TechLevel.ResearchField targetArea = TechLevel.ResearchField.Energy; // default to Energy. // Find the first research priority // TODO: Implement a proper hierarchy of research ("next research field") system. foreach (TechLevel.ResearchField area in Enum.GetValues(typeof(TechLevel.ResearchField))) { if (targetAreas[area] == 1) { targetArea = area; break; } } // Consume resources for research for added paranoia. empire.ResearchResources[targetArea] = empire.ResearchResources[targetArea] + star.ResearchAllocation; star.ResearchAllocation = 0; while (true) { int cost = Research.Cost(targetArea, empire.Race, empire.ResearchLevels, empire.ResearchLevels[targetArea] + 1); if (empire.ResearchResources[targetArea] >= cost) { TechLevelUp(targetArea, empire); } else { break; } } }
/// <summary> /// Return the total energy cost for researching a level (taking into account /// the cost factor specified in the race designer). Note that we skip the first /// few turns of the Fibonacci series as they are too close together. /// </summary> /// <param name="level">The level to be researched.</param> /// <returns>The energy cost to reach that level.</returns> public static int Cost(TechLevel.ResearchField field, Race race, TechLevel totalLevels, int level) { int techAjustment = 0; foreach (int levelAttained in totalLevels) { techAjustment += levelAttained * 10; } // The research cost is based on a Fionacci series (starting) at 5 // multimplied by 10 then 10 points per tech-level reached in all // fields is added. Finally, the cost factor specified in the Race // Designer is then added. // ??? (priority 3) is this the Stars! costs, or some approximation? Need a reference. int baseCost = (Fibonacci(level + 5) * 10) + techAjustment; int costFactor = race.ResearchCosts[field]; return((baseCost * costFactor) / 100); }
/// <Summary> /// Manage research. /// Only changes research field after completing the previous research level. /// </Summary> private void HandleResearch() { // Generate a research command to describe the changes. ResearchCommand command = new ResearchCommand(); command.Topics.Zero(); // Set the percentage of production to dedicate to research command.Budget = 0; // check if messages contains info about tech advence. Could be more than one, so use a flag to prevent setting the research level multiple times. bool hasAdvanced = false; foreach (Message msg in clientState.Messages) { if (!string.IsNullOrEmpty(msg.Type) && msg.Type == "TechAdvance") //// if (!string.IsNullOrEmpty(msg.Type) && msg.Text.Contains("Your race has advanced to Tech Level") == true) // can be removed if the previous line works { hasAdvanced = true; } } if (hasAdvanced) { // pick next topic int minLevel = int.MaxValue; Nova.Common.TechLevel.ResearchField targetResearchField = TechLevel.ResearchField.Weapons; // default to researching weapons if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Propulsion] < 3) { // Prop 3 - Long Hump 6 - Warp 6 engine (or fuel mizer at Prop 2) targetResearchField = TechLevel.ResearchField.Propulsion; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Electronics] < 1) { // Elec 1 - Rhino Scanner - 50 ly scan targetResearchField = TechLevel.ResearchField.Electronics; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Construction] < 3) { // Cons 3 - Destroyer & Medium Freighter targetResearchField = TechLevel.ResearchField.Construction; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Electronics] < 5) { // Elec 5 - Scanners targetResearchField = TechLevel.ResearchField.Electronics; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Weapons] < 6) { // Wep 6 - Beta Torp (@5) and Yakimora Light Phaser targetResearchField = TechLevel.ResearchField.Weapons; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Propulsion] < 7) { // Prop 7 - Warp 8 engine targetResearchField = TechLevel.ResearchField.Propulsion; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Construction] < 6) { // Cons 6 - Frigate targetResearchField = TechLevel.ResearchField.Construction; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Biotechnology] < 4) { // Bio 4 - Unlock terraform and prep for mines targetResearchField = TechLevel.ResearchField.Biotechnology; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Energy] < 3) { // Energy 3 - Mines and shields targetResearchField = TechLevel.ResearchField.Energy; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Construction] < 9) { // Cons 9 - Cruiser targetResearchField = TechLevel.ResearchField.Construction; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Energy] < 6) { // Energy 6 - Shields targetResearchField = TechLevel.ResearchField.Energy; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Weapons] < 12) { // Weapons 12 - Jihad Missile targetResearchField = TechLevel.ResearchField.Weapons; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Construction] < 13) { // Cons 13 - Battleships targetResearchField = TechLevel.ResearchField.Construction; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Energy] < 11) { // Energy 11 - Bear Neutrino at 10, and unlocks Syncro Sapper (need weapons 21) targetResearchField = TechLevel.ResearchField.Energy; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Electronics] < 11) { // Elect 11 - Jammer 20 and Super Computer targetResearchField = TechLevel.ResearchField.Electronics; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Propulsion] < 12) { // Prop 12 - Warp 10 and Overthruster targetResearchField = TechLevel.ResearchField.Propulsion; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Biotechnology] < 7) { // Bio 7 maybe - scanners, Anti-matter generator, smart bombs targetResearchField = TechLevel.ResearchField.Biotechnology; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Weapons] < 24) { // Weapons 24 - research all remaining weapons technologies targetResearchField = TechLevel.ResearchField.Weapons; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Construction] < 26) { // Cons 26 - Nubian targetResearchField = TechLevel.ResearchField.Construction; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Electronics] < 19) { // Elect 19 - Battle nexus targetResearchField = TechLevel.ResearchField.Electronics; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Energy] < 22) { // Energy 22 - Complete Phase Shield targetResearchField = TechLevel.ResearchField.Energy; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Propulsion] < 23) { // Prop 23 - Trans-Star 10 targetResearchField = TechLevel.ResearchField.Propulsion; } else if (clientState.EmpireState.ResearchLevels[TechLevel.ResearchField.Biotechnology] < 10) { // Bio 10 - RNA Scanner targetResearchField = TechLevel.ResearchField.Biotechnology; } else { // research lowest tech field for (TechLevel.ResearchField field = TechLevel.FirstField; field <= TechLevel.LastField; field++) { if (clientState.EmpireState.ResearchLevels[field] < minLevel) { minLevel = clientState.EmpireState.ResearchLevels[field]; targetResearchField = field; } } } command.Topics[targetResearchField] = 1; } if (command.IsValid(clientState.EmpireState)) { clientState.Commands.Push(command); command.ApplyToState(clientState.EmpireState); } }