dimanche 26 avril 2020

Can someone diagnose the issue with my Haskell code?

I get the feeling I'm fundamentally misunderstanding something about the way in which Haskell is written. My code is intended to serve as an evaluation function for a primitive AI for the game Othello. Essentially I want my code to cycle through a list of pieces, each piece represented by a tuple composed of a Position (Int, Int) and a Col (Colour, either Black or White), and given a prospective move identify how good the move is.

The way I'm judging the value of a move is based on a few factors:

  • Is there a piece on the board in a straight line from the intended position of the same colour?
  • If the previous requirement is true, how many pieces of the opposite colour are inbetween those two pieces?

Since Haskell has no loop structures it seems like I need to implement this recursively, as such my code is as follows:

eval :: Position -> [(Position, Col)] -> Col -> GameState -> Int -> Int
eval move pieces moveColour gameState score = do
                                                let moveX = fst move
                                                let moveY = snd move
                                                let piece = head(pieces)
                                                let pieceColour = snd piece
                                                let pieceX = fst fst piece
                                                let pieceY = snd fst piece
                                                if (moveColour == pieceColour) then
                                                  if (moveX == pieceX) then
                                                    if (moveY > pieceY) then
                                                      let newScore = score + (countOtherColour 0 moveY pieceY (pieces gameState) moveColour 0)
                                                      --recurse
                                                      if (tail(pieces) == []) then
                                                        return newScore
                                                      else
                                                        return eval move tail(pieces) moveColour gameState newScore
                                                    else
                                                      let newScore = score + (countOtherColour 0 pieceY moveY (pieces gameState) moveColour 0)
                                                      --recurse
                                                      if (tail(pieces) == []) then
                                                        return newScore
                                                      else
                                                        return eval move tail(pieces) moveColour gameState newScore
                                                  else
                                                    if (moveY == pieceY) then
                                                      if (moveX > pieceX) then
                                                        let newScore = score + (countOtherColour 1 moveX pieceX (pieces gameState) moveColour 0)
                                                        --recurse
                                                        if (tail(pieces) == []) then
                                                          return newScore
                                                        else
                                                          return eval move tail(pieces) moveColour gameState newScore
                                                      else
                                                        let newScore = score + (countOtherColour 1 pieceX moveX (pieces gameState) moveColour 0)
                                                        --recurse
                                                        if (tail(pieces) == []) then
                                                          return newScore
                                                        else
                                                          return eval move tail(pieces) moveColour gameState newScore
                                                    else
                                                      --recurse
                                                      if (tail(pieces) == []) then
                                                        return score
                                                      else
                                                        return eval move tail(pieces) moveColour gameState score
                                                else
                                                  --recurse
                                                  if (tail(pieces) == []) then
                                                    return score
                                                  else
                                                    return eval move tail(pieces) moveColour gameState score

countOtherColour :: Int -> Int -> Int -> [(Position, Col)] -> Col -> Int -> Int
countOtherColour xyFlag upper lower pieces turnColour score = do
                                                                --if xyFlag == 0 it's y aligned if 1 it's x aligned
                                                                let piece = head(pieces)
                                                                let pieceColour = other (snd piece)
                                                                let x = fst fst piece
                                                                let y = snd fst piece
                                                                if (pieceColour == turnColour) then
                                                                  if (xyFlag == 0) then
                                                                    if (upper > x && x > lower) then
                                                                      let newScore = score+1
                                                                      --recurse
                                                                      if (tail(pieces) == []) then
                                                                        return newScore
                                                                      else
                                                                        return countOtherColour xyFlag upper lower tail(pieces) turnColour newScore
                                                                    else
                                                                      --recurse
                                                                      if (tail(pieces) == []) then
                                                                        return score
                                                                      else
                                                                        return countOtherColour xyFlag upper lower tail(pieces) turnColour score
                                                                  else
                                                                    if (upper > y && y > lower) then
                                                                      let newScore = score+1
                                                                      --recurse
                                                                      if (tail(pieces) == []) then
                                                                        return newScore
                                                                      else
                                                                        return countOtherColour xyFlag upper lower tail(pieces) turnColour newScore
                                                                    else
                                                                      --recurse
                                                                      if (tail(pieces) == []) then
                                                                        return score
                                                                      else
                                                                        return countOtherColour xyFlag upper lower tail(pieces) turnColour score
                                                                else
                                                                  --recurse
                                                                  if (tail(pieces) == []) then
                                                                    return score
                                                                  else
                                                                    return countOtherColour xyFlag upper lower tail(pieces) turnColour score

However, this code does not compile. I get a "parse error on "if"" on the first line that reads:

if (tail(pieces) == []) then

This leads me to believe that something fundamental about the way in which I've structured this code is faulty. I would like to clarify I'm NOT looking for someone to solve the implementation for me, only for someone to explain to me how my implementation is flawed, and a general guide on how I can implement recursion within the correct way to structure my code.

If you've read this far thank you, and I look forward to reading your replies.

Aucun commentaire:

Enregistrer un commentaire