Assignment 3 – Backgammon:   the board and its pieces
1 Design, Build and Test

Assignment 3 – Backgammon: the board and its pieces

Due Wednesday 4/14 5:00pm for the testing deliverables and Friday 4/16 11:59pm for the code deliverables

Rules

1 Design, Build and Test

Design and implement a component for the board of Backgammon. Here is a version of the basic rules of the game.

Your component should be oblivious of the exact rules of the game. All it “knows” is that it represents a board that has locations where it can hold checkers (the points, the bar, and home). Players should be able to create new boards and move checkers around between any points, the home, and the bar. It may even be the case that two different colors have checkers on the same point, at least as far as the board is concerned.

It is up to you to decide what specific interface your component should implement and how. However, your code should come with a clear description of the interface you pick that includes an account of all operations the component is supposed to provide and all their contracts. You should also enhance your implementation with code that enforces as many of these contracts as possible and produces appropriate errors if it discovers that the contracts are violated.

Similarly to the previous assignment, to facilitate testing the component against other teams’ tests, implement a test driver that reads JSON from STDIN requests for the component and outputs JSON replies to STDOUT.

The grammar below describes the shapes of JSON values that test driver must accept in a similar manner to the description from assignment 2. We have one new element in the new grammar: the red ellipsis. It appears only in JSON lists and it means the item just before the ellipsis may appear zero or more times in the list, at that position. If the item appears zero times then any preceding comma disappears so that the list remains valid JSON.

test-case-3

 ::= 

{ "ends-with-query" : [ board, move, ..., query ] }

 | 

{ "ends-with-board" : [ board, move, ... ] }

move

 ::= 

[ color, cpos, cpos ]

query

 ::= 

[ color, cpos ]

board

 ::= 

{ "black" : [ cpos, ... ], "white" : [ cpos, ... ] }

color

 ::= 

"black" | "white"

cpos

 ::= 

"bar" | "home"

 | 

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12

 | 

13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24

The non-terminal cpos stands for “checker position” and is from the black player’s point of view (even if the checkers are white).

There are a number of constraints on boards and moves that are not expressed in the grammar:
  • The number of cpos in each of the black and white portions of board must be exactly 15.

  • The cpos in each of the black and white portions of board must be sorted; all of the bars must appear first, followed by the points in numerical order, followed by all of the homes.

  • The move has the source cpo listed first.

  • The source cpo in each move must have a checker of the appropriate color on it.

You may assume that any test case you code receives obeys those constraints (and is valid JSON) and the test cases you produce must follow them. It is a good idea that you actually have contracts in your board library that signal an error when they encounter a violation of the constraints (to help you debug other code that builds on your board library, later).

Your test driver will receive one of the test-case JSON objects as input and then must respond to it. If the input is an object with the member "ends-with-query", the response must be a natural number telling how many checkers are in that position of the given color. If the input is an object with the member "ends-with-board", your driver must print the json for the board that one gets by starting with the given board, applying the given moves in the order given.

As one example, if your test driver gets this input:

{"ends-with-query":[{"black":[1,1,2,2,3,3,4,4,5,5,6,6,"home","home","home"],"white":["bar","bar",12,15,15,15,16,18,18,20,20,20,22,24,24]},["black",6,"home"],["black",6,5],["white","bar",5],["white",18]]}

it should produce the output

2

The input board from the example looks like this:

If the test driver gets this input, which starts from the same board,

{"ends-with-board":[{"black":[1,1,2,2,3,3,4,4,5,5,6,6,"home","home","home"],"white":["bar","bar",12,15,15,15,16,18,18,20,20,20,22,24,24]},["black",6,"home"],["black",6,5],["white","bar",5]]}

it should produce the output

{"black":[1,1,2,2,3,3,4,4,5,5,5,"home","home","home","home"],"white":["bar",5,12,15,15,15,16,18,18,20,20,20,22,24,24]}

which is a board that looks like this:

Testing Deliverables: In your team’s GitHub repository, create a directory "Deliverables/3/3.1/" and put at least five input files for the test driver and their expected output files (using the same names “input1.json”, “input2.json”, “output1.json”, “output2.json”, etc). Each input file should contain one valid JSON value, as described above.

You will receive up to ten points for your tests, two points for each valid pair of input and output files.

Deliverables: In your team’s GitHub repository, create a directory "Deliverables/3/3.1/" and deposit there a Makefile for your test driver. In the same directory, also put five input files for the test driver and their expected output files using the same name convention as for assignment 2 (“input1.json”, “input2.json”, “output1.json”, “output2.json”, etc).

You will receive up to fifty points for your board component depending on how many tests its test driver passes.