Example #1
0
        public static int LastSpaceBeforeWrap(this colorstring cs, int wrap_index)
        {
            string s = "";

            foreach (cstr c in cs.strings)
            {
                s += c.s;
            }
            return(s.LastSpaceBeforeWrap(wrap_index));
        }
Example #2
0
        public static void WriteMapString(int r, int c, colorstring cs)
        {
            if (cs.Length() > 0)
            {
                r += Global.MAP_OFFSET_ROWS;
                c += Global.MAP_OFFSET_COLS;
                int cpos = c;
                foreach (cstr s1 in cs.strings)
                {
                    cstr s = new cstr(s1.s, s1.color, s1.bgcolor);
                    if (cpos - Global.MAP_OFFSET_COLS + s.s.Length > Global.COLS)
                    {
                        s.s = s.s.Substring(0, Global.COLS - (cpos - Global.MAP_OFFSET_COLS));
                    }
                    s.color   = ResolveColor(s.color);
                    s.bgcolor = ResolveColor(s.bgcolor);
                    colorchar cch = new colorchar(' ', s.color, s.bgcolor);

/*					cch.color = s.color;
 *                                      cch.bgcolor = s.bgcolor;*/
                    ConsoleColor co = GetColor(s.color);
                    if (ForegroundColor != co)
                    {
                        ForegroundColor = co;
                    }
                    co = GetColor(s.bgcolor);
                    if (BackgroundColor != co)
                    {
                        BackgroundColor = co;
                    }
                    int  i       = 0;
                    bool changed = false;
                    for (int ii = 0; ii < s.s.Length; ii++)
                    {
                        cch.c = s.s.CharAt(ii);
                        if (!memory[r, cpos + i].Equals(cch))
                        {
                            memory[r, cpos + i] = cch;
                            changed             = true;
                        }
                        ++i;
                    }
                    if (changed)
                    {
                        Game.Console.SetCursorPosition(cpos, r);
                        Game.Console.Write(s.s);
                    }
                    cpos += s.s.Length;
                }

                /*if(cpos-Global.MAP_OFFSET_COLS < Global.COLS){
                 *      WriteString(r,cpos,"".PadRight(Global.COLS-(cpos-Global.MAP_OFFSET_COLS)));
                 * }*/
            }
        }
Example #3
0
        public static colorstring operator +(colorstring one, colorstring two)
        {
            colorstring result = new colorstring();

            foreach (cstr s in one.strings)
            {
                result.strings.Add(s);
            }
            foreach (cstr s in two.strings)
            {
                result.strings.Add(s);
            }
            return(result);
        }
Example #4
0
        public static void WriteString(int r, int c, colorstring cs)
        {
            if (cs.Length() > 0)
            {
                int pos = c;
                foreach (cstr s1 in cs.strings)
                {
                    cstr s = new cstr(s1.s, s1.color, s1.bgcolor);
                    if (s.s.Length + pos > Global.SCREEN_W)
                    {
                        s.s = s.s.Substring(0, Global.SCREEN_W - pos);
                    }
                    s.color   = ResolveColor(s.color);
                    s.bgcolor = ResolveColor(s.bgcolor);
                    colorchar cch = new colorchar(' ', s.color, s.bgcolor);

                    /*cch.color = s.color;
                     * cch.bgcolor = s.bgcolor;*/
                    ConsoleColor co = GetColor(s.color);
                    if (ForegroundColor != co)
                    {
                        ForegroundColor = co;
                    }
                    co = GetColor(s.bgcolor);
                    if (BackgroundColor != co)
                    {
                        BackgroundColor = co;
                    }
                    int  i       = 0;
                    bool changed = false;
                    for (int ii = 0; ii < s.s.Length; ii++)
                    {
                        cch.c = s.s.CharAt(ii);
                        if (!memory[r, pos + i].Equals(cch))
                        {
                            memory[r, pos + i] = cch;
                            changed            = true;
                        }
                        ++i;
                    }
                    if (changed)
                    {
                        Game.Console.SetCursorPosition(pos, r);
                        Game.Console.Write(s.s);
                    }
                    pos += s.s.Length;
                }
            }
        }
Example #5
0
 public static colorstring GetColorString(this string s, Color color)
 {
     if (s.Search(new Regex(@"\[")) > -1)
     {
         string      temp   = s;
         colorstring result = new colorstring();
         while (temp.Search(new Regex(@"\[")) > -1)
         {
             int open  = temp.IndexOf("[");
             int close = temp.IndexOf("]");
             if (close == -1)
             {
                 result.strings.Add(new cstr(temp, color));
                 temp = "";
             }
             else
             {
                 int hyphen = temp.IndexOf("-");
                 if (hyphen != -1 && hyphen > open && hyphen < close)
                 {
                     result.strings.Add(new cstr(temp.Substring(0, open + 1), color));
                     //result.strings.Add(new cstr(temp.Substring(open+1,(close-open)-1),Color.Cyan));
                     result.strings.Add(new cstr(temp.Substring(open + 1, hyphen), Color.Cyan));                         //was hyphen - open
                     result.strings.Add(new cstr("-", color));
                     result.strings.Add(new cstr(temp.Substring(hyphen + 1, (close)), Color.Cyan));                      // was close - hyphen
                     result.strings.Add(new cstr("]", color));
                     temp = temp.Substring(close + 1);
                 }
                 else
                 {
                     result.strings.Add(new cstr(temp.Substring(0, open + 1), color));
                     result.strings.Add(new cstr(temp.Substring(open + 1, (close)), Color.Cyan)); // was close-open
                     result.strings.Add(new cstr("]", color));
                     temp = temp.Substring(close + 1);
                 }
             }
         }
         if (temp != "")
         {
             result.strings.Add(new cstr(temp, color));
         }
         return(result);
     }
     else
     {
         return(new colorstring(s, color));
     }
 }
 public static colorstring GetColorString(this string s, Color text_color, Color key_color)
 {
     if (s.Contains("["))
     {
         string      temp   = s;
         colorstring result = new colorstring();
         while (temp.Contains("["))
         {
             int open  = temp.IndexOf('[');
             int close = temp.IndexOf(']');
             if (close == -1)
             {
                 result.strings.Add(new cstr(temp, text_color));
                 temp = "";
             }
             else
             {
                 int hyphen = temp.IndexOf('-');
                 if (hyphen != -1 && hyphen > open && hyphen < close)
                 {
                     result.strings.Add(new cstr(temp.Substring(0, open + 1), text_color));
                     //result.strings.Add(new cstr(temp.Substring(open+1,(close-open)-1),Color.Cyan));
                     result.strings.Add(new cstr(temp.Substring(open + 1, (hyphen - open) - 1), key_color));
                     result.strings.Add(new cstr("-", text_color));
                     result.strings.Add(new cstr(temp.Substring(hyphen + 1, (close - hyphen) - 1), key_color));
                     result.strings.Add(new cstr("]", text_color));
                     temp = temp.Substring(close + 1);
                 }
                 else
                 {
                     result.strings.Add(new cstr(temp.Substring(0, open + 1), text_color));
                     result.strings.Add(new cstr(temp.Substring(open + 1, (close - open) - 1), key_color));
                     result.strings.Add(new cstr("]", text_color));
                     temp = temp.Substring(close + 1);
                 }
             }
         }
         if (temp != "")
         {
             result.strings.Add(new cstr(temp, text_color));
         }
         return(result);
     }
     else
     {
         return(new colorstring(s, text_color));
     }
 }
Example #7
0
 public void IncreaseSkill(SkillType skill)
 {
     List<string> learned = new List<string>();
     skills[skill]++;
     bool active_feat_learned = false;
     B.Add("You feel a rush of power. ");
     B.PrintAll();
     ConsoleKeyInfo command;
     bool gain_feat = false;
     if(!M.feat_gained_this_level){
         if(Feat.NumberOfFeats(skill,feats_in_order) < 4){
             List<List<SkillType>> skill_groups = new List<List<SkillType>>{new List<SkillType>{tile().type.GetAssociatedSkill()}};
             for(int i=0;i<ROWS;++i){
                 for(int j=0;j<COLS;++j){
                     if(M.tile[i,j].IsShrine() && M.tile[i,j].type != TileType.SPELL_EXCHANGE_SHRINE && this.DistanceFrom(i,j) > 2){
                         foreach(var list in skill_groups){
                             foreach(SkillType s in list){
                                 if(s == M.tile[i,j].type.GetAssociatedSkill()){
                                     goto NoAdd;
                                 }
                             }
                         }
                         List<SkillType> newlist = new List<SkillType>();
                         foreach(Tile t in M.tile[i,j].TilesWithinDistance(2)){
                             if(t.IsShrine() && t.type != TileType.SPELL_EXCHANGE_SHRINE){
                                 SkillType newskill = t.type.GetAssociatedSkill();
                                 if(Feat.NumberOfFeats(newskill,feats_in_order) >= 4){
                                     goto NoAdd;
                                 }
                                 newlist.Add(newskill);
                             }
                         }
                         skill_groups.Add(newlist);
                         NoAdd: continue;
                     }
                 }
             }
             if(M.nextLevelShrines?.Count > 0){
                 List<SchismDungeonGenerator.CellType> nextShrines = new List<SchismDungeonGenerator.CellType>(M.nextLevelShrines);
                 while(nextShrines.Count > 0){
                     List<SkillType> newlist = new List<SkillType>();
                     newlist.Add(nextShrines.RemoveFirst().GetAssociatedSkill());
                     if(nextShrines.Count > 0){
                         newlist.Add(nextShrines.RemoveFirst().GetAssociatedSkill());
                     }
                     foreach(SkillType newskill in newlist){
                         if(Feat.NumberOfFeats(newskill,feats_in_order) >= 4){
                             goto NoAdd;
                         }
                     }
                     skill_groups.Add(newlist);
                     NoAdd: continue;
                 }
             }
             if(skill_groups.Random().Contains(skill)){
                 gain_feat = true;
             }
         }
     }
     if(gain_feat){
         M.feat_gained_this_level = true;
         FeatType feat_chosen = FeatType.NO_FEAT;
         bool done = false;
         MouseUI.PushButtonMap();
         for(int i=0;i<4;++i){
             MouseUI.CreateMapButton((ConsoleKey)(ConsoleKey.A + i),false,1 + i*5,5);
         }
         MouseUI.CreateButton(ConsoleKey.Oem2,true,Global.MAP_OFFSET_ROWS + ROWS-1,Global.MAP_OFFSET_COLS + 32,1,12);
         while(!done){
             Screen.ResetColors();
             Screen.WriteMapString(0,0,"".PadRight(COLS,'-'));
             for(int i=0;i<4;++i){
                 FeatType ft = Feat.OfSkill(skill,i);
                 Color featcolor = (feat_chosen == ft)? Color.Green : Color.Gray;
                 Color lettercolor = Color.Cyan;
                 if(HasFeat(ft)){
                     featcolor = Color.Magenta;
                     lettercolor = Color.DarkRed;
                 }
                 Screen.WriteMapString(1+i*5,0,("["+(char)(i+97)+"] "));
                 Screen.WriteMapChar(1+i*5,1,(char)(i+97),lettercolor);
                 Screen.WriteMapString(1+i*5,4,Feat.Name(ft).PadRight(30),featcolor);
                 if(Feat.IsActivated(ft)){
                     Screen.WriteMapString(1+i*5,30,"        Active".PadToMapSize(),featcolor);
                 }
                 else{
                     Screen.WriteMapString(1+i*5,30,"        Passive".PadToMapSize(),featcolor);
                 }
                 List<string> desc = Feat.Description(ft);
                 for(int j=0;j<4;++j){
                     if(desc.Count > j){
                         Screen.WriteMapString(2+j+i*5,0,"    " + desc[j].PadRight(64),featcolor);
                     }
                     else{
                         Screen.WriteMapString(2+j+i*5,0,"".PadRight(66));
                     }
                 }
             }
             if(feat_chosen != FeatType.NO_FEAT){
                 Screen.WriteMapString(21,0,"--Type [a-d] to choose a feat---[?] for help---[Enter] to accept--");
                 Screen.WriteMapChar(21,8,new colorchar(Color.Cyan,'a'));
                 Screen.WriteMapChar(21,10,new colorchar(Color.Cyan,'d'));
                 Screen.WriteMapChar(21,33,new colorchar(Color.Cyan,'?'));
                 Screen.WriteMapString(21,48,new cstr(Color.Magenta,"Enter"));
                 MouseUI.CreateButton(ConsoleKey.Enter,false,Global.MAP_OFFSET_ROWS + ROWS-1,Global.MAP_OFFSET_COLS + 47,1,17);
             }
             else{
                 Screen.WriteMapString(21,0,"--Type [a-d] to choose a feat---[?] for help----------------------");
                 Screen.WriteMapChar(21,8,new colorchar(Color.Cyan,'a'));
                 Screen.WriteMapChar(21,10,new colorchar(Color.Cyan,'d'));
                 Screen.WriteMapChar(21,33,new colorchar(Color.Cyan,'?'));
                 MouseUI.RemoveButton(Global.MAP_OFFSET_ROWS + ROWS-1,Global.MAP_OFFSET_COLS + 47);
             }
             B.DisplayNow("Your " + Skill.Name(skill) + " skill increases to " + skills[skill] + ". Choose a feat: ");
             if(!Help.displayed[TutorialTopic.Feats]){
                 Help.TutorialTip(TutorialTopic.Feats,true);
                 B.DisplayNow("Your " + Skill.Name(skill) + " skill increases to " + skills[skill] + ". Choose a feat: ");
             }
             Screen.CursorVisible = true;
             command = Input.ReadKey();
             Screen.CursorVisible = false;
             char ch = command.GetCommandChar();
             switch(ch){
             case 'a':
             case 'b':
             case 'c':
             case 'd':
             {
                 FeatType ft = Feat.OfSkill(skill,(int)(ch-97));
                 int i = (int)(ch - 'a');
                 if(feat_chosen == ft){
                     feat_chosen = FeatType.NO_FEAT;
                     MouseUI.RemoveButton(Global.MAP_OFFSET_ROWS + 1 + i*5,60);
                     MouseUI.CreateMapButton((ConsoleKey)(ConsoleKey.A + i),false,1 + i*5,5);
                 }
                 else{
                     if(!HasFeat(ft)){
                         if(feat_chosen != FeatType.NO_FEAT){
                             int num = (int)feat_chosen % 4;
                             MouseUI.RemoveButton(Global.MAP_OFFSET_ROWS + 1 + num*5,60);
                             MouseUI.CreateMapButton((ConsoleKey)(ConsoleKey.A + num),false,1 + num*5,5);
                         }
                         feat_chosen = ft;
                         MouseUI.RemoveButton(Global.MAP_OFFSET_ROWS + 1 + i*5,60);
                         MouseUI.CreateMapButton(ConsoleKey.Enter,false,1 + i*5,5);
                     }
                 }
                 break;
             }
             case '?':
                 Help.DisplayHelp(HelpTopic.Feats);
                 UI.DisplayStats();
                 break;
             case (char)13:
                 if(feat_chosen != FeatType.NO_FEAT){
                     done = true;
                 }
                 break;
             default:
                 break;
             }
         }
         feats[feat_chosen] = true;
         feats_in_order.Add(feat_chosen);
         learned.Add("You master the " + Feat.Name(feat_chosen) + " feat. ");
         if(Feat.IsActivated(feat_chosen)){
             active_feat_learned = true;
         }
         MouseUI.PopButtonMap();
     }
     else{
         learned.Add("Your " + Skill.Name(skill) + " skill increases to " + skills[skill] + ". ");
     }
     if(skill == SkillType.MAGIC){
         maxmp += 5;
         curmp += 5;
         List<SpellType> unknown = new List<SpellType>();
         List<colorstring> unknownstr = new List<colorstring>();
         List<SpellType> random_spell_list = new List<SpellType>();
         foreach(SpellType spell in Enum.GetValues(typeof(SpellType))){
             random_spell_list.Add(spell);
         }
         while(unknown.Count < 5 && random_spell_list.Count > 0){
             SpellType spell = random_spell_list.RemoveRandom();
             if(!HasSpell(spell) && spell != SpellType.NO_SPELL && spell != SpellType.NUM_SPELLS){
                 unknown.Add(spell);
             }
         }
         unknown.Sort((sp1,sp2)=>Spell.Tier(sp1).CompareTo(Spell.Tier(sp2)));
         foreach(SpellType spell in unknown){
             colorstring cs = new colorstring();
             cs.strings.Add(new cstr(Spell.Name(spell).PadRight(17) + Spell.Tier(spell).ToString().PadLeft(3),Color.Gray));
             cs.strings.Add(new cstr("".PadRight(5),Color.Gray));
             unknownstr.Add(cs + Spell.Description(spell));
         }
         M.Draw();
         /*for(int i=unknown.Count+2;i<ROWS;++i){
             Screen.WriteMapString(i,0,"".PadRight(COLS));
         }*/
         Help.TutorialTip(TutorialTopic.SpellTiers);
         Screen.WriteMapString(unknown.Count+2,0,"".PadRight(COLS));
         colorstring topborder = new colorstring("---------------------Tier-----------------Description-------------",Color.Gray);
         int selection = Select("Learn which spell? ",topborder,new colorstring("".PadRight(25,'-') + "[",Color.Gray,"?",Color.Cyan,"] for help".PadRight(COLS,'-'),Color.Gray),unknownstr,false,true,false,true,HelpTopic.Spells);
         spells[unknown[selection]] = true;
         learned.Add("You learn " + Spell.Name(unknown[selection]) + ". ");
         spells_in_order.Add(unknown[selection]);
     }
     if(learned.Count > 0){
         foreach(string s in learned){
             B.Add(s);
         }
     }
     if(active_feat_learned){
         M.Draw();
         Help.TutorialTip(TutorialTopic.ActiveFeats);
     }
 }
Example #8
0
        public static int[] DisplayEquipment()
        {
            MouseUI.PushButtonMap();
            UI.draw_bottom_commands = false;
            UI.darken_status_bar = true;
            Weapon equippedWeapon = player.EquippedWeapon;
            Armor equippedArmor = player.EquippedArmor;
            WeaponType selectedWeapon = equippedWeapon.type;
            ArmorType selectedArmor = equippedArmor.type;
            List<MagicTrinketType> trinkets = player.magic_trinkets;
            int selectedTrinketIdx = -1;
            if(trinkets.Count > 0){
                selectedTrinketIdx = R.Roll(trinkets.Count)-1;
                int i = 0;
                foreach(MagicTrinketType trinket in trinkets){
                    MouseUI.CreateButton((ConsoleKey)(ConsoleKey.I + i),false,i+1+Global.MAP_OFFSET_ROWS,Global.MAP_OFFSET_COLS + 32,1,34);
                    ++i;
                }
            }
            Screen.Blank();
            Screen.WriteMapString(0,0,"".PadRight(COLS,'-'));
            int line = 1;
            for(WeaponType w = WeaponType.SWORD;w <= WeaponType.BOW;++w){
                Screen.WriteMapString(line,2,"[ ] " + player.WeaponOfType(w).EquipmentScreenName());
                ConsoleKey key = (ConsoleKey)(ConsoleKey.A + line-1);
                if(w == selectedWeapon){
                    key = ConsoleKey.Enter;
                }
                if(trinkets.Count >= line){
                    MouseUI.CreateButton(key,false,line+Global.MAP_OFFSET_ROWS,Global.MAP_OFFSET_COLS,1,32);
                }
                else{
                    MouseUI.CreateMapButton(key,false,line,1);
                }
                ++line;
            }
            line = 8;
            for(ArmorType a = ArmorType.LEATHER;a <= ArmorType.FULL_PLATE;++a){
                Screen.WriteMapString(line,2,"[ ] " + player.ArmorOfType(a).EquipmentScreenName());
                ConsoleKey key = (ConsoleKey)(ConsoleKey.A + line-3);
                if(a == selectedArmor){
                    key = ConsoleKey.Enter;
                }
                if(trinkets.Count >= line){
                    MouseUI.CreateButton(key,false,line+Global.MAP_OFFSET_ROWS,Global.MAP_OFFSET_COLS,1,32);
                }
                else{
                    MouseUI.CreateMapButton(key,false,line,1);
                }
                ++line;
            }
            line = 1;
            foreach(MagicTrinketType m in trinkets){
                Screen.WriteMapString(line,34,"[ ] " + MagicTrinket.Name(m).Capitalize());
                ++line;
            }
            Screen.WriteMapString(11,0,"".PadRight(COLS,'-'));
            ConsoleKeyInfo command;
            bool done = false;
            while(!done){
                line = 1;
                for(WeaponType w = WeaponType.SWORD;w <= WeaponType.BOW;++w){
                    char c = ' ';
                    Color letter_color = Color.Cyan;
                    if(equippedWeapon.status[EquipmentStatus.STUCK]){
                        letter_color = Color.Red;
                    }
                    if(selectedWeapon == w){
                        c = '>';
                        letter_color = Color.Red;
                    }
                    Screen.WriteMapChar(line,0,c);
                    Screen.WriteMapChar(line,3,(char)(w+(int)'a'),letter_color);
                    ++line;
                }
                line = 8;
                for(ArmorType a = ArmorType.LEATHER;a <= ArmorType.FULL_PLATE;++a){
                    char c = ' ';
                    Color letter_color = Color.Cyan;
                    if(equippedArmor.status[EquipmentStatus.STUCK]){
                        letter_color = Color.Red;
                    }
                    if(selectedArmor == a){
                        c = '>';
                        letter_color = Color.Red;
                    }
                    Screen.WriteMapChar(line,0,c);
                    Screen.WriteMapChar(line,3,(char)(a+(int)'f'),letter_color);
                    ++line;
                }
                line = 1;
                int letter = 0;
                foreach(MagicTrinketType m in trinkets){
                    if(selectedTrinketIdx == trinkets.IndexOf(m)){
                        Screen.WriteMapChar(line,32,'>');
                    }
                    else{
                        Screen.WriteMapChar(line,32,' ');
                    }
                    Screen.WriteMapChar(line,35,(char)(letter+(int)'i'),Color.Red);
                    ++line;
                    ++letter;
                }
                Weapon newWeapon = player.WeaponOfType(selectedWeapon);
                Armor newArmor = player.ArmorOfType(selectedArmor);
                MagicTrinketType selectedTrinket = selectedTrinketIdx >= 0? trinkets[selectedTrinketIdx] : MagicTrinketType.NO_MAGIC_TRINKET;
                List<colorstring> wStr = newWeapon.Description().GetColorStrings();
                wStr[0] = new colorstring("Weapon",Color.DarkRed,": ",Color.Gray) + wStr[0];
                List<colorstring> aStr = newArmor.Description().GetColorStrings();
                aStr[0] = new colorstring("Armor",Color.DarkCyan,": ",Color.Gray) + aStr[0];
                {
                    string wEnch = newWeapon.DescriptionOfEnchantment();
                    string aEnch = newArmor.DescriptionOfEnchantment();
                    if(wEnch != ""){
                        wStr.Add(new colorstring(wEnch,newWeapon.EnchantmentColor()));
                    }
                    if(aEnch != ""){
                        aStr.Add(new colorstring(aEnch,newArmor.EnchantmentColor()));
                    }
                }
                List<colorstring> mStr = MagicTrinket.Description(selectedTrinket).GetColorStrings();
                mStr[0] = new colorstring("Magic trinket",Color.DarkGreen,": ",Color.Gray) + mStr[0];
                if(mStr.Count > 1){
                    mStr[1] = "".PadRight(15) + mStr[1];
                }
                List<colorstring> wStatusShort = newWeapon.ShortStatusList();
                List<colorstring> aStatusShort = newArmor.ShortStatusList();

                int wMin = wStr.Count + wStatusShort.Count;
                int aMin = aStr.Count + aStatusShort.Count;

                int lines_free = 12 - wMin - aMin - mStr.Count;

                List<colorstring> wStatusLong = newWeapon.LongStatusList();
                List<colorstring> aStatusLong = newArmor.LongStatusList();
                int wDiff = wStatusLong.Count - wStatusShort.Count;
                int aDiff = aStatusLong.Count - aStatusShort.Count;

                bool expandW = false;
                bool expandA = false;
                if(wDiff + aDiff <= lines_free){ //if there's room to use the full versions of both, do that.
                    expandW = true;
                    expandA = true;
                }
                else{
                    if(wDiff > aDiff){ //otherwise, try to fit the biggest.
                        if(wDiff <= lines_free){
                            expandW = true;
                        }
                        else{
                            if(aDiff <= lines_free){
                                expandA = true;
                            } //if that doesn't work, we settle for the condensed version.
                        }
                    }
                    else{
                        if(aDiff <= lines_free){
                            expandA = true;
                        }
                        else{
                            if(wDiff <= lines_free){
                                expandW = true;
                            }
                        }
                    }
                }
                if(expandW){
                    wStr.AddRange(wStatusLong);
                    lines_free -= wDiff;
                }
                else{
                    wStr.AddRange(wStatusShort);
                }
                if(expandA){
                    aStr.AddRange(aStatusLong);
                    lines_free -= aDiff;
                }
                else{
                    aStr.AddRange(aStatusShort);
                }

                List<colorstring> top = new List<colorstring>();

                //now let's distribute those extra lines. (0-7 possible)
                for(int i=0;i<2;++i){ //space between sections, then at the bottom. This takes care of 6 lines.
                    if(lines_free >= 2){
                        lines_free -= 2;
                        wStr.Add(new colorstring(""));
                        aStr.Add(new colorstring(""));
                    }
                    if(lines_free >= 1){
                        lines_free -= 1;
                        mStr.Add(new colorstring(""));
                    }
                }
                if(lines_free >= 1){ //if there's one left, it means that we had the full 7 lines, so we need an extra space at the top.
                    lines_free -= 1;
                    top.Add(new colorstring(""));
                }

                int row = 12;
                foreach(List<colorstring> list in new List<List<colorstring>>{top,wStr,aStr,mStr}){
                    foreach(colorstring cs in list){
                        Screen.WriteMapString(row++,0,cs.PadRight(COLS));
                    }
                }

                if(newWeapon == equippedWeapon && newArmor == equippedArmor){
                    Screen.WriteMapString(row,0,"".PadRight(COLS,'-'));
                    MouseUI.RemoveButton(Global.MAP_OFFSET_ROWS+row,Global.MAP_OFFSET_COLS);
                }
                else{
                    if((newWeapon != equippedWeapon && equippedWeapon.status[EquipmentStatus.STUCK]) || (newArmor != equippedArmor && equippedArmor.status[EquipmentStatus.STUCK])){
                        Screen.WriteMapString(row,0,"".PadRight(COLS,'-'));
                        MouseUI.RemoveButton(Global.MAP_OFFSET_ROWS+row,Global.MAP_OFFSET_COLS);
                    }
                    else{
                        Screen.WriteMapString(row,0,new colorstring("[",Color.Gray,"Enter",Color.Magenta,"] to confirm",Color.Gray).PadOuter(COLS,'-'));
                        MouseUI.CreateMapButton(ConsoleKey.Enter,false,row,1);
                    }
                }

                Screen.ResetColors();
                B.DisplayNow("Your equipment: ");
                Screen.CursorVisible = true;
                command = Input.ReadKey();
                char ch = command.GetCommandChar();
                switch(ch){
                case 'a':
                case 'b':
                case 'c':
                case 'd':
                case 'e':
                case '!':
                case '@':
                case '#':
                case '$':
                case '%':
                {
                    switch(ch){
                    case '!':
                    ch = 'a';
                    break;
                    case '@':
                    ch = 'b';
                    break;
                    case '#':
                    ch = 'c';
                    break;
                    case '$':
                    ch = 'd';
                    break;
                    case '%':
                    ch = 'e';
                    break;
                    }
                    int num = (int)(ch - 'a');
                    if(num != (int)(selectedWeapon)){
                        MouseUI.GetButton((int)(selectedWeapon)+1+Global.MAP_OFFSET_ROWS,Global.MAP_OFFSET_COLS).key = (ConsoleKey)(ConsoleKey.A + (int)selectedWeapon);
                        MouseUI.GetButton(num+1+Global.MAP_OFFSET_ROWS,Global.MAP_OFFSET_COLS).key = ConsoleKey.Enter;
                        selectedWeapon = (WeaponType)num;
                    }
                    break;
                }
                case 'f':
                case 'g':
                case 'h':
                case '*':
                case '(':
                case ')':
                {
                    switch(ch){
                    case '*':
                    ch = 'f';
                    break;
                    case '(':
                    ch = 'g';
                    break;
                    case ')':
                    ch = 'h';
                    break;
                    }
                    int num = (int)(ch - 'f');
                    if(num != (int)(selectedArmor)){
                        MouseUI.GetButton((int)(selectedArmor)+8+Global.MAP_OFFSET_ROWS,Global.MAP_OFFSET_COLS).key = (ConsoleKey)(ConsoleKey.F + (int)selectedArmor);
                        MouseUI.GetButton(num+8+Global.MAP_OFFSET_ROWS,Global.MAP_OFFSET_COLS).key = ConsoleKey.Enter;
                        selectedArmor = (ArmorType)num;
                    }
                    break;
                }
                case 'i':
                case 'j':
                case 'k':
                case 'l':
                case 'm':
                case 'n':
                case 'o':
                case 'p':
                case 'q':
                case 'r':
                {
                    int num = (int)ch - (int)'i';
                    if(num < trinkets.Count && num != selectedTrinketIdx){
                        selectedTrinketIdx = num;
                    }
                    break;
                }
                case (char)27:
                case ' ':
                selectedWeapon = equippedWeapon.type; //reset
                selectedArmor = equippedArmor.type;
                done = true;
                break;
                case (char)13:
                done = true;
                break;
                default:
                break;
                }
            }
            MouseUI.PopButtonMap();
            UI.draw_bottom_commands = true;
            UI.darken_status_bar = false;
            return new int[]{(int)selectedWeapon,(int)selectedArmor};
        }
Example #9
0
        public static int DisplayCharacterInfo(bool readkey)
        {
            //todo remove old version in Actor
            MouseUI.PushButtonMap();
            UI.DisplayStats();
            UI.draw_bottom_commands = false;
            UI.darken_status_bar = true;

            const Color c = Color.Green;
            const Color text = Color.Gray;
            List<colorstring> top = new List<colorstring>{new colorstring("".PadRight(COLS,'-'),text)};
            List<colorstring> name = new List<colorstring>{(new cstr("Name",c) + new cstr(": " + Actor.player_name,text)).PadRight(COLS/2) + (new cstr("Turns played",c) + new cstr(": " + Q.turn/100,text))};
            List<colorstring> skills = null;
            List<colorstring> feats = null;
            List<colorstring> spells = null;
            List<colorstring> trinkets = null;
            List<colorstring> divider = new List<colorstring>{new colorstring("Active abilities",c,":",text)};
            List<colorstring> actives = new List<colorstring>();

            List<List<colorstring>> potential_skills = new List<List<colorstring>>();
            for(int indent=7;indent>=1;--indent){
                List<colorstring> list = new List<colorstring>{new colorstring("Skills",c,":",text)};
                potential_skills.Add(list);
                for(SkillType sk = SkillType.COMBAT;sk < SkillType.NUM_SKILLS;++sk){
                    int skill_base = player.skills[sk];
                    int skill_mod = player.BonusSkill(sk);
                    colorstring skill_string = new colorstring(" " + Skill.Name(sk) + "(",text,skill_base.ToString(),Color.White);
                    if(skill_mod > 0){
                        skill_string.Add($"+{skill_mod}",Color.Yellow);
                    }
                    else{
                        if(skill_mod < 0){
                            skill_string.strings.Add(new cstr(skill_mod.ToString(),Color.Blue));
                        }
                    }
                    skill_string.strings.Add(new cstr(")",text));
                    list.AddWithWrap(skill_string,Global.COLS,indent);
                }
            }
            skills = potential_skills.WhereLeast(x=>x.Count)[0]; //Take the first result (i.e. highest indent) from the lowest count.

            List<List<colorstring>> potential_feats = new List<List<colorstring>>();
            for(int indent=6;indent>=1;--indent){
                List<colorstring> list = new List<colorstring>{new colorstring("Feats",c,":",text)};
                potential_feats.Add(list);
                for(int i=0;i<Actor.feats_in_order.Count;++i){
                    string comma = (i == Actor.feats_in_order.Count - 1)? "" : ",";
                    colorstring feat_string = new colorstring(" " + Feat.Name(Actor.feats_in_order[i]) + comma);
                    list.AddWithWrap(feat_string,Global.COLS,indent);
                }
            }
            feats = potential_feats.WhereLeast(x=>x.Count)[0]; //Take the first result (i.e. highest indent) from the lowest count.

            List<List<colorstring>> potential_spells = new List<List<colorstring>>();
            for(int indent=7;indent>=1;--indent){
                List<colorstring> list = new List<colorstring>{new colorstring("Spells",c,":",text)};
                potential_spells.Add(list);
                for(int i=0;i<Actor.spells_in_order.Count;++i){
                    string comma = (i == Actor.spells_in_order.Count - 1)? "" : ",";
                    colorstring spell_string = new colorstring(" " + Spell.Name(Actor.spells_in_order[i]) + comma);
                    list.AddWithWrap(spell_string,Global.COLS,indent);
                }
            }
            spells = potential_spells.WhereLeast(x=>x.Count)[0]; //Take the first result (i.e. highest indent) from the lowest count.

            List<string> magic_equipment_names = new List<string>();
            foreach(Weapon w in player.weapons){
                if(w.IsEnchanted()){
                    magic_equipment_names.Add(w.NameWithEnchantment());
                }
            }
            foreach(Armor a in player.armors){
                if(a.IsEnchanted()){
                    magic_equipment_names.Add(a.NameWithEnchantment());
                }
            }
            foreach(MagicTrinketType trinket in player.magic_trinkets){
                magic_equipment_names.Add(MagicTrinket.Name(trinket));
            }

            List<List<colorstring>> potential_trinkets = new List<List<colorstring>>();
            for(int indent=18;indent>=1;--indent){ //todo keep this value?
                List<colorstring> list = new List<colorstring>{new colorstring("Magical equipment",c,":",text)};
                potential_trinkets.Add(list);
                for(int i=0;i<magic_equipment_names.Count;++i){
                    string comma = (i == magic_equipment_names.Count - 1)? "" : ",";
                    colorstring equip_string = new colorstring(" " + magic_equipment_names[i].Capitalize() + comma);
                    list.AddWithWrap(equip_string,Global.COLS,indent);
                }
            }
            trinkets = potential_trinkets.WhereLeast(x=>x.Count)[0]; //Take the first result (i.e. highest indent) from the lowest count.

            List<FeatType> active_feats = new List<FeatType>();

            foreach(FeatType f in Actor.feats_in_order){
                if(Feat.IsActivated(f)){
                    active_feats.Add(f);
                }
            }

            for(int i=0;i<active_feats.Count;++i){
                actives.Add(new colorstring("  [",text,((char)(i+'a')).ToString(),Color.Cyan,"] " + Feat.Name(active_feats[i]),text));
            }

            //eventually activated trinkets or temporary effects will go here.

            const int total_height = Global.SCREEN_H - Global.MAP_OFFSET_ROWS;
            List<List<colorstring>> all = new List<List<colorstring>>{top,name,skills,feats,spells,trinkets,divider,actives};
            List<List<colorstring>> some = new List<List<colorstring>>{name,skills,feats,spells};
            List<List<colorstring>> top_titles = new List<List<colorstring>>{name,skills,feats,spells,trinkets};
            int rows_left = total_height - 1; // -1 for the bottom border
            foreach(var list in all){
                rows_left -= list.Count;
            }

            //Here's how the extra rows are distributed:
            if(rows_left >= 1){
                trinkets.Add(new colorstring(""));
                --rows_left;
            }

            if(rows_left >= 1){
                actives.Add(new colorstring(""));
                --rows_left;
            }

            List<List<colorstring>> cramped = new List<List<colorstring>>();
            foreach(var list in some){
                if(list.Count == 1){
                    cramped.Add(list); //a list is considered cramped if its title (in green) is right next to another title.
                }
            }
            if(rows_left >= cramped.Count){
                foreach(var list in cramped){
                    list.Add(new colorstring(""));
                    --rows_left;
                }
            }

            List<List<colorstring>> no_blank_line = new List<List<colorstring>>();
            foreach(var list in some){
                if(list.Last().Length() > 0){
                    no_blank_line.Add(list); //this time, we try to put a space between each list and the next title.
                }
            }
            if(rows_left >= no_blank_line.Count){
                foreach(var list in no_blank_line){
                    list.Add(new colorstring(""));
                    --rows_left;
                }
            }

            /*if(rows_left >= 1){
                divider.Add(new colorstring(""));
                --rows_left;
            }*/

            int top_text_height = 0;
            foreach(var list in top_titles){
                top_text_height += list.Count;
            }
            if(rows_left >= 1 && top_text_height < 14){
                top.Add(new colorstring(""));
                --rows_left;
            }

            for(int i=0;i<rows_left;++i){
                actives.Add(new colorstring(""));
            }

            int row = 0;
            foreach(var list in all){
                foreach(colorstring cs in list){
                    Screen.WriteMapString(row,0,cs.PadRight(COLS));
                    ++row;
                }
            }
            Screen.WriteMapString(row,0,"".PadRight(COLS,'-'),text);
            Screen.ResetColors();
            B.DisplayNow("Character information: ");
            Screen.CursorVisible = true;

            int result = -1;
            if(readkey){
                result = player.GetSelection("Character information: ",active_feats.Count,false,true,false); //todo, currently only feats.
            }
            MouseUI.PopButtonMap();
            UI.draw_bottom_commands = true;
            UI.darken_status_bar = false;
            return result;
        }
Example #10
0
 public override List<colorstring> GetStatusBarInfo()
 {
     List<colorstring> result = new List<colorstring>();
     Color text = UI.darken_status_bar? Colors.status_darken : Color.Gray;
     if(p.Equals(UI.MapCursor)){
         text = UI.darken_status_bar? Colors.status_highlight_darken : Colors.status_highlight;
     }
     foreach(string s in Name(true).GetWordWrappedList(17,true)){
         colorstring cs = new colorstring();
         result.Add(cs);
         if(result.Count == 1){
             Color c = color;
             if(!revealed_by_light && !IsLit()){
                 c = Colors.darkcolor;
             }
             cs.strings.Add(new cstr(symbol.ToString(),c));
             cs.strings.Add(new cstr(": " + s,text));
         }
         else{
             cs.strings.Add(new cstr("   " + s,text));
         }
     }
     return result;
 }
		public static void WriteString(int r,int c,colorstring cs){
			if(cs.Length() > 0){
				int pos = c;
				foreach(cstr s1 in cs.strings){
					cstr s = new cstr(s1.s,s1.color,s1.bgcolor);
					if(s.s.Length + pos > Global.SCREEN_W){
						s.s = s.s.Substring(0,Global.SCREEN_W - pos);
					}
					s.color = ResolveColor(s.color);
					s.bgcolor = ResolveColor(s.bgcolor);
                    colorchar cch = new colorchar(' ', s.color, s.bgcolor);
					/*cch.color = s.color;
					cch.bgcolor = s.bgcolor;*/
					ConsoleColor co = GetColor(s.color);
					if(ForegroundColor != co){
						ForegroundColor = co;
					}
					co = GetColor(s.bgcolor);
					if(BackgroundColor != co){
						BackgroundColor = co;
					}
					int i = 0;
                    bool changed = false;
                    for (int ii = 0; ii < s.s.Length; ii++)
                    {
                        cch.c = s.s.CharAt(ii);
						if(!memory[r,pos+i].Equals(cch)){
							memory[r,pos+i] = cch;
							changed = true;
						}
						++i;
					}
					if(changed){
						Game.Console.SetCursorPosition(pos,r);
						Game.Console.Write(s.s);
					}
					pos += s.s.Length;
				}
			}
		}
Example #12
0
 public List<colorstring> ShortStatusList()
 {
     List<colorstring> result = new List<colorstring>();
     List<EquipmentStatus> list = new List<EquipmentStatus>();
     for(int i=0;i<(int)EquipmentStatus.NUM_STATUS;++i){
         EquipmentStatus st = (EquipmentStatus)i;
         if(status[st]){
             list.Add(st);
         }
     }
     for(int i=0;i<list.Count;++i){
         EquipmentStatus st = list[i];
         string comma = (i == list.Count - 1)? "" : ",";
         colorstring statusString = new colorstring(" " + StatusName(st) + comma,StatusColor(st));
         result.AddWithWrap(statusString,Global.COLS - 2,1);
     }
     if(result.Count > 2){ //hard cap at 2 lines
         result.RemoveRange(2,result.Count - 2);
     }
     for(int i=0;i<result.Count;++i){
         result[i] = result[i].PadOuter(Global.COLS);
     }
     return result;
 }
Example #13
0
 public colorstring EquipmentScreenName()
 {
     colorstring result = new colorstring(NameWithEnchantment().Capitalize() + " ",EnchantmentColor());
     for(int i=0;i<(int)EquipmentStatus.NUM_STATUS;++i){
         if(status[(EquipmentStatus)i]){
             result.strings.Add(new cstr("*",StatusColor((EquipmentStatus)i)));
             if(result.Length() >= 25){
                 break;
             }
         }
     }
     return result;
 }
Example #14
0
 public colorstring(colorstring other)
 {
     foreach(cstr cs in other.strings){
         strings.Add(cs);
     }
 }
Example #15
0
 public static void WriteMapString(int r,int c,colorstring cs)
 {
     if(cs.Length() > 0){
         r += Global.MAP_OFFSET_ROWS;
         c += Global.MAP_OFFSET_COLS;
         int start_col = -1;
         int end_col = -1;
         int cpos = c;
         foreach(cstr s1 in cs.strings){
             cstr s = new cstr(s1.s,s1.color,s1.bgcolor);
             if(cpos-Global.MAP_OFFSET_COLS + s.s.Length > Global.COLS){
                 s.s = s.s.Substring(0,Global.COLS-(cpos-Global.MAP_OFFSET_COLS));
             }
             s.color = Colors.ResolveColor(s.color);
             s.bgcolor = Colors.ResolveColor(s.bgcolor);
             colorchar cch;
             cch.color = s.color;
             cch.bgcolor = s.bgcolor;
             if(!GLMode){
                 ConsoleColor co = Colors.GetColor(s.color);
                 if(ForegroundColor != co){
                     ForegroundColor = co;
                 }
                 co = Colors.GetColor(s.bgcolor);
                 if(BackgroundColor != co){
                     BackgroundColor = co;
                 }
             }
             int i = 0;
             bool changed = false;
             foreach(char ch in s.s){
                 cch.c = ch;
                 if(!memory[r,cpos+i].Equals(cch)){
                     memory[r,cpos+i] = cch;
                     if(start_col == -1){
                         start_col = cpos+i;
                     }
                     end_col = cpos+i;
                     changed = true;
                 }
                 ++i;
             }
             if(changed && !GLMode){
                 Console.SetCursorPosition(cpos,r);
                 Console.Write(s.s);
             }
             cpos += s.s.Length;
         }
         if(GLMode && !NoGLUpdate && start_col != -1){
             UpdateGLBuffer(r,start_col,r,end_col);
         }
         if(MouseUI.AutomaticButtonsFromStrings && GLMode){
             int idx = -1;
             int len = cs.Length();
             for(int i=0;i<len;++i){
                 if(cs[i].c == '['){
                     idx = i;
                     break;
                 }
             }
             if(idx != -1 && idx+1 < cs.Length()){
                 ConsoleKey key = ConsoleKey.A;
                 bool shifted = false;
                 switch(cs[idx+1].c){
                 case 'E':
                     key = ConsoleKey.Enter;
                     break;
                 case 'T':
                     key = ConsoleKey.Tab;
                     break;
                 case 'P': //"Press any key"
                     break;
                 case '?':
                     key = ConsoleKey.Oem2;
                     shifted = true;
                     break;
                 case '=':
                     key = ConsoleKey.OemPlus;
                     break;
                 default: //all others should be lowercase letters
                     key = (ConsoleKey)(ConsoleKey.A + ((int)cs[idx+1].c - (int)'a'));
                     break;
                 }
                 MouseUI.CreateMapButton(key,shifted,r-Global.MAP_OFFSET_ROWS,1);
             }
         }
         /*if(cpos-Global.MAP_OFFSET_COLS < Global.COLS){
             WriteString(r,cpos,"".PadRight(Global.COLS-(cpos-Global.MAP_OFFSET_COLS)));
         }*/
     }
 }
Example #16
0
        public static async Task TutorialTip(TutorialTopic topic)
        {
            if (Global.Option(OptionType.NEVER_DISPLAY_TIPS) || displayed[topic])
            {
                return;
            }
            Color box_edge_color   = Color.Blue;
            Color box_corner_color = Color.Yellow;
            Color first_line_color = Color.Yellow;
            Color text_color       = Color.Gray;

            string[] text        = TutorialText(topic);
            int      stringwidth = 27;        // length of "[Press any key to continue]"

            foreach (string s in text)
            {
                if (s.Length > stringwidth)
                {
                    stringwidth = s.Length;
                }
            }
            stringwidth += 4;             //2 blanks on each side
            int boxwidth  = stringwidth + 2;
            int boxheight = text.Length + 5;

            //for(bool done=false;!done;){
            colorstring[] box = new colorstring[boxheight];             //maybe i should make this a list to match the others
            box[0] = new colorstring("+", box_corner_color, "".PadRight(stringwidth, '-'), box_edge_color, "+", box_corner_color);
            box[text.Length + 1] = new colorstring("|", box_edge_color, "".PadRight(stringwidth), Color.Gray, "|", box_edge_color);
            box[text.Length + 2] = new colorstring("|", box_edge_color) + ("[Press any key to continue]".PadOuter(stringwidth).GetColorString(text_color)) + new colorstring("|", box_edge_color); //PadOuter originally here
            box[text.Length + 3] = new colorstring("|", box_edge_color) + ("[=] Stop showing tips".PadOuter(stringwidth).GetColorString(text_color)) + new colorstring("|", box_edge_color);       //PadOuter originally here
            box[text.Length + 4] = new colorstring("+", box_corner_color, "".PadRight(stringwidth, '-'), box_edge_color, "+", box_corner_color);
            int pos = 1;

            foreach (string s in text)
            {
                box[pos] = new colorstring("|", box_edge_color) + (s.PadOuter(stringwidth).GetColorString(text_color)) + new colorstring("|", box_edge_color); //PadOuter originally here
                if (pos == 1)
                {
                    box[pos] = new colorstring();
                    box[pos].strings.Add(new cstr("|", box_edge_color));
                    box[pos].strings.Add(new cstr(s.PadOuter(stringwidth), first_line_color)); //PadOuter originally here
                    box[pos].strings.Add(new cstr("|", box_edge_color));
                }
                ++pos;
            }
            int y = (Global.SCREEN_H - boxheight) / 2;
            int x = (Global.SCREEN_W - boxwidth) / 2;

            colorchar[,] memory = Screen.GetCurrentRect(y, x, boxheight, boxwidth);
            List <List <colorstring> > frames = new List <List <colorstring> >();

            frames.Add(BoxAnimationFrame(boxheight - 2, FrameWidth(boxheight, boxwidth)));
            for (int i = boxheight - 4; i > 0; i -= 2)
            {
                frames.Add(BoxAnimationFrame(i, FrameWidth(frames.Last().Count, frames.Last()[0].Length())));
            }
            for (int i = frames.Count - 1; i >= 0; --i)     //since the frames are in reverse order
            {
                int y_offset = i + 1;
                int x_offset = (boxwidth - frames[i][0].Length()) / 2;
                Screen.WriteList(y + y_offset, x + x_offset, frames[i]);
                await Task.Delay(20);
            }
            foreach (colorstring s in box)
            {
                Screen.WriteString(y, x, s);
                ++y;
            }
            Actor.player.DisplayStats(false);
            if (topic != TutorialTopic.Feats)             //hacky exception - don't get rid of the line that's already there.
            {
                Actor.B.DisplayNow();
            }
            Game.Console.CursorVisible = false;
            await Task.Delay(500);

            Global.FlushInput();

            /*	switch(Game.Console.ReadKey(true).KeyChar){
             *      case 'q':
             *              box_edge_color = NextColor(box_edge_color);
             *              break;
             *      case 'w':
             *              box_corner_color = NextColor(box_corner_color);
             *              break;
             *      case 'e':
             *              first_line_color = NextColor(first_line_color);
             *              break;
             *      case 'r':
             *              text_color = NextColor(text_color);
             *              break;
             *      default:
             *              done=true;
             *              break;
             *      }
             * }*/
            if ((await Game.Console.ReadKey(true)).KeyChar == '=')
            {
                Global.Options[OptionType.NEVER_DISPLAY_TIPS] = true;
            }
            Screen.WriteArray((Global.SCREEN_H - boxheight) / 2, x, memory);
            if (topic != TutorialTopic.Feats)             //another exception
            {
                Actor.player.DisplayStats(true);
            }
            displayed[topic]           = true;
            Game.Console.CursorVisible = true;
        }
 public async Task<bool> InputHuman()
 {
     DisplayStats(true);
     if (HasFeat(FeatType.DANGER_SENSE))
     {
         M.UpdateDangerValues();
     }
     M.Draw();
     if (HasAttr(AttrType.AUTOEXPLORE))
     {
         if (path.Count == 0)
         {
             if (!FindAutoexplorePath())
             {
                 B.Add("You don't see a path for further exploration. ");
             }
         }
     }
     if (!HasAttr(AttrType.AFRAID) && !HasAttr(AttrType.PARALYZED) && !HasAttr(AttrType.FROZEN) && !HasAttr(AttrType.ASLEEP))
     {
         await B.Print(false);
     }
     else
     {
         B.DisplayNow();
     }
     Cursor();
     Game.Console.CursorVisible = true;
     if (HasAttr(AttrType.PARALYZED) || HasAttr(AttrType.AFRAID) || HasAttr(AttrType.ASLEEP))
     {
         if (HasAttr(AttrType.AFRAID))
         {
             await Task.Delay(250);
         }
         if (HasAttr(AttrType.ASLEEP))
         {
             await Task.Delay(100);
         }
         Q1();
         return true;
     }
     if (HasAttr(AttrType.FROZEN))
     {
         int damage = Global.Roll(Weapon.Damage(weapons[0]).dice, 6) + TotalSkill(SkillType.COMBAT);
         attrs[Forays.AttrType.FROZEN] -= damage;
         if (attrs[Forays.AttrType.FROZEN] < 0)
         {
             attrs[Forays.AttrType.FROZEN] = 0;
         }
         if (HasAttr(AttrType.FROZEN))
         {
             B.Add("You attempt to break free. ");
         }
         else
         {
             B.Add("You break free! ");
         }
         Q1();
         return true;
     }
     if (Global.Option(OptionType.AUTOPICKUP) && tile().inv != null && !tile().inv.ignored && !tile().Is(FeatureType.QUICKFIRE))
     {
         bool grenade = false;
         foreach (Tile t in TilesWithinDistance(1))
         {
             if (t.Is(FeatureType.GRENADE))
             {
                 grenade = true;
             }
         }
         if (!grenade && !HasAttr(AttrType.ON_FIRE) && !HasAttr(AttrType.CATCHING_FIRE))
         {
             bool monster = false;
             foreach (Actor a in M.AllActors())
             {
                 if (a != this && CanSee(a))
                 {
                     monster = true;
                     break;
                 }
             }
             if (!monster)
             {
                 if (await StunnedThisTurn())
                 {
                     return true;
                 }
                 Item i = tile().inv;
                 i.row = -1;
                 i.col = -1;
                 tile().inv = null;
                 B.Add("You pick up " + i.TheName() + ". ");
                 bool added = false;
                 foreach (Item item in inv)
                 {
                     if (item.itype == i.itype && !item.do_not_stack && !i.do_not_stack)
                     {
                         item.quantity += i.quantity;
                         added = true;
                         break;
                     }
                 }
                 if (!added)
                 {
                     inv.Add(i);
                 }
                 Q1();
                 return true;
             }
         }
     }
     if (path.Count > 0)
     {
         bool monsters_visible = false;
         foreach (Actor a in M.AllActors())
         {
             if (a != this && CanSee(a) && HasLOS(a.row, a.col))
             { //check LOS, prevents detected mobs from stopping you
                 monsters_visible = true;
             }
         }
         if (!monsters_visible)
         {
             if (Game.Console.KeyAvailable)
             {
                 await Game.Console.ReadKey(true);
                 Interrupt();
             }
             else
             {
                 //AI_Step(M.tile[path[0]]);
                 await PlayerWalk(DirectionOf(path[0]));
                 if (path.Count > 0)
                 {
                     if (DistanceFrom(path[0]) == 0)
                     {
                         path.RemoveAt(0);
                     }
                 }
                 //QS();
                 return true;
             }
         }
         else
         {
             Interrupt();
         }
     }
     if (HasAttr(AttrType.RUNNING))
     {
         bool monsters_visible = false;
         foreach (Actor a in M.AllActors())
         {
             if (a != this && CanSee(a) && HasLOS(a.row, a.col))
             { //check LOS, prevents detected mobs from stopping you
                 monsters_visible = true;
             }
         }
         Tile t = TileInDirection(attrs[AttrType.RUNNING]);
         bool stopped_by_terrain = false;
         if (t.IsKnownTrap() || t.Is(FeatureType.FUNGUS_ACTIVE) || t.Is(FeatureType.FUNGUS_PRIMED)
         || t.Is(FeatureType.GRENADE) || t.Is(FeatureType.POISON_GAS) || t.Is(FeatureType.QUICKFIRE))
         {
             stopped_by_terrain = true;
         }
         if (!monsters_visible && !stopped_by_terrain && !Game.Console.KeyAvailable)
         {
             if (attrs[AttrType.RUNNING] == 5)
             {
                 int hplimit = HasFeat(FeatType.ENDURING_SOUL) ? 20 : 10;
                 if (curhp % hplimit == 0)
                 {
                     if (HasAttr(AttrType.WAITING))
                     {
                         attrs[Forays.AttrType.WAITING]--;
                         Q1();
                         return true;
                     }
                     else
                     {
                         attrs[AttrType.RUNNING] = 0;
                     }
                 }
                 else
                 {
                     Q1();
                     return true;
                 }
             }
             else
             {
                 if (t.passable)
                 {
                     await PlayerWalk(attrs[AttrType.RUNNING]);
                     return true;
                 }
                 else
                 {
                     Tile opposite = TileInDirection(RotateDirection(attrs[AttrType.RUNNING], true, 4));
                     int num_floors = 0;
                     int floor_dir = 0;
                     foreach (Tile t2 in TilesAtDistance(1))
                     {
                         //if(t2 != opposite && t2.name == "floor"){
                         if (t2 != opposite && (t2.passable || t2.ttype == TileType.DOOR_C))
                         {
                             num_floors++;
                             floor_dir = DirectionOf(t2);
                         }
                     }
                     if (num_floors == 1)
                     {
                         attrs[Forays.AttrType.RUNNING] = floor_dir;
                         await PlayerWalk(floor_dir);
                         return true;
                     }
                     else
                     {
                         attrs[Forays.AttrType.RUNNING] = 0;
                         attrs[Forays.AttrType.WAITING] = 0;
                     }
                 }
             }
         }
         else
         {
             if (Game.Console.KeyAvailable)
             {
                 await Game.Console.ReadKey(true);
             }
             attrs[AttrType.RUNNING] = 0;
             attrs[Forays.AttrType.WAITING] = 0;
         }
     }
     if (HasAttr(AttrType.RESTING))
     {
         if (attrs[AttrType.RESTING] == 10)
         {
             attrs[AttrType.RESTING] = -1;
             curhp += ((maxhp - curhp) / 2); //recover half of your missing health
             ResetSpells();
             B.Add("You rest...you feel great! ");
             await B.Print(false);
             DisplayStats(true);
             Cursor();
         }
         else
         {
             bool monsters_visible = false;
             foreach (Actor a in M.AllActors())
             {
                 if (a != this && CanSee(a) && HasLOS(a.row, a.col))
                 { //check LOS, prevents detected mobs from stopping you
                     monsters_visible = true;
                 }
             }
             if (monsters_visible || Game.Console.KeyAvailable)
             {
                 if (Game.Console.KeyAvailable)
                 {
                     await Game.Console.ReadKey(true);
                 }
                 if (monsters_visible)
                 {
                     attrs[AttrType.RESTING] = 0;
                     B.Add("You rest...you are interrupted! ");
                     await B.Print(false);
                     Cursor();
                 }
                 else
                 {
                     attrs[AttrType.RESTING] = 0;
                     B.Add("You rest...you stop resting. ");
                     await B.Print(false);
                     Cursor();
                 }
             }
             else
             {
                 attrs[AttrType.RESTING]++;
                 B.Add("You rest... ");
                 Q1();
                 return true;
             }
         }
     }
     if (Q.turn == 0)
     {
         await Help.TutorialTip(TutorialTopic.Movement);
         Cursor();
     }
     if (!Help.displayed[TutorialTopic.Attacking] && M.AllActors().Any(a => (a != this && CanSee(a))))
     {
         await Help.TutorialTip(TutorialTopic.Attacking);
         Cursor();
     }
     ConsoleKeyInfo command = await Game.Console.ReadKey(true);
     string ch = ConvertInput(command);
     ch = ConvertVIKeys(ch);
     bool alt = false;
     bool ctrl = false;
     bool shift = false;
     if ((command.Modifiers & ConsoleModifiers.Alt) == ConsoleModifiers.Alt)
     {
         alt = true;
     }
     if ((command.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control)
     {
         ctrl = true;
     }
     if ((command.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift)
     {
         shift = true;
     }
     switch (ch)
     {
         case "7":
         case "8":
         case "9":
         case "4":
         case "6":
         case "1":
         case "2":
         case "3":
             {
                 //jQuery.Select("#debug").ReplaceWith("<div id=\"debug\"><p>DEBUG Key Down, Key is " + command.Key + ", Char is " + command.KeyChar.ToString() + ", ch is " + ch + "</p></div>");
                 int dir = ch[0] - 48; //ascii 0-9 are 48-57
                 if (shift || alt || ctrl)
                 {
                     bool monsters_visible = false;
                     foreach (Actor a in M.AllActors())
                     {
                         if (a != this && CanSee(a) && HasLOS(a.row, a.col))
                         {
                             monsters_visible = true;
                         }
                     }
                     await PlayerWalk(dir);
                     if (!monsters_visible)
                     {
                         attrs[AttrType.RUNNING] = dir;
                     }
                 }
                 else
                 {
                     await PlayerWalk(dir);
                 }
                 break;
             }
         case "5":
         case ".":
             if (HasFeat(FeatType.FULL_DEFENSE) && EnemiesAdjacent() > 0)
             {
                 if (!HasAttr(AttrType.CATCHING_FIRE) && !HasAttr(AttrType.ON_FIRE))
                 {
                     attrs[AttrType.DEFENSIVE_STANCE]++;
                     B.Add("You ready yourself. ");
                 }
             }
             if (HasAttr(AttrType.CATCHING_FIRE))
             {
                 attrs[AttrType.CATCHING_FIRE] = 0;
                 B.Add("You stop the flames from spreading. ");
             }
             else
             {
                 if (HasAttr(AttrType.ON_FIRE))
                 {
                     bool update = false;
                     int oldradius = LightRadius();
                     if (attrs[AttrType.ON_FIRE] > light_radius)
                     {
                         update = true;
                     }
                     int i = 2;
                     if (Global.Roll(1, 3) == 3)
                     { // 1 in 3 times, you don't make progress against the fire
                         i = 1;
                     }
                     attrs[AttrType.ON_FIRE] -= i;
                     if (attrs[AttrType.ON_FIRE] < 0)
                     {
                         attrs[AttrType.ON_FIRE] = 0;
                     }
                     if (update)
                     {
                         UpdateRadius(oldradius, LightRadius());
                     }
                     if (HasAttr(AttrType.ON_FIRE))
                     {
                         B.Add("You put out some of the fire. "); //better message?
                     }
                     else
                     {
                         B.Add("You put out the fire. ");
                     }
                 }
             }
             if (M.tile[row, col].inv != null)
             {
                 B.Add("You see " + M.tile[row, col].inv.AName() + ". ");
             }
             QS();
             break;
         case "w":
             {
                 int dir = await GetDirection("Start walking in which direction? ", false, true);
                 if (dir != 0)
                 {
                     bool monsters_visible = false;
                     foreach (Actor a in M.AllActors())
                     {
                         if (a != this && CanSee(a) && HasLOS(a.row, a.col))
                         {
                             monsters_visible = true;
                         }
                     }
                     if (dir != 5)
                     {
                         await PlayerWalk(dir);
                     }
                     else
                     {
                         Q1();
                     }
                     if (!monsters_visible)
                     {
                         attrs[AttrType.RUNNING] = dir;
                         int hplimit = HasFeat(FeatType.ENDURING_SOUL) ? 20 : 10;
                         if (curhp % hplimit == 0 && dir == 5)
                         {
                             attrs[Forays.AttrType.WAITING] = 20;
                         }
                     }
                 }
                 else
                 {
                     Q0();
                 }
                 break;
             }
         case "o":
             {
                 int dir = 0;
                 int total = 0;
                 foreach (Tile t in TilesAtDistance(1))
                 {
                     if (t.ttype == TileType.DOOR_C || t.ttype == TileType.DOOR_O || t.ttype == TileType.RUBBLE
                     || (HasFeat(FeatType.DISARM_TRAP) && t.IsKnownTrap()))
                     {
                         if (t.actor() == null && (t.inv == null || t.IsTrap()))
                         {
                             dir = DirectionOf(t);
                             ++total;
                         }
                     }
                 }
                 if (total == 1)
                 {
                     Tile t = TileInDirection(dir);
                     if (t.ttype == TileType.DOOR_C || t.ttype == TileType.DOOR_O || t.ttype == TileType.RUBBLE)
                     {
                         if (await StunnedThisTurn())
                         {
                             return true;
                         }
                         t.Toggle(this);
                         Q1();
                     }
                     else
                     {
                         if (t.IsTrap())
                         {
                             if (GrabPreventsMovement(t))
                             {
                                 B.Add("You can't currently reach that trap. ");
                                 Q0();
                                 return true;
                             }
                             else
                             {
                                 if (await StunnedThisTurn())
                                 {
                                     return true;
                                 }
                                 if (Global.Roll(5) <= 4)
                                 {
                                     B.Add("You disarm " + Tile.Prototype(t.ttype).the_name + ". ");
                                     t.Toggle(this);
                                     Q1();
                                 }
                                 else
                                 {
                                     if (Global.Roll(20) <= skills[Forays.SkillType.DEFENSE])
                                     {
                                         B.Add("You almost set off " + Tile.Prototype(t.ttype).the_name + "! ");
                                         Q1();
                                     }
                                     else
                                     {
                                         B.Add("You set off " + Tile.Prototype(t.ttype).the_name + "! ");
                                         await Move(t.row, t.col);
                                         Q1();
                                     }
                                 }
                             }
                         }
                         else
                         {
                             Q0(); //shouldn't happen
                         }
                     }
                 }
                 else
                 {
                     dir = await GetDirection("Operate something in which direction? ");
                     if (dir != -1)
                     {
                         Tile t = TileInDirection(dir);
                         if (t.IsKnownTrap())
                         {
                             if (HasFeat(FeatType.DISARM_TRAP))
                             {
                                 if (GrabPreventsMovement(t))
                                 {
                                     B.Add("You can't currently reach that trap. ");
                                     Q0();
                                     return true;
                                 }
                                 if (await StunnedThisTurn())
                                 {
                                     return true;
                                 }
                                 if (Global.Roll(5) <= 4)
                                 {
                                     B.Add("You disarm " + Tile.Prototype(t.ttype).the_name + ". ");
                                     t.Toggle(this);
                                     Q1();
                                 }
                                 else
                                 {
                                     if (Global.Roll(20) <= skills[Forays.SkillType.DEFENSE])
                                     {
                                         B.Add("You almost set off " + Tile.Prototype(t.ttype).the_name + "! ");
                                         Q1();
                                     }
                                     else
                                     {
                                         B.Add("You set off " + Tile.Prototype(t.ttype).the_name + "! ");
                                         await Move(t.row, t.col);
                                         Q1();
                                     }
                                 }
                             }
                             else
                             {
                                 B.Add("You don't know how to disable that trap. ");
                                 Q0();
                                 return true;
                             }
                         }
                         else
                         {
                             switch (t.ttype)
                             {
                                 case TileType.DOOR_C:
                                 case TileType.DOOR_O:
                                 case TileType.RUBBLE:
                                     if (await StunnedThisTurn())
                                     {
                                         break;
                                     }
                                     t.Toggle(this);
                                     Q1();
                                     break;
                                 case TileType.CHEST:
                                     B.Add("Stand on the chest and press 'g' to retrieve its contents. ");
                                     Q0();
                                     break;
                                 case TileType.STAIRS:
                                     B.Add("Stand on the stairs and press '>' to descend. ");
                                     Q0();
                                     break;
                                 default:
                                     Q0();
                                     break;
                             }
                         }
                     }
                     else
                     {
                         Q0();
                     }
                 }
                 break;
             }
         /*case 'c':
             {
             int door = DirectionOfOnlyUnblocked(TileType.DOOR_O);
             if(door == -1){
                 int dir = GetDirection("Close in which direction? ");
                 if(dir != -1){
                     if(TileInDirection(dir).type == TileType.DOOR_O){
                         if(StunnedThisTurn()){
                             break;
                         }
                         TileInDirection(dir).Toggle(this);
                         Q1();
                     }
                     else{
                         Q0();
                     }
                 }
                 else{
                     Q0();
                 }
             }
             else{
                 if(door == 0){
                     B.Add("There's nothing to close here. ");
                     Q0();
                 }
                 else{
                     if(StunnedThisTurn()){
                         break;
                     }
                     TileInDirection(door).Toggle(this);
                     Q1();
                 }
             }
             break;
             }*/
         case "s":
             {
                 if (Weapon.BaseWeapon(weapons[0]) == WeaponType.BOW || HasFeat(FeatType.QUICK_DRAW))
                 {
                     if (ActorsAtDistance(1).Count > 0)
                     {
                         if (ActorsAtDistance(1).Count == 1)
                         {
                             B.Add("You can't fire with an enemy so close. ");
                         }
                         else
                         {
                             B.Add("You can't fire with enemies so close. ");
                         }
                         Q0();
                     }
                     /*if(Global.Option(OptionType.LAST_TARGET) && target!=null && DistanceFrom(target)==1){ //since you can't fire
                         target = null;										//at adjacent targets anyway.
                     }*/
                     else
                     {
                         List<Tile> line = await GetTarget(12);
                         if (line != null)
                         {
                             //if(DistanceFrom(t) > 1 || t.actor() == null){
                             await FireArrow(line);
                             /*}
                             else{
                                 B.Add("You can't fire at adjacent targets. ");
                                 Q0();
                             }*/
                         }
                         else
                         {
                             Q0();
                         }
                     }
                 }
                 else
                 {
                     B.Add("You can't fire arrows without your bow equipped. ");
                     Q0();
                 }
                 break;
             }
         case "f":
             {
                 List<FeatType> active_feats = new List<FeatType>();
                 List<FeatType> passive_feats = new List<FeatType>();
                 foreach (FeatType ft in feats_in_order)
                 {
                     if (Feat.IsActivated(ft))
                     {
                         active_feats.Add(ft);
                     }
                     else
                     {
                         passive_feats.Add(ft);
                     }
                 }
                 Screen.WriteMapString(0, 0, "".PadRight(COLS, '-'));
                 int line = 1;
                 if (active_feats.Count > 0)
                 {
                     Screen.WriteMapString(line, 0, "Active feats:".PadToMapSize());
                     ++line;
                     char letter = 'a';
                     foreach (FeatType ft in active_feats)
                     {
                         string s = "[" + string.FromCharCode(letter) + "] " + Feat.Name(ft);
                         Screen.WriteMapString(line, 0, s.PadToMapSize());
                         Screen.WriteMapChar(line, 1, string.FromCharCode(letter), Color.Cyan);
                         ++line;
                         ++letter;
                     }
                     Screen.WriteMapString(line, 0, "".PadToMapSize());
                     ++line;
                 }
                 if (passive_feats.Count > 0)
                 {
                     Screen.WriteMapString(line, 0, "Passive feats:".PadToMapSize());
                     ++line;
                     foreach (FeatType ft in passive_feats)
                     {
                         string s = "    " + Feat.Name(ft);
                         Screen.WriteMapString(line, 0, s.PadToMapSize());
                         ++line;
                     }
                     Screen.WriteMapString(line, 0, "".PadToMapSize());
                     ++line;
                 }
                 Screen.WriteMapString(line, 0, "Feats currently being learned:".PadToMapSize());
                 ++line;
                 if (partial_feats_in_order.Count == 0)
                 {
                     Screen.WriteMapString(line, 0, "    None".PadToMapSize());
                     ++line;
                 }
                 else
                 {
                     if (partial_feats_in_order.Count + line > 21)
                     {
                         int extras = partial_feats_in_order.Count + line - 21;
                         foreach (FeatType ft in partial_feats_in_order)
                         {
                             if (line == 21)
                             { //don't print the bottommost feats again
                                 break;
                             }
                             Screen.WriteMapString(line, 0, "    " + Feat.Name(ft).PadRight(21));
                             if (extras > 0)
                             {
                                 Screen.WriteMapString(line, 25, "(" + (-feats[ft]) + "/" + Feat.MaxRank(ft) + ")".PadRight(7));
                                 FeatType ft2 = partial_feats_in_order[partial_feats_in_order.Count - extras];
                                 Screen.WriteMapString(line, 36, Feat.Name(ft2).PadRight(21));
                                 Screen.WriteMapString(line, 57, "(" + (-feats[ft2]) + "/" + Feat.MaxRank(ft2) + ")".PadRight(6));
                                 ++line;
                                 --extras;
                             }
                             else
                             {
                                 Screen.WriteMapString(line, 25, "(" + (-feats[ft]) + "/" + Feat.MaxRank(ft) + ")".PadRight(37));
                                 ++line;
                             }
                         }
                     }
                     else
                     {
                         foreach (FeatType ft in partial_feats_in_order)
                         {
                             Screen.WriteMapString(line, 0, "    " + Feat.Name(ft).PadRight(21));
                             Screen.WriteMapString(line, 25, "(" + (-feats[ft]) + "/" + Feat.MaxRank(ft) + ")".PadRight(37));
                             ++line;
                         }
                     }
                 }
                 Screen.WriteMapString(line, 0, ("".PadRight(25, '-') + "[?] for help").PadRight(COLS, '-'));
                 Screen.WriteMapChar(line, 26, new colorchar(Color.Cyan, "?"));
                 ++line;
                 if (line <= 21)
                 {
                     Screen.WriteMapString(line, 0, "".PadToMapSize());
                 }
                 Screen.ResetColors();
                 if (active_feats.Count > 0)
                 {
                     B.DisplayNow("Use which feat? ");
                 }
                 else
                 {
                     B.DisplayNow("Feats: ");
                 }
                 Game.Console.CursorVisible = true;
                 FeatType selected_feat = FeatType.NO_FEAT;
                 bool done = false;
                 while (!done)
                 {
                     command = await Game.Console.ReadKey(true);
                     ch = ConvertInput(command);
                     int ii = ch[0] - 'a';
                     if (active_feats.Count > ii && ii >= 0)
                     {
                         selected_feat = active_feats[ii];
                         done = true;
                     }
                     else
                     {
                         if (ch == "?")
                         {
                             await Help.DisplayHelp(HelpTopic.Feats);
                             done = true;
                         }
                         else
                         {
                             done = true;
                         }
                     }
                 }
                 M.RedrawWithStrings();
                 if (selected_feat != FeatType.NO_FEAT)
                 {
                     if (await StunnedThisTurn())
                     {
                         break;
                     }
                     if (true != await UseFeat(selected_feat))
                     {
                         Q0();
                     }
                 }
                 else
                 {
                     Q0();
                 }
                 break;
             }
         case "z":
             {
                 foreach (Actor a in ActorsWithinDistance(2))
                 {
                     if (a.HasAttr(AttrType.SPELL_DISRUPTION) && a.HasLOE(this))
                     {
                         if (this == player)
                         {
                             if (CanSee(a))
                             {
                                 B.Add(a.Your() + " presence prevents you from casting! ");
                             }
                             else
                             {
                                 B.Add("Something prevents you from casting! ");
                             }
                         }
                         Q0();
                         return true;
                     }
                 }
                 List<colorstring> ls = new List<colorstring>();
                 List<SpellType> sp = new List<SpellType>();
                 //foreach(SpellType spell in Enum.GetValues(typeof(SpellType))){
                 bool bonus_marked = false;
                 foreach (SpellType spell in spells_in_order)
                 {
                     if (HasSpell(spell))
                     {
                         //string s = Spell.Name(spell).PadRight(15) + Spell.Level(spell).ToString().PadLeft(3);
                         //s = s + FailRate(spell).ToString().PadLeft(9) + "%";
                         //s = s + Spell.Description(spell).PadLeft(34);
                         colorstring cs = new colorstring(Spell.Name(spell).PadRight(15) + Spell.Level(spell).ToString().PadLeft(3), Color.Gray);
                         cs.strings.Add(new cstr(FailRate(spell).ToString().PadLeft(9) + "%", FailColor(spell)));
                         if (HasFeat(FeatType.MASTERS_EDGE) && Spell.IsDamaging(spell) && !bonus_marked)
                         {
                             bonus_marked = true;
                             cs = cs + Spell.DescriptionWithIncreasedDamage(spell);
                         }
                         else
                         {
                             cs = cs + Spell.Description(spell);
                         }
                         ls.Add(cs);
                         sp.Add(spell);
                     }
                 }
                 if (sp.Count > 0)
                 {
                     colorstring topborder = new colorstring("------------------Level---Fail rate--------Description------------", Color.Gray);
                     int basefail = magic_penalty * 5;
                     if (!HasFeat(FeatType.ARMORED_MAGE))
                     {
                         basefail += Armor.AddedFailRate(armors[0]);
                     }
                     colorstring bottomborder = new colorstring("------------Base fail rate: ", Color.Gray, (basefail.ToString().PadLeft(3) + "%"), FailColor(basefail), "----------[", Color.Gray, "?", Color.Cyan, "] for help".PadRight(22, '-'), Color.Gray);
                     //int i = Select("Cast which spell? ",topborder,bottomborder,ls);
                     int i = await Select("Cast which spell? ", topborder, bottomborder, ls, false, false, true, true, HelpTopic.Spells);
                     if (i != -1)
                     {
                         if (true != await CastSpell(sp[i]))
                         {
                             Q0();
                         }
                     }
                     else
                     {
                         Q0();
                     }
                 }
                 else
                 {
                     B.Add("You don't know any spells. ");
                     Q0();
                 }
                 break;
             }
         case "r":
             if (attrs[AttrType.RESTING] != -1)
             { //gets set to -1 if you've rested on this level
                 bool monsters_visible = false;
                 foreach (Actor a in M.AllActors())
                 {
                     if (a != this && CanSee(a) && HasLOS(a.row, a.col))
                     { //check LOS, prevents detected mobs from stopping you
                         monsters_visible = true;
                     }
                 }
                 if (!monsters_visible)
                 {
                     bool can_recover_spells = false;
                     if (magic_penalty > 0)
                     {
                         can_recover_spells = true;
                     }
                     if (curhp < maxhp || can_recover_spells)
                     {
                         if (await StunnedThisTurn())
                         {
                             break;
                         }
                         attrs[AttrType.RESTING] = 1;
                         B.Add("You rest... ");
                         Q1();
                     }
                     else
                     {
                         B.Add("You don't need to rest right now. ");
                         Q0();
                     }
                 }
                 else
                 {
                     B.Add("You can't rest while there are enemies around! ");
                     Q0();
                 }
             }
             else
             {
                 B.Add("You find it impossible to rest again on this dungeon level. ");
                 Q0();
             }
             break;
         case ">":
             if (M.tile[row, col].ttype == TileType.STAIRS)
             {
                 if (await StunnedThisTurn())
                 {
                     break;
                 }
                 bool can_recover_spells = false;
                 if (magic_penalty > 0)
                 {
                     can_recover_spells = true;
                 }
                 if (attrs[AttrType.RESTING] != -1 && (curhp < maxhp || can_recover_spells))
                 {
                     B.DisplayNow("Really take the stairs without resting first?(y/n): ");
                     Game.Console.CursorVisible = true;
                     bool done = false;
                     while (!done)
                     {
                         command = await Game.Console.ReadKey(true);
                         switch (command.KeyChar)
                         {
                             case 'y':
                             case 'Y':
                                 done = true;
                                 break;
                             default:
                                 Q0();
                                 return true;
                         }
                     }
                 }
                 B.Add("You walk down the stairs. ");
                 await B.PrintAll();
                 if (M.current_level < 20)
                 {
                     await M.GenerateLevel();
                 }
                 else
                 {
                     await M.GenerateBossLevel(false);
                     B.Add("You enter a sweltering cavern. ");
                     B.Add("Bones lie scattered across the sulfurous ground. ");
                 }
                 Q0();
             }
             else
             {
                 Tile stairs = null;
                 foreach (Tile t in M.AllTiles())
                 {
                     if (t.ttype == TileType.STAIRS && t.seen)
                     {
                         stairs = t;
                         break;
                     }
                 }
                 if (stairs != null)
                 {
                     B.DisplayNow("Travel to the stairs?(y/n): ");
                     Game.Console.CursorVisible = true;
                     bool done = false;
                     while (!done)
                     {
                         command = await Game.Console.ReadKey(true);
                         switch (command.KeyChar)
                         {
                             case 'y':
                             case 'Y':
                             case '>':
                             case (char)13:
                                 done = true;
                                 break;
                             default:
                                 Q0();
                                 return true;
                         }
                     }
                     FindPath(stairs, -1, true);
                     Q0();
                 }
                 else
                 {
                     B.Add("You don't see any stairs here. ");
                     Q0();
                 }
             }
             break;
         case "x":
             {
                 attrs[AttrType.AUTOEXPLORE]++;
                 Q0();
             }
             break;
         case "g":
         case ";":
             if (tile().inv == null)
             {
                 if (tile().ttype == TileType.CHEST)
                 {
                     if (await StunnedThisTurn())
                     {
                         break;
                     }
                     tile().OpenChest();
                     Q1();
                 }
                 else
                 {
                     if (tile().IsShrine())
                     {
                         if (await StunnedThisTurn())
                         {
                             break;
                         }
                         switch (tile().ttype)
                         {
                             case TileType.COMBAT_SHRINE:
                                 IncreaseSkill(SkillType.COMBAT);
                                 break;
                             case TileType.DEFENSE_SHRINE:
                                 IncreaseSkill(SkillType.DEFENSE);
                                 break;
                             case TileType.MAGIC_SHRINE:
                                 IncreaseSkill(SkillType.MAGIC);
                                 break;
                             case TileType.SPIRIT_SHRINE:
                                 IncreaseSkill(SkillType.SPIRIT);
                                 break;
                             case TileType.STEALTH_SHRINE:
                                 IncreaseSkill(SkillType.STEALTH);
                                 break;
                             case TileType.SPELL_EXCHANGE_SHRINE:
                                 {
                                     List<colorstring> ls = new List<colorstring>();
                                     List<SpellType> sp = new List<SpellType>();
                                     bool bonus_marked = false;
                                     foreach (SpellType spell in spells_in_order)
                                     {
                                         if (HasSpell(spell))
                                         {
                                             colorstring cs = new colorstring(Spell.Name(spell).PadRight(15) + Spell.Level(spell).ToString().PadLeft(3), Color.Gray);
                                             cs.strings.Add(new cstr(FailRate(spell).ToString().PadLeft(9) + "%", FailColor(spell)));
                                             if (HasFeat(FeatType.MASTERS_EDGE) && Spell.IsDamaging(spell) && !bonus_marked)
                                             {
                                                 bonus_marked = true;
                                                 cs = cs + Spell.DescriptionWithIncreasedDamage(spell);
                                             }
                                             else
                                             {
                                                 cs = cs + Spell.Description(spell);
                                             }
                                             ls.Add(cs);
                                             sp.Add(spell);
                                         }
                                     }
                                     if (sp.Count > 0)
                                     {
                                         colorstring topborder = new colorstring("------------------Level---Fail rate--------Description------------", Color.Gray);
                                         int basefail = magic_penalty * 5;
                                         if (!HasFeat(FeatType.ARMORED_MAGE))
                                         {
                                             basefail += Armor.AddedFailRate(armors[0]);
                                         }
                                         colorstring bottomborder = new colorstring("------------Base fail rate: ", Color.Gray, (basefail.ToString().PadLeft(3) + "%"), FailColor(basefail), "----------[", Color.Gray, "?", Color.Cyan, "] for help".PadRight(22, '-'), Color.Gray);
                                         int i = await Select("Trade one of your spells for another? ", topborder, bottomborder, ls, false, false, true, true, HelpTopic.Spells);
                                         if (i != -1)
                                         {
                                             List<SpellType> unknown = new List<SpellType>();
                                             foreach (SpellType spell in GetSpellTypes())
                                             {
                                                 if (!HasSpell(spell) && spell != SpellType.BLESS && spell != SpellType.MINOR_HEAL
                                                 && spell != SpellType.HOLY_SHIELD && spell != SpellType.NO_SPELL && spell != SpellType.NUM_SPELLS)
                                                 {
                                                     unknown.Add(spell);
                                                 }
                                             }
                                             SpellType forgotten = sp[i];
                                             spells_in_order.Remove(forgotten);
                                             spells[forgotten] = 0;
                                             SpellType learned = unknown.Random();
                                             spells[learned] = 1;
                                             spells_in_order.Add(learned);
                                             B.Add("You forget " + Spell.Name(forgotten) + ". You learn " + Spell.Name(learned) + ". ");
                                             tile().TransformTo(TileType.RUINED_SHRINE);
                                         }
                                         else
                                         {
                                             Q0();
                                         }
                                     }
                                     break;
                                 }
                             default:
                                 break;
                         }
                         if (tile().ttype != TileType.SPELL_EXCHANGE_SHRINE)
                         {
                             Q1();
                         }
                         if (tile().ttype == TileType.MAGIC_SHRINE && spells_in_order.Count > 1)
                         {
                             tile().TransformTo(TileType.SPELL_EXCHANGE_SHRINE);
                         }
                         else
                         {
                             if (tile().ttype != TileType.SPELL_EXCHANGE_SHRINE)
                             {
                                 tile().TransformTo(TileType.RUINED_SHRINE);
                             }
                         }
                         foreach (Tile t in TilesAtDistance(2))
                         {
                             if (t.IsShrine())
                             {
                                 t.TransformTo(TileType.RUINED_SHRINE);
                             }
                         }
                     }
                     else
                     {
                         B.Add("There's nothing here to pick up. ");
                         Q0();
                     }
                 }
             }
             else
             {
                 if (await StunnedThisTurn())
                 {
                     break;
                 }
                 if (InventoryCount() < Global.MAX_INVENTORY_SIZE)
                 {
                     if (InventoryCount() + tile().inv.quantity <= Global.MAX_INVENTORY_SIZE)
                     {
                         Item i = tile().inv;
                         tile().inv = null;
                         if (i.light_radius > 0)
                         {
                             i.UpdateRadius(i.light_radius, 0);
                         }
                         i.row = -1;
                         i.col = -1;
                         B.Add("You pick up " + i.TheName() + ". ");
                         bool added = false;
                         foreach (Item item in inv)
                         {
                             if (item.itype == i.itype && !item.do_not_stack && !i.do_not_stack)
                             {
                                 item.quantity += i.quantity;
                                 added = true;
                                 break;
                             }
                         }
                         if (!added)
                         {
                             inv.Add(i);
                         }
                         Q1();
                     }
                     else
                     {
                         int space_left = Global.MAX_INVENTORY_SIZE - InventoryCount();
                         Item i = tile().inv;
                         Item newitem = new Item(i, row, col);
                         newitem.quantity = space_left;
                         i.quantity -= space_left;
                         B.Add("You pick up " + newitem.TheName() + ", but have no room for the other " + i.quantity.ToString() + ". ");
                         bool added = false;
                         foreach (Item item in inv)
                         {
                             if (item.itype == newitem.itype && !item.do_not_stack && !newitem.do_not_stack)
                             {
                                 item.quantity += newitem.quantity;
                                 added = true;
                                 break;
                             }
                         }
                         if (!added)
                         {
                             inv.Add(newitem);
                         }
                         Q1();
                     }
                 }
                 else
                 {
                     B.Add("Your pack is too full to pick up " + tile().inv.TheName() + ". ");
                     Q0();
                 }
             }
             break;
         case "d":
             if (inv.Count == 0)
             {
                 B.Add("You have nothing to drop. ");
                 Q0();
             }
             else
             {
                 int num = -1;
                 Screen.WriteMapString(0, 0, "".PadRight(COLS, '-'));
                 char letter = 'a';
                 int line = 1;
                 foreach (string s in InventoryList())
                 {
                     string s2 = "[" + (string)letter + "] " + s;
                     Screen.WriteMapString(line, 0, s2.PadRight(COLS));
                     Screen.WriteMapChar(line, 1, new colorchar(Color.Cyan, letter));
                     letter++;
                     line++;
                 }
                 //Screen.WriteMapString(line,0,("".PadRight(25,"-") + "[?] for help").PadRight(COLS,"-"));
                 Screen.WriteMapString(line, 0, ("------Space left: " + (Global.MAX_INVENTORY_SIZE - InventoryCount()).ToString().PadRight(7, '-') + "[?] for help").PadRight(COLS, '-'));
                 Screen.WriteMapChar(line, 26, new colorchar(Color.Cyan, "?"));
                 if (line < ROWS)
                 {
                     Screen.WriteMapString(line + 1, 0, "".PadRight(COLS));
                 }
                 B.DisplayNow("Drop which item? ");
                 Game.Console.CursorVisible = true;
                 while (true)
                 {
                     command = await Game.Console.ReadKey(true);
                     ch = ConvertInput(command);
                     int ii = ch[0] - 'a';
                     if (ii >= 0 && ii < InventoryList().Count)
                     {
                         num = ii;
                         break;
                     }
                     else
                     {
                         if (ch == "?")
                         {
                             await Help.DisplayHelp(HelpTopic.Items);
                             num = -1;
                             break;
                         }
                     }
                     break;
                 }
                 M.RedrawWithStrings();
                 if (num != -1)
                 {
                     if (await StunnedThisTurn())
                     {
                         break;
                     }
                     Item i = inv[num];
                     if (i.quantity <= 1)
                     {
                         if (tile().ttype == TileType.HEALING_POOL)
                         {
                             B.Add("You drop " + i.TheName() + " into the healing pool. ");
                             inv.Remove(i);
                             if (curhp < maxhp)
                             {
                                 B.Add("The pool glows briefly. ");
                                 B.Add("You suddenly feel great again! ");
                                 B.Add("The healing pool dries up. ");
                                 curhp = maxhp;
                             }
                             else
                             {
                                 B.Add("The pool glows briefly, then dries up. ");
                             }
                             tile().TurnToFloor();
                             Q1();
                         }
                         else
                         {
                             if (tile().GetItem(i))
                             {
                                 B.Add("You drop " + i.TheName() + ". ");
                                 inv.Remove(i);
                                 i.ignored = true;
                                 Q1();
                             }
                             else
                             {
                                 B.Add("There is no room. ");
                                 Q0();
                             }
                         }
                     }
                     else
                     {
                         if (tile().ttype == TileType.HEALING_POOL)
                         {
                             Item newitem = new Item(i, row, col);
                             newitem.quantity = 1;
                             i.quantity--;
                             B.Add("You drop " + newitem.TheName() + " into the healing pool. ");
                             if (curhp < maxhp)
                             {
                                 B.Add("The pool glows briefly. ");
                                 B.Add("You suddenly feel great again! ");
                                 B.Add("The healing pool dries up. ");
                                 curhp = maxhp;
                             }
                             else
                             {
                                 B.Add("The pool glows briefly, then dries up. ");
                             }
                             tile().TurnToFloor();
                             Q1();
                         }
                         else
                         {
                             B.DisplayNow("Drop how many? (1-" + i.quantity + "): ");
                             int count = await Global.EnterInt();
                             if (count == 0)
                             {
                                 Q0();
                             }
                             else
                             {
                                 if (count >= i.quantity || count == -1)
                                 {
                                     if (tile().GetItem(i))
                                     {
                                         B.Add("You drop " + i.TheName() + ". ");
                                         inv.Remove(i);
                                         i.ignored = true;
                                         Q1();
                                     }
                                     else
                                     {
                                         B.Add("There is no room. ");
                                         Q0();
                                     }
                                 }
                                 else
                                 {
                                     Item newitem = new Item(i, row, col);
                                     newitem.quantity = count;
                                     if (tile().GetItem(newitem))
                                     {
                                         i.quantity -= count;
                                         B.Add("You drop " + newitem.TheName() + ". ");
                                         newitem.ignored = true;
                                         Q1();
                                     }
                                     else
                                     {
                                         B.Add("There is no room. ");
                                         Q0();
                                     }
                                 }
                             }
                         }
                     }
                 }
                 else
                 {
                     Q0();
                 }
             }
             break;
         case "i":
             /*				if(inv.Count == 0){
                                 B.Add("You have nothing in your pack. ");
                             }
                             else{
                                 Select("In your pack: ",InventoryList(),true,false,true);
                                 Game.Console.CursorVisible = true;
                                 Game.Console.ReadKey(true);
                             }
                             Q0();
                             break;*/
             if (inv.Count == 0)
             {
                 B.Add("You have nothing in your pack. ");
                 Q0();
             }
             else
             {
                 //					int i = Select("Use which item? ",InventoryList());
                 Screen.WriteMapString(0, 0, "".PadRight(COLS, '-'));
                 char letter = 'a';
                 int line = 1;
                 foreach (string s in InventoryList())
                 {
                     string s2 = "[" + string.FromCharCode(letter) + "] " + s;
                     Screen.WriteMapString(line, 0, s2.PadRight(COLS));
                     Screen.WriteMapChar(line, 1, new colorchar(Color.Cyan, letter));
                     letter++;
                     line++;
                 }
                 Screen.WriteMapString(line, 0, ("------Space left: " + (Global.MAX_INVENTORY_SIZE - InventoryCount()).ToString().PadRight(7, '-') + "[?] for help").PadRight(COLS, '-'));
                 Screen.WriteMapChar(line, 26, new colorchar(Color.Cyan, "?"));
                 if (line < ROWS)
                 {
                     Screen.WriteMapString(line + 1, 0, "".PadRight(COLS));
                 }
                 B.DisplayNow("In your pack: ");
                 Game.Console.CursorVisible = true;
                 command = await Game.Console.ReadKey(true);
                 ch = ConvertInput(command);
                 if (ch == "?")
                 {
                     await Help.DisplayHelp(HelpTopic.Items);
                 }
                 M.RedrawWithStrings();
                 Q0();
             }
             break;
         case "a":
             if (inv.Count == 0)
             {
                 B.Add("You have nothing in your pack. ");
                 Q0();
             }
             else
             {
                 //					int i = Select("Use which item? ",InventoryList());
                 int num = -1;
                 Screen.WriteMapString(0, 0, "".PadRight(COLS, '-'));
                 char letter = 'a';
                 int line = 1;
                 foreach (string s in InventoryList())
                 {
                     string s2 = "[" + (string)letter + "] " + s;
                     Screen.WriteMapString(line, 0, s2.PadRight(COLS));
                     Screen.WriteMapChar(line, 1, new colorchar(Color.Cyan, letter));
                     letter++;
                     line++;
                 }
                 Screen.WriteMapString(line, 0, ("------Space left: " + (Global.MAX_INVENTORY_SIZE - InventoryCount()).ToString().PadRight(7, '-') + "[?] for help").PadRight(COLS, '-'));
                 //Screen.WriteMapString(line,0,("".PadRight(25,"-") + "[?] for help").PadRight(COLS,"-"));
                 Screen.WriteMapChar(line, 26, new colorchar(Color.Cyan, "?"));
                 if (line < ROWS)
                 {
                     Screen.WriteMapString(line + 1, 0, "".PadRight(COLS));
                 }
                 B.DisplayNow("Apply which item? ");
                 Game.Console.CursorVisible = true;
                 while (true)
                 {
                     command = await Game.Console.ReadKey(true);
                     ch = ConvertInput(command);
                     int ii = ch[0] - 'a';
                     if (ii >= 0 && ii < InventoryList().Count)
                     {
                         num = ii;
                         break;
                     }
                     else
                     {
                         if (ch == "?")
                         {
                             await Help.DisplayHelp(HelpTopic.Items);
                             num = -1;
                             break;
                         }
                     }
                     break;
                 }
                 M.RedrawWithStrings();
                 //if(i != -1){
                 if (num != -1)
                 {
                     if (await StunnedThisTurn())
                     {
                         break;
                     }
                     //if(inv[i].Use(this)){
                     if (await inv[num].Use(this))
                     {
                         Q1();
                     }
                     else
                     {
                         Q0();
                     }
                 }
                 else
                 {
                     Q0();
                 }
             }
             break;
         case "e":
             {
                 int[] changes = await DisplayEquipment();
                 WeaponType new_weapon = Weapon.BaseWeapon((WeaponType)changes[0]);
                 ArmorType new_armor = Armor.BaseArmor((ArmorType)changes[1]);
                 WeaponType old_weapon = weapons[0];
                 ArmorType old_armor = armors[0];
                 bool weapon_changed = (new_weapon != Weapon.BaseWeapon(old_weapon));
                 bool armor_changed = (new_armor != Armor.BaseArmor(old_armor));
                 bool cursed_weapon = false;
                 if (weapon_changed && HasAttr(AttrType.CURSED_WEAPON))
                 {
                     cursed_weapon = true;
                     weapon_changed = false;
                 }
                 if (!weapon_changed && !armor_changed)
                 {
                     if (cursed_weapon)
                     {
                         B.Add("Your " + Weapon.Name(weapons[0]) + " is stuck to your hand and can't be dropped. ");
                     }
                     Q0();
                 }
                 else
                 {
                     if (await StunnedThisTurn())
                     {
                         break;
                     }
                     if (weapon_changed)
                     {
                         bool done = false;
                         while (!done)
                         {
                             WeaponType w = weapons[0];
                             weapons.Remove(w);
                             weapons.Insert(weapons.Count, w);
                             if (new_weapon == Weapon.BaseWeapon(weapons[0]))
                             {
                                 done = true;
                             }
                         }
                         if (HasFeat(FeatType.QUICK_DRAW) && !armor_changed)
                         {
                             B.Add("You quickly ready your " + Weapon.Name(weapons[0]) + ". ");
                         }
                         else
                         {
                             B.Add("You ready your " + Weapon.Name(weapons[0]) + ". ");
                         }
                         UpdateOnEquip(old_weapon, weapons[0]);
                     }
                     if (armor_changed)
                     {
                         bool done = false;
                         while (!done)
                         {
                             ArmorType a = armors[0];
                             armors.Remove(a);
                             armors.Insert(armors.Count, a);
                             if (new_armor == Armor.BaseArmor(armors[0]))
                             {
                                 done = true;
                             }
                         }
                         B.Add("You wear your " + Armor.Name(armors[0]) + ". ");
                         UpdateOnEquip(old_armor, armors[0]);
                     }
                     if (cursed_weapon)
                     {
                         B.Add("Your " + Weapon.Name(weapons[0]) + " is stuck to your hand and can't be dropped. ");
                     }
                     if (HasFeat(FeatType.QUICK_DRAW) && !armor_changed)
                     {
                         Q0();
                     }
                     else
                     {
                         Q1();
                     }
                 }
                 break;
             }
         case "!": //note that these are the top-row numbers, NOT the actual shifted versions
         case "@": //<---this is the "2" above the "w"    (not the "@", and not the numpad 2)
         case "#":
         case "$":
         case "%":
             {
                 if (HasAttr(AttrType.CURSED_WEAPON))
                 {
                     B.Add("Your " + Weapon.Name(weapons[0]) + " is stuck to your hand and can't be dropped. ");
                     Q0();
                 }
                 else
                 {
                     WeaponType new_weapon = WeaponType.NO_WEAPON;
                     switch (ch)
                     {
                         case "!":
                             new_weapon = WeaponType.SWORD;
                             break;
                         case "@":
                             new_weapon = WeaponType.MACE;
                             break;
                         case "#":
                             new_weapon = WeaponType.DAGGER;
                             break;
                         case "$":
                             new_weapon = WeaponType.STAFF;
                             break;
                         case "%":
                             new_weapon = WeaponType.BOW;
                             break;
                     }
                     WeaponType old_weapon = weapons[0];
                     if (new_weapon == Weapon.BaseWeapon(old_weapon))
                     {
                         Q0();
                     }
                     else
                     {
                         if (await StunnedThisTurn())
                         {
                             break;
                         }
                         bool done = false;
                         while (!done)
                         {
                             WeaponType w = weapons[0];
                             weapons.Remove(w);
                             weapons.Insert(weapons.Count, w);
                             if (new_weapon == Weapon.BaseWeapon(weapons[0]))
                             {
                                 done = true;
                             }
                         }
                         if (HasFeat(FeatType.QUICK_DRAW))
                         {
                             B.Add("You quickly ready your " + Weapon.Name(weapons[0]) + ". ");
                             Q0();
                         }
                         else
                         {
                             B.Add("You ready your " + Weapon.Name(weapons[0]) + ". ");
                             Q1();
                         }
                         UpdateOnEquip(old_weapon, weapons[0]);
                     }
                 }
                 break;
             }
         case "*": //these are toprow numbers, not shifted versions. see above.
         case "(":
         case ")":
             {
                 ArmorType new_armor = ArmorType.NO_ARMOR;
                 switch (ch)
                 {
                     case "*":
                         new_armor = ArmorType.LEATHER;
                         break;
                     case "(":
                         new_armor = ArmorType.CHAINMAIL;
                         break;
                     case ")":
                         new_armor = ArmorType.FULL_PLATE;
                         break;
                 }
                 ArmorType old_armor = armors[0];
                 if (new_armor == Armor.BaseArmor(old_armor))
                 {
                     Q0();
                 }
                 else
                 {
                     if (await StunnedThisTurn())
                     {
                         break;
                     }
                     bool done = false;
                     while (!done)
                     {
                         ArmorType a = armors[0];
                         armors.Remove(a);
                         armors.Insert(armors.Count, a);
                         if (new_armor == Armor.BaseArmor(armors[0]))
                         {
                             done = true;
                         }
                     }
                     B.Add("You wear your " + Armor.Name(armors[0]) + ". ");
                     Q1();
                     UpdateOnEquip(old_armor, armors[0]);
                 }
                 break;
             }
         case "t":
             if (await StunnedThisTurn())
             {
                 break;
             }
             if (light_radius == 0)
             {
                 if (HasAttr(AttrType.ENHANCED_TORCH))
                 {
                     UpdateRadius(LightRadius(), Global.MAX_LIGHT_RADIUS - attrs[AttrType.DIM_LIGHT] * 2, true);
                 }
                 else
                 {
                     UpdateRadius(LightRadius(), 6 - attrs[AttrType.DIM_LIGHT], true); //normal light radius is 6
                 }
                 if (!M.wiz_dark)
                 {
                     B.Add("You bring out your torch. ");
                 }
                 else
                 {
                     B.Add("You bring out your torch, but it gives off no light! ");
                 }
             }
             else
             {
                 UpdateRadius(LightRadius(), 0, true);
                 UpdateRadius(0, attrs[AttrType.ON_FIRE]);
                 if (!M.wiz_lite)
                 {
                     B.Add("You put away your torch. ");
                 }
                 else
                 {
                     B.Add("You put away your torch. The air still shines brightly. ");
                 }
             }
             Q1();
             break;
         case "\u000D":
             await GetTarget(true, -1, true);
             Q0();
             break;
         case "p":
             {
                 Screen.WriteMapString(0, 0, "".PadRight(COLS, '-'));
                 int i = 1;
                 foreach (string s in B.GetMessages())
                 {
                     Screen.WriteMapString(i, 0, s.PadRight(COLS));
                     ++i;
                 }
                 Screen.WriteMapString(21, 0, "".PadRight(COLS, '-'));
                 B.DisplayNow("Previous messages: ");
                 Game.Console.CursorVisible = true;
                 await Game.Console.ReadKey(true);
                 Q0();
                 break;
             }
         case "c":
             DisplayCharacterInfo();
             Q0();
             break;
         case "O":
         case "=":
             {
                 for (bool done = false; !done; )
                 {
                     List<string> ls = new List<string>();
                     ls.Add("Use last target when possible".PadRight(58) + (Global.Option(OptionType.LAST_TARGET) ? "yes " : "no ").PadLeft(4));
                     ls.Add("Automatically pick up items (if safe)".PadRight(58) + (Global.Option(OptionType.AUTOPICKUP) ? "yes " : "no ").PadLeft(4));
                     ls.Add("Hide old messages instead of darkening them".PadRight(58) + (Global.Option(OptionType.HIDE_OLD_MESSAGES) ? "yes " : "no ").PadLeft(4));
                     ls.Add("Hide the command hints on the side".PadRight(58) + (Global.Option(OptionType.HIDE_COMMANDS) ? "yes " : "no ").PadLeft(4));
                     ls.Add("Cast a spell instead of attacking".PadRight(46) + (F[0] == SpellType.NO_SPELL ? "no " : Spell.Name(F[0])).PadLeft(16));
                     ls.Add("Don't use roman numerals for automatic naming".PadRight(58) + (Global.Option(OptionType.NO_ROMAN_NUMERALS) ? "yes " : "no ").PadLeft(4));
                     ls.Add("Never show tutorial tips".PadRight(58) + (Global.Option(OptionType.NEVER_DISPLAY_TIPS) ? "yes " : "no ").PadLeft(4));
                     ls.Add("Reset tutorial tips before each game".PadRight(58) + (Global.Option(OptionType.ALWAYS_RESET_TIPS) ? "yes " : "no ").PadLeft(4));
                     await Select("Options: ", ls, true, false, false);
                     Game.Console.CursorVisible = true;
                     ch = ConvertInput(await Game.Console.ReadKey(true));
                     switch (ch)
                     {
                         case "a":
                             Global.Options[OptionType.LAST_TARGET] = !Global.Option(OptionType.LAST_TARGET);
                             break;
                         case "b":
                             Global.Options[OptionType.AUTOPICKUP] = !Global.Option(OptionType.AUTOPICKUP);
                             break;
                         case "c":
                             Global.Options[OptionType.HIDE_OLD_MESSAGES] = !Global.Option(OptionType.HIDE_OLD_MESSAGES);
                             break;
                         case "d":
                             Global.Options[OptionType.HIDE_COMMANDS] = !Global.Option(OptionType.HIDE_COMMANDS);
                             break;
                         case "e":
                             {
                                 if (skills[Forays.SkillType.MAGIC] > 0)
                                 {
                                     M.RedrawWithStrings();
                                     List<colorstring> list = new List<colorstring>();
                                     List<SpellType> sp = new List<SpellType>();
                                     bool bonus_marked = false;
                                     foreach (SpellType spell in spells_in_order)
                                     {
                                         if (HasSpell(spell))
                                         {
                                             colorstring cs = new colorstring(Spell.Name(spell).PadRight(15) + Spell.Level(spell).ToString().PadLeft(3), Color.Gray);
                                             cs.strings.Add(new cstr(FailRate(spell).ToString().PadLeft(9) + "%", FailColor(spell)));
                                             if (HasFeat(FeatType.MASTERS_EDGE) && Spell.IsDamaging(spell) && !bonus_marked)
                                             {
                                                 bonus_marked = true;
                                                 cs = cs + Spell.DescriptionWithIncreasedDamage(spell);
                                             }
                                             else
                                             {
                                                 cs = cs + Spell.Description(spell);
                                             }
                                             list.Add(cs);
                                             sp.Add(spell);
                                         }
                                     }
                                     if (sp.Count > 0)
                                     {
                                         colorstring topborder = new colorstring("------------------Level---Fail rate--------Description------------", Color.Gray);
                                         int basefail = magic_penalty * 5;
                                         if (!HasFeat(FeatType.ARMORED_MAGE))
                                         {
                                             basefail += Armor.AddedFailRate(armors[0]);
                                         }
                                         colorstring bottomborder = new colorstring("------------Base fail rate: ", Color.Gray, (basefail.ToString().PadLeft(3) + "%"), FailColor(basefail), "".PadRight(37, '-'), Color.Gray);
                                         int i = await Select("Automatically cast which spell? ", topborder, bottomborder, list, false, false, false, false, HelpTopic.Overview);
                                         if (i != -1)
                                         {
                                             F[0] = sp[i];
                                         }
                                         else
                                         {
                                             F[0] = SpellType.NO_SPELL;
                                         }
                                     }
                                 }
                                 break;
                             }
                         case "f":
                             Global.Options[OptionType.NO_ROMAN_NUMERALS] = !Global.Option(OptionType.NO_ROMAN_NUMERALS);
                             break;
                         case "g":
                             Global.Options[OptionType.NEVER_DISPLAY_TIPS] = !Global.Option(OptionType.NEVER_DISPLAY_TIPS);
                             break;
                         case "h":
                             Global.Options[OptionType.ALWAYS_RESET_TIPS] = !Global.Option(OptionType.ALWAYS_RESET_TIPS);
                             break;
                         case "\u001B":
                         case " ":
                         case "\u000D":
                             done = true;
                             break;
                         default:
                             break;
                     }
                 }
                 Q0();
                 break;
             }
         case "?":
         case "/":
             {
                 await Help.DisplayHelp();
                 Q0();
                 break;
             }
         case "-":
             {
                 Game.Console.CursorVisible = false;
                 List<string> commandhelp = Help.HelpText(HelpTopic.Commands);
                 commandhelp.RemoveRange(0, 2);
                 Screen.WriteMapString(0, 0, "".PadRight(COLS, '-'));
                 for (int i = 0; i < 20; ++i)
                 {
                     Screen.WriteMapString(i + 1, 0, commandhelp[i].PadRight(COLS));
                 }
                 Screen.WriteMapString(ROWS - 1, 0, "".PadRight(COLS, '-'));
                 B.DisplayNow("Commands: ");
                 Game.Console.CursorVisible = true;
                 await Game.Console.ReadKey(true);
                 Q0();
                 break;
             }
         case "q":
             {
                 List<string> ls = new List<string>();
                 ls.Add("Save your progress and exit to main menu");
                 ls.Add("Save your progress and quit game");
                 ls.Add("Abandon character and exit to main menu");
                 ls.Add("Abandon character and quit game");
                 ls.Add("Quit game immediately - don't save anything");
                 ls.Add("Continue playing");
                 Game.Console.CursorVisible = true;
                 switch (await Select("Quit? ", ls))
                 {
                     case 0:
                         Global.SaveGame(B, M, Q);
                         Global.GAME_OVER = true;
                         Global.SAVING = true;
                         break;
                     case 1:
                         Global.SaveGame(B, M, Q);
                         Global.GAME_OVER = true;
                         Global.QUITTING = true;
                         Global.SAVING = true;
                         break;
                     case 2:
                         Global.GAME_OVER = true;
                         Global.KILLED_BY = "giving up";
                         break;
                     case 3:
                         Global.GAME_OVER = true;
                         Global.QUITTING = true;
                         Global.KILLED_BY = "giving up";
                         break;
                     case 4:
                         Global.Quit();
                         break;
                     case 5:
                     default:
                         break;
                 }
                 Q0();
                 break;
             }
         case "~": //debug mode 
             if (false)
             {
                 List<string> l = new List<string>();
                 l.Add("Throw a prismatic orb");
                 l.Add("create chests");
                 l.Add("Create a poison gas vent");
                 l.Add("create fog");
                 l.Add("Forget the map");
                 l.Add("Heal to full");
                 l.Add("Become invulnerable");
                 l.Add("get items!");
                 l.Add("Spawn a monster");
                 l.Add("Use a rune of passage");
                 l.Add("See the entire level");
                 l.Add("Generate new level");
                 l.Add("Gain all skills and feats");
                 l.Add("Spawn shrines");
                 l.Add("create trap");
                 l.Add("create door");
                 l.Add("spawn lots of goblins and lose neck snap");
                 l.Add("remove all enemies, spawn boss");
                 l.Add("detect monsters forever");
                 l.Add("trigger floor collapse");
                 switch (await Select("Activate which cheat? ", l))
                 {
                     case 0:
                         {
                             await new Item(ConsumableType.PRISMATIC, "prismatic orb", "*", Color.White).Use(this);
                             Q1();
                             break;
                         }
                     case 1:
                         {
                             foreach (Tile t in TilesWithinDistance(3))
                             {
                                 t.TransformTo(TileType.CHEST);
                             }
                             Q0();
                             //Screen.AnimateExplosion(this,5,new colorchar(Color.RandomIce,"*"),25);
                             //Q1();
                             break;
                         }
                     case 2:
                         {
                             List<Tile> line = await GetTarget(-1, -1);
                             if (line != null)
                             {
                                 Tile t = line.Last();
                                 /*if(t != null && t.inv == null){
                                     Item.Create(Item.RandomItem(),t.row,t.col);
                                     t.inv.do_not_stack = true;
                                     Q.Add(new Event(t.inv,new List<Tile>{t},100,Forays.EventType.MIMIC,AttrType.NO_ATTR,0,""));
                                 }*/
                                 if (t != null)
                                 {
                                     /*t.TransformTo(TileType.FIRE_GEYSER);
                                     int frequency = Global.Roll(21) + 4; //5-25
                                     int variance = Global.Roll(10) - 1; //0-9
                                     int variance_amount = (frequency * variance) / 10;
                                     int number_of_values = variance_amount*2 + 1;
                                     int minimum_value = frequency - variance_amount;
                                     if(minimum_value < 5){
                                         int diff = 5 - minimum_value;
                                         number_of_values -= diff;
                                         minimum_value = 5;
                                     }
                                     int delay = ((minimum_value - 1) + Global.Roll(number_of_values)) * 100;
                                     Q.Add(new Event(t,delay + 200,EventType.FIRE_GEYSER,(frequency*10)+variance)); //notice the hacky way the value is stored
                                     Q.Add(new Event(t,delay,EventType.FIRE_GEYSER_ERUPTION,2));*/
                                     t.TransformTo(TileType.POISON_GAS_VENT);
                                     Q.Add(new Event(t, 100, EventType.POISON_GAS_VENT));
                                 }
                             }
                             Q0();
                             break;
                         }
                     case 3:
                         {
                             //ConsoleKeyInfo command2 = Game.Console.ReadKey(true);
                             //Game.Console.Write(command2.Key);
                             List<Tile> line = await GetTarget(-1, -1);
                             if (line != null)
                             {
                                 Tile t = line.Last();
                                 if (t != null)
                                 {
                                     t.AddOpaqueFeature(FeatureType.FOG);
                                 }
                             }
                             Q0();
                             break;
                         }
                     case 4:
                         {
                             Game.Console.CursorVisible = false;
                             colorchar cch;
                             cch.c = " ";
                             cch.color = Color.Black;
                             cch.bgcolor = Color.Black;
                             foreach (Tile t in M.AllTiles())
                             {
                                 t.seen = false;
                                 Screen.WriteMapChar(t.row, t.col, cch);
                             }
                             Game.Console.CursorVisible = true;
                             Q0();
                             break;
                         }
                     case 5:
                         curhp = maxhp;
                         Q0();
                         break;
                     case 6:
                         if (!HasAttr(AttrType.INVULNERABLE))
                         {
                             attrs[AttrType.INVULNERABLE]++;
                             B.Add("On. ");
                         }
                         else
                         {
                             attrs[AttrType.INVULNERABLE] = 0;
                             B.Add("Off. ");
                         }
                         Q0();
                         break;
                     case 7:
                         {
                             for (int i = 0; i < 50; ++i)
                             {
                                 Item.Create(Item.RandomItem(), this);
                             }
                             Q0();
                             break;
                         }
                     case 8:
                         //Create(ActorType.CULTIST,18,50);
                         M.SpawnMob(ActorType.DIRE_RAT);
                         Q1();
                         break;
                     case 9:
                         await new Item(ConsumableType.PASSAGE, "rune of passage", "&", Color.White).Use(this);
                         Q1();
                         break;
                     case 10:
                         foreach (Tile t in M.AllTiles())
                         {
                             t.seen = true;
                         }
                         M.Draw();
                         foreach (Actor a in M.AllActors())
                         {
                             Screen.WriteMapChar(a.row, a.col, new colorchar(a.color, Color.Black, a.symbol));
                         }
                         await Game.Console.ReadKey(true);
                         Q0();
                         break;
                     case 11:
                         await M.GenerateLevel();
                         Q0();
                         break;
                     case 12:
                         {
                             /*Tile t = await GetTarget();
                             if(t != null){
                                 TileType oldtype = t.type;
                                 t.TransformTo(TileType.GRENADE);
                                 t.toggles_into = oldtype;
                                 t.passable = Tile.Prototype(oldtype).passable;
                                 t.opaque = Tile.Prototype(oldtype).opaque;
                                 switch(oldtype){
                                 case TileType.FLOOR:
                                     t.the_name = "the grenade on the floor";
                                     t.a_name = "a grenade on a floor";
                                     break;
                                 case TileType.STAIRS:
                                     t.the_name = "the grenade on the stairway";
                                     t.a_name = "a grenade on a stairway";
                                     break;
                                 case TileType.DOOR_O:
                                     t.the_name = "the grenade in the open door";
                                     t.a_name = "a grenade in an open door";
                                     break;
                                 default:
                                     t.the_name = "the grenade and " + Tile.Prototype(oldtype).the_name;
                                     t.a_name = "a grenade and " + Tile.Prototype(oldtype).a_name;
                                     break;
                                 }
                                 Q.Add(new Event(t,100,EventType.GRENADE));
                             }*/
                             level = 10;
                             skills[SkillType.COMBAT] = 10;
                             skills[SkillType.DEFENSE] = 10;
                             skills[SkillType.MAGIC] = 10;
                             skills[SkillType.SPIRIT] = 10;
                             skills[SkillType.STEALTH] = 10;
                             foreach (FeatType f in GetFeatTypes())
                             {
                                 if (f != FeatType.NO_FEAT && f != FeatType.NUM_FEATS)
                                 {
                                     feats[f] = 1;
                                 }
                             }
                             Q0();
                             B.Add("\"I HAVE THE POWERRRR!\" ");
                             break;
                         }
                     case 13:
                         {
                             //LevelUp();
                             foreach (Tile t in TilesWithinDistance(2))
                             {
                                 t.TransformTo((TileType)(Global.Roll(5) + 20));
                             }
                             Q0();
                             break;
                         }
                     case 14:
                         {
                             foreach (Tile t in TilesAtDistance(1))
                             {
                                 t.TransformTo(Tile.RandomTrap());
                             }
                             Q0();
                             break;
                         }
                     case 15:
                         {
                             List<Tile> line = await GetTarget(-1, -1);
                             if (line != null)
                             {
                                 Tile t = line.Last();
                                 if (t != null)
                                 {
                                     t.TransformTo(TileType.DOOR_O);
                                 }
                             }
                             Q0();
                             break;
                         }
                     case 16:
                         {
                             for (int i = 0; i < 100; ++i)
                             {
                                 M.SpawnMob(ActorType.GOBLIN);
                             }
                             if (HasFeat(FeatType.NECK_SNAP))
                             {
                                 feats[FeatType.NECK_SNAP] = 0;
                             }
                             Q0();
                             break;
                         }
                     case 17:
                         {
                             foreach (Actor a in M.AllActors())
                             {
                                 if (a != this)
                                 {
                                     Q.KillEvents(a, Forays.EventType.ANY_EVENT);
                                     M.RemoveTargets(a);
                                     M.actor[a.p] = null;
                                 }
                             }
                             foreach (Tile t in M.AllTiles())
                             {
                                 if (t.passable && t.actor() == null)
                                 {
                                     Create(ActorType.FIRE_DRAKE, t.row, t.col, true, false);
                                     break;
                                 }
                             }
                             Q0();
                             break;
                         }
                     case 18:
                         {
                             if (attrs[Forays.AttrType.DETECTING_MONSTERS] == 0)
                             {
                                 attrs[Forays.AttrType.DETECTING_MONSTERS] = 1;
                             }
                             else
                             {
                                 attrs[Forays.AttrType.DETECTING_MONSTERS] = 0;
                             }
                             Q0();
                             break;
                         }
                     case 19:
                         {
                             List<Tile> line = await GetTarget(-1, -1);
                             if (line != null)
                             {
                                 Tile t = line.Last();
                                 if (t != null)
                                 {
                                     t.Toggle(null, TileType.CHASM);
                                     Q.Add(new Event(t, 100, EventType.FLOOR_COLLAPSE));
                                     B.Add("The floor begins to collapse! ");
                                 }
                             }
                             Q0();
                             break;
                         }
                     default:
                         Q0();
                         break;
                 }
             }
             else
             {
                 Q0();
             }
             break;
         case " ":
             Q0();
             break;
         default:
             B.Add("Press '?' for help. ");
             Q0();
             break;
     }
     if (ch != "x")
     {
         attrs[Forays.AttrType.AUTOEXPLORE] = 0;
     }
     return false;
 }
 public async Task<int> Select(string message, colorstring top_border, colorstring bottom_border, List<colorstring> strings, bool no_ask, bool no_cancel, bool easy_cancel, bool help_key, HelpTopic help_topic)
 {
     int result = -2;
     while (result == -2)
     {
         Screen.WriteMapString(0, 0, top_border);
         char letter = 'a';
         int i = 1;
         foreach (colorstring s in strings)
         {
             Screen.WriteMapString(i, 0, new colorstring("[", Color.Gray, (string)letter, Color.Cyan, "] ", Color.Gray));
             Screen.WriteMapString(i, 4, s);
             letter++;
             i++;
         }
         Screen.WriteMapString(i, 0, bottom_border);
         if (i < ROWS - 1)
         {
             Screen.WriteMapString(i + 1, 0, "".PadRight(COLS));
         }
         if (no_ask)
         {
             B.DisplayNow(message);
             return -1;
         }
         else
         {
             result = await GetSelection(message, strings.Count, no_cancel, easy_cancel, help_key);
             if (result == -2)
             {
                 await Help.DisplayHelp(help_topic);
             }
             else
             {
                 M.RedrawWithStrings();
                 return result;
             }
         }
     }
     return -1;
 }
 public async void IncreaseSkill(SkillType skill)
 {
     List<string> learned = new List<string>();
     skills[skill]++;
     B.Add("You feel a rush of power. ");
     //DisplayStats();
     await B.PrintAll();
     ConsoleKeyInfo command;
     FeatType feat_increased = FeatType.NO_FEAT;
     bool done = false;
     while (!done)
     {
         Screen.ResetColors();
         Screen.WriteMapString(0, 0, "".PadRight(COLS, '-'));
         for (int i = 0; i < 4; ++i)
         {
             FeatType ft = Feat.OfSkill(skill, i);
             Color featcolor = (feat_increased == ft) ? Color.Green : Color.Gray;
             Color lettercolor = Color.Cyan;
             int featlevel = (feat_increased == ft) ? (-feats[ft]) + 1 : (-feats[ft]);
             if (HasFeat(ft))
             {
                 featcolor = Color.Magenta;
                 lettercolor = Color.DarkRed;
                 featlevel = Feat.MaxRank(ft);
             }
             Screen.WriteMapString(1 + i * 5, 0, ("[" + string.FromCharCode((char)(i + 97)) + "] "));
             Screen.WriteMapChar(1 + i * 5, 1, string.FromCharCode((char)(i + 97)), lettercolor);
             Screen.WriteMapString(1 + i * 5, 4, Feat.Name(ft).PadRight(21) + "(" + featlevel + "/" + Feat.MaxRank(ft) + ")", featcolor);
             if (Feat.IsActivated(ft))
             {
                 Screen.WriteMapString(1 + i * 5, 30, "        Active".PadToMapSize());
             }
             else
             {
                 Screen.WriteMapString(1 + i * 5, 30, "        Passive".PadToMapSize());
             }
             List<string> desc = Feat.Description(ft);
             for (int j = 0; j < 4; ++j)
             {
                 if (desc.Count > j)
                 {
                     Screen.WriteMapString(2 + j + i * 5, 0, "    " + desc[j].PadRight(64));
                 }
                 else
                 {
                     Screen.WriteMapString(2 + j + i * 5, 0, "".PadRight(66));
                 }
             }
         }
         if (feat_increased != FeatType.NO_FEAT)
         {
             Screen.WriteMapString(21, 0, "--Type [a-d] to choose a feat---[?] for help---[Enter] to accept--");
             Screen.WriteMapChar(21, 8, new colorchar(Color.Cyan, 'a'));
             Screen.WriteMapChar(21, 10, new colorchar(Color.Cyan, 'd'));
             Screen.WriteMapChar(21, 33, new colorchar(Color.Cyan, '?'));
             Screen.WriteMapString(21, 48, new cstr(Color.Magenta, "Enter"));
         }
         else
         {
             Screen.WriteMapString(21, 0, "--Type [a-d] to choose a feat---[?] for help----------------------");
             Screen.WriteMapChar(21, 8, new colorchar(Color.Cyan, 'a'));
             Screen.WriteMapChar(21, 10, new colorchar(Color.Cyan, 'd'));
             Screen.WriteMapChar(21, 33, new colorchar(Color.Cyan, '?'));
         }
         B.DisplayNow("Your " + Skill.Name(skill) + " skill increases to " + skills[skill] + ". Choose a feat: ");
         if (!Help.displayed[TutorialTopic.Feats])
         {
             await Help.TutorialTip(TutorialTopic.Feats);
             B.DisplayNow("Your " + Skill.Name(skill) + " skill increases to " + skills[skill] + ". Choose a feat: ");
         }
         Game.Console.CursorVisible = true;
         command = await Game.Console.ReadKey(true);
         Game.Console.CursorVisible = false;
         string ch = ConvertInput(command);
         switch (ch)
         {
             case "a":
             case "b":
             case "c":
             case "d":
                 {
                     FeatType ft = Feat.OfSkill(skill, (int)(ch[0] - 97));
                     if (feat_increased == ft)
                     {
                         feat_increased = FeatType.NO_FEAT;
                     }
                     else
                     {
                         if (feat_increased == FeatType.NO_FEAT && !HasFeat(ft))
                         {
                             feat_increased = ft;
                         }
                     }
                     break;
                 }
             case "?":
                 await Help.DisplayHelp(HelpTopic.Feats);
                 DisplayStats();
                 break;
             case "\u000D":
                 if (feat_increased != FeatType.NO_FEAT)
                 {
                     done = true;
                 }
                 break;
             default:
                 break;
         }
     }
     feats[feat_increased]--; //negative values are used until you've completely learned a feat
     partial_feats_in_order.AddUnique(feat_increased);
     if (feats[feat_increased] == -(Feat.MaxRank(feat_increased)))
     {
         feats[feat_increased] = 1;
         partial_feats_in_order.Remove(feat_increased);
         feats_in_order.Add(feat_increased);
         learned.Add("You master the " + Feat.Name(feat_increased) + " feat. ");
     }
     else
     {
         string points = "points";
         if (Feat.MaxRank(feat_increased) + feats[feat_increased] == 1)
         {
             points = "point";
         }
         if (feats[feat_increased] == -1)
         {
             learned.Add("You start learning the " + Feat.Name(feat_increased) + " feat (" + (Feat.MaxRank(feat_increased) + feats[feat_increased]) + " " + points + " left). ");
         }
         else
         {
             learned.Add("You continue learning the " + Feat.Name(feat_increased) + " feat (" + (Feat.MaxRank(feat_increased) + feats[feat_increased]) + " " + points + " left). ");
         }
     }
     if (skill == SkillType.MAGIC)
     {
         List<SpellType> unknown = new List<SpellType>();
         List<colorstring> unknownstr = new List<colorstring>();
         foreach (SpellType spell in GetSpellTypes())
         {
             if (!HasSpell(spell) && spell != SpellType.BLESS && spell != SpellType.MINOR_HEAL
             && spell != SpellType.HOLY_SHIELD && spell != SpellType.NO_SPELL && spell != SpellType.NUM_SPELLS)
             {
                 unknown.Add(spell);
                 colorstring cs = new colorstring();
                 cs.strings.Add(new cstr(Spell.Name(spell).PadRight(15) + Spell.Level(spell).ToString().PadLeft(3), Color.Gray));
                 int failrate = (Spell.Level(spell) - TotalSkill(SkillType.MAGIC)) * 5;
                 if (failrate < 0)
                 {
                     failrate = 0;
                 }
                 cs.strings.Add(new cstr(failrate.ToString().PadLeft(9) + "%", FailColor(failrate)));
                 unknownstr.Add(cs + Spell.Description(spell));
             }
         }
         for (int i = unknown.Count + 2; i < ROWS; ++i)
         {
             Screen.WriteMapString(i, 0, "".PadRight(COLS));
         }
         colorstring topborder = new colorstring("------------------Level---Fail rate--------Description------------", Color.Gray);
         int selection = await Select("Learn which spell? ", topborder, new colorstring("".PadRight(25, '-') + "[", Color.Gray, "?", Color.Cyan, "] for help".PadRight(COLS, '-'), Color.Gray), unknownstr, false, true, false, true, HelpTopic.Spells);
         spells[unknown[selection]] = 1;
         learned.Add("You learn " + Spell.Name(unknown[selection]) + ". ");
         spells_in_order.Add(unknown[selection]);
     }
     if (learned.Count > 0)
     {
         foreach (string s in learned)
         {
             B.Add(s);
         }
     }
 }
 public async Task<bool> UseFeat(FeatType feat)
 {
     switch (feat)
     {
         case FeatType.LUNGE:
             {
                 List<Tile> line = await GetTarget(2);
                 Tile t = null;
                 if (line != null)
                 {
                     t = line.Last();
                 }
                 if (t != null && t.actor() != null)
                 {
                     bool moved = false;
                     /*foreach(Tile neighbor in t.NeighborsBetween(row,col)){
                         if(neighbor.passable && neighbor.actor() == null){
                             moved = true;
                             B.Add("You lunge! ");
                             Move(neighbor.row,neighbor.col);
                             attrs[AttrType.BONUS_COMBAT] += 4;
                             Attack(0,t.actor());
                             attrs[AttrType.BONUS_COMBAT] -= 4;
                             break;
                         }
                     }*/
                     if (DistanceFrom(t) == 2 && line[1].passable && line[1].actor() == null && !GrabPreventsMovement(line[1]))
                     {
                         moved = true;
                         B.Add("You lunge! ");
                         await Move(line[1].row, line[1].col);
                         attrs[AttrType.BONUS_COMBAT] += 4;
                         await Attack(0, t.actor());
                         attrs[AttrType.BONUS_COMBAT] -= 4;
                     }
                     if (!moved)
                     {
                         if (GrabPreventsMovement(line[1]))
                         {
                             B.Add("You can't currently reach that spot. ");
                             return false;
                         }
                         else
                         {
                             B.Add("The way is blocked! ");
                             return false;
                         }
                     }
                     else
                     {
                         MakeNoise();
                         return true;
                     }
                 }
                 else
                 {
                     return false;
                 }
                 //break;
             }
         case FeatType.TUMBLE:
             /*Tumble - (A, 200 energy) - You pick a tile within distance 2. If there is at least one passable tile between 
             you and it(you CAN tumble past actors), you move to that tile. Additional effects: If you move past an actor, 
             they lose sight of you and their turns_target_location is set to X - rand_function_of(stealth skill). (there's a good chance
             they'll find you, then attack, but you will have still moved past them) ; You will automatically dodge the first arrow
             that would hit you before your next turn.(it's still possible they'll roll 2 successes and hit you) ; Has the same
             effect as standing still, if you're on fire or catching fire. */
             {
                 target = null; //don't try to automatically pick previous targets while tumbling. this solution isn't ideal.
                 List<Tile> line = await GetTarget(false, 2, false);
                 target = null; //then, don't remember an actor picked as the target of tumble
                 Tile t = null;
                 if (line != null)
                 {
                     t = line.Last();
                 }
                 if (t != null && t.passable && t.actor() == null && !GrabPreventsMovement(t))
                 {
                     List<Actor> actors_moved_past = new List<Actor>();
                     bool moved = false;
                     foreach (Tile neighbor in t.NeighborsBetween(row, col))
                     {
                         if (neighbor.actor() != null)
                         {
                             actors_moved_past.Add(neighbor.actor());
                         }
                         if (neighbor.passable && !moved)
                         {
                             B.Add("You tumble. ");
                             await Move(t.row, t.col);
                             moved = true;
                             attrs[AttrType.TUMBLING]++;
                             if (HasAttr(AttrType.CATCHING_FIRE))
                             { //copy&paste happened here: todo, make a single fire-handling method
                                 attrs[AttrType.CATCHING_FIRE] = 0;
                                 B.Add("You stop the flames from spreading. ");
                                 if (HasAttr(AttrType.STARTED_CATCHING_FIRE_THIS_TURN))
                                 {
                                     attrs[AttrType.STARTED_CATCHING_FIRE_THIS_TURN] = 0;
                                     B.Add("You stop the flames from spreading. ");
                                 }
                             }
                             else
                             {
                                 if (HasAttr(AttrType.STARTED_CATCHING_FIRE_THIS_TURN))
                                 {
                                     attrs[AttrType.STARTED_CATCHING_FIRE_THIS_TURN] = 0;
                                     B.Add("You stop the flames from spreading. ");
                                 }
                                 else
                                 {
                                     if (HasAttr(AttrType.ON_FIRE))
                                     {
                                         bool update = false;
                                         int oldradius = LightRadius();
                                         if (attrs[AttrType.ON_FIRE] > light_radius)
                                         {
                                             update = true;
                                         }
                                         int i = 2;
                                         if (Global.Roll(1, 3) == 3)
                                         { // 1 in 3 times, you don't make progress against the fire
                                             i = 1;
                                         }
                                         attrs[AttrType.ON_FIRE] -= i;
                                         if (attrs[AttrType.ON_FIRE] < 0)
                                         {
                                             attrs[AttrType.ON_FIRE] = 0;
                                         }
                                         if (update)
                                         {
                                             UpdateRadius(oldradius, LightRadius());
                                         }
                                         if (HasAttr(AttrType.ON_FIRE))
                                         {
                                             B.Add("You put out some of the fire. ");
                                         }
                                         else
                                         {
                                             B.Add("You put out the fire. ");
                                         }
                                     }
                                 }
                             }
                         }
                     }
                     if (moved)
                     {
                         foreach (Actor a in actors_moved_past)
                         {
                             int i = 10 - Global.Roll(Stealth());
                             if (i < 0)
                             {
                                 i = 0;
                             }
                             a.player_visibility_duration = i;
                         }
                         Q.Add(new Event(this, 200, EventType.MOVE));
                         return true;
                     }
                     else
                     {
                         B.Add("The way is blocked! ");
                         return false;
                     }
                 }
                 else
                 {
                     if (GrabPreventsMovement(t))
                     {
                         B.Add("You can't currently reach that spot. ");
                     }
                     return false;
                 }
                 //break;
             }
         case FeatType.ARCANE_SHIELD: //25% fail rate for the 'failrate' feats
             if (magic_penalty < 20)
             {
                 /*if(curhp < maxhp){ here's the old arcane healing feat
                     magic_penalty += 5;
                     if(magic_penalty > 20){
                         magic_penalty = 20;
                     }
                     B.Add("You drain your magic reserves. ");
                     int amount = Global.Roll(TotalSkill(SkillType.MAGIC)/2,6) + 25;
                     TakeDamage(DamageType.HEAL,DamageClass.NO_TYPE,amount,null);
                     if(curhp == maxhp){
                         B.Add("Your wounds close. ");
                     }
                     else{
                         B.Add("Some of your wounds close. ");
                     }
                 }
                 else{
                     B.Add("You're not injured. ");
                     return false;
                 }*/
                 magic_penalty += 5;
                 if (magic_penalty > 20)
                 {
                     magic_penalty = 20;
                 }
                 B.Add("You drain your magic reserves. ");
                 int amount = Global.Roll(TotalSkill(SkillType.MAGIC) / 2, 6) + 25;
                 if (HasAttr(AttrType.ARCANE_SHIELDED))
                 {
                     B.Add("You strengthen your arcane barrier. ");
                 }
                 else
                 {
                     B.Add("An arcane barrier surrounds you. ");
                 }
                 attrs[Forays.AttrType.ARCANE_SHIELDED] += amount;
                 Q.KillEvents(this, AttrType.ARCANE_SHIELDED);
                 Q.Add(new Event(this, 2000, Forays.AttrType.ARCANE_SHIELDED, "Your arcane shield dissolves. "));
             }
             else
             {
                 B.Add("Your magic reserves are empty! ");
                 return false;
             }
             break;
         case FeatType.FORCE_OF_WILL:
             foreach (Actor a in ActorsWithinDistance(2))
             {
                 if (a.HasAttr(AttrType.SPELL_DISRUPTION) && a.HasLOE(this))
                 {
                     if (this == player)
                     {
                         if (CanSee(a))
                         {
                             B.Add(a.Your() + " presence prevents you from casting! ");
                         }
                         else
                         {
                             B.Add("Something prevents you from casting! ");
                         }
                     }
                     return false;
                 }
             }
             if (magic_penalty < 20)
             {
                 int basefail = magic_penalty * 5;
                 basefail -= skills[SkillType.SPIRIT] * 2;
                 if (basefail > 100)
                 {
                     basefail = 100;
                 }
                 if (basefail < 0)
                 {
                     basefail = 0;
                 }
                 List<colorstring> ls = new List<colorstring>();
                 List<SpellType> sp = new List<SpellType>();
                 bool bonus_marked = false;
                 foreach (SpellType spell in spells_in_order)
                 {
                     if (HasSpell(spell))
                     {
                         colorstring cs = new colorstring(Spell.Name(spell).PadRight(15) + Spell.Level(spell).ToString().PadLeft(3), Color.Gray);
                         cs.strings.Add(new cstr(basefail.ToString().PadLeft(9) + "%", FailColor(basefail)));
                         if (HasFeat(FeatType.MASTERS_EDGE) && Spell.IsDamaging(spell) && !bonus_marked)
                         {
                             bonus_marked = true;
                             cs = cs + Spell.DescriptionWithIncreasedDamage(spell);
                         }
                         else
                         {
                             cs = cs + Spell.Description(spell);
                         }
                         ls.Add(cs);
                         sp.Add(spell);
                     }
                 }
                 if (sp.Count > 0)
                 {
                     colorstring topborder = new colorstring("------------------Level---Fail rate--------Description------------", Color.Gray);
                     colorstring bottomborder = new colorstring("---Force of will fail rate: ", Color.Gray, (basefail.ToString().PadLeft(3) + "%"), FailColor(basefail), "".PadRight(37, '-'), Color.Gray);
                     int i = await Select("Use force of will to cast which spell? ", topborder, bottomborder, ls, false, false, true, true, HelpTopic.Spells);
                     if (i != -1)
                     {
                         if (true != await CastSpell(sp[i], true))
                         {
                             Q0();
                             return true;
                         }
                         else
                         { //drained magic is now handled in CastSpell
                             return true;
                         }
                     }
                     else
                     {
                         Q0();
                         return true;
                     }
                 }
                 else
                 {
                     Q0();
                     return true;
                 }
             }
             else
             {
                 B.Add("Your magic reserves are empty! ");
                 return false;
             }
         //break;
         case FeatType.DISARM_TRAP:
             {
                 int dir = await GetDirection("Disarm which trap? ");
                 if (dir != -1 && TileInDirection(dir).IsKnownTrap())
                 {
                     if (ActorInDirection(dir) != null)
                     {
                         B.Add("There is " + ActorInDirection(dir).AVisible() + " in the way. ");
                     }
                     else
                     {
                         if (GrabPreventsMovement(TileInDirection(dir)))
                         {
                             B.Add("You can't currently reach that trap. ");
                             Q0();
                             return true;
                         }
                         if (Global.Roll(5) <= 4)
                         {
                             B.Add("You disarm " + Tile.Prototype(TileInDirection(dir).ttype).the_name + ". ");
                             TileInDirection(dir).Toggle(this);
                             Q1();
                         }
                         else
                         {
                             if (Global.Roll(20) <= skills[SkillType.DEFENSE])
                             {
                                 B.Add("You almost set off " + Tile.Prototype(TileInDirection(dir).ttype).the_name + "! ");
                                 Q1();
                             }
                             else
                             {
                                 B.Add("You set off " + Tile.Prototype(TileInDirection(dir).ttype).the_name + "! ");
                                 await Move(TileInDirection(dir).row, TileInDirection(dir).col);
                                 Q1();
                             }
                         }
                     }
                 }
                 else
                 {
                     Q0();
                 }
                 return true;
             }
         case FeatType.DISTRACT:
             {
                 List<Tile> line = await GetTarget(12, 3);
                 Tile t = null;
                 if (line != null)
                 {
                     t = line.Last();
                 }
                 if (t != null)
                 {
                     if (!t.passable)
                     {
                         t = line.LastBeforeSolidTile();
                     }
                     B.Add("You throw a small stone. ");
                     foreach (Actor a in t.ActorsWithinDistance(3))
                     {
                         if (a != this && a.player_visibility_duration >= 0)
                         {
                             if (a.HasAttr(AttrType.DISTRACTED))
                             {
                                 B.Add(a.the_name + " isn't fooled. ", a);
                                 a.player_visibility_duration = 999; //automatic detection next turn
                             }
                             else
                             {
                                 List<pos> p = a.GetPath(t);
                                 if (p.Count <= 6)
                                 {
                                     a.path = p;
                                     if (Global.CoinFlip())
                                     {
                                         a.attrs[Forays.AttrType.DISTRACTED]++;
                                     }
                                 }
                             }
                         }
                     }
                 }
                 else
                 {
                     return false;
                 }
                 break;
             }
         default:
             return false;
     }
     Q1();
     return true;
 }
Example #21
0
        public void InputHuman()
        {
            if(HasAttr(AttrType.DETECTING_MOVEMENT) && footsteps.Count > 0 && time_of_last_action < Q.turn){
                Screen.CursorVisible = false;
                Screen.AnimateMapCells(footsteps,new colorchar('!',Color.Red));
                previous_footsteps = footsteps;
                footsteps = new List<pos>();
            }
            if(HasAttr(AttrType.SWITCHING_ARMOR)){
                attrs[AttrType.SWITCHING_ARMOR]--;
            }
            if(HasFeat(FeatType.DANGER_SENSE)){
                M.UpdateDangerValues();
            }
            Screen.UpdateScreenCenterColumn(col);
            M.Draw();
            UI.MapCursor = new pos(-1,-1);
            UI.DisplayStats();
            if(HasAttr(AttrType.AUTOEXPLORE) && !grab_item_at_end_of_path){
                if(path.Count == 0){ //todo: autoexplore could also track whether the current path is leading to an unexplored tile instead of to an item/shrine/etc.
                    if(!FindAutoexplorePath()){ // - in this case I could check that tile's neighbors each turn, and calculate a new path early if they've all been mapped now.
                        B.Add("You don't see a path for further exploration. ");
                    }
                }
            }
            if(!HasAttr(AttrType.PARALYZED) && !HasAttr(AttrType.ASLEEP)){
                B.Print(false);
            }
            else{
                B.DisplayNow();
            }
            Cursor();
            Screen.CursorVisible = true;
            if(HasAttr(AttrType.PARALYZED,AttrType.ASLEEP)){
                if(HasAttr(AttrType.ASLEEP)){
                    Thread.Sleep(25);
                }
                Q1();
                return;
            }
            if(HasAttr(AttrType.ENRAGED) && !HasAttr(AttrType.FROZEN)){
                Thread.Sleep(100);
                EnragedMove();
                return;
            }
            bool pick_up = false;
            if(tile().inv != null || tile().type == TileType.CHEST){
                if(grab_item_at_end_of_path && path.Count == 0){
                    pick_up = true;
                }
                if((Global.Option(OptionType.AUTOPICKUP) && InventoryCount() < Global.MAX_INVENTORY_SIZE && (tile().type == TileType.CHEST || !tile().inv.ignored))){
                    pick_up = true;
                }
            }
            if(pick_up){
                if(!NextStepIsDangerous(tile())){
                    if(StunnedThisTurn()){
                        return;
                    }
                    if(tile().type == TileType.CHEST){
                        tile().OpenChest();
                        if(tile().type != TileType.CHEST){
                            grab_item_at_end_of_path = false;
                        }
                        Q1();
                    }
                    else{
                        if(InventoryCount() + tile().inv.quantity <= Global.MAX_INVENTORY_SIZE){
                            Item i = tile().inv;
                            tile().inv = null;
                            if(i.light_radius > 0){
                                i.UpdateRadius(i.light_radius,0);
                            }
                            i.row = -1;
                            i.col = -1;
                            B.Add("You pick up " + i.TheName() + ". ");
                            GetItem(i);
                            Q1();
                        }
                        else{
                            Item i = tile().inv;
                            int space_left = Global.MAX_INVENTORY_SIZE - InventoryCount();
                            if(space_left <= 0){
                                B.Add("You have no room for " + i.TheName() + ". ");
                                i.ignored = true;
                                Q0();
                            }
                            else{
                                Item newitem = new Item(i,row,col);
                                newitem.quantity = space_left;
                                i.quantity -= space_left;
                                B.Add("You pick up " + newitem.TheName() + ", but have no room for the other " + i.quantity.ToString() + ". ");
                                i.ignored = true;
                                GetItem(newitem);
                                Q1();
                            }
                        }
                        grab_item_at_end_of_path = false;
                    }
                    return;
                }
            }
            if(path.Count > 0){
                if(!NextStepIsDangerous(M.tile[path[0]])){
                    if(Input.KeyIsAvailable()){
                        ConsoleKeyInfo key = Input.ReadKey();
                        if(key.GetCommandChar() == 'x' && HasAttr(AttrType.AUTOEXPLORE)){
                            PlayerWalk(DirectionOf(path[0]));
                            if(path.Count > 0){
                                if(DistanceFrom(path[0]) == 0){
                                    path.RemoveAt(0);
                                }
                            }
                            return;
                        }
                        else{
                            Interrupt();
                        }
                    }
                    else{
                        PlayerWalk(DirectionOf(path[0]));
                        if(path.Count > 0){
                            if(DistanceFrom(path[0]) == 0){
                                path.RemoveAt(0);
                            }
                        }
                        return;
                    }
                }
                else{
                    Interrupt();
                }
            }
            if(HasAttr(AttrType.RUNNING)){
                Tile next = TileInDirection(attrs[AttrType.RUNNING]);
                if(!NextStepIsDangerous(next) && !Input.KeyIsAvailable()){
                    if(attrs[AttrType.RUNNING] == 5){
                        bool recover = false;
                        if(!HasAttr(AttrType.NONLIVING)){
                            if(HasFeat(FeatType.ENDURING_SOUL) && curhp % 10 != 0){
                                recover = true;
                            }
                            if(HasAttr(AttrType.BANDAGED)){
                                recover = true;
                            }
                        }
                        if(!recover){
                            if(HasAttr(AttrType.WAITING)){
                                attrs[AttrType.WAITING]--;
                                Q1();
                                return;
                            }
                            else{
                                attrs[AttrType.RUNNING] = 0;
                            }
                        }
                        else{
                            Q1();
                            return;
                        }
                    }
                    else{
                        bool corridor = true;
                        foreach(int dir in U.FourDirections){
                            if(TileInDirection(dir).passable && TileInDirection(dir.RotateDir(true,1)).passable && TileInDirection(dir.RotateDir(true,2)).passable){
                                corridor = false;
                                break;
                            }
                        }
                        List<Tile> tiles = new List<Tile>();
                        if(corridor){
                            List<int> blocked = new List<int>();
                            for(int i=-1;i<=1;++i){
                                blocked.Add(attrs[AttrType.RUNNING].RotateDir(true,4+i));
                            }
                            tiles = TilesAtDistance(1).Where(x=>(x.passable || x.Is(TileType.DOOR_C,TileType.RUBBLE)) && ApproximateEuclideanDistanceFromX10(x) == 10 && !blocked.Contains(DirectionOf(x)));
                        }
                        if(!corridor && next.passable){
                            PlayerWalk(attrs[AttrType.RUNNING]);
                            return;
                        }
                        else{
                            if(corridor && tiles.Count == 1){
                                attrs[AttrType.RUNNING] = DirectionOf(tiles[0]);
                                PlayerWalk(attrs[AttrType.RUNNING]);
                                foreach(int dir in U.FourDirections){ //now check again to see whether the player has entered a room
                                    if(TileInDirection(dir).passable && TileInDirection(dir.RotateDir(true,1)).passable && TileInDirection(dir.RotateDir(true,2)).passable){
                                        corridor = false;
                                        break;
                                    }
                                }
                                if(!corridor){
                                    attrs[AttrType.RUNNING] = 0;
                                    attrs[AttrType.WAITING] = 0;
                                }
                                return;
                            }
                            else{
                                attrs[AttrType.RUNNING] = 0;
                                attrs[AttrType.WAITING] = 0;
                            }
                            /*Tile opposite = TileInDirection(attrs[AttrType.RUNNING].RotateDir(true,4));
                            int num_floors = 0;
                            int floor_dir = 0;
                            foreach(Tile t2 in TilesAtDistance(1)){
                                //if(t2 != opposite && t2.name == "floor"){
                                if(t2 != opposite && (t2.passable || t2.type == TileType.DOOR_C)){
                                    num_floors++;
                                    floor_dir = DirectionOf(t2);
                                }
                            }
                            if(num_floors == 1){
                                attrs[AttrType.RUNNING] = floor_dir;//the purpose of this code is to detect whether there's a valid turn to make
                                PlayerWalk(floor_dir); //and take it if so. if there's a branch, it should stop.
                                return;
                            }
                            else{
                                attrs[AttrType.RUNNING] = 0;
                                attrs[AttrType.WAITING] = 0;
                            }*/
                        }
                    }
                }
                else{
                    if(Input.KeyIsAvailable()){
                        Input.ReadKey();
                    }
                    attrs[AttrType.RUNNING] = 0;
                    attrs[AttrType.WAITING] = 0;
                }
            }
            if(HasAttr(AttrType.RESTING)){
                if(attrs[AttrType.RESTING] == 10){
                    attrs[AttrType.RESTING] = -1;
                    curhp = maxhp;
                    curmp = maxmp;
                    B.Add("You rest...you feel great! ");
                    RemoveExhaustion();
                    bool repaired = false;
                    foreach(EquipmentStatus eqstatus in Enum.GetValues(typeof(EquipmentStatus))){
                        foreach(Weapon w in weapons){
                            if(w.status[eqstatus]){
                                repaired = true;
                                w.status[eqstatus] = false;
                            }
                        }
                        foreach(Armor a in armors){
                            if(a.status[eqstatus]){
                                repaired = true;
                                a.status[eqstatus] = false;
                            }
                        }
                    }
                    if(repaired){
                        B.Add("You finish repairing your equipment. ");
                    }
                    if(magic_trinkets.Contains(MagicTrinketType.CIRCLET_OF_THE_THIRD_EYE)){
                        Event hiddencheck = null;
                        foreach(Event e in Q.list){
                            if(!e.dead && e.type == EventType.CHECK_FOR_HIDDEN){
                                hiddencheck = e;
                                break;
                            }
                        }
                        List<Tile> valid_list = M.AllTiles().Where(x=>x.passable && !x.seen);
                        while(valid_list.Count > 0){
                            Tile chosen = valid_list.RemoveRandom();
                            if(chosen == null){
                                break;
                            }
                            var dijkstra = M.tile.GetDijkstraMap(new List<pos>{chosen.p},x=>!M.tile[x].passable && !M.tile[x].IsDoorType(true)); //todo: blocksconnectivityofmap?
                            if(chosen.TilesWithinDistance(18).Where(x=>x.passable && !x.seen && dijkstra[x.p] <= 18).Count < 20){
                                continue;
                            }
                            foreach(Tile t in chosen.TilesWithinDistance(12)){
                                if(t.type != TileType.FLOOR && !t.solid_rock){
                                    t.seen = true;
                                    if(t.type != TileType.WALL){
                                        t.revealed_by_light = true;
                                    }
                                    if(t.IsTrap() || t.Is(TileType.HIDDEN_DOOR)){
                                        if(hiddencheck != null){
                                            hiddencheck.area.Remove(t);
                                        }
                                    }
                                    if(t.IsTrap()){
                                        t.name = Tile.Prototype(t.type).name;
                                        t.a_name = Tile.Prototype(t.type).a_name;
                                        t.the_name = Tile.Prototype(t.type).the_name;
                                        t.symbol = Tile.Prototype(t.type).symbol;
                                        t.color = Tile.Prototype(t.type).color;
                                    }
                                    if(t.Is(TileType.HIDDEN_DOOR)){
                                        t.Toggle(null);
                                    }
                                    colorchar ch2 = Screen.BlankChar();
                                    if(t.inv != null){
                                        t.inv.revealed_by_light = true;
                                        ch2.c = t.inv.symbol;
                                        ch2.color = t.inv.color;
                                        M.last_seen[t.row,t.col] = ch2;
                                    }
                                    else{
                                        if(t.features.Count > 0){
                                            ch2 = t.FeatureVisual();
                                            M.last_seen[t.row,t.col] = ch2;
                                        }
                                        else{
                                            ch2.c = t.symbol;
                                            ch2.color = t.color;
                                            if(ch2.c == '#' && ch2.color == Color.RandomGlowingFungus){
                                                ch2.color = Color.Gray;
                                            }
                                            M.last_seen[t.row,t.col] = ch2;
                                        }
                                    }
                                }
                            }
                            M.Draw();
                            B.Add("Your " + MagicTrinket.Name(MagicTrinketType.CIRCLET_OF_THE_THIRD_EYE) + " grants you a vision. ");
                            break;
                        }
                    }
                    B.Print(false);
                    UI.DisplayStats();
                    Cursor();
                }
                else{
                    bool monsters_visible = false;
                    foreach(Actor a in M.AllActors()){
                        if(a != this && CanSee(a) && HasLOS(a.row,a.col)){ //check LOS, prevents detected mobs from stopping you
                            if(!a.Is(ActorType.CARNIVOROUS_BRAMBLE,ActorType.MUD_TENTACLE) || DistanceFrom(a) <= 1){
                                monsters_visible = true;
                            }
                        }
                    }
                    if(monsters_visible || Input.KeyIsAvailable()){
                        if(Input.KeyIsAvailable()){
                            Input.ReadKey();
                        }
                        if(monsters_visible){
                            attrs[AttrType.RESTING] = 0;
                            B.Add("You rest...you are interrupted! ");
                            B.Print(false);
                            Cursor();
                        }
                        else{
                            attrs[AttrType.RESTING] = 0;
                            B.Add("You rest...you stop resting. ");
                            B.Print(false);
                            Cursor();
                        }
                    }
                    else{
                        attrs[AttrType.RESTING]++;
                        B.Add("You rest... ",true);
                        Q1();
                        return;
                    }
                }
            }
            MouseUI.IgnoreMouseMovement = false;
            if(Q.turn == 0){
                Help.TutorialTip(TutorialTopic.Movement); //todo: move this elsewhere?
                Cursor();
            }
            if(!Help.displayed[TutorialTopic.Attacking] && M.AllActors().Any(a=>(a != this && CanSee(a)))){
                Help.TutorialTip(TutorialTopic.Attacking);
                Cursor();
            }
            ConsoleKeyInfo command = Input.ReadKey();
            char ch = command.GetAction().GetCommandChar();
            bool alt = false;
            bool ctrl = false;
            bool shift = false;
            if((command.Modifiers & ConsoleModifiers.Alt) == ConsoleModifiers.Alt){
                alt = true;
            }
            if((command.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control){
                ctrl = true;
            }
            if((command.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift){
                shift = true;
            }
            switch(ch){
            case '7':
            case '8':
            case '9':
            case '4':
            case '6':
            case '1':
            case '2':
            case '3':
            {
                if(FrozenThisTurn()){
                    break;
                }
                if(HasAttr(AttrType.CONFUSED)){
                    PlayerWalk(Global.RandomDirection());
                    break;
                }
                int dir = ch - 48; //ascii 0-9 are 48-57
                if(shift || alt || ctrl){
                    bool monsters_visible = false;
                    foreach(Actor a in M.AllActors()){
                        if(a!=this && CanSee(a) && HasLOS(a.row,a.col)){
                            if(!a.Is(ActorType.CARNIVOROUS_BRAMBLE,ActorType.MUD_TENTACLE) || DistanceFrom(a) <= 2){
                                monsters_visible = true;
                            }
                        }
                    }
                    PlayerWalk(dir);
                    if(!monsters_visible){
                        attrs[AttrType.RUNNING] = dir;
                    }
                }
                else{
                    PlayerWalk(dir);
                }
                break;
            }
            case '5':
            {
                if(tile().inv != null){
                    tile().inv.revealed_by_light = true;
                    if(tile().inv.quantity > 1){
                        B.Add("There are " + tile().inv.AName() + " here. ");
                    }
                    else{
                        B.Add("There is " + tile().inv.AName() + " here. ");
                    }
                    //B.Add("You see " + M.tile[row,col].inv.AName() + ". ");
                }
                if(HasAttr(AttrType.BURNING)){
                    if(tile().IsWater() && !tile().Is(FeatureType.OIL)){
                        B.Add("You extinguish the flames. ");
                        attrs[AttrType.BURNING] = 0;
                        if(light_radius == 0){
                            UpdateRadius(1,0);
                        }
                        Q.KillEvents(this,AttrType.BURNING);
                        Fire.burning_objects.Remove(this);
                    }
                    else{
                        if(tile().Is(FeatureType.SLIME)){
                            B.Add("You cover yourself in slime to remove the flames. ");
                            attrs[AttrType.BURNING] = 0;
                            if(light_radius == 0){
                                UpdateRadius(1,0);
                            }
                            Q.KillEvents(this,AttrType.BURNING);
                            attrs[AttrType.SLIMED] = 1;
                            Fire.burning_objects.Remove(this);
                            Help.TutorialTip(TutorialTopic.Slimed);
                        }
                    }
                }
                if(HasAttr(AttrType.SLIMED) && tile().IsWater() && !tile().Is(FeatureType.FIRE)){
                    attrs[AttrType.SLIMED] = 0;
                    B.Add("You wash off the slime. ");
                }
                if(HasAttr(AttrType.OIL_COVERED) && tile().Is(FeatureType.SLIME)){
                    attrs[AttrType.OIL_COVERED] = 0;
                    attrs[AttrType.SLIMED] = 1;
                    B.Add("You cover yourself in slime to remove the oil. ");
                    Help.TutorialTip(TutorialTopic.Slimed);
                }
                if(HasAttr(AttrType.OIL_COVERED) && tile().IsWater() && !tile().Is(FeatureType.FIRE,FeatureType.OIL)){
                    attrs[AttrType.OIL_COVERED] = 0;
                    B.Add("You wash off the oil. ");
                    tile().AddFeature(FeatureType.OIL);
                }
                attrs[AttrType.NO_PLATE_ARMOR_NOISE] = 1;
                if(Speed() < 100){
                    QS();
                }
                else{
                    Q1();
                }
                break;
            }
            case 'w':
            {
                int dir = GetDirection("Start walking in which direction? ",false,true);
                if(dir != 0){
                    bool monsters_visible = false;
                    foreach(Actor a in M.AllActors()){
                        if(a != this && CanSee(a) && HasLOS(a.row,a.col)){
                            if(!a.Is(ActorType.CARNIVOROUS_BRAMBLE,ActorType.MUD_TENTACLE) || DistanceFrom(a) <= 2){
                                monsters_visible = true;
                            }
                        }
                    }
                    if(dir != 5){
                        if(FrozenThisTurn()){
                            break;
                        }
                        PlayerWalk(dir);
                    }
                    else{
                        QS();
                    }
                    if(!monsters_visible){
                        attrs[AttrType.RUNNING] = dir;
                        bool recover = false;
                        if(!HasAttr(AttrType.NONLIVING)){
                            if(HasFeat(FeatType.ENDURING_SOUL) && curhp % 10 != 0){
                                recover = true;
                            }
                            if(HasAttr(AttrType.BANDAGED)){
                                recover = true;
                            }
                        }
                        if(!recover && dir == 5){
                            attrs[AttrType.WAITING] = 20;
                        }
                    }
                }
                else{
                    Q0();
                }
                break;
            }
            case 'o':
            {
                if(FrozenThisTurn()){
                    break;
                }
                int dir = GetDirection("Operate something in which direction? ");
                if(dir != -1){
                    Tile t = TileInDirection(dir);
                    if(t.IsKnownTrap()){
                        if(HasFeat(FeatType.DISARM_TRAP)){
                            if(ActorInDirection(dir) != null){
                                B.Add("There is " + ActorInDirection(dir).AName(true) + " in the way. ");
                                Q0();
                                return;
                            }
                            if(StunnedThisTurn()){
                                return;
                            }
                            if(t.name.Contains("(safe)")){
                                B.Add("You disarm " + Tile.Prototype(t.type).the_name + ". ");
                                t.Toggle(this);
                            }
                            else{
                                B.Add("You make " + Tile.Prototype(t.type).the_name + " safe to cross. ");
                                t.SetName(Tile.Prototype(t.type).name + " (safe)");
                            }
                            Q1();
                        }
                        else{
                            B.Add("You don't know how to disable that trap. ");
                            Q0();
                            return;
                        }
                    }
                    else{
                        switch(t.type){
                        case TileType.DOOR_C:
                        case TileType.DOOR_O:
                        case TileType.RUBBLE:
                            if(StunnedThisTurn()){
                                break;
                            }
                            if(t.type == TileType.RUBBLE && !HasAttr(AttrType.BRUTISH_STRENGTH)){
                                IncreaseExhaustion(1);
                            }
                            t.Toggle(this);
                            Q1();
                            break;
                        case TileType.CHEST:
                            B.Add("Stand on the chest and press 'g' to retrieve its contents. ");
                            Q0();
                            break;
                        case TileType.STAIRS:
                            B.Add("Stand on the stairs and press '>' to descend. ");
                            Q0();
                            break;
                        case TileType.POOL_OF_RESTORATION:
                            B.Add("Stand over the pool and drop an item in to activate it. ");
                            Q0();
                            break;
                        case TileType.STONE_SLAB:
                            B.Add("The slab will open if light shines upon it. ");
                            Q0();
                            break;
                        default:
                            if(t.IsShrine()){
                                B.Add("Stand on the shrine and press 'g' to activate it. ");
                            }
                            Q0();
                            break;
                        }
                    }
                }
                else{
                    Q0();
                }
                break;
            }
            case 's':
            {
                if(FrozenThisTurn()){
                    break;
                }
                if(Bow.status[EquipmentStatus.OUT_OF_ARROWS]){
                    B.Add("You're out of arrows! ");
                    Q0();
                }
                else{
                    if(EquippedWeapon.type == WeaponType.BOW || HasFeat(FeatType.QUICK_DRAW)){
                        if(ActorsAtDistance(1).Count > 0){
                            int seen = ActorsAtDistance(1).Where(x=>CanSee(x)).Count;
                            if(seen > 0){
                                if(seen == 1){
                                    B.Add("You can't fire with an enemy so close. ");
                                }
                                else{
                                    B.Add("You can't fire with enemies so close. ");
                                }
                                Q0();
                            }
                            else{
                                B.Add("As you raise your bow, something knocks it down! ");
                                B.Print(true);
                                Q1();
                            }
                        }
                        else{
                            MouseUI.fire_arrow_hack = true;
                            List<Tile> line = GetTargetLine(12);
                            if(line != null && line.LastOrDefault() != tile()){
                                if(EquippedWeapon != Bow && HasFeat(FeatType.QUICK_DRAW)){
                                    EquippedWeapon = Bow;
                                }
                                FireArrow(line);
                                if(Bow.status[EquipmentStatus.ONE_ARROW_LEFT]){
                                    Bow.status[EquipmentStatus.ONE_ARROW_LEFT] = false;
                                    Bow.status[EquipmentStatus.OUT_OF_ARROWS] = true;
                                }
                                else{
                                    if(Bow.status[EquipmentStatus.ALMOST_OUT_OF_ARROWS]){
                                        if(R.OneIn(15)){
                                            Bow.status[EquipmentStatus.ALMOST_OUT_OF_ARROWS] = false;
                                            Bow.status[EquipmentStatus.ONE_ARROW_LEFT] = true;
                                            B.Add("You're down to your last arrow! ");
                                            B.PrintAll();
                                        }
                                    }
                                    else{
                                        if(Bow.status[EquipmentStatus.LOW_ON_ARROWS]){
                                            if(R.OneIn(20)){
                                                Bow.status[EquipmentStatus.LOW_ON_ARROWS] = false;
                                                Bow.status[EquipmentStatus.ALMOST_OUT_OF_ARROWS] = true;
                                                B.Add("You have only a few arrows left! ");
                                                B.PrintAll();
                                            }
                                        }
                                        else{
                                            if(R.OneIn(25)){
                                                Bow.status[EquipmentStatus.LOW_ON_ARROWS] = true;
                                                B.Add("You're running a bit low on arrows. ");
                                                B.PrintAll();
                                            }
                                        }
                                    }
                                }
                            }
                            else{
                                Q0();
                            }
                        }
                    }
                    else{
                        B.Add("You need your bow to fire arrows - press e to switch equipment. ");
                        //B.Add("You can't fire arrows without your bow equipped - press e to switch equipment. ");
                        Q0();
                    }
                }
                break;
            }
            case 'z':
            {
                if(FrozenThisTurn()){
                    break;
                }
                foreach(Actor a in ActorsWithinDistance(2)){
                    if(a.HasAttr(AttrType.SILENCE_AURA) && a.HasLOE(this)){
                        if(this == player){
                            if(CanSee(a)){
                                B.Add(a.Your() + " aura of silence prevents you from casting! ");
                            }
                            else{
                                B.Add("An aura of silence prevents you from casting! ");
                            }
                        }
                        Q0();
                        return;
                    }
                }
                if(HasAttr(AttrType.SILENCED)){
                    B.Add("You can't cast while silenced. ");
                    Q0();
                    return;
                }
                List<colorstring> ls = new List<colorstring>();
                List<SpellType> sp = new List<SpellType>();
                //foreach(SpellType spell in Enum.GetValues(typeof(SpellType))){
                bool bonus_marked = false;
                foreach(SpellType spell in spells_in_order){
                    if(HasSpell(spell)){
                        //string s = Spell.Name(spell).PadRight(15) + Spell.Tier(spell).ToString().PadLeft(3);
                        //s = s + FailRate(spell).ToString().PadLeft(9) + "%";
                        //s = s + Spell.Description(spell).PadLeft(34);
                        //this is the recent one!   colorstring cs = new colorstring(Spell.Name(spell).PadRight(17) + Spell.Tier(spell).ToString().PadLeft(3),Color.Gray);
                        colorstring cs = new colorstring(Spell.Name(spell).PadRight(17) + Spell.Tier(spell).ToString().PadLeft(2),Color.Gray);
                        //cs.strings.Add(new cstr(FailRate(spell).ToString().PadLeft(9) + "%",FailColor(spell)));
                        int failrate = Spell.FailRate(spell,exhaustion);
                        cs.strings.Add(new cstr("/",Color.DarkGray));
                        cs.strings.Add(new cstr((failrate.ToString() + "%  ").PadRight(5),FailColor(failrate)));
                        // this too cs.strings.Add(new cstr("".PadLeft(5),Color.Gray));
                        if(HasFeat(FeatType.MASTERS_EDGE) && Spell.IsDamaging(spell) && !bonus_marked){
                            bonus_marked = true;
                            cs = cs + Spell.DescriptionWithIncreasedDamage(spell);
                        }
                        else{
                            cs = cs + Spell.Description(spell);
                        }
                        ls.Add(cs);
                        sp.Add(spell);
                    }
                }
                if(sp.Count > 0){
                    colorstring topborder = new colorstring("-------------------Tier/Fail%-----------Description---------------",Color.Gray);
                    //colorstring topborder = new colorstring("-------------------Tier (fail%)---------Description---------------",Color.Gray);
                    //colorstring topborder = new colorstring("---------------------Tier-----------------Description-------------",Color.Gray);
                    colorstring bottomborder = new colorstring("".PadRight(25,'-') + "[",Color.Gray,"?",Color.Cyan,"] for help".PadRight(COLS,'-'),Color.Gray);
                    //colorstring bottomborder = new colorstring("----------------" + "Exhaustion: ".PadLeft(12+(3-basefail.ToString().Length),'-'),Color.Gray,(basefail.ToString() + "%"),FailColor(basefail),"----------[",Color.Gray,"?",Color.Cyan,"] for help".PadRight(22,'-'),Color.Gray);
                    //int i = Select("Cast which spell? ",topborder,bottomborder,ls);
                    int i = Select("Cast which spell? ",topborder,bottomborder,ls,false,false,true,true,HelpTopic.Spells);
                    if(i != -1){
                        if(!CastSpell(sp[i])){
                            Q0();
                        }
                    }
                    else{
                        Q0();
                    }
                }
                else{
                    B.Add("You don't know any spells. ");
                    Q0();
                }
                break;
            }
            case 'r':
                if(FrozenThisTurn()){
                    break;
                }
                if(attrs[AttrType.RESTING] != -1){ //gets set to -1 if you've rested on this level
                    bool monsters_visible = false;
                    foreach(Actor a in M.AllActors()){
                        if(a != this && CanSee(a) && HasLOS(a.row,a.col)){ //check LOS, prevents detected mobs from stopping you
                            if(!a.Is(ActorType.CARNIVOROUS_BRAMBLE,ActorType.MUD_TENTACLE) || DistanceFrom(a) <= 1){
                                monsters_visible = true;
                            }
                        }
                    }
                    bool equipment_can_be_repaired = false;
                    foreach(EquipmentStatus eqs in Enum.GetValues(typeof(EquipmentStatus))){
                        foreach(Weapon w in weapons){
                            if(w.status[eqs]){
                                equipment_can_be_repaired = true;
                                break;
                            }
                        }
                        foreach(Armor a in armors){
                            if(a.status[eqs]){
                                equipment_can_be_repaired = true;
                                break;
                            }
                        }
                        if(equipment_can_be_repaired){
                            break;
                        }
                    }
                    if(!monsters_visible){
                        if(curhp < maxhp || curmp < maxmp || exhaustion > 0 || equipment_can_be_repaired){
                            if(Global.Option(OptionType.CONFIRM_BEFORE_RESTING) && !B.YesOrNoPrompt("Rest and repair your equipment?")){
                                Q0();
                                break;
                            }
                            if(StunnedThisTurn()){
                                break;
                            }
                            attrs[AttrType.RESTING] = 1;
                            B.Add("You rest... ",true);
                            Q1();
                        }
                        else{
                            B.Add("You don't need to rest right now. ");
                            Q0();
                        }
                    }
                    else{
                        B.Add("You can't rest while there are enemies around! ");
                        Q0();
                    }
                }
                else{
                    B.Add("You find it impossible to rest again on this dungeon level. ");
                    Q0();
                }
                break;
            case '>':
                if(FrozenThisTurn()){
                    break;
                }
                if(M.tile[row,col].type == TileType.STAIRS){
                    if(StunnedThisTurn()){
                        break;
                    }
                    bool equipment_can_be_repaired = false;
                    foreach(EquipmentStatus eqs in Enum.GetValues(typeof(EquipmentStatus))){
                        foreach(Weapon w in weapons){
                            if(w.status[eqs]){
                                equipment_can_be_repaired = true;
                                break;
                            }
                        }
                        foreach(Armor a in armors){
                            if(a.status[eqs]){
                                equipment_can_be_repaired = true;
                                break;
                            }
                        }
                        if(equipment_can_be_repaired){
                            break;
                        }
                    }
                    if(attrs[AttrType.RESTING] != -1 && (curhp < maxhp || curmp < maxmp || exhaustion > 0 || equipment_can_be_repaired)){
                        MouseUI.descend_hack = true;
                        if(!B.YesOrNoPrompt("Really take the stairs without resting first?")){
                            Q0();
                            return;
                        }
                    }
                    bool shrine_remaining = false;
                    for(int i=0;i<ROWS;++i){
                        for(int j=0;j<COLS;++j){
                            if(M.tile[i,j].IsShrine() && M.tile[i,j].type != TileType.SPELL_EXCHANGE_SHRINE){
                                shrine_remaining = true;
                                break;
                            }
                        }
                        if(shrine_remaining){
                            MouseUI.descend_hack = true;
                            break;
                        }
                    }
                    if(shrine_remaining){
                        Help.TutorialTip(TutorialTopic.DistributionOfShrines);
                        if(!B.YesOrNoPrompt("You feel an ancient power calling you back. Leave anyway?")){
                            Q0();
                            return;
                        }
                    }
                    B.Add("You walk down the stairs. ");
                    B.PrintAll();
                    if(M.current_level < 20){
                        M.GenerateLevel();
                    }
                    else{
                        M.GenerateFinalLevel();
                        B.Add("Strange chants and sulfurous smoke fill the air here. ");
                    }
                    if(magic_trinkets.Contains(MagicTrinketType.LENS_OF_SCRYING)){
                        Item i = inv.Where(x=>!Item.identified[x.type]).RandomOrDefault();
                        if(i != null){
                            string itemname = i.NameWithoutQuantity();
                            Item.identified[i.type] = true;
                            string IDedname = i.NameWithoutQuantity();
                            string isare = " is a ";
                            if(i.quantity > 1){
                                isare = " are ";
                            }
                            B.Add("Your " + MagicTrinket.Name(MagicTrinketType.LENS_OF_SCRYING) + " reveals that your " + itemname + isare + IDedname + ". ");
                        }
                    }
                    if(M.current_level == 3){
                        Help.TutorialTip(TutorialTopic.SwitchingEquipment);
                    }
                    Q0();
                }
                else{
                    Tile stairs = null;
                    foreach(Tile t in M.AllTiles()){
                        if(t.type == TileType.STAIRS && t.seen){
                            stairs = t;
                            break;
                        }
                    }
                    if(stairs != null){
                        List<pos> stairpath = GetPath(stairs,-1,true);
                        foreach(pos p in stairpath){
                            if(p.row != row || p.col != col){
                                colorchar cch = Screen.MapChar(p.row,p.col);
                                if(p.row == stairs.row && p.col == stairs.col){
                                    cch.bgcolor = Color.Green;
                                    if(Global.LINUX && !Screen.GLMode){ //no bright bg in terminals
                                        cch.bgcolor = Color.DarkGreen;
                                    }
                                    if(cch.color == cch.bgcolor){
                                        cch.color = Color.Black;
                                    }
                                    Screen.WriteMapChar(p.row,p.col,cch);
                                }
                                else{
                                    cch.bgcolor = Color.DarkGreen;
                                    if(cch.color == cch.bgcolor){
                                        cch.color = Color.Black;
                                    }
                                    Screen.WriteMapChar(p.row,p.col,cch);
                                }
                            }
                        }
                        MouseUI.PushButtonMap(MouseMode.YesNoPrompt);
                        MouseUI.CreateButton(ConsoleKey.Y,false,2,Global.MAP_OFFSET_COLS + 22,1,2);
                        MouseUI.CreateButton(ConsoleKey.N,false,2,Global.MAP_OFFSET_COLS + 25,1,2);
                        B.DisplayNow("Travel to the stairs? (y/n): ");
                        Screen.CursorVisible = true;
                        bool done = false;
                        while(!done){
                            command = Input.ReadKey();
                            switch(command.KeyChar){
                            case 'y':
                            case 'Y':
                            case '>':
                            case (char)13:
                                done = true;
                                MouseUI.PopButtonMap();
                                break;
                            default:
                                Q0();
                                MouseUI.PopButtonMap();
                                return;
                            }
                        }
                        FindPath(stairs,-1,true);
                        if(path.Count > 0){
                            PlayerWalk(DirectionOf(path[0]));
                            if(path.Count > 0){
                                if(DistanceFrom(path[0]) == 0){
                                    path.RemoveAt(0);
                                }
                            }
                        }
                        else{
                            B.Add("There's no path to the stairs. ");
                            Q0();
                        }
                    }
                    else{
                        B.Add("You don't see any stairs here. ");
                        Q0();
                    }
                }
                break;
            case 'x':
            {
                if(FrozenThisTurn()){
                    break;
                }
                if((tile().inv != null && !tile().inv.ignored) || (tile().Is(TileType.CHEST) && (tile().inv == null || !tile().inv.ignored))){
                    goto case 'g';
                }
                if(!FindAutoexplorePath()){
                    B.Add("You don't see a path for further exploration. ");
                    Q0();
                }
                else{
                    attrs[AttrType.AUTOEXPLORE]++;
                    PlayerWalk(DirectionOf(path[0]));
                    if(path.Count > 0){
                        if(DistanceFrom(path[0]) == 0){
                            path.RemoveAt(0);
                        }
                    }
                }
                break;
            }
            case 'X':
                if(FrozenThisTurn()){
                    break;
                }
                Screen.CursorVisible = false;
                Dictionary<Actor,colorchar> old_ch = new Dictionary<Actor,colorchar>();
                List<Actor> drawn = new List<Actor>();
                foreach(Actor a in M.AllActors()){
                    if(CanSee(a)){
                        old_ch.Add(a,M.last_seen[a.row,a.col]);
                        M.last_seen[a.row,a.col] = new colorchar(a.symbol,a.color);
                        drawn.Add(a);
                    }
                }
                Screen.MapDrawWithStrings(M.last_seen,0,0,ROWS,COLS);
                ChoosePathingDestination();
                foreach(Actor a in drawn){
                    M.last_seen[a.row,a.col] = old_ch[a];
                }
                M.Redraw();
                if(path.Count > 0){
                    PlayerWalk(DirectionOf(path[0]));
                    if(path.Count > 0){
                        if(DistanceFrom(path[0]) == 0){
                            path.RemoveAt(0);
                        }
                    }
                }
                else{
                    Q0();
                }
                break;
            case 'g':
            {
                if(FrozenThisTurn()){
                    break;
                }
                if(tile().inv == null){
                    if(tile().type == TileType.CHEST){
                        if(StunnedThisTurn()){
                            break;
                        }
                        tile().OpenChest();
                        Q1();
                    }
                    else{
                        if(tile().IsShrine()){
                            if(StunnedThisTurn()){
                                break;
                            }
                            switch(tile().type){
                            case TileType.COMBAT_SHRINE:
                                Help.TutorialTip(TutorialTopic.Combat);
                                IncreaseSkill(SkillType.COMBAT);
                                break;
                            case TileType.DEFENSE_SHRINE:
                                Help.TutorialTip(TutorialTopic.Defense);
                                IncreaseSkill(SkillType.DEFENSE);
                                break;
                            case TileType.MAGIC_SHRINE:
                                Help.TutorialTip(TutorialTopic.Magic);
                                IncreaseSkill(SkillType.MAGIC);
                                break;
                            case TileType.SPIRIT_SHRINE:
                                Help.TutorialTip(TutorialTopic.Spirit);
                                IncreaseSkill(SkillType.SPIRIT);
                                break;
                            case TileType.STEALTH_SHRINE:
                                Help.TutorialTip(TutorialTopic.Stealth);
                                IncreaseSkill(SkillType.STEALTH);
                                break;
                            case TileType.SPELL_EXCHANGE_SHRINE: //currently disabled
                            {
                                List<colorstring> ls = new List<colorstring>();
                                List<SpellType> sp = new List<SpellType>();
                                bool bonus_marked = false;
                                foreach(SpellType spell in spells_in_order){
                                    if(HasSpell(spell)){
                                        colorstring cs = new colorstring(Spell.Name(spell).PadRight(18) + Spell.Tier(spell).ToString().PadLeft(3),Color.Gray);
                                        //cs.strings.Add(new cstr(FailRate(spell).ToString().PadLeft(9) + "%",FailColor(spell)));
                                        cs.strings.Add(new cstr("".PadRight(5),Color.Gray));
                                        if(HasFeat(FeatType.MASTERS_EDGE) && Spell.IsDamaging(spell) && !bonus_marked){
                                            bonus_marked = true;
                                            cs = cs + Spell.DescriptionWithIncreasedDamage(spell);
                                        }
                                        else{
                                            cs = cs + Spell.Description(spell);
                                        }
                                        ls.Add(cs);
                                        sp.Add(spell);
                                    }
                                }
                                if(sp.Count > 0){
                                    colorstring topborder = new colorstring("----------------------Tier-----------------Description------------",Color.Gray);
                                    int basefail = exhaustion;
                                    colorstring bottomborder = new colorstring("----------------" + "Exhaustion: ".PadLeft(12+(3-basefail.ToString().Length),'-'),Color.Gray,(basefail.ToString() + "%"),FailColor(basefail),"----------[",Color.Gray,"?",Color.Cyan,"] for help".PadRight(22,'-'),Color.Gray);
                                    int i = Select("Trade one of your spells for another? ",topborder,bottomborder,ls,false,false,true,true,HelpTopic.Spells);
                                    if(i != -1){
                                        List<SpellType> unknown = new List<SpellType>();
                                        foreach(SpellType spell in Enum.GetValues(typeof(SpellType))){
                                            if(!HasSpell(spell) && spell != SpellType.NO_SPELL && spell != SpellType.NUM_SPELLS){
                                                unknown.Add(spell);
                                            }
                                        }
                                        SpellType forgotten = sp[i];
                                        spells_in_order.Remove(forgotten);
                                        spells[forgotten] = false;
                                        SpellType learned = unknown.Random();
                                        spells[learned] = true;
                                        spells_in_order.Add(learned);
                                        B.Add("You forget " + Spell.Name(forgotten) + ". You learn " + Spell.Name(learned) + ". ");
                                        tile().TransformTo(TileType.RUINED_SHRINE);
                                        tile().SetName("ruined shrine of magic");
                                    }
                                    else{
                                        Q0();
                                    }
                                }
                                break;
                            }
                            default:
                                break;
                            }
                            if(tile().type != TileType.SPELL_EXCHANGE_SHRINE){
                                Q1();
                            }
                            //if(tile().type == TileType.MAGIC_SHRINE && spells_in_order.Count > 1){
                            //	tile().TransformTo(TileType.SPELL_EXCHANGE_SHRINE);
                            //}
                            //else{
                                if(tile().type != TileType.SPELL_EXCHANGE_SHRINE && !tile().name.Contains("ruined")){
                                    string oldname = tile().name;
                                    tile().TransformTo(TileType.RUINED_SHRINE);
                                    tile().SetName("ruined " + oldname);
                                }
                            //}
                            foreach(Tile t in TilesWithinDistance(2)){
                                if(t.IsShrine()){
                                    string oldname = t.name;
                                    t.TransformTo(TileType.RUINED_SHRINE);
                                    t.SetName("ruined " + oldname);
                                }
                            }
                        }
                        else{
                            if(tile().type == TileType.BLAST_FUNGUS){
                                if(InventoryCount() < Global.MAX_INVENTORY_SIZE){
                                    if(StunnedThisTurn()){
                                        break;
                                    }
                                    B.Add("You pull the blast fungus from the floor. ");
                                    B.Add("Its fuse ignites! ");
                                    tile().Toggle(null);
                                    Item i = Item.Create(ConsumableType.BLAST_FUNGUS,this);
                                    if(i != null){
                                        i.other_data = 3;
                                        i.revealed_by_light = true;
                                        Q.Add(new Event(i,100,EventType.BLAST_FUNGUS));
                                        Screen.AnimateMapCell(row,col,new colorchar('3',Color.Red),100);
                                    }
                                    Q1();
                                }
                                else{
                                    B.Add("Your pack is too full to pick up the blast fungus. ");
                                    Q0();
                                }
                            }
                            else{
                                if(tile().type == TileType.RUINED_SHRINE){
                                    B.Add("This " + tile().name + " has no power left. ");
                                    Q0();
                                }
                                else{
                                    B.Add("There's nothing here to pick up. ");
                                    Q0();
                                }
                            }
                        }
                    }
                }
                else{
                    if(InventoryCount() < Global.MAX_INVENTORY_SIZE){
                        if(StunnedThisTurn()){
                            break;
                        }
                        if(InventoryCount() + tile().inv.quantity <= Global.MAX_INVENTORY_SIZE){
                            Item i = tile().inv;
                            tile().inv = null;
                            if(i.light_radius > 0){
                                i.UpdateRadius(i.light_radius,0);
                            }
                            i.row = -1;
                            i.col = -1;
                            i.revealed_by_light = true;
                            B.Add("You pick up " + i.TheName() + ". ");
                            GetItem(i);
                            Q1();
                        }
                        else{
                            int space_left = Global.MAX_INVENTORY_SIZE - InventoryCount();
                            Item i = tile().inv;
                            Item newitem = new Item(i,row,col);
                            newitem.quantity = space_left;
                            i.quantity -= space_left;
                            newitem.revealed_by_light = true;
                            B.Add("You pick up " + newitem.TheName() + ", but have no room for the other " + i.quantity.ToString() + ". ");
                            i.ignored = true;
                            GetItem(newitem);
                            Q1();
                        }
                    }
                    else{
                        tile().inv.revealed_by_light = true;
                        B.Add("Your pack is too full to pick up " + tile().inv.TheName() + ". ");
                        tile().inv.ignored = true;
                        Q0();
                    }
                }
                break;
            }
            case 'i':
            case 'a': //these are handled in the same case label so I can drop down from the selection to the action
            case 'f':
            case 'd':
            {
                if(inv.Count == 0){
                    B.Add("You have nothing in your pack. ");
                    Q0();
                    break;
                }
                if(ch == 'a' || ch == 'f' || ch == 'd'){
                    if(FrozenThisTurn()){
                        break;
                    }
                }
                string msg = "In your pack: ";
                bool no_redraw = (ch == 'i');
                switch(ch){
                case 'a':
                    msg = "Apply which item? ";
                    break;
                case 'f':
                    msg = "Fling which item? ";
                    break;
                case 'd':
                    msg = "Drop which item? ";
                    break;
                }
                ItemSelection sel = new ItemSelection();
                sel.value = -2;
                while(sel.value != -1){
                    sel = SelectItem(msg,no_redraw);
                    if(ch == 'i'){
                        sel.description_requested = true;
                    }
                    if(sel.value != -1 && sel.description_requested){
                        MouseUI.PushButtonMap(MouseMode.Inventory);
                        MouseUI.AutomaticButtonsFromStrings = true;
                        Screen.CursorVisible = false;
                        colorchar[,] screen = Screen.GetCurrentScreen();
                        for(int letter=0;letter<inv.Count;++letter){
                            Screen.WriteMapChar(letter+1,1,(char)(letter+'a'),Color.DarkCyan);
                        }
                        List<colorstring> box = UI.ItemDescriptionBox(inv[sel.value],false,false,31);
                        int i = (Global.SCREEN_H - box.Count) / 2;
                        int j = (Global.SCREEN_W - box[0].Length()) / 2;
                        foreach(colorstring cs in box){
                            Screen.WriteString(i,j,cs);
                            ++i;
                        }
                        switch(Input.ReadKey().GetCommandChar()){
                        case 'a':
                            ch = 'a';
                            sel.description_requested = false;
                            break;
                        case 'f':
                            ch = 'f';
                            sel.description_requested = false;
                            break;
                        case 'd':
                            ch = 'd';
                            sel.description_requested = false;
                            break;
                        }
                        MouseUI.PopButtonMap();
                        MouseUI.AutomaticButtonsFromStrings = false;
                        if(sel.description_requested){
                            Screen.WriteArray(0,0,screen);
                        }
                        else{
                            M.Redraw(); //this will break if the box goes off the map, todo
                            break;
                        }
                        Screen.CursorVisible = true;
                    }
                    else{
                        break;
                    }
                }
                if(sel.value == -1){
                    Q0();
                    break;
                }
                int num = sel.value;
                if(ch == 'f' && (inv[num].NameOfItemType() == "orb" || inv[num].type == ConsumableType.BLAST_FUNGUS)){
                    ch = 'a';
                }
                switch(ch){
                case 'a':
                {
                    if(FrozenThisTurn()){
                        break;
                    }
                    if(HasAttr(AttrType.NONLIVING) && inv[num].NameOfItemType() == "potion"){
                        B.Add("Potions have no effect on you in stone form. ");
                        Q0();
                    }
                    else{
                        if(HasAttr(AttrType.NONLIVING) && inv[num].type == ConsumableType.BANDAGES){
                            B.Add("Bandages have no effect on you in stone form. ");
                            Q0();
                        }
                        else{
                            if(HasAttr(AttrType.BLIND) && inv[num].NameOfItemType() == "scroll"){
                                B.Add("You can't read scrolls while blind. ");
                                Q0();
                            }
                            else{
                                if(inv[num].NameOfItemType() == "wand" && inv[num].charges == 0 && inv[num].other_data == -1){
                                    B.Add("That wand has no charges left. ");
                                    Q0();
                                }
                                else{
                                    bool silenced = HasAttr(AttrType.SILENCED,AttrType.SILENCE_AURA);
                                    string silence_message = "You can't read scrolls while silenced. ";
                                    if(HasAttr(AttrType.SILENCE_AURA)){
                                        silence_message = "Your silence aura makes reading scrolls impossible. ";
                                    }
                                    else{
                                        List<Actor> auras = ActorsWithinDistance(2).Where(x=>x.HasAttr(AttrType.SILENCE_AURA) && x.HasLOE(this));
                                        if(auras.Count > 0){
                                            silenced = true;
                                            Actor a = auras.Where(x=>CanSee(x)).RandomOrDefault();
                                            if(a != null){
                                                silence_message = a.the_name + "'s silence aura makes reading scrolls impossible. ";
                                            }
                                            else{
                                                silence_message = "An aura of silence makes reading scrolls impossible. ";
                                            }
                                        }
                                    }
                                    if(silenced && inv[num].NameOfItemType() == "scroll"){
                                        B.Add(silence_message);
                                        Q0();
                                    }
                                    else{
                                        Actor thief = ActorsAtDistance(1).Where(x=>x.type == ActorType.SNEAK_THIEF).RandomOrDefault();
                                        if(thief != null){
                                            B.Add(thief.YouVisible("snatch",true) + " your " + inv[num].SingularName(false) + "! ");
                                            B.PrintAll();
                                            Item stolen = inv[num];
                                            if(inv[num].quantity > 1){
                                                stolen = new Item(inv[num],inv[num].row,inv[num].col);
                                                stolen.revealed_by_light = inv[num].revealed_by_light;
                                                inv[num].quantity--;
                                            }
                                            else{
                                                inv.Remove(stolen);
                                            }
                                            thief.GetItem(stolen);
                                            Q1();
                                        }
                                        else{
                                            if(StunnedThisTurn()){
                                                break;
                                            }
                                            if(HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED) && R.OneIn(5)){
                                                Item i = inv[num];
                                                B.Add("The " + i.SingularName() + " slips out of your hands! ");
                                                i.revealed_by_light = true;
                                                if(i.quantity <= 1){
                                                    if(tile().type == TileType.POOL_OF_RESTORATION){
                                                        B.Add("You drop " + i.TheName() + " into the pool. ");
                                                        inv.Remove(i);
                                                        if(curhp < maxhp || curmp < maxmp || exhaustion > 0){
                                                            B.Add("The pool's glow restores you. ");
                                                            curhp = maxhp;
                                                            curmp = maxmp;
                                                            RemoveExhaustion();
                                                        }
                                                        else{
                                                            B.Add("The pool of restoration glows briefly, then dries up. ");
                                                        }
                                                        tile().TurnToFloor();
                                                    }
                                                    else{
                                                        if(tile().GetItem(i)){
                                                            B.Add("You drop " + i.TheName() + ". ");
                                                            inv.Remove(i);
                                                        }
                                                        else{
                                                            //this only happens if every tile is full - i.e. never
                                                        }
                                                    }
                                                }
                                                else{
                                                    if(tile().type == TileType.POOL_OF_RESTORATION){
                                                        Item newitem = new Item(i,row,col);
                                                        newitem.quantity = 1;
                                                        i.quantity--;
                                                        B.Add("You drop " + newitem.TheName() + " into the pool. ");
                                                        if(curhp < maxhp || curmp < maxmp){
                                                            B.Add("The pool's glow restores you. ");
                                                            curhp = maxhp;
                                                            curmp = maxmp;
                                                        }
                                                        else{
                                                            B.Add("The pool of restoration glows briefly, then dries up. ");
                                                        }
                                                        tile().TurnToFloor();
                                                    }
                                                    else{
                                                        Item newitem = new Item(i,row,col);
                                                        newitem.quantity = 1;
                                                        newitem.revealed_by_light = true;
                                                        if(tile().GetItem(newitem)){
                                                            i.quantity -= 1;
                                                            B.Add("You drop " + newitem.TheName() + ". ");
                                                        }
                                                        else{
                                                            //should never happen
                                                        }
                                                    }
                                                }
                                                Q1();
                                                break;
                                            }
                                            if(inv[num].Use(this)){
                                                Q1();
                                            }
                                            else{
                                                Q0();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
                }
                case 'f':
                {
                    if(FrozenThisTurn()){
                        break;
                    }
                    if(StunnedThisTurn()){
                        break;
                    }
                    List<Tile> line = GetTargetTile(12,0,false,false);
                    if(line != null){
                        Item i = null;
                        if(inv[num].quantity == 1){
                            i = inv[num];
                        }
                        else{
                            i = new Item(inv[num],-1,-1);
                            inv[num].quantity--;
                        }
                        i.revealed_by_light = true;
                        i.ignored = true;
                        Tile t = line.LastBeforeSolidTile();
                        Actor first = FirstActorInLine(line);
                        B.Add(You("fling") + " " + i.TheName() + ". ");
                        if(first != null && first != this){
                            t = first.tile();
                            B.Add("It hits " + first.the_name + ". ",first);
                        }
                        line = line.ToFirstSolidTileOrActor();
                        if(line.Count > 0){
                            line.RemoveAt(line.Count - 1);
                        }
                        {
                            Tile first_unseen = null;
                            foreach(Tile tile2 in line){
                                if(!tile2.seen){
                                    first_unseen = tile2;
                                    break;
                                }
                            }
                            if(first_unseen != null){
                                line = line.To(first_unseen);
                                if(line.Count > 0){
                                    line.RemoveAt(line.Count - 1);
                                }
                            }
                        }
                        if(line.Count > 0){
                            AnimateProjectile(line,i.symbol,i.color);
                        }
                        if(i.IsBreakable()){
                            B.Add("It breaks! ",t);
                            i.CheckForMimic();
                        }
                        else{
                            bool broken = false;
                            if(i.type == ConsumableType.FLINT_AND_STEEL){
                                if(R.OneIn(3)){
                                    i.other_data--;
                                    if(i.other_data == 2){
                                        B.Add("Your flint & steel shows signs of wear. ",t);
                                    }
                                    if(i.other_data == 1){
                                        B.Add("Your flint & steel is almost depleted. ",t);
                                    }
                                    if(i.other_data == 0){
                                        broken = true;
                                        B.Add("Your flint & steel is used up. ",t);
                                    }
                                }
                            }
                            if(!broken){
                                t.GetItem(i);
                            }
                        }
                        inv.Remove(i);
                        t.MakeNoise(2);
                        if(first != null && first != this){
                            first.player_visibility_duration = -1;
                            first.attrs[AttrType.PLAYER_NOTICED]++;
                        }
                        else{
                            if(t.IsTrap()){
                                t.TriggerTrap();
                            }
                        }
                        Q1();
                    }
                    else{
                        Q0();
                    }
                    break;
                }
                case 'd':
                {
                    if(FrozenThisTurn()){
                        break;
                    }
                    if(StunnedThisTurn()){
                        break;
                    }
                    Item i = inv[num];
                    i.revealed_by_light = true;
                    if(i.quantity <= 1){
                        if(tile().type == TileType.POOL_OF_RESTORATION){
                            B.Add("You drop " + i.TheName() + " into the pool. ");
                            inv.Remove(i);
                            if(curhp < maxhp || curmp < maxmp){
                                B.Add("The pool's glow restores you. ");
                                curhp = maxhp;
                                curmp = maxmp;
                            }
                            else{
                                B.Add("The pool of restoration glows briefly, then dries up. ");
                            }
                            tile().TurnToFloor();
                            Q1();
                        }
                        else{
                            if(tile().GetItem(i)){
                                B.Add("You drop " + i.TheName() + ". ");
                                inv.Remove(i);
                                i.ignored = true;
                                Q1();
                            }
                            else{
                                B.Add("There is no room. ");
                                Q0();
                            }
                        }
                    }
                    else{
                        if(tile().type == TileType.POOL_OF_RESTORATION){
                            Item newitem = new Item(i,row,col);
                            newitem.quantity = 1;
                            i.quantity--;
                            B.Add("You drop " + newitem.TheName() + " into the pool. ");
                            if(curhp < maxhp || curmp < maxmp){
                                B.Add("The pool's glow restores you. ");
                                curhp = maxhp;
                                curmp = maxmp;
                            }
                            else{
                                B.Add("The pool of restoration glows briefly, then dries up. ");
                            }
                            tile().TurnToFloor();
                            Q1();
                        }
                        else{
                            //B.DisplayNow("Drop how many? (1-" + i.quantity + "): ");
                            //int count = Global.EnterInt();
                            int count = 1;
                            if(count == 0){
                                Q0();
                            }
                            else{
                                if(count >= i.quantity || count == -1){
                                    if(tile().GetItem(i)){
                                        B.Add("You drop " + i.TheName() + ". ");
                                        inv.Remove(i);
                                        i.ignored = true;
                                        Q1();
                                    }
                                    else{
                                        B.Add("There is no room. ");
                                        Q0();
                                    }
                                }
                                else{
                                    Item newitem = new Item(i,row,col);
                                    newitem.quantity = count;
                                    newitem.revealed_by_light = true;
                                    if(tile().GetItem(newitem)){
                                        i.quantity -= count;
                                        B.Add("You drop " + newitem.TheName() + ". ");
                                        newitem.ignored = true;
                                        Q1();
                                    }
                                    else{
                                        B.Add("There is no room. ");
                                        Q0();
                                    }
                                }
                            }
                        }
                    }
                    break;
                }
                }
                break;
            }
            case 'e':
            {
                int[] changes = UI.DisplayEquipment();
                M.Redraw();
                Weapon new_weapon = WeaponOfType((WeaponType)changes[0]);
                Armor new_armor = ArmorOfType((ArmorType)changes[1]);
                Weapon old_weapon = EquippedWeapon;
                Armor old_armor = EquippedArmor;
                bool weapon_changed = (new_weapon != old_weapon);
                bool armor_changed = (new_armor != old_armor);
                if(weapon_changed || armor_changed){
                    if(FrozenThisTurn()){
                        break;
                    }
                }
                bool cursed_weapon = false;
                bool cursed_armor = false;
                if(weapon_changed && EquippedWeapon.status[EquipmentStatus.STUCK]){
                    cursed_weapon = true;
                    weapon_changed = false;
                    armor_changed = false;
                }
                if(armor_changed && EquippedArmor.status[EquipmentStatus.STUCK]){
                    cursed_armor = true;
                    armor_changed = false;
                    weapon_changed = false;
                }
                if(!weapon_changed && !armor_changed){
                    if(cursed_weapon){
                        B.Add("Your " + EquippedWeapon + " is stuck to your hand and can't be put away. ");
                    }
                    if(cursed_armor){
                        B.Add("Your " + EquippedArmor + " is stuck to your body and can't be removed. ");
                    }
                    Q0();
                }
                else{
                    if(StunnedThisTurn()){
                        break;
                    }
                    Help.displayed[TutorialTopic.SwitchingEquipment] = true;
                    if(weapon_changed){
                        EquippedWeapon = new_weapon;
                        if(HasFeat(FeatType.QUICK_DRAW) && !armor_changed && old_weapon != Bow){
                            B.Add("You quickly ready your " + EquippedWeapon + ". ");
                        }
                        else{
                            if(old_weapon == Bow){
                                B.Add("You put away your bow and ready your " + EquippedWeapon + ". ");
                            }
                            else{
                                B.Add("You ready your " + EquippedWeapon + ". ");
                            }
                        }
                        //UpdateOnEquip(old_weapon,EquippedWeapon);
                    }
                    if(armor_changed){
                        EquippedArmor = new_armor;
                        //UpdateOnEquip(old_armor,EquippedArmor);
                        if(TotalProtectionFromArmor() == 0){
                            if(EquippedArmor.status[EquipmentStatus.DAMAGED]){
                                B.Add("You wear your damaged " + EquippedArmor + ". ");
                                B.Add("(It provides no protection until repaired.) ");
                            }
                            else{
                                B.Add("You wear your " + EquippedArmor + ". ");
                                B.Add("You can't wear it effectively in your exhausted state. ");
                            }
                        }
                        else{
                            B.Add("You wear your " + EquippedArmor + ". ");
                        }
                        attrs[AttrType.SWITCHING_ARMOR] = 1;
                    }
                    if(cursed_weapon){
                        B.Add("Your " + EquippedWeapon + " is stuck to your hand and can't be put away. ");
                    }
                    if(cursed_armor){
                        B.Add("Your " + EquippedArmor + " is stuck to your body and can't be removed. ");
                    }
                    if(HasFeat(FeatType.QUICK_DRAW) && !armor_changed && old_weapon != Bow){
                        Q0();
                    }
                    else{
                        Q1();
                    }
                }
                break;
            }
            case '!': //note that these are the top-row numbers, NOT the actual shifted versions
            case '@': //<---this is the '2' above the 'w'    (not the '@', and not the numpad 2)
            case '#':
            case '$':
            case '%':
            {
                if(FrozenThisTurn()){
                    break;
                }
                if(EquippedWeapon.status[EquipmentStatus.STUCK]){
                    B.Add("Your " + EquippedWeapon + " is stuck to your hand and can't be put away. ");
                    Q0();
                }
                else{
                    Weapon new_weapon = null;
                    switch(ch){
                    case '!':
                        new_weapon = Sword;
                        break;
                    case '@':
                        new_weapon = Mace;
                        break;
                    case '#':
                        new_weapon = Dagger;
                        break;
                    case '$':
                        new_weapon = Staff;
                        break;
                    case '%':
                        new_weapon = Bow;
                        break;
                    }
                    Weapon old_weapon = EquippedWeapon;
                    if(new_weapon == old_weapon){
                        Q0();
                    }
                    else{
                        if(StunnedThisTurn()){
                            break;
                        }
                        Help.displayed[TutorialTopic.SwitchingEquipment] = true;
                        EquippedWeapon = new_weapon;
                        if(HasFeat(FeatType.QUICK_DRAW) && old_weapon != Bow){
                            B.Add("You quickly ready your " + EquippedWeapon + ". ");
                            Q0();
                        }
                        else{
                            if(old_weapon == Bow){
                                B.Add("You put away your bow and ready your " + EquippedWeapon + ". ");
                            }
                            else{
                                B.Add("You ready your " + EquippedWeapon + ". ");
                            }
                            Q1();
                        }
                        //UpdateOnEquip(old_weapon,EquippedWeapon);
                    }
                }
                break;
            }
            case '*': //these are toprow numbers, not shifted versions. see above.
            case '(':
            case ')':
            {
                if(FrozenThisTurn()){
                    break;
                }
                if(EquippedArmor.status[EquipmentStatus.STUCK]){
                    B.Add("Your " + EquippedArmor + " is stuck to your body and can't be removed. ");
                    Q0();
                }
                else{
                    Armor new_armor = null;
                    switch(ch){
                    case '*':
                        new_armor = Leather;
                        break;
                    case '(':
                        new_armor = Chainmail;
                        break;
                    case ')':
                        new_armor = Plate;
                        break;
                    }
                    Armor old_armor = EquippedArmor;
                    if(new_armor == old_armor){
                        Q0();
                    }
                    else{
                        if(StunnedThisTurn()){
                            break;
                        }
                        Help.displayed[TutorialTopic.SwitchingEquipment] = true;
                        EquippedArmor = new_armor;
                        if(TotalProtectionFromArmor() == 0){
                            if(EquippedArmor.status[EquipmentStatus.DAMAGED]){
                                B.Add("You wear your damaged " + EquippedArmor + ". ");
                                B.Add("(It provides no protection until repaired.) ");
                            }
                            else{
                                B.Add("You wear your " + EquippedArmor + ". ");
                                B.Add("You can't wear it effectively in your exhausted state. ");
                            }
                        }
                        else{
                            B.Add("You wear your " + EquippedArmor + ". ");
                        }
                        attrs[AttrType.SWITCHING_ARMOR] = 1;
                        Q1();
                        //UpdateOnEquip(old_weapon,EquippedWeapon);
                    }
                }
                break;
            }
            case 't':
                if(FrozenThisTurn()){
                    break;
                }
                if(StunnedThisTurn()){
                    break;
                }
                if(light_radius==0){
                    if(!M.wiz_dark){
                        B.Add("You bring out your torch. ");
                    }
                    else{
                        B.Add("You bring out your torch, but it gives off no light! ");
                    }
                    int old = LightRadius();
                    light_radius = 6;
                    if(old != LightRadius()){
                        UpdateRadius(old,LightRadius());
                    }
                    if(HasAttr(AttrType.DIM_LIGHT)){
                        CalculateDimming();
                    }
                }
                else{
                    if(!M.wiz_lite){
                        B.Add("You put away your torch. ");
                    }
                    else{
                        B.Add("You put away your torch. The air still shines brightly. ");
                    }
                    int old = LightRadius();
                    if(HasAttr(AttrType.SHINING)){
                        RefreshDuration(AttrType.SHINING,0);
                    }
                    light_radius = 0;
                    if(old != LightRadius()){
                        UpdateRadius(old,LightRadius());
                    }
                    if(HasAttr(AttrType.SHADOW_CLOAK) && !tile().IsLit()){
                        B.Add("You fade away in the darkness. ");
                    }
                }
                Q1();
                break;
            case (char)9:
            {
                GetTarget(true,-1,0,false,false,true,"");
                if(path.Count > 0){
                    if(FrozenThisTurn()){
                        break;
                    }
                    PlayerWalk(DirectionOf(path[0]));
                    if(path.Count > 0){
                        if(DistanceFrom(path[0]) == 0){
                            path.RemoveAt(0);
                        }
                    }
                }
                else{
                    Q0();
                }
                break;
            }
            case 'm':
            {
                MouseUI.PushButtonMap();
                Screen.CursorVisible = false;
                Tile stairs = M.AllTiles().Where(x=>x.type == TileType.STAIRS && x.seen).RandomOrDefault();
                colorchar cch = Screen.BlankChar();
                if(stairs != null){
                    cch = M.last_seen[stairs.row,stairs.col];
                    M.last_seen[stairs.row,stairs.col] = new colorchar('>',stairs.color);
                }
                Screen.MapDrawWithStrings(M.last_seen,0,0,ROWS,COLS);
                Screen.CursorVisible = true;
                UI.viewing_map_shrine_info = true;
                ChoosePathingDestination(false,false,"Map of dungeon level " + M.current_level + ": ");
                UI.viewing_map_shrine_info = false;
                if(stairs != null){
                    M.last_seen[stairs.row,stairs.col] = cch;
                }
                MouseUI.PopButtonMap();
                M.Redraw();
                if(path.Count > 0){
                    if(FrozenThisTurn()){
                        break;
                    }
                    PlayerWalk(DirectionOf(path[0]));
                    if(path.Count > 0){
                        if(DistanceFrom(path[0]) == 0){
                            path.RemoveAt(0);
                        }
                    }
                }
                else{
                    Q0();
                }
                break;
            }
            case 'p':
            {
                SharedEffect.ShowPreviousMessages(true);
                Q0();
                break;
            }
            case 'c':
            {
                int feat = UI.DisplayCharacterInfo();
                if(feat >= 0){
                    if(FrozenThisTurn()){ //todo: fix this, once there are things besides feats to use.
                        break;
                    }
                    foreach(FeatType f in feats_in_order){
                        if(Feat.IsActivated(f)){
                            if(feat == 0){
                                M.Redraw();
                                if(StunnedThisTurn()){
                                    break;
                                }
                                if(!UseFeat(f)){
                                    Q0();
                                }
                                break;
                            }
                            else{
                                --feat;
                            }
                        }
                    }
                }
                else{
                    Q0();
                }
                break;
            }
            case '\\':
            {
                SharedEffect.ShowKnownItems(Item.identified);
                Q0();
                break;
                /*MouseUI.PushButtonMap();
                List<colorstring> potions = new List<colorstring>();
                List<colorstring> scrolls = new List<colorstring>();
                List<colorstring> orbs = new List<colorstring>();
                foreach(ConsumableType ct in Enum.GetValues(typeof(ConsumableType))){
                    string type_name = "    " + ct.ToString()[0] + ct.ToString().Substring(1).ToLower();
                    type_name = type_name.Replace('_',' ');
                    Color ided_color = Color.Cyan;
                    if(Item.NameOfItemType(ct) == "potion"){
                        if(Item.identified[ct]){
                            potions.Add(new colorstring(type_name,ided_color));
                        }
                        else{
                            potions.Add(new colorstring(type_name,Color.DarkGray));
                        }
                    }
                    else{
                        if(Item.NameOfItemType(ct) == "scroll"){
                            if(Item.identified[ct]){
                                scrolls.Add(new colorstring(type_name,ided_color));
                            }
                            else{
                                scrolls.Add(new colorstring(type_name,Color.DarkGray));
                            }
                        }
                        else{
                            if(Item.NameOfItemType(ct) == "orb"){
                                if(Item.identified[ct]){
                                    orbs.Add(new colorstring(type_name,ided_color));
                                }
                                else{
                                    orbs.Add(new colorstring(type_name,Color.DarkGray));
                                }
                            }
                        }
                    }
                }
                Screen.WriteMapString(0,0,"".PadRight(COLS,'-'));
                for(int i=1;i<ROWS-1;++i){
                    Screen.WriteMapString(i,0,"".PadToMapSize());
                }
                Screen.WriteMapString(ROWS-1,0,"".PadRight(COLS,'-'));
                Color label_color = Color.Yellow;
                Screen.WriteMapString(1,0,"  - Potions -",label_color);
                Screen.WriteMapString(1,33,"  - Scrolls -",label_color);
                int line = 2;
                foreach(colorstring s in potions){
                    Screen.WriteMapString(line,0,s);
                    ++line;
                }
                line = 2;
                foreach(colorstring s in scrolls){
                    Screen.WriteMapString(line,33,s);
                    ++line;
                }
                Screen.WriteMapString(12,0,"  - Orbs -",label_color);
                line = 13;
                foreach(colorstring s in orbs){
                    Screen.WriteMapString(line,0,s);
                    ++line;
                }
                B.DisplayNow("Discovered item types: ");
                Screen.CursorVisible = true;
                Input.ReadKey();
                MouseUI.PopButtonMap();
                Q0();
                break;*/
            }
            case 'O':
            case '=':
            {
                MouseUI.PushButtonMap();
                for(bool done=false;!done;){
                    List<string> ls = new List<string>();
                    ls.Add("Disable wall sliding".PadRight(58) + (Global.Option(OptionType.NO_WALL_SLIDING)? "yes ":"no ").PadLeft(4));
                    ls.Add("Automatically pick up items (if safe)".PadRight(58) + (Global.Option(OptionType.AUTOPICKUP)? "yes ":"no ").PadLeft(4));
                    ls.Add("Hide the path shown by mouse movement".PadRight(58) + (!MouseUI.VisiblePath? "yes ":"no ").PadLeft(4));
                    ls.Add("Use top-row numbers for movement".PadRight(58) + (Global.Option(OptionType.TOP_ROW_MOVEMENT)? "yes ":"no ").PadLeft(4));
                    ls.Add("Ask for confirmation before resting".PadRight(58) + (Global.Option(OptionType.CONFIRM_BEFORE_RESTING)? "yes ":"no ").PadLeft(4));
                    ls.Add("Show out-of-sight areas in dark gray instead".PadRight(58) + (Global.Option(OptionType.DARK_GRAY_UNSEEN)? "yes ":"no ").PadLeft(4));
                    ls.Add("Never show tutorial tips".PadRight(58) + (Global.Option(OptionType.NEVER_DISPLAY_TIPS)? "yes ":"no ").PadLeft(4));
                    ls.Add("Reset tutorial tips before each game".PadRight(58) + (Global.Option(OptionType.ALWAYS_RESET_TIPS)? "yes ":"no ").PadLeft(4));
                    if(Global.LINUX && !Screen.GLMode){
                        ls.Add("Attempt to fix display glitches on certain terminals".PadRight(COLS));
                    }
                    /*if(Screen.GLMode){
                        ls.Add("Disable graphics".PadRight(58) + (Global.Option(OptionType.DISABLE_GRAPHICS)? "yes ":"no ").PadLeft(4));
                    }*/
                    Select("Options: ",ls,true,false,false);
                    Screen.CursorVisible = true;
                    ch = Input.ReadKey().GetCommandChar();
                    switch(ch){
                    case 'a':
                        Global.Options[OptionType.NO_WALL_SLIDING] = !Global.Option(OptionType.NO_WALL_SLIDING);
                        break;
                    case 'b':
                        Global.Options[OptionType.AUTOPICKUP] = !Global.Option(OptionType.AUTOPICKUP);
                        break;
                    case 'c':
                        MouseUI.VisiblePath = !MouseUI.VisiblePath;
                        break;
                    case 'd':
                        Global.Options[OptionType.TOP_ROW_MOVEMENT] = !Global.Option(OptionType.TOP_ROW_MOVEMENT);
                        break;
                    case 'e':
                        Global.Options[OptionType.CONFIRM_BEFORE_RESTING] = !Global.Option(OptionType.CONFIRM_BEFORE_RESTING);
                        break;
                    case 'f':
                        Global.Options[OptionType.DARK_GRAY_UNSEEN] = !Global.Option(OptionType.DARK_GRAY_UNSEEN);
                        M.Draw();
                        if(Screen.GLMode){
                            Screen.UpdateGLBuffer(0,0,Global.SCREEN_H-1,Global.SCREEN_W-1);
                        }
                        break;
                    case 'g':
                        Global.Options[OptionType.NEVER_DISPLAY_TIPS] = !Global.Option(OptionType.NEVER_DISPLAY_TIPS);
                        break;
                    case 'h':
                        Global.Options[OptionType.ALWAYS_RESET_TIPS] = !Global.Option(OptionType.ALWAYS_RESET_TIPS);
                        break;
                    case 'i':
                        if(Global.LINUX && !Screen.GLMode){
                            colorchar[,] screen = Screen.GetCurrentScreen();
                            colorchar cch = new colorchar('@',Color.White);
                            for(int i=0;i<Global.SCREEN_H;++i){
                                for(int j=i%2;j<Global.SCREEN_W;j+=2){
                                    if(i != Global.SCREEN_H-1 || j != Global.SCREEN_W-1){
                                        Screen.WriteChar(i,j,cch);
                                    }
                                }
                            }
                            cch = new colorchar('@',Color.Green);
                            for(int i=0;i<Global.SCREEN_H;++i){
                                Screen.WriteChar(i,0,cch);
                                for(int j=1 + i%2;j<Global.SCREEN_W;j+=2){
                                    if(i != Global.SCREEN_H-1 || j != Global.SCREEN_W-1){
                                        Screen.WriteChar(i,j,cch);
                                    }
                                }
                            }
                            cch = new colorchar('@',Color.Cyan);
                            for(int j=0;j<Global.SCREEN_W;++j){
                                for(int i=0;i<Global.SCREEN_H;++i){
                                    if(i != Global.SCREEN_H-1 || j != Global.SCREEN_W-1){
                                        Screen.WriteChar(i,j,cch);
                                    }
                                }
                            }
                            for(int i=0;i<Global.SCREEN_H;++i){
                                for(int j=0;j<Global.SCREEN_W;++j){
                                    if(i != Global.SCREEN_H-1 || j != Global.SCREEN_W-1){
                                        Screen.WriteChar(i,j,screen[i,j]);
                                    }
                                }
                            }
                        }
                        /*else{
                            if(Screen.GLMode){
                                Global.Options[OptionType.DISABLE_GRAPHICS] = !Global.Option(OptionType.DISABLE_GRAPHICS);
                                GLGame.graphics_surface.Disabled = Global.Option(OptionType.DISABLE_GRAPHICS);
                                Global.GRAPHICAL = !Global.Option(OptionType.DISABLE_GRAPHICS);
                                if(Global.Option(OptionType.DISABLE_GRAPHICS)){
                                    Screen.UpdateCursor(false);
                                }
                                else{
                                    Game.gl.ResizeToDefault();
                                }
                            }
                        }*/
                        break;
                    case (char)27:
                    case ' ':
                    case (char)13:
                        done = true;
                        break;
                    default:
                        break;
                    }
                }
                MouseUI.PopButtonMap();
                Q0();
                break;
            }
            case '?':
            case '/':
            {
                Help.DisplayHelp();
                Q0();
                break;
            }
            case '-':
            {
                MouseUI.PushButtonMap();
                UI.draw_bottom_commands = false;
                UI.darken_status_bar = true;
                Screen.CursorVisible = false;
                List<string> commandhelp = Help.HelpText(HelpTopic.Commands);
                commandhelp.RemoveRange(0,2);
                Screen.WriteMapString(0,0,"".PadRight(COLS,'-'));
                for(int i=0;i<23;++i){
                    Screen.WriteMapString(i+1,0,commandhelp[i].PadRight(COLS));
                }
                Screen.WriteMapString(ROWS+2,0,"".PadRight(COLS,'-'));
                B.DisplayNow("Commands: ");
                Screen.CursorVisible = true;
                Input.ReadKey();
                MouseUI.PopButtonMap();
                UI.draw_bottom_commands = true;
                UI.darken_status_bar = false;
                Q0();
                break;
            }
            case 'q':
            {
                List<string> ls = new List<string>();
                ls.Add("Save your progress and exit to main menu");
                ls.Add("Save your progress and quit game");
                ls.Add("Abandon character and exit to main menu");
                ls.Add("Abandon character and quit game");
                ls.Add("Quit game immediately - don't save anything");
                ls.Add("Continue playing");
                bool no_close = Game.NoClose;
                Game.NoClose = false;
                Screen.CursorVisible = true;
                switch(Select("Quit? ",ls)){
                case 0:
                    Global.GAME_OVER = true;
                    Global.SAVING = true;
                    break;
                case 1:
                    Global.GAME_OVER = true;
                    Global.QUITTING = true;
                    Global.SAVING = true;
                    break;
                case 2:
                    Global.GAME_OVER = true;
                    Global.KILLED_BY = "giving up";
                    break;
                case 3:
                    Global.GAME_OVER = true;
                    Global.QUITTING = true;
                    Global.KILLED_BY = "giving up";
                    break;
                case 4:
                    Global.Quit();
                    break;
                case 5:
                default:
                    break;
                }
                if(!Global.SAVING){
                    Q0();
                }
                Game.NoClose = no_close;
                break;
            }
            case 'v':
            {
                UI.viewing_commands_idx = U.Modulo(UI.viewing_commands_idx + 1,3);
                MouseUI.PopButtonMap();
                MouseUI.PushButtonMap(MouseMode.Map);
                MouseUI.CreateStatsButtons();
                Q0();
                break;
            }
            case '~': //debug mode
            {
                if(false){
                    List<string> l = new List<string>();
                    l.Add("blink");
                    l.Add("create chests");
                    l.Add("gain power");
                    l.Add("spawn monster");
                    l.Add("Forget the map");
                    l.Add("Heal to full");
                    l.Add("Become invulnerable");
                    l.Add("get items!");
                    l.Add("other");
                    l.Add("Use a rune of passage");
                    l.Add("See the entire level");
                    l.Add("Generate new level");
                    l.Add("Create ice or slime");
                    l.Add("Spawn shrines");
                    l.Add("create trap");
                    l.Add("create door");
                    l.Add("spawn lots of goblins and lose neck snap");
                    l.Add("brushfire test");
                    l.Add("detect monsters forever");
                    l.Add("get specific items");
                    switch(Select("Activate which cheat? ",l)){
                    case 0:
                    {
                        //new Item(ConsumableType.DETONATION,"orb of detonation",'*',Color.White).Use(this);
                        new Item(ConsumableType.BLINKING,"orb of detonation",'*',Color.White).Use(this);
                        Q1();
                        break;
                    }
                    case 1:
                    {
                        foreach(Tile t in TilesWithinDistance(3)){
                            t.TransformTo(TileType.CHEST);
                        }
                        Q0();
                        for(int i=0;i<20;++i){
                            Screen.WriteMapString(i,0,Item.GenerateScrollName().ToLower().PadRight(Global.COLS));
                        }
                        foreach(EquipmentStatus st in Enum.GetValues(typeof(EquipmentStatus))){
                            EquippedWeapon.status[st] = true;
                        }
                        Input.ReadKey();
                        /*while(true){
                            var k = Input.ReadKey();
                            B.Add(k.Key.ToString() + "! ");
                            B.Print(true);
                            if(k.Key == ConsoleKey.M){
                                break;
                            }
                        }*/
                        break;
                    }
                    case 2:
                    {
                        /*int[,] row_displacement = GetDiamondSquarePlasmaFractal(ROWS,COLS);
                        int[,] col_displacement = GetDiamondSquarePlasmaFractal(ROWS,COLS);
                        colorchar[,] scr = Screen.GetCurrentMap();
                        M.actor[p] = null;
                        scr[p.row,p.col] = M.VisibleColorChar(p.row,p.col);
                        M.actor[p] = this;
                        int total_rd = 0;
                        int total_cd = 0;
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                total_rd += row_displacement[i,j];
                                total_cd += col_displacement[i,j];
                            }
                        }
                        int avg_rd = total_rd / (ROWS*COLS);
                        int avg_cd = total_cd / (ROWS*COLS);
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                row_displacement[i,j] -= avg_rd;
                                col_displacement[i,j] -= avg_cd;
                            }
                        }
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                if(i == p.row && j == p.col){
                                    Screen.WriteMapChar(i,j,'@',Color.White);
                                }
                                else{
                                    row_displacement[i,j] /= 8;
                                    col_displacement[i,j] /= 8;
                                    if(M.tile.BoundsCheck(i+row_displacement[i,j],j+col_displacement[i,j])){
                                        Screen.WriteMapChar(i,j,scr[i+row_displacement[i,j],j+col_displacement[i,j]]);
                                    }
                                    else{
                                        Screen.WriteMapChar(i,j,Screen.BlankChar());
                                    }
                                }
                            }
                        }
                        Input.ReadKey();

                        var noise = U.GetNoise(17);
                        for(int i=0;i<17;++i){
                            for(int j=0;j<17;++j){
                                char ch2 = '~';
                                if(noise[i,j] > 0.5f){
                                    ch2 = '^';
                                }
                                else{
                                    if(noise[i,j] > 0.1f){
                                        ch2 = '#';
                                    }
                                    else{
                                        if(noise[i,j] > -0.1f){
                                            ch2 = '.';
                                        }
                                        else{
                                            if(noise[i,j] > -0.5f){
                                                ch2 = ',';
                                            }
                                        }
                                    }
                                }
                                Screen.WriteChar(i,j,ch2);
                            }
                            //Screen.WriteMapString(i,0,Global.GenerateCharacterName().PadToMapSize());
                            //Screen.WriteMapString(i,0,Item.RandomItem().ToString().PadToMapSize());
                        }

                        pos p1 = new pos(10,9);
                        pos p1b = new pos(11,9);
                        pos p2 = new pos(10,56);
                        pos p2b = new pos(11,56);
                        int dist = p1.ApproximateEuclideanDistanceFromX10(1,32) + p2.ApproximateEuclideanDistanceFromX10(1,32);
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                if(p1.ApproximateEuclideanDistanceFromX10(i,j) + p2.ApproximateEuclideanDistanceFromX10(i,j) <= dist
                                || p1b.ApproximateEuclideanDistanceFromX10(i,j) + p2b.ApproximateEuclideanDistanceFromX10(i,j) <= dist){
                                    Screen.WriteMapChar(i,j,'.');
                                }
                                else{
                                    Screen.WriteMapChar(i,j,'#');
                                }
                            }
                        }
                        //Input.ReadKey();
                        //M.InitLevel();
                        //Move(1,1);
                        //List<TileType> tilelist = new List<TileType>{TileType.WALL,TileType.WATER,TileType.VINE,TileType.WAX_WALL,TileType.FLOOR,TileType.BREACHED_WALL,TileType.DOOR_C,TileType.DOOR_O,TileType.CHEST,TileType.STATUE,TileType.FIREPIT,TileType.STALAGMITE,TileType.RUBBLE,TileType.COMBAT_SHRINE,TileType.DEFENSE_SHRINE,TileType.MAGIC_SHRINE,TileType.SPIRIT_SHRINE,TileType.STEALTH_SHRINE,TileType.SPELL_EXCHANGE_SHRINE,TileType.RUINED_SHRINE,TileType.FIRE_GEYSER,TileType.FOG_VENT,TileType.POISON_GAS_VENT,TileType.ICE,TileType.STONE_SLAB,TileType.CHASM,TileType.CRACKED_WALL,TileType.BRUSH,TileType.POPPY_FIELD,TileType.BLAST_FUNGUS,TileType.GLOWING_FUNGUS,TileType.TOMBSTONE,TileType.GRAVE_DIRT,TileType.BARREL,TileType.STANDING_TORCH,TileType.POISON_BULB,TileType.DEMONIC_IDOL,TileType.FIRE_TRAP,TileType.TELEPORT_TRAP,TileType.LIGHT_TRAP,TileType.SLIDING_WALL_TRAP,TileType.GRENADE_TRAP,TileType.SHOCK_TRAP,TileType.ALARM_TRAP,TileType.DARKNESS_TRAP,TileType.POISON_GAS_TRAP,TileType.BLINDING_TRAP,TileType.ICE_TRAP,TileType.PHANTOM_TRAP,TileType.SCALDING_OIL_TRAP,TileType.FLING_TRAP,TileType.STONE_RAIN_TRAP};
                        //List<pos> tileposlist = new List<pos>{new pos(0,0),new pos(4,0),new pos(8,0),new pos(12,0),new pos(0,8),new pos(0,9),new pos(0,10),new pos(2,10),new pos(4,10),new pos(8,10),new pos(12,10),new pos(13,10),new pos(14,10),new pos(0,11),new pos(1,11),new pos(2,11),new pos(3,11),new pos(4,11),new pos(5,11),new pos(6,11),new pos(8,11),new pos(9,11),new pos(10,11),new pos(11,11),new pos(12,11),new pos(14,11),new pos(15,11),new pos(0,12),new pos(4,12),new pos(5,12),new pos(10,12),new pos(12,12),new pos(13,12),new pos(14,12),new pos(15,12),new pos(0,13),new pos(1,13),new pos(0,14),new pos(1,14),new pos(2,14),new pos(3,14),new pos(4,14),new pos(5,14),new pos(6,14),new pos(7,14),new pos(8,14),new pos(9,14),new pos(10,14),new pos(11,14),new pos(12,14),new pos(13,14),new pos(14,14)};

                        int[] intarray = new int[16];
                        intarray[1] = 1;
                        intarray[2] = 1;
                        intarray[5] = -1;
                        intarray[8] = 1;
                        intarray[9] = -1;
                        intarray[10] = 3;

                        Bitmap bmp = new Bitmap("todo_remove.png");
                        Bitmap result;
                        using(var temp = new Bitmap("result_remove.png")){
                            result = new Bitmap(temp);
                        }

                        //Bitmap result = new Bitmap("result_remove.png");
                        //int idx=0;
                        foreach(ConsumableType ct in Enum.GetValues(typeof(ConsumableType))){
                            if(Item.NameOfItemType(ct) == "other"){
                                M.tile[2,2].inv = null;
                                Item.Create(ct,2,2);
                                colorchar cch = M.VisibleColorChar(2,2);
                                int ch_offset = (int)(cch.c) * 16;
                                int pos_col = 48 + (idx % 16);
                                int pos_row = 5 + idx / 16;
                                for(int i=0;i<16;++i){
                                    for(int j=0;j<16;++j){
                                        if(bmp.GetPixel(ch_offset + j,i).ToArgb() == System.Drawing.Color.Black.ToArgb()){
                                            System.Drawing.Color pixel_color = System.Drawing.Color.FromArgb(Colors.ConvertColor(Colors.ResolveColor(cch.color)).ToArgb());
                                            result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,pixel_color);
                                        }
                                        else{
                                            result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,System.Drawing.Color.Transparent);
                                        }
                                    }
                                }
                                ++idx;
                            }
                        }

                        attrs[AttrType.DETECTING_MONSTERS] = 1;
                        for(ActorType at = ActorType.GOBLIN;at <= ActorType.DEMON_LORD;at++){
                            if(at != ActorType.MARBLE_HORROR_STATUE && at != ActorType.FINAL_LEVEL_CULTIST){
                                M.actor[2,2] = null;
                                Actor.Create(at,2,2);
                                colorchar cch = M.VisibleColorChar(2,2);
                                int ch_offset = (int)(cch.c) * 16;
                                int pos_col = 32 + (idx % 16);
                                int pos_row = 4 + idx / 16;
                                for(int i=0;i<16;++i){
                                    for(int j=0;j<16;++j){
                                        if(bmp.GetPixel(ch_offset + j,i).ToArgb() == System.Drawing.Color.Black.ToArgb()){
                                            System.Drawing.Color pixel_color = System.Drawing.Color.FromArgb(Colors.ConvertColor(Colors.ResolveColor(cch.color)).ToArgb());
                                            result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,pixel_color);
                                            result.SetPixel(pos_col * 16 + j + 16,pos_row * 16 + i,pixel_color);
                                        }
                                        else{
                                            result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,System.Drawing.Color.Transparent);
                                            result.SetPixel(pos_col * 16 + j + 16,pos_row * 16 + i,System.Drawing.Color.Transparent);
                                        }
                                    }
                                }
                                idx += 2;
                            }
                        }
                        {
                            colorchar cch = M.VisibleColorChar(1,1);
                            int ch_offset = (int)(cch.c) * 16;
                            int pos_col = 32;
                            int pos_row = 0;
                            for(int i=0;i<16;++i){
                                for(int j=0;j<16;++j){
                                    if(bmp.GetPixel(ch_offset + j,i).ToArgb() == System.Drawing.Color.Black.ToArgb()){
                                        System.Drawing.Color pixel_color = System.Drawing.Color.FromArgb(Colors.ConvertColor(Colors.ResolveColor(cch.color)).ToArgb());
                                        result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,pixel_color);
                                        result.SetPixel(pos_col * 16 + j + 16,pos_row * 16 + i,pixel_color);
                                    }
                                    else{
                                        result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,System.Drawing.Color.Transparent);
                                        result.SetPixel(pos_col * 16 + j + 16,pos_row * 16 + i,System.Drawing.Color.Transparent);
                                    }
                                }
                            }
                        }
                        for(ActorType at = ActorType.PHANTOM_ZOMBIE;at <= ActorType.PHANTOM_CONSTRICTOR;at++){
                                M.actor[2,2] = null;
                            Actor.CreatePhantom(2,2);
                            if(!M.actor[2,2].Is(at)){
                                at--;
                                continue;
                            }
                                colorchar cch = M.VisibleColorChar(2,2);
                                int ch_offset = (int)(cch.c) * 16;
                                int pos_col = 32 + (idx % 16);
                                int pos_row = 4 + idx / 16;
                                for(int i=0;i<16;++i){
                                    for(int j=0;j<16;++j){
                                        if(bmp.GetPixel(ch_offset + j,i).ToArgb() == System.Drawing.Color.Black.ToArgb()){
                                            System.Drawing.Color pixel_color = System.Drawing.Color.FromArgb(Colors.ConvertColor(Colors.ResolveColor(cch.color)).ToArgb());
                                            result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,pixel_color);
                                            result.SetPixel(pos_col * 16 + j + 16,pos_row * 16 + i,pixel_color);
                                        }
                                        else{
                                            result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,System.Drawing.Color.Transparent);
                                            result.SetPixel(pos_col * 16 + j + 16,pos_row * 16 + i,System.Drawing.Color.Transparent);
                                        }
                                    }
                                }
                                idx += 2;
                        }

                        int diff = 0;
                        foreach(FeatureType ft in Enum.GetValues(typeof(FeatureType))){
                            M.tile[2,2] = null;
                            Tile.Create(TileType.FLOOR,2,2);
                            M.tile[2,2].revealed_by_light = true;
                            M.tile[2,2].AddFeature(ft);
                            colorchar cch = M.VisibleColorChar(2,2);
                            int ch_offset = (int)(cch.c) * 16;
                            int pos_col = 16 + (diff % 16);
                            int pos_row = diff / 16;
                            for(int i=0;i<16;++i){
                                for(int j=0;j<16;++j){
                                    if(bmp.GetPixel(ch_offset + j,i).ToArgb() == System.Drawing.Color.Black.ToArgb()){
                                        System.Drawing.Color pixel_color = System.Drawing.Color.FromArgb(Colors.ConvertColor(Colors.ResolveColor(cch.color)).ToArgb());
                                        result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,pixel_color);
                                    }
                                    else{
                                        result.SetPixel(pos_col * 16 + j,pos_row * 16 + i,System.Drawing.Color.Transparent);
                                    }
                                }
                            }
                            diff += intarray[idx];
                            diff++;
                            ++idx;
                        }

                        foreach(TileType tt in tilelist){
                            M.tile[2,2] = null;
                            pos tilepos = tileposlist[idx];
                            Tile.Create(tt,2,2);
                            M.tile[2,2].revealed_by_light = true;
                            colorchar cch = M.VisibleColorChar(2,2);
                            int ch_offset = (int)(cch.c) * 16;
                            for(int i=0;i<16;++i){
                                for(int j=0;j<16;++j){
                                    if(bmp.GetPixel(ch_offset + j,i).ToArgb() == System.Drawing.Color.Black.ToArgb()){
                                        System.Drawing.Color pixel_color = System.Drawing.Color.FromArgb(Colors.ConvertColor(Colors.ResolveColor(cch.color)).ToArgb());
                                        result.SetPixel(tilepos.row * 16 + j,tilepos.col * 16 + i,pixel_color);
                                    }
                                    else{
                                        result.SetPixel(tilepos.row * 16 + j,tilepos.col * 16 + i,System.Drawing.Color.Black);
                                    }
                                }
                            }
                            ++idx;
                        }*/
                        Q0();
                        maxmp = 99;
                        curmp = maxmp;
                        skills[SkillType.MAGIC] = 10;
                        foreach(SpellType sp in new List<SpellType>{SpellType.TELEKINESIS,SpellType.COLLAPSE,SpellType.FORCE_PALM,SpellType.GREASE,SpellType.AMNESIA,SpellType.FLYING_LEAP}){
                            GainSpell(sp);
                            spells_in_order.Add(sp);
                        }
                        IsHiddenFrom(this);
                        /*M.UpdateSafetyMap(player);
                        var dijk = U.GetDijkstraMap(M.tile,x=>M.tile[x].BlocksConnectivityOfMap(),new List<pos>{this.p});
                        foreach(pos p in M.AllPositions()){
                            int v = M.safetymap[p];
                            colorchar cch = new colorchar(' ',Color.White);
                            if(v == U.DijkstraMin){
                                cch.c = '#';
                            }
                            if(v == U.DijkstraMax){
                                cch.c = '!';
                            }
                            if(v.IsValidDijkstraValue()){
                                v /= 10;
                                cch.c = (char)('z' - v.Modulo(26));
                                cch.color = (Color)(3 - (v+1)/26);
                            }
                            Screen.WriteMapChar(p.row,p.col,cch);
                        }
                        Input.ReadKey();
                        foreach(pos p in M.AllPositions()){
                            int v = M.safetymap[p];
                            colorchar cch = new colorchar(' ',Color.White);
                            if(v == U.DijkstraMin){
                                cch.c = '#';
                            }
                            if(v == U.DijkstraMax){
                                cch.c = '!';
                            }
                            if(v.IsValidDijkstraValue()){
                                v = v/10 + dijk[p];
                                if(v > -2){
                                    cch.c = ':';
                                }
                                else{
                                    cch.c = '.';
                                }
                                cch.c = (char)('z' - v.Modulo(26));
                                cch.color = (Color)(3 - (v+1)/26);
                            }
                            Screen.WriteMapChar(p.row,p.col,cch);
                        }
                        Input.ReadKey();*/
                        break;
                    }
                    case 3:
                    {
                        /*ConsoleKeyInfo command2 = Input.ReadKey();
                        Screen.WriteMapString(14,14,((int)(command2.KeyChar)).ToString());
                        Input.ReadKey();
                        List<Tile> line = GetTarget(-1,-1);
                        if(line != null){
                            Tile t = line.Last();
                            if(t != null){
                                t.AddOpaqueFeature(FeatureType.FOG);
                            }
                        }*/
                        Actor a = M.SpawnMob(ActorType.STALKING_WEBSTRIDER);
                        /*foreach(Actor a in M.AllActors()){
                            if(a.type == ActorType.WARG){
                                a.attrs[AttrType.WANDERING] = 1;
                            }
                        }*/
                        Q0();
                        //M.GenerateFinalLevel();
                        break;
                    }
                    case 4:
                    {
                        Screen.CursorVisible = false;
                        colorchar cch;
                        cch.c = ' ';
                        cch.color = Color.Black;
                        cch.bgcolor = Color.Black;
                        foreach(Tile t in M.AllTiles()){
                            t.seen = false;
                            Screen.WriteMapChar(t.row,t.col,cch);
                        }
                        Screen.CursorVisible = true;
                        Q0();
                        break;
                    }
                    case 5:
                        curhp = maxhp;
                        Q0();
                        break;
                    case 6:
                        if(!HasAttr(AttrType.INVULNERABLE)){
                            attrs[AttrType.INVULNERABLE]++;
                            B.Add("On. ");
                        }
                        else{
                            attrs[AttrType.INVULNERABLE] = 0;
                            B.Add("Off. ");
                        }
                        Q0();
                        break;
                    case 7:
                    {
                        if(InventoryCount() >= Global.MAX_INVENTORY_SIZE){
                            inv = new List<Item>();
                        }
                        while(InventoryCount() < Global.MAX_INVENTORY_SIZE){
                            Item.Create(Item.RandomItem(),this);
                        }
                        foreach(Item i in inv){
                            i.revealed_by_light = true;
                        }
                        Q0();
                        break;
                    }
                    case 8:
                    {
                        //int[,] a = GetBinaryNoise(ROWS,COLS);
                        /*int[,] a = GetDividedNoise(ROWS,COLS,40);
                        int[,] chances = new int[ROWS,COLS];
                        int[,] values = new int[ROWS,COLS];
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                bool passable = (a[i,j] == 1);
                                if(passable){
                                    values[i,j] = -1;
                                }
                                else{
                                    values[i,j] = 0;
                                }
                            }
                        }
                        int minrow = 1;
                        int maxrow = ROWS-2;
                        int mincol = 1;
                        int maxcol = COLS-2;
                        int val = 0;
                        bool done = false;
                        while(!done){
                            done = true;
                            for(int i=minrow;i<=maxrow;++i){
                                for(int j=mincol;j<=maxcol;++j){
                                    if(values[i,j] == val){
                                        for(int s=i-1;s<=i+1;++s){
                                            for(int t=j-1;t<=j+1;++t){
                                                if(values[s,t] == -1){
                                                    values[s,t] = val + 1;
                                                    done = false;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            ++val;
                        }
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                if(a[i,j] == 1){
                                    //distances[i,j] = values[i,j];
                                    int k = 5 + values[i,j];
                                    if(k >= 10){
                                        chances[i,j] = 10;
                                    }
                                    else{
                                        chances[i,j] = k;
                                    }
                                }
                            }
                        }
                        values = new int[ROWS,COLS];
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                bool passable = (a[i,j] == -1);
                                if(passable){
                                    values[i,j] = -1;
                                }
                                else{
                                    values[i,j] = 0;
                                }
                            }
                        }
                        val = 0;
                        done = false;
                        while(!done){
                            done = true;
                            for(int i=minrow;i<=maxrow;++i){
                                for(int j=mincol;j<=maxcol;++j){
                                    if(values[i,j] == val){
                                        for(int s=i-1;s<=i+1;++s){
                                            for(int t=j-1;t<=j+1;++t){
                                                if(values[s,t] == -1){
                                                    values[s,t] = val + 1;
                                                    done = false;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            ++val;
                        }
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                if(a[i,j] == -1){
                                    //distances[i,j] = -(values[i,j]);
                                    int k = 5 + values[i,j];
                                    if(k >= 10){
                                        chances[i,j] = 0;
                                    }
                                    else{
                                        chances[i,j] = 10 - k;
                                    }
                                }
                            }
                        }
                        DungeonGen.StandardDungeon dungeon1 = new DungeonGen.StandardDungeon();
                        char[,] map1 = dungeon1.GenerateStandard();
                        DungeonGen.StandardDungeon dungeon2 = new DungeonGen.StandardDungeon();
                        char[,] map2 = dungeon2.GenerateCave();
                        char[,] map3 = new char[ROWS,COLS];
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                if(a[i,j] == -1){
                                    map3[i,j] = map1[i,j];
                                }
                                else{
                                    if(a[i,j] == 1){
                                        map3[i,j] = map2[i,j];
                                    }
                                    else{
                                        if(map1[i,j] == '#'){
                                            map3[i,j] = map2[i,j];
                                        }
                                        else{
                                            if(map2[i,j] == '#'){
                                                map3[i,j] = map1[i,j];
                                            }
                                            else{
                                                if(R.CoinFlip()){
                                                    map3[i,j] = map1[i,j];
                                                }
                                                else{
                                                    map3[i,j] = map2[i,j];
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                Screen.WriteMapChar(i,j,map3[i,j]);
                                if(distances[i,j] > -10){
                                    if(distances[i,j] < 10){
                                        if(distances[i,j] < 0){
                                            Screen.WriteMapChar(i,j,(-distances[i,j]).ToString()[0],Color.DarkMagenta);
                                        }
                                        else{
                                            if(distances[i,j] > 0){
                                                Screen.WriteMapChar(i,j,distances[i,j].ToString()[0],Color.DarkCyan);
                                            }
                                            else{
                                                Screen.WriteMapChar(i,j,distances[i,j].ToString()[0],Color.DarkGray);
                                            }
                                        }
                                    }
                                    else{
                                        Screen.WriteMapChar(i,j,'+',Color.DarkCyan);
                                    }
                                }
                                else{
                                    Screen.WriteMapChar(i,j,'-',Color.DarkMagenta);
                                }
                            }
                        }

                        tile().Toggle(null,TileType.BLAST_FUNGUS);

                        List<Tile> area = new List<Tile>();
                        foreach(Tile t in TilesWithinDistance(3).Where(x=>x.passable && HasLOE(x))){
                            t.Toggle(null,TileType.POPPY_FIELD);
                            area.Add(t);
                        }
                        Q.Add(new Event(area,100,EventType.POPPIES));

                        tile().Toggle(null,TileType.TOMBSTONE);
                        Input.ReadKey();

                        List<string> movement = new List<string>{"is immobile","moves quickly","moves slowly"};
                        List<string> ability = new List<string>{"can step back after attacking","moves erratically","flies","can use an aggressive stance","uses a ranged attack","uses a burst attack","lunges","has a poisonous attack","drains life","has a powerful but slow attack","grabs its targets","has a knockback attack","has a slowing attack","has a silencing attack","can steal items","explodes when defeated","stays at range",
                        "sidesteps when it attacks","has a paralyzing attack","has a stunning attack","is stealthy","appears with others of its type","carries a light source","is invisible in darkness","disrupts nearby spells","regenerates","comes back after death","wears armor","has heightened senses","has hard skin that can blunt edged weapons","casts spells","can reduce its target's attack power","can burrow"};
                        List<string> rare_ability = new List<string>{"is attracted to light","is blind in the light","can create illusions of itself","sets itself on fire","throws a bola to slow its targets","dims nearby light sources","screams to terrify its prey","howls to embolden others attacking its prey","breathes poison","is surrounded by a poisonous cloud",
                        "is surrounded by a cloud of fog","can summon a minion","can fill the area with sunlight","is resistant to weapons","can turn into a statue","can throw explosives","can create stalagmites","collapses into rubble when defeated","has a fiery attack","can teleport its foes away","can pull its targets closer from a distance","releases spores when attacked","can absorb light to heal","leaves a trail as it travels","breathes fire","can spit blinding poison","lays volatile eggs","can breach nearby walls","is knocked back by blunt weapons","causes attackers to become exhausted","can create a temporary wall","can throw its foes overhead"};
                        char randomsymbol = (char)((R.Roll(26)-1) + (int)'a');
                        if(R.CoinFlip()){
                            randomsymbol = randomsymbol.ToString().ToUpper()[0];
                        }
                        string s1 = "This monster is a " + Screen.GetColor(Color.RandomAny).ToString().ToLower().Replace("dark","dark ") + " '" + randomsymbol + "'. ";
                        string s2 = "It ";
                        bool add_move = R.OneIn(5);
                        int num_abilities = R.Roll(2) + 1;
                        if(R.OneIn(10)){
                            ++num_abilities;
                        }
                        int total = num_abilities;
                        if(add_move){ ++total; }
                        if(add_move){
                            --total;
                            if(total == 0){
                                s2 = s2 + "and " + movement.Random() + ". ";
                            }
                            else{
                                s2 = s2 + movement.Random() + ", ";
                            }
                        }
                        for(int i=num_abilities;i>0;--i){
                            --total;
                            string a = "";
                            if(R.PercentChance(50)){
                                a = ability.Random();
                            }
                            else{
                                a = rare_ability.Random();
                            }
                            if(!s2.Contains(a)){
                                if(total == 0){
                                    s2 = s2 + "and " + a + ". ";
                                }
                                else{
                                    s2 = s2 + a + ", ";
                                }
                            }
                            else{
                                ++i;
                                ++total;
                            }
                        }

                        if(add_rare){
                            --total;
                            if(total == 0){
                                s2 = s2 + "and " + rare_ability.Random() + ". ";
                            }
                            else{
                                s2 = s2 + rare_ability.Random() + ", ";
                            }
                        }

                        B.Add(s1);
                        B.Add(s2);
                        if(s2.Contains("casts spells")){
                            List<SpellType> all_spells = new List<SpellType>();
                            foreach(SpellType spl in Enum.GetValues(typeof(SpellType))){
                                all_spells.Add(spl);
                            }
                            all_spells.Remove(SpellType.NO_SPELL);
                            all_spells.Remove(SpellType.NUM_SPELLS);
                            string sp = "It can cast ";
                            for(int num_spells = R.Roll(4);num_spells > 0;--num_spells){
                                if(num_spells == 1){
                                    sp = sp + "and " + all_spells.RemoveRandom().ToString().ToLower().Replace('_',' ') + ". ";
                                }
                                else{
                                    sp = sp + all_spells.RemoveRandom().ToString().ToLower().Replace('_',' ') + ", ";
                                }
                            }
                            B.Add(sp);
                        }*/
                        Q0();
                        foreach(Tile t in M.AllTiles()){
                            if(t.passable && DistanceFrom(t) > 4 && R.OneIn(10)){
                                ActorType at = (ActorType)R.Between(3,72);
                                Actor.Create(at,t.row,t.col);
                            }
                        }
                        break;
                    }
                    case 9:
                        new Item(ConsumableType.PASSAGE,"rune of passage",'&',Color.White).Use(this);
                        Q1();
                        break;
                    case 10:
                        foreach(Tile t in M.AllTiles()){
                            t.seen = true;
                            colorchar ch2 = Screen.BlankChar();
                            if(t.IsKnownTrap() || t.IsShrine() || t.Is(TileType.RUINED_SHRINE)){
                                t.revealed_by_light = true;
                            }
                            if(t.inv != null){
                                t.inv.revealed_by_light = true;
                                ch2.c = t.inv.symbol;
                                ch2.color = t.inv.color;
                                M.last_seen[t.row,t.col] = ch2;
                            }
                            else{
                                if(t.features.Count > 0){
                                    ch2 = t.FeatureVisual();
                                    M.last_seen[t.row,t.col] = ch2;
                                }
                                else{
                                    ch2.c = t.symbol;
                                    ch2.color = t.color;
                                    if(ch2.c == '#' && ch2.color == Color.RandomGlowingFungus){
                                        ch2.color = Color.Gray;
                                    }
                                    M.last_seen[t.row,t.col] = ch2;
                                }
                            }
                            Screen.WriteMapChar(t.row,t.col,ch2);
                        }
                        //M.Draw();
                        foreach(Actor a in M.AllActors()){
                            Screen.WriteMapChar(a.row,a.col,new colorchar(a.color,Color.Black,a.symbol));
                        }
                        Input.ReadKey();
                        Q0();
                        break;
                    case 11:
                        for(int i=0;i<1;++i){
                            if(M.current_level < 20){
                                //M.level_types[M.current_level] = LevelType.Standard;
                            }
                            M.GenerateLevel();
                            /*foreach(Tile t in M.AllTiles()){
                                if(t.TilesWithinDistance(1).Any(x=>x.type != TileType.WALL)){
                                    t.seen = true;
                                }
                            }
                            B.Print(false);
                            M.Draw();*/
                        }
                        Q0();
                        break;
                    case 12:
                    {
                        /*PosArray<int> map = new PosArray<int>(ROWS,COLS);
                        pos center = new pos(ROWS/2,COLS/2);
                        int n = 2;
                        foreach(pos p in center.PositionsWithinDistance(n-1)){
                            map[p] = 1;
                        }
                        bool changed = true;
                        while(changed){
                            changed = false;
                            List<pos> list = center.PositionsAtDistance(n);
                            while(list.Count > 0){
                                pos p = list.RemoveRandom();
                                int count = p.PositionsAtDistance(1).Where(x=>map[x] == 1).Count;
                                if(R.PercentChance(count*25)){ //this number can be anywhere from ~19 to 25
                                    map[p] = 1;
                                    changed = true;
                                }
                            }
                            ++n;
                        }
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                //pos p = new pos(i,j);
                                //if(p.PositionsWithinDistance(1).Where(x=>map[x] == 1).Count >= 5){
                                if(map[i,j] == 1){
                                    Screen.WriteMapChar(i,j,'.',Color.Green);
                                }
                                else{
                                    Screen.WriteMapChar(i,j,'~',Color.Blue);
                                }
                            }
                        }
                        Input.ReadKey();
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                pos p = new pos(i,j);
                                if(p.PositionsWithinDistance(1).Where(x=>map[x] == 1).Count >= 5){
                                //if(map[i,j] == 1){
                                    Screen.WriteMapChar(i,j,'.',Color.Green);
                                }
                                else{
                                    Screen.WriteMapChar(i,j,'~',Color.Blue);
                                }
                            }
                        }
                        Input.ReadKey();

                        level = 10;
                        skills[SkillType.COMBAT] = 10;
                        skills[SkillType.DEFENSE] = 10;
                        skills[SkillType.MAGIC] = 10;
                        skills[SkillType.SPIRIT] = 10;
                        skills[SkillType.STEALTH] = 10;
                        foreach(FeatType f in Enum.GetValues(typeof(FeatType))){
                            if(f != FeatType.NO_FEAT && f != FeatType.NUM_FEATS){
                                feats[f] = true;
                            }
                        }

                        foreach(Tile t in M.AllTiles()){
                            if(t.type == TileType.FLOOR){
                                if(R.CoinFlip()){
                                    t.Toggle(null,TileType.STONE_RAIN_TRAP);
                                }
                                else{
                                    t.Toggle(null,TileType.FLING_TRAP);
                                }
                            }
                        }
                        for(int i=0;i<10;++i){
                            M.SpawnMob(ActorType.FROSTLING);
                        }*/
                        Q0();
                        RefreshDuration(AttrType.ENRAGED,1500);
                        break;
                    }
                    case 13:
                    {
                        //LevelUp();
                            foreach(Tile t in TilesWithinDistance(2)){
                                t.TransformTo((TileType)(R.Between(0,4)+(int)TileType.COMBAT_SHRINE));
                            }
                        Q0();
                        break;
                    }
                    case 14:
                    {
                        foreach(Tile t in TilesAtDistance(1)){
                            t.TransformTo(Tile.RandomTrap());
                        }
                        Q0();
                        break;
                    }
                    case 15:
                    {
                            List<Tile> line = GetTargetTile(-1,0,false,false);
                            if(line != null){
                                Tile t = line.LastOrDefault();
                                if(t != null){
                                    //t.TransformTo(TileType.DOOR_O);
                                if(t.Is(FeatureType.FIRE)){
                                    t.RemoveFeature(FeatureType.FIRE);
                                    t.Toggle(null,TileType.DEMONIC_IDOL);
                                }
                                else{
                                t.AddFeature(FeatureType.FIRE);
                                }
                                }
                            }
                        Q0();
                        break;
                    }
                    case 16:
                    {
                        for(int i=0;i<100;++i){
                            M.SpawnMob(ActorType.GOBLIN);
                        }
                        if(HasFeat(FeatType.NECK_SNAP)){
                            feats[FeatType.NECK_SNAP] = false;
                        }
                        Q0();
                        break;
                    }
                    case 17:
                    {
                        /*List<Tile> list = new List<Tile>();
                        while(list.Count < 15){
                            int rr = R.Roll(ROWS-2);
                            int rc = R.Roll(COLS-2);
                            if(M.tile[rr,rc].passable){
                                list.AddUnique(M.tile[rr,rc]);
                            }
                        }
                        for(int i=0;i<ROWS;++i){
                            for(int j=0;j<COLS;++j){
                                if(M.tile[i,j].passable){
                                    List<Tile> closest_tiles = list.WhereLeast(x => x.ApproximateEuclideanDistanceFromX10(i,j));
                                    //List<Tile> closest_tiles = list.WhereLeast(x => new Actor(this,i,j).GetPath(x.row,x.col).Count);
                                    if(closest_tiles.Count == 2){
                                        Screen.WriteMapChar(i,j,'=',Color.White);
                                    }
                                    else{
                                        int idx = list.IndexOf(closest_tiles[0]);
                                        Screen.WriteMapChar(i,j,M.tile[i,j].symbol,(Color)(idx+3));
                                    }
                                }
                                else{
                                    if(!M.tile[i,j].solid_rock){
                                        Screen.WriteMapChar(i,j,M.tile[i,j].symbol,M.tile[i,j].color);
                                    }
                                    else{
                                        Screen.WriteMapChar(i,j,Screen.BlankChar());
                                    }
                                }
                            }
                        }

                        Screen.Blank();
                        Tile[] prev = new Tile[20];
                        int idx = 0;
                        foreach(Tile t in M.ReachableTilesByDistance(row,col,false,TileType.DOOR_C)){
                            Screen.WriteMapChar(t.row,t.col,t.symbol,t.color);
                            prev[idx] = t;
                            idx = (idx + 1) % 20;
                            if(prev[idx] != null){
                                Screen.WriteMapChar(prev[idx].row,prev[idx].col,Screen.BlankChar());
                            }
                            Thread.Sleep(10);
                        }*/
                        foreach(Actor a in M.AllActors()){
                            if(a != this){
                                a.Kill();
                            }
                        }
                        UpdateRadius(LightRadius(),0);
                        for(int i=1;i<ROWS-1;++i){
                            for(int j=1;j<COLS-1;++j){
                                M.tile[i,j] = null;
                                Tile.Create(TileType.BRUSH,i,j);
                            }
                        }
                        UpdateRadius(0,LightRadius());
                        foreach(Tile t in M.AllTiles()){
                            if(t.TilesWithinDistance(1).Any(x=>x.type != TileType.WALL)){
                                t.seen = true;
                            }
                        }
                        Q.KillEvents(null,EventType.CHECK_FOR_HIDDEN);
                        M.wiz_lite = true;
                        M.wiz_dark = false;
                        B.Print(false);
                        M.Draw();
                        Q0();
                        break;
                    }
                    case 18:
                    {
                        if(attrs[AttrType.DETECTING_MONSTERS] == 0){
                            attrs[AttrType.DETECTING_MONSTERS] = 1;
                        }
                        else{
                            attrs[AttrType.DETECTING_MONSTERS] = 0;
                        }
                        Q0();
                        break;
                    }
                    case 19:
                    {
                        /*List<Tile> line = GetTargetTile(-1,0,false);
                        if(line != null){
                            Tile t = line.Last();
                            if(t != null){
                                t.Toggle(null,TileType.CHASM);
                                Q.Add(new Event(t,100,EventType.FLOOR_COLLAPSE));
                                B.Add("The floor begins to collapse! ");
                            }
                        }*/
                        if(tile().inv == null){
                            tile().inv = Item.Create(ConsumableType.ENCHANTMENT,row,col);
                            //TileInDirection(8).inv = Item.Create(ConsumableType.FLAMES,-1,-1);
                            B.Add("You feel something roll beneath your feet. ");
                            //magic_trinkets.Add(MagicTrinketType.PENDANT_OF_LIFE);
                        }
                        Q0();
                        break;
                    }
                    default:
                        Q0();
                        break;
                    }
                }
                else{
                    Q0();
                }
                break;
            }
            case ' ':
                Q0();
                break;
            default:
                B.Add("Press '?' for help. ");
                Q0();
                break;
            }
            if(ch != 'x'){
                attrs[AttrType.AUTOEXPLORE] = 0;
            }
        }
		public static async Task TutorialTip(TutorialTopic topic){
			if(Global.Option(OptionType.NEVER_DISPLAY_TIPS) || displayed[topic]){
				return;
			}
			Color box_edge_color = Color.Blue;
			Color box_corner_color = Color.Yellow;
			Color first_line_color = Color.Yellow;
			Color text_color = Color.Gray;
			string[] text = TutorialText(topic);
			int stringwidth = 27; // length of "[Press any key to continue]"
			foreach(string s in text){
				if(s.Length > stringwidth){
					stringwidth = s.Length;
				}
			}
			stringwidth += 4; //2 blanks on each side
			int boxwidth = stringwidth + 2;
			int boxheight = text.Length + 5;
			//for(bool done=false;!done;){
			colorstring[] box = new colorstring[boxheight]; //maybe i should make this a list to match the others
			box[0] = new colorstring("+",box_corner_color,"".PadRight(stringwidth,'-'),box_edge_color,"+",box_corner_color);
			box[text.Length + 1] = new colorstring("|",box_edge_color,"".PadRight(stringwidth),Color.Gray,"|",box_edge_color);
            box[text.Length + 2] = new colorstring("|", box_edge_color) + ("[Press any key to continue]".PadOuter(stringwidth).GetColorString(text_color)) + new colorstring("|", box_edge_color); //PadOuter originally here
            box[text.Length + 3] = new colorstring("|", box_edge_color) + ("[=] Stop showing tips".PadOuter(stringwidth).GetColorString(text_color)) + new colorstring("|", box_edge_color); //PadOuter originally here
			box[text.Length + 4] = new colorstring("+",box_corner_color,"".PadRight(stringwidth,'-'),box_edge_color,"+",box_corner_color);
			int pos = 1;
			foreach(string s in text){
                box[pos] = new colorstring("|", box_edge_color) + (s.PadOuter(stringwidth).GetColorString(text_color)) + new colorstring("|", box_edge_color); //PadOuter originally here
				if(pos == 1){
					box[pos] = new colorstring();
					box[pos].strings.Add(new cstr("|",box_edge_color));
                    box[pos].strings.Add(new cstr(s.PadOuter(stringwidth), first_line_color)); //PadOuter originally here
					box[pos].strings.Add(new cstr("|",box_edge_color));
				}
				++pos;
			}
			int y = (Global.SCREEN_H - boxheight) / 2;
			int x = (Global.SCREEN_W - boxwidth) / 2;
			colorchar[,] memory = Screen.GetCurrentRect(y,x,boxheight,boxwidth);
			List<List<colorstring>> frames = new List<List<colorstring>>();
			frames.Add(BoxAnimationFrame(boxheight-2,FrameWidth(boxheight,boxwidth)));
			for(int i=boxheight-4;i>0;i-=2){
				frames.Add(BoxAnimationFrame(i,FrameWidth(frames.Last().Count,frames.Last()[0].Length())));
			}
			for(int i=frames.Count-1;i>=0;--i){ //since the frames are in reverse order
				int y_offset = i + 1;
				int x_offset = (boxwidth - frames[i][0].Length()) / 2;
				Screen.WriteList(y+y_offset,x+x_offset,frames[i]);
                await Task.Delay(20);
			}
			foreach(colorstring s in box){
				Screen.WriteString(y,x,s);
				++y;
			}
			Actor.player.DisplayStats(false);
			if(topic != TutorialTopic.Feats){ //hacky exception - don't get rid of the line that's already there.
				Actor.B.DisplayNow();
			}
			Game.Console.CursorVisible = false;
            await Task.Delay(500);
			Global.FlushInput();
			/*	switch(Game.Console.ReadKey(true).KeyChar){
				case 'q':
					box_edge_color = NextColor(box_edge_color);
					break;
				case 'w':
					box_corner_color = NextColor(box_corner_color);
					break;
				case 'e':
					first_line_color = NextColor(first_line_color);
					break;
				case 'r':
					text_color = NextColor(text_color);
					break;
				default:
					done=true;
					break;
				}
			}*/
			if((await Game.Console.ReadKey(true)).KeyChar == '='){
				Global.Options[OptionType.NEVER_DISPLAY_TIPS] = true;
			}
			Screen.WriteArray((Global.SCREEN_H - boxheight) / 2,x,memory);
			if(topic != TutorialTopic.Feats){ //another exception
				Actor.player.DisplayStats(true);
			}
			displayed[topic] = true;
			Game.Console.CursorVisible = true;
		}
Example #23
0
 public static void WriteString(int r,int c,colorstring cs)
 {
     if(cs.Length() > 0){
         int pos = c;
         int start_col = -1;
         int end_col = -1;
         foreach(cstr s1 in cs.strings){
             cstr s = new cstr(s1.s,s1.color,s1.bgcolor);
             if(s.s.Length + pos > Global.SCREEN_W){
                 s.s = s.s.Substring(0,Global.SCREEN_W - pos);
             }
             s.color = Colors.ResolveColor(s.color);
             s.bgcolor = Colors.ResolveColor(s.bgcolor);
             colorchar cch;
             cch.color = s.color;
             cch.bgcolor = s.bgcolor;
             if(!GLMode){
                 ConsoleColor co = Colors.GetColor(s.color);
                 if(ForegroundColor != co){
                     ForegroundColor = co;
                 }
                 co = Colors.GetColor(s.bgcolor);
                 if(BackgroundColor != co){
                     BackgroundColor = co;
                 }
             }
             int i = 0;
             bool changed = false;
             foreach(char ch in s.s){
                 cch.c = ch;
                 if(!memory[r,pos+i].Equals(cch)){
                     memory[r,pos+i] = cch;
                     if(start_col == -1){
                         start_col = pos+i;
                     }
                     end_col = pos+i;
                     changed = true;
                 }
                 ++i;
             }
             if(changed && !GLMode){
                 Console.SetCursorPosition(pos,r);
                 Console.Write(s.s);
             }
             pos += s.s.Length;
         }
         if(GLMode && !NoGLUpdate && start_col != -1){
             UpdateGLBuffer(r,start_col,r,end_col);
         }
         if(MouseUI.AutomaticButtonsFromStrings && GLMode){
             int idx = 0;
             int brace = -1;
             int start = -1;
             int end = -1;
             bool last_char_was_separator = false;
             while(true){
                 char ch = cs[idx].c;
                 if(brace == -1){
                     if(ch == '['){
                         brace = 0;
                         start = idx;
                     }
                 }
                 else{
                     if(brace == 0){
                         if(ch == ']'){
                             brace = 1;
                             end = idx;
                         }
                     }
                     else{
                         if(ch == ' ' || ch == '-' || ch == ','){
                             if(last_char_was_separator){
                                 ConsoleKey key = ConsoleKey.A;
                                 bool shifted = false;
                                 switch(cs[start+1].c){
                                 case 'E':
                                     key = ConsoleKey.Enter;
                                     break;
                                 case 'T':
                                     key = ConsoleKey.Tab;
                                     break;
                                 case 'P': //"Press any key"
                                     break;
                                 case '?':
                                     key = ConsoleKey.Oem2;
                                     shifted = true;
                                     break;
                                 case '=':
                                     key = ConsoleKey.OemPlus;
                                     break;
                                 default: //all others should be lowercase letters
                                     key = (ConsoleKey)(ConsoleKey.A + ((int)cs[start+1].c - (int)'a'));
                                     break;
                                 }
                                 MouseUI.CreateButton(key,shifted,r,c+start,1,end-start+1);
                                 brace = -1;
                                 start = -1;
                                 end = -1;
                             }
                             last_char_was_separator = !last_char_was_separator;
                         }
                         else{
                             last_char_was_separator = false;
                             end = idx;
                         }
                     }
                 }
                 ++idx;
                 if(idx == cs.Length()){
                     if(brace == 1){
                         ConsoleKey key = ConsoleKey.A;
                         bool shifted = false;
                         switch(cs[start+1].c){
                         case 'E':
                             key = ConsoleKey.Enter;
                             break;
                         case 'T':
                             key = ConsoleKey.Tab;
                             break;
                         case 'P': //"Press any key"
                             break;
                         case '?':
                             key = ConsoleKey.Oem2;
                             shifted = true;
                             break;
                         case '=':
                             key = ConsoleKey.OemPlus;
                             break;
                         default: //all others should be lowercase letters
                             key = (ConsoleKey)(ConsoleKey.A + ((int)cs[start+1].c - (int)'a'));
                             break;
                         }
                         MouseUI.CreateButton(key,shifted,r,c+start,1,end-start+1);
                     }
                     break;
                 }
             }
         }
     }
 }
Example #24
0
 public colorstring NameOnStatusBar()
 {
     if(IsEnchanted()){
         colorstring cs = new colorstring("+",EnchantmentColor());
         return new colorstring("-- ",cs,NameWithoutEnchantment().Capitalize(),cs," --").PadOuter(Global.STATUS_WIDTH);
     }
     else{
         return new colorstring(("-- " + NameWithoutEnchantment().Capitalize() + " --").PadOuter(Global.STATUS_WIDTH),Color.Gray);
     }
 }
Example #25
0
 public static colorstring operator +(cstr one,colorstring two)
 {
     //todo: whoops, forgot colorchar in this section.
     colorstring result = new colorstring();
     result.strings.Add(one);
     foreach(cstr s in two.strings){
         result.strings.Add(s);
     }
     return result;
 }
		public static colorstring operator +(colorstring one,colorstring two){
			colorstring result = new colorstring();
			foreach(cstr s in one.strings){
				result.strings.Add(s);
			}
			foreach(cstr s in two.strings){
				result.strings.Add(s);
			}
			return result;
		}
Example #27
0
 public static colorstring operator +(colorstring one,string two)
 {
     colorstring result = new colorstring();
     foreach(cstr s in one.strings){
         result.strings.Add(s);
     }
     result.strings.Add(new cstr(two,Color.Gray));
     return result;
 }
		public static void WriteMapString(int r,int c,colorstring cs){
			if(cs.Length() > 0){
				r += Global.MAP_OFFSET_ROWS;
				c += Global.MAP_OFFSET_COLS;
				int cpos = c;
				foreach(cstr s1 in cs.strings){
					cstr s = new cstr(s1.s,s1.color,s1.bgcolor);
					if(cpos-Global.MAP_OFFSET_COLS + s.s.Length > Global.COLS){
						s.s = s.s.Substring(0,Global.COLS-(cpos-Global.MAP_OFFSET_COLS));
					}
					s.color = ResolveColor(s.color);
					s.bgcolor = ResolveColor(s.bgcolor);
                    colorchar cch = new colorchar(' ', s.color, s.bgcolor);
/*					cch.color = s.color;
					cch.bgcolor = s.bgcolor;*/
					ConsoleColor co = GetColor(s.color);
					if(ForegroundColor != co){
						ForegroundColor = co;
					}
					co = GetColor(s.bgcolor);
					if(BackgroundColor != co){
						BackgroundColor = co;
					}
					int i = 0;
                    bool changed = false;
                    for (int ii = 0; ii < s.s.Length; ii++)
                    {
                        cch.c = s.s.CharAt(ii);
						if(!memory[r,cpos+i].Equals(cch)){
							memory[r,cpos+i] = cch;
							changed = true;
						}
						++i;
					}
					if(changed){
						Game.Console.SetCursorPosition(cpos,r);
						Game.Console.Write(s.s);
					}
					cpos += s.s.Length;
				}
				/*if(cpos-Global.MAP_OFFSET_COLS < Global.COLS){
					WriteString(r,cpos,"".PadRight(Global.COLS-(cpos-Global.MAP_OFFSET_COLS)));
				}*/
			}
		}
Example #29
0
        public static void AddWithWrap(this List <colorstring> l, colorstring cs, int wrap_width, int indent = 0)
        {
            colorstring last      = l.LastOrDefault();
            colorstring remainder = null;

            if (last == null)
            {
                remainder = cs;
            }
            else
            {
                if (last.Length() + cs.Length() <= wrap_width)
                {
                    foreach (cstr s in cs.strings)
                    {
                        last.strings.Add(s);
                    }
                }
                else
                {
                    int split_idx = cs.LastSpaceBeforeWrap(wrap_width - last.Length());
                    if (split_idx == -1)
                    {
                        remainder = cs;
                    }
                    else
                    {
                        var split = cs.SplitAt(split_idx, true);
                        foreach (cstr s in split[0].strings)
                        {
                            last.strings.Add(s);
                        }
                        remainder = split[1];
                    }
                }
            }
            while (remainder?.Length() > 0)
            {
                if (indent + remainder.Length() <= wrap_width)
                {
                    l.Add(new colorstring("".PadRight(indent)) + remainder);
                    break;
                }
                else
                {
                    colorstring next = new colorstring("".PadRight(indent));
                    l.Add(next);
                    int  split_idx    = remainder.LastSpaceBeforeWrap(wrap_width - indent);
                    bool remove_space = true;
                    if (split_idx == -1)                     // if there's nowhere better, just cut it off at the end of the line.
                    {
                        split_idx    = wrap_width - indent;
                        remove_space = false;
                    }
                    var split = remainder.SplitAt(split_idx, remove_space);
                    foreach (cstr s in split[0].strings)
                    {
                        next.strings.Add(s);
                    }
                    remainder = split[1];
                }
            }
        }
 public virtual List<colorstring> GetStatusBarInfo()
 {
     List<colorstring> result = new List<colorstring>();
     Color text = UI.darken_status_bar? Colors.status_darken : Color.Gray;
     if(p.Equals(UI.MapCursor)){
         text = UI.darken_status_bar? Colors.status_highlight_darken : Colors.status_highlight;
     }
     foreach(string s in name.GetWordWrappedList(17,true)){
         colorstring cs = new colorstring();
         result.Add(cs);
         if(result.Count == 1){
             cs.strings.Add(new cstr(symbol.ToString(),color));
             cs.strings.Add(new cstr(": " + s,text));
         }
         else{
             cs.strings.Add(new cstr("   " + s,text));
         }
     }
     if(name == "troll corpse"){ //gotta do this here, since TerrainFeature isn't a class.
         result.Add(new colorstring("Regenerating".PadOuter(Global.STATUS_WIDTH),text,Color.StatusEffectBar));
     }
     else{
         if(name == "troll bloodwitch corpse"){
             result.Add(new colorstring("Regenerating 3".PadOuter(Global.STATUS_WIDTH),text,Color.StatusEffectBar));
         }
     }
     return result;
 }
Example #31
0
 public int Select(string message,colorstring top_border,colorstring bottom_border,List<colorstring> strings,bool no_ask,bool no_cancel,bool easy_cancel,bool never_redraw_map,bool help_key,HelpTopic help_topic)
 {
     if(!no_ask){
         MouseUI.PushButtonMap();
     }
     MouseUI.AutomaticButtonsFromStrings = true;
     int result = -2;
     while(result == -2){
         Screen.WriteMapString(0,0,top_border);
         char letter = 'a';
         int i=1;
         foreach(colorstring s in strings){
             Screen.WriteMapString(i,0,new colorstring("[",Color.Gray,letter.ToString(),Color.Cyan,"] ",Color.Gray));
             Screen.WriteMapString(i,4,s);
             if(s.Length() < COLS-4){
                 Screen.WriteMapString(i,s.Length()+4,"".PadRight(COLS - (s.Length()+4)));
             }
             letter++;
             i++;
         }
         Screen.WriteMapString(i,0,bottom_border);
         if(i < ROWS-1){
             Screen.WriteMapString(i+1,0,"".PadRight(COLS));
         }
         if(no_ask){
             B.DisplayNow(message);
             if(!no_ask){
                 MouseUI.PopButtonMap();
             }
             MouseUI.AutomaticButtonsFromStrings = false;
             return -1;
         }
         else{
             result = GetSelection(message,strings.Count,no_cancel,easy_cancel,help_key);
             if(result == -2){
                 MouseUI.AutomaticButtonsFromStrings = false;
                 Help.DisplayHelp(help_topic);
                 MouseUI.AutomaticButtonsFromStrings = true;
             }
             else{
                 if(!never_redraw_map && result != -1){
                     M.Redraw();
                 }
                 if(!no_ask){
                     MouseUI.PopButtonMap();
                 }
                 MouseUI.AutomaticButtonsFromStrings = false;
                 return result;
             }
         }
     }
     if(!no_ask){
         MouseUI.PopButtonMap();
     }
     MouseUI.AutomaticButtonsFromStrings = false;
     return -1;
 }
Example #32
0
 public static void StatusWriteString(ref int row,colorstring s)
 {
     if(row >= status_row_cutoff){
         return;
     }
     Screen.WriteString(row,0,s);
     ++row;
 }
Example #33
0
 public int Select(string message,colorstring top_border,colorstring bottom_border,List<colorstring> strings,bool no_ask,bool no_cancel,bool easy_cancel,bool help_key,HelpTopic help_topic)
 {
     return Select(message,top_border,bottom_border,strings,no_ask,no_cancel,easy_cancel,false,help_key,help_topic);
 }
Example #34
0
 public colorstring[] SplitAt(int idx,bool remove_at_split_idx = false)
 {
     if(idx < 0){
         throw new ArgumentOutOfRangeException("idx argument " + idx.ToString() + " can't be negative.");
     }
     if(idx >= Length()){
         throw new ArgumentOutOfRangeException("idx argument " + idx.ToString() + " can't be outside the string.");
     }
     colorstring[] result = new colorstring[2];
     result[0] = new colorstring();
     result[1] = new colorstring();
     foreach(cstr s in strings){
         int len_0 = result[0].Length();
         if(len_0 < idx){
             if(len_0 + s.s.Length > idx){
                 result[0].strings.Add(new cstr(s.s.Substring(0,idx - len_0),s.color,s.bgcolor));
                 int second_start = idx - len_0;
                 if(remove_at_split_idx){
                     ++second_start;
                 }
                 if(second_start < s.s.Length){
                     result[1].strings.Add(new cstr(s.s.Substring(idx - len_0),s.color,s.bgcolor));
                 }
                 if(result[0].Length() != idx){
                     throw new Exception("whoops"); //todo, remove this after it works.
                 }
             }
             else{
                 result[0].strings.Add(s);
             }
         }
         else{
             result[1].strings.Add(s);
         }
     }
     return result;
 }
Example #35
0
 public override List<colorstring> GetStatusBarInfo()
 {
     string s_name = name;
     int s_curhp = curhp;
     int s_maxhp = maxhp;
     string s_aware = AwarenessStatus();
     if(type == ActorType.DREAM_WARRIOR_CLONE){
         if(group != null && group.Count > 0){
             foreach(Actor a in group){
                 if(a.type == ActorType.DREAM_WARRIOR){
                     s_name = a.name;
                     s_curhp = a.curhp;
                     s_maxhp = a.maxhp;
                     s_aware = a.AwarenessStatus();
                 }
             }
         }
     }
     if(type == ActorType.DREAM_SPRITE_CLONE){
         if(group != null && group.Count > 0){
             foreach(Actor a in group){
                 if(a.type == ActorType.DREAM_SPRITE){
                     s_name = a.name;
                     s_curhp = a.curhp;
                     s_maxhp = a.maxhp;
                     s_aware = a.AwarenessStatus();
                 }
             }
         }
     }
     List<colorstring> result = new List<colorstring>();
     Color text = UI.darken_status_bar? Colors.status_darken : Color.Gray;
     if(p.Equals(UI.MapCursor)){
         text = UI.darken_status_bar? Colors.status_highlight_darken : Colors.status_highlight;
     }
     foreach(string s in s_name.Capitalize().GetWordWrappedList(Global.STATUS_WIDTH - 3,true)){
         colorstring cs = new colorstring();
         result.Add(cs);
         if(result.Count == 1){
             cs.strings.Add(new cstr(symbol.ToString(),color));
             cs.strings.Add(new cstr(": " + s,text));
         }
         else{
             cs.strings.Add(new cstr("   " + s,text));
         }
     }
     string hp = ("HP: " + s_curhp.ToString() + "  (" + s_aware + ")").PadOuter(Global.STATUS_WIDTH);
     int idx = UI.GetStatusBarIndex(s_curhp,s_maxhp);
     result.Add(new colorstring(new cstr(hp.SafeSubstring(0,idx),text,Color.HealthBar),new cstr(hp.SafeSubstring(idx),text)));
     Dictionary<AttrType,Event> events = Q.StatusEvents.ContainsKey(this)? Q.StatusEvents[this] : null;
     foreach(AttrType attr in UI.displayed_statuses){
         if(HasAttr(attr) && !attr.StatusIsHidden(this)){
             int value = 1;
             int max = 1; // If no other data is found, a full bar (1/1) will be shown.
             if(!attr.StatusByStrength(this,(events != null && events.ContainsKey(attr))? events[attr] : null,ref value,ref max)){
                 if(events != null && events.ContainsKey(attr)){
                     Event e = events[attr];
                     value = e.delay + e.time_created + 100 - Q.turn;
                     max = e.delay;
                 }
             }
             int attr_idx = UI.GetStatusBarIndex(value,max);
             string attr_name = attr.StatusName(this).PadOuter(Global.STATUS_WIDTH);
             result.Add(new colorstring(new cstr(attr_name.SafeSubstring(0,attr_idx),text,Color.StatusEffectBar),new cstr(attr_name.SafeSubstring(attr_idx),text)));
         }
     }
     if(p.BoundsCheck(M.tile)){ //in rare cases, the sidebar could be updated while a burrowing enemy is still present. this prevents a crash in that situation.
         if(tile().Is(FeatureType.WEB) && !HasAttr(AttrType.BURNING,AttrType.SLIMED,AttrType.OIL_COVERED)){
             result.Add(new colorstring("Webbed".PadOuter(Global.STATUS_WIDTH),text,Color.StatusEffectBar));
         }
         if(IsSilencedHere() && !HasAttr(AttrType.SILENCED,AttrType.SILENCE_AURA)){
             result.Add(new colorstring(AttrType.SILENCED.StatusName(this).PadOuter(Global.STATUS_WIDTH),text,Color.StatusEffectBar));
         }
     }
     return result;
 }