void reactionComputingThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (!e.Cancelled) { // Don't let multiple threads eat atoms. Nor let two check for two reactions at // the same time with an overlapping atom. lock (CoreModel.Instance) { IList<Tile> tilesInReaction = e.Result as IList<Tile>; // Final check if someone ate our atoms in-between and unbalanced us. if (tilesInReaction != null && tilesInReaction.Count > 0 && tilesInReaction.Sum(t => t.Atom.IonCharge) == 0) { // Add points. Not displayed outside of Avalanche and Trickle, oh well. model.Points += tilesInReaction.Sum(t => t.Atom.Points); this.updateAtomsLeftOrPointsCounter(); StringBuilder equation = new StringBuilder(); tilesInReaction = tilesInReaction.OrderBy(tile => tile, this._orderTilesByAtomNameComparer).ToList(); String previousElement = tilesInReaction[0].Atom.Element; String currentElement = ""; int quantity = 0; Tile finalTile = tilesInReaction[tilesInReaction.Count - 1]; // Equations only on non-Avalanche and non-Trickle mode. foreach (Tile reactionTile in tilesInReaction) { // For some reason, these appear at high levels in large chains. // HACK: don't display it. if (reactionTile.IsEmpty()) { continue; } reactionTile.AtomSprite.ColorOperation = ColorOperation.Add; reactionTile.AtomSprite.RedRate = 3f; reactionTile.AtomSprite.GreenRate = 3f; reactionTile.AtomSprite.BlueRate = 3f; this._reactingTiles.Add(reactionTile); // Print out something nice, like 2Fl + H + Li. // Or, in Avalanche/Trickle, 1 + 16 + 9. if (model.CurrentLevel != CoreModel.AVALANCHE_LEVEL && model.CurrentLevel != CoreModel.TRICKLE_LEVEL) { currentElement = reactionTile.Atom.Element; if (previousElement == currentElement) { quantity++; } else if (previousElement != currentElement) { // Print nothing if quantity = 1, i.e. we like to // see "H + Cl" not "1H + 1Cl" equation.Append(string.Format("{0}{1} + ", (quantity > 1 ? quantity.ToString() : ""), previousElement)); // 1, not 0, because we won't do this elsewhere; fixes bug where // Fl-Fl-H-H becomes 2Fl + H. quantity = 1; } previousElement = reactionTile.Atom.Element; } else { equation.Append(string.Format("{0} + ", reactionTile.Atom.Points)); } reactionTile.Empty(); // Prevent quick clickers from chaining } // Dump of last element if (model.CurrentLevel != CoreModel.AVALANCHE_LEVEL && model.CurrentLevel != CoreModel.TRICKLE_LEVEL) { equation.Append(string.Format("{0}{1} + ", (quantity > 1 ? quantity.ToString() : ""), previousElement)); } if (equation.Length >= 3) { // Trickle mode bug? equation.Remove(equation.Length - 3, 3); // trailing " + " } TowerText equationText = new TowerText(this.AddText(equation.ToString())); equationText.YVelocity = 15; equationText.AlphaRate = -0.1f; equationText.Scale = 24; equationText.AddShadow(); equationText.InsertNewLines(SpriteManager.Camera.Width); AudioManager.Instance.PlaySound(CoreModel.SOUND_FILE_PATH + "reaction.mp3"); this._reactionText.Add(equationText.BaseText); this._reactionText.Add(equationText.EffectText); } if (model.CurrentLevel >= CoreModel.FIRST_PUZZLE_LEVEL && model.CurrentLevel <= CoreModel.LAST_PUZZLE_LEVEL && model.NextAtom == Atom.NONE && !model.IsLevelOver()) { // Puzzle mode, out of atoms; game over. model.SignalGameOver(); } } } }