private static Option <ICommand> CastSpell(Player player, int spellnum, Spell.ISpell spell) { int mainMana = spell.Cost.MainManaUsed(); int altMana = spell.Cost.AltManaUsed(); int minMainCost = spell.Cost.MainCost.Item1; int minAltCost = spell.Cost.AltCost.Item1; if (mainMana < minMainCost || mainMana < minAltCost) { Game.MessagePanel.AddMessage("Not enough mana"); return(Option.None <ICommand>()); } if (spell.Instant) { // TODO: multi-hitting instants return(spell.Zone.GetAllValidTargets(player.Pos) .Random(Game.Rand) .FlatMap(cursor => { IEnumerable <Loc> targets = spell.Zone.GetTilesInRange(player.Pos, cursor); PaySpellCost(player, spell, mainMana, altMana); return Option.Some(spell.Evoke(player, targets, (mainMana, altMana))); })); } else { Game.StateHandler.PushState( new TargettingState(player, spell.Zone, spellnum, targets => { if (!targets.Any()) { return(Option.None <ICommand>()); } PaySpellCost(player, spell, mainMana, altMana); Game.StateHandler.PopState(); return(Option.Some(spell.Evoke(player, targets, (mainMana, altMana)))); }));