Extend types of Split Action
authorjin <psyzj1@nottingham.ac.uk>
Fri, 21 Jul 2017 09:41:53 +0000 (10:41 +0100)
committerjin <psyzj1@nottingham.ac.uk>
Fri, 21 Jul 2017 09:41:53 +0000 (10:41 +0100)
src/RMCA/GUI/Board.hs
src/RMCA/GUI/HelpersRewrite.hs
src/RMCA/GUI/MultiBoard.hs
src/RMCA/GUI/NoteSettings.hs
src/RMCA/Semantics.hs

index 2e2a3de00409db7923b7b00d9b916c079105263f..06d464ca243231aca046316349169a56ccd84431 100644 (file)
@@ -48,10 +48,10 @@ newtype GUIBoard = GUIBoard (GameState Int Tile Player GUICell)
 -- want to remove that.
 data Tile = TileW | TileB
 
-
 rotateGUICell :: GUICell -> GUICell
 rotateGUICell g = g { cellAction = rotateAction $ cellAction g }
   where rotateAction (ChDir b na d) = ChDir b na (nextDir d)
+        rotateAction (Split na ds)  = Split na (turnQueue ds 1)
         rotateAction x              = x
 
 tileW :: Int
@@ -307,4 +307,4 @@ actionToFile = \case
                     Stop _          -> "img/stop.svg"
                     ChDir True _ d  -> "img/start" ++ show d ++ ".svg"
                     ChDir False _ d -> "img/ric" ++ show d ++ ".svg"
-                    Split _         -> "img/split.svg"
+                    Split _ _       -> "img/split.svg"
index eba78f19fe4d560377a2d1916298dcd3bb11b4b8..e9a243f40d78cc32f63ac40380731f69fb3ef9b5 100644 (file)
@@ -61,7 +61,7 @@ ctrlPieces = [(xMax+2,y,Player,GUICell { cellAction = action
                                        })
              | let actions = [ Absorb, Stop defNa
                              , ChDir False defNa N, ChDir True defNa N
-                             , Split defNa]
+                             , Split defNa [0..5]]
                      -- /!\ It would be nice to find a general formula
                      -- for placing the control pieces.
                      , (y,action) <- zip [ yMin+4,yMin+8..] actions]
index 8931b167a50e155c264b0f34b07cc3d1dfba875a..cde2db7daaab0d9969e6c0b0f8259d051e51ea5e 100644 (file)
@@ -2,6 +2,7 @@
 
 module RMCA.GUI.MultiBoard where
 
+import Debug.Trace
 import           Control.Concurrent.MVar
 import           Control.Monad
 import           Control.Monad.IO.Class
index f76b75e87f7d9e9557074b6c271132128603b915..e3933a899a66b8c390af5e0fcc6919229c6706a2 100644 (file)
@@ -3,6 +3,7 @@
 
 module RMCA.GUI.NoteSettings where
 
+import Debug.Trace
 import Control.Monad
 import Data.List
 import Data.Maybe
@@ -18,19 +19,34 @@ import RMCA.GUI.Board
 import RMCA.MCBMVar
 import RMCA.Semantics
 
+toJust :: a -> Maybe a
+toJust a = Just a
+
+getSplit :: Action -> Maybe Action
+getSplit (Split na ds) = Just (Split na ds)
+getSplit _ = Nothing
+
+setSplitDir :: [Int] -> Action -> Action
+setSplitDir ds (Split na _) = Split na ds
+setSplitDir _ a = a
+
+getSplitDir :: Action -> Maybe [Int]
+getSplitDir (Split _ ds) = Just ds
+getSplitDir _ = Nothing
+
 setNAttr :: NoteAttr -> Action -> Action
 setNAttr _ Inert            = Inert
 setNAttr _ Absorb           = Absorb
 setNAttr na (Stop _)        = Stop na
 setNAttr na (ChDir b _ dir) = ChDir b na dir
-setNAttr na (Split _)       = Split na
+setNAttr na (Split _ ds)    = Split na ds
 
 getNAttr :: Action -> Maybe NoteAttr
 getNAttr Inert          = Nothing
 getNAttr Absorb         = Nothing
 getNAttr (Stop na)      = Just na
 getNAttr (ChDir _ na _) = Just na
-getNAttr (Split na)     = Just na
+getNAttr (Split na _)   = Just na
 
 symbolString :: [(Duration,String)]
 symbolString = map (\(_,y,z) -> (z,y)) noteSymbList
@@ -64,6 +80,8 @@ noteSettingsBox = do
   naBox <- vBoxNew False 5
   boxPackStart pieceBox naBox PackNatural 0
 
+
+
   -- Articulation box
   artCombo <- comboBoxNewText
   artIndex <- mapM (\art -> do i <- comboBoxAppendText artCombo
@@ -128,6 +146,33 @@ noteSettingsBox = do
   boxPackStart noteDurBox noteDurCombo PackNatural 0
   boxPackStart noteDurBox noteDurLabel PackNatural 0
 
+  -- Split direction box
+  splitDirBox <- hBoxNew False 10
+  splitDirCombo <- comboBoxNewText
+  splitDirIndex <- mapM (\(str, dir) -> do i <- comboBoxAppendText splitDirCombo
+                                                (fromString str)
+                                           return (dir, i)) dirList
+  comboBoxSetActive splitDirCombo 0
+  let indexToDir i =
+        fromMaybe (error "In indexToDir: failed \
+                         \to find the correct \
+                         \ direction for the \
+                         \selected index.") $ lookup i $ map swap splitDirIndex
+      dirToIndex ds =
+        fromMaybe (error "In dirToIndex: \
+                         \failed to find \
+                         \the correct index \
+                         \for the direction.") $ lookup ds' splitDirIndex where
+                                                  ds' = fst $ fromProto ds
+  
+      splitDirRV = bijection (indexToDir, dirToIndex) `liftRW`
+                   comboBoxIndexRV splitDirCombo
+  splitDirLabel <- labelNew =<< return (Just "")
+  let splitDirLabelRV = labelTextReactive splitDirLabel
+  boxPackStart naBox splitDirBox PackNatural 0
+  boxPackStart splitDirBox splitDirCombo PackNatural 0
+  boxPackStart splitDirBox splitDirLabel PackNatural 0
+
   -- Repeat count box
   rCountAdj <- adjustmentNew 1 0 100 1 1 0
   rCount <- spinButtonNew rCountAdj 1 0
@@ -138,6 +183,19 @@ noteSettingsBox = do
   -- Carries the index of the tile to display and what to display.
   setRV <- newMCBMVar inertCell
 
+  reactiveValueOnCanRead splitDirRV $ do
+    cDir <- reactiveValueRead splitDirRV
+    oCell <- reactiveValueRead setRV
+    let nCa :: Action
+        nCa = cellAction oCell
+        nCell :: GUICell
+        nCell = if isJust $ getSplit nCa
+                then oCell { cellAction =
+                             setSplitDir cDir nCa }
+                else oCell
+    reactiveValueWriteOnNotEq setRV nCell
+
+
   reactiveValueOnCanRead noteDurRV $ do
     nDur <- reactiveValueRead noteDurRV
     oCell <- reactiveValueRead setRV
@@ -190,23 +248,32 @@ noteSettingsBox = do
                   widgetHide artCombo
                   widgetShow rCount
                   widgetHideAll noteDurBox
+                  widgetHideAll splitDirBox
       showNa :: IO ()
       showNa = do widgetShow slideCombo
                   widgetShow artCombo
                   widgetShow rCount
                   widgetShowAll noteDurBox
+                  widgetHideAll splitDirBox
+      showDir :: IO ()
+      showDir = widgetShowAll splitDirBox
+
       updateNaBox :: GUICell -> IO ()
       updateNaBox GUICell { cellAction = act } = case act of
         Inert  -> hideNa
         Absorb -> hideNa
+        Split _ _ -> showNa >> showDir
         _      -> showNa
 
   reactiveValueOnCanRead setRV $ postGUIAsync $ do
     nCell <- reactiveValueRead setRV
+    fromMaybeM_ (fmap (reactiveValueWriteOnNotEq splitDirRV)
+                      (getSplitDir $ cellAction nCell))
+    fromMaybeM_ (fmap (reactiveValueWriteOnNotEq splitDirLabelRV . show . snd . fromProto)
+                      (getSplitDir $ cellAction nCell))
     fromMaybeM_ (fmap (reactiveValueWriteOnNotEq artComboRV . naArt)
                       (getNAttr (cellAction nCell)))
-    fromMaybeM_ (fmap (reactiveValueWriteOnNotEq slideComboRV
-                       . ornSlide . naOrn)
+    fromMaybeM_ (fmap (reactiveValueWriteOnNotEq slideComboRV . ornSlide . naOrn)
                       (getNAttr (cellAction nCell)))
     reactiveValueWriteOnNotEq rCountRV $ repeatCount nCell
     fromMaybeM_ (fmap (reactiveValueWriteOnNotEq noteDurRV . naDur)
index 1d1318e403519381652900634aa5d06b43ad1390..7f80ed9a8a751c34cc2dc1a689716e6f52437635 100644 (file)
 
 module RMCA.Semantics where
 
+import Debug.Trace
 import Data.Array
 import Data.List      (intercalate, nub)
-import Data.Maybe     (catMaybes)
+import Data.Maybe     (catMaybes, fromJust)
 import RMCA.Auxiliary
 
 
@@ -300,7 +301,6 @@ nextDir d | d ==  maxBound = minBound
 turn :: Dir -> Angle -> Dir
 turn d a = toEnum ((fromEnum d + a) `mod` 6)
 
-
 type Pos = (Int, Int)
 
 -- Position of neighbour in given direction
@@ -331,9 +331,40 @@ data Action = Inert                   -- No action, play heads move through.
             | Absorb                  -- Remove play head silently.
             | Stop  NoteAttr          -- Play note then remove play head.
             | ChDir Bool NoteAttr Dir -- Play note then change direction.
-            | Split NoteAttr          -- Play note then split head into five.
+            | Split NoteAttr [Int]    -- Play note then split head into more than one.
+            -- | Split NoteAttr          -- Play note then split head into five.
             deriving (Show,Read,Eq)
 
+dirList :: [(String, [Int])]
+dirList = [ ("0 1 2 3 4 5", [0, 1, 2, 3, 4, 5])
+          , ("0 1 2 3 4", [0, 1, 2, 3, 4])
+          , ("0 1 2 3", [0, 1, 2, 3])
+          , ("0 1 2 4", [0, 1, 2, 4])
+          , ("0 1 3 4", [0, 1, 3, 4])
+          , ("0 1 2", [0, 1, 2])
+          , ("0 1 3", [0, 1, 3])
+          , ("0 2 3", [0, 2, 3])
+          , ("0 2 4", [0, 2, 4])
+          , ("0 1", [0, 1])
+          , ("0 2", [0, 2])
+          , ("0 3", [0, 3])
+          ]
+
+turnQueue :: [Int] -> Int -> [Int]
+turnQueue ds n = sortQueue [] $ map ((`mod` 6) . (+ n)) ds
+
+sortQueue :: [Int] -> [Int] -> [Int]
+sortQueue [] ys = sortQueue [head ys] (tail ys)
+sortQueue xs [] = xs
+sortQueue xs ys = case last xs > head ys of
+                    True -> ys ++ xs
+                    False -> sortQueue (xs ++ [head ys]) (tail ys)
+
+fromProto :: [Int] -> ([Int], Int)
+fromProto ds = fromJust $ lookup s rotates where
+  s = minimum $ map fst rotates
+  rotates = [(sum ds', (ds', d)) | d <- ds, let ds' = turnQueue ds (-d)]
+
 -- Contains a list of all the actions. Useful to have for e.g. pixbufs
 -- generation. It is shared for all applications from here to avoid
 -- forgetting to add a case if future actions are added.
@@ -341,8 +372,11 @@ actionList :: [Action]
 actionList = [ Inert
              , Absorb
              , Stop noNoteAttr
-             , Split noNoteAttr
              ] ++
+             [ Split noNoteAttr ds | proto <- map snd dirList
+                                   , offset <- [0..6]
+                                   , let ds = turnQueue proto offset
+                                   ] ++
              [ ChDir t noNoteAttr d | t <- [True, False]
                                     , d <- [minBound..maxBound]
                                     ]
@@ -351,7 +385,7 @@ anonymizeConstructor :: Action -> Action
 anonymizeConstructor Inert         = Inert
 anonymizeConstructor Absorb        = Absorb
 anonymizeConstructor (Stop _)      = Stop noNoteAttr
-anonymizeConstructor (Split _)     = Split noNoteAttr
+anonymizeConstructor (Split _ ds)  = Split noNoteAttr ds
 anonymizeConstructor (ChDir t _ d) = ChDir t noNoteAttr d
 
 -- Cells
@@ -480,13 +514,13 @@ advanceHead bd bn tr st ph = ahAux (moveHead bd ph)
                 Stop na       -> (newPHs [], mkNote p bn tr st na)
                 ChDir _ na d' -> (newPHs [ph {phDir = d'}],
                                   mkNote p bn tr st na)
-                Split na      -> (newPHs [ PlayHead {
+                Split na ds   -> (newPHs [ PlayHead {
                                                phPos   = p,
                                                phBTM   = 0,
                                                phDir   = d'
                                            }
-                                         | a <- [-2 .. 2],
-                                           let d' = turn d a
+                                         | a <- ds,
+                                           let d' = turn N a
                                          ],
                                   mkNote p bn tr st na)
             where