packages feed

hcheckers-0.1.0.2: src/Rules/Turkish.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
module Rules.Turkish (
    Turkish, turkish, turkishBase
  ) where

import Data.Typeable

import Core.Types
import Core.Board
import Core.BoardMap
import Core.Evaluator
import Rules.Generic

newtype Turkish = Turkish GenericRules
  deriving (Typeable, HasBoardOrientation)

instance Show Turkish where
  show = rulesName

instance HasTopology Turkish where
  boardTopology _ = Orthogonal

instance GameRules Turkish where
  type EvaluatorForRules Turkish = SimpleEvaluator
  initBoard rnd r =
    let board = buildBoard rnd r (boardOrientation r) (8, 8)
        labels1 = ["a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
                   "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3"]
        labels2 = ["a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
                   "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6"]
    in  setManyPieces' labels1 (Piece Man First) $ setManyPieces' labels2 (Piece Man Second) board

  initPiecesCount _ = 32

  boardSize _ = (8, 8)

  dfltEvaluator r = (defaultEvaluator r) {seKingCoef = 5, seHelpedKingCoef = 6, seBorderManWeight = 0}

  boardNotation _ = chessNotation

  parseNotation _ = parseChessNotation

  rulesName _ = "turkish"

  possibleMoves (Turkish rules) side board = gPossibleMoves rules side board

  updateRules r _ = r

  getGameResult = genericGameResult

  pdnId _ = "43"

  getBackDirections _ = [Backward]
  getAllAddresses r = addresses8 r

turkishBase :: GenericRules -> GenericRules
turkishBase =
  let rules this = (abstractRules this) {
                        gManSimpleMoveDirections = [PLeft, Forward, PRight]
                      , gManCaptureDirections =  [PLeft, Forward, PRight]
                      , gKingCaptureDirections = [Backward, PLeft, Forward, PRight]
                      , gKingSimpleMoveDirections = [Backward, PLeft, Forward, PRight]
                      , gManCaptures = manCaptures this
                      , gManCaptures1 = manCaptures1 this
                      , gCaptureMax = True
                      , gRemoveCapturedImmediately = True
                    }
  in  rules

turkish :: Turkish
turkish = Turkish $
  let rules = turkishBase rules
  in  rules

manCaptures :: GenericRules -> CaptureState -> [PossibleMove]
manCaptures rules ct@(CaptureState {..}) =
  let side = pieceSide ctPiece
      captures = manCaptures1 rules ct
      -- when last horizontal reached, pass non-promoted piece to
      -- next moves check; man can not capture backward.
      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 myNeighbour 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 myNeighbour rules side dir victimAddr of
                       Nothing -> []
                       Just freeAddr ->
                        if isFree freeAddr ctBoard || aLabel freeAddr `labelSetMember` ctCaptured
                          then let captured' = insertLabelSet (aLabel victimAddr) ctCaptured
                                   next = ct {
                                            ctPrevDirection = Just dir,
                                            ctCaptured = captured',
                                            ctCurrent = freeAddr
                                          }
                               in [Capture {
                                  cSrc = a,
                                  cDirection = dir,
                                  cInitSteps = 0,
                                  cFreeSteps = 1,
                                  cVictim = victimAddr,
                                  cRemoveVictimImmediately = gRemoveCapturedImmediately rules,
                                  cDst = freeAddr,
                                  cPromote = isLastHorizontal side freeAddr &&
                                             not (gCanCaptureFrom rules next)
                                }]
                          else []
        _ -> []