hcheckers-0.1.0.2: src/Rules/English.hs
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
module Rules.English (English (..), english) where
import Data.Typeable
import Data.List
import Core.Types
import Core.Board
import Core.BoardMap
import Core.Evaluator
import qualified Rules.Russian as Russian
import Rules.Generic
newtype English = English GenericRules
deriving (Typeable, HasBoardOrientation)
instance Show English where
show = rulesName
instance HasTopology English where
boardTopology _ = Diagonal
instance GameRules English where
type EvaluatorForRules English = SimpleEvaluator
boardSize _ = boardSize Russian.russian
initBoard rnd r =
let board = buildBoard rnd r (boardOrientation r) (boardSize r)
labels1 = line1labels ++ line2labels ++ line3labels
labels2 = line8labels ++ line7labels ++ line6labels
in setManyPieces' labels1 (Piece Man Second) $ setManyPieces' labels2 (Piece Man First) board
initPiecesCount _ = 24
boardNotation r = numericNotation (boardSize r)
parseNotation r = parseNumericNotation (boardSize r)
dfltEvaluator r = (defaultEvaluator r) {seKingCoef = 2, seHelpedKingCoef = 3}
rulesName _ = "english"
updateRules r _ = r
getGameResult = genericGameResult
possibleMoves (English rules) side board = gPossibleMoves rules side board
mobilityScore (English rules) side board = gMobilityScore rules side board
pdnId _ = "21"
getAllAddresses r = addresses8' r
english :: English
english = English $
let rules = (abstractRules rules) {
gKingSimpleMoves = kingSimpleMoves rules,
gManCaptures = manCaptures rules,
gKingCaptures = kingCaptures rules,
gKingCaptures1 = kingCaptures1 rules,
gManCaptureDirections = [ForwardLeft, ForwardRight],
gBoardOrientation = SecondAtBottom
}
in rules
kingSimpleMoves :: GenericRules -> Side -> Board -> Address -> [PossibleMove]
kingSimpleMoves rules side board src =
concatMap check (gKingSimpleMoveDirections rules)
where
piece = Piece King 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 []
captures1 :: GenericRules -> CaptureState -> [PlayerDirection] -> [Capture]
captures1 rules ct@(CaptureState {..}) dirs =
concatMap (check ctCurrent) $ filter allowedDir dirs
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,
cFreeSteps = 1,
cVictim = victimAddr,
cRemoveVictimImmediately = gRemoveCapturedImmediately rules,
cDst = freeAddr,
cPromote = isLastHorizontal side freeAddr
}]
else []
_ -> []
manCaptures :: GenericRules -> CaptureState -> [PossibleMove]
manCaptures rules ct@(CaptureState {..}) =
let side = pieceSide ctPiece
captures = gManCaptures1 rules ct
-- when last horizontal reached, pass non-promoted piece
-- to next moves check; man cant capture backwards, so
-- the piece will stop there.
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]
kingCaptures1 :: GenericRules -> CaptureState -> [Capture]
kingCaptures1 rules ct =
captures1 rules ct (gKingCaptureDirections rules)
kingCaptures :: GenericRules -> CaptureState -> [PossibleMove]
kingCaptures rules ct@(CaptureState {..}) =
let captures = gKingCaptures1 rules ct
-- king cant be promoted anyway
nextMoves pm = genericNextMoves rules ct False pm
in nub $ concat $ flip map captures $ \capture1 ->
let moves1 = translateCapture ctPiece capture1
allNext = map nextMoves moves1
isLast = all null allNext
in if isLast
then moves1
else [catPMoves move1 move2 | move1 <- moves1, move2 <- nextMoves move1]