Anonymous user
Generate random chess position: Difference between revisions
m
→{{header|Haskell}}
(improved function pawn_on_extreme_ranks) |
|||
Line 556:
Uses System.Random library: https://hackage.haskell.org/package/random-1.1/docs/System-Random.html
Module RandomChess
<lang haskell>{-# LANGUAGE LambdaCase, TupleSections #-}
module RandomChess
( placeKings
, placePawns
, placeRemaining
, boardSort
, emptyBoard
, toFen
, ChessBoard
, Square (..)
, Pos
, BoardState (..)
, getBoard
)
where
import
import Data.List (find, sortBy)
import
type Pos = (Char, Int)
Line 576 ⟶ 591:
type PieceCount = [(Square, Int)]
data BoardState = BoardState { board :: ChessBoard , generator :: StdGen }
instance Show Square where
Line 595 ⟶ 612:
randomR (a, b) g = case randomR (fromEnum a, fromEnum b) g of
(x, g'') -> (toEnum x, g'')
random
instance Random PieceColor where
randomR (a, b) g = case randomR (fromEnum a, fromEnum b) g of
(x, g'') -> (toEnum x, g'')
random
fullBoard :: PieceCount
Line 620 ⟶ 637:
emptyBoard :: ChessBoard
emptyBoard =
replaceSquareByPos :: (Square, Pos) -> ChessBoard -> ChessBoard
replaceSquareByPos e@(
isPosOccupied :: Pos -> ChessBoard -> Bool
Line 632 ⟶ 649:
isAdjacent :: Pos -> Pos -> Bool
isAdjacent (
let upOrDown = (pred
leftOrRight = (pred
in (
|| (pred
|| (succ
|| (leftOrRight &&
fen :: Square -> String
Line 655 ⟶ 672:
boardSort :: (Square, Pos) -> (Square, Pos) -> Ordering
boardSort (_, (
|
|
toFen :: ChessBoard -> String
toFen [] = " w - - 0 1" <> []
toFen b
scanRow [] 0
scanRow [] n
scanRow
scanRow (x:xs) 0
scanRow (x:xs) n
nextRow = "/" <> toFen (drop 8 b)
nextPiece x xs = fen x <> scanRow xs 0
-- State functions
randomPos :: State BoardState Pos
randomPos = do
currentState <- get
let gen1 = generator currentState
let (num, gen2) = randomR (1, 8) gen1
let (chr, gen3) = randomR ('a', 'h') gen2
put (currentState {generator = gen3})
let pos = (chr, num)
if isPosOccupied pos (board currentState) then
randomPos
else
pure pos
randomPiece :: State BoardState Square
randomPiece = do
currentState <- get
let gen1 = generator currentState
let (rank, gen2) = random gen1
let (color, gen3) = random gen2
put (currentState {generator = gen3})
pure $ ChessPiece rank color
placeKings :: State BoardState ()
placeKings = do
currentState <- get
p1 <- randomPos
p2 <- randomPos
if p1 `isAdjacent` p2 || p1 == p2
then placeKings
else
put currentState { board = updatedBoard }
placePawns ::
placePawns
currentState <- get
let gen1 = generator currentState
let (totalPawns, gen2) = randomR (1, 16) gen1
put currentState { generator = gen2 }
go totalPawns
where
go 0 = pure ()
go n = do
currentState <- get
pos <- randomPos
let (color, gen2) = random gen1
put currentState { generator = gen2 }
let pawn = ChessPiece Pawn color
let currentBoard = board currentState
if promoted color == snd pos || isPosOccupied pos currentBoard ||
enpassant color == snd pos || firstPos color == snd pos
then go n
else do
put currentState { board = replaceSquareByPos (pawn, pos) currentBoard }
go $ pred n
promoted White = 8
promoted Black = 1
enpassant White = 5
enpassant Black = 4
firstPos White = 1
firstPos Black = 8
placeRemaining :: State BoardState ()
placeRemaining = do
currentState <- get
let gen1 = generator currentState
let (n, gen2) = randomR (5, sum $ fmap snd remaining) gen1
put currentState { generator = gen2 }
go remaining n
where
remaining = filter (\case
(ChessPiece King _, _) -> False
(ChessPiece Pawn _, _) -> False
(EmptySquare, _) -> False
_ -> True)
fullBoard
go :: [(Square, Int)] -> Int -> State BoardState ()
go _ 0 = pure ()
go remaining n = do
currentState <- get
let currentBoard = board currentState
position <- randomPos
piece <- randomPiece
if not (isPermitted piece) || isPosOccupied position currentBoard
then go remaining n
else do
let updatedBoard = replaceSquareByPos (piece, position) currentBoard
put currentState { board = updatedBoard }
go (consume piece remaining) (pred n)
where
isPermitted p =
case find ((==p) . fst) remaining of
Just (_, count) -> count > 0
Nothing -> False
consume p'' = fmap (\(p, c) -> if p == p'' then (p, pred c) else (p, c))
getBoard = gets (sortBy boardSort . board)</lang>
Module Main
<lang haskell>module Main where
import Control.Monad.State (evalState)
import RandomChess (ChessBoard, emptyBoard, placeKings, getBoard,
placePawns, placeRemaining, toFen, BoardState (..))
import System.Random (newStdGen)
draw :: ChessBoard -> IO ()
draw b = do
showXAxis >> drawLine
mapM_ (\b@(p, (x,y)) ->
case x of 'h' -> putStr (" | " <> show p <> " | " <> show y <> "\n") >> drawLine
'a' -> putStr (show y <> " | " <> show p)
)
b
showXAxis >> putStrLn "" >> putStrLn (toFen b)
where
drawLine = putStrLn (" " <> replicate 33 '-')
showXAxis = do
putStr " "
mapM_ (\(_, (x, _)) -> putStr $ " " <> [x]) (take 8
putStrLn ""
main :: IO ()
main = do
stdGen <- newStdGen
draw $ evalState buildBoard (BoardState emptyBoard stdGen)
where
buildBoard = placeKings >> placePawns >> placeRemaining >> getBoard</lang>
{{out}}
Run 1
<pre> a b c d e f g h
---------------------------------
8 | | |
---------------------------------
7 | ♙ |
---------------------------------
6 | | | |
---------------------------------
5 |
---------------------------------
4 | | |
---------------------------------
3 |
---------------------------------
2 |
---------------------------------
1 | | |
---------------------------------
a b c d e f g h
Run 2
<pre> a b c d e f g h
---------------------------------
8 | |
---------------------------------
7 |
---------------------------------
6 |
---------------------------------
5 | | |
---------------------------------
4 | |
---------------------------------
3 | |
---------------------------------
2 | | |
---------------------------------
1 |
---------------------------------
a b c d e f g h
etc...
|