/// <summary> /// Constructs the token sprite based on the individual /// components. This is the "view" part of a token. /// </summary> public TokenSprite( Display display, Token token) { this.display = display; this.token = token; // Create the tile typeSprite = token.TypeSpriteName; tileDrawable = Game.Theme.DrawableFactory.Create(typeSprite); // Create the letter valueSprite = token.ValueSpriteName; letterDrawable = Game.Theme.DrawableFactory.Create(valueSprite); letterState = new DrawableState(); // Create the selected selectedDrawable = Game.Theme.DrawableFactory.Create("selected"); selectedState = new DrawableState(); // Randomize it Randomize(); }
/// <summary> /// Returns true if the given token is adjacent to this one. /// </summary> public bool IsAdjacent(Token token) { // If we are free, always yet if (Game.Config.SelectionType == SelectionType.Free) { return true; } // Get the difference int dr = Row - token.Row; int dc = Column - token.Column; // Either the row or column must be equal if (Game.Config.SelectionType == SelectionType.Cross && dr != 0 && dc != 0) { return false; } // Now check to see if they are close return !(dr < -1 || dr > 1 || dc < -1 || dc > 1); }
/// <summary> /// Gets a token sprite for a given token, or returns null if /// there is one. /// </summary> public TokenSprite GetTokenSprite(Token token) { // Return it ContainerSprite ms = GetContainerSprite(token); if (ms == null) { return null; } else { return ms.ProxiedSprite as TokenSprite; } }
/// <summary> /// Gets a token sprite for a given token, or returns null if /// there is one. /// </summary> public ContainerSprite GetContainerSprite(Token token) { // Go through the sprites, unwrap the moving sprites, and // check for the token. foreach (ISprite sprite in sprites) { if (sprite is ContainerSprite) { ContainerSprite ms = (ContainerSprite) sprite; TokenSprite ts = ms.TokenSprite; if (ts != null && ts.Token == token) { return ms; } } } // Can't find it return null; }
public TokenArgs(Token token) { Token = token; }
/// <summary> /// Handles flooded tiles which fill empty spaces. /// </summary> private void UpdateFlooded() { // Speed check, look for at least one flooded bool hasFlooded = false; foreach (Token token in tokens) { if (token.Type == TokenType.Flooded) { hasFlooded = true; break; } } if (!hasFlooded) { return; } // Remove all the empty flooded tokens from the list LinkedList<Token> toRem = new LinkedList<Token>(); foreach (Token token in tokens) { if (token.Type == TokenType.Flooded && token.Value == ' ') { toRem.Add(token); OnTokenRemoved(token, false); } } tokens.RemoveAll(toRem); // First go through and make sure we don't have any orphan // Go through all the rows and look for empty spaces while (true) { // Keep going as long as we made at least one change LinkedList<Token> toAdd = new LinkedList<Token>(); for (int row = 0; row < Rows; row++) { for (int col = 0; col < Columns; col++) { // Check for null Token token = GetToken(row, col); if (token != null) { continue; } // This is a flooded candidate, so check the // tokens next to this one bool isFlooded = false; foreach (Token next in GetTokensAdjacent(row, col)) { if (next.Type == TokenType.Flooded) { isFlooded = true; } } // Check for flooded if (isFlooded) { token = new Token(TokenType.Flooded, ' ', row, col); toAdd.Add(token); } } } // If we didn't have any added tokens, stop processing if (toAdd.Count == 0) { break; } // Add the tokens we want to add foreach (Token t in toAdd) { tokens.Add(t); OnTokenAdded(t); } } }
/// <summary> /// Removes a token from the board. /// </summary> private void RemoveToken( Token token, bool burnt) { tokens.Remove(token); OnTokenRemoved(token, burnt); }
/// <summary> /// This is the default operation for when a token is removed. /// </summary> protected virtual void OnTokenRemoved( Token token, bool burnt) { // Build the arguments TokenArgs args = new TokenArgs(token); args.IsBurnt = burnt; // Call it if (TokenRemoved != null) { TokenRemoved(this, args); } }
/// <summary> /// This is the default operation for when a token is changed. /// </summary> protected virtual void OnTokenChanged(Token token) { if (TokenChanged != null) { TokenChanged(this, new TokenArgs(token)); } }
/// <summary> /// Returns true if this is a valid chain. /// </summary> public bool IsFinalToken(Token token) { // Check the score first if (CurrentChainScore == null) { return false; } // Check that this is last return token == chain.Last; }
/// <summary> /// Adds the token to the chain. /// </summary> public void AddToChain(Token token) { try { // Check to see if there is only one and it is this // one. If it is, then reset the chain. if (chain.Count == 1 && chain.Contains(token)) { chain.Clear(); token.InChain = false; return; } // Check to see if there is anything in the chain already if (chain.Count > 0) { // Go backwards until we find one that is adjacent to // the current one bool addRest = false; bool containsToken = chain.Contains(token); ArrayList<Token> revChain = new ArrayList<Token>(); revChain.AddAll(chain); revChain.Reverse(); LinkedList<Token> newChain = new LinkedList<Token>(); foreach (Token test in revChain) { // Check for containing code if (containsToken && !addRest && test != token) { test.InChain = false; continue; } if (containsToken && test == token) { // Add the rest, but not this one because we // append at the end. addRest = true; continue; } // Check for adjacent if (!addRest && !test.IsAdjacent(token)) { // Pop off this one test.InChain = false; continue; } // Check for adjacent if (test.IsAdjacent(token)) { addRest = true; } // Add the chain test.InChain = true; newChain.Add(test); } // Reverse it again newChain.Reverse(); chain = newChain; } // At this point, we can append the token to the chain chain.Add(token); token.InChain = true; } finally { // Fire a change OnChainChanged(); } }