Index: branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/CardGameSimulation.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/CardGameSimulation.cs	(revision 10454)
+++ branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/CardGameSimulation.cs	(revision 10454)
@@ -0,0 +1,650 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.SimulationCore.Samples {
+  #region Model
+  public enum Suits { Hearts, Bells, Leaves, Acorns }
+  public enum Faces { Numeric, Under, Over, King, Sow }
+
+  [StorableClass]
+  public sealed class Card : IDeepCloneable {
+    [Storable]
+    public Suits Suit { get; private set; }
+    [Storable]
+    public Faces Face { get; private set; }
+    [Storable]
+    public int Value { get; private set; }
+
+    [StorableConstructor]
+    private Card(bool deserializing) { }
+    private Card(Card original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      Suit = original.Suit;
+      Face = original.Face;
+      Value = original.Value;
+    }
+    public Card(Suits s, Faces f, int v) {
+      Suit = s;
+      Face = f;
+      Value = v;
+    }
+
+    public object Clone() { return Clone(new Cloner()); }
+    public IDeepCloneable Clone(Cloner cloner) {
+      return new Card(this, cloner);
+    }
+
+    public override bool Equals(object obj) {
+      var other = (obj as Card);
+      if (other == null) return false;
+      return Suit == other.Suit && Face == other.Face && Value == other.Value;
+    }
+
+    public override int GetHashCode() {
+      return Suit.GetHashCode() ^ Face.GetHashCode() ^ Value.GetHashCode();
+    }
+  }
+
+  [StorableClass]
+  public sealed class Deck : IDeepCloneable {
+    private List<Card> cards;
+    public IEnumerable<Card> Cards { get { return cards.Select(x => x); } }
+
+    public int Count { get { return cards.Count; } }
+
+    [StorableConstructor]
+    private Deck(bool deserializing) { }
+    private Deck(Deck original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      cards = original.Cards.Select(cloner.Clone).ToList();
+    }
+    public Deck() {
+      cards = new List<Card>() {
+        new Card(Suits.Acorns, Faces.Numeric, 7), 
+        new Card(Suits.Acorns, Faces.Numeric, 8),
+        new Card(Suits.Acorns, Faces.Numeric, 9), 
+        new Card(Suits.Acorns, Faces.Numeric, 10), 
+        new Card(Suits.Acorns, Faces.Under, 10), 
+        new Card(Suits.Acorns, Faces.Over, 10), 
+        new Card(Suits.Acorns, Faces.King, 10), 
+        new Card(Suits.Acorns, Faces.Sow, 11),  
+        new Card(Suits.Bells, Faces.Numeric, 7), 
+        new Card(Suits.Bells, Faces.Numeric, 8),
+        new Card(Suits.Bells, Faces.Numeric, 9), 
+        new Card(Suits.Bells, Faces.Numeric, 10), 
+        new Card(Suits.Bells, Faces.Under, 10), 
+        new Card(Suits.Bells, Faces.Over, 10), 
+        new Card(Suits.Bells, Faces.King, 10), 
+        new Card(Suits.Bells, Faces.Sow, 11),  
+        new Card(Suits.Hearts, Faces.Numeric, 7), 
+        new Card(Suits.Hearts, Faces.Numeric, 8),
+        new Card(Suits.Hearts, Faces.Numeric, 9), 
+        new Card(Suits.Hearts, Faces.Numeric, 10), 
+        new Card(Suits.Hearts, Faces.Under, 10), 
+        new Card(Suits.Hearts, Faces.Over, 10), 
+        new Card(Suits.Hearts, Faces.King, 10), 
+        new Card(Suits.Hearts, Faces.Sow, 11), 
+        new Card(Suits.Leaves, Faces.Numeric, 7), 
+        new Card(Suits.Leaves, Faces.Numeric, 8),
+        new Card(Suits.Leaves, Faces.Numeric, 9), 
+        new Card(Suits.Leaves, Faces.Numeric, 10), 
+        new Card(Suits.Leaves, Faces.Under, 10), 
+        new Card(Suits.Leaves, Faces.Over, 10), 
+        new Card(Suits.Leaves, Faces.King, 10), 
+        new Card(Suits.Leaves, Faces.Sow, 11), 
+      };
+    }
+
+    public object Clone() { return Clone(new Cloner()); }
+    public IDeepCloneable Clone(Cloner cloner) {
+      return new Deck(this, cloner);
+    }
+
+    public void Shuffle() {
+      cards = cards.Shuffle(new FastRandom()).ToList();
+    }
+
+    public Card Deal1() {
+      var deal = cards[cards.Count - 1];
+      cards.RemoveAt(cards.Count - 1);
+      return deal;
+    }
+
+    public Card[] Deal3() {
+      var deal = new Card[3];
+      deal[0] = cards[cards.Count - 3];
+      deal[1] = cards[cards.Count - 2];
+      deal[2] = cards[cards.Count - 1];
+      cards.RemoveRange(cards.Count - 3, 3);
+      return deal;
+    }
+  }
+
+  [StorableClass]
+  public sealed class Hand : IDeepCloneable {
+    [Storable]
+    public Card First { get; set; }
+    [Storable]
+    public Card Second { get; set; }
+    [Storable]
+    public Card Third { get; set; }
+
+    public IEnumerable<Card> Cards {
+      get { return new[] { First, Second, Third }; }
+      set {
+        var v = value.ToArray();
+        First = v[0];
+        Second = v[1];
+        Third = v[2];
+        if (v.Length != 3) throw new ArgumentException("A hand must always consist of exactly three cards.");
+      }
+    }
+
+    [StorableConstructor]
+    private Hand(bool deserializing) { }
+    private Hand(Hand original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      Cards = original.Cards.Select(cloner.Clone);
+    }
+    public Hand(IEnumerable<Card> cards) {
+      Cards = cards;
+    }
+
+    public object Clone() { return Clone(new Cloner()); }
+    public IDeepCloneable Clone(Cloner cloner) {
+      return new Hand(this, cloner);
+    }
+
+    public int Rating() {
+      if (First.Suit == Second.Suit && First.Suit == Third.Suit) {
+        var value = First.Value + Second.Value + Third.Value;
+        if (value == 31) return 36;
+        return value;
+      }
+      if (First.Suit == Second.Suit) return First.Value + Second.Value;
+      if (First.Suit == Third.Suit) return First.Value + Third.Value;
+      if (Second.Suit == Third.Suit) return Second.Value + Third.Value;
+      if (Cards.Select(x => x.Face).Distinct().Count() == 1) return 33;
+      return 0;
+    }
+  }
+
+  [StorableClass]
+  public sealed class Player : IDeepCloneable {
+    [Storable]
+    public string Name { get; private set; }
+    [Storable]
+    public Hand Hand { get; set; }
+    [Storable]
+    public int Coins { get; set; }
+    [Storable]
+    public bool Blocks { get; set; }
+
+    [StorableConstructor]
+    private Player(bool deserializing) { }
+    private Player(Player original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      Name = original.Name;
+      Hand = cloner.Clone(original.Hand);
+      Coins = original.Coins;
+      Blocks = original.Blocks;
+    }
+    public Player(string name, int coins) {
+      Name = name;
+      Coins = coins;
+      Blocks = false;
+    }
+
+    public object Clone() { return Clone(new Cloner()); }
+    public IDeepCloneable Clone(Cloner cloner) {
+      return new Player(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class CardGameModel : Model {
+    [Storable]
+    public Hand Table { get; set; }
+    [Storable]
+    public Hand Talon { get; set; }
+    [Storable]
+    public List<Player> Players { get; set; }
+    [Storable]
+    public Deck Deck { get; set; }
+    [Storable]
+    public int DealerIndex { get; set; }
+    [Storable]
+    public int PlayerIndex { get; set; }
+    [Storable]
+    public IRandom Random { get; set; }
+
+    [StorableConstructor]
+    private CardGameModel(bool deserializing) : base(deserializing) { }
+    private CardGameModel(CardGameModel original, Cloner cloner)
+      : base(original, cloner) {
+      Table = cloner.Clone(original.Table);
+      Talon = cloner.Clone(original.Talon);
+      if (original.Players != null) Players = original.Players.Select(cloner.Clone).ToList();
+      Deck = cloner.Clone(original.Deck);
+      DealerIndex = original.DealerIndex;
+      PlayerIndex = original.PlayerIndex;
+      Random = cloner.Clone(original.Random);
+    }
+    public CardGameModel() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CardGameModel(this, cloner);
+    }
+  }
+  #endregion
+
+  #region Simulation
+  [StorableClass]
+  [Creatable("Simulations")]
+  public sealed class CardGameSimulation : DiscreteEventSimulation<CardGameModel> {
+    public override Type ProblemType {
+      get { return typeof(CardGameScenario); }
+    }
+
+    private CardGameScenario Scenario {
+      get { return (CardGameScenario)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [StorableConstructor]
+    private CardGameSimulation(bool deserializing) : base(deserializing) { }
+    private CardGameSimulation(CardGameSimulation original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterScenarioEventHandlers();
+    }
+    public CardGameSimulation() {
+      PrepareSimulation();
+      Scenario = new CardGameScenario();
+      ParameterizeInitialAction();
+      RegisterScenarioEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CardGameSimulation(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterScenarioEventHandlers();
+    }
+
+    private void PrepareSimulation() {
+      Activities = new Activity<CardGameModel>[] { new DealerActivity(), new PlayerActivity() };
+      Reporters = new Reporter<CardGameModel>[0];
+      InitialAction = new InitializeModelAction();
+      Model = new CardGameModel();
+    }
+
+    private void RegisterScenarioEventHandlers() {
+      Scenario.NumberOfPlayersParameter.Value.ValueChanged += ParametersChanged;
+      Scenario.InitialCoinsParameter.Value.ValueChanged += ParametersChanged;
+    }
+
+    protected override void OnProblemChanged() {
+      base.OnProblemChanged();
+      RegisterScenarioEventHandlers();
+      ParameterizeInitialAction();
+    }
+
+    protected override void OnPrepared() {
+      PrepareSimulation();
+      ParameterizeInitialAction();
+      base.OnPrepared();
+    }
+
+    private void ParametersChanged(object sender, EventArgs e) {
+      ParameterizeInitialAction();
+    }
+
+    private void ParameterizeInitialAction() {
+      ((InitializeModelAction)InitialAction).NumberOfPlayers = Scenario.NumberOfPlayersParameter.Value.Value;
+      ((InitializeModelAction)InitialAction).InitialCoins = Scenario.InitialCoinsParameter.Value.Value;
+    }
+  }
+
+  [Item("Card Game Scenario", "A card game scenario.")]
+  [StorableClass]
+  public sealed class CardGameScenario : Scenario {
+    public IFixedValueParameter<IntValue> NumberOfPlayersParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["NumberOfPlayers"]; }
+    }
+    public IFixedValueParameter<IntValue> InitialCoinsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["InitialCoins"]; }
+    }
+
+    public CardGameScenario() {
+      Parameters.Add(new FixedValueParameter<IntValue>("NumberOfPlayers", "The number of players.", new IntValue(5)));
+      Parameters.Add(new FixedValueParameter<IntValue>("InitialCoins", "The number of initial coins.", new IntValue(3)));
+    }
+    [StorableConstructor]
+    private CardGameScenario(bool deserializing) : base(deserializing) { }
+    private CardGameScenario(CardGameScenario original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CardGameScenario(this, cloner);
+    }
+  }
+  #endregion
+
+  #region Activities
+  [StorableClass]
+  public sealed class DealerActivity : Activity<CardGameModel> {
+    public override IEnumerable<Type> MonitoredActions {
+      get { return new[] { typeof(InitializeModelAction), typeof(FinalizeRoundAction), typeof(FoldCardsAction), typeof(AcceptCardsAction) }; }
+    }
+
+    [StorableConstructor]
+    private DealerActivity(bool deserializing) : base(deserializing) { }
+    private DealerActivity(DealerActivity original, Cloner cloner) : base(original, cloner) { }
+    public DealerActivity() : base(new SortedListEventQueue<CardGameModel>()) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DealerActivity(this, cloner);
+    }
+
+    public override void ManageEvents(CardGameModel model, IAction<CardGameModel> lastAction) {
+      if (lastAction is InitializeModelAction || lastAction is FinalizeRoundAction) {
+        if (model.Players.Count <= 1) return;
+        var nextPlayer = model.Players[(model.DealerIndex + 1) % model.Players.Count];
+        EventQueue.Push(model.CurrentTime + 1, new DealCardsAction(nextPlayer, doYouKeep: true));
+      } else if (lastAction is AcceptCardsAction || lastAction is FoldCardsAction) {
+        EventQueue.Push(model.CurrentTime + 1, new DealCardsAction(model.Players.Where(x => x.Hand == null)));
+        EventQueue.Push(model.CurrentTime + 2, new DealTableCardsAction());
+      }
+    }
+  }
+
+  [StorableClass]
+  public sealed class PlayerActivity : Activity<CardGameModel> {
+    public override IEnumerable<Type> MonitoredActions {
+      get { return new[] { typeof(DealCardsAction), typeof(DealTableCardsAction), typeof(NextPlayerAction) }; }
+    }
+
+    [StorableConstructor]
+    private PlayerActivity(bool deserializing) : base(deserializing) { }
+    private PlayerActivity(PlayerActivity original, Cloner cloner) : base(original, cloner) { }
+    public PlayerActivity() : base(new SortedListEventQueue<CardGameModel>()) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PlayerActivity(this, cloner);
+    }
+
+    public override void ManageEvents(CardGameModel model, IAction<CardGameModel> lastAction) {
+      if (lastAction is DealCardsAction) ManageDealCards(model, (DealCardsAction)lastAction);
+      else if (lastAction is DealTableCardsAction) ManageTableCards(model);
+      else if (lastAction is NextPlayerAction) ManageNextPlayer(model);
+    }
+
+    private void ManageDealCards(CardGameModel model, DealCardsAction dealCardsAction) {
+      if (dealCardsAction.DoYouKeep) {
+        var player = dealCardsAction.Players[0];
+        if (player.Hand.Rating() < 16)
+          EventQueue.Push(model.CurrentTime + 1, new FoldCardsAction(player));
+        else EventQueue.Push(model.CurrentTime + 1, new AcceptCardsAction());
+      }
+    }
+
+    private void ManageTableCards(CardGameModel model) {
+      var player = model.Players[model.PlayerIndex];
+      if (player.Hand.Rating() > 20)
+        EventQueue.Push(model.CurrentTime + 1, new PlayerBlocksAction());
+      else
+        EventQueue.Push(model.CurrentTime + 1, new SwapCardsAction(player.Hand, model.Table, model.Random.Next(1, 4), model.Random.Next(1, 4)));
+      EventQueue.Push(model.CurrentTime + 2, new NextPlayerAction());
+    }
+
+    private void ManageNextPlayer(CardGameModel model) {
+      var player = model.Players[model.PlayerIndex];
+      if (player.Blocks || player.Hand.Rating() == 36) {
+        EventQueue.Push(model.CurrentTime + 1, new FinalizeRoundAction());
+        return;
+      }
+      if (player.Hand.Rating() > 20)
+        EventQueue.Push(model.CurrentTime + 1, new PlayerBlocksAction());
+      else
+        EventQueue.Push(model.CurrentTime + 1, new SwapCardsAction(player.Hand, model.Table, model.Random.Next(1, 4), model.Random.Next(1, 4)));
+      EventQueue.Push(model.CurrentTime + 2, new NextPlayerAction());
+    }
+  }
+  #endregion
+
+  #region Actions
+  [StorableClass]
+  public sealed class InitializeModelAction : Action<CardGameModel> {
+    [Storable]
+    public int NumberOfPlayers { get; set; }
+    [Storable]
+    public int InitialCoins { get; set; }
+
+    private InitializeModelAction(InitializeModelAction original, Cloner cloner)
+      : base(original, cloner) {
+      NumberOfPlayers = original.NumberOfPlayers;
+      InitialCoins = original.InitialCoins;
+    }
+    public InitializeModelAction() {
+      NumberOfPlayers = 5;
+      InitialCoins = 3;
+    }
+
+    public override void Execute(CardGameModel model) {
+      model.CurrentTime = 0;
+      model.Random = new FastRandom();
+      model.Players = new List<Player>();
+      for (int i = 0; i < NumberOfPlayers; i++) {
+        model.Players.Add(new Player("Player " + i, InitialCoins));
+      }
+      model.DealerIndex = model.Random.Next(model.Players.Count);
+      model.PlayerIndex = (model.DealerIndex + 1) % model.Players.Count;
+      model.Deck = new Deck();
+      model.Deck.Shuffle();
+      model.Table = null;
+      model.Talon = null;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new InitializeModelAction(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class FinalizeRoundAction : Action<CardGameModel> {
+    private FinalizeRoundAction(FinalizeRoundAction original, Cloner cloner) : base(original, cloner) { }
+    public FinalizeRoundAction() { }
+
+    public override void Execute(CardGameModel model) {
+      var minScore = model.Players.Min(x => x.Hand.Rating());
+      foreach (var p in model.Players.Where(x => x.Hand.Rating() == minScore))
+        p.Coins--;
+
+      model.DealerIndex -= model.Players.Select((v, i) => new { Idx = i, Player = v }).Count(x => x.Idx <= model.DealerIndex && x.Player.Coins < 0);
+      model.Players = model.Players.Where(x => x.Coins >= 0).ToList();
+      foreach (var p in model.Players) {
+        p.Blocks = false;
+        p.Hand = null;
+      }
+      if (model.Players.Count > 0) {
+        model.DealerIndex = Math.Min(model.DealerIndex, model.Players.Count);
+        model.DealerIndex = (model.DealerIndex + 1) % model.Players.Count;
+        model.PlayerIndex = (model.DealerIndex + 1) % model.Players.Count;
+      }
+      model.Deck = new Deck();
+      model.Deck.Shuffle();
+      model.Table = null;
+      model.Talon = null;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FinalizeRoundAction(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class DealCardsAction : Action<CardGameModel> {
+    [Storable]
+    public Player[] Players { get; private set; }
+    [Storable]
+    public bool DoYouKeep { get; private set; }
+
+    private DealCardsAction(DealCardsAction original, Cloner cloner)
+      : base(original, cloner) {
+      Players = original.Players.Select(cloner.Clone).ToArray();
+      DoYouKeep = original.DoYouKeep;
+    }
+    private DealCardsAction() { }
+    public DealCardsAction(Player player, bool doYouKeep) {
+      Players = new[] { player };
+      DoYouKeep = doYouKeep;
+    }
+    public DealCardsAction(IEnumerable<Player> players, bool doYouKeep = false) {
+      Players = players.ToArray();
+      DoYouKeep = doYouKeep;
+    }
+
+    public override void Execute(CardGameModel model) {
+      foreach (var player in Players)
+        player.Hand = new Hand(model.Deck.Deal3());
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DealCardsAction(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class FoldCardsAction : Action<CardGameModel> {
+    [Storable]
+    public Player Player { get; private set; }
+
+    private FoldCardsAction(FoldCardsAction original, Cloner cloner)
+      : base(original, cloner) {
+      Player = cloner.Clone(original.Player);
+    }
+    public FoldCardsAction(Player player) {
+      Player = player;
+    }
+
+    public override void Execute(CardGameModel model) {
+      model.Talon = Player.Hand;
+      Player.Hand = null;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FoldCardsAction(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class AcceptCardsAction : Action<CardGameModel> {
+    [StorableConstructor]
+    private AcceptCardsAction(AcceptCardsAction original, Cloner cloner) : base(original, cloner) { }
+    public AcceptCardsAction() { }
+
+    public override void Execute(CardGameModel model) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AcceptCardsAction(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class DealTableCardsAction : Action<CardGameModel> {
+    private DealTableCardsAction(DealTableCardsAction original, Cloner cloner) : base(original, cloner) { }
+    public DealTableCardsAction() { }
+
+    public override void Execute(CardGameModel model) {
+      model.Table = new Hand(model.Deck.Deal3());
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DealTableCardsAction(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class SwapCardsAction : Action<CardGameModel> {
+    [Storable]
+    public Hand Source { get; private set; }
+    [Storable]
+    public Hand Target { get; private set; }
+    [Storable]
+    public int SourceIndex { get; private set; }
+    [Storable]
+    public int TargetIndex { get; private set; }
+
+    private SwapCardsAction(SwapCardsAction original, Cloner cloner)
+      : base(original, cloner) {
+      Source = cloner.Clone(original.Source);
+      Target = cloner.Clone(original.Target);
+      SourceIndex = original.SourceIndex;
+      TargetIndex = original.TargetIndex;
+    }
+    public SwapCardsAction(Hand source, Hand target, int sourceIndex, int targetIndex) {
+      Source = source;
+      Target = target;
+      SourceIndex = sourceIndex;
+      TargetIndex = targetIndex;
+    }
+
+    public override void Execute(CardGameModel model) {
+      if (SourceIndex == -1) {
+        var source = Source.Cards.ToArray();
+        Source.Cards = Target.Cards;
+        Target.Cards = source;
+      } else {
+        var sourceCards = Source.Cards.ToArray();
+        var targetCards = Target.Cards.ToArray();
+        var h = sourceCards[SourceIndex - 1];
+        sourceCards[SourceIndex - 1] = targetCards[TargetIndex - 1];
+        targetCards[TargetIndex - 1] = h;
+        Source.Cards = sourceCards;
+        Target.Cards = targetCards;
+      }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SwapCardsAction(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class PlayerBlocksAction : Action<CardGameModel> {
+    private PlayerBlocksAction(PlayerBlocksAction original, Cloner cloner) : base(original, cloner) { }
+    public PlayerBlocksAction() { }
+
+    public override void Execute(CardGameModel model) {
+      model.Players[model.PlayerIndex].Blocks = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PlayerBlocksAction(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public sealed class NextPlayerAction : Action<CardGameModel> {
+    private NextPlayerAction(NextPlayerAction original, Cloner cloner) : base(original, cloner) { }
+    public NextPlayerAction() { }
+
+    public override void Execute(CardGameModel model) {
+      model.PlayerIndex = (model.PlayerIndex + 1) % model.Players.Count;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NextPlayerAction(this, cloner);
+    }
+  }
+  #endregion
+}
Index: branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeDiscreteEventSimulation.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeDiscreteEventSimulation.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeDiscreteEventSimulation.cs	(revision 10454)
@@ -6,56 +6,9 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
 
 namespace HeuristicLab.SimulationCore.Samples {
-  [Item("Game of Life (discrete event)", "A discrete event based implementation of the game of life simulation.")]
-  [Creatable("Simulations")]
-  public class GameOfLifeDiscreteEventSimulation : DiscreteEventSimulation<GameOfLifeModel> {
-    private GameOfLifeScenario Scenario {
-      get { return Problem as GameOfLifeScenario; }
-      set { Problem = value; }
-    }
-
-    private GameOfLifeDiscreteEventSimulation(GameOfLifeDiscreteEventSimulation original, Cloner cloner)
-      : base(original, cloner) { }
-    public GameOfLifeDiscreteEventSimulation() {
-      Scenario = new GameOfLifeScenario();
-      InitialAction = new InitializeGameOfLifeBoardAction() { AliveRate = Scenario.AliveRateParameter.Value.Value };
-      Activities = new IActivity<GameOfLifeModel>[] { new CurrentTimeMonitor() };
-      Reporters = new IReporter<GameOfLifeModel>[] { new GameOfLifeStateReporter() };
-      Initialize();
-    }
-
-    private void Initialize() {
-      Scenario.WidthParameter.ValueChanged += ValueChanged;
-      if (Scenario.WidthParameter.Value != null) Scenario.WidthParameter.Value.ValueChanged += ParametersChanged;
-      Scenario.HeightParameter.ValueChanged += ValueChanged;
-      if (Scenario.HeightParameter.Value != null) Scenario.HeightParameter.Value.ValueChanged += ParametersChanged;
-      Scenario.AliveRateParameter.ValueChanged += ValueChanged;
-      if (Scenario.AliveRateParameter.Value != null) Scenario.AliveRateParameter.Value.ValueChanged += ParametersChanged;
-    }
-
-
-    private void ValueChanged(object sender, EventArgs e) {
-      if (Scenario.WidthParameter.Value != null) Scenario.WidthParameter.Value.ValueChanged += ParametersChanged;
-      if (Scenario.HeightParameter.Value != null) Scenario.HeightParameter.Value.ValueChanged += ParametersChanged;
-      if (Scenario.AliveRateParameter.Value != null) Scenario.AliveRateParameter.Value.ValueChanged += ParametersChanged;
-      ParametersChanged(sender, e);
-    }
-
-    private void ParametersChanged(object sender, EventArgs e) {
-      Model = new GameOfLifeModel(Scenario.WidthParameter.Value.Value, Scenario.HeightParameter.Value.Value);
-      ((InitializeGameOfLifeBoardAction)InitialAction).AliveRate = Scenario.AliveRateParameter.Value.Value;
-    }
-
-    protected override void OnPrepared() {
-      Model = new GameOfLifeModel(Scenario.WidthParameter.Value.Value, Scenario.HeightParameter.Value.Value);
-      base.OnPrepared();
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new GameOfLifeDiscreteEventSimulation(this, cloner);
-    }
-  }
-
+
+  #region Model
   [StorableClass]
   public sealed class GameOfLifeModel : IModel {
@@ -79,25 +32,94 @@
     }
   }
-
-  [StorableClass]
-  sealed class CurrentTimeMonitor : Activity<GameOfLifeModel> {
-    public override IEnumerable<Guid> MonitoredActionIds {
-      get { return new[] { InitializeGameOfLifeBoardAction.Id, ModelTimeUpdateAction<GameOfLifeModel>.Id }; }
+  #endregion
+
+  #region Simulation
+  [Item("Game of Life (discrete event)", "A discrete event based implementation of the game of life simulation.")]
+  [Creatable("Simulations")]
+  public class GameOfLifeDiscreteEventSimulation : DiscreteEventSimulation<GameOfLifeModel> {
+    public override Type ProblemType { get { return typeof(GameOfLifeScenario); } }
+
+    private GameOfLifeScenario Scenario {
+      get { return (GameOfLifeScenario)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    private GameOfLifeDiscreteEventSimulation(GameOfLifeDiscreteEventSimulation original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterScenarioEventHandlers();
+    }
+    public GameOfLifeDiscreteEventSimulation() {
+      PrepareSimulation();
+      Scenario = new GameOfLifeScenario();
+      Parameterize();
+      RegisterScenarioEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GameOfLifeDiscreteEventSimulation(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterScenarioEventHandlers();
+    }
+
+    private void PrepareSimulation() {
+      InitialAction = new InitializeGameOfLifeBoardAction();
+      Activities = new IActivity<GameOfLifeModel>[] { new BoardActivity() };
+      Reporters = new IReporter<GameOfLifeModel>[] { new GameOfLifeStateReporter() };
+    }
+
+    private void RegisterScenarioEventHandlers() {
+      Scenario.WidthParameter.Value.ValueChanged += ParametersChanged;
+      Scenario.HeightParameter.Value.ValueChanged += ParametersChanged;
+      Scenario.AliveRateParameter.Value.ValueChanged += ParametersChanged;
+    }
+
+    protected override void OnProblemChanged() {
+      base.OnProblemChanged();
+      Parameterize();
+      RegisterScenarioEventHandlers();
+    }
+
+    protected override void OnPrepared() {
+      base.OnPrepared();
+      PrepareSimulation();
+    }
+
+    private void ParametersChanged(object sender, EventArgs e) {
+      Parameterize();
+    }
+
+    private void Parameterize() {
+      Model = new GameOfLifeModel(Scenario.WidthParameter.Value.Value, Scenario.HeightParameter.Value.Value);
+      ((InitializeGameOfLifeBoardAction)InitialAction).AliveRate = Scenario.AliveRateParameter.Value.Value;
+    }
+  }
+  #endregion
+
+  #region Activities
+  [StorableClass]
+  sealed class BoardActivity : Activity<GameOfLifeModel> {
+    public override IEnumerable<Type> MonitoredActions {
+      get { return new[] { typeof(InitializeGameOfLifeBoardAction), typeof(UpdateGameOfLifeBoardAction) }; }
     }
 
     [StorableConstructor]
-    private CurrentTimeMonitor(bool deserializing) : base(deserializing) { }
-    private CurrentTimeMonitor(CurrentTimeMonitor original, Cloner cloner) : base(original, cloner) { }
-    public CurrentTimeMonitor() : base(new SortedListEventQueue<GameOfLifeModel>()) { }
+    private BoardActivity(bool deserializing) : base(deserializing) { }
+    private BoardActivity(BoardActivity original, Cloner cloner) : base(original, cloner) { }
+    public BoardActivity() : base(new SortedListEventQueue<GameOfLifeModel>()) { }
 
     public override void ManageEvents(GameOfLifeModel model, IAction<GameOfLifeModel> lastAction) {
-      EventQueue.Push(new Event<GameOfLifeModel>(model.CurrentTime + 1, new UpdateGameOfLifeBoardAction()));
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new CurrentTimeMonitor(this, cloner);
-    }
-  }
-
+      EventQueue.Push(model.CurrentTime + 1, new UpdateGameOfLifeBoardAction());
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BoardActivity(this, cloner);
+    }
+  }
+  #endregion
+
+  #region Reporters
   [StorableClass]
   sealed class GameOfLifeStateReporter : Reporter<GameOfLifeModel> {
@@ -123,17 +145,12 @@
     }
   }
-
+  #endregion
+
+  #region Actions
   [StorableClass]
   sealed class InitializeGameOfLifeBoardAction : Action<GameOfLifeModel> {
-    public static readonly Guid Id = new Guid("a6d37f71-ccef-4c2a-b11b-793fda0f9f4f");
-    public override Guid ActionId {
-      get { return Id; }
-    }
-
     [Storable]
     public double AliveRate { get; set; }
 
-    [StorableConstructor]
-    private InitializeGameOfLifeBoardAction(bool deserializing) : base(deserializing) { }
     private InitializeGameOfLifeBoardAction(InitializeGameOfLifeBoardAction original, Cloner cloner)
       : base(original, cloner) {
@@ -145,5 +162,5 @@
 
     public override void Execute(GameOfLifeModel model) {
-      var random = new Random();
+      var random = new FastRandom();
       var rows = model.Grid.GetLength(0);
       var cols = model.Grid.GetLength(1);
@@ -161,11 +178,4 @@
   [StorableClass]
   sealed class UpdateGameOfLifeBoardAction : Action<GameOfLifeModel> {
-    public static readonly Guid Id = new Guid("323bb2ef-bc66-488f-ac88-798b91565e62");
-    public override Guid ActionId {
-      get { return Id; }
-    }
-
-    [StorableConstructor]
-    private UpdateGameOfLifeBoardAction(bool deserializing) : base(deserializing) { }
     private UpdateGameOfLifeBoardAction(UpdateGameOfLifeBoardAction original, Cloner cloner) : base(original, cloner) { }
     public UpdateGameOfLifeBoardAction() { }
@@ -195,3 +205,4 @@
     }
   }
+  #endregion
 }
Index: branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeScenario.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeScenario.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeScenario.cs	(revision 10454)
@@ -20,33 +20,29 @@
 #endregion
 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Common;
 using HeuristicLab.Data;
 using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.SimulationCore.Samples {
   [Item("GameOfLifeScenario", "A game of life scenario.")]
   [StorableClass]
-  public sealed class GameOfLifeScenario: Scenario {
-    public ValueParameter<IntValue> WidthParameter {
-      get { return (ValueParameter<IntValue>)Parameters["Width"]; }
+  public sealed class GameOfLifeScenario : Scenario {
+    public IFixedValueParameter<IntValue> WidthParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["Width"]; }
     }
-    public ValueParameter<IntValue> HeightParameter {
-      get { return (ValueParameter<IntValue>)Parameters["Height"]; }
+    public IFixedValueParameter<IntValue> HeightParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["Height"]; }
     }
-    public ValueParameter<PercentValue> AliveRateParameter {
-      get { return (ValueParameter<PercentValue>)Parameters["AliveRate"]; }
+    public IFixedValueParameter<PercentValue> AliveRateParameter {
+      get { return (IFixedValueParameter<PercentValue>)Parameters["AliveRate"]; }
     }
 
     public GameOfLifeScenario()
       : base() {
-      Parameters.Add(new ValueParameter<IntValue>("Width", "The width value.", new IntValue(100)));
-      Parameters.Add(new ValueParameter<IntValue>("Height", "The height value.", new IntValue(100)));
-      Parameters.Add(new ValueParameter<PercentValue>("AliveRate", "The rate of the initialyy alive cells.", new PercentValue(0.5)));
+      Parameters.Add(new FixedValueParameter<IntValue>("Width", "The width value.", new IntValue(100)));
+      Parameters.Add(new FixedValueParameter<IntValue>("Height", "The height value.", new IntValue(100)));
+      Parameters.Add(new FixedValueParameter<PercentValue>("AliveRate", "The rate of the initialyy alive cells.", new PercentValue(0.5)));
     }
     [StorableConstructor]
Index: branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeSimulation.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeSimulation.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeSimulation.cs	(revision 10454)
@@ -22,15 +22,14 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System.Threading;
+using HeuristicLab.Analysis;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Parameters;
 using HeuristicLab.Data;
 using HeuristicLab.Optimization;
-using System.Threading;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
 using HeuristicLab.SimulationCore.AgentBased;
-using HeuristicLab.Analysis;
 
 namespace HeuristicLab.SimulationCore.Samples {
@@ -38,5 +37,5 @@
   [Creatable("Simulations")]
   [StorableClass]
-  public sealed class GameOfLifeSimulation: AgentBasedSimulation {
+  public sealed class GameOfLifeSimulation : AgentBasedSimulation {
     public override Type ProblemType {
       get { return typeof(GameOfLifeScenario); }
@@ -48,10 +47,11 @@
       }
     }
-    
+
     public ValueParameter<IntValue> IterationsParameter {
       get { return (ValueParameter<IntValue>)Parameters["Iterations"]; }
     }
-    
-    public GameOfLifeSimulation() : base() {
+
+    public GameOfLifeSimulation()
+      : base() {
       Parameters.Add(new ValueParameter<IntValue>("Iterations", "The number of iterations.", new IntValue(100)));
 
@@ -72,5 +72,5 @@
     }
 
-    private GameOfLifeAgent GetAgent(int x, int y) {     
+    private GameOfLifeAgent GetAgent(int x, int y) {
       int width = Scenario.WidthParameter.Value.Value;
       int height = Scenario.HeightParameter.Value.Value;
@@ -79,5 +79,5 @@
         throw new Exception("invalid index");
 
-      int index = x + y * width;  
+      int index = x + y * width;
 
       return Agents[index] as GameOfLifeAgent;
@@ -86,10 +86,6 @@
     private void Initialize() {
       if (Scenario != null) {
-        Scenario.WidthParameter.ValueChanged += new EventHandler(WidthParameter_ValueChanged);
-        if(Scenario.WidthParameter.Value != null)
-          Scenario.WidthParameter.Value.ValueChanged += new EventHandler(Width_ValueChanged);
-        Scenario.HeightParameter.ValueChanged += new EventHandler(HeightParameter_ValueChanged);
-        if (Scenario.HeightParameter.Value != null)
-          Scenario.HeightParameter.Value.ValueChanged += new EventHandler(Height_ValueChanged);
+        Scenario.WidthParameter.Value.ValueChanged += new EventHandler(Width_ValueChanged);
+        Scenario.HeightParameter.Value.ValueChanged += new EventHandler(Height_ValueChanged);
       }
     }
@@ -103,17 +99,9 @@
     }
 
-    void HeightParameter_ValueChanged(object sender, EventArgs e) {
-      CreateAgents();
-    }
-
-    void WidthParameter_ValueChanged(object sender, EventArgs e) {
-      CreateAgents();
-    }
-
     public IEnumerable<GameOfLifeAgent> GetNeighbors(GameOfLifeAgent agent) {
       int width = Scenario.WidthParameter.Value.Value;
       int height = Scenario.HeightParameter.Value.Value;
       int index = Agents.IndexOf(agent);
-      
+
       List<GameOfLifeAgent> result = new List<GameOfLifeAgent>();
 
@@ -159,5 +147,5 @@
       int height = Scenario.HeightParameter.Value.Value;
 
-      Random rand = new Random();
+      var rand = new FastRandom();
 
       for (int i = 0; i < width * height; i++) {
@@ -190,5 +178,5 @@
 
       Results["Cells"].Value = cells;
-      
+
       IntValue currentIterations = (Results["CurrentIterations"].Value as IntValue);
       currentIterations.Value++;
@@ -206,11 +194,11 @@
         Results.Add(new Result("CurrentIterations", new IntValue(0)));
         Results.Add(new Result("Cells", new HeatMap(width, height)));
-      }      
+      }
 
       for (int i = start; i < iterations; i++) {
         cancellationToken.ThrowIfCancellationRequested();
-        
+
         base.Step();
-        UpdateResults();        
+        UpdateResults();
       }
     }
Index: branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/HeuristicLab.SimulationCore.Samples-3.3.csproj
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/HeuristicLab.SimulationCore.Samples-3.3.csproj	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/HeuristicLab.SimulationCore.Samples-3.3.csproj	(revision 10454)
@@ -155,4 +155,8 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="HeuristicLab.Random-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Random-3.3.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -164,4 +168,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="CardGameSimulation.cs" />
     <Compile Include="GameOfLifeAgent.cs" />
     <Compile Include="GameOfLifeDiscreteEventSimulation.cs" />
Index: branches/SimulationCore/HeuristicLab.SimulationCore.Tests/EventQueueTest.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore.Tests/EventQueueTest.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore.Tests/EventQueueTest.cs	(revision 10454)
@@ -32,17 +32,17 @@
     public void EventQueueCreateTest() {
       var queue = new SortedListEventQueue<IModel>();
-      queue.Push(new Event<IModel>(5, new DummyAction()));
+      queue.Push(5, new DummyAction());
       Assert.IsTrue(queue.Count == 1);
-      queue.Push(new Event<IModel>(2, new DummyAction()));
+      queue.Push(2, new DummyAction());
       Assert.IsTrue(queue.Peek().Time == 2);
       Assert.IsTrue(queue.Count == 2);
-      queue.Push(new Event<IModel>(3, new DummyAction()));
+      queue.Push(3, new DummyAction());
       Assert.IsTrue(queue.Peek().Time == 2);
       Assert.IsTrue(queue.Count == 3);
       for (var i = 10; i < 50; i++)
-        queue.Push(new Event<IModel>(i, new DummyAction()));
+        queue.Push(i, new DummyAction());
       Assert.IsTrue(queue.Peek().Time == 2);
       Assert.IsTrue(queue.Count == 43);
-      queue.Push(new Event<IModel>(2, new DummyAction()));
+      queue.Push(2, new DummyAction());
     }
   }
Index: branches/SimulationCore/HeuristicLab.SimulationCore.sln
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore.sln	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore.sln	(revision 10454)
@@ -74,6 +74,3 @@
 		HideSolutionNode = FALSE
 	EndGlobalSection
-	GlobalSection(Performance) = preSolution
-		HasPerformanceSessions = true
-	EndGlobalSection
 EndGlobal
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Action.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Action.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Action.cs	(revision 10454)
@@ -6,5 +6,4 @@
   [StorableClass]
   public abstract class Action<TModel> : IAction<TModel> where TModel : IModel {
-    public abstract Guid ActionId { get; }
     public IActivity<TModel> Mandate { get; protected set; }
 
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Activity.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Activity.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Activity.cs	(revision 10454)
@@ -15,6 +15,6 @@
     }
 
-    public virtual IEnumerable<Guid> MonitoredActionIds {
-      get { return new Guid[0]; }
+    public virtual IEnumerable<Type> MonitoredActions {
+      get { return new Type[0]; }
     }
 
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/CompositeEventQueue.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/CompositeEventQueue.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/CompositeEventQueue.cs	(revision 10454)
@@ -41,4 +41,10 @@
     }
 
+    public void Clear() {
+      foreach (var queue in queues) {
+        queue.Clear();
+      }
+    }
+
     [StorableConstructor]
     private CompositeEventQueue(bool deserializing) : base(deserializing) { }
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/DiscreteEventSimulation.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/DiscreteEventSimulation.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/DiscreteEventSimulation.cs	(revision 10454)
@@ -2,4 +2,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using System.Text;
 using System.Threading;
 using HeuristicLab.Common;
@@ -32,4 +33,6 @@
     }
 
+    [StorableConstructor]
+    protected DiscreteEventSimulation(bool deserializing) : base(deserializing) { }
     protected DiscreteEventSimulation(DiscreteEventSimulation<TModel> original, Cloner cloner)
       : base(original, cloner) {
@@ -39,7 +42,12 @@
       Model = cloner.Clone(original.Model);
     }
-
     protected DiscreteEventSimulation() {
       Parameters.Add(new FixedValueParameter<DoubleValue>("MaximumTime", "The simulation stops after reaching this time.", new DoubleValue(1000)));
+    }
+
+    protected override void OnPrepared() {
+      base.OnPrepared();
+      if (CompositeEventQueue != null)
+        CompositeEventQueue.Clear();
     }
 
@@ -47,7 +55,9 @@
       CompositeEventQueue = new CompositeEventQueue<TModel>(Activities.Select(x => x.EventQueue));
 
-      var actionMonitor = new Dictionary<Guid, List<IActivity<TModel>>>();
+      var log = new StringBuilder();
+
+      var actionMonitor = new Dictionary<Type, List<IActivity<TModel>>>();
       foreach (var activity in Activities) {
-        foreach (var actionId in activity.MonitoredActionIds) {
+        foreach (var actionId in activity.MonitoredActions) {
           if (!actionMonitor.ContainsKey(actionId)) actionMonitor[actionId] = new List<IActivity<TModel>>();
           actionMonitor[actionId].Add(activity);
@@ -55,5 +65,5 @@
       }
 
-      if (InitialAction != null) {
+      if (CompositeEventQueue.Empty && InitialAction != null) {
         InitialAction.Execute(Model);
         CallActivities(actionMonitor, InitialAction);
@@ -62,28 +72,32 @@
       while (!CompositeEventQueue.Empty && Model.CurrentTime < MaximumTime) {
         var @event = CompositeEventQueue.Pop();
+        if (@event.Time < Model.CurrentTime) continue;
+        log.AppendLine(@event.Action.GetType().Name);
+        Model.CurrentTime = @event.Time;
+
         var nextEvent = CompositeEventQueue.Empty ? null : CompositeEventQueue.Peek();
         var action = @event.Action;
 
         action.Execute(Model);
-        CallActivities(actionMonitor, action);
 
-        if (@event.Time > Model.CurrentTime && (nextEvent == null || @event.Time < nextEvent.Time)) {
-          var timeUpdateAction = new ModelTimeUpdateAction<TModel>(null, @event.Time);
-          timeUpdateAction.Execute(Model);
-
-          if (actionMonitor.ContainsKey(timeUpdateAction.ActionId))
-            foreach (var activity in actionMonitor[timeUpdateAction.ActionId])
-              activity.ManageEvents(Model, timeUpdateAction);
-
+        if (nextEvent == null || @event.Time < nextEvent.Time) {
           foreach (var reporter in Reporters)
             reporter.UpdateReporting(Model, Results);
         }
+
+        CallActivities(actionMonitor, action);
+
         cancellationToken.ThrowIfCancellationRequested();
       };
     }
 
-    private void CallActivities(Dictionary<Guid, List<IActivity<TModel>>> actionMonitor, IAction<TModel> action) {
-      if (actionMonitor.ContainsKey(action.ActionId)) {
-        foreach (var activity in actionMonitor[action.ActionId])
+    private void CallActivities(Dictionary<Type, List<IActivity<TModel>>> actionMonitor, IAction<TModel> action) {
+      if (actionMonitor.ContainsKey(action.GetType())) {
+        foreach (var activity in actionMonitor[action.GetType()])
+          activity.ManageEvents(Model, action);
+      }
+
+      if (actionMonitor.ContainsKey(typeof(object))) {
+        foreach (var activity in actionMonitor[typeof(object)])
           activity.ManageEvents(Model, action);
       }
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Event.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Event.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Event.cs	(revision 10454)
@@ -11,7 +11,7 @@
 
     #region Storable Properties
-    [Storable]
     // ReSharper disable UnusedMember.Local
     // ReSharper disable UnusedParameter.Local
+    [Storable]
     private double StorableTime {
       get { return time; }
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IAction.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IAction.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IAction.cs	(revision 10454)
@@ -1,8 +1,6 @@
-﻿using System;
-using HeuristicLab.Common;
+﻿using HeuristicLab.Common;
 
 namespace HeuristicLab.SimulationCore {
   public interface IAction<TModel> : IDeepCloneable, IContent where TModel : IModel {
-    Guid ActionId { get; }
     IActivity<TModel> Mandate { get; }
 
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IActivity.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IActivity.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IActivity.cs	(revision 10454)
@@ -7,5 +7,5 @@
     where TModel : IModel {
     IEventQueue<TModel> EventQueue { get; }
-    IEnumerable<Guid> MonitoredActionIds { get; }
+    IEnumerable<Type> MonitoredActions { get; }
 
     void ManageEvents(TModel model, IAction<TModel> lastAction);
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IEventQueue.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IEventQueue.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Interfaces/IEventQueue.cs	(revision 10454)
@@ -8,5 +8,5 @@
     IEvent<TModel> Peek();
     IEvent<TModel> Pop();
-    void Push(IEvent<TModel> @event);
+    void Push(double time, IAction<TModel> action);
 
     IEvent<TModel> ChangeTime(IEvent<TModel> @event, double newTime);
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Model.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Model.cs	(revision 10454)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/Model.cs	(revision 10454)
@@ -0,0 +1,27 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.SimulationCore {
+  [StorableClass]
+  public abstract class Model : IModel {
+    [Storable]
+    public double CurrentTime { get; set; }
+
+    [StorableConstructor]
+    protected Model(bool deserializing) { }
+    protected Model(Model original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      CurrentTime = original.CurrentTime;
+    }
+    protected Model() { }
+    protected Model(double time) {
+      CurrentTime = time;
+    }
+
+    public object Clone() {
+      return Clone(new Cloner());
+    }
+
+    public abstract IDeepCloneable Clone(Cloner cloner);
+  }
+}
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/ModelTimeUpdateAction.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/ModelTimeUpdateAction.cs	(revision 10450)
+++ 	(revision )
@@ -1,31 +1,0 @@
-﻿using System;
-using HeuristicLab.Common;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.SimulationCore {
-  [StorableClass]
-  public sealed class ModelTimeUpdateAction<TModel> : Action<TModel> where TModel : IModel {
-    public static readonly Guid Id = new Guid("1dd664ec-809d-494b-a96b-567696a59a5b");
-    public override Guid ActionId {
-      get { return Id; }
-    }
-
-    public double NextTime { get; private set; }
-
-    [StorableConstructor]
-    private ModelTimeUpdateAction(bool deserializing) : base(deserializing) { }
-    private ModelTimeUpdateAction(Action<TModel> original, Cloner cloner) : base(original, cloner) { }
-    public ModelTimeUpdateAction(IActivity<TModel> mandate, double nextTime)
-      : base(mandate) {
-      NextTime = nextTime;
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new ModelTimeUpdateAction<TModel>(this, cloner);
-    }
-
-    public override void Execute(TModel model) {
-      model.CurrentTime = NextTime;
-    }
-  }
-}
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/SortedListEventQueue.cs
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/SortedListEventQueue.cs	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/DiscreteEvent/SortedListEventQueue.cs	(revision 10454)
@@ -26,15 +26,19 @@
     }
 
-    public void Push(IEvent<TModel> @event) {
-      if (queue.ContainsKey(@event.Time))
-        queue[@event.Time].Add(@event);
-      else queue.Add(@event.Time, new List<IEvent<TModel>>() { @event });
+    public void Push(double time, IAction<TModel> action) {
+      PushEvent(time, action);
+    }
+
+    private IEvent<TModel> PushEvent(double time, IAction<TModel> action) {
+      IEvent<TModel> result = new Event<TModel>(time, action);
+      if (queue.ContainsKey(time))
+        queue[time].Add(result);
+      else queue.Add(time, new List<IEvent<TModel>>() { result });
+      return result;
     }
 
     public IEvent<TModel> ChangeTime(IEvent<TModel> @event, double newTime) {
       Remove(@event);
-      var newEvent = new Event<TModel>(newTime, @event.Action);
-      Push(newEvent);
-      return newEvent;
+      return PushEvent(newTime, @event.Action);
     }
 
Index: branches/SimulationCore/HeuristicLab.SimulationCore/3.3/HeuristicLab.SimulationCore-3.3.csproj
===================================================================
--- branches/SimulationCore/HeuristicLab.SimulationCore/3.3/HeuristicLab.SimulationCore-3.3.csproj	(revision 10450)
+++ branches/SimulationCore/HeuristicLab.SimulationCore/3.3/HeuristicLab.SimulationCore-3.3.csproj	(revision 10454)
@@ -159,5 +159,5 @@
     <Compile Include="DiscreteEvent\Event.cs" />
     <Compile Include="DiscreteEvent\Interfaces\IReporter.cs" />
-    <Compile Include="DiscreteEvent\ModelTimeUpdateAction.cs" />
+    <Compile Include="DiscreteEvent\Model.cs" />
     <Compile Include="DiscreteEvent\Reporter.cs" />
     <Compile Include="DiscreteEvent\SortedListEventQueue.cs" />
