Course:CPSC312-2016-Project2-Go-Fish

From UBC Wiki

Title

Authors: John Jang, Nafisa Shazia

What is the problem?

For our project, we will be implementing Go Fish (https://cardgames.io/gofish/#rules). Go Fish is a card game that can be played with two to four players. A single player can either be a human or an AI, but not all players can be AIs. We are going to see if implementing this specific card game is feasible in Haskell.

What is the something extra?

1) Create an AI to play the game with a user. The AI will use pseudo-randomness to simulate the actions of a real human.

2) Increase the capacity of players up to four players (initially two).

3) Increase the capacity of AI players up to three players (initially one).

4*(updated) Use a lot of pseudo-randomness in the game. Using IO Random was harder than we anticipated. Some notable difficulties were: shuffling cards randomly and generating non-repeating random numbers from a given range.

5) (deleted) Implement a simple telnet session so different users under the same network can play the game remotely. We were able to make a simple telnet session, but we didn't have enough time to implement it all the way through.

What did we learn from doing this?

Biggest takeaway from this project is: Once you go impure, you can't go pure. We had a hard time understanding the idea of monads and IO types. It does make sense that once you have IO, you have to stay as IO since Haskell is pure functional language. Because of this, we struggled to finish the project towards the end as we started to introduce randomness into the play. For example, something as simple as shuffling a deck of cards (only 8 lines), took about whole day to come up with. We spent most of the time reading/understanding about IO's and Monads of Haskell.

Haskell seems to be an excellent language when it comes to implementing each certain general state of a game. Even though the game may look a bit complicated and may seem to have a lot of states, in reality we only had four general states that were going back and forth depending on the input. We didn't anticipate we could have generalized this much, but it was possible because it was functional language.

Lastly, we didn't understand at first why functional languages were so powerful especially in debugging. Since it is purely functional, it was easy to debug a specific state without actually going through the whole process. There weren't any 100 lines of codes in one function like many other languages do, but rather it is all in small parts, letting us to test very easily a specific parts of the program.