public static getColorFromPercent ( int percent, double light ) : Color | ||
percent | int | percent that determines the shade between red and green (0 to 100) |
light | double | double from -1 to 1. Values greater zero make the color brighter, lower than zero make the color darker. |
return | Color |
public void setNumbers(int levelWild, int levelDom, double valueBreeding, double valueDom) { // visualization of wild level int barLengthPercentage = (int)Math.Min(100, Math.Round(levelWild * (300.0f / (cc != null? cc.maxWildLevel:40)))); this.panelBarWildLevels.Width = (int)(164 * barLengthPercentage / 100.0f); panelBarWildLevels.BackColor = Utils.getColorFromPercent(barLengthPercentage); tt.SetToolTip(panelBarWildLevels, Utils.levelPercentile(levelWild)); // visualization of dom level barLengthPercentage = (int)Math.Min(100, Math.Round(levelDom * (300.0f / (cc != null? cc.maxWildLevel:40)))); this.panelBarDomLevels.Width = (int)(164 * barLengthPercentage / 100.0f); panelBarDomLevels.BackColor = Utils.getColorFromPercent(barLengthPercentage); if (levelWild < 0) { labelWildLevel.Text = "n/a"; labelWildLevel.ForeColor = Color.LightGray; } else { labelWildLevel.Text = levelWild.ToString(); labelWildLevel.ForeColor = SystemColors.ControlText; } labelLevelDom.Text = levelDom.ToString(); labelBreedingValue.Text = (Percent ? Math.Round(100 * valueBreeding, 1).ToString("N1") + " %" : valueBreeding.ToString("N1")); labelDomValue.Text = (Percent ? Math.Round(100 * valueDom, 1).ToString("N1") + " %" : valueDom.ToString("N1")); }
public void setCreature(Creature creature) { this.creature = creature; groupBox1.Text = (!onlyLevels && creature.status != CreatureStatus.Available ? "(" + Utils.statusSymbol(creature.status) + ") " : "") + creature.name + " (" + creature.levelHatched + (totalLevelUnknown ? "+" : "") + ")"; if (!onlyLevels && creature.status == CreatureStatus.Dead) { groupBox1.ForeColor = SystemColors.GrayText; tt.SetToolTip(groupBox1, "Creature has passed away"); } else if (!onlyLevels && creature.status == CreatureStatus.Unavailable) { groupBox1.ForeColor = SystemColors.GrayText; tt.SetToolTip(groupBox1, "Creature is currently not available"); } for (int s = 0; s < 7; s++) { if (creature.levelsWild[s] < 0) { labels[s].Text = "?"; labels[s].BackColor = Color.WhiteSmoke; labels[s].ForeColor = Color.LightGray; } else { labels[s].Text = creature.levelsWild[s].ToString(); labels[s].BackColor = Utils.getColorFromPercent((int)(creature.levelsWild[s] * 2.5), (creature.topBreedingStats[s] ? 0.2 : 0.7)); labels[s].ForeColor = SystemColors.ControlText; tt.SetToolTip(labels[s], Utils.statName(s) + ": " + (creature.valuesBreeding[s] * (Utils.precision(s) == 3 ? 100 : 1)).ToString() + (Utils.precision(s) == 3 ? "%" : "")); } labels[s].Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, (creature.topBreedingStats[s] ? System.Drawing.FontStyle.Bold : System.Drawing.FontStyle.Regular), System.Drawing.GraphicsUnit.Point, ((byte)(0))); } if (onlyLevels) { labelSex.Visible = false; pictureBox1.Visible = false; plainTextcurrentValuesToolStripMenuItem.Visible = false; aRKChatcurrentValuesToolStripMenuItem.Visible = false; } else { labelSex.Visible = true; labelSex.Text = Utils.sexSymbol(creature.gender); labelSex.BackColor = creature.neutered ? SystemColors.GrayText : Utils.sexColor(creature.gender); // creature Colors pictureBox1.Image = CreatureColored.getColoredCreature(creature.colors, "", enabledColorRegions, 24, 22, true); labelSex.Visible = true; pictureBox1.Visible = true; plainTextcurrentValuesToolStripMenuItem.Visible = true; aRKChatcurrentValuesToolStripMenuItem.Visible = true; } labelMutations.BackColor = Color.FromArgb(225, 192, 255); labelMutations.Text = creature.mutationCounter.ToString(); labelMutations.Visible = creature.mutationCounter > 0; contextMenuAvailable = true; }
private void UpdateLevelSums() { int sumW = 0, sumD = 0; for (int s = 0; s < 7; s++) { sumW += statControls[s].levelWild; sumD += statControls[s].levelDom; } lbLevelSumWild.Text = "Sum LevelWild = " + sumW.ToString(); bool positive; int diff = sumW - statControls[7].levelWild; if (diff != 0) { positive = diff > 0; if (!positive) { diff = -diff; } lbLevelSumWild.Text += " (" + (positive ? "+" : "") + (sumW - statControls[7].levelWild).ToString() + ")"; if (diff > 50) { diff = 50; } lbLevelSumWild.BackColor = Utils.getColorFromPercent(50 - diff, 0.6, !positive); } else { lbLevelSumWild.BackColor = SystemColors.Window; } lbLevelSumDom.Text = "Sum LevelDom = " + sumD.ToString(); diff = sumW + sumD + 1 - (int)nudCreatureLevel.Value; if (diff != 0) { positive = diff > 0; if (!positive) { diff = -diff; } lbLevelSumDom.Text += " (" + (positive ? "+" : "") + (sumW + sumD + 1 - (int)nudCreatureLevel.Value).ToString() + ")"; if (diff > 50) { diff = 50; } lbLevelSumDom.BackColor = Utils.getColorFromPercent(50 - diff, 0.6, !positive); } else { lbLevelSumDom.BackColor = SystemColors.Window; } }
private void drawBars() { SuspendLayout(); Clear(false); int totalWidth = Width; int totalHeight = Height - 14; double heightMultiplier = totalHeight / maxProbability; int barNumber = levelProbabilities.Count; if (barNumber > 0) { int barWidth = totalWidth / barNumber; int i = 0; foreach (KeyValuePair <int, double> prob in levelProbabilities.OrderBy(l => l.Key)) { Panel p = new Panel { Width = barWidth, Height = (int)Math.Ceiling(prob.Value * heightMultiplier) }; tt.SetToolTip(p, $"Level {prob.Key} ({Math.Round(prob.Value * 100, 2)}%)"); p.Left = i * barWidth; p.Top = totalHeight - p.Height; p.BackColor = Utils.getColorFromPercent(100 * (prob.Key - maxWildLevel / 2) / (2 * maxWildLevel)); // color range from maxWildLevel/2 up to 2*maxWildLevel p.BorderStyle = BorderStyle.FixedSingle; Controls.Add(p); barPanels.Add(p); // min/max-labels if (i == 0) { labelMin.Text = prob.Key.ToString(); } if (i == barNumber - 1) { labelMax.Text = prob.Key.ToString(); } i++; } labelMax.Left = i * barWidth - labelMax.Width; labelMaxProb.Text = Math.Round(maxProbability * 100, 2) + "%"; } ResumeLayout(); }
private void numLvD_ValueChanged(object sender, EventArgs e) { int lengthPercentage = 100 * (int)numLvD.Value / barMaxLevel; // in percentage of the max-barwidth if (lengthPercentage > 100) { lengthPercentage = 100; } if (lengthPercentage < 0) { lengthPercentage = 0; } this.panelBarDomLevels.Width = lengthPercentage * 283 / 100; this.panelBarDomLevels.BackColor = Utils.getColorFromPercent(lengthPercentage); if (inputType != StatIOInputType.FinalValueInputType) { LevelChanged(this); } }
private void numLvW_ValueChanged(object sender, EventArgs e) { int lengthPercentage = (int)((int)numLvW.Value * (100.0f / Properties.Settings.Default.BarMaximum)); // in percentage of the max-barwidth if (lengthPercentage > 100) { lengthPercentage = 100; } if (lengthPercentage < 0) { lengthPercentage = 0; } this.panelBarWildLevels.Width = lengthPercentage * 283 / 100; this.panelBarWildLevels.BackColor = Utils.getColorFromPercent(lengthPercentage); tt.SetToolTip(panelBarWildLevels, Utils.levelPercentile((int)numLvW.Value)); if (inputType != StatIOInputType.FinalValueInputType) { LevelChanged(this); } }
private void AsyncCalculateBreedingScoresAndDisplayPairs(BreedingMode breedingMode, bool updateBreedingData = false) { SuspendLayout(); this.SuspendDrawing(); Cursor.Current = Cursors.WaitCursor; ClearControls(); // chosen Creature (only consider this one for its sex) bool considerChosenCreature = chosenCreature != null; // filter by tags int crCountF = females.Count; int crCountM = males.Count; List <Creature> chosenF, chosenM; if (considerChosenCreature && chosenCreature.sex == Sex.Female) { chosenF = new List <Creature>(); } else { chosenF = FilterByTags(females); } if (considerChosenCreature && chosenCreature.sex == Sex.Male) { chosenM = new List <Creature>(); } else { chosenM = FilterByTags(males); } // filter by servers if (cbServerFilterLibrary.Checked) { chosenF = chosenF.Where(c => (c.server == "" && !creatureCollection.hiddenServers.Contains("n/a")) || (c.server != "" && !creatureCollection.hiddenServers.Contains(c.server))).ToList(); chosenM = chosenM.Where(c => (c.server == "" && !creatureCollection.hiddenServers.Contains("n/a")) || (c.server != "" && !creatureCollection.hiddenServers.Contains(c.server))).ToList(); } // filter by owner if (cbOwnerFilterLibrary.Checked) { chosenF = chosenF.Where(c => (c.owner == "" && !creatureCollection.hiddenOwners.Contains("n/a")) || (c.owner != "" && !creatureCollection.hiddenOwners.Contains(c.owner))).ToList(); chosenM = chosenM.Where(c => (c.owner == "" && !creatureCollection.hiddenOwners.Contains("n/a")) || (c.owner != "" && !creatureCollection.hiddenOwners.Contains(c.owner))).ToList(); } bool creaturesTagFilteredOut = (crCountF != chosenF.Count) || (crCountM != chosenM.Count); crCountF = chosenF.Count; crCountM = chosenM.Count; if (nudBPMutationLimit.Value >= 0) { chosenF = chosenF.Where(c => c.Mutations <= nudBPMutationLimit.Value).ToList(); chosenM = chosenM.Where(c => c.Mutations <= nudBPMutationLimit.Value).ToList(); } bool creaturesMutationsFilteredOut = (crCountF != chosenF.Count) || (crCountM != chosenM.Count); if (considerChosenCreature) { if (chosenCreature.sex == Sex.Female) { chosenF.Add(chosenCreature); } if (chosenCreature.sex == Sex.Male) { chosenM.Add(chosenCreature); } } lbBreedingPlanHeader.Text = currentSpecies.DescriptiveNameAndMod + (considerChosenCreature ? " (" + string.Format(Loc.s("onlyPairingsWith"), chosenCreature.name) + ")" : ""); if (considerChosenCreature && (chosenCreature.flags.HasFlag(CreatureFlags.Neutered) || chosenCreature.status != CreatureStatus.Available)) { lbBreedingPlanHeader.Text += $"{Loc.s("BreedingNotPossible")} ! ({(chosenCreature.flags.HasFlag(CreatureFlags.Neutered) ? Loc.s("Neutered") : Loc.s("notAvailable"))})"; } string warningText = ""; if (creaturesTagFilteredOut) { warningText = Loc.s("BPsomeCreaturesAreFilteredOutTags"); } if (creaturesMutationsFilteredOut) { warningText += (warningText.Length > 0 ? " " + Loc.s("BPorMutations") : Loc.s("BPsomeCreaturesAreFilteredOutMutations")); } if (warningText.Length > 0) { SetMessageLabelText(warningText + ".\n" + Loc.s("BPTopStatsShownMightNotTotalTopStats"), MessageBoxIcon.Warning); } var combinedCreatures = new List <Creature>(chosenF); combinedCreatures.AddRange(chosenM); // determine top-stats for choosen creatures. int[] topStats = new int[Values.STATS_COUNT]; foreach (Creature c in combinedCreatures) { for (int s = 0; s < Values.STATS_COUNT; s++) { if (topStats[s] < c.levelsWild[s]) { topStats[s] = c.levelsWild[s]; } } } if (Properties.Settings.Default.IgnoreSexInBreedingPlan) { chosenF = new List <Creature>(combinedCreatures); chosenM = new List <Creature>(combinedCreatures); } if (chosenF.Count > 0 && chosenM.Count > 0) { pedigreeCreature1.Show(); pedigreeCreature2.Show(); lbBPBreedingScore.Show(); breedingPairs.Clear(); short[] bestPossLevels = new short[Values.STATS_COUNT]; // best possible levels foreach (Creature female in chosenF) { foreach (Creature male in chosenM) { if (male == female || // happens if Properties.Settings.Default.IgnoreSexInBreedingPlan (when using S+ mutator) (nudBPMutationLimit.Value >= 0 && female.Mutations > nudBPMutationLimit.Value && male.Mutations > nudBPMutationLimit.Value) // if one pair is below the limit, show this pair ) { continue; } double t = 0; int nrTS = 0; double eTS = 0; int topfemale = 0; int topmale = 0; for (int s = 0; s < Values.STATS_COUNT; s++) { if (s == (int)StatNames.Torpidity) { continue; } bestPossLevels[s] = 0; int higherLevel = Math.Max(female.levelsWild[s], male.levelsWild[s]); int lowerlevel = Math.Min(female.levelsWild[s], male.levelsWild[s]); if (higherLevel < 0) { higherLevel = 0; } if (lowerlevel < 0) { lowerlevel = 0; } double tt = statWeights[s] * (probabilityHigherLevel * higherLevel + probabilityLowerLevel * lowerlevel) / 40; if (tt > 0) { if (breedingMode == BreedingMode.TopStatsLucky) { if (female.levelsWild[s] == topStats[s] || male.levelsWild[s] == topStats[s]) { if (female.levelsWild[s] == topStats[s] && male.levelsWild[s] == topStats[s]) { tt *= 1.142; } } else if (bestLevels[s] > 0) { tt *= .01; } } else if (breedingMode == BreedingMode.TopStatsConservative && bestLevels[s] > 0) { bestPossLevels[s] = (short)Math.Max(female.levelsWild[s], male.levelsWild[s]); tt *= .01; if (female.levelsWild[s] == topStats[s] || male.levelsWild[s] == topStats[s]) { nrTS++; eTS += female.levelsWild[s] == topStats[s] && male.levelsWild[s] == topStats[s] ? 1 : probabilityHigherLevel; if (female.levelsWild[s] == topStats[s]) { topfemale++; } if (male.levelsWild[s] == topStats[s]) { topmale++; } } } } t += tt; } if (breedingMode == BreedingMode.TopStatsConservative) { if (topfemale < nrTS && topmale < nrTS) { t += eTS; } else { t += .1 * eTS; } // check if the best possible stat outcome already exists in a male bool maleExists = false; foreach (Creature cr in chosenM) { maleExists = true; for (int s = 0; s < Values.STATS_COUNT; s++) { if (s == (int)StatNames.Torpidity || cr.valuesDom[s] == 0) { continue; // TODO check if stat is used with cr.species.statsUsed[s] } if (cr.levelsWild[s] != bestPossLevels[s]) { maleExists = false; break; } } if (maleExists) { break; } } if (maleExists) { t *= .4; // another male with the same stats is not worth much, the mating-cooldown of males is short. } else { // check if the best possible stat outcome already exists in a female bool femaleExists = false; foreach (Creature cr in chosenF) { femaleExists = true; for (int s = 0; s < Values.STATS_COUNT; s++) { if (s == (int)StatNames.Torpidity || cr.valuesDom[s] == 0) { continue; // TODO check if stat is used with cr.species.statsUsed[s] } if (cr.levelsWild[s] != bestPossLevels[s]) { femaleExists = false; break; } } if (femaleExists) { break; } } if (femaleExists) { t *= .8; // another female with the same stats may be useful, but not so much in conservative breeding } } //t *= 2; // scale conservative mode as it rather displays improvement, but only scarcely } breedingPairs.Add(new BreedingPair(female, male, t * 1.25)); } } breedingPairs = breedingPairs.OrderByDescending(p => p.BreedingScore).ToList(); double minScore = (breedingPairs.Count > 0 ? breedingPairs[breedingPairs.Count - 1].BreedingScore : 0); if (minScore < 0) { foreach (BreedingPair bp in breedingPairs) { bp.BreedingScore -= minScore; } } // draw best parents int row = 0; // scrolloffsets int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; for (int i = 0; i < breedingPairs.Count && i < creatureCollection.maxBreedingSuggestions; i++) { PedigreeCreature pc; if (2 * i < pcs.Count) { pcs[2 * i].Creature = breedingPairs[i].Female; pcs[2 * i].enabledColorRegions = enabledColorRegions; pcs[2 * i].comboId = i; pcs[2 * i].Show(); } else { pc = new PedigreeCreature(breedingPairs[i].Female, enabledColorRegions, i); //pc.Location = new Point(10 + xS, 5 + 35 * row + yS); pc.CreatureClicked += CreatureClicked; pc.CreatureEdit += CreatureEdit; pc.BPRecalc += RecalculateBreedingPlan; pc.BestBreedingPartners += BestBreedingPartners; pc.exportToClipboard += ExportToClipboard; flowLayoutPanelPairs.Controls.Add(pc); pcs.Add(pc); } // draw score PictureBox pb; if (i < pbs.Count) { pb = pbs[i]; pbs[i].Show(); } else { pb = new PictureBox { Size = new Size(87, 35) }; //pb.Location = new Point(308 + xS, 19 + 35 * row + yS); pbs.Add(pb); flowLayoutPanelPairs.Controls.Add(pb); } if (2 * i + 1 < pcs.Count) { pcs[2 * i + 1].Creature = breedingPairs[i].Male; pcs[2 * i + 1].enabledColorRegions = enabledColorRegions; pcs[2 * i + 1].comboId = i; pcs[2 * i + 1].Show(); } else { pc = new PedigreeCreature(breedingPairs[i].Male, enabledColorRegions, i); //pc.Location = new Point(397 + xS, 5 + 35 * row + yS); pc.CreatureClicked += CreatureClicked; pc.CreatureEdit += CreatureEdit; pc.BPRecalc += RecalculateBreedingPlan; pc.BestBreedingPartners += BestBreedingPartners; pc.exportToClipboard += ExportToClipboard; flowLayoutPanelPairs.Controls.Add(pc); flowLayoutPanelPairs.SetFlowBreak(pc, true); pcs.Add(pc); } Bitmap bm = new Bitmap(pb.Width, pb.Height); Graphics g; using (g = Graphics.FromImage(bm)) { g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; Brush br = new SolidBrush(Utils.getColorFromPercent((int)(breedingPairs[i].BreedingScore * 12.5), 0.5)); Brush brd = new SolidBrush(Utils.getColorFromPercent((int)(breedingPairs[i].BreedingScore * 12.5), -.2)); g.FillRectangle(brd, 0, 15, 87, 5); g.FillRectangle(brd, 20, 10, 47, 15); g.FillRectangle(br, 1, 16, 85, 3); g.FillRectangle(br, 21, 11, 45, 13); g.DrawString(breedingPairs[i].BreedingScore.ToString("N4"), new Font("Microsoft Sans Serif", 8.25f), new SolidBrush(Color.Black), 24, 12); pb.Image = bm; } row++; } // hide unused controls for (int i = breedingPairs.Count; i < creatureCollection.maxBreedingSuggestions && 2 * i + 1 < pcs.Count && i < pbs.Count; i++) { pcs[2 * i].Hide(); pcs[2 * i + 1].Hide(); pbs[i].Hide(); } if (updateBreedingData) { SetBreedingData(currentSpecies); } if (breedingPairs.Count > 0) { SetParents(0); // if breeding mode is conservative and a creature with top-stats already exists, the scoring might seem off if (breedingMode == BreedingMode.TopStatsConservative) { bool bestCreatureAlreadyAvailable = true; Creature bestCreature = null; List <Creature> choosenFemalesAndMales = chosenF.Concat(chosenM).ToList(); foreach (Creature cr in choosenFemalesAndMales) { bestCreatureAlreadyAvailable = true; for (int s = 0; s < Values.STATS_COUNT; s++) { // if the stat is not a top stat and the stat is leveled in wild creatures if (!cr.topBreedingStats[s] && cr.Species.stats[s].IncPerWildLevel != 0) { bestCreatureAlreadyAvailable = false; break; } } if (bestCreatureAlreadyAvailable) { bestCreature = cr; break; } } if (bestCreatureAlreadyAvailable) { SetMessageLabelText(string.Format(Loc.s("AlreadyCreatureWithTopStats"), bestCreature.name, Utils.sexSymbol(bestCreature.sex)), MessageBoxIcon.Warning); } } } else { SetParents(-1); } } else { // hide unused controls pedigreeCreature1.Hide(); pedigreeCreature2.Hide(); lbBPBreedingScore.Hide(); for (int i = 0; i < creatureCollection.maxBreedingSuggestions && 2 * i + 1 < pcs.Count && i < pbs.Count; i++) { pcs[2 * i].Hide(); pcs[2 * i + 1].Hide(); pbs[i].Hide(); } lbBreedingPlanInfo.Text = string.Format(Loc.s("NoPossiblePairingForSpeciesFound"), currentSpecies); lbBreedingPlanInfo.Visible = true; if (updateBreedingData) { SetBreedingData(currentSpecies); } } Cursor.Current = Cursors.Default; this.ResumeDrawing(); if (considerChosenCreature) { btShowAllCreatures.Text = "Unset Restriction to " + chosenCreature.name; } btShowAllCreatures.Visible = considerChosenCreature; ResumeLayout(); }
public void drawBestParents(BreedingMode breedingMode, bool updateBreedingData = false) { SuspendLayout(); Cursor.Current = Cursors.WaitCursor; ClearControls(); // chosen Creature (only consider this one for its gender) bool considerChosenCreature = chosenCreature != null; Sex chosenCS = (considerChosenCreature ? chosenCreature.gender : Sex.Unknown); labelTitle.Text = currentSpecies + (considerChosenCreature ? " (only pairings with \"" + chosenCreature.name + "\")" : ""); if (considerChosenCreature && (chosenCreature.neutered || chosenCreature.status != CreatureStatus.Available)) { labelTitle.Text += "! Breeding not possible ! (" + (chosenCreature.neutered ? "neutered" : "not available") + ")"; } // filter by tags List <Creature> choosenF = filterByTags(females); List <Creature> choosenM = filterByTags(males); if (choosenF != null && choosenM != null && choosenF.Count > 0 && choosenM.Count > 0) { pedigreeCreature1.Show(); pedigreeCreature2.Show(); labelBreedingScore.Show(); combinedTops[0].Clear(); combinedTops[1].Clear(); comboScore.Clear(); comboOrder.Clear(); double t = 0, tt = 0, eTS; int o = 0, nrTS; Int16[] bestPossLevels = new Int16[7]; // best possible levels for (int f = 0; f < choosenF.Count; f++) { if (considerChosenCreature && chosenCS == Sex.Female && choosenF[f] != chosenCreature) { continue; } for (int m = 0; m < choosenM.Count; m++) { if (considerChosenCreature && chosenCS == Sex.Male && choosenM[m] != chosenCreature) { continue; } combinedTops[0].Add(f); combinedTops[1].Add(m); t = 0; nrTS = 0; // number of possible top-stats eTS = 0; // expected number of top stats for (int s = 0; s < 7; s++) { bestPossLevels[s] = 0; int higherLevel = Math.Max(choosenF[f].levelsWild[s], choosenM[m].levelsWild[s]); int lowerlevel = Math.Min(choosenF[f].levelsWild[s], choosenM[m].levelsWild[s]); if (higherLevel < 0) { higherLevel = 0; } if (lowerlevel < 0) { lowerlevel = 0; } tt = statWeights[s] * (0.7 * higherLevel + 0.3 * lowerlevel) / 40; if (tt > 0) { if (breedingMode == BreedingMode.TopStatsLucky) { if (choosenF[f].topBreedingStats[s] || choosenM[m].topBreedingStats[s]) { if (choosenF[f].topBreedingStats[s] && choosenM[m].topBreedingStats[s]) { tt *= 1.142; } } else if (bestLevels[s] > 0) { tt *= .01; } } else if (breedingMode == BreedingMode.TopStatsConservative && bestLevels[s] > 0) { bestPossLevels[s] = (Int16)Math.Max(choosenF[f].levelsWild[s], choosenM[m].levelsWild[s]); tt *= .01; if (choosenF[f].topBreedingStats[s] || choosenM[m].topBreedingStats[s]) { nrTS++; eTS += ((choosenF[f].topBreedingStats[s] && choosenM[m].topBreedingStats[s]) ? 1 : 0.7); } } } t += tt; } if (breedingMode == BreedingMode.TopStatsConservative) { if (choosenF[f].topStatsCountBP < nrTS && choosenM[m].topStatsCountBP < nrTS) { t += eTS; } else { t += .1 * eTS; } // check if the best possible stat outcome already exists in a male bool maleExists = false; foreach (Creature cr in choosenM) { maleExists = true; for (int s = 0; s < 7; s++) { if (cr.levelsWild[s] != bestPossLevels[s]) { maleExists = false; break; } } if (maleExists) { break; } } if (maleExists) { t *= .4; // another male with the same stats is not worth much, the mating-cooldown of males is short. } else { // check if the best possible stat outcome already exists in a female bool femaleExists = false; foreach (Creature cr in choosenF) { femaleExists = true; for (int s = 0; s < 7; s++) { if (cr.levelsWild[s] != bestPossLevels[s]) { femaleExists = false; break; } } if (femaleExists) { break; } } if (femaleExists) { t *= .8; // another female with the same stats may be useful, but not so much in conservative breeding } } //t *= 2; // scale conservative mode as it rather displays improvement, but only scarcely } comboScore.Add(t * 1.25); comboOrder.Add(o++); } } comboOrder = comboOrder.OrderByDescending(c => comboScore[c]).ToList(); double minCombo = comboScore.Min(); if (minCombo < 0) { for (int i = 0; i < comboScore.Count; i++) { comboScore[i] -= minCombo; } } // draw best parents int row = 0; // scrolloffsets int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; PedigreeCreature pc; Bitmap bm; Graphics g; PictureBox pb; for (int i = 0; i < creatureCollection.maxBreedingSuggestions && i < comboOrder.Count; i++) { if (2 * i < pcs.Count) { pcs[2 * i].Creature = choosenF[combinedTops[0][comboOrder[i]]]; pcs[2 * i].enabledColorRegions = enabledColorRegions; pcs[2 * i].comboId = comboOrder[i]; pcs[2 * i].Show(); } else { pc = new PedigreeCreature(choosenF[combinedTops[0][comboOrder[i]]], enabledColorRegions, comboOrder[i]); pc.Location = new Point(10 + xS, 5 + 35 * row + yS); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BPRecalc += new PedigreeCreature.BPRecalcEventHandler(recalculateBreedingPlan); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pc.exportToClipboard += new PedigreeCreature.ExportToClipboardEventHandler(exportToClipboard); panelCombinations.Controls.Add(pc); pcs.Add(pc); } if (2 * i + 1 < pcs.Count) { pcs[2 * i + 1].Creature = choosenM[combinedTops[1][comboOrder[i]]]; pcs[2 * i + 1].enabledColorRegions = enabledColorRegions; pcs[2 * i + 1].comboId = comboOrder[i]; pcs[2 * i + 1].Show(); } else { pc = new PedigreeCreature(choosenM[combinedTops[1][comboOrder[i]]], enabledColorRegions, comboOrder[i]); pc.Location = new Point(397 + xS, 5 + 35 * row + yS); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BPRecalc += new PedigreeCreature.BPRecalcEventHandler(recalculateBreedingPlan); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pc.exportToClipboard += new PedigreeCreature.ExportToClipboardEventHandler(exportToClipboard); panelCombinations.Controls.Add(pc); pcs.Add(pc); } // draw score if (i < pbs.Count) { pb = pbs[i]; pbs[i].Show(); } else { pb = new PictureBox(); pb.Size = new Size(87, 15); pb.Location = new Point(308 + xS, 19 + 35 * row + yS); pbs.Add(pb); panelCombinations.Controls.Add(pb); } bm = new Bitmap(pb.Width, pb.Height); g = Graphics.FromImage(bm); g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; Brush br = new SolidBrush(Utils.getColorFromPercent((int)(comboScore[comboOrder[i]] * 12.5), 0.5)); Brush brd = new SolidBrush(Utils.getColorFromPercent((int)(comboScore[comboOrder[i]] * 12.5), -.2)); g.FillRectangle(brd, 0, 5, 87, 5); g.FillRectangle(brd, 20, 0, 47, 15); g.FillRectangle(br, 1, 6, 85, 3); g.FillRectangle(br, 21, 1, 45, 13); g.DrawString(comboScore[comboOrder[i]].ToString("N4"), new System.Drawing.Font("Microsoft Sans Serif", 8.25f), new System.Drawing.SolidBrush(System.Drawing.Color.Black), 24, 2); pb.Image = bm; g.Dispose(); row++; } // hide unused controls for (int i = comboOrder.Count; i < creatureCollection.maxBreedingSuggestions && 2 * i + 1 < pcs.Count && i < pbs.Count; i++) { pcs[2 * i].Hide(); pcs[2 * i + 1].Hide(); pbs[i].Hide(); } if (updateBreedingData) { setBreedingData(currentSpecies); } if (comboOrder.Count > 0) { setParents(comboOrder[0]); // if breeding mode is conservative and a creature with top-stats already exists, the scoring might seem off if (breedingMode == BreedingMode.TopStatsConservative) { bool bestCreatureAlreadyAvailable = true; Creature bestCreature = null; List <Creature> choosenFemalesAndMales = choosenF.Concat(choosenM).ToList(); bool noWildSpeedLevels = Values.V.species[speciesIndex].NoImprintingForSpeed == true; foreach (Creature cr in choosenFemalesAndMales) { bestCreatureAlreadyAvailable = true; for (int s = 0; s < 7; s++) { if (!cr.topBreedingStats[s] && !(s == 6 && noWildSpeedLevels)) { bestCreatureAlreadyAvailable = false; break; } } if (bestCreatureAlreadyAvailable) { bestCreature = cr; break; } } if (bestCreatureAlreadyAvailable) { if (MessageBox.Show("There is already a creature in your library that has all the available top-stats (" + bestCreature.name + " " + Utils.sexSymbol(bestCreature.gender) + ")." + "\nThe currently selected conservative-breeding-mode might show some suggestions that may seem non-optimal.\n\n" + "Change the breeding-mode to \"High Stats\" for better suggestions.\nDo you want to change the breeding-mode to \"High Stats\"?", "Top-creature already available", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) { radioButtonBPHighStats.Checked = true; } } } } else { setParents(-1); } } else { // hide unused controls pedigreeCreature1.Hide(); pedigreeCreature2.Hide(); labelBreedingScore.Hide(); for (int i = 0; i < creatureCollection.maxBreedingSuggestions && 2 * i + 1 < pcs.Count && i < pbs.Count; i++) { pcs[2 * i].Hide(); pcs[2 * i + 1].Hide(); pbs[i].Hide(); } labelInfo.Text = "No possible pairings found for " + currentSpecies + ". Make sure at least one female and male are available in your library and that you didn't exclude all possible creatures via the tag-selector."; labelInfo.Visible = true; if (updateBreedingData) { setBreedingData(currentSpecies); } } Cursor.Current = Cursors.Default; ResumeLayout(); }
private void AsyncCalculateBreedingScoresAndDisplayPairs(BreedingMode breedingMode, bool updateBreedingData = false) { SuspendLayout(); this.SuspendDrawing(); Cursor.Current = Cursors.WaitCursor; ClearControls(); // chosen Creature (only consider this one for its sex) bool considerChosenCreature = chosenCreature != null; // filter by tags int crCountF = females.Count; int crCountM = males.Count; List <Creature> chosenF, chosenM; if (considerChosenCreature && chosenCreature.sex == Sex.Female) { chosenF = new List <Creature>(); } else { chosenF = filterByTags(females); } if (considerChosenCreature && chosenCreature.sex == Sex.Male) { chosenM = new List <Creature>(); } else { chosenM = filterByTags(males); } bool creaturesTagFilteredOut = (crCountF != chosenF.Count) || (crCountM != chosenM.Count); crCountF = chosenF.Count; crCountM = chosenM.Count; if (nudMutationLimit.Value >= 0) { chosenF = chosenF.Where(c => c.mutationsMaternal + c.mutationsPaternal <= nudMutationLimit.Value).ToList(); chosenM = chosenM.Where(c => c.mutationsMaternal + c.mutationsPaternal <= nudMutationLimit.Value).ToList(); } bool creaturesMutationsFilteredOut = (crCountF != chosenF.Count) || (crCountM != chosenM.Count); if (considerChosenCreature) { if (chosenCreature.sex == Sex.Female) { chosenF.Add(chosenCreature); } if (chosenCreature.sex == Sex.Male) { chosenM.Add(chosenCreature); } } labelTitle.Text = currentSpecies + (considerChosenCreature ? " (only pairings with \"" + chosenCreature.name + "\")" : ""); if (considerChosenCreature && (chosenCreature.neutered || chosenCreature.status != CreatureStatus.Available)) { labelTitle.Text += "! Breeding not possible ! (" + (chosenCreature.neutered ? "neutered" : "not available") + ")"; } string warningText = ""; if (creaturesTagFilteredOut) { warningText = "Some creatures are filtered out due to their tags"; } if (creaturesMutationsFilteredOut) { warningText += (warningText.Length > 0 ? " or mutations" : "Some creatures are filtered out due to their mutations"); } if (warningText.Length > 0) { setMessageLabelText(warningText + ".\nThe top-stats shown here might not be the top-stats of your entire library", MessageBoxIcon.Warning); } var combinedCreatures = new List <Creature>(chosenF); combinedCreatures.AddRange(chosenM); // determine top-stats for choosen creatures. int[] topStats = new int[7]; foreach (Creature c in combinedCreatures) { for (int s = 0; s < 7; s++) { if (c.levelsWild[s] > topStats[s]) { topStats[s] = c.levelsWild[s]; } } } if (Properties.Settings.Default.IgnoreSexInBreedingPlan) { chosenF = new List <Creature>(combinedCreatures); chosenM = new List <Creature>(combinedCreatures); } if (chosenF.Count > 0 && chosenM.Count > 0) { pedigreeCreature1.Show(); pedigreeCreature2.Show(); labelBreedingScore.Show(); breedingPairs.Clear(); double t = 0, tt = 0, eTS; int nrTS; Int16[] bestPossLevels = new Int16[7]; // best possible levels foreach (Creature female in chosenF) { foreach (Creature male in chosenM) { if (male == female) { continue; // happens if Properties.Settings.Default.IgnoreSexInBreedingPlan (when using S+ mutator) } t = 0; nrTS = 0; // number of possible top-stats eTS = 0; // expected number of top stats for (int s = 0; s < 7; s++) { bestPossLevels[s] = 0; int higherLevel = Math.Max(female.levelsWild[s], male.levelsWild[s]); int lowerlevel = Math.Min(female.levelsWild[s], male.levelsWild[s]); if (higherLevel < 0) { higherLevel = 0; } if (lowerlevel < 0) { lowerlevel = 0; } tt = statWeights[s] * (0.7 * higherLevel + 0.3 * lowerlevel) / 40; if (tt > 0) { if (breedingMode == BreedingMode.TopStatsLucky) { if (female.levelsWild[s] == topStats[s] || male.levelsWild[s] == topStats[s]) { if (female.levelsWild[s] == topStats[s] && male.levelsWild[s] == topStats[s]) { tt *= 1.142; } } else if (bestLevels[s] > 0) { tt *= .01; } } else if (breedingMode == BreedingMode.TopStatsConservative && bestLevels[s] > 0) { bestPossLevels[s] = (Int16)Math.Max(female.levelsWild[s], male.levelsWild[s]); tt *= .01; if (female.levelsWild[s] == topStats[s] || male.levelsWild[s] == topStats[s]) { nrTS++; eTS += ((female.levelsWild[s] == topStats[s] && male.levelsWild[s] == topStats[s]) ? 1 : 0.7); } } } t += tt; } if (breedingMode == BreedingMode.TopStatsConservative) { if (female.topStatsCountBP < nrTS && male.topStatsCountBP < nrTS) { t += eTS; } else { t += .1 * eTS; } // check if the best possible stat outcome already exists in a male bool maleExists = false; foreach (Creature cr in chosenM) { maleExists = true; for (int s = 0; s < 7; s++) { if (cr.levelsWild[s] != bestPossLevels[s]) { maleExists = false; break; } } if (maleExists) { break; } } if (maleExists) { t *= .4; // another male with the same stats is not worth much, the mating-cooldown of males is short. } else { // check if the best possible stat outcome already exists in a female bool femaleExists = false; foreach (Creature cr in chosenF) { femaleExists = true; for (int s = 0; s < 7; s++) { if (cr.levelsWild[s] != bestPossLevels[s]) { femaleExists = false; break; } } if (femaleExists) { break; } } if (femaleExists) { t *= .8; // another female with the same stats may be useful, but not so much in conservative breeding } } //t *= 2; // scale conservative mode as it rather displays improvement, but only scarcely } breedingPairs.Add(new BreedingPair(female, male, t * 1.25)); } } breedingPairs = breedingPairs.OrderByDescending(p => p.BreedingScore).ToList(); double minScore = (breedingPairs.Count > 0 ? breedingPairs[breedingPairs.Count - 1].BreedingScore : 0); if (minScore < 0) { foreach (BreedingPair bp in breedingPairs) { bp.BreedingScore -= minScore; } } // draw best parents int row = 0; // scrolloffsets int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; PedigreeCreature pc; Bitmap bm; Graphics g; PictureBox pb; for (int i = 0; i < breedingPairs.Count && i < creatureCollection.maxBreedingSuggestions; i++) { if (2 * i < pcs.Count) { pcs[2 * i].Creature = breedingPairs[i].Female; pcs[2 * i].enabledColorRegions = enabledColorRegions; pcs[2 * i].comboId = i; pcs[2 * i].Show(); } else { pc = new PedigreeCreature(breedingPairs[i].Female, enabledColorRegions, i); //pc.Location = new Point(10 + xS, 5 + 35 * row + yS); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BPRecalc += new PedigreeCreature.BPRecalcEventHandler(recalculateBreedingPlan); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pc.exportToClipboard += new PedigreeCreature.ExportToClipboardEventHandler(exportToClipboard); flowLayoutPanelPairs.Controls.Add(pc); pcs.Add(pc); } // draw score if (i < pbs.Count) { pb = pbs[i]; pbs[i].Show(); } else { pb = new PictureBox { Size = new Size(87, 35) }; //pb.Location = new Point(308 + xS, 19 + 35 * row + yS); pbs.Add(pb); flowLayoutPanelPairs.Controls.Add(pb); } if (2 * i + 1 < pcs.Count) { pcs[2 * i + 1].Creature = breedingPairs[i].Male; pcs[2 * i + 1].enabledColorRegions = enabledColorRegions; pcs[2 * i + 1].comboId = i; pcs[2 * i + 1].Show(); } else { pc = new PedigreeCreature(breedingPairs[i].Male, enabledColorRegions, i); //pc.Location = new Point(397 + xS, 5 + 35 * row + yS); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BPRecalc += new PedigreeCreature.BPRecalcEventHandler(recalculateBreedingPlan); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pc.exportToClipboard += new PedigreeCreature.ExportToClipboardEventHandler(exportToClipboard); flowLayoutPanelPairs.Controls.Add(pc); flowLayoutPanelPairs.SetFlowBreak(pc, true); pcs.Add(pc); } bm = new Bitmap(pb.Width, pb.Height); using (g = Graphics.FromImage(bm)) { g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; Brush br = new SolidBrush(Utils.getColorFromPercent((int)(breedingPairs[i].BreedingScore * 12.5), 0.5)); Brush brd = new SolidBrush(Utils.getColorFromPercent((int)(breedingPairs[i].BreedingScore * 12.5), -.2)); g.FillRectangle(brd, 0, 15, 87, 5); g.FillRectangle(brd, 20, 10, 47, 15); g.FillRectangle(br, 1, 16, 85, 3); g.FillRectangle(br, 21, 11, 45, 13); g.DrawString(breedingPairs[i].BreedingScore.ToString("N4"), new System.Drawing.Font("Microsoft Sans Serif", 8.25f), new System.Drawing.SolidBrush(System.Drawing.Color.Black), 24, 12); pb.Image = bm; } row++; } // hide unused controls for (int i = breedingPairs.Count; i < creatureCollection.maxBreedingSuggestions && 2 * i + 1 < pcs.Count && i < pbs.Count; i++) { pcs[2 * i].Hide(); pcs[2 * i + 1].Hide(); pbs[i].Hide(); } if (updateBreedingData) { setBreedingData(currentSpecies); } if (breedingPairs.Count > 0) { setParents(0); // if breeding mode is conservative and a creature with top-stats already exists, the scoring might seem off if (breedingMode == BreedingMode.TopStatsConservative) { bool bestCreatureAlreadyAvailable = true; Creature bestCreature = null; List <Creature> choosenFemalesAndMales = chosenF.Concat(chosenM).ToList(); bool noWildSpeedLevels = Values.V.species[speciesIndex].NoImprintingForSpeed == true; foreach (Creature cr in choosenFemalesAndMales) { bestCreatureAlreadyAvailable = true; for (int s = 0; s < 7; s++) { if (!cr.topBreedingStats[s] && !(s == 6 && noWildSpeedLevels)) { bestCreatureAlreadyAvailable = false; break; } } if (bestCreatureAlreadyAvailable) { bestCreature = cr; break; } } if (bestCreatureAlreadyAvailable) { setMessageLabelText("There is already a creature in your library that has all the available top-stats (" + bestCreature.name + " " + Utils.sexSymbol(bestCreature.sex) + ")." + "\nThe currently selected conservative-breeding-mode might show some suggestions that may seem non-optimal.\n" + "Change the breeding-mode to \"High Stats\" for better suggestions.", MessageBoxIcon.Warning); } } } else { setParents(-1); } } else { // hide unused controls pedigreeCreature1.Hide(); pedigreeCreature2.Hide(); labelBreedingScore.Hide(); for (int i = 0; i < creatureCollection.maxBreedingSuggestions && 2 * i + 1 < pcs.Count && i < pbs.Count; i++) { pcs[2 * i].Hide(); pcs[2 * i + 1].Hide(); pbs[i].Hide(); } labelInfo.Text = "No possible pairings found for " + currentSpecies + ". Make sure at least one female and male are available in your library and that you didn't exclude all possible creatures via the tag-selector."; labelInfo.Visible = true; if (updateBreedingData) { setBreedingData(currentSpecies); } } Cursor.Current = Cursors.Default; this.ResumeDrawing(); ResumeLayout(); }
public void setLevels(int[] levels) { if (levels != null && levels.Length > 6 && maxR > 5) { Bitmap bmp = new Bitmap(Width, Height); Graphics g = Graphics.FromImage(bmp); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; double angleSeven = Math.PI / 3.5; double offset = Math.PI / 2; for (int s = 0; s < 7; s++) { if (levels[s] != oldLevels[s]) { oldLevels[s] = levels[s]; int r = levels[s] * maxR / maxLevel; if (r < 0) { r = 0; } if (r > maxR) { r = maxR; } double angle = angleSeven * s - offset; ps[s] = new Point(xm + (int)(r * Math.Cos(angle)), ym + (int)(r * Math.Sin(angle))); } } g.FillEllipse(grBrushBG, xm - maxR, ym - maxR, 2 * maxR + 1, 2 * maxR + 1); Pen penL = new Pen(Color.FromArgb(128, 255, 255, 255)); g.FillPolygon(grBrushFG, ps.ToArray()); g.DrawPolygon(penL, ps.ToArray()); double stepFactor = (double)step / maxLevel; for (int r = 0; r < 5; r++) { g.DrawEllipse(new Pen(Utils.getColorFromPercent((int)(100 * r * stepFactor), -0.4)), (int)(xm - maxR * r * stepFactor), (int)(ym - maxR * r * stepFactor), (int)(2 * maxR * r * stepFactor + 1), (int)(2 * maxR * r * stepFactor + 1)); } g.DrawEllipse(new Pen(Utils.getColorFromPercent(100, -0.4)), xm - maxR, ym - maxR, 2 * maxR + 1, 2 * maxR + 1); Pen pen = new Pen(Color.Black); for (int s = 0; s < 7; s++) { pen.Width = 1; pen.Color = Color.Gray; g.DrawLine(pen, xm, ym, maxPs[s].X, maxPs[s].Y); Color cl = Utils.getColorFromPercent(100 * levels[s] / maxLevel); pen.Color = cl; pen.Width = 3; g.DrawLine(pen, xm, ym, ps[s].X, ps[s].Y); Brush b = new SolidBrush(cl); g.FillEllipse(b, ps[s].X - 4, ps[s].Y - 4, 8, 8); g.DrawEllipse(penL, ps[s].X - 4, ps[s].Y - 4, 8, 8); b.Dispose(); } for (int r = 1; r < 5; r++) { g.DrawString((step * r).ToString("N0"), new System.Drawing.Font("Microsoft Sans Serif", 8f), new System.Drawing.SolidBrush(Color.FromArgb(190, 255, 255, 255)), xm - 8, ym - 6 + r * maxR / 5); } g.DrawString((maxLevel).ToString("N0"), new System.Drawing.Font("Microsoft Sans Serif", 8f), new System.Drawing.SolidBrush(Color.FromArgb(190, 255, 255, 255)), xm - 8, ym - 11 + maxR); g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; for (int s = 0; s < 7; s++) { double angle = angleSeven * s - offset; g.DrawString(Utils.statName(s, true), new System.Drawing.Font("Microsoft Sans Serif", 8f), new System.Drawing.SolidBrush(Color.Black), xm - 9 + (int)((maxR + 10) * Math.Cos(angle)), ym - 5 + (int)((maxR + 10) * Math.Sin(angle))); } g.Dispose(); Image = bmp; } }
public void drawBestParents(BreedingMode breedingMode, bool updateBreedingData = false) { SuspendLayout(); Cursor.Current = Cursors.WaitCursor; ClearControls(); // chosen Creature (only consider this one for its gender) bool considerChosenCreature = chosenCreature != null; Gender chosenCG = (considerChosenCreature ? chosenCreature.gender : Gender.Unknown); labelTitle.Text = currentSpecies + (considerChosenCreature ? " (only pairings with \"" + chosenCreature.name + "\")" : ""); if (females != null && males != null && females.Count > 0 && males.Count > 0) { combinedTops[0].Clear(); combinedTops[1].Clear(); comboScore.Clear(); comboOrder.Clear(); double t = 0, tt = 0, pTS = 1; int o = 0, nrTS = 0; Int16[] bestPossLevels = new Int16[7]; // best possible levels for (int f = 0; f < females.Count; f++) { if (considerChosenCreature && chosenCG == Gender.Female && females[f] != chosenCreature) { continue; } for (int m = 0; m < males.Count; m++) { if (considerChosenCreature && chosenCG == Gender.Male && males[m] != chosenCreature) { continue; } combinedTops[0].Add(f); combinedTops[1].Add(m); t = 0; nrTS = 0; // number of possible top-stats pTS = 1; for (int s = 0; s < 7; s++) { bestPossLevels[s] = 0; tt = statWeights[s] * (0.7 * Math.Max(females[f].levelsWild[s], males[m].levelsWild[s]) + 0.3 * Math.Min(females[f].levelsWild[s], males[m].levelsWild[s])) / 40; if (tt <= 0) { tt = 0; } else if (breedingMode == BreedingMode.TopStatsLucky) { if (females[f].topBreedingStats[s] || males[m].topBreedingStats[s]) { if (females[f].topBreedingStats[s] && males[m].topBreedingStats[s]) { tt *= 1.142; } } else if (bestLevels[s] > 0) { tt *= .01; } } else if (breedingMode == BreedingMode.TopStatsConservative && bestLevels[s] > 0) { bestPossLevels[s] = (Int16)Math.Max(females[f].levelsWild[s], males[m].levelsWild[s]); tt *= .01; if (females[f].topBreedingStats[s] || males[m].topBreedingStats[s]) { nrTS++; pTS *= ((females[f].topBreedingStats[s] && males[m].topBreedingStats[s]) ? 1 : 0.7); } } t += tt; } if (breedingMode == BreedingMode.TopStatsConservative) { if (females[f].topStatsCountBP < nrTS && males[m].topStatsCountBP < nrTS) { t += nrTS * pTS; } else { t += .1 * nrTS * pTS; } // check if the best possible stat outcome already exists in a male bool maleExists = false; foreach (Creature cr in males) { maleExists = true; for (int s = 0; s < 7; s++) { if (cr.levelsWild[s] != bestPossLevels[s]) { maleExists = false; break; } } if (maleExists) { break; } } if (maleExists) { t *= .2; // another male with the same stats is not worth much } else { // check if the best possible stat outcome already exists in a female bool femaleExists = false; foreach (Creature cr in females) { femaleExists = true; for (int s = 0; s < 7; s++) { if (cr.levelsWild[s] != bestPossLevels[s]) { femaleExists = false; break; } } if (femaleExists) { break; } } if (femaleExists) { t *= .5; // another female with the same stats may be useful, but not so much in conservative breeding } } t *= 2; // scale conservative mode as it rather displays improvement, but only scarcely } comboScore.Add(t * 1.25); comboOrder.Add(o++); } } comboOrder = comboOrder.OrderByDescending(c => comboScore[c]).ToList(); // draw best parents int row = 0; // scrolloffsets int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; PedigreeCreature pc; Bitmap bm; Graphics g; PictureBox pb; for (int i = 0; i < maxSuggestions && i < comboOrder.Count; i++) { pc = new PedigreeCreature(females[combinedTops[0][comboOrder[i]]], enabledColorRegions, comboOrder[i]); pc.Location = new Point(10 + xS, 5 + 35 * row + yS); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BPRecalc += new BPRecalcEventHandler(BPRecalc); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); panelCombinations.Controls.Add(pc); pcs.Add(pc); pc = new PedigreeCreature(males[combinedTops[1][comboOrder[i]]], enabledColorRegions, comboOrder[i]); pc.Location = new Point(350 + xS, 5 + 35 * row + yS); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BPRecalc += new BPRecalcEventHandler(BPRecalc); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); panelCombinations.Controls.Add(pc); pcs.Add(pc); // draw score pb = new PictureBox(); pbs.Add(pb); panelCombinations.Controls.Add(pb); pb.Size = new Size(87, 15); pb.Location = new Point(261 + xS, 19 + 35 * row + yS); bm = new Bitmap(pb.Width, pb.Height); g = Graphics.FromImage(bm); g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; Brush br = new SolidBrush(Utils.getColorFromPercent((int)(comboScore[comboOrder[i]] * 12.5), 0.5)); Brush brd = new SolidBrush(Utils.getColorFromPercent((int)(comboScore[comboOrder[i]] * 12.5), -.2)); g.FillRectangle(brd, 0, 5, 87, 5); g.FillRectangle(brd, 20, 0, 47, 15); g.FillRectangle(br, 1, 6, 85, 3); g.FillRectangle(br, 21, 1, 45, 13); g.DrawString(comboScore[comboOrder[i]].ToString("N4"), new System.Drawing.Font("Microsoft Sans Serif", 8.25f), new System.Drawing.SolidBrush(System.Drawing.Color.Black), 24, 2); pb.Image = bm; g.Dispose(); row++; } if (updateBreedingData) { setBreedingData(currentSpecies); } if (comboOrder.Count > 0) { setParents(comboOrder[0]); } else { setParents(-1); } } else { labelInfo.Text = "No possible pairings found for " + currentSpecies + ". Make sure at least one female and male are available in your library."; labelInfo.Visible = true; if (updateBreedingData) { setBreedingData(currentSpecies); } } Cursor.Current = Cursors.Default; ResumeLayout(); }