/// <summary> /// Find weakest neighbouring Micromon /// </summary> /// <param name="attacker">Attacking Micromon</param> /// <returns>The attack results on the weakest neighbouring Micromon, if all neighbours are of the same type, the default value is passed</returns> private ProbeResults FindWeakestNeighbour(Micromon attacker) { //Get all four potential targets Micromon[] targets = new Micromon[4]; targets[0] = this[Utils.Clamp(0, this.Size, attacker.X - 1), attacker.Y]; targets[1] = this[Utils.Clamp(0, this.Size, attacker.X + 1), attacker.Y]; targets[2] = this[attacker.X, Utils.Clamp(0, this.Size, attacker.Y - 1)]; targets[3] = this[attacker.X, Utils.Clamp(0, this.Size, attacker.Y + 1)]; //Filter out invalid targets List <Micromon> valid = new List <Micromon>(targets.Where(m => attacker.Pair != m.Pair)); //If no valid targets available, return default value if (valid.Count == 0) { return(new ProbeResults()); } //Find the valid target with the highest possible damage ProbeResults highest = CalculateDamage(attacker, valid[0]); for (int i = 1; i < valid.Count; i++) { ProbeResults current = CalculateDamage(attacker, valid[i]); if (current.damage > highest.damage) { highest = current; } } //Return the highest damage return(highest); }
/// <summary> /// Creates a new Grid of the specified size /// </summary> /// <param name="size">Size of the simulation Grid</param> /// <param name="worker">BackgroundWorker to report progress to</param> public Grid(int size, BackgroundWorker worker) { //Initialize data structures this.Size = size; this.grid = new Micromon[size, size]; List <Micromon> list = new List <Micromon>(size * size); //Loop through all coordinates for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { //Add new Micromon to each location Micromon mon = new Micromon(x, y); this.grid[y, x] = mon; list.Add(mon); worker.ReportProgress(0); } } //Sort Micromons by speed and setup LinkedList list.Sort(); this.attackList = new LinkedList <Micromon>(list); Micromon.SetupLinkedList(this.attackList); }
/// <summary> /// Calculates the effectiveness of a particular attacking type against a Pokemon /// </summary> /// <param name="attacking">Attacking type</param> /// <param name="defending">Defending Pokemon</param> /// <returns>The effectiveness of the move (ranging from 0 to 4)</returns> private static double Matchup(Type attacking, Micromon defending) { //If attacking type is none, return 0 if (attacking == Type.NONE) { return(0d); } //Calculate matchup for this attacking/defending type setup double effectiveness = matchup[(int)attacking, (int)defending.Type1]; if (defending.Type2 != Type.NONE) { effectiveness *= matchup[(int)attacking, (int)defending.Type2]; } return(effectiveness); }
/// <summary> /// Simulates a full round of attack and defending throughout the whole simulation Grid /// </summary> /// <param name="worker">BackgroundWorker to report the progress to</param> public void Simulate(BackgroundWorker worker) { //Loop through the full list for (LinkedListNode <Micromon> n = this.attackList.First; n != null; n = n.Next) { Micromon attacker = n.Value; //Find weakest neighbouring Micromon to attack ProbeResults result = FindWeakestNeighbour(attacker); Micromon target = result.target; //If there is a potential target, attack it, if it succumbs, take over it's spot if (target != null && !target.Defend(result.damage)) { n = target.TakenOver(attacker); } //Report progress (increment bar) worker.ReportProgress(0); } }
/// <summary> /// Creates a new ProbeResult of the given damage to the specified target /// </summary> /// <param name="damage">Total damage</param> /// <param name="target">Targeted Micromon</param> public ProbeResults(double damage, Micromon target) { this.damage = damage; this.target = target; }
/// <summary> /// Calculates potential damage whith a specified attacking and defending Micromon /// </summary> /// <param name="attacker">Attacking Micromon</param> /// <param name="defender">Defending Micromon</param> /// <returns>The results of the simulated attack</returns> private static ProbeResults CalculateDamage(Micromon attacker, Micromon defender) { //Damage shoud not be any lower than 1 return(new ProbeResults(Math.Max(1d, (attacker.Attack - (defender.Defense / 2d)) * Typing.CalculateEffectiveness(attacker, defender)), defender)); }
/// <summary> /// Calculates the best effectiveness of a Pokemon against another /// </summary> /// <param name="attacking">Attacking Pokemon</param> /// <param name="defending">Defending Pokemon</param> /// <returns>The effectiveness of the best attacking move (ranging from 0 to 4)</returns> public static double CalculateEffectiveness(Micromon attacking, Micromon defending) { //Find the best attacking/defending matchup return(Math.Max(Matchup(attacking.Type1, defending), Matchup(attacking.Type2, defending))); }