HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Reversi (Othello) game engine + command line interface

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
enginelinereversiothellointerfacegamecommand

Problem

I have written a game engine for the game Reversi, also called Othello. The game engine works not exactly like the official rules. For example it is possible to place "holes" on the board, places which can never hold a stone.

The game engine works fine, I have only some problems with the command line interface which includes lots of IO. Another problem I couldn't solve is exception handling. I read, that in Haskell, exceptions are rarely used. Nevertheless I was unable to refactor them to pure code. I have placed comments to the functions where the exceptions occur.

So, the main points which need review are:

  • Exceptions



  • How to handle errors in the program? Exceptions should not be used and type signatures like x :: XXX -> Either ErrorResult SuccessResult look ugly.



  • How to work with qualified imports? Are there style rules how to qualify them?



  • It is inefficient to compute Game.possibleMoves more than one time per step. How to cache it during the steps? Should I save them to the Game data type?



  • Is it possible to improve signatures like x :: Game -> XXX -> IO Game? Because there is no namespace for a data type, the data have have to be delivered explicitly. Thus, is there some syntactic sugar to do this?



  • Code smells



A sample game:

> newGame 8 8
> move F5
> move D6
> move C5
> print
--------
--------
--------
---WB---
--BBBB--
---W----
--------
--------
turn: White
> possibleMoves
Possible moves: B4,B6,F4,F6
> abort
Game over! Black has won (5:2)!
> quit


The code is not yet documented and it contains about 450 lines of code. I hope, this means not to much work for a code review. ;)

Main.hs

```
import qualified Data.Map as Map
import qualified Data.List as List
import qualified Data.List.Split as Split
import qualified Data.Text as T
import qualified Data.Array as A
import qualified Data.Maybe as Maybe
import qualified Text.Printf as Print
import qualified Control.Exception as E
import Control.Exception.Base
import System.IO
import Pos

Solution


  • Handling of errors is done via monads, but you don't need to understand monads in their full glory to know how to handle errors gracefully in Haskell. Oh, and Haskell has exceptions (that's the same link as before), but it's not always the best way to do it.



  • Imports You can look at the guidelines of the HaskellWiki regarding imports.



  • Signatures x :: Game -> XXX -> IO Game is explicit in a nice way, I don't believe it should be avoided.



  • Caching possibleMoves You can cache them in Game or something else, but you can also wonder how related it is to the issue of memoization.

Context

StackExchange Code Review Q#9950, answer score: 4

Revisions (0)

No revisions yet.