packages feed

hcheckers-0.1.0.2: src/Rules/Simple.hs

{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
module Rules.Simple (Simple, simple) where

import Data.Typeable

import Core.Types
import Core.Board
import Core.BoardMap
import Core.Evaluator
import qualified Rules.Russian as Russian
import Rules.Generic

newtype Simple = Simple GenericRules
  deriving (Typeable, HasBoardOrientation)

instance Show Simple where
  show = rulesName

instance HasTopology Simple where
  boardTopology _ = Diagonal

instance GameRules Simple where
  type EvaluatorForRules Simple = SimpleEvaluator
  initBoard rnd _ = initBoard rnd Russian.russian
  boardSize _ = boardSize Russian.russian
  initPiecesCount _ = 24

  boardNotation _ = boardNotation Russian.russian

  parseNotation _ = parseNotation Russian.russian

  dfltEvaluator r = defaultEvaluator r

  rulesName _ = "simple"

  updateRules r _ = r

  getGameResult = genericGameResult

  possibleMoves (Simple rules) side board = gPossibleMoves rules side board
  mobilityScore (Simple rules) side board = gMobilityScore rules side board

  pdnId _ = "43"
  getAllAddresses r = addresses8 r

simple :: Simple
simple = Simple $
  let rules = (Russian.russianBase rules) {
                gManSimpleMoves = manSimpleMoves rules,
                gManCaptures = manCaptures rules,
                gManCaptures1 = manCaptures1 rules
              }
  in  rules

manSimpleMoves :: GenericRules -> Side -> Board -> Address -> [PossibleMove]
manSimpleMoves rules side board src =
    concatMap check (gManSimpleMoveDirections rules)
  where
    piece = Piece Man side
    check dir =
      case myNeighbour rules side dir src of
        Nothing -> []
        Just dst -> if isFree dst board
                      then [PossibleMove {
                              pmBegin = src,
                              pmEnd = dst,
                              pmVictims = [],
                              pmVictimsCount = 0,
                              pmMove = Move src [Step dir False False],
                              pmPromote = False,
                              pmResult = [Take src, Put dst piece]
                            }]
                      else []

manCaptures :: GenericRules -> CaptureState -> [PossibleMove]
manCaptures rules ct@(CaptureState {..}) =
  let captures = gManCaptures1 rules ct
      nextMoves pm = genericNextMoves rules ct False pm
  in concat $ flip map captures $ \capture ->
       let [move1] = translateCapture ctPiece capture
           moves2 = nextMoves move1
       in  if null moves2
             then [move1]
             else [catPMoves move1 move2 | move2 <- moves2]

manCaptures1 :: GenericRules -> CaptureState -> [Capture]
manCaptures1 rules ct@(CaptureState {..}) =
    concatMap (check ctCurrent) $ filter allowedDir (gManCaptureDirections rules)
  where
    side = pieceSide ctPiece

    allowedDir dir =
      case ctPrevDirection of
        Nothing -> True
        Just prevDir -> oppositeDirection prevDir /= dir

    check a dir =
      case neighbour (myDirection rules side dir) a of
        Just victimAddr | not (aLabel victimAddr `labelSetMember` ctCaptured) ->
          case getPiece victimAddr ctBoard of
            Nothing -> []
            Just victim ->
              if isMyPiece side victim
                then []
                else case neighbour (myDirection rules side dir) victimAddr of
                       Nothing -> []
                       Just freeAddr ->
                        if isFree freeAddr ctBoard
                          then [Capture {
                                  cSrc = a,
                                  cDirection = dir,
                                  cInitSteps = 0,
                                  cVictim = victimAddr,
                                  cRemoveVictimImmediately = gRemoveCapturedImmediately rules,
                                  cFreeSteps = 1,
                                  cDst = freeAddr,
                                  cPromote = False
                                }]
                          else []
        _ -> []