packages feed

hs-pgms-0.1: src/SimpleStrat.hs

-- |
-- Module      : SimpleStrat
-- Copyright   : (c) 2008 Bertram Felgenhauer
-- License     : BSD3
--
-- Maintainer  : Bertram Felgenhauer <int-e@gmx.de>
-- Stability   : experimental
-- Portability : portable
--
-- This module is part of Haskell PGMS.
--
-- Another simple minesweeper strategy.
--

module SimpleStrat (simpleStrat) where

import Mine

import Data.Array.IArray
import System.Random
import Control.Monad

simpleStrat :: Strategy
simpleStrat = defaultStrategy {
    sName        = "SimpleStrat",
    sAuthor      = "Bertram Felgenhauer <int-e@gmx.de>",
    sDescription =
        "This strategy makes inferences from exposed cells and their immediate \
        \neighbourhood, and picks a random cell if no inference can be made.\n\
        \It should be equivalent to the PGMS Single Point Strategy.",
    sRun  = \s -> getConfig >>= flip worker s
}

worker :: Config -> StdGen -> StrategyM String
worker cfg gen = do
    view <- getView
    let actions = scan cfg view
    if null actions then randomMove cfg view gen >>= worker cfg
                    else sequence_ actions >> worker cfg gen

randomMove :: Config -> View -> StdGen -> StrategyM StdGen
randomMove cfg@Config { cSize = Pos sX sY } view gen = let
    (x, gen') = randomR (1, sX) gen
    (y, gen'') = randomR (1, sY) gen'
    p = Pos x y
  in
    if view ! p == Hidden then move p >> return gen''
                          else randomMove cfg view gen''

scan :: Config -> View -> [StrategyM ()]
scan cfg view = concat
    [ moves
    | (p, Exposed num) <- assocs view,
      let ns = neighbours cfg p
          ms = [n | n <- ns, view ! n == Marked]
          us = [n | n <- ns, view ! n == Hidden]
          moves | num == length ms             = [move_ n | n <- us]
                | num == length ms + length us = [mark  n | n <- us]
                | otherwise                    = []]