diff --git a/Nomyx-Core.cabal b/Nomyx-Core.cabal
--- a/Nomyx-Core.cabal
+++ b/Nomyx-Core.cabal
@@ -1,5 +1,5 @@
 name: Nomyx-Core
-version: 0.7.2
+version: 0.7.3
 cabal-version: >=1.6
 build-type: Simple
 license: BSD3
@@ -15,7 +15,7 @@
 data-dir: data
  
 library 
-    build-depends: Nomyx-Language         == 0.7.2,
+    build-depends: Nomyx-Language         == 0.7.3,
                    DebugTraceHelpers      == 0.12.*,
                    MissingH               == 1.2.*,
                    acid-state             == 0.12.*,
@@ -31,7 +31,7 @@
                    either-unwrap          == 1.1.*,
                    exceptions             == 0.6.*,
                    filepath               == 1.3.*,
-                   happstack-authenticate == 0.10.*,
+                   happstack-authenticate == 0.10.15,
                    hint                   == 0.4.*,
                    hint-server            == 1.4.*,
                    hscolour               == 1.20.*,
@@ -72,6 +72,7 @@
                      Nomyx.Core.Test
                      Nomyx.Core.Engine
                      Nomyx.Core.Engine.Evaluation
+                     Nomyx.Core.Engine.EventEval
                      Nomyx.Core.Engine.EvalUtils
                      Nomyx.Core.Engine.Types
                      Nomyx.Core.Engine.GameEvents
diff --git a/data/test/TestTime.hs b/data/test/TestTime.hs
new file mode 100644
--- /dev/null
+++ b/data/test/TestTime.hs
@@ -0,0 +1,13 @@
+
+module TestTime where
+
+import Prelude
+import Language.Nomyx
+import Control.Monad
+import Data.Time
+
+myRule :: Rule
+myRule = void $ outputAll_ helperFunction
+
+helperFunction :: String
+helperFunction = "Hello"
diff --git a/src/Nomyx/Core/Context.hs b/src/Nomyx/Core/Context.hs
--- a/src/Nomyx/Core/Context.hs
+++ b/src/Nomyx/Core/Context.hs
@@ -25,6 +25,7 @@
                   "Control.Monad.State",
                   "Control.Monad.State",
                   "Control.Monad.Writer",
+                  "Control.Monad.Loops",
                   "Data.Array",
                   "Data.Bits",
                   "Data.Bool",
@@ -55,7 +56,8 @@
                    "base",
                    "bytestring",
                    "containers",
-                   "text"]
+                   "text",
+                   "time"]
 
 qualImports :: [(String, Maybe String)]
 qualImports = [("Control.Category", Just "C"),
diff --git a/src/Nomyx/Core/Engine.hs b/src/Nomyx/Core/Engine.hs
--- a/src/Nomyx/Core/Engine.hs
+++ b/src/Nomyx/Core/Engine.hs
@@ -2,7 +2,6 @@
 -- | Warning: Nomyx internals (not required to compose rules and play the game)
 -- This module implements game engine.
 -- the module manages the effects of rules over each others.
--- This module is not required
 module Nomyx.Core.Engine(
    -- * Game management
    GameEvent(..),
@@ -15,7 +14,7 @@
    game,
    emptyGame,
    getLoggedGame,
-   gameName,
+   gameName, gameDesc,
    players,
    getVictorious,
 
@@ -28,7 +27,7 @@
 
    -- * Events management
    events,
-   getEventFields,
+   getRemainingSignals,
    getEventInfo,
    getFormField,
 
@@ -51,10 +50,12 @@
    tracePN,
    replaceWith,
    getChoiceEvents,
-   getTextEvents
+   getTextEvents,
+   runEvaluate
    ) where
 
 import Nomyx.Core.Engine.Evaluation
+import Nomyx.Core.Engine.EventEval
 import Nomyx.Core.Engine.Types
 import Nomyx.Core.Engine.GameEvents
 import Nomyx.Core.Engine.Utils
diff --git a/src/Nomyx/Core/Engine/EvalUtils.hs b/src/Nomyx/Core/Engine/EvalUtils.hs
--- a/src/Nomyx/Core/Engine/EvalUtils.hs
+++ b/src/Nomyx/Core/Engine/EvalUtils.hs
@@ -18,22 +18,22 @@
 import Data.Maybe
 import Data.List
 import Control.Applicative
-import Control.Monad.Error
 import Language.Nomyx.Expression
 import Nomyx.Core.Engine.Types
 import Nomyx.Core.Engine.Utils
 import Safe
 
--- find a field result in an environment
-lookupField :: Typeable a => Field a -> FieldAddress -> [FieldResult] -> Maybe a
-lookupField fi fa frs = headMay $ mapMaybe (maybeField fi fa) frs
+-- find a signal occurence in an environment
+lookupSignal :: Typeable a => Signal a -> SignalAddress -> [SignalOccurence] -> Maybe a
+lookupSignal s sa env = headMay $ mapMaybe (getSignalData s sa) env
 
---return the field result if it matches with the input field and address
-maybeField :: Typeable a => Field a -> FieldAddress -> FieldResult -> Maybe a
-maybeField fi fa (FieldResult fi' res fa') = do
-   ((fi'', res') :: (Field a, a)) <- cast (fi', res)
-   if (fi'' == fi) && maybe True (== fa) fa' then (Just res') else Nothing
+--get the signal data from the signal occurence
+getSignalData :: Typeable a => Signal a -> SignalAddress -> SignalOccurence -> Maybe a
+getSignalData s sa (SignalOccurence (SignalData s' res) sa') = do
+   ((s'', res') :: (Signal a, a)) <- cast (s', res)
+   if (s'' == s) && (sa' == sa) then (Just res') else Nothing
 
+
 errorHandler :: EventNumber -> String -> Evaluate ()
 errorHandler en s = do
    rn <- access eRuleNumber
@@ -53,32 +53,8 @@
 liftEval :: EvaluateNE a -> Evaluate a
 liftEval r = runReader r <$> get
 
---extract the game state from an Evaluate
---knowing the rule number performing the evaluation (0 if by the system)
---and the player number to whom display errors (set to Nothing for all players)
---TODO: clean
-runEvalError :: RuleNumber -> (Maybe PlayerNumber) -> Evaluate a -> State Game ()
-runEvalError rn mpn egs = modify (\g -> _eGame $ execState (runEvalError' mpn egs) (EvalEnv rn g))
 
-runEvalError' :: (Maybe PlayerNumber) -> Evaluate a -> State EvalEnv ()
-runEvalError' mpn egs = do
-   e <- runErrorT egs
-   case e of
-      Right _ -> return ()
-      Left e' -> do
-         tracePN (fromMaybe 0 mpn) $ "Error: " ++ e'
-         void $ runErrorT $ log mpn "Error: "
 
-
-runEvaluateNE :: Game -> RuleNumber -> EvaluateNE a -> a
-runEvaluateNE g rn ev = runReader ev (EvalEnv rn g)
-
-runSystemEval :: PlayerNumber -> Evaluate a -> State Game ()
-runSystemEval pn e = runEvalError 0 (Just pn) e
-
-runSystemEval' :: Evaluate a -> State Game ()
-runSystemEval' e = runEvalError 0 Nothing e
-
 focusGame :: State Game a -> Evaluate a
 focusGame = lift . (focus eGame)
 
@@ -118,8 +94,8 @@
    eRuleNumber ~= oldRn
    return a
 
-instance Eq SomeField where
-  (SomeField e1) == (SomeField e2) = e1 === e2
+instance Eq SomeSignal where
+  (SomeSignal e1) == (SomeSignal e2) = e1 === e2
 
 instance Show EventInfo where
    show (EventInfo en rn _ _ s env) =
diff --git a/src/Nomyx/Core/Engine/Evaluation.hs b/src/Nomyx/Core/Engine/Evaluation.hs
--- a/src/Nomyx/Core/Engine/Evaluation.hs
+++ b/src/Nomyx/Core/Engine/Evaluation.hs
@@ -1,10 +1,4 @@
 {-# LANGUAGE GADTs #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE DoAndIfThenElse #-}
 
 -- | Evaluation of a Nomyx expression
 module Nomyx.Core.Engine.Evaluation where
@@ -19,23 +13,21 @@
 import Data.Lens
 import Data.Maybe
 import Data.Todo
-import Data.Either
-import Data.Function (on)
 import Control.Category hiding (id)
 import Control.Applicative
-import Control.Monad.Error.Class (MonadError(..))
+import Control.Monad.Error
 import Language.Nomyx.Expression
 import Nomyx.Core.Engine.Types hiding (_vRuleNumber)
+import Nomyx.Core.Engine.EventEval
 import Nomyx.Core.Engine.EvalUtils
 import Nomyx.Core.Engine.Utils
-import Safe
 import System.Random
 
 
+
 -- * Evaluation
 
 -- | evaluate an effecful expression.
--- The rule number passed is the number of the rule containing the expression.
 evalNomex :: Nomex a -> Evaluate a
 evalNomex (NewVar v a)            = evNewVar v a
 evalNomex (DelVar v)              = evDelVar v
@@ -75,17 +67,6 @@
 evalNomexNE (Simu sim ev)   = evSimu sim ev
 
 
-
---TODO should we also give a rule number to simulate the Nomex with?
--- currently we use the simulating rule number
-evSimu :: Nomex a -> NomexNE Bool -> EvaluateNE Bool
-evSimu sim ev = do
-   rn <- asks _eRuleNumber
-   let s = runEvalError rn Nothing (evalNomex sim)
-   g <- asks _eGame
-   let g' = execState s g
-   return $ runEvaluateNE g' rn (evalNomexNE ev)
-
 evNewVar :: (Typeable a, Show a) => VarName -> a -> Evaluate (Maybe (V a))
 evNewVar name def = do
    (vars, rn) <- accessGame variables
@@ -277,144 +258,15 @@
    putGame randomGen g'
    return a
 
-
-
--- * Events
-
-
-
--- | Get the field at a certain address
-findField :: EventInfo -> FieldAddress -> FormField -> EvaluateNE (Maybe SomeField)
-findField (EventInfo _ _ e _ _ er) addr ft = findField' addr e er ft
-
-findField' :: FieldAddress -> Event e -> [FieldResult] -> FormField -> EvaluateNE (Maybe SomeField)
-findField' []         (BaseEvent f)    _   ft = return $ do
-   ft' <- getFormField (SomeField f)
-   guard (ft' == ft)
-   return $ SomeField f
-findField' (SumL:as)  (SumEvent e1 _)  frs ft = findField' as e1 (filterPath SumL frs) ft
-findField' (SumR:as)  (SumEvent _ e2)  frs ft = findField' as e2 (filterPath SumR frs) ft
-findField' (AppL:as)  (AppEvent e1 _)  frs ft = findField' as e1 (filterPath AppL frs) ft
-findField' (AppR:as)  (AppEvent _ e2)  frs ft = findField' as e2 (filterPath AppR frs) ft
-findField' (BindL:as) (BindEvent e1 _) frs ft = findField' as e1 (filterPath BindL frs) ft
-findField' (BindR:as) (BindEvent e1 f) frs ft = do
-   ter <- getEventResult e1 (filterPath BindL frs) --
-   case ter of
-      Done e2 -> findField' as (f e2) (filterPath BindR frs) ft
-      Todo _  -> return $ Nothing
-findField' (Shortcut:as) (ShortcutEvents es _) frs ft = do
-   msfs <- mapM (\e-> findField' as e frs ft) es
-   return $ headMay $ catMaybes msfs  -- returning the first field that matches
-
-findField' fa _ _ _ = error $ "findField: wrong field address: " ++ (show fa)
-
-filterPath :: FieldAddressElem -> [FieldResult] -> [FieldResult]
-filterPath fa frs = mapMaybe f frs where
-   f (FieldResult fe fr (Just (fa':fas))) | fa == fa' = Just $ FieldResult fe fr (Just fas)
-   f fr = Just fr
-
-getFormField :: SomeField -> Maybe FormField
-getFormField (SomeField (Input pn s (Radio choices)))    = Just $ RadioField pn s (zip [0..] (snd <$> choices))
-getFormField (SomeField (Input pn s Text))               = Just $ TextField pn s
-getFormField (SomeField (Input pn s TextArea))           = Just $ TextAreaField pn s
-getFormField (SomeField (Input pn s Button))             = Just $ ButtonField pn s
-getFormField (SomeField (Input pn s (Checkbox choices))) = Just $ CheckboxField pn s (zip [0..] (snd <$> choices))
-getFormField _ = Nothing
-
-
---get the fields left to be completed in an event
-getEventFields :: EventInfo -> Game -> [(FieldAddress, SomeField)]
-getEventFields (EventInfo _ rn e _ _ env) g = case runEvaluateNE g rn $ getEventResult e env of
-   Done _ -> []
-   Todo a -> a
-
--- compute the result of an event given an environment.
--- in the case the event cannot be computed because some fields results are pending, return that list instead.
-getEventResult :: Event a -> [FieldResult] -> EvaluateNE (Todo (FieldAddress, SomeField) a)
-getEventResult e frs = getEventResult' e frs []
-
-getEventResult' :: Event a -> [FieldResult] -> FieldAddress -> EvaluateNE (Todo (FieldAddress, SomeField) a)
-getEventResult' (PureEvent a)   _   _  = return $ Done a
-getEventResult'  EmptyEvent     _   _  = return $ Todo []
-getEventResult' (SumEvent a b)  ers fa = liftM2 (<|>) (getEventResult' a ers (fa ++ [SumL])) (getEventResult' b ers (fa ++ [SumR]))
-getEventResult' (AppEvent f b)  ers fa = liftM2 (<*>) (getEventResult' f ers (fa ++ [AppL])) (getEventResult' b ers (fa ++ [AppR]))
-getEventResult' (LiftEvent a)   _   _  = evalNomexNE a >>= return . Done
-getEventResult' (BindEvent a f) ers fa = do
-   er <- getEventResult' a ers (fa ++ [BindL])
-   case er of
-      Done a' -> getEventResult' (f a') ers (fa ++ [BindR])
-      Todo bs -> return $ Todo bs
-
-getEventResult' (BaseEvent a)  ers fa = return $ case lookupField a fa ers of
-   Just r  -> Done r
-   Nothing -> Todo [(fa, SomeField a)]
-
-getEventResult' (ShortcutEvents es f) ers fa = do
-  (ers :: [Todo (FieldAddress, SomeField) a]) <- mapM (\e -> getEventResult' e ers (fa ++ [Shortcut])) es -- get the result for each event in the list
-  return $ case f (toMaybe <$> ers) of                                                                    -- apply f to the event results that we already have
-     True  -> Done $ toMaybe <$> ers                                                                      -- if the result is true, we are done. Return the list of maybe results
-     False -> Todo $ join $ lefts $ toEither <$> ers                                                      -- otherwise, return the list of remaining fields to complete from each event
-
-
--- trigger an event
-triggerEvent :: (Typeable e, Show e) => Field e -> e -> Evaluate ()
-triggerEvent e dat = access (eGame >>> events) >>= triggerEvent' (FieldResult e dat Nothing)
-
--- trigger some specific events
-triggerEvent' :: FieldResult -> [EventInfo] -> Evaluate ()
-triggerEvent' res evs = do
-   evs' <- mapM (liftEval . (updateEventInfo res)) (sortBy (compare `on` _ruleNumber) evs)  -- get all the EventInfos updated with the field
-   (eGame >>> events) %= union (map fst evs')                                               -- store them
-   void $ mapM triggerIfComplete evs'                                                       -- trigger the handlers for completed events
-
--- if the event is complete, trigger its handler
-triggerIfComplete :: (EventInfo, Maybe SomeData) -> Evaluate ()
-triggerIfComplete (EventInfo en rn _ h SActive _, Just (SomeData val)) = case (cast val) of
-   Just a ->  void $ withRN rn $ (evalNomex $ h (en, a)) `catchError` (errorHandler en)
-   Nothing -> error "Bad trigger data type"
-triggerIfComplete _ = return ()
-
--- update the EventInfo with the field result.
--- get the event result if all fields are completed
-updateEventInfo :: FieldResult -> EventInfo -> EvaluateNE (EventInfo, Maybe SomeData)
-updateEventInfo (FieldResult field dat addr) ei@(EventInfo _ _ ev _ _ envi) = do
+--TODO should we also give a rule number to simulate the Nomex with?
+-- currently we use the simulating rule number
+evSimu :: Nomex a -> NomexNE Bool -> EvaluateNE Bool
+evSimu sim ev = do
+   rn <- asks _eRuleNumber
+   let s = runEvalError rn Nothing (evalNomex sim)
    g <- asks _eGame
-   let eventRes = FieldResult field dat addr
-   er <- getEventResult ev (eventRes : envi)
-   return $ case er of                                                      -- check if the event will be complete
-      Todo _ -> if (SomeField field) `elem` (map snd $ getEventFields ei g) -- is yes, check if our field is really a missing field of the event
-         then (env ^=  (eventRes : envi) $ ei, Nothing)                     -- some fields are left to complete: add ours in the environment
-         else (ei, Nothing)                                                 -- field not found: do nothing
-      Done a -> (env ^=  [] $ ei, Just $ SomeData a)                        -- the event is complete: empty the environment and output the result
-
--- * input triggers
-
--- trigger the input event with the input data
-triggerInput :: EventNumber -> FieldAddress -> FormField -> InputData -> Evaluate ()
-triggerInput en fa ft ir = do
-   evs <- access (eGame >>> events)
-   let mei = find ((== en) . getL eventNumber) evs
-   when (isJust mei) $ execInputHandler ir fa ft (fromJust mei)
-
--- execute the corresponding handler
-execInputHandler :: InputData -> FieldAddress -> FormField -> EventInfo -> Evaluate ()
-execInputHandler ir fa ft ei@(EventInfo _ _ _ _ SActive _) = do
-   i <- liftEval $ findField ei fa ft
-   case i of
-      Just sf -> execInputHandler' ir sf fa ei
-      Nothing -> logAll $ "Input not found, InputData=" ++ (show ir) ++ " FieldAddress=" ++ (show fa) ++ " FormField=" ++ (show ft)
-execInputHandler _ _ _ _ = return ()
-
--- execute the event handler using the data received from user
-execInputHandler' :: InputData -> SomeField -> FieldAddress -> EventInfo -> Evaluate ()
-execInputHandler' (TextData s)      (SomeField e@(Input _ _ (Text)))        fa ei = triggerEvent' (FieldResult e s                     (Just fa)) [ei]
-execInputHandler' (TextAreaData s)  (SomeField e@(Input _ _ (TextArea)))    fa ei = triggerEvent' (FieldResult e s                     (Just fa)) [ei]
-execInputHandler' (ButtonData)      (SomeField e@(Input _ _ (Button)))      fa ei = triggerEvent' (FieldResult e ()                    (Just fa)) [ei]
-execInputHandler' (RadioData i)     (SomeField e@(Input _ _ (Radio cs)))    fa ei = triggerEvent' (FieldResult e (fst $ cs!!i)         (Just fa)) [ei]
-execInputHandler' (CheckboxData is) (SomeField e@(Input _ _ (Checkbox cs))) fa ei = triggerEvent' (FieldResult e (fst <$> cs `sel` is) (Just fa)) [ei]
-execInputHandler' _ _ _ _ = return ()
-
-
+   let g' = execState s g
+   return $ runEvaluateNE g' rn (evalNomexNE ev)
 
 -- * misc
 
@@ -453,7 +305,40 @@
    vic <- access (eGame >>> victory)
    when (isJust vic && _vRuleNumber (fromJust vic) == rn) $ void $ (eGame >>> victory) ~= Nothing
 
+--extract the game state from an Evaluate
+--knowing the rule number performing the evaluation (0 if by the system)
+--and the player number to whom display errors (set to Nothing for all players)
+--TODO: clean
+runEvalError :: RuleNumber -> (Maybe PlayerNumber) -> Evaluate a -> State Game ()
+runEvalError rn mpn egs = modify (\g -> _eGame $ execState (runEvalError' mpn egs) (EvalEnv rn g evalNomex evalNomexNE))
 
+runEvalError' :: (Maybe PlayerNumber) -> Evaluate a -> State EvalEnv ()
+runEvalError' mpn egs = do
+   e <- runErrorT egs
+   case e of
+      Right _ -> return ()
+      Left e' -> do
+         tracePN (fromMaybe 0 mpn) $ "Error: " ++ e'
+         void $ runErrorT $ log mpn "Error: "
+
+runSystemEval :: PlayerNumber -> Evaluate a -> State Game ()
+runSystemEval pn e = runEvalError 0 (Just pn) e
+
+runSystemEval' :: Evaluate a -> State Game ()
+runSystemEval' e = runEvalError 0 Nothing e
+
+--get the signals left to be completed in an event
+getRemainingSignals :: EventInfo -> Game -> [(SignalAddress, SomeSignal)]
+getRemainingSignals (EventInfo _ rn e _ _ env) g = case runEvaluateNE g rn (getEventResult e env) of
+   Done _ -> []
+   Todo a -> a
+
+runEvaluateNE :: Game -> RuleNumber -> EvaluateNE a -> a
+runEvaluateNE g rn ev = runReader ev (EvalEnv rn g evalNomex evalNomexNE)
+
+runEvaluate :: Game -> RuleNumber -> State EvalEnv a -> a
+runEvaluate g rn ev = evalState ev (EvalEnv rn g evalNomex evalNomexNE)
+
 -- | Show instance for Game
 -- showing a game involves evaluating some parts (such as victory and outputs)
 instance Show Game where
@@ -473,7 +358,7 @@
 displayEvent g ei@(EventInfo en rn _ _ s env) =
    "event num: " ++ (show en) ++
    ", rule num: " ++ (show rn) ++
-   ", event fields: " ++ (show $ getEventFields ei g) ++ --TODO: display also event result?
+   ", remaining signals: " ++ (show $ getRemainingSignals ei g) ++ --TODO: display also event result?
    ", envs: " ++ (show env) ++
    ", status: " ++ (show s)
 
@@ -484,8 +369,3 @@
    ", by pn: " ++ (show mpn) ++
    ", output: " ++ (show $ evalOutput g o) ++
    ", status: " ++ (show s)
-
-displayEvent' :: EventInfo -> EvaluateNE String
-displayEvent' ei = do
-   (EvalEnv _ g) <- ask
-   return $ displayEvent g ei
diff --git a/src/Nomyx/Core/Engine/EventEval.hs b/src/Nomyx/Core/Engine/EventEval.hs
new file mode 100644
--- /dev/null
+++ b/src/Nomyx/Core/Engine/EventEval.hs
@@ -0,0 +1,173 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE GADTs #-}
+
+-- | Evaluation of the events
+module Nomyx.Core.Engine.EventEval where
+
+import Prelude hiding ((.), log)
+import Control.Monad
+import Control.Monad.State
+import Control.Monad.Reader
+import Data.List
+import Data.Typeable
+import Data.Lens
+import Data.Maybe
+import Data.Todo
+import Data.Either
+import Data.Function (on)
+import Control.Category hiding (id)
+import Control.Applicative
+import Control.Monad.Error.Class (MonadError(..))
+import Language.Nomyx.Expression
+import Nomyx.Core.Engine.Types hiding (_vRuleNumber)
+import Nomyx.Core.Engine.EvalUtils
+import Nomyx.Core.Engine.Utils
+import Safe
+
+-- * Event triggers
+
+-- trigger an event
+triggerEvent :: (Typeable e, Show e) => Signal e -> e -> Evaluate ()
+triggerEvent s dat = do
+   evs <- access (eGame >>> events)
+   triggerEvent' (SignalData s dat) Nothing evs
+
+-- trigger some specific signal
+triggerEvent' :: SignalData -> Maybe SignalAddress -> [EventInfo] -> Evaluate ()
+triggerEvent' sd msa evs = do
+   let evs' = sortBy (compare `on` _ruleNumber) evs
+   eids <- mapM (liftEval . (getUpdatedEventInfo sd msa)) evs'  -- get all the EventInfos updated with the field
+   (eGame >>> events) %= union (map fst eids)                   -- store them
+   void $ mapM triggerIfComplete eids                           -- trigger the handlers for completed events
+
+-- if the event is complete, trigger its handler
+triggerIfComplete :: (EventInfo, Maybe SomeData) -> Evaluate ()
+triggerIfComplete (EventInfo en rn _ h SActive _, Just (SomeData val)) = case (cast val) of
+   Just a -> do
+      evalNomex <- gets evalNomexFunc
+      void $ withRN rn $ (evalNomex $ h (en, a)) `catchError` (errorHandler en)
+   Nothing -> error "Bad trigger data type"
+triggerIfComplete _ = return ()
+
+-- get update the EventInfo updated with the signal data.
+-- get the event result if all signals are completed
+getUpdatedEventInfo :: SignalData -> Maybe SignalAddress -> EventInfo -> EvaluateNE (EventInfo, Maybe SomeData)
+getUpdatedEventInfo sd@(SignalData signal _) addr ei@(EventInfo _ _ ev _ _ envi) = do
+   trs <- getEventResult ev envi
+   case trs of
+      Todo rs -> case find (\(sa, ss) -> (ss == SomeSignal signal) && maybe True (==sa) addr) rs of -- check if our signal match one of the remaining signals
+         Just (sa, _) -> do
+            let envi' = (SignalOccurence sd sa) : envi
+            er <- getEventResult ev envi'                                                           -- add our event to the environment and get the result
+            return $ case er of
+               Todo _ -> (env ^=  envi' $ ei, Nothing)                                              -- some other signals are left to complete: add ours in the environment
+               Done a -> (env ^=  [] $ ei, Just $ SomeData a)                                       -- event complete: return the final data result
+         Nothing -> return (ei, Nothing)                                                            -- our signal does not belong to this event.
+      Done a -> return (env ^=  [] $ ei, Just $ SomeData a)
+
+--get the signals left to be completed in an event
+getRemainingSignals' :: EventInfo -> EvaluateNE [(SignalAddress, SomeSignal)]
+getRemainingSignals' (EventInfo _ _ e _ _ env) = do
+   tr <- getEventResult e env
+   return $ case tr of
+      Done _ -> []
+      Todo a -> a
+
+-- compute the result of an event given an environment.
+-- in the case the event cannot be computed because some signals results are pending, return that list instead.
+getEventResult :: Event a -> [SignalOccurence] -> EvaluateNE (Todo (SignalAddress, SomeSignal) a)
+getEventResult e frs = getEventResult' e frs []
+
+-- compute the result of an event given an environment. The third argument is used to know where we are in the event tree.
+getEventResult' :: Event a -> [SignalOccurence] -> SignalAddress -> EvaluateNE (Todo (SignalAddress, SomeSignal) a)
+getEventResult' (PureEvent a)   _   _  = return $ Done a
+getEventResult'  EmptyEvent     _   _  = return $ Todo []
+getEventResult' (SumEvent a b)  ers fa = liftM2 (<|>) (getEventResult' a ers (fa ++ [SumL])) (getEventResult' b ers (fa ++ [SumR]))
+getEventResult' (AppEvent f b)  ers fa = liftM2 (<*>) (getEventResult' f ers (fa ++ [AppL])) (getEventResult' b ers (fa ++ [AppR]))
+getEventResult' (LiftEvent a)   _   _  = do
+   evalNomexNE <- asks evalNomexNEFunc
+   r <- evalNomexNE a
+   return $ Done r
+getEventResult' (BindEvent a f) ers fa = do
+   er <- getEventResult' a ers (fa ++ [BindL])
+   case er of
+      Done a' -> getEventResult' (f a') ers (fa ++ [BindR])
+      Todo bs -> return $ Todo bs
+
+getEventResult' (SignalEvent a)  ers fa = return $ case lookupSignal a fa ers of
+   Just r  -> Done r
+   Nothing -> Todo [(fa, SomeSignal a)]
+
+getEventResult' (ShortcutEvents es f) ers fa = do
+  (ers :: [Todo (SignalAddress, SomeSignal) a]) <- mapM (\e -> getEventResult' e ers (fa ++ [Shortcut])) es -- get the result for each event in the list
+  return $ case f (toMaybe <$> ers) of                                                                      -- apply f to the event results that we already have
+     True  -> Done $ toMaybe <$> ers                                                                        -- if the result is true, we are done. Return the list of maybe results
+     False -> Todo $ join $ lefts $ toEither <$> ers                                                        -- otherwise, return the list of remaining fields to complete from each event
+
+
+-- * Input triggers
+
+-- trigger the input form with the input data
+triggerInput :: FormField -> InputData -> SignalAddress -> EventNumber -> Evaluate ()
+triggerInput ff id sa en = do
+   evs <- access (eGame >>> events)
+   let mei = find ((== en) . getL eventNumber) evs
+   when (isJust mei) $ triggerInputSignal id sa ff (fromJust mei)
+
+-- trigger the input signal with the input data
+triggerInputSignal :: InputData -> SignalAddress -> FormField -> EventInfo -> Evaluate ()
+triggerInputSignal id sa ff ei@(EventInfo _ _ _ _ SActive _) = do
+   i <- liftEval $ findField ff sa ei
+   case i of
+      Just sf -> triggerInputSignal' id sf sa ei
+      Nothing -> logAll $ "Input not found, InputData=" ++ (show id) ++ " SignalAddress=" ++ (show sa) ++ " FormField=" ++ (show ff)
+triggerInputSignal _ _ _ _ = return ()
+
+-- trigger the input signal with the input data
+triggerInputSignal' :: InputData -> SomeSignal -> SignalAddress -> EventInfo -> Evaluate ()
+triggerInputSignal' (TextData s)      (SomeSignal e@(Input _ _ (Text)))        sa ei = triggerEvent' (SignalData e s)                     (Just sa) [ei]
+triggerInputSignal' (TextAreaData s)  (SomeSignal e@(Input _ _ (TextArea)))    sa ei = triggerEvent' (SignalData e s)                     (Just sa) [ei]
+triggerInputSignal' (ButtonData)      (SomeSignal e@(Input _ _ (Button)))      sa ei = triggerEvent' (SignalData e ())                    (Just sa) [ei]
+triggerInputSignal' (RadioData i)     (SomeSignal e@(Input _ _ (Radio cs)))    sa ei = triggerEvent' (SignalData e (fst $ cs!!i))         (Just sa) [ei]
+triggerInputSignal' (CheckboxData is) (SomeSignal e@(Input _ _ (Checkbox cs))) sa ei = triggerEvent' (SignalData e (fst <$> cs `sel` is)) (Just sa) [ei]
+triggerInputSignal' _ _ _ _ = return ()
+
+
+-- | Get the form field at a certain address
+findField :: FormField -> SignalAddress -> EventInfo -> EvaluateNE (Maybe SomeSignal)
+findField ff addr (EventInfo _ _ e _ _ env) = findField' addr e env ff
+
+findField' :: SignalAddress -> Event e -> [SignalOccurence] -> FormField -> EvaluateNE (Maybe SomeSignal)
+findField' []         (SignalEvent f)    _   ff = return $ do
+   ff' <- getFormField (SomeSignal f)
+   guard (ff' == ff)
+   return $ SomeSignal f
+findField' (SumL:as)  (SumEvent e1 _)  env ff = findField' as e1 (filterPath SumL env) ff
+findField' (SumR:as)  (SumEvent _ e2)  env ff = findField' as e2 (filterPath SumR env) ff
+findField' (AppL:as)  (AppEvent e1 _)  env ff = findField' as e1 (filterPath AppL env) ff
+findField' (AppR:as)  (AppEvent _ e2)  env ff = findField' as e2 (filterPath AppR env) ff
+findField' (BindL:as) (BindEvent e1 _) env ff = findField' as e1 (filterPath BindL env) ff
+findField' (BindR:as) (BindEvent e1 f) env ff = do
+   ter <- getEventResult e1 (filterPath BindL env)
+   case ter of
+      Done e2 -> findField' as (f e2) (filterPath BindR env) ff
+      Todo _  -> return $ Nothing
+findField' (Shortcut:as) (ShortcutEvents es _) env ff = do
+   msfs <- mapM (\e-> findField' as e env ff) es
+   return $ headMay $ catMaybes msfs  -- returning the first field that matches
+
+findField' fa _ _ _ = error $ "findField: wrong field address: " ++ (show fa)
+
+-- | removes one element of signal address for all signal occurences
+filterPath :: SignalAddressElem -> [SignalOccurence] -> [SignalOccurence]
+filterPath fa env = mapMaybe f env where
+   f (SignalOccurence sd (fa':fas)) | fa == fa' = Just $ SignalOccurence sd fas
+   f fr = Just fr
+
+getFormField :: SomeSignal -> Maybe FormField
+getFormField (SomeSignal (Input pn s (Radio choices)))    = Just $ RadioField    pn s (zip [0..] (snd <$> choices))
+getFormField (SomeSignal (Input pn s Text))               = Just $ TextField     pn s
+getFormField (SomeSignal (Input pn s TextArea))           = Just $ TextAreaField pn s
+getFormField (SomeSignal (Input pn s Button))             = Just $ ButtonField   pn s
+getFormField (SomeSignal (Input pn s (Checkbox choices))) = Just $ CheckboxField pn s (zip [0..] (snd <$> choices))
+getFormField _ = Nothing
diff --git a/src/Nomyx/Core/Engine/GameEvents.hs b/src/Nomyx/Core/Engine/GameEvents.hs
--- a/src/Nomyx/Core/Engine/GameEvents.hs
+++ b/src/Nomyx/Core/Engine/GameEvents.hs
@@ -9,7 +9,7 @@
 import Data.List
 import Language.Nomyx.Expression
 import Nomyx.Core.Engine.Evaluation
-import Nomyx.Core.Engine.EvalUtils
+import Nomyx.Core.Engine.EventEval
 import Nomyx.Core.Engine.Types
 import Nomyx.Core.Engine.Utils
 import Data.Lens
@@ -23,7 +23,7 @@
 data GameEvent = JoinGame          PlayerNumber PlayerName
                | LeaveGame         PlayerNumber
                | ProposeRuleEv     PlayerNumber SubmitRule
-               | InputResult       PlayerNumber EventNumber FieldAddress FormField InputData
+               | InputResult       PlayerNumber EventNumber SignalAddress FormField InputData
                | GLog              (Maybe PlayerNumber) String
                | TimeEvent         UTCTime
                | SystemAddRule     SubmitRule
@@ -126,20 +126,20 @@
    void $ logs %= (Log mpn time s : )
 
 -- | the user has provided an input result
-inputResult :: PlayerNumber -> EventNumber -> FieldAddress -> FormField -> InputData -> State Game ()
-inputResult pn en fa ft ir = do
-   tracePN pn $ "input result: EventNumber " ++ show en ++ ", FieldAddress " ++ show fa ++ ", Form " ++ show ft ++ ", choice " ++ show ir
-   runSystemEval pn $ triggerInput en fa ft ir
+inputResult :: PlayerNumber -> EventNumber -> SignalAddress -> FormField -> InputData -> State Game ()
+inputResult pn en sa ff id = do
+   tracePN pn $ "input result: EventNumber " ++ show en ++ ", SignalAddress " ++ show sa ++ ", Form " ++ show ff ++ ", choice " ++ show id
+   runSystemEval pn $ triggerInput ff id sa en
 
 getGameTimes :: Game -> [UTCTime]
 getGameTimes g = concatMap (\ei -> getTimes ei g) (_events g)
 
 getTimes :: EventInfo -> Game -> [UTCTime]
-getTimes ei g = mapMaybe getTime (map snd $ getEventFields ei g)
+getTimes ei g = mapMaybe getTime (map snd $ getRemainingSignals ei g)
 
 
-getTime :: SomeField -> Maybe UTCTime
-getTime (SomeField (Time t)) = Just t
+getTime :: SomeSignal -> Maybe UTCTime
+getTime (SomeSignal (Time t)) = Just t
 getTime _                    = Nothing
 
 -- | A helper function to run the game state.
diff --git a/src/Nomyx/Core/Engine/Test.hs b/src/Nomyx/Core/Engine/Test.hs
--- a/src/Nomyx/Core/Engine/Test.hs
+++ b/src/Nomyx/Core/Engine/Test.hs
@@ -13,7 +13,7 @@
 import Language.Nomyx.Vote
 import Language.Nomyx.Examples
 import Nomyx.Core.Engine.Evaluation
-import Nomyx.Core.Engine.EvalUtils
+import Nomyx.Core.Engine.EventEval
 import Nomyx.Core.Engine.Types
 import Nomyx.Core.Engine.Utils
 import Control.Monad.State
@@ -51,22 +51,22 @@
                        _rStatus       = Pending,
                        _rAssessedBy   = Nothing}
 
-execRuleEvent :: (Show e, Typeable e) => Nomex a -> Field e -> e -> Game
+execRuleEvent :: (Show e, Typeable e) => Nomex a -> Signal e -> e -> Game
 execRuleEvent r f d = execState (runSystemEval' $ evalNomex r >> triggerEvent f d) testGame
 
-execRuleEvents :: (Show e, Typeable e) => Nomex a -> [(Field e, e)] -> Game
+execRuleEvents :: (Show e, Typeable e) => Nomex a -> [(Signal e, e)] -> Game
 execRuleEvents f eds = execState (runSystemEval' $ evalNomex f >> mapM (\(a,b) -> triggerEvent a b) eds) testGame
 
-execRuleInput :: Nomex a -> EventNumber -> FieldAddress -> FormField -> InputData -> Game
-execRuleInput r en fa ft d = execState (runSystemEval' $ evalNomex r >> triggerInput en fa ft d) testGame
+execRuleInput :: Nomex a -> EventNumber -> SignalAddress -> FormField -> InputData -> Game
+execRuleInput r en sa ff id = execState (runSystemEval' $ evalNomex r >> triggerInput ff id sa en) testGame
 
-execRuleInputs :: Nomex a -> EventNumber -> [(FieldAddress, FormField, InputData)] -> Game
-execRuleInputs r en fads = execState (runSystemEval' $ evalNomex r >> mapM (\(fa, ft, d) -> triggerInput en fa ft d) fads) testGame
+execRuleInputs :: Nomex a -> EventNumber -> [(SignalAddress, FormField, InputData)] -> Game
+execRuleInputs r en fads = execState (runSystemEval' $ evalNomex r >> mapM (\(sa, ff, id) -> triggerInput ff id sa en) fads) testGame
 
 execRuleGame :: Nomex a -> Game -> Game
 execRuleGame r g = execState (runSystemEval' $ void $ evalNomex r) g
 
-execRuleEventGame :: (Show e, Typeable e) => Nomex a -> Field e -> e -> Game -> Game
+execRuleEventGame :: (Show e, Typeable e) => Nomex a -> Signal e -> e -> Game -> Game
 execRuleEventGame r f d g = execState (runSystemEval' $ evalNomex r >> (triggerEvent f d)) g
 
 execRule :: Nomex a -> Game
@@ -118,7 +118,8 @@
          ("test two separate events", testTwoEventsEx),
          ("test monadic event", testMonadicEventEx),
          ("test monadic event2", testMonadicEventEx2),
-         ("test shortcut event", testShorcutEventEx)
+         ("test shortcut event", testShorcutEventEx),
+         ("test double event", testDoubleEventEx)
          ]
 
 allTests = all snd tests
@@ -224,7 +225,7 @@
 testUserInputWrite = do
     newVar_ "vote" (Nothing::Maybe Choice2)
     onEvent_ (messageEvent (Msg "voted" :: Msg ())) h2
-    void $ onEvent_ (BaseEvent $ Input 1 "Vote for" (Radio [(Me, "Me"), (You, "You")])) h1 where
+    void $ onEvent_ (SignalEvent $ Input 1 "Vote for" (Radio [(Me, "Me"), (You, "You")])) h1 where
         h1 a = do
             writeVar (V "vote") (Just a)
             SendMessage (Msg "voted") ()
@@ -313,8 +314,8 @@
     when timeEvent $ evTriggerTime date2
 
 --Trigger a vote event (0 for positive, 1 for negative), using event details
-triggerVote :: Int -> (EventNumber, FieldAddress, PlayerNumber, String) -> Evaluate ()
-triggerVote res (en, fa, pn, t) = triggerInput en fa (RadioField pn t [(0,"For"),(1,"Against")]) (RadioData res)
+triggerVote :: Int -> (EventNumber, SignalAddress, PlayerNumber, String) -> Evaluate ()
+triggerVote res (en, sa, pn, t) = triggerInput (RadioField pn t [(0,"For"),(1,"Against")]) (RadioData res) sa en
 
 voteGame' :: Int -> Int -> Int -> Bool -> Rule -> Game
 voteGame' positives negatives notVoted timeEvent rf  = voteGameActions positives negatives notVoted timeEvent $ addActivateRule rf 1
@@ -423,7 +424,7 @@
 testMonadicEvent2PlayerArrive = flip execState testGame {_players = []} $ runSystemEval' $ do
     addActivateRule testMonadicEvent2 1
     addPlayer (PlayerInfo 1 "coco 1" Nothing)
-    triggerInput 1 [BindR] (TextField 1 "") (TextData "coco2")
+    triggerInput (TextField 1 "") (TextData "coco2") [BindR] 1
 
 testMonadicEventEx2 = isOutput "coco2" testMonadicEvent2PlayerArrive
 
@@ -439,31 +440,48 @@
 testShorcutEventEx = isOutput "coco1" g where
    g = execRuleInputs testShorcutEvent 1 [([Shortcut], (TextField 1 "a"), TextData "coco1")]
 
+--This event waits for two identical signals to fire
+testDoubleEvent :: Rule
+testDoubleEvent = do
+   let displayMsg a = void $ newOutput_ Nothing (_playerName a)
+   let e :: Event PlayerInfo
+       e = do
+       playerEvent Arrive
+       playerEvent Arrive
+   void $ onEvent_ e displayMsg
 
+testDoubleEvent2PlayerArrive :: Game
+testDoubleEvent2PlayerArrive = flip execState testGame {_players = []} $ runSystemEval' $ do
+    addActivateRule testDoubleEvent 1
+    addPlayer (PlayerInfo 1 "coco1" Nothing)
+    addPlayer (PlayerInfo 2 "coco2" Nothing)
+
+testDoubleEventEx = isOutput "coco2" testDoubleEvent2PlayerArrive
+
 --Get all event numbers of type choice (radio button)
-getChoiceEvents :: State EvalEnv [(EventNumber, FieldAddress, PlayerNumber, String)]
+getChoiceEvents :: State EvalEnv [(EventNumber, SignalAddress, PlayerNumber, String)]
 getChoiceEvents = do
    evs <- access (eGame >>> events)
    g <- access eGame
    return $ [(_eventNumber ev, fa, pn, t) | ev <- evs, (fa, pn, t) <- getInputChoices ev g]
 
-getInputChoices :: EventInfo -> Game -> [(FieldAddress, PlayerNumber, String)]
-getInputChoices ei g = mapMaybe isInput (getEventFields ei g) where
-   isInput :: (FieldAddress, SomeField) -> Maybe (FieldAddress, PlayerNumber, String)
-   isInput (fa, (SomeField (Input pn t (Radio _)))) = Just (fa, pn, t)
+getInputChoices :: EventInfo -> Game -> [(SignalAddress, PlayerNumber, String)]
+getInputChoices ei g = mapMaybe isInput (getRemainingSignals ei g) where
+   isInput :: (SignalAddress, SomeSignal) -> Maybe (SignalAddress, PlayerNumber, String)
+   isInput (fa, (SomeSignal (Input pn t (Radio _)))) = Just (fa, pn, t)
    isInput _ = Nothing
 
 --Get all event numbers of type text (text field)
-getTextEvents :: State Game [(EventNumber, FieldAddress)]
+getTextEvents :: State Game [(EventNumber, SignalAddress)]
 getTextEvents = do
    evs <- access events
    g <- get
    return $ [(_eventNumber ev, fa) | ev <- evs, fa <- getInputTexts ev g]
 
-getInputTexts :: EventInfo -> Game -> [FieldAddress]
-getInputTexts ei g = mapMaybe isInput (getEventFields ei g) where
-   isInput :: (t, SomeField) -> Maybe t
-   isInput (fa, (SomeField (Input _ _ Text))) = Just fa
+getInputTexts :: EventInfo -> Game -> [SignalAddress]
+getInputTexts ei g = mapMaybe isInput (getRemainingSignals ei g) where
+   isInput :: (t, SomeSignal) -> Maybe t
+   isInput (fa, (SomeSignal (Input _ _ Text))) = Just fa
    isInput _ = Nothing
 
 addPlayer :: PlayerInfo -> Evaluate Bool
diff --git a/src/Nomyx/Core/Engine/Types.hs b/src/Nomyx/Core/Engine/Types.hs
--- a/src/Nomyx/Core/Engine/Types.hs
+++ b/src/Nomyx/Core/Engine/Types.hs
@@ -5,6 +5,7 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE RankNTypes #-}
 
 -- | Types for the engine
 module Nomyx.Core.Engine.Types where
@@ -21,14 +22,21 @@
 import GHC.Generics
 import System.Random
 
+
 -- * Evaluation
 
+-- | Environment necessary for the evaluation of any nomyx expressions or events
 --TODO: should the first field be a "Maybe RuleNumber"?
 --Indeed an evaluation is not always performed by a rule but also by the system (in which case we currently use rule number 0)
-data EvalEnv = EvalEnv { _eRuleNumber :: RuleNumber,  -- number of the rule requesting the evaluation
-                         _eGame :: Game}              -- game to be read/modified
+data EvalEnv = EvalEnv { _eRuleNumber :: RuleNumber,                             -- number of the rule requesting the evaluation
+                         _eGame :: Game,                                         -- game to be read/modified
+                         evalNomexFunc :: forall a. Nomex a -> Evaluate a,       -- evaluation function
+                         evalNomexNEFunc :: forall b. NomexNE b -> EvaluateNE b} -- evaluation function without effect
 
-type Evaluate   a = ErrorT String (State EvalEnv) a
+-- | Environment necessary for the evaluation of Nomex
+type Evaluate   a = ErrorT String (State EvalEnv ) a
+
+-- | Environment necessary for the evaluation of NomexNE
 type EvaluateNE a = Reader EvalEnv a
 
 -- * Game
@@ -49,7 +57,7 @@
                    _randomGen   :: StdGen}
                    deriving (Typeable)
 
-data GameDesc = GameDesc { _desc :: String, _agora :: String} deriving (Eq, Show, Read, Ord)
+data GameDesc = GameDesc { _desc :: String, _forumURL :: String} deriving (Eq, Show, Read, Ord)
 
 instance Eq Game where
    (Game {_gameName=gn1}) == (Game {_gameName=gn2}) = gn1 == gn2
@@ -85,17 +93,17 @@
 -- * Events
 
 -- a form field
-data FormField = RadioField PlayerNumber String [(Int, String)]
-               | TextField PlayerNumber String
+data FormField = RadioField    PlayerNumber String [(Int, String)]
+               | TextField     PlayerNumber String
                | TextAreaField PlayerNumber String
-               | ButtonField PlayerNumber String
+               | ButtonField   PlayerNumber String
                | CheckboxField PlayerNumber String [(Int, String)]
                  deriving (Show, Read, Ord, Eq, Generic)
 
 -- data sent back by the form fields
-data InputData = RadioData Int
+data InputData = RadioData    Int
                | CheckboxData [Int]
-               | TextData String
+               | TextData     String
                | TextAreaData String
                | ButtonData
                  deriving (Show, Read, Eq, Ord)
diff --git a/src/Nomyx/Core/Mail.hs b/src/Nomyx/Core/Mail.hs
--- a/src/Nomyx/Core/Mail.hs
+++ b/src/Nomyx/Core/Mail.hs
@@ -13,7 +13,6 @@
 import Text.Blaze.Html.Renderer.String
 import Network.Mail.Mime hiding (mailTo)
 import Safe
-import Data.List
 import Data.Text(Text, pack)
 import Data.Maybe
 import qualified Data.Text.Lazy as B
@@ -69,12 +68,11 @@
 newRuleObject :: PlayerName -> String
 newRuleObject name = "[Nomyx] New rule posted by player " ++ name ++ "!"
 
-sendMailsNewRule :: Session -> SubmitRule -> PlayerNumber -> IO ()
-sendMailsNewRule s sr pn = when (_sendMails $ _mSettings $ _multi s) $ do
-   putStrLn "Sending mails"
-   gi <- fromJustNote "sendMailsNewRule" <$> getPlayersGame pn s
+sendMailsNewRule :: Session -> SubmitRule -> PlayerNumber -> GameInfo -> IO ()
+sendMailsNewRule s sr pn gi = when (_sendMails $ _mSettings $ _multi s) $ do
    guard (_isPublic gi)
-   let sendMailsTo = delete pn (map _playerNumber (_players $ _game $ _loggedGame gi))
+   putStrLn "Sending mails"
+   let sendMailsTo = map _playerNumber (_players $ _game $ _loggedGame gi)
    proposer <- Nomyx.Core.Profile.getPlayerName pn s
    profiles <- mapM (getProfile s) sendMailsTo
    mapM_ (send proposer (_net $ _mSettings $ _multi s) sr) (_pPlayerSettings <$> catMaybes profiles)
diff --git a/src/Nomyx/Core/Multi.hs b/src/Nomyx/Core/Multi.hs
--- a/src/Nomyx/Core/Multi.hs
+++ b/src/Nomyx/Core/Multi.hs
@@ -41,7 +41,7 @@
 getTimeEvents now m = do
    let games = map (_game . _loggedGame) (_gameInfos m)
    let times = concatMap getGameTimes games
-   return $ filter (\t -> t <= now && t > (-2) `addUTCTime` now) times
+   return $ filter (\t -> t <= now && t > (-32) `addUTCTime` now) times
 
 -- | the initial rule set for a game.
 rVoteUnanimity = SubmitRule "Unanimity Vote"
@@ -71,9 +71,6 @@
                        _startedAt  = date}
 
    execStateT (initialGame sh) lg
-
-getGameByName :: GameName -> StateT Multi IO (Maybe GameInfo)
-getGameByName gn =  find ((==gn) . getL gameNameLens) <$> access gameInfos
 
 defaultMulti :: Settings -> Multi
 defaultMulti = Multi []
diff --git a/src/Nomyx/Core/Profile.hs b/src/Nomyx/Core/Profile.hs
--- a/src/Nomyx/Core/Profile.hs
+++ b/src/Nomyx/Core/Profile.hs
@@ -7,8 +7,6 @@
 module Nomyx.Core.Profile where
 
 import Language.Nomyx
-
-
 import Control.Monad.Reader.Class (MonadReader(..))
 import Control.Monad.Catch (bracket)
 import Control.Concurrent.STM
@@ -28,7 +26,6 @@
 import System.FilePath ((</>))
 import Nomyx.Core.Quotes
 import Nomyx.Core.Types
-import Nomyx.Core.Utils
 import Nomyx.Core.Engine
 
 -- | set 'ProfileData' for UserId
@@ -45,10 +42,9 @@
    let pfs = toList profilesData
    let filtered = filter (\a -> _pPlayerNumber a == uid) pfs
    return $ headMay filtered
-   --return $ getOne $ profilesData @= uid
 
 initialProfileData :: PlayerNumber -> PlayerSettings -> ProfileData
-initialProfileData uid ps = ProfileData uid ps Nothing (Just (exampleRule, "")) NoUpload False
+initialProfileData uid ps = ProfileData uid ps (Just (exampleRule, "")) NoUpload False
 
 exampleRule :: SubmitRule
 exampleRule = SubmitRule "" "" [cr|
@@ -127,15 +123,6 @@
 getPlayerInGameName g pn = case find ((==pn) . getL playerNumber) (_players g) of
    Nothing -> error "getPlayersName': No player by that number in that game"
    Just pm -> _playerName pm
-
--- | returns the game the player is in
-getPlayersGame :: PlayerNumber -> Session -> IO (Maybe GameInfo)
-getPlayersGame pn s = do
-   pfd <- A.query' (acidProfileData $ _profiles s) (AskProfileData pn)
-   let mgn = _pViewingGame $ fromJustNote "getPlayersGame" pfd
-   return $ do
-      gn <- mgn
-      find ((== gn) . getL gameNameLens) (_gameInfos $ _multi s) --checks if any game by that name exists
 
 getAllProfiles :: Session -> IO [ProfileData]
 getAllProfiles s = A.query' (acidProfileData $ _profiles s) AskProfilesData
diff --git a/src/Nomyx/Core/Quotes.hs b/src/Nomyx/Core/Quotes.hs
--- a/src/Nomyx/Core/Quotes.hs
+++ b/src/Nomyx/Core/Quotes.hs
@@ -1,16 +1,4 @@
------------------------------------------------------------------------------
---
--- Module      :  Quotes
--- Copyright   :
--- License     :  BSD3
---
--- Maintainer  :  corentin.dupont@gmail.com
--- Stability   :
--- Portability :
---
--- |
---
------------------------------------------------------------------------------
+
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE QuasiQuotes #-}
 
@@ -47,9 +35,9 @@
       Right "Exp Effect ()"  -> [| s |]
       Right "Nomex ()"       -> [| s |]
       Right "Exp 'Effect ()" -> [| s |]
-      Right "Rule" -> [| s |]
+      Right "Rule"           -> [| s |]
       Right a -> fail $ "Rule doesn't typecheck: " ++ show a
-      Left e -> fail $ show e
+      Left  e -> fail $ show e
 
 
 
diff --git a/src/Nomyx/Core/Serialize.hs b/src/Nomyx/Core/Serialize.hs
--- a/src/Nomyx/Core/Serialize.hs
+++ b/src/Nomyx/Core/Serialize.hs
@@ -79,7 +79,7 @@
 $(deriveJSON defaultOptions ''LoggedGame)
 $(deriveJSON defaultOptions ''GameInfo)
 $(deriveJSON defaultOptions ''TimedEvent)
-$(deriveJSON defaultOptions ''FieldAddressElem)
+$(deriveJSON defaultOptions ''SignalAddressElem)
 $(deriveJSON defaultOptions ''FormField)
 $(deriveJSON defaultOptions ''GameEvent)
 $(deriveJSON defaultOptions ''InputData)
diff --git a/src/Nomyx/Core/Session.hs b/src/Nomyx/Core/Session.hs
--- a/src/Nomyx/Core/Session.hs
+++ b/src/Nomyx/Core/Session.hs
@@ -10,6 +10,7 @@
 import Data.Lens
 import Data.Time as T
 import Data.List
+import Data.Maybe
 import qualified Data.Acid.Advanced as A (update', query')
 import Happstack.Auth.Core.Auth
 import Control.Category hiding ((.))
@@ -24,6 +25,7 @@
 import Nomyx.Core.Interpret
 import Nomyx.Core.Serialize
 import Nomyx.Core.Engine as G
+import Nomyx.Core.Mail
 
 -- | add a new player
 newPlayer :: PlayerNumber -> PlayerSettings -> StateT Session IO ()
@@ -49,17 +51,23 @@
          void $ gameInfos %= (lg : )
       else tracePN pn "this name is already used"
 
--- | view a game.
-viewGamePlayer :: GameName -> PlayerNumber -> StateT Session IO ()
-viewGamePlayer gn pn = do
-   mg <- focus multi $ getGameByName gn
-   case mg of
-      Nothing -> tracePN pn "No game by that name"
-      Just _ -> modifyProfile pn (pViewingGame ^= Just gn)
-
--- | unview a game.
-unviewGamePlayer :: PlayerNumber -> StateT Session IO ()
-unviewGamePlayer pn = modifyProfile pn (pViewingGame ^= Nothing)
+forkGame :: GameName -> GameName -> GameDesc -> Bool -> PlayerNumber -> StateT Session IO ()
+forkGame fromgn newgn desc isPublic pn = focus multi $ do
+   gms <- access gameInfos
+   case filter ((== fromgn) . getL gameNameLens) gms of
+      gi:[] -> do
+         tracePN pn $ "Forking game: " ++ fromgn
+         time <- liftIO T.getCurrentTime
+         let lg = ((game >>> gameName) `setL` (newgn)) .
+                  ((game >>> gameDesc) `setL` (desc)) $ _loggedGame gi
+         let gi' = GameInfo {
+            _loggedGame     = lg,
+            _ownedBy        = Just pn,
+            _forkedFromGame = Just fromgn,
+            _isPublic       = isPublic,
+            _startedAt      = time}
+         void $ gameInfos %= (gi' : )
+      _ -> tracePN pn $ "Forking game: no game by that name: " ++ fromgn
 
 -- | join a game (also view it for conveniency)
 joinGame :: GameName -> PlayerNumber -> StateT Session IO ()
@@ -67,13 +75,11 @@
    s <- get
    name <- lift $ Nomyx.Core.Profile.getPlayerName pn s
    inGameDo gn $ G.execGameEvent $ JoinGame pn name
-   viewGamePlayer gn pn
 
 -- | delete a game.
 delGame :: GameName -> StateT Session IO ()
 delGame name = focus multi $ void $ gameInfos %= filter ((/= name) . getL gameNameLens)
 
-
 -- | leave a game.
 leaveGame :: GameName -> PlayerNumber -> StateT Session IO ()
 leaveGame game pn = inGameDo game $ G.execGameEvent $ LeaveGame pn
@@ -83,11 +89,14 @@
 submitRule sr@(SubmitRule _ _ code) pn gn sh = do
    tracePN pn $ "proposed " ++ show sr
    mrr <- liftIO $ interpretRule code sh
+   s <- get
+   let gi = getGameByName gn s
    case mrr of
       Right _ -> do
          tracePN pn "proposed rule compiled OK "
          inGameDo gn $ G.execGameEvent' (Just $ getRuleFunc sh) (ProposeRuleEv pn sr)
          modifyProfile pn (pLastRule ^= Just (sr, "Rule submitted OK!"))
+         liftIO $ sendMailsNewRule s sr pn (fromJust gi)
       Left e -> submitRuleError sr pn gn e
 
 adminSubmitRule :: SubmitRule -> PlayerNumber -> GameName -> ServerHandle -> StateT Session IO ()
@@ -121,7 +130,7 @@
          tracePN pn ("Error in submitted rule: " ++ errorMsg)
          modifyProfile pn (pLastRule ^= Just (sr, errorMsg))
 
-inputResult :: PlayerNumber -> EventNumber -> FieldAddress -> FormField -> InputData -> GameName -> StateT Session IO ()
+inputResult :: PlayerNumber -> EventNumber -> SignalAddress -> FormField -> InputData -> GameName -> StateT Session IO ()
 inputResult pn en fa ft ir gn = inGameDo gn $ execGameEvent $ InputResult pn en fa ft ir
 
 -- | upload a rule file, given a player number, the full path of the file, the file name and the server handle
@@ -132,13 +141,13 @@
    tracePN pn $ " uploaded " ++ show mod
    case m of
       Nothing -> do
-         inPlayersGameDo pn $ execGameEvent $ GLog (Just pn) ("File loaded: " ++ show temp ++ ", as " ++ show mod ++"\n")
+         inAllGamesDo $ execGameEvent $ GLog (Just pn) ("File loaded: " ++ show temp ++ ", as " ++ show mod ++"\n")
          tracePN pn "upload success"
          modifyProfile pn (pLastUpload ^= UploadSuccess)
          return True
       Just e -> do
          let errorMsg = showInterpreterError e
-         inPlayersGameDo pn $ execGameEvent $ GLog (Just pn) ("Error in file: " ++ show e ++ "\n")
+         inAllGamesDo $ execGameEvent $ GLog (Just pn) ("Error in file: " ++ show e ++ "\n")
          tracePN pn $ "upload failed: \n" ++ show e
          modifyProfile pn (pLastUpload ^= UploadFailure (temp, errorMsg))
          return False
@@ -175,35 +184,14 @@
    pfd <- A.query' (acidProfileData $ _profiles s) AskProfileDataNumber
    return $ pfd + 1
 
-forkGame :: GameName -> PlayerNumber -> StateT Session IO ()
-forkGame gn pn = focus multi $ do
-   gms <- access gameInfos
-   case filter ((== gn) . getL gameNameLens) gms of
-      gi:[] -> do
-         tracePN pn $ "Forking game: " ++ gn
-         time <- liftIO T.getCurrentTime
-         let gi' = GameInfo {
-            _loggedGame     = (game >>> gameName) `setL` ("Forked " ++ gn) $ _loggedGame gi,
-            _ownedBy        = Just pn,
-            _forkedFromGame = Just gn,
-            _isPublic       = False,
-            _startedAt      = time}
-         void $ gameInfos %= (gi' : )
-      _ -> tracePN pn $ "Creating a simulation game: no game by that name: " ++ gn
-
-
 -- | this function apply the given game actions to the game the player is in.
-inPlayersGameDo :: PlayerNumber -> StateT LoggedGame IO a -> StateT Session IO (Maybe a)
-inPlayersGameDo pn action = do
-   s <- get
+inAllGamesDo :: StateT LoggedGame IO a -> StateT Session IO ()
+inAllGamesDo action = do
    t <- lift T.getCurrentTime
-   mg <- lift $ getPlayersGame pn s
-   case mg of
-      Nothing -> tracePN pn "You must be in a game" >> return Nothing
-      Just gi -> do
+   gis <- access (multi >>> gameInfos)
+   forM_ gis $ \gi -> do
          (a, mylg) <- lift $ runStateT action (setL (game >>> currentTime) t (_loggedGame gi))
          focus multi $ modifyGame (gi {_loggedGame = mylg})
-         return (Just a)
 
 inGameDo :: GameName -> StateT LoggedGame IO  () -> StateT Session IO ()
 inGameDo gn action = focus multi $ do
@@ -227,10 +215,11 @@
          save $ _multi s
       Nothing -> putStrLn "thread timed out, session discarded"
 
-
 evalSession :: StateT Session IO () -> Session -> IO Session
 evalSession sm s = do
    s' <- execStateT sm s
    writeFile nullFileName $ show $ _multi s' --dirty hack to force deep evaluation --deepseq (_multi s') (return ())
    return s'
 
+getGameByName :: GameName -> Session -> Maybe GameInfo
+getGameByName gn s = find ((==gn) . getL (loggedGame >>> game >>> gameName)) (_gameInfos $ _multi s)
diff --git a/src/Nomyx/Core/Test.hs b/src/Nomyx/Core/Test.hs
--- a/src/Nomyx/Core/Test.hs
+++ b/src/Nomyx/Core/Test.hs
@@ -1,16 +1,4 @@
------------------------------------------------------------------------------
---
--- Module      :  Test
--- Copyright   :
--- License     :  BSD3
---
--- Maintainer  :  corentin.dupont@gmail.com
--- Stability   :
--- Portability :
---
--- |
---
------------------------------------------------------------------------------
+
 {-# LANGUAGE TupleSections #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE QuasiQuotes #-}
@@ -45,7 +33,6 @@
 import Nomyx.Core.Profile
 import Nomyx.Core.Quotes
 import Nomyx.Core.Engine
-import Nomyx.Core.Engine.Types
 import qualified Nomyx.Core.Engine as G
 
 playTests :: FilePath -> ServerHandle -> Maybe String -> IO [(String, Bool)]
@@ -73,6 +60,10 @@
          ("Partial Function 3",    gamePartialFunction3,   condPartialFunction3),
          ("Test file 1",           testFile1,              condNRules 3),
          ("Test file 2",           testFile2,              condNRules 3),
+#if __GLASGOW_HASKELL__ >= 708
+         --Data.Time is Safe only in recent versions
+         ("Test import Data.Time", testFileTime,           condNRules 3),
+#endif
          ("load file twice",       testFileTwice,          condNRules 3),
          ("load file twice 2",     testFileTwice',         condNRules 4),
          ("load file unsafe",      testFileUnsafeIO,       condNRules 2)] ++
@@ -122,14 +113,12 @@
    newPlayer 1 PlayerSettings {_pPlayerName = "Player 1", _mail = "", _mailNewInput = False, _mailNewRule = False, _mailNewOutput = False, _mailConfirmed = False}
    newGame "test" (GameDesc "" "") 1 True
    joinGame "test" 1
-   viewGamePlayer "test" 1
 
 twoPlayersOneGame :: StateT Session IO ()
 twoPlayersOneGame = do
    onePlayerOneGame
    newPlayer 2 PlayerSettings {_pPlayerName = "Player 2", _mail = "", _mailNewInput = False, _mailNewRule = False, _mailNewOutput = False, _mailConfirmed = False}
    joinGame "test" 2
-   viewGamePlayer "test" 2
 
 submitR :: String -> StateT Session IO ()
 submitR r = do
@@ -282,6 +271,12 @@
    void $ testFile "SimpleModule.hs" "SimpleModule.myRule"
 
 
+--module that imports Data.Time (should be Safe in recent versions)
+testFileTime :: StateT Session IO ()
+testFileTime = do
+   onePlayerOneGame
+   void $ testFile "TestTime.hs" "TestTime.myRule"
+
 --loading two modules with the same name is forbidden
 testFileTwice :: StateT Session IO ()
 testFileTwice = do
@@ -310,11 +305,12 @@
 isOutput' :: String -> Multi -> Bool
 isOutput' s m = any (isOutput s . _game . _loggedGame) (_gameInfos m)
 
+
 -- select a choice for all radio buttons
 inputAllRadios :: Int -> StateT Session IO ()
 inputAllRadios choice = do
    s <- get
-   let evs = evalState getChoiceEvents (EvalEnv 0 (firstGame $ _multi s))
+   let evs = runEvaluate (firstGame $ _multi s) 0 getChoiceEvents
    mapM_ (\(en, fa, pn, t) -> inputResult pn en fa (RadioField pn t [(0,"For"),(1,"Against")]) (RadioData choice) "test") evs
 
 -- input text for all text fields
diff --git a/src/Nomyx/Core/Types.hs b/src/Nomyx/Core/Types.hs
--- a/src/Nomyx/Core/Types.hs
+++ b/src/Nomyx/Core/Types.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE TypeFamilies #-}
 
 module Nomyx.Core.Types where
 
@@ -11,7 +12,7 @@
 import Data.Acid (AcidState)
 import Data.Data (Data)
 import Data.IxSet (inferIxSet, noCalcs)
-import Data.SafeCopy (base, deriveSafeCopy)
+import Data.SafeCopy (base, extension, deriveSafeCopy, Migrate(..))
 import Data.Time
 import Language.Nomyx
 import Nomyx.Core.Engine
@@ -66,15 +67,31 @@
 
 -- | 'ProfileData' contains application specific
 data ProfileData =
-    ProfileData { _pPlayerNumber   :: PlayerNumber, -- ^ same as UserId
+    ProfileData { _pPlayerNumber   :: PlayerNumber, -- same as UserId
                   _pPlayerSettings :: PlayerSettings,
-                  _pViewingGame    :: Maybe GameName,
                   _pLastRule       :: Maybe LastRule,
                   _pLastUpload     :: LastUpload,
                   _pIsAdmin        :: Bool
                   }
     deriving (Eq, Ord, Read, Show, Typeable, Data)
-$(deriveSafeCopy 1 'base ''ProfileData)
+
+data ProfileDataOld =
+    ProfileDataOld { _pPlayerNumberOld   :: PlayerNumber, -- same as UserId
+                     _pPlayerSettingsOld :: PlayerSettings,
+                     _pViewingGameOld    :: Maybe GameName,
+                     _pLastRuleOld       :: Maybe LastRule,
+                     _pLastUploadOld     :: LastUpload,
+                     _pIsAdminOld        :: Bool
+                   }
+
+$(deriveSafeCopy 2 'extension ''ProfileData)
+$(deriveSafeCopy 1 'base ''ProfileDataOld)
+
+instance Migrate ProfileData where
+  type MigrateFrom ProfileData = ProfileDataOld
+  migrate (ProfileDataOld a b c d e f) = (ProfileData a b d e f)
+
+
 $(deriveSafeCopy 1 'base ''SubmitRule)
 
 $(inferIxSet "ProfilesData" ''ProfileData 'noCalcs [''PlayerNumber]) -- , ''Text
diff --git a/src/Nomyx/Core/Utils.hs b/src/Nomyx/Core/Utils.hs
--- a/src/Nomyx/Core/Utils.hs
+++ b/src/Nomyx/Core/Utils.hs
@@ -1,16 +1,3 @@
------------------------------------------------------------------------------
---
--- Module      :  Utils
--- Copyright   :
--- License     :  AllRightsReserved
---
--- Maintainer  :
--- Stability   :
--- Portability :
---
--- |
---
------------------------------------------------------------------------------
 
 {-# LANGUAGE CPP #-}
 
@@ -140,13 +127,13 @@
    mvar <- newEmptyMVar
    hSetBuffering stdout NoBuffering
    --start evaluation thread
-   id <- forkOS $ do
+   id <- forkIO $ do
       s' <- f s
       s'' <- evaluate s'
       writeFile nullFileName $ show s''
       putMVar mvar (Just s'')
    --start watchdog thread
-   forkIO $ watchDog 3 id mvar
+   forkIO $ watchDog 5 id mvar
    takeMVar mvar
 
 evalWithWatchdog' :: NFData a => IO a -> IO (Maybe a)
@@ -154,20 +141,21 @@
    mvar <- newEmptyMVar
    hSetBuffering stdout NoBuffering
    --start evaluation thread
-   id <- forkOS $ do
+   id <- forkIO $ do
       s' <- s
       let s'' = force s'
       putMVar mvar (Just s'')
    --start watchdog thread
-   forkIO $ watchDog 3 id mvar
+   forkIO $ watchDog 5 id mvar
    takeMVar mvar
 
 
--- | Fork off a thread which will sleep and then kill off the specified thread.
+-- | Fork off a thread which will sleep n seconds and then kill off the specified thread.
 watchDog :: Int -> ThreadId -> MVar (Maybe a) -> IO ()
-watchDog tout tid mvar = do
-   threadDelay (tout * 1000000)
+watchDog n tid mvar = do
+   threadDelay (n * 1000000)
    killThread tid
+   threadDelay 1000000 --give some time to kill the thread
    putMVar mvar Nothing
 
 gameNameLens :: Lens GameInfo GameName
