/CSE230MM

F2022 CSE 230 final project

Primary LanguageHaskell

CSE230 Final Project F22

    _/      _/                        _/                         
   _/_/  _/_/    _/_/_/    _/_/_/  _/_/_/_/    _/_/    _/  _/_/
  _/  _/  _/  _/    _/  _/_/        _/      _/_/_/_/  _/_/     
 _/      _/  _/    _/      _/_/    _/      _/        _/        
_/      _/    _/_/_/  _/_/_/        _/_/    _/_/_/  _/        

    _/      _/   _/                  _/   
   _/_/  _/_/       _/_/_/      _/_/_/    
  _/  _/  _/   _/  _/    _/  _/    _/     
 _/      _/   _/  _/    _/  _/    _/      
_/      _/   _/  _/    _/    _/_/_/   

Project Organization

  • README.md - This file.
  • ./MM - Directory containing all source code.
    • ./MM/src/Tui.hs - Source code for all TUI drawing and game state transitions.
    • ./MM/src/Lib.hs - Source code for all custom data types, game logics, constants and internal variables.
    • ./MM/src/Ptest.hs - Source code for property based testing.
    • ./MM/src/LibTest.hs - Source code for general unit testing.
    • ./MM/* - All files automatically generated by stack.
  • ./figures - Directory containing screenshots of the game.

Application

Our application is based on the 1970 boardgame "MasterMind". image info

This game aims to guess the correct sequence of colors in 4 positions. We will have two players, one player guesses and one player provides the colors and the positions of the 4 pegs. For example, the answer could be blue, red, yellow, green and the player needs to guess both the color and the order correctly. There will be 6 colors available. The guesser will guess up to 10 rounds and each round the player would know extra information about the answer based on the current guess.

Application Architecture

data Slot
  = Empty
  | Guess PinColor

data PinColor
  = Red
  | Blue
  | Green
  | White
  | Purple
  | Yellow

Game State

TuiState
  {   homeScreen     :: [String]         -- Descriptions for the game modes.
    , navSelect      :: Int              -- Index for homeScreen selection.
    , screen         :: Int              -- Index for which UI screen to draw.
    , gameState      :: [([Slot], Int)]  -- Game board state, a list of rows, each row is a list of Slots.
    , gameStateIndex :: (Int, Int)       -- current input pointer, (row, col).
    , pinSlots       :: [[String]]       -- list of Slots for the information.
    , boss           :: ([Slot], Bool)   -- the 4 colored pegs that the player is trying to guess.
    , random         :: [Slot]           -- randomly generated colors, used in 1 player mode only.
    , aiSearchSpace  :: [[Slot]]         -- DKAI algorithm's solution search space
  }
  • UI Screens
    • Home screen
    • Game screen
    • User input screen
  • Game Modes
    • 1 Player - Player trying to guess the randomly generated 4 colored pegs, currenly restricting to non-repeating colors.
    • 2 Players Player 1 will be directed to User input screen to input 4(repeat disallowed) colors. Player 2 will be trying to guess those 4 colors.
    • DKAI vs Player Player 1 will be directed to User input screen to input 4(repeat disallowed) colors. AI will try to make a guess after player press KENTER AI's initial blind guess will always be [Red, Green, Blue, Yellow].

Challenges

  • Initial project enviroment setup. We encountered a major issue in the beginning of our project. Due to some subtle differences in our haskell enviroment .yaml.lock files, we were not able to get our code to compile. This was later solved by modifying the .yaml.lock file and shared with all team members.

  • Random number generation. Player 1 mode requires the system to randomly generate a set of 4 colors for the player to guess, however, we spend quite some time figuring out how to integrate the randomness into our program.

  • Color attributes

  • AI's implementation Implementation of Donald Knuth's algorithm, which can solve any non-repeating patterns in (most cases) five moves or fewer. This is the DKAI mode in our game.

  • Implementation choice for updating the game's internal settings. Could be seperate game screens and state variables that the system keeps track of, or having the game settings in a seperate readable file outside.

Property Based Testing

  • Our game logic has below simple properties that can be tested with QuickCheck.
    • No judgement should produce [R,R,R,W] as a result.
    • For combinations without duplicate pegs, the minimum result should be [W,W]
      • Check for [] and [W].
    • Number of red pins should match number of color correct pegs placed at correct positions.
    • Number of white pins should match the number of correct colors left after red-pin checks
    • All judgements should be of size 4.
    • AI's search space should be strickly reduced at each iteration.

Quickcheck of randomly generated 10000 tests, even though there are only 1296 possible color combinations(with duplicate).

Result:

*Main Test.QuickCheck> quickCheckN 10000 prop_genSlotInvalid 
+++ OK, passed 10000 tests.

*Main Test.QuickCheck> quickCheckN 10000 prop_genSlotEmpty 
+++ OK, passed 10000 tests.

*Main Test.QuickCheck> quickCheckN 10000 prop_genSlotEmpty1 
+++ OK, passed 10000 tests.

*Main Test.QuickCheck> quickCheckN 10000 prop_genredJudge
+++ OK, passed 10000 tests.

*Main Test.QuickCheck> quickCheckN 10000 prop_whiteJudge
+++ OK, passed 10000 tests.

*Main Test.QuickCheck> quickCheckN 10000 prop_dkSearchSize
+++ OK, passed 10000 tests.

*Main Test.QuickCheck> quickCheckN 10000 prop_judgeSize
+++ OK, passed 10000 tests.

Unit Testing

  • Our game logic can also be tested manually by iterating all possible input situations. The MasterJudge Function is responsible for making judgment by comparing the user's input(in the form of "[pinColor,pinColor,pinColor,pinColor]") with the final answer(in the form of "[pinColor,pinColor,pinColor,pinColor]"). Since the input pins' colors are selected from 6 colors and can not be repeated, there are 6*5*4*3=360 possible input arrays. Similarly, the final answer also has 360 possible states. Considering that the arrangement of different colors is symmetrical, there are essentially (360/(4*3*2*1))^2=225 combinations for the MasterJudge Function to judge. Therefore, we listed the 225 testing cases and tested them manually.

User Interaction Testing

  • Our game has 5 screens to implement user interactions. We manually test the switching between each screen to ensure that undefined I/O operations do not cause any errors. Our testing guarantees that 3 different game modes can be conducted smoothly from the home screen to the end screen.

Goals

G1

  • Basic TUI setup as well as basic game state logic. [Done]
  • Implementation for 1 Player game mode. [Done]

G2

  • Implementation for 2 Players game mode. [Done]

G3 (Milestone 3)

  • TUI optimization with colored pegs. [Done]
  • TUI navigation and control optimizations. [Done]

G4

  • Implementation for the AI player game mode. [Done]
  • Implementation for variable game settings. (If time permits)
    • Players are allowed to change the followings:
      • Number of rounds (Not likely)
      • Possible peg colors (Not likely)
      • Allow/disallow duplicate pins in hidden pegs. (Likely)
    • Settings might be inputted into a different setting file, which will be read by the system at start. This may reqire restart the game if the user wishes to change game settings.

Collaborator

  • Chufan Wu (Testing)
  • Yuan Chang (Logic)
  • Yuxin Liu (Interface)
  • Siran Ma (Testing)

History

Last edit Dec 7, 2022