internal static Ship Load(NounCollection shelf, string id, Sector sector, Universe u) { var s = new Ship(sector, u); var noun = shelf[id]; s.ID = id; s.RealName = noun["name"][0]; s.Owner = u.Players.SingleOrDefault(p => p.TeamName == noun["owner"][0]); if (s.Owner == null) { s.Owner = u.AddPlayer(noun["owner"][0]); } if (shelf.Contains("Vnotes")) { if (shelf["Vnotes"].Contains("Name:" + s.ID)) { s.DisplayName = shelf["Vnotes"]["Name:" + s.ID][0]; } else if (s.RealName.StartsWith(s.Owner.TeamName + " ")) { s.DisplayName = s.RealName.Substring(s.Owner.TeamName.Length + 1); } else { s.DisplayName = s.RealName; } } else if (s.RealName.StartsWith(s.Owner.TeamName + " ")) { s.DisplayName = s.RealName.Substring(s.Owner.TeamName.Length + 1); } else { s.DisplayName = s.RealName; } s.IsMothership = noun["isMothership"][0] == 1; s.PreviousSector = u.Sectors.SingleOrDefault(sec => { if (noun.Contains("previousLocation") && noun["previousLocation"].Count > 0) { return(noun["previousLocation"][0] == sec.ID); } return(false); }); if (s.IsOurs) { s.Components = new Resources { Hull = noun["hull"][0], Weapons = noun["weapon"][0], Thrusters = noun["thruster"][0], Shields = noun["shield"][0], }; s.Size = (int)(Math.Sqrt((int)noun["hull"][0] + (int)noun["weapon"][0] + (int)noun["thruster"][0] + (int)noun["shield"][0])); s.IsArmed = noun["weapon"][0] > 0; s.IsMobile = noun["thruster"][0] > 0; s.ShieldCharge = noun["shieldcharge"][0]; } else { s.Size = noun["sizeClass"][0]; var status = noun["status"][0]; s.IsArmed = status == "normal" || status == "immobile"; s.IsMobile = status == "normal" || status == "unarmed"; } return(s); }
/// <summary> /// Loads a universe from a root noun which has been loaded from a savegame. /// The root noun can be identified by its ID of "Vroot". /// Note that the root noun needs to belong to a noun collection in the library. /// </summary> /// <param name="root"></param> /// <returns></returns> public static Universe Load(Noun root) { // check library var shelf = Library.NounLibrary.Where(s => s.Contains(root)).FirstOrDefault(); if (shelf == null) { throw new Exception("Cannot load this universe; its root noun is not in the library."); } // let there be light! var u = new Universe(root["mapwidth"][0], root["mapheight"][0], root["turn"][0], root["playerObject"][0]); // load players u.players.AddRange(shelf.Where(noun => noun.Contains("teamName")).Select(noun => Player.Load(noun, u))); u.Us = u.Players.Single(p => p.ID == u.PlayerID); foreach (var p in u.Players) { p.Shipset = Shipset.DefaultEnemy; } u.Us.Shipset = Shipset.DefaultFriendly; if (shelf.Contains("Vnotes")) { // HACK - hide self shipsets from old versions; don't name your empire Pme or an emptystring :) foreach (var note in shelf["Vnotes"].Where(note => note.Key.StartsWith("Shipset:") && note.Key != "Shipset:Pme" && note.Key != "Shipset:")) { var teamName = note.Key.Substring("Shipset:".Length); var noteplr = u.Players.SingleOrDefault(p => p.TeamName == teamName); if (noteplr == null) { noteplr = u.AddPlayer(teamName); } noteplr.ShipsetName = note[0]; } } // load sectors u.Sectors = new SectorCollection(shelf.Where(noun => noun.Contains("X") && noun.Contains("Y")).Select(noun => { var s = new Sector(u); // coordinates, name, etc. s.ID = noun.Key; s.Coordinates = new Point(noun["X"][0], noun["Y"][0]); s.RealName = noun["name"][0]; if (shelf.Contains("Vnotes")) { if (shelf["Vnotes"].Contains("Name:" + s.ID)) { s.DisplayName = shelf["Vnotes"]["Name:" + s.ID][0]; } else { s.DisplayName = s.RealName; } } else { s.DisplayName = s.RealName; } // resource value if (noun.Contains("hullValue")) { s.Value = new Resources { Hull = noun["hullValue"][0], Weapons = noun["weaponValue"][0], Thrusters = noun["thrusterValue"][0], Shields = noun["shieldValue"][0], }; } // resource income if (noun.Contains("minedHull")) { s.Income = new Resources { Hull = noun["minedHull"][0], Weapons = noun["minedWeapon"][0], Thrusters = noun["minedThruster"][0], Shields = noun["minedShield"][0], }; } return(s); })); u.MaxValue = new Resources() { Hull = u.Sectors.Max(s => s.Value == null ? double.Epsilon : s.Value.Hull), Weapons = u.Sectors.Max(s => s.Value == null ? double.Epsilon : s.Value.Weapons), Thrusters = u.Sectors.Max(s => s.Value == null ? double.Epsilon : s.Value.Thrusters), Shields = u.Sectors.Max(s => s.Value == null ? double.Epsilon : s.Value.Shields), }; // load ships u.Ships = shelf.Where(noun => noun.Contains("location") && (noun.Contains("sizeClass") || noun.Contains("hull"))).Select(noun => Ship.Load(shelf, noun.Key, u.Sectors.Single(sector => sector.ID == noun["location"][0]), u)).ToArray(); foreach (var sector in u.Sectors) { sector.Ships = u.Ships.Where(ship => ship.Sector == sector && (ship.IsMobile || ship.IsArmed)).ToArray(); } // load treasury var usNoun = shelf[u.Us.ID]; u.Treasury = new Resources { Hull = usNoun["availableHull"][0], Weapons = usNoun["availableWeapon"][0], Thrusters = usNoun["availableThruster"][0], Shields = usNoun["availableShield"][0], }; // cache stuff u.OurMaximumFleetStrength = u.Sectors.Max(sector => sector.OurFleetStrength); u.MaximumEnemyFleetStrength = u.Sectors.Max(sector => sector.EnemyFleetStrength); u.MaximumShipSize = u.Ships.Max(ship => ship.Size); foreach (var ship in u.Ships.ToArray()) { var s = ship; // needed to make the ship "real" or something for the linqy stuff ship.Image = new Cache <Image>(() => s.Owner.Shipset.BuildShipImage(128, s.Config)); ship.SmallImage = new Cache <Image>(() => s.Owner.Shipset.BuildShipImage(24, s.Config)); } // load events u.Events = shelf[u.PlayerID]["eventList"].Select(adj => (string)adj); // load battles u.Battles = shelf.Where(noun => noun.Contains("eventSequence")).Select(noun => new Battle { ID = noun.Key, Location = u.Sectors.Single(sector => sector.ID == noun["location"][0]), Name = noun["name"][0], Ships = u.Ships.Join(noun["shipsPresent"], ship => ship.ID, adjPhrase => (string)adjPhrase, (ship, adjPhrase) => ship).ToArray(), Events = noun["eventSequence"].Select(adjPhrase => { var evtID = (string)adjPhrase; var evtNoun = shelf[evtID]; return(new BattleEvent { ID = evtID, Attacker = u.Ships.Single(ship => ship.ID == evtNoun["attacker"][0]), Target = u.Ships.Single(ship => ship.ID == evtNoun["target"][0]), DamageInflicted = new Resources { Hull = evtNoun["hull"][0], Weapons = evtNoun["weapon"][0], Thrusters = evtNoun["thruster"][0], Shields = evtNoun["shield"][0], }, DamageBlocked = evtNoun["block"][0], TargetDestroyed = evtNoun["dead"][0] != "0" && evtNoun["dead"][0] != "" && evtNoun["dead"][0] != null, }); }).ToArray() }).ToArray(); // init construction u.Construction = new List <ConstructionItem>(); // load ship designs var designs = new List <ConstructionItem>(); if (shelf.Contains("Vnotes")) { foreach (var dn in shelf["Vnotes"].Where(dn => dn.Key.StartsWith("Design:"))) { var d = new ConstructionItem(); d.Quantity = 1; d.Name = dn.Key.Substring("Design:".Length); var split = ((string)dn[0]).Split(' '); d.Weapons = int.Parse(split[0]); d.Thrusters = int.Parse(split[1]); d.Shields = int.Parse(split[2]); d.Armor = int.Parse(split[3]); designs.Add(d); } } u.Designs = designs; return(u); }