state == [num]			|| for nim; but it could be anything
game  == state -> [state]	|| ie, codification of legal moves of game

goodmove :: game -> state -> (bool, state)	|| a winning move, if any
  goodmove g s = findgoodmove (zip2 moves worths)
                 where
                 moves = g s
                 worths = map (goodmove g) moves
                 findgoodmove []    = (False, undef)
                 findgoodmove ((move,(False,dummy)) : rest) = (True, move)
                 findgoodmove ((move,(True, dummy)) : rest) = findgoodmove rest



|| Front end to goodmove...
|| "play" finds a best move, with a commentary string implying whether it can
||  definitely win or not; or, if there is no *possible* move, it resigns.
play :: game -> state -> ([char], state)
  play g s = error "I can't move: I resign", if moves  = []
           = ("I move to: ", thegoodmove),   if moves ~= [] &  isgoodmove
           = ("I make do with: ", hd moves), if moves ~= [] & ~isgoodmove
             where
             moves = g s
             (isgoodmove, thegoodmove) = goodmove g s




|| Some example games.

nim :: game
  nim [] = []
  nim (0:t) = error "zero-size heaps are meaningless!"
  nim ((h+1):t) = (mkset . map (filter (~=0)))
                   (map (:t) [0..h] ++ map ((h+1):) (nim t))

misere_nim :: game
  misere_nim = filter (~=[]) . nim
