예제 #1
0
        private static void ParseSpaceAndReach(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Space\s(?<Space>\w+)\s?ft\.,?;?\s+Reach\s(?<Reach>\w+)\s?ft\.";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                try
                {
                    attributes.Space = Convert.ToInt32(match.Groups["Space"].Value);
                }
                catch (FormatException)
                {
                    attributes.Space = 5;
                }

                try
                {
                    attributes.Reach = Convert.ToInt32(match.Groups["Reach"].Value);
                }
                catch (FormatException)
                {
                    attributes.Reach = 5;
                }
            }
        }
예제 #2
0
        private static void ParseSpeed(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Speed\s+(?<LandSpeed>\d+)\s+ft.\s*\(\d+\ssquares\)(,\s?(?<OtherSpeeds>.+))?";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                attributes.Speed.LandSpeed = Convert.ToInt32(match.Groups["LandSpeed"].Value);

                string          speedPattern = @"\s?(?<Type>\w+)\s(?<Speed>\d+)\s*ft.\s?(\((?<Manouverability>\w+)\))?";
                Regex           speedRegex   = new Regex(speedPattern, RegexOptions.IgnoreCase);
                MatchCollection speedMatches = speedRegex.Matches(match.Groups["OtherSpeeds"].Value);

                foreach (Match speedMatch in speedMatches)
                {
                    Types.Manouverability manouverability = Types.Manouverability.None;
                    if (speedMatch.Groups["Manouverability"].Success)
                    {
                        manouverability = Methods.GetManouverabilityFromString(speedMatch.Groups["Manouverability"].Value);
                    }
                    int    distance       = Convert.ToInt32(speedMatch.Groups["Speed"].Value);
                    string movementString = speedMatch.Groups["Type"].Value.Trim();

                    Types.Movement movementType = Methods.GetMovementTypeFromString(movementString);
                    attributes.Speed.Speeds.Add(new Model.Speed(distance, movementType, manouverability));
                }
            }
        }
예제 #3
0
        private static void ParseBaseAttackAndGrapple(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Base Atk\s(?<BAB>\S+);\s+Grp\s(?<Grapple>\S+)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                try
                {
                    attributes.BaseAttackBonus = Convert.ToInt32(match.Groups["BAB"].Value);
                }
                catch (FormatException)
                {
                    attributes.BaseAttackBonus = 0;
                }

                try
                {
                    attributes.GrappleModifier = Convert.ToInt32(match.Groups["Grapple"].Value);
                }
                catch (FormatException)
                {
                    attributes.GrappleModifier = 0;
                }
            }
        }
예제 #4
0
        private static void ParseImmunities(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Immune\s?(?<Immunities>.+)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                string          immunityPattern = @"(?<Type>[a-z]+)(\,|\z)";
                Regex           immunityRegex   = new Regex(immunityPattern, RegexOptions.IgnoreCase);
                MatchCollection immunityMatches = immunityRegex.Matches(match.Groups["Immunities"].Value);

                foreach (Match immunityMatch in immunityMatches)
                {
                    Model.DamageDescriptorSet damageTypes = GetDamageDescriptorSetFromString(immunityMatch.Groups["Type"].Value, "and");
                    foreach (Types.Damage damageType in damageTypes.ToList())
                    {
                        if (damageType != Types.Damage.Magic)                         // Immunity to magic does not mean immunity to magic weapons
                        {
                            attributes.Immunities.Add(damageType);
                        }
                    }
                }
            }
        }
예제 #5
0
        private static void ParseHitPoints(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"hp\s(?<HP>\d+)\s\((?<HD>\d+)\sHD\)(;\sfast\shealing\s(?<FastHealing>\d+))?(;\s(?<DR>DR\s.*))?";
            Regex  regex   = new Regex(pattern, RegexOptions.IgnoreCase);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                attributes.HitPoints = Convert.ToInt32(match.Groups["HP"].Value);
                attributes.HitDice   = Convert.ToInt32(match.Groups["HD"].Value);

                if (match.Groups["FastHealing"].Success)
                {
                    attributes.FastHealing = Convert.ToInt32(match.Groups["FastHealing"].Value);
                }

                if (match.Groups["DR"].Success)
                {
                    string          drStr     = match.Groups["DR"].Value;
                    string          drPattern = @"(?<Value>\d+)\/(?<Types>.+?)(\,|\z)";
                    Regex           drRegex   = new Regex(drPattern, RegexOptions.IgnoreCase);
                    MatchCollection drMatches = drRegex.Matches(drStr);

                    foreach (Match drMatch in drMatches)
                    {
                        Model.DamageReduction dr = new Model.DamageReduction();
                        dr.Value       = Convert.ToInt32(drMatch.Groups["Value"].Value);
                        dr.DamageTypes = GetDamageDescriptorSetFromString(drMatch.Groups["Types"].Value, "and");
                        attributes.DamageReductions.Add(dr);
                    }
                }
            }
        }
예제 #6
0
        private static void ParseFeats(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Feats\s(?<Feats>.+)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                foreach (string feat in match.Groups["Feats"].Value.Split(','))
                {
                    feat.Trim();
                    feat.Trim('*');
                    feat.Trim();
                    attributes.Feats.Add(feat);
                }

                if (attributes.WeaponFinesse)
                {
                    foreach (Model.AttackSet attackSet in attributes.AttackSets)
                    {
                        foreach (Model.Attack attack in attackSet.Attacks)
                        {
                            if (attack.Type == Types.Attack.Melee ||
                                attack.Type == Types.Attack.MeleeTouch ||
                                attack.Type == Types.Attack.IncorporealTouch)
                            {
                                attack.Ability = Types.Ability.Dexterity;
                            }
                        }
                    }
                }
            }
        }
예제 #7
0
        private static void ParseAttack(Model.CreatureAttributes attributes, string str, Types.Attack attackType)
        {
            Model.AttackSet attackSet = new Model.AttackSet
            {
                Name = "Full Attack",
            };

            string          attacksPattern = @"(?<NumAttacks>\d+)?\s?(?<Name>\D+)\s(?<HitMod>[+-]\d+)(\seach)?\s(\((?<Damage>[^\(]*)\))?";
            Regex           attacksRegex   = new Regex(attacksPattern, RegexOptions.IgnoreCase);
            MatchCollection attackMatches  = attacksRegex.Matches(str);

            foreach (Match attackMatch in attackMatches)
            {
                int    numAttacks = 1;
                string name       = attackMatch.Groups["Name"].Value;
                if (attackMatch.Groups["NumAttacks"].Value != "")
                {
                    numAttacks = Convert.ToInt32(attackMatch.Groups["NumAttacks"].Value);
                    PluralizationService ps = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-us"));
                    name = ps.Singularize(name);
                }

                name = char.ToUpper(name[0]) + name.Substring(1);

                for (int i = 0; i < numAttacks; ++i)
                {
                    Model.Attack attack = new Model.Attack();

                    attack.Name     = name;
                    attack.Modifier = Convert.ToInt32(attackMatch.Groups["HitMod"].Value);
                    attack.Type     = attackType;

                    string          damageStr     = attackMatch.Groups["Damage"].Value;
                    string          damagePattern = @"(?<NumDice>\d+)(?<Die>d\d+)(?<DamageMod>[\+\-]?\d*)\s?(?<DamageType>(?!plus\b)\b\w+)?";
                    Regex           damageRegex   = new Regex(damagePattern, RegexOptions.IgnoreCase);
                    MatchCollection damageMatches = damageRegex.Matches(damageStr);

                    foreach (Match damageMatch in damageMatches)
                    {
                        Model.Damage damage = new Model.Damage();
                        damage.NumDice = Convert.ToInt32(damageMatch.Groups["NumDice"].Value);
                        damage.Die     = Methods.GetDieTypeFromString(damageMatch.Groups["Die"].Value);
                        if (damageMatch.Groups["DamageMod"].Value != "")
                        {
                            damage.Modifier = Convert.ToInt32(damageMatch.Groups["DamageMod"].Value);
                        }
                        if (damageMatch.Groups["DamageType"].Value != "")
                        {
                            damage.DamageDescriptorSet.Add(Methods.GetDamageTypeFromString(damageMatch.Groups["DamageType"].Value));
                        }
                        attack.Damages.Add(damage);
                    }

                    attackSet.Attacks.Add(attack);
                }
            }

            attributes.AttackSets.Add(attackSet);
        }
예제 #8
0
        public Model.HitPointChange GetHit(Model.CreatureAttributes creatureAttributes)
        {
            Model.HitPointChange hitPointChange = new Model.HitPointChange();
            bool   askForInput = true;
            string feedback    = null;

            while (askForInput)
            {
                SetSelectedWeapon();

                View.HitPointChangeDialog damageDialog = new View.HitPointChangeDialog(feedback);
                damageDialog.DataContext = this;
                if (damageDialog.ShowDialog() == true)
                {
                    List <int> damage = new List <int>();
                    try
                    {
                        if (Healing != "")
                        {
                            int healing = Convert.ToInt32(Healing);
                            hitPointChange = new Model.Heal(healing);
                        }
                        else
                        {
                            if (Damage1 != "")
                            {
                                damage.Add(Convert.ToInt32(Damage1));
                            }
                            if (Damage2 != "")
                            {
                                damage.Add(Convert.ToInt32(Damage2));
                            }
                            if (Damage3 != "")
                            {
                                damage.Add(Convert.ToInt32(Damage3));
                            }

                            Model.Weapon weapon = GetWeapon();

                            hitPointChange = new Model.Hit(damage, weapon, creatureAttributes);
                        }

                        askForInput = false;
                    }
                    catch (FormatException)
                    {
                        // Failed to parse input
                        feedback = "Invalid format";
                    }
                }
                else
                {
                    askForInput = false;
                }
            }

            return(hitPointChange);
        }
예제 #9
0
        private static void ParseAlignmentSizeAndType(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"(?<Alignment>LG|NG|CG|LN|N|CN|LE|NE|CE)\s(?<Size>Fine|Diminuative|Tiny|Small|Medium|Large|Huge|Gargantuan|Colossal)\s(?<Type>[A-Za-z]+)";
            Regex  regex   = new Regex(pattern, RegexOptions.IgnoreCase);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                attributes.Size = Methods.GetSizeFromString(match.Groups["Size"].Value);
                attributes.Type = Methods.GetCreatureTypeFromString(match.Groups["Type"].Value);
            }
        }
예제 #10
0
        private static void ParseArmorClass(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"(?<AC>\d+),\s*touch\s*(?<TouchAC>\d+),\s*flat\-footed\s*(?<FFAC>\d+)";
            Regex  regex   = new Regex(pattern, RegexOptions.IgnoreCase);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                attributes.ArmorClass           = Convert.ToInt32(match.Groups["AC"].Value);
                attributes.TouchArmorClass      = Convert.ToInt32(match.Groups["TouchAC"].Value);
                attributes.FlatFootedArmorClass = Convert.ToInt32(match.Groups["FFAC"].Value);
            }
        }
예제 #11
0
        private static void ParseChallengeRating(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"CR\s(?<CR>\w+)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                try
                {
                    attributes.ChallengeRating = Convert.ToInt32(match.Groups["CR"].Value);
                }
                catch (FormatException)
                {
                    attributes.ChallengeRating = 0;
                }
            }
        }
예제 #12
0
        private static void ParseSpellResistance(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"SR\s(?<SR>\w+)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                try
                {
                    attributes.SpellResistance = Convert.ToInt32(match.Groups["SR"].Value);
                }
                catch (FormatException)
                {
                    attributes.SpellResistance = 0;
                }
            }
        }
예제 #13
0
        private static void ParseInitiative(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Init\s(?<Init>[\+\-]\d+)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                try
                {
                    attributes.InitiativeMod = Convert.ToInt32(match.Groups["Init"].Value);
                }
                catch (FormatException)
                {
                    attributes.InitiativeMod = 0;
                }
            }
        }
예제 #14
0
        public static Model.Creature ParseMM4Text(string text)
        {
            Model.CreatureAttributes attributes = new Model.CreatureAttributes();

            if (text != "")
            {
                string[] lines       = text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
                string   currentLine = "";
                try
                {
                    for (int l = 0; l < lines.Count(); ++l)
                    {
                        currentLine = lines[l];

                        // Parse one-line data types
                        ParseChallengeRating(attributes, currentLine);
                        ParseSaves(attributes, currentLine);
                        ParseBaseAttackAndGrapple(attributes, currentLine);
                        ParseSpaceAndReach(attributes, currentLine);
                        ParseAbilities(attributes, currentLine);
                        ParseResistances(attributes, currentLine);
                        ParseSpellResistance(attributes, currentLine);
                        ParseImmunities(attributes, currentLine);
                        ParseSpeed(attributes, currentLine);
                        ParseArmorClass(attributes, currentLine);
                        ParseAlignmentSizeAndType(attributes, currentLine);
                        ParseInitiative(attributes, currentLine);
                        ParseHitPoints(attributes, currentLine);
                        ParseFeats(attributes, currentLine);
                        ParseAttacks(attributes, currentLine);
                    }
                }
                catch (FormatException e)
                {
                    MessageBox.Show("Cannot parse:\n" + currentLine);
                    throw e;
                }
            }

            Model.Creature creature = new Model.Creature(attributes);

            return(creature);
        }
예제 #15
0
        private static void ParseAttacks(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Melee\s(?<Attacks>.*)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                ParseAttack(attributes, match.Groups["Attacks"].Value, Types.Attack.Melee);
            }

            pattern = @"Ranged\s(?<Attacks>.*)";
            regex   = new Regex(pattern);
            match   = regex.Match(str);

            if (match.Success)
            {
                ParseAttack(attributes, match.Groups["Attacks"].Value, Types.Attack.Ranged);
            }
        }
예제 #16
0
        private static void ParseSaves(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Fort\s(?<Fort>[\+\-]\d+)\s?(\(.+\))?,?\s+Ref\s(?<Ref>[\+\-]\d+)\s?(\(.+\))?,?\s+Will?\s(?<Will>[\+\-]\d+)\s?(\(.+\))?";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                try
                {
                    attributes.FortitudeSave = Convert.ToInt32(match.Groups["Fort"].Value);
                }
                catch (FormatException)
                {
                    attributes.FortitudeSave = 0;
                }

                try
                {
                    attributes.ReflexSave = Convert.ToInt32(match.Groups["Ref"].Value);
                }
                catch (FormatException)
                {
                    attributes.ReflexSave = 0;
                }

                try
                {
                    attributes.WillSave = Convert.ToInt32(match.Groups["Will"].Value);
                }
                catch (FormatException)
                {
                    attributes.WillSave = 0;
                }
            }
        }
예제 #17
0
        private static void ParseResistances(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Resist\s?(?<Resistances>[^;]+)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                string          resistancePattern = @"(?<Type>[a-z]+)\s(?<Value>\d+)";
                Regex           resistanceRegex   = new Regex(resistancePattern, RegexOptions.IgnoreCase);
                MatchCollection resistanceMatches = resistanceRegex.Matches(match.Groups["Resistances"].Value);

                foreach (Match resistanceMatch in resistanceMatches)
                {
                    Model.EnergyResistance res = new Model.EnergyResistance();
                    try
                    {
                        res.Value = Convert.ToInt32(resistanceMatch.Groups["Value"].Value);
                    }
                    catch (FormatException)
                    {
                        res.Value = 0;
                    }

                    try
                    {
                        res.EnergyType = Methods.GetDamageTypeFromString(resistanceMatch.Groups["Type"].Value);
                    }
                    catch (FormatException)
                    {
                        res.EnergyType = Types.Damage.Subdual;
                    }
                    attributes.EnergyResistances.Add(res);
                }
            }
        }
예제 #18
0
        private static void ParseAbilities(Model.CreatureAttributes attributes, string str)
        {
            string pattern = @"Str\s(?<Str>\S+),\s+Dex\s(?<Dex>\S+),\s+Con\s(?<Con>\S+),\s+Int\s(?<Int>\S+),\s+Wis\s(?<Wis>\S+),\s+Cha\s(?<Cha>\S+)";
            Regex  regex   = new Regex(pattern);
            Match  match   = regex.Match(str);

            if (match.Success)
            {
                try
                {
                    attributes.Strength = Convert.ToInt32(match.Groups["Str"].Value);
                }
                catch (FormatException)
                {
                    attributes.Strength = 0;
                }

                try
                {
                    attributes.Dexterity = Convert.ToInt32(match.Groups["Dex"].Value);
                }
                catch (FormatException)
                {
                    attributes.Dexterity = 0;
                }

                try
                {
                    attributes.Constitution = Convert.ToInt32(match.Groups["Con"].Value);
                }
                catch (FormatException)
                {
                    attributes.Constitution = 0;
                }

                try
                {
                    attributes.Intelligence = Convert.ToInt32(match.Groups["Int"].Value);
                }
                catch (FormatException)
                {
                    attributes.Intelligence = 0;
                }

                try
                {
                    attributes.Wisdom = Convert.ToInt32(match.Groups["Wis"].Value);
                }
                catch (FormatException)
                {
                    attributes.Wisdom = 0;
                }

                try
                {
                    attributes.Charisma = Convert.ToInt32(match.Groups["Cha"].Value);
                }
                catch (FormatException)
                {
                    attributes.Charisma = 0;
                }
            }
        }
예제 #19
0
        public Model.Creature GetCreature()
        {
            bool   askForInput = true;
            string feedback    = null;

            Model.Creature creature = null;
            while (askForInput)
            {
                View.CreateCreatureWindow createCreatureWindow = new View.CreateCreatureWindow(feedback);
                createCreatureWindow.DataContext = this;
                if (createCreatureWindow.ShowDialog() == true)
                {
                    try
                    {
                        Model.CreatureAttributes creatureAttributes = new Model.CreatureAttributes
                        {
                            InitiativeMod        = Convert.ToInt32(InitiativeMod),
                            Type                 = Methods.GetCreatureTypeFromString(CreatureTypes.ElementAt(SelectedCreatureType)),
                            ChallengeRating      = Convert.ToSingle(ChallengeRating),
                            AttackSets           = AttackSets,
                            Strength             = Convert.ToInt32(Strength),
                            Dexterity            = Convert.ToInt32(Dexterity),
                            Constitution         = Convert.ToInt32(Constitution),
                            Intelligence         = Convert.ToInt32(Intelligence),
                            Wisdom               = Convert.ToInt32(Wisdom),
                            Charisma             = Convert.ToInt32(Charisma),
                            BaseAttackBonus      = Convert.ToInt32(BaseAttackBonus),
                            GrappleModifier      = Convert.ToInt32(GrappleModifier),
                            HitPoints            = Convert.ToInt32(HitPoints),
                            HitDice              = Convert.ToInt32(HitDice),
                            HitDieType           = Methods.GetDieTypeFromString(DieTypes.ElementAt(SelectedHitDie)),
                            ArmorClass           = Convert.ToInt32(ArmorClass),
                            TouchArmorClass      = Convert.ToInt32(TouchArmorClass),
                            FlatFootedArmorClass = Convert.ToInt32(FlatFootedArmorClass),
                            Speed                = Speeds,
                            Space                = Convert.ToInt32(Space),
                            Reach                = Convert.ToInt32(Reach),
                            FortitudeSave        = Convert.ToInt32(FortitudeSave),
                            ReflexSave           = Convert.ToInt32(ReflexSave),
                            WillSave             = Convert.ToInt32(WillSave),
                            Feats                = Feats,
                            Size                 = Methods.GetSizeFromString(Sizes.ElementAt(SelectedSize)),
                            DamageReductions     = DamageReductions,
                            Immunities           = Immunities,
                            EnergyResistances    = EnergyResistances,
                            SpellResistance      = Convert.ToInt32(SpellResistance),
                            FastHealing          = Convert.ToInt32(FastHealing),
                            SpecialAttacks       = SpecialAttacks,
                            SpecialQualities     = SpecialQualities,
                        };
                        creature = new Model.Creature(creatureAttributes)
                        {
                            ActorName = ActorName,
                        };
                        askForInput = false;
                    }
                    catch (FormatException)
                    {
                        feedback = "Invalid format";
                    }
                }
                else
                {
                    askForInput = false;
                }
            }

            return(creature);
        }
예제 #20
0
        public static Model.Creature ParseSRDText(string text)
        {
            Model.CreatureAttributes attributes = new Model.CreatureAttributes();

            if (text != null && text != "")
            {
                string[] lines       = text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
                string   currentLine = "";
                try
                {
                    foreach (string line in lines)
                    {
                        currentLine = line;
                        if (currentLine != "")
                        {
                            string[] splitLine = line.Split(':');
                            if (splitLine.Length != 2)
                            {
                                throw new FormatException();
                            }
                            else
                            {
                                string     identifier = splitLine[0];
                                string     entry      = splitLine[1];
                                List <int> numbers    = GetNumbersFromString(entry);
                                string[]   words      = splitLine[1].Split((char[])null, StringSplitOptions.RemoveEmptyEntries);

                                if (identifier == "Size/Type")
                                {
                                    attributes.Size = Methods.GetSizeFromString(words[0]);
                                    string typeStr = string.Join(" ", words.Skip(1));

                                    string typePattern = @"\s*(?<Type>\w+)\s*(\((?<SubTypes>\D+)\))?";
                                    Regex  typeRegex   = new Regex(typePattern, RegexOptions.IgnoreCase);
                                    Match  typeMatch   = typeRegex.Match(typeStr);

                                    if (typeMatch.Success)
                                    {
                                        attributes.Type = Methods.GetCreatureTypeFromString(typeMatch.Groups["Type"].Value);

                                        /*
                                         * if (typeMatch.Groups.Count > 1)
                                         * {
                                         *      string subTypes = typeMatch.Groups["SubTypes"].Value;
                                         *
                                         *      string subTypePattern = @"\s*(?<Type>\w+)\s*(\((?<SubTypes>\D+)\))?";
                                         *      Regex subTypeRegex = new Regex(subTypePattern, RegexOptions.IgnoreCase);
                                         *      Match subTypeMatch = subTypeRegex.Match(entry);
                                         *
                                         *      if (subTypeMatch.Success)
                                         *      {
                                         *              attributes.Subtypes = Methods.GetCreatureSubTypeFromString();
                                         *      }
                                         * }
                                         */
                                    }
                                }
                                else if (identifier == "Hit Dice")
                                {
                                    string hpPattern = @"\s?(?<NumHD>\d+)(?<HDType>[dD]\d+)\s?(?<HDMod>[\+\-]\d+)?\s?\((?<HP>\d+)\s?hp\)";
                                    Regex  hpRegex   = new Regex(hpPattern, RegexOptions.IgnoreCase);
                                    Match  hpMatch   = hpRegex.Match(entry);

                                    if (hpMatch.Success)
                                    {
                                        attributes.HitDice    = Convert.ToInt32(hpMatch.Groups["NumHD"].Value);
                                        attributes.HitDieType = Methods.GetDieTypeFromString(hpMatch.Groups["HDType"].Value);
                                        attributes.HitPoints  = Convert.ToInt32(hpMatch.Groups["HP"].Value);
                                    }
                                }
                                else if (identifier == "Initiative")
                                {
                                    attributes.InitiativeMod = numbers[0];
                                }
                                else if (identifier == "Speed")
                                {
                                    char[] commaChar = { ',' };

                                    foreach (string speedStr in entry.Split(commaChar, StringSplitOptions.RemoveEmptyEntries))
                                    {
                                        string speedPattern = @"\s?(?<Type>\D*)\s(?<Speed>\d+)\s*ft.\s*(\((?<Manouverability>\w+)\))?";
                                        Regex  speedRegex   = new Regex(speedPattern, RegexOptions.IgnoreCase);
                                        Match  speedMatch   = speedRegex.Match(speedStr);

                                        if (speedMatch.Success)
                                        {
                                            Types.Manouverability manouverability = Types.Manouverability.None;
                                            if (speedMatch.Groups["Manouverability"].Success)
                                            {
                                                manouverability = Methods.GetManouverabilityFromString(speedMatch.Groups["Manouverability"].Value);
                                            }
                                            int    distance       = Convert.ToInt32(speedMatch.Groups["Speed"].Value);
                                            string movementString = speedMatch.Groups["Type"].Value.Trim();
                                            if (movementString.Equals(""))
                                            {
                                                attributes.Speed.LandSpeed = distance;
                                            }
                                            else
                                            {
                                                Types.Movement movementType = Methods.GetMovementTypeFromString(movementString);
                                                attributes.Speed.Speeds.Add(new Model.Speed(distance, movementType, manouverability));
                                            }
                                        }
                                    }
                                }
                                else if (identifier == "Armor Class")
                                {
                                    string acPattern = @"(?<AC>\d+)\s\(.*\),\s*touch\s*(?<TouchAC>\d+),\s*flat\-footed\s*(?<FFAC>\d+)";
                                    Regex  acRegex   = new Regex(acPattern, RegexOptions.IgnoreCase);
                                    Match  acMatch   = acRegex.Match(entry);

                                    if (acMatch.Success)
                                    {
                                        attributes.ArmorClass           = Convert.ToInt32(acMatch.Groups["AC"].Value);
                                        attributes.TouchArmorClass      = Convert.ToInt32(acMatch.Groups["TouchAC"].Value);
                                        attributes.FlatFootedArmorClass = Convert.ToInt32(acMatch.Groups["FFAC"].Value);
                                    }
                                }
                                else if (identifier == "Base Attack/Grapple")
                                {
                                    attributes.BaseAttackBonus = numbers[0];
                                    attributes.GrappleModifier = numbers[1];
                                }
                                else if (identifier == "Attack" || identifier == "Full Attack")
                                {
                                    string[] orStr = { "or" };
                                    foreach (string attackSetStr in entry.Split(orStr, StringSplitOptions.RemoveEmptyEntries))
                                    {
                                        Model.AttackSet attackSet = new Model.AttackSet
                                        {
                                            Name = identifier,
                                        };

                                        string          attackPattern = @"(?<NumAttacks>\d+)?\s?(?<Name>(?!and\b)\b\D+)\s(?<AttackMod>[\+\-]\d+)\s(?<Type>\D+\s?\D*)\s\((?<Damage>[^\(]*)\)";
                                        Regex           attackRegex   = new Regex(attackPattern, RegexOptions.IgnoreCase);
                                        MatchCollection attackMatches = attackRegex.Matches(attackSetStr);
                                        foreach (Match attackMatch in attackMatches)
                                        {
                                            int    numAttacks = 1;
                                            string name       = attackMatch.Groups["Name"].Value;
                                            if (attackMatch.Groups["NumAttacks"].Value != "")
                                            {
                                                numAttacks = Convert.ToInt32(attackMatch.Groups["NumAttacks"].Value);
                                                PluralizationService ps = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-us"));
                                                name = ps.Singularize(name);
                                            }

                                            name = char.ToUpper(name[0]) + name.Substring(1);

                                            for (int i = 0; i < numAttacks; ++i)
                                            {
                                                Model.Attack attack = new Model.Attack();

                                                attack.Name     = name;
                                                attack.Modifier = Convert.ToInt32(attackMatch.Groups["AttackMod"].Value);
                                                attack.Type     = Methods.GetAttackTypeFromString(attackMatch.Groups["Type"].Value);

                                                string          damageStr     = attackMatch.Groups["Damage"].Value;
                                                string          damagePattern = @"(?<NumDice>\d+)(?<Die>d\d+)(?<DamageMod>[\+\-]?\d*)\s?(?<DamageType>(?!plus\b)\b\w+)?";
                                                Regex           damageRegex   = new Regex(damagePattern, RegexOptions.IgnoreCase);
                                                MatchCollection damageMatches = damageRegex.Matches(damageStr);

                                                foreach (Match damageMatch in damageMatches)
                                                {
                                                    Model.Damage damage = new Model.Damage();
                                                    damage.NumDice = Convert.ToInt32(damageMatch.Groups["NumDice"].Value);
                                                    damage.Die     = Methods.GetDieTypeFromString(damageMatch.Groups["Die"].Value);
                                                    if (damageMatch.Groups["DamageMod"].Value != "")
                                                    {
                                                        damage.Modifier = Convert.ToInt32(damageMatch.Groups["DamageMod"].Value);
                                                    }
                                                    if (damageMatch.Groups["DamageType"].Value != "")
                                                    {
                                                        damage.DamageDescriptorSet.Add(Methods.GetDamageTypeFromString(damageMatch.Groups["DamageType"].Value));
                                                    }
                                                    attack.Damages.Add(damage);
                                                }

                                                attackSet.Attacks.Add(attack);
                                            }
                                        }

                                        attributes.AttackSets.Add(attackSet);
                                    }
                                }
                                else if (identifier == "Space/Reach")
                                {
                                    attributes.Space = numbers[0];
                                    attributes.Reach = numbers[1];
                                }
                                else if (identifier == "Special Attacks")
                                {
                                    attributes.SpecialAttacks = entry.Trim();
                                }
                                else if (identifier == "Special Qualities")
                                {
                                    foreach (string specialQuality in entry.Split(','))
                                    {
                                        attributes.SpecialQualities.Add(specialQuality.Trim());
                                    }

                                    string          drPattern = @"damage reduction (?<Value>\d+)\/(?<Types>.+?)(\,|\z)";
                                    Regex           drRegex   = new Regex(drPattern, RegexOptions.IgnoreCase);
                                    MatchCollection drMatches = drRegex.Matches(entry);

                                    foreach (Match drMatch in drMatches)
                                    {
                                        Model.DamageReduction dr = new Model.DamageReduction();
                                        dr.Value       = Convert.ToInt32(drMatch.Groups["Value"].Value);
                                        dr.DamageTypes = GetDamageDescriptorSetFromString(drMatch.Groups["Types"].Value, "and");
                                        attributes.DamageReductions.Add(dr);
                                    }

                                    string          immunityPattern = @"immunity to (?<Types>.+?)(\,|\z)";
                                    Regex           immunityRegex   = new Regex(immunityPattern, RegexOptions.IgnoreCase);
                                    MatchCollection immunityMatches = immunityRegex.Matches(entry);

                                    foreach (Match immunityMatch in immunityMatches)
                                    {
                                        Model.DamageDescriptorSet damageTypes = GetDamageDescriptorSetFromString(immunityMatch.Groups["Types"].Value, "and");
                                        foreach (Types.Damage damageType in damageTypes.ToList())
                                        {
                                            if (damageType != Types.Damage.Magic)                                             // Immunity to magic does not mean immunity to magic weapons
                                            {
                                                attributes.Immunities.Add(damageType);
                                            }
                                        }
                                    }

                                    string resistancesPattern = @"resistance to (?<Types>.+?)(\,|\z)";
                                    Regex  resistancesRegex   = new Regex(resistancesPattern, RegexOptions.IgnoreCase);
                                    Match  resistancesMatch   = resistancesRegex.Match(entry);

                                    if (resistancesMatch.Success)
                                    {
                                        string          resistancePattern = @"(?<Type>[a-z]+)\s(?<Value>\d+)";
                                        Regex           resistanceRegex   = new Regex(resistancePattern, RegexOptions.IgnoreCase);
                                        MatchCollection resistanceMatches = resistanceRegex.Matches(resistancesMatch.Groups["Types"].Value);

                                        foreach (Match resistanceMatch in resistanceMatches)
                                        {
                                            Model.EnergyResistance res = new Model.EnergyResistance();
                                            res.Value      = Convert.ToInt32(resistanceMatch.Groups["Value"].Value);
                                            res.EnergyType = Methods.GetDamageTypeFromString(resistanceMatch.Groups["Type"].Value);
                                            attributes.EnergyResistances.Add(res);
                                        }
                                    }

                                    string spellResistancePattern = @"spell resistance (?<Value>\d+)(\,|\z)";
                                    Regex  spellResistanceRegex   = new Regex(spellResistancePattern, RegexOptions.IgnoreCase);
                                    Match  spellResistanceMatch   = spellResistanceRegex.Match(entry);

                                    if (spellResistanceMatch.Success)
                                    {
                                        attributes.SpellResistance = Convert.ToInt32(spellResistanceMatch.Groups["Value"].Value);
                                    }

                                    string regenerationPattern = @"regeneration (?<Value>\d+)(\,|\z)";
                                    Regex  regenerationRegex   = new Regex(regenerationPattern, RegexOptions.IgnoreCase);
                                    Match  regenerationMatch   = regenerationRegex.Match(entry);

                                    if (regenerationMatch.Success)
                                    {
                                        attributes.FastHealing = Convert.ToInt32(regenerationMatch.Groups["Value"].Value);
                                    }

                                    string fastHealingPattern = @"fast healing (?<Value>\d+)(\,|\z)";
                                    Regex  fastHealingRegex   = new Regex(fastHealingPattern, RegexOptions.IgnoreCase);
                                    Match  fastHealingMatch   = fastHealingRegex.Match(entry);

                                    if (fastHealingMatch.Success)
                                    {
                                        attributes.FastHealing = Convert.ToInt32(fastHealingMatch.Groups["Value"].Value);
                                    }
                                }
                                else if (identifier == "Saves")
                                {
                                    attributes.FortitudeSave = numbers[0];
                                    attributes.ReflexSave    = numbers[1];
                                    attributes.WillSave      = numbers[2];
                                }
                                else if (identifier == "Abilities")
                                {
                                    string attributePattern = @"Str\s(?<Value>\w+)";
                                    Regex  attributeRegex   = new Regex(attributePattern, RegexOptions.IgnoreCase);
                                    Match  attributeMatch   = attributeRegex.Match(entry);

                                    if (attributeMatch.Success)
                                    {
                                        try
                                        {
                                            attributes.Strength = Convert.ToInt32(attributeMatch.Groups["Value"].Value);
                                        }
                                        catch (FormatException)
                                        {
                                            attributes.Strength = 0;
                                        }
                                    }

                                    attributePattern = @"Dex\s(?<Value>\w+)";
                                    attributeRegex   = new Regex(attributePattern, RegexOptions.IgnoreCase);
                                    attributeMatch   = attributeRegex.Match(entry);

                                    if (attributeMatch.Success)
                                    {
                                        try
                                        {
                                            attributes.Dexterity = Convert.ToInt32(attributeMatch.Groups["Value"].Value);
                                        }
                                        catch (FormatException)
                                        {
                                            attributes.Dexterity = 0;
                                        }
                                    }

                                    attributePattern = @"Con\s(?<Value>\w+)";
                                    attributeRegex   = new Regex(attributePattern, RegexOptions.IgnoreCase);
                                    attributeMatch   = attributeRegex.Match(entry);

                                    if (attributeMatch.Success)
                                    {
                                        try
                                        {
                                            attributes.Constitution = Convert.ToInt32(attributeMatch.Groups["Value"].Value);
                                        }
                                        catch (FormatException)
                                        {
                                            attributes.Constitution = 0;
                                        }
                                    }

                                    attributePattern = @"Int\s(?<Value>\w+)";
                                    attributeRegex   = new Regex(attributePattern, RegexOptions.IgnoreCase);
                                    attributeMatch   = attributeRegex.Match(entry);

                                    if (attributeMatch.Success)
                                    {
                                        try
                                        {
                                            attributes.Intelligence = Convert.ToInt32(attributeMatch.Groups["Value"].Value);
                                        }
                                        catch (FormatException)
                                        {
                                            attributes.Intelligence = 0;
                                        }
                                    }

                                    attributePattern = @"Wis\s(?<Value>\w+)";
                                    attributeRegex   = new Regex(attributePattern, RegexOptions.IgnoreCase);
                                    attributeMatch   = attributeRegex.Match(entry);

                                    if (attributeMatch.Success)
                                    {
                                        try
                                        {
                                            attributes.Wisdom = Convert.ToInt32(attributeMatch.Groups["Value"].Value);
                                        }
                                        catch (FormatException)
                                        {
                                            attributes.Wisdom = 0;
                                        }
                                    }

                                    attributePattern = @"Cha\s(?<Value>\w+)";
                                    attributeRegex   = new Regex(attributePattern, RegexOptions.IgnoreCase);
                                    attributeMatch   = attributeRegex.Match(entry);

                                    if (attributeMatch.Success)
                                    {
                                        try
                                        {
                                            attributes.Charisma = Convert.ToInt32(attributeMatch.Groups["Value"].Value);
                                        }
                                        catch (FormatException)
                                        {
                                            attributes.Charisma = 0;
                                        }
                                    }
                                }
                                else if (identifier == "Feats")
                                {
                                    foreach (string feat in entry.Split(','))
                                    {
                                        attributes.Feats.Add(feat.Trim());
                                    }

                                    if (attributes.WeaponFinesse)
                                    {
                                        foreach (Model.AttackSet attackSet in attributes.AttackSets)
                                        {
                                            foreach (Model.Attack attack in attackSet.Attacks)
                                            {
                                                attack.Ability = Types.Ability.Dexterity;
                                            }
                                        }
                                    }
                                }
                                else if (identifier == "Challenge Rating")
                                {
                                    if (numbers.Count == 2)
                                    {
                                        attributes.ChallengeRating = numbers[0] / numbers[1];
                                    }
                                    else if (numbers.Count == 1)
                                    {
                                        attributes.ChallengeRating = numbers[0];
                                    }
                                    else
                                    {
                                        attributes.ChallengeRating = 1;
                                    }
                                }
                            }
                        }
                    }
                }
                catch (FormatException e)
                {
                    MessageBox.Show("Cannot parse:\n" + currentLine);
                    throw e;
                }
            }

            Model.Creature creature = new Model.Creature(attributes);

            return(creature);
        }