コード例 #1
0
ファイル: Main.cs プロジェクト: ptrefall/ForaysIntoNorrendrin
 static void MainMenu()
 {
     ConsoleKeyInfo command;
     string recentname = "".PadRight(30);
     int recentdepth = -1;
     char recentwin = '-';
     string recentcause = "";
     bool on_highscore_list = false;
     MouseUI.PushButtonMap();
     while(true){
         Screen.Blank();
         int row = 8;
         int col = (Global.SCREEN_W - 28) / 2; //centering "Forays into Norrendrin x.y.z", which is 28 chars.
         Screen.WriteString(row++,col,new cstr(Color.Yellow,"Forays into Norrendrin " + Global.VERSION));
         Screen.WriteString(row++,col,new cstr(Color.Green,"".PadRight(28,'-')));
         col += 4; //recenter for menu options
         row++;
         bool saved_game = File.Exists("forays.sav");
         if(!saved_game){
             Screen.WriteString(row++,col,"[a] Start a new game");
         }
         else{
             Screen.WriteString(row++,col,"[a] Resume saved game");
         }
         Screen.WriteString(row++,col,"[b] How to play");
         Screen.WriteString(row++,col,"[c] High scores");
         Screen.WriteString(row++,col,"[d] Quit");
         for(int i=0;i<4;++i){
             Screen.WriteChar(i+row-4,col+1,new colorchar(Color.Cyan,(char)(i+'a')));
             MouseUI.CreateButton((ConsoleKey)(i + ConsoleKey.A),false,i+row-4,0,1,Global.SCREEN_W);
         }
         Screen.ResetColors();
         Screen.SetCursorPosition(Global.MAP_OFFSET_COLS,Global.MAP_OFFSET_ROWS+8);
         command = Input.ReadKey();
         switch(command.KeyChar){
         case 'a':
         {
             Global.GAME_OVER = false;
             Global.BOSS_KILLED = false;
             Global.SAVING = false;
             Global.LoadOptions();
             Game game = new Game();
             Actor.attack[ActorType.PLAYER] = new List<AttackInfo>{new AttackInfo(100,2,AttackEffect.NO_CRIT,"& hit *","& miss *","")};
             if(!saved_game){
                 game.player = new Actor(ActorType.PLAYER,"you",'@',Color.White,100,100,0,0,AttrType.HUMANOID_INTELLIGENCE);
                 game.player.inv = new List<Item>();
                 Actor.feats_in_order = new List<FeatType>();
                 Actor.spells_in_order = new List<SpellType>();
                 game.player.weapons.AddLast(new Weapon(WeaponType.SWORD));
                 game.player.weapons.AddLast(new Weapon(WeaponType.MACE));
                 game.player.weapons.AddLast(new Weapon(WeaponType.DAGGER));
                 game.player.weapons.AddLast(new Weapon(WeaponType.STAFF));
                 game.player.weapons.AddLast(new Weapon(WeaponType.BOW));
                 game.player.armors.AddLast(new Armor(ArmorType.LEATHER));
                 game.player.armors.AddLast(new Armor(ArmorType.CHAINMAIL));
                 game.player.armors.AddLast(new Armor(ArmorType.FULL_PLATE));
             }
             game.M = new Map(game);
             game.B = new Buffer(game);
             game.Q = new Queue(game);
             Map.Q = game.Q;
             Map.B = game.B;
             PhysicalObject.M = game.M;
             PhysicalObject.B = game.B;
             PhysicalObject.Q = game.Q;
             PhysicalObject.player = game.player;
             Event.Q = game.Q;
             Event.B = game.B;
             Event.M = game.M;
             Event.player = game.player;
             Fire.fire_event = null;
             Fire.burning_objects = new List<PhysicalObject>();
             if(!saved_game){
                 Actor.player_name = "";
                 if(File.Exists("name.txt")){
                     StreamReader file = new StreamReader("name.txt");
                     string base_name = file.ReadLine();
                     if(base_name == "%random%"){
                         Actor.player_name = Global.GenerateCharacterName();
                     }
                     else{
                         Actor.player_name = base_name;
                     }
                     int num = 0;
                     if(base_name != "%random%" && file.Peek() != -1){
                         num = Convert.ToInt32(file.ReadLine());
                         if(num > 1){
                             Actor.player_name = Actor.player_name + " " + Global.RomanNumeral(num);
                         }
                     }
                     file.Close();
                     if(num > 0){
                         StreamWriter fileout = new StreamWriter("name.txt",false);
                         fileout.WriteLine(base_name);
                         fileout.WriteLine(num+1);
                         fileout.Close();
                     }
                 }
                 if(Actor.player_name == ""){
                     MouseUI.PushButtonMap(MouseMode.NameEntry);
                     Screen.Blank();
                     /*for(int i=4;i<=7;++i){
                         Screen.WriteMapString(i,0,"".PadToMapSize());
                     }*/
                     string s = "";
                     int name_option = 0;
                     int c = 3;
                     while(true){
                         Screen.WriteMapString(4,c,"Enter name: ");
                         if(s == ""){
                             Screen.WriteMapString(6,c,"(Press [Enter] for a random name)".GetColorString());
                         }
                         else{
                             Screen.WriteMapString(6,c,"(Press [Enter] when finished)    ".GetColorString());
                         }
                         List<string> name_options = new List<string>{"Default: Choose a new name for each character","Static:  Use this name for every character","Legacy:  Name all future characters after this one","Random:  Name all future characters randomly"};
                         for(int i=0;i<4;++i){
                             Color option_color = Color.DarkGray;
                             if(i == name_option){
                                 option_color = Color.White;
                             }
                             Screen.WriteMapString(15+i,c,name_options[i],option_color);
                         }
                         Screen.WriteMapString(20,c,"(Press [Tab] to change naming preference)".GetColorString());
                         if(name_option != 0){
                             Screen.WriteMapString(22,c-5,"(To stop naming characters automatically, delete name.txt)",Color.Green);
                         }
                         else{
                             Screen.WriteMapString(22,c-5,"".PadToMapSize());
                         }
                         Screen.WriteMapString(4,c+12,s.PadRight(26));
                         Screen.SetCursorPosition(c + Global.MAP_OFFSET_COLS + 12 + s.Length,Global.MAP_OFFSET_ROWS + 4);
                         MouseUI.CreateButton(ConsoleKey.Enter,false,6+Global.MAP_OFFSET_ROWS,0,1,Global.SCREEN_W);
                         MouseUI.CreateButton(ConsoleKey.Tab,false,20+Global.MAP_OFFSET_ROWS,0,1,Global.SCREEN_W);
                         MouseUI.CreateButton(ConsoleKey.F21,false,15+Global.MAP_OFFSET_ROWS,0,1,Global.SCREEN_W);
                         MouseUI.CreateButton(ConsoleKey.F22,false,16+Global.MAP_OFFSET_ROWS,0,1,Global.SCREEN_W);
                         MouseUI.CreateButton(ConsoleKey.F23,false,17+Global.MAP_OFFSET_ROWS,0,1,Global.SCREEN_W);
                         MouseUI.CreateButton(ConsoleKey.F24,false,18+Global.MAP_OFFSET_ROWS,0,1,Global.SCREEN_W);
                         Screen.CursorVisible = true;
                         command = Input.ReadKey();
                         if((command.KeyChar >= '!' && command.KeyChar <= '~') || command.KeyChar == ' '){
                             if(s.Length < 26){
                                 s = s + command.KeyChar;
                             }
                         }
                         else{
                             if(command.Key == ConsoleKey.Backspace && s.Length > 0){
                                 s = s.Substring(0,s.Length-1);
                             }
                             else{
                                 if(command.Key == ConsoleKey.Escape){
                                     s = "";
                                 }
                                 else{
                                     if(command.Key == ConsoleKey.Tab){
                                         name_option = (name_option + 1) % 4;
                                     }
                                     else{
                                         if(command.Key == ConsoleKey.Enter){
                                             if(s.Length == 0){
                                                 s = Global.GenerateCharacterName();
                                             }
                                             else{
                                                 Actor.player_name = s;
                                                 break;
                                             }
                                         }
                                         else{
                                             switch(command.Key){
                                             case ConsoleKey.F21:
                                                 name_option = 0;
                                                 break;
                                             case ConsoleKey.F22:
                                                 name_option = 1;
                                                 break;
                                             case ConsoleKey.F23:
                                                 name_option = 2;
                                                 break;
                                             case ConsoleKey.F24:
                                                 name_option = 3;
                                                 break;
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                     MouseUI.PopButtonMap();
                     switch(name_option){
                     case 1: //static
                     {
                         StreamWriter fileout = new StreamWriter("name.txt",false);
                         fileout.WriteLine(s);
                         fileout.WriteLine(0);
                         fileout.Close();
                         break;
                     }
                     case 2: //legacy
                     {
                         StreamWriter fileout = new StreamWriter("name.txt",false);
                         fileout.WriteLine(s);
                         fileout.WriteLine(2);
                         fileout.Close();
                         break;
                     }
                     case 3: //random
                     {
                         StreamWriter fileout = new StreamWriter("name.txt",false);
                         fileout.WriteLine("%random%");
                         fileout.WriteLine(0);
                         fileout.Close();
                         break;
                     }
                     }
                 }
                 {
                     Event e = new Event(game.player,0,EventType.MOVE);
                     e.tiebreaker = 0;
                     game.Q.Add(e);
                 }
                 Item.GenerateUnIDedNames();
                 game.M.GenerateLevelTypes();
                 game.M.GenerateLevel();
                 game.player.UpdateRadius(0,6,true);
                 Item.Create(ConsumableType.BANDAGES,game.player).other_data = 5;
                 Item.Create(ConsumableType.FLINT_AND_STEEL,game.player).other_data = 3;
                 game.player.inv[0].revealed_by_light = true;
                 game.player.inv[1].revealed_by_light = true;
             }
             else{ //loading
                 FileStream file = new FileStream("forays.sav",FileMode.Open);
                 BinaryReader b = new BinaryReader(file);
                 Dictionary<int,PhysicalObject> id = new Dictionary<int, PhysicalObject>();
                 id.Add(0,null);
                 Dict<PhysicalObject,int> missing_target_id = new Dict<PhysicalObject, int>();
                 List<Actor> need_targets = new List<Actor>();
                 Dict<PhysicalObject,int> missing_location_id = new Dict<PhysicalObject, int>();
                 List<Actor> need_location = new List<Actor>();
                 Actor.player_name = b.ReadString();
                 game.M.current_level = b.ReadInt32();
                 game.M.level_types = new List<LevelType>();
                 for(int i=0;i<20;++i){
                     game.M.level_types.Add((LevelType)b.ReadInt32());
                 }
                 game.M.wiz_lite = b.ReadBoolean();
                 game.M.wiz_dark = b.ReadBoolean();
                 for(int i=0;i<Global.ROWS;++i){
                     for(int j=0;j<Global.COLS;++j){
                         game.M.last_seen[i,j].c = b.ReadChar();
                         game.M.last_seen[i,j].color = (Color)b.ReadInt32();
                         game.M.last_seen[i,j].bgcolor = (Color)b.ReadInt32();
                     }
                 }
                 if(game.M.current_level == 21){
                     game.M.final_level_cultist_count = new int[5];
                     for(int i=0;i<5;++i){
                         game.M.final_level_cultist_count[i] = b.ReadInt32();
                     }
                     game.M.final_level_demon_count = b.ReadInt32();
                     game.M.final_level_clock = b.ReadInt32();
                 }
                 Actor.feats_in_order = new List<FeatType>();
                 Actor.spells_in_order = new List<SpellType>();
                 int num_featlist = b.ReadInt32();
                 for(int i=0;i<num_featlist;++i){
                     Actor.feats_in_order.Add((FeatType)b.ReadInt32());
                 }
                 int num_spelllist = b.ReadInt32();
                 for(int i=0;i<num_spelllist;++i){
                     Actor.spells_in_order.Add((SpellType)b.ReadInt32());
                 }
                 int num_actor_tiebreakers = b.ReadInt32();
                 Actor.tiebreakers = new List<Actor>(num_actor_tiebreakers);
                 for(int i=0;i<num_actor_tiebreakers;++i){
                     int ID = b.ReadInt32();
                     if(ID != 0){
                         Actor a = new Actor();
                         id.Add(ID,a);
                         a.row = b.ReadInt32();
                         a.col = b.ReadInt32();
                         if(a.row >= 0 && a.row < Global.ROWS && a.col >= 0 && a.col < Global.COLS){
                             game.M.actor[a.row,a.col] = a;
                         }
                         Actor.tiebreakers.Add(a);
                         a.name = b.ReadString();
                         a.the_name = b.ReadString();
                         a.a_name = b.ReadString();
                         a.symbol = b.ReadChar();
                         a.color = (Color)b.ReadInt32();
                         a.type = (ActorType)b.ReadInt32();
                         if(a.type == ActorType.PLAYER){
                             game.player = a;
                             Actor.player = a;
                             Buffer.player = a;
                             Item.player = a;
                             Map.player = a;
                             Event.player = a;
                             Tile.player = a;
                         }
                         a.maxhp = b.ReadInt32();
                         a.curhp = b.ReadInt32();
                         a.maxmp = b.ReadInt32();
                         a.curmp = b.ReadInt32();
                         a.speed = b.ReadInt32();
                         a.light_radius = b.ReadInt32();
                         int target_ID = b.ReadInt32();
                         if(id.ContainsKey(target_ID)){
                             a.target = (Actor)id[target_ID];
                         }
                         else{
                             a.target = null;
                             need_targets.Add(a);
                             missing_target_id[a] = target_ID;
                         }
                         int num_items = b.ReadInt32();
                         for(int j=0;j<num_items;++j){
                             int item_id = b.ReadInt32();
                             if(item_id != 0){
                                 Item item = new Item();
                                 id.Add(item_id,item);
                                 item.name = b.ReadString();
                                 item.the_name = b.ReadString();
                                 item.a_name = b.ReadString();
                                 item.symbol = b.ReadChar();
                                 item.color = (Color)b.ReadInt32();
                                 item.light_radius = b.ReadInt32();
                                 item.type = (ConsumableType)b.ReadInt32();
                                 item.quantity = b.ReadInt32();
                                 item.charges = b.ReadInt32();
                                 item.other_data = b.ReadInt32();
                                 item.ignored = b.ReadBoolean();
                                 item.do_not_stack = b.ReadBoolean();
                                 item.revealed_by_light = b.ReadBoolean();
                                 a.inv.Add(item);
                             }
                         }
                         int num_attrs = b.ReadInt32();
                         for(int j=0;j<num_attrs;++j){
                             AttrType t = (AttrType)b.ReadInt32();
                             a.attrs[t] = b.ReadInt32();
                         }
                         int num_skills = b.ReadInt32();
                         for(int j=0;j<num_skills;++j){
                             SkillType t = (SkillType)b.ReadInt32();
                             a.skills[t] = b.ReadInt32();
                         }
                         int num_feats = b.ReadInt32();
                         for(int j=0;j<num_feats;++j){
                             FeatType t = (FeatType)b.ReadInt32();
                             a.feats[t] = b.ReadBoolean();
                         }
                         int num_spells = b.ReadInt32();
                         for(int j=0;j<num_spells;++j){
                             SpellType t = (SpellType)b.ReadInt32();
                             a.spells[t] = b.ReadBoolean();
                         }
                         a.exhaustion = b.ReadInt32();
                         a.time_of_last_action = b.ReadInt32();
                         a.recover_time = b.ReadInt32();
                         int path_count = b.ReadInt32();
                         for(int j=0;j<path_count;++j){
                             int path_row = b.ReadInt32();
                             int path_col = b.ReadInt32();
                             a.path.Add(new pos(path_row,path_col));
                         }
                         int location_ID = b.ReadInt32();
                         if(id.ContainsKey(location_ID)){
                             a.target_location = (Tile)id[location_ID];
                         }
                         else{
                             a.target_location = null;
                             need_location.Add(a);
                             missing_location_id[a] = location_ID;
                         }
                         a.player_visibility_duration = b.ReadInt32();
                         int num_weapons = b.ReadInt32();
                         for(int j=0;j<num_weapons;++j){
                             Weapon w = new Weapon(WeaponType.NO_WEAPON);
                             w.type = (WeaponType)b.ReadInt32();
                             w.enchantment = (EnchantmentType)b.ReadInt32();
                             int num_statuses = b.ReadInt32();
                             for(int k=0;k<num_statuses;++k){
                                 EquipmentStatus st = (EquipmentStatus)b.ReadInt32();
                                 bool has_st = b.ReadBoolean();
                                 w.status[st] = has_st;
                             }
                             a.weapons.AddLast(w);
                         }
                         int num_armors = b.ReadInt32();
                         for(int j=0;j<num_armors;++j){
                             Armor ar = new Armor(ArmorType.NO_ARMOR);
                             ar.type = (ArmorType)b.ReadInt32();
                             ar.enchantment = (EnchantmentType)b.ReadInt32();
                             int num_statuses = b.ReadInt32();
                             for(int k=0;k<num_statuses;++k){
                                 EquipmentStatus st = (EquipmentStatus)b.ReadInt32();
                                 bool has_st = b.ReadBoolean();
                                 ar.status[st] = has_st;
                             }
                             a.armors.AddLast(ar);
                         }
                         int num_magic_trinkets = b.ReadInt32();
                         for(int j=0;j<num_magic_trinkets;++j){
                             a.magic_trinkets.Add((MagicTrinketType)b.ReadInt32());
                         }
                     }
                     else{
                         Actor.tiebreakers.Add(null);
                     }
                 }
                 int num_groups = b.ReadInt32();
                 for(int i=0;i<num_groups;++i){
                     List<Actor> group = new List<Actor>();
                     int group_size = b.ReadInt32();
                     for(int j=0;j<group_size;++j){
                         group.Add((Actor)id[b.ReadInt32()]);
                     }
                     foreach(Actor a in group){
                         a.group = group;
                     }
                 }
                 int num_tiles = b.ReadInt32();
                 for(int i=0;i<num_tiles;++i){
                     Tile t = new Tile();
                     int ID = b.ReadInt32();
                     id.Add(ID,t);
                     t.row = b.ReadInt32();
                     t.col = b.ReadInt32();
                     game.M.tile[t.row,t.col] = t;
                     t.name = b.ReadString();
                     t.the_name = b.ReadString();
                     t.a_name = b.ReadString();
                     t.symbol = b.ReadChar();
                     t.color = (Color)b.ReadInt32();
                     t.light_radius = b.ReadInt32();
                     t.type = (TileType)b.ReadInt32();
                     t.passable = b.ReadBoolean();
                     t.SetInternalOpacity(b.ReadBoolean());
                     t.SetInternalSeen(b.ReadBoolean());
                     //t.seen = b.ReadBoolean();
                     t.revealed_by_light = b.ReadBoolean();
                     t.solid_rock = b.ReadBoolean();
                     t.light_value = b.ReadInt32();
                     t.direction_exited = b.ReadInt32();
                     if(b.ReadBoolean()){ //indicates a toggles_into value
                         t.toggles_into = (TileType)b.ReadInt32();
                     }
                     else{
                         t.toggles_into = null;
                     }
                     int item_id = b.ReadInt32();
                     if(item_id != 0){
                         t.inv = new Item();
                         id.Add(item_id,t.inv);
                         t.inv.name = b.ReadString();
                         t.inv.the_name = b.ReadString();
                         t.inv.a_name = b.ReadString();
                         t.inv.symbol = b.ReadChar();
                         t.inv.color = (Color)b.ReadInt32();
                         t.inv.light_radius = b.ReadInt32();
                         t.inv.type = (ConsumableType)b.ReadInt32();
                         t.inv.quantity = b.ReadInt32();
                         t.inv.charges = b.ReadInt32();
                         t.inv.other_data = b.ReadInt32();
                         t.inv.ignored = b.ReadBoolean();
                         t.inv.do_not_stack = b.ReadBoolean();
                         t.inv.revealed_by_light = b.ReadBoolean();
                     }
                     else{
                         t.inv = null;
                     }
                     int num_features = b.ReadInt32();
                     for(int j=0;j<num_features;++j){
                         t.features.Add((FeatureType)b.ReadInt32());
                     }
                 }
                 foreach(Actor a in need_targets){
                     if(id.ContainsKey(missing_target_id[a])){
                         a.target = (Actor)id[missing_target_id[a]];
                     }
                     else{
                         throw new Exception("Error: some actors weren't loaded(1). ");
                     }
                 }
                 foreach(Actor a in need_location){
                     if(id.ContainsKey(missing_location_id[a])){
                         a.target_location = (Tile)id[missing_location_id[a]];
                     }
                     else{
                         throw new Exception("Error: some tiles weren't loaded(2). ");
                     }
                 }
                 int game_turn = b.ReadInt32();
                 game.Q.turn = -1; //this keeps events from being added incorrectly to the front of the queue while loading. turn is set correctly after events are all loaded.
                 int num_events = b.ReadInt32();
                 for(int i=0;i<num_events;++i){
                     Event e = new Event();
                     if(b.ReadBoolean()){ //if true, this is an item that doesn't exist elsewhere, so grab all its info.
                         int item_id = b.ReadInt32();
                         if(item_id != 0){
                             Item item = new Item();
                             id.Add(item_id,item);
                             item.name = b.ReadString();
                             item.the_name = b.ReadString();
                             item.a_name = b.ReadString();
                             item.symbol = b.ReadChar();
                             item.color = (Color)b.ReadInt32();
                             item.light_radius = b.ReadInt32();
                             item.type = (ConsumableType)b.ReadInt32();
                             item.quantity = b.ReadInt32();
                             item.charges = b.ReadInt32();
                             item.other_data = b.ReadInt32();
                             item.ignored = b.ReadBoolean();
                             item.do_not_stack = b.ReadBoolean();
                             item.revealed_by_light = b.ReadBoolean();
                             e.target = item;
                         }
                     }
                     else{
                         int target_ID = b.ReadInt32();
                         if(id.ContainsKey(target_ID)){
                             e.target = id[target_ID];
                         }
                         else{
                             throw new Exception("Error: some tiles/actors weren't loaded(4). ");
                         }
                     }
                     int area_count = b.ReadInt32();
                     for(int j=0;j<area_count;++j){
                         if(e.area == null){
                             e.area = new List<Tile>();
                         }
                         int tile_ID = b.ReadInt32();
                         if(id.ContainsKey(tile_ID)){
                             e.area.Add((Tile)id[tile_ID]);
                         }
                         else{
                             throw new Exception("Error: some tiles weren't loaded(5). ");
                         }
                     }
                     e.delay = b.ReadInt32();
                     e.type = (EventType)b.ReadInt32();
                     e.attr = (AttrType)b.ReadInt32();
                     e.feature = (FeatureType)b.ReadInt32();
                     e.value = b.ReadInt32();
                     e.secondary_value = b.ReadInt32();
                     e.msg = b.ReadString();
                     int objs_count = b.ReadInt32();
                     for(int j=0;j<objs_count;++j){
                         if(e.msg_objs == null){
                             e.msg_objs = new List<PhysicalObject>();
                         }
                         int obj_ID = b.ReadInt32();
                         if(id.ContainsKey(obj_ID)){
                             e.msg_objs.Add(id[obj_ID]);
                         }
                         else{
                             throw new Exception("Error: some actors/tiles weren't loaded(6). ");
                         }
                     }
                     e.time_created = b.ReadInt32();
                     e.dead = b.ReadBoolean();
                     e.tiebreaker = b.ReadInt32();
                     game.Q.Add(e);
                     if(e.type == EventType.FIRE && !e.dead){
                         Fire.fire_event = e;
                     }
                 }
                 game.Q.turn = game_turn;
                 foreach(Event e in game.Q.list){
                     if(e.type == EventType.MOVE && e.target == game.player){
                         game.Q.current_event = e;
                         break;
                     }
                 }
                 int num_footsteps = b.ReadInt32();
                 for(int i=0;i<num_footsteps;++i){
                     int step_row = b.ReadInt32();
                     int step_col = b.ReadInt32();
                     Actor.footsteps.Add(new pos(step_row,step_col));
                 }
                 int num_prev_footsteps = b.ReadInt32();
                 for(int i=0;i<num_prev_footsteps;++i){
                     int step_row = b.ReadInt32();
                     int step_col = b.ReadInt32();
                     Actor.previous_footsteps.Add(new pos(step_row,step_col));
                 }
                 Actor.interrupted_path.row = b.ReadInt32();
                 Actor.interrupted_path.col = b.ReadInt32();
                 UI.viewing_commands_idx = b.ReadInt32();
                 game.M.feat_gained_this_level = b.ReadBoolean();
                 game.M.extra_danger = b.ReadInt32();
                 int num_unIDed = b.ReadInt32();
                 for(int i=0;i<num_unIDed;++i){
                     ConsumableType ct = (ConsumableType)b.ReadInt32();
                     string s = b.ReadString();
                     Item.unIDed_name[ct] = s;
                 }
                 int num_IDed = b.ReadInt32();
                 for(int i=0;i<num_IDed;++i){
                     ConsumableType ct = (ConsumableType)b.ReadInt32();
                     bool IDed = b.ReadBoolean();
                     Item.identified[ct] = IDed;
                 }
                 int num_item_colors = b.ReadInt32();
                 for(int i=0;i<num_item_colors;++i){
                     ConsumableType ct = (ConsumableType)b.ReadInt32();
                     Item.proto[ct].color = (Color)b.ReadInt32();
                 }
                 int num_burning = b.ReadInt32();
                 for(int i=0;i<num_burning;++i){
                     int obj_ID = b.ReadInt32();
                     if(id.ContainsKey(obj_ID)){
                         Fire.burning_objects.Add(id[obj_ID]);
                     }
                     else{
                         throw new Exception("Error: some actors/tiles weren't loaded(7). ");
                     }
                 }
                 string[] messages = new string[Buffer.log_length];
                 int num_messages = b.ReadInt32();
                 for(int i=0;i<num_messages;++i){
                     messages[i] = b.ReadString();
                 }
                 for(int i=num_messages;i<Buffer.log_length;++i){
                     messages[i] = "";
                 }
                 int message_pos = b.ReadInt32();
                 game.B.LoadMessagesAndPosition(messages,message_pos,num_messages);
                 b.Close();
                 file.Close();
                 File.Delete("forays.sav");
                 Tile.Feature(FeatureType.TELEPORTAL).color = Item.Prototype(ConsumableType.TELEPORTAL).color;
                 game.M.CalculatePoppyDistanceMap();
                 game.M.UpdateDangerValues();
                 if(game.M.aesthetics == null) game.M.aesthetics = new PosArray<AestheticFeature>(Global.ROWS,Global.COLS); //todo! save these properly
                 if(game.M.dungeon_description == null){
                     game.M.dungeon_description = new PosArray<string>(Global.ROWS,Global.COLS);
                     for(int ii=0;ii<Global.ROWS;++ii){
                         for(int jj=0;jj<Global.COLS;++jj){
                             game.M.dungeon_description[ii,jj] = "";
                         }
                     }
                 } //todo fixme hack save properly
             }
             Game.NoClose = true;
             MouseUI.PushButtonMap(MouseMode.Map);
             MouseUI.CreateStatsButtons();
             try{
                 while(!Global.GAME_OVER){ game.Q.Pop(); }
             }
             catch(Exception e){
                 StreamWriter fileout = new StreamWriter("error.txt",false);
                 fileout.WriteLine(e.Message);
                 fileout.WriteLine(e.StackTrace);
                 fileout.Close();
                 MouseUI.IgnoreMouseMovement = true;
                 MouseUI.IgnoreMouseClicks = true;
                 Screen.CursorVisible = false;
                 Screen.Blank();
                 Screen.WriteString(12,0,"  An error has occured. See error.txt for more details. Press any key to quit.".PadOuter(Global.SCREEN_W));
                 Input.ReadKey();
                 Global.Quit();
             }
             MouseUI.PopButtonMap();
             MouseUI.IgnoreMouseMovement = false;
             Game.NoClose = false;
             Screen.CursorVisible = false;
             Global.SaveOptions();
             recentdepth = game.M.current_level;
             recentname = Actor.player_name;
             recentwin = Global.BOSS_KILLED? 'W' : '-';
             recentcause = Global.KILLED_BY;
             on_highscore_list = false;
             if(!Global.SAVING){
                 List<string> newhighscores = new List<string>();
                 int num_scores = 0;
                 bool added = false;
                 if(File.Exists("highscore.txt")){
                     StreamReader file = new StreamReader("highscore.txt");
                     string s = "";
                     while(s.Length < 2 || s.Substring(0,2) != "--"){
                         s = file.ReadLine();
                         newhighscores.Add(s);
                     }
                     s = "!!";
                     while(s.Substring(0,2) != "--"){
                         s = file.ReadLine();
                         if(s.Substring(0,2) == "--"){
                             if(!added && num_scores < Global.HIGH_SCORES){
                                 char symbol = Global.BOSS_KILLED? 'W' : '-';
                                 newhighscores.Add(game.M.current_level.ToString() + " " + symbol + " " + Actor.player_name + " -- " + Global.KILLED_BY);
                                 on_highscore_list = true;
                             }
                             newhighscores.Add(s);
                             break;
                         }
                         if(num_scores < Global.HIGH_SCORES){
                             string[] tokens = s.Split(' ');
                             int dlev = Convert.ToInt32(tokens[0]);
                             if(dlev < game.M.current_level || (dlev == game.M.current_level && Global.BOSS_KILLED)){
                                 if(!added){
                                     char symbol = Global.BOSS_KILLED? 'W' : '-';
                                     newhighscores.Add(game.M.current_level.ToString() + " " + symbol + " " + Actor.player_name + " -- " + Global.KILLED_BY);
                                     ++num_scores;
                                     added = true;
                                     on_highscore_list = true;
                                 }
                                 if(num_scores < Global.HIGH_SCORES){
                                     newhighscores.Add(s);
                                     ++num_scores;
                                 }
                             }
                             else{
                                 newhighscores.Add(s);
                                 ++num_scores;
                             }
                         }
                     }
                     file.Close();
                 }
                 else{
                     newhighscores.Add("High scores:");
                     newhighscores.Add("--");
                     char symbol = Global.BOSS_KILLED? 'W' : '-';
                     newhighscores.Add(game.M.current_level.ToString() + " " + symbol + " " + Actor.player_name + " -- " + Global.KILLED_BY);
                     newhighscores.Add("--");
                     on_highscore_list = true;
                 }
                 StreamWriter fileout = new StreamWriter("highscore.txt",false);
                 foreach(string str in newhighscores){
                     fileout.WriteLine(str);
                 }
                 fileout.Close();
             }
             if(!Global.QUITTING && !Global.SAVING){
                 GameOverScreen(game);
             }
             break;
         }
         case 'b':
         {
             Help.DisplayHelp();
             break;
         }
         case 'c':
         {
             MouseUI.PushButtonMap();
             Screen.Blank();
             List<string> scores = new List<string>();
             {
                 if(!File.Exists("highscore.txt")){
                     List<string> newhighscores = new List<string>();
                     newhighscores.Add("High scores:");
                     newhighscores.Add("--");
                     newhighscores.Add("--");
                     StreamWriter fileout = new StreamWriter("highscore.txt",false);
                     foreach(string str in newhighscores){
                         fileout.WriteLine(str);
                     }
                     fileout.Close();
                 }
                 StreamReader file = new StreamReader("highscore.txt");
                 string s = "";
                 while(s.Length < 2 || s.Substring(0,2) != "--"){
                     s = file.ReadLine();
                 }
                 s = "!!";
                 while(s.Substring(0,2) != "--"){
                     s = file.ReadLine();
                     if(s.Substring(0,2) == "--" || scores.Count == Global.HIGH_SCORES){
                         break;
                     }
                     else{
                         scores.Add(s);
                     }
                 }
                 file.Close();
             }
             if(scores.Count == Global.HIGH_SCORES && !on_highscore_list && recentdepth != -1){
                 scores.RemoveLast();
                 scores.Add(recentdepth.ToString() + " " + recentwin + " " + recentname + " -- " + recentcause);
             }
             int longest_name = 0;
             int longest_cause = 0;
             foreach(string s in scores){
                 string[] tokens = s.Split(' ');
                 string name_and_cause_of_death = s.Substring(tokens[0].Length + 3);
                 int idx = name_and_cause_of_death.LastIndexOf(" -- ");
                 string name = name_and_cause_of_death.Substring(0,idx);
                 string cause_of_death = name_and_cause_of_death.Substring(idx+4);
                 if(name.Length > longest_name){
                     longest_name = name.Length;
                 }
                 if(cause_of_death.Length > longest_cause){
                     longest_cause = cause_of_death.Length;
                 }
             }
             int total_spaces = Global.SCREEN_W - (longest_name + 4 + longest_cause); //max name length is 26 and max cause length is 42. Depth is the '4'.
             int half_spaces = total_spaces / 2;
             int half_spaces_offset = (total_spaces+1) / 2;
             int spaces1 = half_spaces / 4;
             int spaces2 = half_spaces - (half_spaces / 4);
             int spaces3 = half_spaces_offset - (half_spaces_offset / 4);
             int name_middle = spaces1 + longest_name/2;
             int depth_middle = spaces1 + spaces2 + longest_name + 1;
             int cause_middle = spaces1 + spaces2 + spaces3 + longest_name + 4 + (longest_cause-1)/2;
             Color primary = Color.Green;
             Color recent = Color.Cyan;
             Screen.WriteString(0,(Global.SCREEN_W - 11) / 2,new cstr("HIGH SCORES",Color.Yellow)); //"HIGH SCORES" has width 11
             Screen.WriteString(1,(Global.SCREEN_W - 11) / 2,new cstr("-----------",Color.Cyan));
             Screen.WriteString(2,name_middle-4,new cstr("Character",primary));
             Screen.WriteString(2,depth_middle-2,new cstr("Depth",primary));
             Screen.WriteString(2,cause_middle-6,new cstr("Cause of death",primary));
             bool written_recent = false;
             int line = 3;
             foreach(string s in scores){
                 if(line >= Global.SCREEN_H){
                     break;
                 }
                 string[] tokens = s.Split(' ');
                 int dlev = Convert.ToInt32(tokens[0]);
                 char winning = tokens[1][0];
                 string name_and_cause_of_death = s.Substring(tokens[0].Length + 3);
                 int idx = name_and_cause_of_death.LastIndexOf(" -- ");
                 string name = name_and_cause_of_death.Substring(0,idx);
                 string cause_of_death = name_and_cause_of_death.Substring(idx+4);
                 string cause_capitalized = cause_of_death.Substring(0,1).ToUpper() + cause_of_death.Substring(1);
                 Color current_color = Color.White;
                 if(!written_recent && name == recentname && dlev == recentdepth && winning == recentwin && cause_of_death == recentcause){
                     current_color = recent;
                     written_recent = true;
                 }
                 else{
                     current_color = Color.White;
                 }
                 Screen.WriteString(line,spaces1,new cstr(name,current_color));
                 Screen.WriteString(line,spaces1 + spaces2 + longest_name,new cstr(dlev.ToString().PadLeft(2),current_color));
                 Screen.WriteString(line,spaces1 + spaces2 + spaces3 + longest_name + 4,new cstr(cause_capitalized,current_color));
                 if(winning == 'W'){
                     Screen.WriteString(line,spaces1 + spaces2 + longest_name + 3,new cstr("W",Color.Yellow));
                 }
                 ++line;
             }
             Input.ReadKey();
             MouseUI.PopButtonMap();
             break;
         }
         case 'd':
             Global.Quit();
             break;
         default:
             break;
         }
         if(Global.QUITTING){
             Global.Quit();
         }
     }
 }