5 — The Strategy
Due Wednesday, 27 October 2021, 11:59:59pm
Delivery Place the product of this week’s milestone into your repo as follows:
for the Programming Task, place strategy.PP into a new folder: Player/;
for the Design Task, place player-protocol.md into Planning/
for the Testing Task, place xlegal and Tests/ into a repo-level directory named 5
Programming Task Fundamentals I teaches to abstract after you have seen several similar pieces of code. In this situation, you can see ahead of time that the playing mechanics remains the same, that the decision-making changes, and what the decision-making is all about. It is therefore appropriate to abstract immediately. A player needs a strategy, and indeed, it may need more than one strategy to find out which is best. So a player component should clearly handle the mechanics of playing a game and should abstract over a strategy component.
during setup, it much pick destinations that it wishes to connect;
for each turn, the player must decide whether to request additional colored cards or to acquire a connection.
if the player decides to acquire a connection, it must choose one.
- The first one is dubbed Hold-10 and works like this:
During setup, choose the two destination cards that come first in the lexicographic ordering specified below.
For a turn,
The strategy requests more cards, if the player’s wallet contains 10 or fewer.
If the player owns more than 10 cards, it attempts to acquire a connection.
The strategy acquires the first connection from the lexicographically sorted sequence for which it has enough cards and rails; if there aren’t any, it asks for additional cards.
- The second is Buy-Now and shares some traits with the first:
During setup, choose the two destination cards that come last in the lexicographic ordering specified below.
For a turn, the strategy always tries to buy a connection if possible (using the same algorithm as Hold-10), and requests more cards otherwise.
Lexicographic Ordering of Connections Given two connections, a lexicographic ordering chooses the connection whose cities are ordered according to the lexicographic ordering for destinations. If those are equal, a lexicographic orders the two connections in ascending order of number of segments. If further tie-breaking is needed, the string<? comparison the two colors is used.
The player will also communicate with the tournament manager. See Trains.Com, a Plan. You do not need to address this aspect yet.
Design Task As 4 —
A protocol supplements an API to explain the calling sequence. Protocols are rarely checked, violations hard to detect, and the resulting errors tend to be obscure.
Design the interaction protocol between the referee and the player(s). The document, named player-protocol.md, should be a well-organized English write-up. If you are familiar with UML sequence diagrams (or you have time to read up on them), illustrate the prose with one of those.
Two pages should suffice. Less is more.
Keep in mind our Trains.Com, a Plan when you work on designs.
Testing Task Create a test harness named xlegal. The harness consumes its JSON input from STDIN and produces its results to STDOUT. Create three tests; place them in Tests/.
Constraint No test file may exceed the size limit of 20Kb.
Its inputs are a Map followed by a PlayerState object and an Acquired. The latter represents the connection the active player wishes to acquire.
Its output is true or false, depending on whether the requested action is legal according to the rules with respect to the given map and state.
As always, the tests are well-formed and valid JSON.
Rationale Both the player and the referee must be able to decide whether a proposed or requested action, respectively, is legal. Hence it must suffice to use PlayerState.
{ "this" : ThisPlayer, "acquired" : [Player, ..., Player]} |
|
INTERPRETATION The object describes the state of the now-active player itself and |
as much as it can know about the remaining players, plus the order in which |
they take turns. |
|
This information is exactly what is available to every player in a physical |
version of the game. If your game state represents more information than that, |
your deserialization program must compute it from here. |
|
|
CONSTRAINT The first Name must be string<? to the second Name. |
|
INTERPRETATION specifies an un-directed edge between two cities, its color, and |
the length of the segment between two cities |
|
{ "destination1" : Destination, |
"destination2" : Destination, |
"rails" : Natural, |
"cards" : Card*, |
"acquired" : Player} |
|
INTERPRETATION describes the state of the player: its chosen destination |
cards, its number of rails, its colored cards, and its acquired connections |
|
|
INTERPRETATION specifies a destination card |
|
Card* is an object whose domain elements are Colors |
and whose range elements are natural numbers. |
|
INTERPRETATION describes how many cards of each color this player has |
|
Player is a JSON array of Acquireds. |
|
INTERPRETATION denotes a set of connections (owned by a player) |
Pedagogy Building harnesses for integration tests doesn’t slow you
down—