/// <summary> /// Reads a new simulation-state out of stream. /// </summary> /// <returns>New simulation-state or null, if stream is over</returns> public SimulationState Read() { // if stream is at his end, return null if (complete) { return(null); } // first block have to be a frame-start ISerializable block; BlockType blockType = serializer.Read(out block); // detect stream-end if (blockType == BlockType.StreamEnd) { complete = true; return(null); } // unexpected block-type if (blockType != BlockType.FrameStart) { throw new InvalidOperationException( string.Format( CultureInfo.CurrentCulture, Resource.AntvideoReaderInvalidBlockType, blockType)); } // block-loop while (blockType != BlockType.FrameEnd) { blockType = serializer.Read(out block); switch (blockType) { case BlockType.Ant: Ant ant = (Ant)block; antList.Add(ant.Id, ant); break; case BlockType.Anthill: Anthill anthill = (Anthill)block; anthillList.Add(anthill.Id, anthill); break; case BlockType.AntLost: Lost antLost = (Lost)block; antList.Remove(antLost.Id); break; case BlockType.AntUpdate: AntUpdate antUpdate = (AntUpdate)block; antList[antUpdate.Id].Update(antUpdate); break; case BlockType.Bug: Bug bug = (Bug)block; bugList.Add(bug.Id, bug); break; case BlockType.BugLost: Lost bugLost = (Lost)block; bugList.Remove(bugLost.Id); break; case BlockType.BugUpdate: BugUpdate bugUpdate = (BugUpdate)block; bugList[bugUpdate.Id].Update(bugUpdate); break; case BlockType.Caste: Caste caste = (Caste)block; casteList[caste.ColonyId].Add(caste.Id, caste); break; case BlockType.Team: Team team = (Team)block; teamList.Add(team.Id, team); colonyList.Add(team.Id, new Dictionary <int, Colony>()); break; case BlockType.Colony: Colony colony = (Colony)block; colonyList[colony.TeamId].Add(colony.Id, colony); casteList.Add(colony.Id, new Dictionary <int, Caste>()); break; case BlockType.ColonyUpdate: ColonyUpdate colonyUpdate = (ColonyUpdate)block; colonyList[colonyUpdate.TeamId][colonyUpdate.Id].Update(colonyUpdate); break; case BlockType.Frame: frame = (Frame)block; break; case BlockType.FrameUpdate: FrameUpdate frameUpdate = (FrameUpdate)block; frame.Update(frameUpdate); break; case BlockType.Fruit: Fruit fruit = (Fruit)block; fruitList.Add(fruit.Id, fruit); break; case BlockType.FruitLost: Lost fruitLost = (Lost)block; fruitList.Remove(fruitLost.Id); break; case BlockType.FruitUpdate: FruitUpdate fruitUpdate = (FruitUpdate)block; fruitList[fruitUpdate.Id].Update(fruitUpdate); break; case BlockType.Marker: Marker marker = (Marker)block; markerList.Add(marker.Id, marker); break; case BlockType.MarkerLost: Lost markerLost = (Lost)block; markerList.Remove(markerLost.Id); break; case BlockType.MarkerUpdate: MarkerUpdate markerUpdate = (MarkerUpdate)block; markerList[markerUpdate.Id].Update(markerUpdate); break; case BlockType.Sugar: Sugar sugar = (Sugar)block; sugarList.Add(sugar.Id, sugar); break; case BlockType.SugarLost: Lost sugarLost = (Lost)block; sugarList.Remove(sugarLost.Id); break; case BlockType.SugarUpdate: SugarUpdate sugarUpdate = (SugarUpdate)block; sugarList[sugarUpdate.Id].Update(sugarUpdate); break; } } // Detect streamend if ((BlockType)serializer.Peek() == BlockType.StreamEnd) { complete = true; } // Interpolate all elements and buildup state frame.Interpolate(); SimulationState state = frame.GenerateState(); foreach (Bug bug in bugList.Values) { bug.Interpolate(); state.BugStates.Add(bug.GenerateState()); } foreach (Fruit fruit in fruitList.Values) { fruit.Interpolate(); state.FruitStates.Add(fruit.GenerateState()); } foreach (Sugar sugar in sugarList.Values) { sugar.Interpolate(); state.SugarStates.Add(sugar.GenerateState()); } foreach (Team team in teamList.Values) { TeamState teamState = team.GenerateState(); state.TeamStates.Add(teamState); foreach (Colony colony in colonyList[team.Id].Values) { colony.Interpolate(); ColonyState colonyState = colony.GenerateState(); teamState.ColonyStates.Add(colonyState); foreach (Caste caste in casteList[colony.Id].Values) { colonyState.CasteStates.Add(caste.GenerateState()); } foreach (Anthill anthill in anthillList.Values) { if (anthill.ColonyId == colony.Id) { colonyState.AnthillStates.Add(anthill.GenerateState()); } } foreach (Ant ant in antList.Values) { if (ant.ColonyId == colony.Id) { ant.Interpolate(); colonyState.AntStates.Add(ant.GenerateState()); } } foreach (Marker marker in markerList.Values) { if (marker.ColonyId == colony.Id) { marker.Interpolate(); colonyState.MarkerStates.Add(marker.GenerateState()); } } } } // deliver return(state); }
/// <summary> /// Writes a new state to the stream. /// </summary> /// <param name="state">New state</param> public void Write(SimulationState state) { serializer.Write(BlockType.FrameStart); int[] keys; #region Framestart // The first call creates the frame if (frame == null) { // Create new frame frame = new Frame(state); serializer.Write(BlockType.Frame, frame); } else { // Send frame-update FrameUpdate update = frame.GenerateUpdate(state); if (update != null) { serializer.Write(BlockType.FrameUpdate, update); } } #endregion #region Teams and ColonyStates #region ant-reset // reset alive-flag foreach (Ant ant in antList.Values) { ant.IsAlive = false; } #endregion #region marker-reset // reset alive-flag foreach (Marker marker in markerList.Values) { marker.IsAlive = false; } #endregion // Teams are static and need no update // enumerate all teams foreach (TeamState teamState in state.TeamStates) { // Check, if team is known if (teamList.ContainsKey(teamState.Id)) { // No Teamupdate needed } else { Team team = new Team(teamState); serializer.Write(BlockType.Team, team); teamList.Add(teamState.Id, team); } // ColonyStates are static and need no update // enumerate all colonies foreach (ColonyState colonyState in teamState.ColonyStates) { // Check, if colony is known if (colonyList.ContainsKey(colonyState.Id)) { // colony-update ColonyUpdate update = colonyList[colonyState.Id].GenerateUpdate(colonyState); if (update != null) { serializer.Write(BlockType.ColonyUpdate, update); } colonyList[colonyState.Id].Interpolate(); } else { // new colony Colony colony = new Colony(colonyState, teamState.Id); serializer.Write(BlockType.Colony, colony); colonyList.Add(colonyState.Id, colony); casteList.Add(colonyState.Id, new Dictionary <int, Caste>()); #region Castes // Casts are static and need no update Dictionary <int, Caste> castes = casteList[colonyState.Id]; // enumerate casts for (ushort i = 0; i < colonyState.CasteStates.Count; i++) { // Check, if caste is known if (!castes.ContainsKey(i)) { // add caste Caste caste = new Caste(colonyState.CasteStates[i]); serializer.Write(BlockType.Caste, caste); } } #endregion #region Anthills // Anthills are static and need no update // enumerate anthills foreach (AnthillState anthill in colonyState.AnthillStates) { if (!anthillList.ContainsKey(anthill.Id)) { Anthill hill = new Anthill(anthill); serializer.Write(BlockType.Anthill, hill); anthillList.Add(anthill.Id, hill); } } #endregion } #region Ants // enumerate ants foreach (AntState antState in colonyState.AntStates) { // Check, if ant is known if (antList.ContainsKey(antState.Id)) { // ant-update AntUpdate update = antList[antState.Id].GenerateUpdate(antState); if (update != null) { serializer.Write(BlockType.AntUpdate, update); } antList[antState.Id].Interpolate(); } else { // create ant Ant ant = new Ant(antState); serializer.Write(BlockType.Ant, ant); antList.Add(ant.Id, ant); } antList[antState.Id].IsAlive = true; } #endregion #region Marker // enumerate marker foreach (MarkerState markerState in colonyState.MarkerStates) { // Check, if marker is known if (markerList.ContainsKey(markerState.Id)) { // marker-update MarkerUpdate update = markerList[markerState.Id].GenerateUpdate(markerState); if (update != null) { serializer.Write(BlockType.MarkerUpdate, update); } markerList[markerState.Id].Interpolate(); } else { // create marker Marker marker = new Marker(markerState); serializer.Write(BlockType.Marker, marker); markerList.Add(markerState.Id, marker); } markerList[markerState.Id].IsAlive = true; } #endregion } } #region Ant-Cleanup // remove dead ants keys = new int[antList.Keys.Count]; antList.Keys.CopyTo(keys, 0); for (int i = 0; i < keys.Length; i++) { if (!antList[keys[i]].IsAlive) { serializer.Write(BlockType.AntLost, new Lost(keys[i])); antList.Remove(keys[i]); } } #endregion #region Marker-Cleanup // remove dead marker keys = new int[markerList.Keys.Count]; markerList.Keys.CopyTo(keys, 0); for (int i = 0; i < keys.Length; i++) { if (!markerList[keys[i]].IsAlive) { serializer.Write(BlockType.MarkerLost, new Lost(keys[i])); markerList.Remove(keys[i]); } } #endregion #endregion #region Fruit // reset alive-flag foreach (Fruit fruit in fruitList.Values) { fruit.IsAlive = false; } // enumerate fruit foreach (FruitState fruitState in state.FruitStates) { // Check, if fruit is known if (fruitList.ContainsKey(fruitState.Id)) { // fruit-update FruitUpdate update = fruitList[fruitState.Id].GenerateUpdate(fruitState); if (update != null) { serializer.Write(BlockType.FruitUpdate, update); } fruitList[fruitState.Id].Interpolate(); } else { // create fruit Fruit fruit = new Fruit(fruitState); serializer.Write(BlockType.Fruit, fruit); fruitList.Add(fruitState.Id, fruit); } fruitList[fruitState.Id].IsAlive = true; } // remove dead fruits keys = new int[fruitList.Keys.Count]; fruitList.Keys.CopyTo(keys, 0); for (int i = 0; i < keys.Length; i++) { if (!fruitList[keys[i]].IsAlive) { serializer.Write(BlockType.FruitLost, new Lost(keys[i])); fruitList.Remove(keys[i]); } } #endregion #region Sugar // reset alive-flag foreach (Sugar sugar in sugarList.Values) { sugar.IsAlive = false; } // enumerate sugar foreach (SugarState sugarState in state.SugarStates) { // Check, if sugar is known if (sugarList.ContainsKey(sugarState.Id)) { // sugar-update SugarUpdate update = sugarList[sugarState.Id].GenerateUpdate(sugarState); if (update != null) { serializer.Write(BlockType.SugarUpdate, update); } sugarList[sugarState.Id].Interpolate(); } else { // create sugar Sugar sugar = new Sugar(sugarState); serializer.Write(BlockType.Sugar, sugar); sugarList.Add(sugarState.Id, sugar); } sugarList[sugarState.Id].IsAlive = true; } // remove dead sugar keys = new int[sugarList.Keys.Count]; sugarList.Keys.CopyTo(keys, 0); for (int i = 0; i < keys.Length; i++) { if (!sugarList[keys[i]].IsAlive) { serializer.Write(BlockType.SugarLost, new Lost(keys[i])); sugarList.Remove(keys[i]); } } #endregion #region Bugs // reset alive-flag foreach (Bug bug in bugList.Values) { bug.IsAlive = false; } // enumerate bugs foreach (BugState bugState in state.BugStates) { // Check, if bug is known if (bugList.ContainsKey(bugState.Id)) { // bug-update BugUpdate update = bugList[bugState.Id].GenerateUpdate(bugState); if (update != null) { serializer.Write(BlockType.BugUpdate, update); } bugList[bugState.Id].Interpolate(); } else { // create bug Bug bug = new Bug(bugState); serializer.Write(BlockType.Bug, bug); bugList.Add(bugState.Id, bug); } bugList[bugState.Id].IsAlive = true; } // remove dead bugs keys = new int[bugList.Keys.Count]; bugList.Keys.CopyTo(keys, 0); for (int i = 0; i < keys.Length; i++) { if (!bugList[keys[i]].IsAlive) { serializer.Write(BlockType.BugLost, new Lost(keys[i])); bugList.Remove(keys[i]); } } #endregion serializer.Write(BlockType.FrameEnd); }
/// <summary> /// Reads the next block out of stream. /// </summary> /// <param name="block">the found block</param> /// <returns>type of found block</returns> public BlockType Read(out ISerializable block) { BlockType blockType = (BlockType)stream.ReadByte(); block = null; switch (blockType) { case BlockType.Ant: block = new Ant(this); break; case BlockType.Anthill: block = new Anthill(this); break; case BlockType.AnthillLost: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); case BlockType.AnthillUpdate: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); case BlockType.AntLost: block = new Lost(this); break; case BlockType.AntUpdate: block = new AntUpdate(this); break; case BlockType.Bug: block = new Bug(this); break; case BlockType.BugLost: block = new Lost(this); break; case BlockType.BugUpdate: block = new BugUpdate(this); break; case BlockType.Team: block = new Team(this); break; case BlockType.TeamLost: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); case BlockType.TeamUpdate: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); case BlockType.Colony: block = new Colony(this); break; case BlockType.ColonyLost: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); case BlockType.ColonyUpdate: block = new ColonyUpdate(this); break; case BlockType.Frame: block = new Frame(this); break; case BlockType.StreamEnd: break; case BlockType.FrameLost: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); case BlockType.FrameUpdate: block = new FrameUpdate(this); break; case BlockType.Fruit: block = new Fruit(this); break; case BlockType.FruitLost: block = new Lost(this); break; case BlockType.FruitUpdate: block = new FruitUpdate(this); break; case BlockType.Marker: block = new Marker(this); break; case BlockType.MarkerLost: block = new Lost(this); break; case BlockType.MarkerUpdate: block = new MarkerUpdate(this); break; case BlockType.Caste: block = new Caste(this); break; case BlockType.CasteLost: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); case BlockType.CasteUpdate: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); case BlockType.Sugar: block = new Sugar(this); break; case BlockType.SugarLost: block = new Lost(this); break; case BlockType.SugarUpdate: block = new SugarUpdate(this); break; case BlockType.FrameStart: break; case BlockType.FrameEnd: break; default: throw new InvalidOperationException(string.Format(Resource.AntvideoSerializerInvalidBlockType, blockType)); } return(blockType); }