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(); }
/// <summary> /// call this function to create the pedigreeCreature-Elements /// </summary> public void createPedigree() { // clear old pedigreeCreatures ClearControls(); if (creature != null) { SuspendLayout(); bool isGlowSpecies = Values.V.IsGlowSpecies(creature.Species?.name); pedigreeCreature1.IsGlowSpecies = isGlowSpecies; int leftBorder = 40; int pedigreeElementWidth = 325; int margin = 10; lbPedigreeEmpty.Visible = false; // create ancestors createParentsChild(creature, leftBorder + pedigreeElementWidth + margin, 60, true, true); if (creature.Mother != null) { if (createParentsChild(creature.Mother, leftBorder, 20)) { lines[1].Add(new[] { leftBorder + pedigreeElementWidth, 79, leftBorder + pedigreeElementWidth + margin, 79 }); } } if (creature.Father != null) { if (createParentsChild(creature.Father, leftBorder + 2 * (pedigreeElementWidth + margin), 20)) { lines[1].Add(new[] { leftBorder + 2 * pedigreeElementWidth + 2 * margin, 79, leftBorder + 2 * pedigreeElementWidth + margin, 159 }); } } // create descendants int row = 0; // scrolloffsets int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; foreach (Creature c in children) { PedigreeCreature pc = new PedigreeCreature(c, enabledColorRegions) { Location = new Point(leftBorder + xS, 200 + 35 * row + yS) }; for (int s = 0; s < PedigreeCreature.displayedStats.Length; s++) { int si = PedigreeCreature.displayedStats[s]; if (creature.valuesDom[si] > 0 && creature.levelsWild[si] >= 0 && creature.levelsWild[si] == c.levelsWild[si]) { lines[0].Add(new[] { leftBorder + 38 + 29 * s, 200 + 35 * row + 6, leftBorder + 38 + 29 * s, 200 + 35 * row + 15, 0, 0 }); } } pc.CreatureClicked += CreatureClicked; pc.CreatureEdit += CreatureEdit; pc.BestBreedingPartners += BestBreedingPartners; pc.exportToClipboard += exportToClipboard; splitContainer1.Panel2.Controls.Add(pc); pcs.Add(pc); row++; } pictureBox.Image = CreatureColored.getColoredCreature(creature.colors, creature.Species, enabledColorRegions, 256); Invalidate(); ResumeLayout(); } else { noCreatureSelected(); } }
private bool createParentsChild(Creature creature, int x, int y, bool drawWithNoParents = false, bool highlightCreature = false) { if (creature != null && (drawWithNoParents || creature.Mother != null || creature.Father != null)) { // scrolloffset for control-locations (not for lines) int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; // creature PedigreeCreature pc = new PedigreeCreature(creature, enabledColorRegions); if (highlightCreature) { pc.highlight = true; } pc.Location = new Point(x + xS, y + yS + 40); splitContainer1.Panel2.Controls.Add(pc); pc.CreatureClicked += CreatureClicked; pc.CreatureEdit += CreatureEdit; pc.BestBreedingPartners += BestBreedingPartners; pc.exportToClipboard += exportToClipboard; pcs.Add(pc); // mother if (creature.Mother != null) { pc = new PedigreeCreature(creature.Mother, enabledColorRegions) { Location = new Point(x + xS, y + yS) }; splitContainer1.Panel2.Controls.Add(pc); pc.CreatureClicked += CreatureClicked; pc.CreatureEdit += CreatureEdit; pc.BestBreedingPartners += BestBreedingPartners; pc.exportToClipboard += exportToClipboard; pcs.Add(pc); } // father if (creature.Father != null) { pc = new PedigreeCreature(creature.Father, enabledColorRegions) { Location = new Point(x + xS, y + yS + 80) }; splitContainer1.Panel2.Controls.Add(pc); pc.CreatureClicked += CreatureClicked; pc.CreatureEdit += CreatureEdit; pc.BestBreedingPartners += BestBreedingPartners; pc.exportToClipboard += exportToClipboard; pcs.Add(pc); } // gene-inheritance-lines // better: if father < mother: 1, if mother < father: -1 for (int s = 0; s < PedigreeCreature.displayedStats.Length; s++) { int si = PedigreeCreature.displayedStats[s]; if (creature.valuesDom[si] <= 0) { continue; // don't display arrows for non used stats } int better = 0; if (creature.Mother != null && creature.Father != null) { if (creature.Mother.levelsWild[si] < creature.Father.levelsWild[si]) { better = -1; } else if (creature.Mother.levelsWild[si] > creature.Father.levelsWild[si]) { better = 1; } } // offspring can have stats that are up to 2 levels higher due to mutations. currently there are no decreasing levels due to mutations if (creature.Mother != null && creature.levelsWild[si] >= 0 && (creature.levelsWild[si] == creature.Mother.levelsWild[si] || creature.levelsWild[si] == creature.Mother.levelsWild[si] + 2)) { lines[0].Add(new[] { 38 + x + 29 * s, y + 33, 38 + x + 29 * s, y + 42, (better == -1 ? 1 : 2), (creature.levelsWild[si] > creature.Mother.levelsWild[si] ? 1 : 0) }); } if (creature.Father != null && creature.levelsWild[si] >= 0 && (creature.levelsWild[si] == creature.Father.levelsWild[si] || creature.levelsWild[si] == creature.Father.levelsWild[si] + 2)) { lines[0].Add(new[] { 38 + x + 29 * s, y + 83, 38 + x + 29 * s, y + 74, (better == 1 ? 1 : 2), (creature.levelsWild[si] > creature.Father.levelsWild[si] ? 1 : 0) }); } } return(true); } return(false); }
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(); }
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(); }
/// <summary> /// Creates the pedigree with creature controls. /// </summary> private void CreatePedigree() { // clear old pedigreeCreatures ClearControls(); if (_selectedCreature == null) { NoCreatureSelected(); return; } SuspendLayout(); pedigreeCreature1.SetCustomStatNames(_selectedCreature?.Species?.statNames); const int leftBorder = 40; const int pedigreeElementWidth = 325; const int margin = 10; lbPedigreeEmpty.Visible = false; // create ancestors CreateParentsChild(_selectedCreature, leftBorder + pedigreeElementWidth + margin, 60, true, true); if (_selectedCreature.Mother != null) { if (CreateParentsChild(_selectedCreature.Mother, leftBorder, 20)) { _lines[1].Add(new[] { leftBorder + pedigreeElementWidth, 79, leftBorder + pedigreeElementWidth + margin, 79 }); } } if (_selectedCreature.Father != null) { if (CreateParentsChild(_selectedCreature.Father, leftBorder + 2 * (pedigreeElementWidth + margin), 20)) { _lines[1].Add(new[] { leftBorder + 2 * pedigreeElementWidth + 2 * margin, 79, leftBorder + 2 * pedigreeElementWidth + margin, 159 }); } } // create descendants int row = 0; // scrolloffsets int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; foreach (Creature c in _creatureChildren) { PedigreeCreature pc = new PedigreeCreature(c, _enabledColorRegions) { Location = new Point(leftBorder + xS, 200 + 35 * row + yS) }; for (int s = 0; s < PedigreeCreature.displayedStatsCount; s++) { int si = PedigreeCreature.displayedStats[s]; if (_selectedCreature.valuesDom[si] > 0 && _selectedCreature.levelsWild[si] >= 0 && _selectedCreature.levelsWild[si] == c.levelsWild[si]) { _lines[0].Add(new[] { leftBorder + 38 + 29 * s, 200 + 35 * row + 6, leftBorder + 38 + 29 * s, 200 + 35 * row + 15, 0, 0 }); } } pc.CreatureClicked += CreatureClicked; pc.CreatureEdit += CreatureEdit; pc.BestBreedingPartners += BestBreedingPartners; pc.ExportToClipboard += ExportToClipboard; splitContainer1.Panel2.Controls.Add(pc); _pcs.Add(pc); row++; } pictureBox.Image = CreatureColored.GetColoredCreature(_selectedCreature.colors, _selectedCreature.Species, _enabledColorRegions, 256, creatureSex: _selectedCreature.sex); pictureBox.Visible = true; Invalidate(); 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(); }
private bool createParentsChild(Creature creature, int x, int y, bool drawWithNoParents = false, bool highlightCreature = false) { if (creature != null && (drawWithNoParents || creature.Mother != null || creature.Father != null)) { // scrolloffset for control-locations (not for lines) int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; // creature PedigreeCreature pc = new PedigreeCreature(creature, enabledColorRegions); if (highlightCreature) { pc.highlight = true; } pc.Location = new Point(x + xS, y + yS + 40); Controls.Add(pc); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pc.exportToClipboard += new PedigreeCreature.ExportToClipboardEventHandler(exportToClipboard); pcs.Add(pc); // mother if (creature.Mother != null) { pc = new PedigreeCreature(creature.Mother, enabledColorRegions); pc.Location = new Point(x + xS, y + yS); Controls.Add(pc); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pc.exportToClipboard += new PedigreeCreature.ExportToClipboardEventHandler(exportToClipboard); pcs.Add(pc); } // father if (creature.Father != null) { pc = new PedigreeCreature(creature.Father, enabledColorRegions); pc.Location = new Point(x + xS, y + yS + 80); Controls.Add(pc); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pc.exportToClipboard += new PedigreeCreature.ExportToClipboardEventHandler(exportToClipboard); pcs.Add(pc); } // gene-inheritance-lines // better: if father < mother: 1, if mother < father: -1 int better; for (int s = 0; s < 7; s++) { better = 0; if (creature.Mother != null && creature.Father != null) { if (creature.Mother.levelsWild[s] < creature.Father.levelsWild[s]) { better = -1; } else if (creature.Mother.levelsWild[s] > creature.Father.levelsWild[s]) { better = 1; } } // offspring can have stats that are up to 2 levels higher due to mutations. currently there are no decreasing levels due to mutations if (creature.Mother != null && creature.levelsWild[s] >= 0 && (creature.levelsWild[s] == creature.Mother.levelsWild[s] || creature.levelsWild[s] == creature.Mother.levelsWild[s] + 2)) { lines[0].Add(new int[] { 38 + x + 28 * s, y + 33, 38 + x + 28 * s, y + 42, (better == -1 ? 1 : 2), (creature.levelsWild[s] > creature.Mother.levelsWild[s] ? 1 : 0) }); } if (creature.Father != null && creature.levelsWild[s] >= 0 && (creature.levelsWild[s] == creature.Father.levelsWild[s] || creature.levelsWild[s] == creature.Father.levelsWild[s] + 2)) { lines[0].Add(new int[] { 38 + x + 28 * s, y + 83, 38 + x + 28 * s, y + 74, (better == 1 ? 1 : 2), (creature.levelsWild[s] > creature.Father.levelsWild[s] ? 1 : 0) }); } } return(true); } return(false); }
/// <summary> /// call this function to create the pedigreeCreature-Elements /// </summary> public void createPedigree() { // clear old pedigreeCreatures ClearControls(); if (creature != null) { this.SuspendLayout(); int leftBorder = 200; lbPedigreeEmpty.Visible = false; // create ancestors createParentsChild(creature, leftBorder + 325, 60, true, true); if (creature.Mother != null) { if (createParentsChild(creature.Mother, leftBorder + 10, 20, false)) { lines[1].Add(new int[] { leftBorder + 306, 79, leftBorder + 325, 79 }); } } if (creature.Father != null) { if (createParentsChild(creature.Father, leftBorder + 640, 20, false)) { lines[1].Add(new int[] { leftBorder + 640, 79, leftBorder + 621, 159 }); } } // create descendants int row = 0; // scrolloffsets int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; foreach (Creature c in children) { PedigreeCreature pc = new PedigreeCreature(c, enabledColorRegions); pc.Location = new Point(leftBorder + 10 + xS, 200 + 35 * row + yS); for (int s = 0; s < 7; s++) { if (creature.levelsWild[s] >= 0 && creature.levelsWild[s] == c.levelsWild[s]) { lines[0].Add(new int[] { leftBorder + 10 + 38 + 28 * s, 200 + 35 * row + 6, leftBorder + 10 + 38 + 28 * s, 200 + 35 * row + 15, 0, 0 }); } } pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pc.exportToClipboard += new PedigreeCreature.ExportToClipboardEventHandler(exportToClipboard); Controls.Add(pc); pcs.Add(pc); row++; } pictureBox.Image = CreatureColored.getColoredCreature(creature.colors, creature.species, enabledColorRegions, 256); this.Invalidate(); this.ResumeLayout(); } else { noCreatureSelected(); } }
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(); }
/// <summary> /// call this function to create the pedigreeCreature-Elements /// </summary> public void createPedigree() { // clear old pedigreeCreatures ClearControls(); if (creature != null) { this.SuspendLayout(); labelEmptyInfo.Visible = false; // create ancestors createParentsChild(creature, 278, 60, true, true); if (creature.Mother != null) { if (createParentsChild(creature.Mother, 10, 20, false)) lines[1].Add(new int[] { 259, 79, 278, 79 }); } if (creature.Father != null) { if (createParentsChild(creature.Father, 546, 20, false)) lines[1].Add(new int[] { 546, 79, 527, 159 }); } // create descendants int row = 0; // scrolloffsets int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; foreach (Creature c in children) { PedigreeCreature pc = new PedigreeCreature(c, enabledColorRegions); pc.Location = new Point(10 + xS, 200 + 35 * row + yS); for (int s = 0; s < 7; s++) { if (creature.levelsWild[s] >= 0 && creature.levelsWild[s] == c.levelsWild[s]) lines[0].Add(new int[] { 10 + 38 + 28 * s, 200 + 35 * row + 6, 10 + 38 + 28 * s, 200 + 35 * row + 15, 0 }); } pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); Controls.Add(pc); pcs.Add(pc); row++; } pictureBox.Image = CreatureColored.getColoredCreature(creature.colors, creature.species, enabledColorRegions, 256); this.Invalidate(); this.ResumeLayout(); } else { noCreatureSelected(); } }
private bool createParentsChild(Creature creature, int x, int y, bool drawWithNoParents = false, bool highlightCreature = false) { if (creature != null && (drawWithNoParents || creature.Mother != null || creature.Father != null)) { // scrolloffset for control-locations (not for lines) int xS = AutoScrollPosition.X; int yS = AutoScrollPosition.Y; // creature PedigreeCreature pc = new PedigreeCreature(creature, enabledColorRegions); if (highlightCreature) pc.highlight = true; pc.Location = new Point(x + xS, y + yS + 40); Controls.Add(pc); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pcs.Add(pc); // mother if (creature.Mother != null) { pc = new PedigreeCreature(creature.Mother, enabledColorRegions); pc.Location = new Point(x + xS, y + yS); Controls.Add(pc); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pcs.Add(pc); } // father if (creature.Father != null) { pc = new PedigreeCreature(creature.Father, enabledColorRegions); pc.Location = new Point(x + xS, y + yS + 80); Controls.Add(pc); pc.CreatureClicked += new PedigreeCreature.CreatureChangedEventHandler(CreatureClicked); pc.CreatureEdit += new PedigreeCreature.CreatureEditEventHandler(CreatureEdit); pc.BestBreedingPartners += new PedigreeCreature.CreaturePartnerEventHandler(BestBreedingPartners); pcs.Add(pc); } // gene-inheritance-lines // better: if father < mother: 1, if mother < father: -1 int better; for (int s = 0; s < 7; s++) { better = 0; if (creature.Mother != null && creature.Father != null) { if (creature.Mother.levelsWild[s] < creature.Father.levelsWild[s]) better = -1; else if (creature.Mother.levelsWild[s] > creature.Father.levelsWild[s]) better = 1; } if (creature.Mother != null && creature.levelsWild[s] >= 0 && creature.levelsWild[s] == creature.Mother.levelsWild[s]) { lines[0].Add(new int[] { 38 + x + 28 * s, y + 33, 38 + x + 28 * s, y + 42, (better == -1 ? 1 : 2) }); } if (creature.Father != null && creature.levelsWild[s] >= 0 && creature.levelsWild[s] == creature.Father.levelsWild[s]) { lines[0].Add(new int[] { 38 + x + 28 * s, y + 83, 38 + x + 28 * s, y + 74, (better == 1 ? 1 : 2) }); } } return true; } return false; }