[-*- Mode: emacs-lisp -*-] [ Copyright 2010 Ken Takusagawa This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ] [-----grammar (gz start (prog)) (gz prog (module)) (gz module (id language-pragma-opt exports imports topdecl-star ::pr("[[language-pragma-opt]]module [[id]] [[exports]] where{\n[[imports]]\n" "[[topdecl-star('',';\n','\n')]]}\n\n"))) (gz language-pragma ( :language-pragma f id-non-star j ::pr ("{-# LANGUAGE [[id-non-star('',',','')]] #-}\n"))) (gz exports (f export-star j ::pr("[[export-star('(',', ',')')]]")) (:export-everything ::pr(""))) (gz export (id) (f :module-export id j ::pr("module [[id]]")) ) (gz imports (f import-star j ::pr("[[import-star('',';\n',';\n')]]"))) (gz import(id ::pr( "import [[id]]")) (f :qualified (original-name ::is id) (new-name ::is id) j ::pr ( "import qualified [[original-name]] as [[new-name]]")) (f :specific id id-non-star j ::pr ("import [[id]][[id-non-star('(',',',')')]]")) ) (gz type-class (f decl-mark (class-name ::is id) :type-class context-opt id-non-plus f type-class-decl-star j j ::pr("class [[context-opt]][[class-name]] [[id-non-plus('',' ','')]] where{\n" "[[type-class-decl-star('',';\n','\n')]]}"))) (gz topdecl (decl) (data)(type-synonym)(newtype)(instance)(type-class)) (gz type-class-decl (type-signature)(decl)) (gz type-signature (f :tysig name ret-type-and-params j ::pr("[[name]] :: [[ret-type-and-params]]"))) (gz instance (f :instance (type ::is id) (name ::is simpletype) decls j ::pr ("instance [[type]] ([[name]]) where [[decls]]"))) [(gz instance (f :instance context-opt (type ::is id) simpletype-plus :x decls j ::pr ("instance [[context-opt]][[type]] [[simpletype-plus('(',')(',')')]] where [[decls]]")))] (gz newtype (f decl-mark id :newtype type-vars-opt constr deriving-opt j ::pr("newtype [[id]] [[type-vars-opt]] = [[constr]][[deriving-opt]]"))) (gz deriving (:deriving f id-non-plus j ::pr(" deriving [[id-non-plus('(',', ',')')]]"))) (gz id-non (id)) (gz type-synonym (f decl-mark id :type-synonym type-vars-opt type j ::pr("type [[id]] [[type-vars-opt]] = [[type]]"))) (gz data (f decl-mark id :data type-vars-opt constrs deriving-opt j ::pr("data [[id]] [[type-vars-opt]] = [[constrs]][[deriving-opt]]"))) (gz simpletype (f id-non-plus j ::pr ("[[id-non-plus('',' ','')]]"))) (gz type-vars (:args f id-non-star j ::pr ("[[id-non-star('',' ','')]]"))) (gz constrs(constr-star ::pr("[[constr-star('',' | ','')]]")) ) (gz field-type-and-param (f param type j ::pr("[[param]] :: [[type]]"))) (gz type-and-param ( f param type j ::pr("[[type]]"))) (gz constr(positional-constructor) (field-label-constructor) ) (gz field-label-constructor(f type-ctor :field field-type-and-param-star j ::pr("[[type-ctor]][[field-type-and-param-star('{',', ','}')]]"))) (gz decls ( decl-star ::pr("{[[decl-star('\n',';\n','\n')]]}\n"))) (gz context (:context f a-context-plus j ::pr ("[[a-context-plus('(',', ',')')]] => "))) (gz a-context [(f (type ::is id) id-non-plus j ::pr("[[type]] [[id-non-plus('',' ','')]]"))] (f (class ::is id) type-plus j ::pr("[[class]] [[type-plus('(',')(',')')]]")) ) (gz forall (:forall f id-non-plus j ::pr("forall [[id-non-plus('',' ','')]] . "))) (gz ret-type-and-params (type f type-and-param-star j forall-opt context-opt ::pr("[[forall-opt]][[context-opt]][[type-and-param-star('',' \x2d> ','')]]" (::c "if(my_type_and_param_star->v.size()>0)out(' \x2d> ');") "[[type]]"))) (gz decl (f decl-mark name :fun ret-type-and-params expr j ::pr("[[name]] :: [[ret-type-and-params]];\n" "[[name]]" (::c "for(many_trees::const_iterator pos = my_ret_type_and_params->my_type_and_param_star->v.begin();pos!= my_ret_type_and_params->my_type_and_param_star->v.end();++pos){" "const tr_type_and_param* t=dynamic_cast(*pos);" "assert(t);" "out(' ');" "t->my_param->print();" "}") " = [[expr]]")) (f decl-mark name :fun :no-sig ret-type-and-params expr j ::pr("[[name]]" (::c "for(many_trees::const_iterator pos = my_ret_type_and_params->my_type_and_param_star->v.begin();pos!= my_ret_type_and_params->my_type_and_param_star->v.end();++pos){" "const tr_type_and_param* t=dynamic_cast(*pos);" "assert(t);" "out(' ');" "t->my_param->print();" "}") " = [[expr]]")) (f decl-mark name :simple expr j ::pr("[[name]] = [[expr]]")) ) (gz name (id)) (gz positional-constructor ["this one is sketchy"] (type-ctor ::pr("[[type-ctor]]")) (f type-ctor typepls-opt j ::pr("[[type-ctor]][[typepls-opt]]")) (f :tuple type-plus j ::pr("[[type-plus('(',', ',')')]]")) ) (gz pattern (id) (f pattern-ctor pattern-star j ::pr ("([[pattern-ctor]] [[pattern-star('',' ','')]])")) (f pattern-ctor :fpat f fpat-star j j ::pr ("[[pattern-ctor]][[fpat-star('{',', ','}')]]")) (f :ptuple pattern-plus j [pattern-plus cuz :nil exists for empty lists] ::pr("[[pattern-plus('(',', ',')')]]")) (f :plist pattern-plus j [pattern-plus cuz :nil exists for empty lists] ::pr("[[pattern-plus('\x5b',', ','\x5d')]]")) (f :pchar astring j ::pr("(\x27[[astring]]\x27)")) (f :pstring astring j ::pr("\x22[[astring]]\x22")) (f :as id pattern j ::pr("[[id]]@[[pattern]]")) ) (gz pattern-ctor (id) (:cons ::pr ("(:)")) (:nil ::pr ("[]"))) (gz fpat (f (variable ::is id) pattern j ::pr("[[variable]] = [[pattern]]"))) (gz type (f :fn ret-type-and-params j ::pr ("([[ret-type-and-params]])")) (:unit ::pr("()")) (positional-constructor)) (gz typepls (paren-type-plus)) (gz paren-type (type ::pr( "([[type]])")) (f :strict type j ::pr("!([[type]])")) (f :generic id j ::pr (" [[id]] "))) (gz type-ctor(id)(:list ::pr ("[]"))(:nondet ::pr ("[]"))) (gz param (pattern)) (gz qastring (astring ::pr("\x22[[astring]]\x22"))) (gz expr (id) (:mcons ::pr ("(:)")) [(:nil ::pr ("[]"))] [(f :pipe expr-plus j ::pr[("[[expr-star('(',' $ ',')')]]")] ( (::c "for(many_trees::const_iterator pos = my_expr_plus->v.begin();" "pos!=my_expr_plus->v.end();++pos){") "(" (::c "(*pos)->print();" "}") (::c "for(many_trees::const_iterator pos = my_expr_plus->v.begin();" "pos!=my_expr_plus->v.end();++pos){") ")" (::c "}") ) )] (f :join expr-plus j ::pr("[[expr-plus('(',' >>= ',')')]]")) (f :rpipe expr-plus j ::pr[("[[expr-star('(',' $ ',')')]]")] (["http;//gcc.gnu.org/bugzilla/show_bug.cgi?id=11729"] (::c "for(many_trees::reverse_iterator pos = my_expr_plus->v.rbegin();" "pos!=my_expr_plus->v.rend();++pos){") "(" (::c "(*pos)->print();" "}") (::c "for(many_trees::const_iterator pos = my_expr_plus->v.begin();" "pos!=my_expr_plus->v.end();++pos){") ")" (::c "}") ) ) (f :rcompose expr-plus j ::pr [("[[expr-plus('(',' . ',')')]]")] ("(" (::c "for(many_trees::reverse_iterator pos = my_expr_plus->v.rbegin();" "pos!=my_expr_plus->v.rend();++pos){") (::c "if(pos!=my_expr_plus->v.rbegin())") " . " (::c "(*pos)->print();" "}") ")" ) ) (f :cc expr-star j ::pr ("[[expr-star('(',' ++ ',')')]]")) (qastring) (f :lit astring j ::pr("[[astring]]")) (f :ty type expr j ::pr("([[expr]] :: [[type]])")) (f (fun-name ::is expr) expr-star j ::pr ("([[fun-name]][[expr-star(' ',' ','')]])")) [(f :construct ctor expr-star j ::pr ("([[ctor]] [[expr-star('',' ','')]])"))] (f :do stmt-star j ::pr("(do{\n[[stmt-star(' ','\n ','\n')]]})")) (f :case expr alt-star j ::pr("(case [[expr]] of {\n[[alt-star(' ',';\n ','\n')]]})")) (f :case expr alt-star :else (underbar ::is expr) j ["the else is there so the grammar does not have a reduce/reduce conflict"] ::pr("(case [[expr]] of {\n[[alt-star(' ',';\n ',';\n')]]" " _ -> [[underbar]]\n" "})")) (f :lcase alt-star j ::pr("(\x5clambda_case_var ->" "case lambda_case_var of {\n" "[[alt-star(' ',';\n ','\n')]]})")) (f :lcase alt-star :else (underbar ::is expr) j ::pr("(\x5clambda_case_var ->" "case lambda_case_var of {\n" "[[alt-star(' ',';\n ',';\n')]]" " _ -> [[underbar]]\n" "})")) (f :let decl-star expr j ::pr("(let {[[decl-star('\n',';\n','\n')]]}\n in [[expr]])")) (f :cfd expr assignments-star j ::pr("([[expr]][[assignments-star('{',', ','}')]])")) [(f :compose (a ::is expr) (b ::is expr) j ::pr("((.)[[a]] [[b]])"))] [(:compose ::pr ("(.)"))] [(f :compose expr-plus j ::pr ("[[expr-plus('(',' . ',')')]]"))] (f :mlist expr-star j ::pr("[[expr-star('\x5b',', ','\x5d')]]")) (f :cons-list expr-star j ::pr("[[expr-star('(',':',')')]]")) (f :mtuple expr-star j ::pr("[[expr-star('(',', ',')')]]")) (:nothing ::pr ("()")) (f :lambda name ret-type-and-params expr j ::pr("(let {[[name]] :: [[ret-type-and-params]];\n" "[[name]]" (::c "for(many_trees::const_iterator pos = my_ret_type_and_params->my_type_and_param_star->v.begin();pos!= my_ret_type_and_params->my_type_and_param_star->v.end();++pos){" "const tr_type_and_param* t=dynamic_cast(*pos);" "assert(t);" "out(' ');" "t->my_param->print();" "}") " = [[expr]]} in [[name]])")) (f :lambda-simple id-non expr j [recommended only for reordering arguments to functions and other simple expressions] [only one variable to keep it simple] ::pr ("(\x5c[[id-non]] -> [[expr]])")) ) (gz assignments (f id expr j ::pr("[[id]] = [[expr]]"))) (gz stmt (expr ::pr("[[expr]];")) (f ":=" pattern type expr j ::pr("[[pattern]] :: [[type]] <- [[expr]];")) (f :dlet decl-star j ::pr ("let {[[decl-star('\n',';\n','\n')]]};")) ) (gz alt (f pattern expr-or-gpat j ::pr("[[pattern]][[expr-or-gpat]]"))) (gz expr-or-gpat (expr ::pr ("-> [[expr]]")) (where-opt :gpats pred-expr-star [silly lookahead limitation] ::pr ("\n[[pred-expr-star('','','')]] [[where-opt]]" ))) (gz pred-expr ( f (pred ::is expr) (do ::is expr) j ::pr ("| [[pred]]\n -> [[do]]\n"))) (gz where (:where decls ::pr ("where [[decls]]"))) (gz decl-mark (":")) ] Main :language-pragma ( ScopedTypeVariables [PatternSignatures] GeneralizedNewtypeDeriving ) (main) ( Array System Char IO [Control.Monad.State] Control.Exception Monad Random Data.List (:qualified Data.Set Set) (:qualified Data.Map Map) Maybe Data.Array.ST Control.Monad.ST ) (: main :fun (IO :unit)() (:do (hPutStrLn stderr rcs-code) (setStdGen(mkStdGen 1)) (:join getArgs (:lcase ((:plist(:pstring "nothing"))(return :nothing)) ((:plist(:pstring "many-moves"))(many-moves initial-game-state)) ((:plist(:pstring "counter")n) (:do (:rpipe n read mkStdGen setStdGen) (many-moves-counter 0 initial-game-state))) )) )) (: map-tuple :fun(:tuple(b)(b))((fn(:fn(b)((x(a))))) (x(:tuple(a)(a)))) (:mtuple (fn (fst x))(fn (snd x)))) (: apply-first :fun(:tuple(b)(c))((fn(:fn(b)((_(a))))) (x(:tuple(a)(c)))) (:mtuple (fn (fst x))(snd x))) (: apply-second :fun(:tuple(c)(b)) ((fn(:fn(b)((_(a)))))(x(:tuple(c)(a)))) (:mtuple (fst x)(fn (snd x)))) (: zip-check-same-length :fun (:list(:tuple(a)(b))) ((x1(:list(a)))(x2(:list(b)))) (:case (:mtuple x1 x2) ((:ptuple(:nil)(:nil))(:mlist)) ((:ptuple(:cons(a)(arest)) (:cons(b)(brest))) (:mcons(:mtuple a b) (zip-check-same-length arest brest))))) (: zipWith-check-same-length :fun (:list(c)) ((f(:fn(c)((x1(a))(x2(b)))))(x1(:list(a))) (x2(:list(b)))) (:case (:mtuple x1 x2) ((:ptuple(:nil)(:nil))(:mlist)) ((:ptuple(:cons(a)(arest)) (:cons(b)(brest))) (:mcons (f a b) (zipWith-check-same-length f arest brest))))) (: zip-map :fun (:list(:tuple a b)) ((f(:fn b ((x a)))) (l(:list a))) (zip l (map f l))) (: flip-tuple :fun (:tuple b a) ((x(:tuple a b))) (:mtuple (snd x)(fst x))) (: show-list :fun (IO :unit)((l(:list a))):context ((Show a)) (:rpipe l (map show) unlines putStr)) (: compare-zipped :fun (:fn Ordering ((x(:tuple a b))(y(:tuple a b)))) () :context ((Ord b)) (curry(:rcompose (map_tuple snd)(uncurry compare)))) (: take-while-plus :fun (:tuple(:list a)(Maybe a)) ((p(:fn Bool ((x a)))) (l(:list a))) (:case l ((:nil)(:mtuple(:mlist)Nothing)) ((:cons(h)(t)) (:case(p h) ((False)(:mtuple(:mlist)(Just h))) ((_)(:let (: answer :simple (take-while-plus p t)) (:mtuple (:mcons h (:rpipe answer fst)) (snd answer)))))))) (: random-from-list :fun (IO a) ((l (:list a))) (:join (:rpipe (:mtuple 0 (:rpipe l length pred) ) randomR getStdRandom ) (:rcompose (!! l) return))) (: rcs-code :fun String () "$Id: crazyhouseannihilation.ll,v 1.29 2010/11/15 09:35:03 kenta Exp kenta $") (: test :fun Int ((xy(:tuple Int Int))) (:case xy ((:ptuple v z) z))) (: pparam :fun Int (((:ptuple q r)(:tuple Int Int))) q) (: iopat :fun (IO Int) () (:do (:= (:ptuple x y) (:tuple Int Int) undefined) (return x) )) (: ray :fun (:list Coord)((origin Coord) (delta(:tuple Int Int))) (:let (: nc :fun Coord () (add-coord origin delta) ) (:mcons nc (ray nc delta)) )) (: add-coord :fun Coord (((Coord(:ptuple ox oy))Coord) ((:ptuple dx dy)Delta)) (Coord(:mtuple (+ ox dx) (+ oy dy) ))) [(: Coord :type-synonym (:tuple Int Int))] (: Coord :newtype (Coord (:tuple Int Int)) :deriving (Eq Ord Ix)) (: board-range :fun (:tuple Coord Coord)() (:mtuple (Coord(:mtuple 0 0)) (Coord(:mtuple bmax bmax))) ) (: Board :type-synonym (Array Coord (Maybe Piece))) (: Promotion-state :data Original Was-a-pawn :deriving (Eq Show)) (: Piece :type-synonym (:tuple Color (:tuple Type-piece Promotion-state))) (: Color :data White Black :deriving (Show Eq Ord)) (: Type-piece :data Pawn Night Bishop Rook Queen King :deriving ( Eq Show Ord)) (: random-piece :fun (IO Type-piece) () (random-from-list all-pieces)) (: random-mpiece :fun (IO (Maybe Piece)) () (:join (random-from-list (:mlist False True)) (:lcase (True (return Nothing)) :else (:do (:= color Color (random-from-list (:mlist Black White))) (:= p Type-piece random-piece) (:= promoted Promotion-state (:case p ((Pawn)(return Original)) :else (random-from-list (:mlist Original Was-a-pawn)))) (:rpipe (Just (:mtuple color (:mtuple p promoted)))return) )))) (: show-type-piece :fun String ((p Type-piece)) (:mlist (:rpipe p show head))) (: show-color :fun String ((c Color)) (:case c (White "w") (Black "b"))) (: show-piece :fun String ((p (Maybe Piece))) (:case p (Nothing " .") ((Just(:ptuple c (:ptuple t promoted))) (++ (show-color c) (map (:case promoted (Was-a-pawn toLower) (Original toUpper)) (show-type-piece t)) )))) (: show-row :fun String ((lp(:list(Maybe Piece)))) (:rpipe lp (map show-piece) (intersperse " ") concat)) (: bmax :fun Int () 7) (: sixty-four :fun Int () (* (+ 1 bmax) (+ 1 bmax))) (: board-row :fun (:list(Maybe Piece)) ((b Board)(r Int)) (:do (:= i Int (enumFromTo 0 bmax)) (return (! b (Coord(:mtuple r i)))))) (: random-board :fun (IO Board) () (:join (:rpipe random-mpiece (replicate sixty-four) sequence) (:rcompose (listArray board-range) return))) (: show-board :fun String ((b Board)) (:rpipe (:do (:= r String (:rpipe (enumFromThenTo bmax (- bmax 1) 0) (map (board-row b)) (map show-row))) (return (++ r "\n"))) concat)) (: ray-possibilities :fun (:list Coord) ((b Board)(origin Coord)(delta Delta)) (:case (:rpipe (ray origin delta) (takeWhile (inRange (bounds b))) (take-while-plus (:lambda-simple xy (== Nothing (! b xy)))) ) ((:ptuple empties old-capture) (++ empties (:case old-capture ((Just(xy)) (:case (== (:rpipe (! b xy) fromJust fst) (:rpipe (! b origin)fromJust fst)) (False(:mlist xy)) :else (:mlist))) :else (:mlist)))))) (: many-ray-possibilities :fun (:list Coord) ((b Board)(origin Coord)(delta (:list Delta))) (:rpipe delta (concatMap (ray-possibilities b origin)) )) (: Delta :type-synonym (:tuple Int Int)) (: queen-rays :fun (:list Delta) () (:let (: p :fun Int () 1) (: z :fun Int () 0) (: n :fun Int () (negate 1)) (:do (:= x Int (:mlist p z n)) (:= y Int (:mlist p z n)) (guard (|| (/= x 0) (/= y 0))) (return (:mtuple x y)) ))) (: rook-rays :fun (:list Delta) () (:do (:= (:ptuple x y) Delta queen-rays) (guard (== 0 (* x y))) (return (:mtuple x y)) )) (: bishop-rays :fun (:list Delta) () (:do (:= (:ptuple x y) Delta queen-rays) (guard (/= 0 (* x y))) (return (:mtuple x y)) )) [(: white-pawn :fun (:tuple (:list Coord)(:list Coord)) ((b Board)(enpassant(Maybe Coord))(origin Coord)) (:mtuple (white-pawn-advance b origin) (white-pawn-capture b enpassant origin) ))] (: get-promotion :fun (:list (Maybe Type-piece)) ((do-promotion Bool)) (:case do-promotion (False (return Nothing)) :else (map Just (:mlist Night Bishop Rook Queen)))) (: white-pawn-advance :fun (:list Move-dest) ((b Board)((Coord(:ptuple row col)) Coord)) (:let (: one :fun Coord () (Coord(:mtuple (+ row 1)col))) (: two :fun Coord () (Coord(:mtuple (+ row 2)col))) (++ (:do (guard (inRange (bounds b) one)) [should not be necessary as no pawns on 8th rank] (guard (== Nothing (! b one))) (:= promotion (Maybe Type-piece) (get-promotion (== (+ row 1) bmax))) (return (Regular-move one promotion)) ) (:do (guard (== row 1)) [only second rank pawns may advance 2] (guard (== Nothing (! b one))) (guard (== Nothing (! b two))) (:rpipe (Double-pawn (Empty-square-ep one) (Killed-piece-ep two)) return) ) ))) (: black-pawn-advance :fun (:list Move-dest) ((b Board)((Coord(:ptuple row col)) Coord)) (:let (: one :fun Coord () (Coord(:mtuple (- row 1)col))) (: two :fun Coord () (Coord(:mtuple (- row 2)col))) (++ (:do (guard (inRange (bounds b) one)) [should not be necessary as no pawns on 8th rank] (guard (== Nothing (! b one))) (:= promotion (Maybe Type-piece) (get-promotion (== row 1))) (return (Regular-move one promotion)) ) (:do (guard (== row (- bmax 1))) [only second rank pawns may advance 2] (guard (== Nothing (! b one))) (guard (== Nothing (! b two))) (:rpipe (Double-pawn (Empty-square-ep one) (Killed-piece-ep two)) return) ) ))) (: pawn-attack-dir :fun (:list Coord) ((direction Int)(b Board) ((Coord(:ptuple row col)) Coord)) [not checked whether there is a piece there or enpassant] (:do (:= ncol Int (:mlist (- col 1)(+ col 1))) (:dlet (: advance :fun Coord () (Coord(:mtuple (+ row direction)ncol)))) (guard (inRange (bounds b) advance)) (return advance) ) ) (: night-steps :fun (:list Delta) () (:let (: sign :fun (:list Int) () (:mlist 1 (negate 1))) (: onetwo :fun (:list Int) () (:mlist 1 2)) (:do (:= x Int onetwo) (:= y Int onetwo) (guard (/= x y)) (:= sx Int sign) (:= sy Int sign) (:rpipe(:mtuple (* sx x)(* sy y)) return)))) (: classify-pawn-capture :fun (:list Move-dest) ((mycolor Color)(b Board)(enpassant Enpassant)(c Coord)) (:case enpassant ((Enpassant (Empty-square-ep empty) killed) :where :gpats ((== c empty) (return (Enpassant-capture (Empty-square-ep empty) killed)))) :else (:case (! b c) (Nothing mzero) :else (:do (guard (/= mycolor (get-color b c))) (:= promotion (Maybe Type-piece) (get-promotion (is-promotion mycolor c))) (return (Regular-move c promotion)))))) (: is-promotion :fun Bool ((mycolor Color)((Coord(:ptuple row _))Coord)) (|| (&& (== mycolor White) (== row bmax)) (&& (== mycolor Black) (== row 0)))) (: Move-dest :data (Double-pawn Empty-square-ep Killed-piece-ep) (Enpassant-capture Empty-square-ep Killed-piece-ep) (Regular-move Coord (Maybe Type-piece) [second is promotion]) :deriving (Show)) (: pawn-advance :fun (:fn (:list Move-dest) ((b Board)((:ptuple row col) Coord))) ((color Color)) (:case color (Black black-pawn-advance) (White white-pawn-advance))) [XXX detect color automatically] (: pawn-attack :fun (:fn (:list Coord) ((b Board) ((:ptuple row col) Coord))) ((color Color)) (:case color (White (pawn-attack-dir 1)) (Black (pawn-attack-dir (negate 1))))) (: get-pawn-moves :fun (:list Move-dest) ((b Board)(enpassant Enpassant)(start Coord)) (:let (: color :fun Color () (:rpipe start (! b) fromJust fst)) (++ (pawn-advance color b start) (:rpipe (pawn-attack color b start) (concatMap (classify-pawn-capture color b enpassant)) )))) (: ok-to-move :fun Bool ((b Board)(start Coord)(destination Coord)) (:case (! b destination) (Nothing True) ((Just (:ptuple othercolor _)) (/= (get-color b start) othercolor)))) (: get-piece-moves :fun (:list Move-dest) ((b Board)(enpassant Enpassant)(start Coord)) (:case (:rpipe start (! b) fromJust snd fst) (Pawn (get-pawn-moves b enpassant start)) :else (:do (:= c Coord (regular-moves b start)) (return (Regular-move c Nothing))) )) (: regular-moves :fun (:list Coord) ((b Board)(start Coord)) (:case (:rpipe start (! b) fromJust snd fst) (night-or-king :where :gpats ( (|| (== night-or-king Night) (== night-or-king King)) (:rpipe (:case night-or-king (Night night-steps) (King queen-rays)) (map (add-coord start)) (filter (inRange (bounds b))) (filter (ok-to-move b start)) ))) (ray-piece (:rpipe (:case ray-piece (Queen queen-rays) (Bishop bishop-rays) (Rook rook-rays)) (many-ray-possibilities b start) )) )) (: get-color :fun Color ((b Board)(start Coord)) (:rpipe start (! b) fromJust fst)) (: get-attacked-squares :fun (:list Coord) ((b Board) (start Coord)) (:do (:= s Coord (:case (:rpipe start (! b) fromJust snd fst) (Pawn (pawn-attack (get-color b start) b start)) :else (regular-moves b start) )) (guard (== Nothing (! b s))) (return s))) (: board-my-pieces :fun (:list Coord) ((b Board)(mycolor Color)) (:do (:= (:ptuple xy mp) (:tuple Coord (Maybe Piece))(assocs b)) (guard (isJust mp)) (:rpipe mp fromJust fst (== mycolor) guard) (return xy) )) (: all-attacked-squares :fun (:list Coord) ((b Board)(mycolor Color)) (:rpipe (board-my-pieces b mycolor) (map (get-attacked-squares b)) concat Set.fromList Set.toList )) (: In-hand :type-synonym (Map.Map Type-piece Int)) (: foo :fun Int ((a Both-pieces-in-hand)) (fromJust(Map.lookup King (:rpipe a (Map.lookup White) fromJust) ))) (:instance Show (Coord) (: show :fun :no-sig String (((Coord (:ptuple rank file)) Coord)) (++(:mlist (chr (+ (ord (head "a")) file))) (show (+ rank 1)))) ) (: initial-board :fun Board () (:let (: w :fun (Maybe Piece) ((color Color)(t Type-piece)) (Just (:mtuple color (:mtuple t Original)))) (: first-rank :fun (:list Type-piece) () (:mlist Rook Night Bishop Queen King Bishop Night Rook)) (: pawns :fun (:list Type-piece) () (replicate 8 Pawn)) (listArray board-range (:cc (map (w White) first-rank ) (map (w White) pawns ) (replicate 32 Nothing) (map (w Black) pawns ) (map (w Black) first-rank ) )))) (: Both-pieces-in-hand :type-synonym (Map.Map Color In-hand)) (: Game-state :data (Game-state Board Enpassant Color Both-pieces-in-hand) :deriving (Show)) (: Dmove :data Pass (Rmove Coord Move-dest) (Drop Type-piece Coord) :deriving (Show) ) (: Enpassant :data No-enpassant (Enpassant Empty-square-ep Killed-piece-ep) :deriving(Show) ) (: Empty-square-ep :newtype (Empty-square-ep Coord) :deriving (Show Eq)) (: Killed-piece-ep :newtype (Killed-piece-ep Coord) :deriving (Show Eq)) (: all-pieces :fun (:list Type-piece) () (:mlist Pawn Rook Night Bishop Queen King)) [(: null-pieces :fun Both-pieces-in-hand () [xxx delete this] (:let (: nothing :fun In-hand () [(Map.fromList (:do (:= ty Type-piece all-pieces) (return (:mtuple ty 0))))] Map.empty ) (Map.fromList (:mlist (:mtuple White nothing) (:mtuple Black nothing) ) )))] (: othercolor :fun Color ((c Color)) (:case c (Black White) (White Black))) (: execute-regular-move :fun Game-state (((:as g(Game-state oldboard _ color oldhand)) Game-state) (origin Coord) ((Regular-move dest mpromote) Move-dest)) (:let (: newboard :fun Board () (// oldboard (:mlist (:mtuple origin Nothing) (:mtuple dest (:case mpromote (Nothing (! oldboard origin)) ((Just ty) (Just(:mtuple color (:mtuple ty Was-a-pawn)))))))) ) (: newhand :fun Both-pieces-in-hand () (:case (! oldboard dest) (Nothing oldhand) ((Just(:ptuple _ (:ptuple ty Original))) (increment-both-hand g ty)) ((Just(:ptuple _ (:ptuple _ Was-a-pawn))) (increment-both-hand g Pawn)) )) (: theothercolor :fun Color () (othercolor color)) (:rpipe (Game-state newboard No-enpassant theothercolor newhand) (assert (== color (:rpipe (! oldboard origin) fromJust fst))) (assert (:case (! oldboard dest) (Nothing True) ((Just (:ptuple oc _))(== oc theothercolor)))) ) )) (: execute-enpassant :fun Game-state (((:as g(Game-state oldboard (Enpassant old-e old-k) color _)) Game-state) (origin Coord) ((Enpassant-capture (:as e(Empty-square-ep empty)) (:as k(Killed-piece-ep killed))) Move-dest)) (:let (: newboard :fun Board () (// oldboard (:mlist (:mtuple origin Nothing) (:mtuple empty (! oldboard origin)) (:mtuple killed Nothing)))) (: theothercolor :fun Color () (othercolor color)) (:rpipe (Game-state newboard No-enpassant theothercolor (increment-both-hand g Pawn)) [enps match] (assert (&& (== e old-e) (== k old-k))) [moving piece was a pawn] (assert (== (Just (:mtuple color (:mtuple Pawn Original))) (! oldboard origin))) [empty square is empty] (:rpipe empty (! oldboard) isNothing assert) [killed piece was a pawn] (assert (== (Just (:mtuple theothercolor (:mtuple Pawn Original))) (! oldboard killed))) ))) (: execute-double-pawn :fun Game-state (((Game-state oldboard _ color oldpieces) Game-state) (origin Coord) ((Double-pawn (:as e(Empty-square-ep empty)) (:as k (Killed-piece-ep killed))) Move-dest)) (:let (: newboard :fun Board () (// oldboard (:mlist (:mtuple origin Nothing) (:mtuple killed (! oldboard origin) )))) (: theothercolor :fun Color () (othercolor color)) (:rpipe (Game-state newboard (Enpassant e k) theothercolor oldpieces) [moving piece was a pawn] (assert (== (Just (:mtuple color (:mtuple Pawn Original))) (! oldboard origin))) [empty square is empty] (:rpipe empty (! oldboard) isNothing assert) [killed square is empty] (:rpipe killed (! oldboard) isNothing assert)) )) (: execute-drop :fun Game-state (((:as g(Game-state oldboard _ color _)) Game-state) (ty Type-piece) (location Coord) ) (:let (: newboard :fun Board () (// oldboard (:mlist (:mtuple location (Just(:mtuple color (:mtuple ty Original)))) ))) (: theothercolor :fun Color () (othercolor color)) (:rpipe (Game-state newboard No-enpassant theothercolor (decrement-both-hand g ty)) [empty square is empty] (:rpipe location (! oldboard) isNothing assert) ))) (: execute-pass :fun Game-state (((Game-state oldboard _ color oldhand) Game-state)) (:let (: theothercolor :fun Color () (othercolor color)) (Game-state oldboard No-enpassant theothercolor oldhand) )) (: execute-move :fun Game-state ((g Game-state) (dm Dmove)) (:case dm ((Rmove origin (:as m (Regular-move _ _))) (execute-regular-move g origin m)) ((Rmove origin (:as m (Enpassant-capture _ _))) (execute-enpassant g origin m)) ((Rmove origin (:as m (Double-pawn _ _))) (execute-double-pawn g origin m)) ((Drop ty loc) (execute-drop g ty loc)) (Pass (execute-pass g)) )) (: initial-game-state :fun Game-state () (Game-state initial-board No-enpassant White (Map.fromList (:mlist (:mtuple White Map.empty) (:mtuple Black Map.empty))) )) (: get-moves :fun (:list Dmove) ((g Game-state)) (:mcons Pass (++ (get-drops g) (get-rmoves g)))) (: get-drops :fun (:list Dmove) (((Game-state board enpassant color hand)Game-state)) (:do (:= empty Coord (all-attacked-squares board color)) (:rpipe (return :nothing) (:rpipe (! board empty) isNothing assert)) (:= dropper Type-piece (available-pieces-in-hand ((Map.!) hand color))) (guard (:case dropper (Pawn (pawn-drop-ok empty)) :else True)) (return (Drop dropper empty))) ) (: get-rmoves :fun (:list Dmove) (((Game-state board enpassant color hand)Game-state)) (:do (:= p Coord (board-my-pieces board color)) (:= m Move-dest (get-piece-moves board enpassant p)) (return (Rmove p m)) ) ) (: print-game-state :fun (IO :unit) (((Game-state b _ _ hand)Game-state)) (:do (:rpipe b show-board putStrLn) (:rpipe hand Map.toList show-list) )) (: move-number :fun Game-state ((g Game-state)(n Int)) (execute-move g (!! (get-moves g) n))) [useful with foldl: print_game_state$foldl move_number initial_game_state [11,9,27,6,29] ] (: st-execute-double-pawn :fun (ST s :unit)((oldgame (STArray s Coord (Maybe Piece)))) undefined) (: increment-in-hand :fun In-hand ((old In-hand)(t Type-piece)) (Map.insertWith + t 1 old)) (: increment-both-hand :fun Both-pieces-in-hand (((Game-state _ _ color hand)Game-state)(t Type-piece)) (:let (: old :fun In-hand () ((Map.!) hand color) [parentheses required... sigh] ) (Map.insert color (increment-in-hand old t) hand))) (: decrement-both-hand :fun Both-pieces-in-hand (((Game-state _ _ color hand)Game-state)(t Type-piece)) (:rpipe (Map.insert color (Map.insertWith + t (negate 1) ((Map.!)hand color)) hand) (assert (< 0 ((Map.!)((Map.!)hand color) t))) )) (: available-pieces-in-hand :fun (:list Type-piece) ((hand In-hand)) (:do (:= pc Type-piece all-pieces) (guard (:case (Map.lookup pc hand) (Nothing False) ((Just(n))(< 0 n)))) (return pc))) (: numbered-move-list :fun (IO :unit) ((g Game-state)) (:rpipe g get-moves (zip (enumFrom 0)) show-list)) (: pawn-drop-ok :fun Bool (((Coord(:ptuple row _))Coord)) (&& ( < 0 row) ( < row bmax))) (: state-and-moves :fun (IO :unit) ((g Game-state)) (:do (numbered-move-list g) (:join(:rpipe(:mtuple 0 (:rpipe g get-moves length pred)) randomR getStdRandom)print) (print-game-state g) )) (: do-random-move :fun (IO (Maybe (:tuple Dmove Game-state)))((g Game-state)) (:case (is-position-lost g) (True (return Nothing)) :else (:do (:dlet (: moves :fun (:list Dmove)() (get-moves g))) (putStrLn (:cc (show(length moves)) " moves")) (:= m Dmove (random-from-list moves)) (return (Just (:mtuple m (execute-move g m))))))) (: decer :fun (IO Integer) ((x Integer)) (:do (return ( - x 2)))) (: manydecer :fun (IO :unit) ((start Integer)) (:do (:= once Integer (decer start)) (:case once (0 (:do (putStrLn "done"))) :else (manydecer once)))) [the above, works] (: many-moves :fun (IO :unit) ((start Game-state)) (:do (:= mmove (Maybe (:tuple Dmove Game-state)) (depth-one-search start)) (:case mmove (Nothing (return :nothing)) ((Just(:ptuple move newstate)) (:do (putStrLn(show move)) (print-game-state newstate) (putStrLn "=====") (many-moves newstate)))))) (: is-position-lost :fun Bool (((Game-state board _ color _)Game-state)) (null (board-my-pieces board color))) (: depth-one-search :fun (IO (Maybe (:tuple Dmove Game-state)))((g Game-state)) (:case (is-position-lost g) (True (return Nothing)) :else (:let (: moves2 :fun (:list Dmove)() (depth-one-moves g)) (:do [(putStrLn (:cc (show(length moves2)) " moves"))] (:= m Dmove (random-from-list moves2)) (return (Just (:mtuple m (execute-move g m)))))))) (: capturing-rmove :fun Bool (((Game-state board _ _ _)Game-state) (m Dmove)) (:case m ((Rmove _ (Double-pawn _ _))False) ((Rmove _ (Enpassant-capture _ _))True) ((Rmove _ (Regular-move dest _))(isJust (! board dest))) )) (: depth-one-moves :fun (:list Dmove) ((g Game-state)) (:case (:rpipe g get-rmoves [only rmoves can kill] (filter (:rcompose (execute-move g) is-position-lost))) ((:nil)(get-moves g)) (x x))) (: many-moves-counter :fun (IO :unit) ((counter Int)(start Game-state)) (:do (:= mmove (Maybe (:tuple Dmove Game-state)) (depth-one-search start)) (:case mmove (Nothing (print counter)) ((Just(:ptuple move newstate)) (:do [(putStrLn(show move)) (print-game-state newstate) (putStrLn "=====")] (:let [(: next-counter :fun Int () (succ counter))] (seq counter (many-moves-counter (succ counter) newstate))))))))