private static void SaveItem(Item i, BinaryWriter b, IDMethod get_id)
 {
     b.Write(get_id(i));
     b.Write(i.name);
     b.Write(i.the_name);
     b.Write(i.a_name);
     b.Write(i.symbol);
     b.Write((int)i.color);
     b.Write(i.light_radius);
     b.Write((int)i.type);
     b.Write(i.quantity);
     b.Write(i.charges);
     b.Write(i.other_data);
     b.Write(i.ignored);
     b.Write(i.do_not_stack);
     b.Write(i.revealed_by_light);
 }
        public static void SaveGame(Buffer B, Map M, Queue Q)        //games are loaded in Main.cs
        {
            FileStream   file = new FileStream("forays.sav", FileMode.CreateNew);
            BinaryWriter b    = new BinaryWriter(file);
            Dictionary <PhysicalObject, int> id = new Dictionary <PhysicalObject, int>();
            int      next_id = 1;
            IDMethod GetID   = delegate(PhysicalObject o){
                if (o == null)
                {
                    return(0);
                }
                if (!id.ContainsKey(o))
                {
                    id.Add(o, next_id);
                    ++next_id;
                }
                return(id[o]);
            };

            b.Write(Actor.player_name);
            b.Write(M.current_level);
            for (int i = 0; i < 20; ++i)
            {
                b.Write((int)M.level_types[i]);
            }
            b.Write(M.wiz_lite);
            b.Write(M.wiz_dark);
            for (int i = 0; i < ROWS; ++i)
            {
                for (int j = 0; j < COLS; ++j)
                {
                    b.Write(M.last_seen[i, j].c);
                    b.Write((int)M.last_seen[i, j].color);
                    b.Write((int)M.last_seen[i, j].bgcolor);
                }
            }
            if (M.current_level == 21)
            {
                for (int i = 0; i < 5; ++i)
                {
                    b.Write(M.final_level_cultist_count[i]);
                }
                b.Write(M.final_level_demon_count);
                b.Write(M.final_level_clock);
            }
            b.Write(Actor.feats_in_order.Count);
            foreach (FeatType ft in Actor.feats_in_order)
            {
                b.Write((int)ft);
            }
            b.Write(Actor.spells_in_order.Count);
            foreach (SpellType sp in Actor.spells_in_order)
            {
                b.Write((int)sp);
            }
            List <List <Actor> > groups = new List <List <Actor> >();

            b.Write(Actor.tiebreakers.Count);
            foreach (Actor a in Actor.tiebreakers)
            {
                if (a == null)
                {
                    b.Write(GetID(a));
                }
                else
                {
                    SaveActor(a, b, groups, GetID);
                }
            }
            b.Write(groups.Count);
            foreach (List <Actor> group in groups)
            {
                b.Write(group.Count);
                foreach (Actor a in group)
                {
                    b.Write(GetID(a));
                }
            }
            b.Write(M.AllTiles().Count);
            foreach (Tile t in M.AllTiles())
            {
                b.Write(GetID(t));
                b.Write(t.row);
                b.Write(t.col);
                b.Write(t.name);
                b.Write(t.the_name);
                b.Write(t.a_name);
                b.Write(t.symbol);
                b.Write((int)t.color);
                b.Write(t.light_radius);
                b.Write((int)t.type);
                b.Write(t.passable);
                b.Write(t.GetInternalOpacity());
                b.Write(t.seen);
                b.Write(t.revealed_by_light);
                b.Write(t.solid_rock);
                b.Write(t.light_value);
                b.Write(t.direction_exited);
                if (t.toggles_into.HasValue)
                {
                    b.Write(true);
                    b.Write((int)t.toggles_into.Value);
                }
                else
                {
                    b.Write(false);
                }
                if (t.inv != null)
                {
                    SaveItem(t.inv, b, GetID);

                    /*b.Write(t.inv.name);
                     * b.Write(t.inv.the_name);
                     * b.Write(t.inv.a_name);
                     * b.Write(t.inv.symbol);
                     * b.Write((int)t.inv.color);
                     * b.Write(t.inv.light_radius);
                     * b.Write((int)t.inv.type);
                     * b.Write(t.inv.quantity);
                     * b.Write(t.inv.charges);
                     * b.Write(t.inv.other_data);
                     * b.Write(t.inv.ignored);
                     * b.Write(t.inv.do_not_stack);
                     * b.Write(t.inv.revealed_by_light);*/
                }
                else
                {
                    b.Write(GetID(null));
                }
                b.Write(t.features.Count);
                foreach (FeatureType f in t.features)
                {
                    b.Write((int)f);
                }
            }
            b.Write(Q.turn);
            int num_events = 0;

            foreach (Event e in Q.list)
            {
                if (!e.dead)
                {
                    ++num_events;
                }
            }
            b.Write(num_events);
            //b.Write(Q.list.Count);
            foreach (Event e in Q.list)
            {
                if (e.dead)
                {
                    continue;
                }
                if (e.target is Item && !id.ContainsKey(e.target))                 //in this case, we have an item that isn't on the map or in an inventory, so we need to write all its info.
                {
                    b.Write(true);
                    SaveItem(e.target as Item, b, GetID);
                }
                else
                {
                    b.Write(false);
                    b.Write(GetID(e.target));                     //in every other case, the target should already be accounted for.
                }
                if (e.area == null)
                {
                    b.Write(0);
                }
                else
                {
                    b.Write(e.area.Count);
                    foreach (Tile t in e.area)
                    {
                        b.Write(GetID(t));
                    }
                }
                b.Write(e.delay);
                b.Write((int)e.type);
                b.Write((int)e.attr);
                b.Write((int)e.feature);
                b.Write(e.value);
                b.Write(e.secondary_value);
                b.Write(e.msg);
                if (e.msg_objs == null)
                {
                    b.Write(0);
                }
                else
                {
                    b.Write(e.msg_objs.Count);
                    foreach (PhysicalObject o in e.msg_objs)
                    {
                        b.Write(GetID(o));
                    }
                }
                b.Write(e.time_created);
                b.Write(e.dead);
                b.Write(e.tiebreaker);
            }
            b.Write(Actor.footsteps.Count);
            foreach (pos p in Actor.footsteps)
            {
                b.Write(p.row);
                b.Write(p.col);
            }
            b.Write(Actor.previous_footsteps.Count);
            foreach (pos p in Actor.previous_footsteps)
            {
                b.Write(p.row);
                b.Write(p.col);
            }
            b.Write(Actor.interrupted_path.row);
            b.Write(Actor.interrupted_path.col);
            b.Write(Actor.viewing_more_commands);
            b.Write(M.feat_gained_this_level);
            b.Write(M.extra_danger);
            for (int i = 0; i < 5; ++i)
            {
                b.Write(Map.shrine_locations[i].row);
                b.Write(Map.shrine_locations[i].col);
            }
            b.Write(Item.unIDed_name.Count);
            foreach (ConsumableType ct in Item.unIDed_name.Keys)
            {
                b.Write((int)ct);
                b.Write(Item.unIDed_name[ct]);
            }
            b.Write(Item.identified.d.Count);
            foreach (ConsumableType ct in Item.identified.d.Keys)
            {
                b.Write((int)ct);
                b.Write(Item.identified[ct]);
            }
            b.Write(Item.proto.Keys.Count);
            foreach (ConsumableType ct in Item.proto.Keys)
            {
                b.Write((int)ct);
                b.Write((int)Item.proto[ct].color);
            }
            b.Write(Fire.burning_objects.Count);
            foreach (PhysicalObject o in Fire.burning_objects)
            {
                b.Write(GetID(o));
            }
            int num_messages = B.SaveNumMessages();

            b.Write(num_messages);
            string[] messages = B.SaveMessages();
            for (int i = 0; i < num_messages; ++i)
            {
                b.Write(messages[i]);
            }
            b.Write(B.SavePosition());
            b.Close();
            file.Close();
        }
        private static void SaveActor(Actor a, BinaryWriter b, List <List <Actor> > groups, IDMethod get_id)
        {
            b.Write(get_id(a));
            b.Write(a.row);
            b.Write(a.col);
            b.Write(a.name);
            b.Write(a.the_name);
            b.Write(a.a_name);
            b.Write(a.symbol);
            b.Write((int)a.color);
            b.Write((int)a.type);
            b.Write(a.maxhp);
            b.Write(a.curhp);
            b.Write(a.maxmp);
            b.Write(a.curmp);
            b.Write(a.speed);
            b.Write(a.light_radius);
            b.Write(get_id(a.target));
            b.Write(a.inv.Count);
            foreach (Item i in a.inv)
            {
                SaveItem(i, b, get_id);

                /*b.Write(i.name);
                 * b.Write(i.the_name);
                 * b.Write(i.a_name);
                 * b.Write(i.symbol);
                 * b.Write((int)i.color);
                 * b.Write(i.light_radius);
                 * b.Write((int)i.type);
                 * b.Write(i.quantity);
                 * b.Write(i.charges);
                 * b.Write(i.other_data);
                 * b.Write(i.ignored);
                 * b.Write(i.do_not_stack);
                 * b.Write(i.revealed_by_light);*/
            }
            b.Write(a.attrs.d.Count);
            foreach (AttrType at in a.attrs.d.Keys)
            {
                b.Write((int)at);
                b.Write(a.attrs[at]);
            }
            b.Write(a.skills.d.Count);
            foreach (SkillType st in a.skills.d.Keys)
            {
                b.Write((int)st);
                b.Write(a.skills[st]);
            }
            b.Write(a.feats.d.Count);
            foreach (FeatType ft in a.feats.d.Keys)
            {
                b.Write((int)ft);
                b.Write(a.feats[ft]);
            }
            b.Write(a.spells.d.Count);
            foreach (SpellType sp in a.spells.d.Keys)
            {
                b.Write((int)sp);
                b.Write(a.spells[sp]);
            }
            b.Write(a.exhaustion);
            b.Write(a.time_of_last_action);
            b.Write(a.recover_time);
            b.Write(a.path.Count);
            foreach (pos p in a.path)
            {
                b.Write(p.row);
                b.Write(p.col);
            }
            b.Write(get_id(a.target_location));
            b.Write(a.player_visibility_duration);
            if (a.group != null && groups != null)
            {
                groups.AddUnique(a.group);
            }
            b.Write(a.weapons.Count);
            foreach (Weapon w in a.weapons)
            {
                b.Write((int)w.type);
                b.Write((int)w.enchantment);
                b.Write(w.status.d.Count);
                foreach (EquipmentStatus st in w.status.d.Keys)
                {
                    b.Write((int)st);
                    b.Write(w.status[st]);
                }
            }
            b.Write(a.armors.Count);
            foreach (Armor ar in a.armors)
            {
                b.Write((int)ar.type);
                b.Write((int)ar.enchantment);
                b.Write(ar.status.d.Count);
                foreach (EquipmentStatus st in ar.status.d.Keys)
                {
                    b.Write((int)st);
                    b.Write(ar.status[st]);
                }
            }
            b.Write(a.magic_trinkets.Count);
            foreach (MagicTrinketType m in a.magic_trinkets)
            {
                b.Write((int)m);
            }
        }