ãã¼ã¿ãå¦çãããã¨ã¯ãããã°ã©ãã³ã°ã®ãã£ã¨ãæ¬è³ªçãªé¨åã§ãããæ°å¤ãæååããããã¯ãã¼ã¿ã®éã¾ããªã©ãæ±ãããã«ãæ°ã ã®æ§é ãèãããã¦ãããHaskellã«ããã¦ã¯ããæé ãããã¼ã¿ã¨ãã¦æ±ããã¨ãã§ãããããã¯ãDSLãä½ãããã§é常ã«æç¨ã§ãããã²ã¼ã éçºããã¼ã¿ãã¼ã¹æä½â¦â¦æç¶ãããããããããããã®ã«å¿ç¨ã§ããã ããã
æé ããã¼ã¿ã¨ãã¦æ±ãæ¹æ³ã¨ãã¦ãFreeã¢ããã¨Operationalã¢ããããããããã§ã¯ãOperationalã¢ãããã²ã¼ã ã®ãã£ã©ã¯ã¿ã¼ã®å¶å¾¡ã«ç¨ããä¾ãç´¹ä»ãããFreeã¢ããã®å°å ¥ã«ã¤ãã¦ã¯ãAndres Löhæ°ã®Haskell eXchange 2013ã®è¬æ¼ããããããããããããã§ããã
ãã¼ã¿ãä½ã
ã¢ã¯ã·ã§ã³ã²ã¼ã ã®æµã®åãã¨ãã¦ããã®äºã¤ãèããã:
- å¾ æ©
- æ¥è¿(æ»æ)
- ç´¢æµ(ãã¬ã¤ã¤ã¼ã®ä½ç½®ã調ã¹ã)
EnemyMã¨ããã¢ãããããã°ãHaskellã®å¤ã¨ãã¦ããããå®ç¾©ãããã¨ãã§ããã
wait :: EnemyM () move :: Position -> EnemyM () scout :: EnemyM Position
ã§ã¯ãEnemyMã¯ã©ããã£ã¦ä½ãã®ã ãããï¼ãã®çãã®ä¸ã¤ã¯Operationalã¢ããã ã
{-# LANGUAGE TemplateHaskell #-} import Control.Monad.Operational.Mini data EnemyI a where Wait :: EnemyI () Move :: Position -> EnemyI () Scout :: EnemyM Position makeSingletons ''EnemyI type EnemyM = Program EnemyI
ãä½ç½®pã«åãã£ã¦åããã¨ããåä½ã¯ããã®ã¾ã¾Move p :: EnemyI ()ã¨ããå¤ã¨ãã¦è¡¨ç¾ããããEnemyIã¯æåã®æå°åä½ã«ãªã£ã¦ããããã®åã«Programããã¶ãããã¨ã«ãã£ã¦ãããããåæã§ããããã«ãªãââProgramã¯å¥½ããªãã®ãã¢ããã«ãã¦ãã¾ãåãããã®ã ãå ·ä½çãªæ§ææ¹æ³ã«ã¤ãã¦ã¯ãç§ã®éå»ã®è¨äº*1ãåç §ããããã
å®è£
以ä¸ã¯ããã®èãã«åºã¥ãå®è£ ããã³ã¼ãã ããã£ã¨ãåºæ¬çãªé¢æ°singletonã¯ãå½ä»¤ã®æå°åä½ãProgramã¬ãã«ã«æã¡ä¸ãããminioperationalã®makeSingletonsã使ãã°ãsingletonãé©ç¨ããå½ä»¤ãèªåçæãããã¨ãå¯è½ã ããä»åã¯ä½¿ã£ã¦ããªãã
data Tactic x where Approach :: Tactic () Wait :: Tactic () RelativePlayer :: Tactic (Maybe (V2 Float)) Put :: Enemy -> Tactic () Get :: Tactic Enemy Randomly :: Random r => (r, r) -> Tactic r type Strategy = ReifiedProgram Tactic defaultStrategy :: Strategy () defaultStrategy = do r <- singleton RelativePlayer a <- use enemyAttacked case r of Just d | a -> attacking defaultStrategy | quadrance d < 160 ^ 2 -> attacking defaultStrategy | quadrance d > 320 ^ 2 -> enemyAttacked .= False _ -> singleton Wait attacking :: Strategy a -> Strategy a attacking cont = do replicateM_ 29 $ singleton Approach replicateM_ 33 $ singleton Wait cont
ããã§ãReifiedProgramã¯Programã®å¤ç¨®ã§ãããCPSå¤æããã¦ãããã©ããã®éãããããã説æã¯çç¥ãããEnemy
ã¯æµã®ç¶æ
ãç´æ¥çã«è¡¨ãåã§ãããæµã®ç¨®é¡ãã¨ã«ã³ã³ã¹ãã©ã¯ã¿ãä½ãã°ãAffine traversal*2ã§å
é¨ç¶æ
ãèªã¿æ¸ãã§ãããããã¨ã¦ã便å©ã ã
ç¬èªã®ã¢ãããå®ç¾©ããã¡ãªããã¯ããåãããã°ã©ã (Strategy)ã§ãããã£ã©ã¯ã¿ã¼ãã¨ã®åæ§ã表ç¾ã§ãããã¨ãããã¨ã¨ããã¼ã¿ã§ãããããåæãå解ãæ¤è¨¼ã容æã§ããã¨ããç¹ã«ããã
以ä¸ã¯ããã°ã©ã ãå解ããããå ·ä½çãªåãã«å¤æãã¦ããé¢æ°ã®ä¾ã§ãããæµã®ç¶æ ãæ±ãStateã¢ããã®ä¸ã§åãã¦ããã
exec cha (Approach :>>= cont) = do target <- lift $ use $ thePlayer . position pos <- use position case cha of Squirt -> do velocity . _x .= signum (view _x target - view _x pos) modify updateAnimation Fly -> velocity .= normalize (target - pos) * V2 3 6 return (cont ()) exec cha (Wait :>>= cont) = do velocity . _x .= 0 return (cont ()) exec _ (RelativePlayer :>>= cont) = do target <- lift $ use $ thePlayer . position pos <- use position return (cont (Just $ target - pos)) exec _ (Get :>>= cont) = cont <$> get exec _ (Put s :>>= cont) = cont <$> put s exec _ (Randomly r :>>= cont) = cont <$> liftIO (randomRIO r)
ééæµã¨é£ã¶æµã§ã移åã®æ¹æ³ãå¤ãã¦ãããã¾ããRelativePlayerã®é¨åã®å¦çãå¤ããã°ããè¦éããè¨ããã¨ãã£ãé«åº¦ãªãã¨ãå¯è½ã«ãªãã ããã
ProgramãReifiedProgramã¯ãå¤æå ã®ã¢ãããå¶éããªãããã®ãããããã¨ããããç°å¢*3ã«ããã°ã©ã ãæã¡éã¶ãã¨ãã§ãããã¡ããã©Luaã®ãããªåãè¾¼ã¿è¨èªã®ãããã«ä¸ä½çã¨è¦ã¦ããã*4ã
ãã®å®è£ ã®å ¨ä½ã¯GitHubã§å ¬éãã¦ããã
ãã®ä»
- æä½ã®free-gameãã²ã¼ã ã¨ã³ã¸ã³ã¨ãã¦ä½¿ã£ãããã¹ã¯ãã¼ã«ãå«ããããã®æç»ã¯äºæ³ãã¦ãããããç°¡åã«è¨è¿°ãããã¨ãã§ããããã®çç±ãã¾ããã¢ããããã¼ã¿ã¨ãã¦æ±ã£ã¦ããããã§ããã
- å ¨ä½ã§ç´500è¡ã¨ãå 容ã®è²§ç¸ãã®å²ã«ã¯è¡æ°ããããã§ãã¾ã£ããç¡çãã¦Stateã¢ãããå©ç¨ããã«ããªã¢ã¯ãã£ãããã°ã©ãã³ã°ãåãå ¥ããã»ããããã£ããããããªããkarakuriã¨ããããã±ã¼ã¸ã§ããã¢ã¯ã¿ã¼ã®è¨è¿°ã®ããããæ¹æ³ã模索ãã¦ããã
- é³å£°é¢é£ã®ã©ã¤ãã©ãªã¯ã¾ã ååã«æ´åããã¦ããªãã®ãç¾ç¶ã§ãããDirectSoundãå ¬éãããããã¯ãã¹ãã©ãããã©ã¼ã ãã¤ã¤ã³ã¹ãã¼ã«ãããããã¤ã¡ã³ããã®ããããã±ã¼ã¸ã¯ã¾ã ãªããHaskellã§ã²ã¼ã éçºããã¦ããããã§ãä»ãã£ã¨ã大ããªåé¡ã ã¨èãã¦ããã
課é¡
ä»åã¯é常ã«åç´ãªæåã ã£ããããã¨ãã°åçè¨ç»æ³ãªã©ãç¨ãã¦ãããã®æ ¼åã¨è¡åã«ã¹ã³ã¢ãå²ãå½ã¦ãã¹ã³ã¢ãé«ãã¨ããã«åãã£ã¦è¡åãããªã©ãããé«åº¦ãªAIãè¨è¿°ã§ããã¯ãã ãæ¦ç¥æ§ã¨ã¢ã¯ã·ã§ã³æ§ã両ç«ããããããã¢ããã¼ãã¨ãã¦ãã¢ããã¯ã¨ã¦ãé©æ°çãªãã¼ã«ã ã¨ç¢ºä¿¡ãã¦ããã
ããã°ã©ã ã®æ¤è¨¼ã«ã¤ãã¦ã¯ãæ¬ç 究ã§ã¯ç¢ºå®ãªææ³ãè¦åºããã¨ã¯ã§ããªãã£ããä»å¾ããä½ãé¢ç½ãã¢ããã¼ããã§ããªããèãã¦ããããã
åè
*1: ã¢ããã¨ã¯ã¢ããã§ãã - ã¢ããã¨ãããã¨ã³ã¢ãã
*2:対象ãåå¨ããªãå ´åãããLensã®å¤ç¨®ãLensã«ã¤ãã¦ã¯http://hackage.haskell.org/package/lens-3.10/docs/Control-Lens.htmlãåç §ã®ãã¨
*3:åã¯ã©ã¹ã«ããã¢ããã¼ãã¨éããåãã¢ããã«å¯¾ãè¤æ°ã®å¤ææ¹æ³ããã£ã¦ããã
*4:å®è¡æã«åä½ãå·®ãæ¿ããããªãã®ãé£ç¹ã ãâ¦