Week 9 Set a
Due Date Monday 10/29 at 9:00pm (Week 9)
Purpose To design the multiplayer version of the project
Finger Exercises
Graded Exercises
You’ve shared the single player version of Minicraft with some early testers, and they all think it’ll be a hit. But they’ve also convinced you that for it to be a true success, players should be able to interact with one another. Indeed, they think that there should be one large world, with many different 20x20 tiles that players can move between. One of the testers, helpfully, offered to implement the server, so all that you and your partner have to do is extend your game to be a suitable multiplayer client.
You and your partner have gone back to your design studio and, in consultation with your anonymous benefactor (i.e., implementer of the server), came up with the following plan:
The multiplayer version of the game is a generalization of the single-player version, where much remains the same. We begin by imagining we have many independent players on their own single-player versions. We then want to have them all exist in the same Minicraft world. To do that, we need to communicate actions between the single-player games (i.e., that I move left, that I place material, etc.), where those actions will then be replayed by the other players. In this setting, the server is relatively "dumb" – it acts primarily as a communication medium between games. All of the logic is still played out by the individual games.
All of the players will exist in a larger world that is made up of many tiles. Each tile is a grid like your single-player game had. The multiplayer game world is a 10x10 grid of tiles, and each tile is a 20x20 grid of cells, so there should be plenty or room for everyone!
The server manages everything about the tiles: you will only be responsible for reporting whenever you move to the server, and if the server detects that you are moving off of one tile and onto another, it will send a new tile to you to load. Loading a tile is also what will happen when you first connect to the server (when it will randomly place you on a tile). The server will also send you the coordinate of which tile you are on, which you should display in your interface.
There are two critical data types that will be used for the multiplayer game:
IDs are small numeric unique identifiers used to identify different players. They will remain the same while a player is connected to the server, but are not guaranteed to be the same if you reconnect. They will be how you are told that other players are doing things.
Your interface should show the IDs on the players, so you can distinguish different players moving around the map!
SExps: The client and server communicate via s-expressions. This means that you’ll have to convert between your data representations and the representations specified in the protocol below. Most likely, you will want to define helper functions to convert common data types like Posn to the representation used (a list with two numbers in it), and also between the representations of things like cells (which in s-expression format are quite error prone) and the representation that you have in your own game.
Further, the server will specify and require coordinates where the origin (0,0) is at the top left. If you, for whatever reason, decided to represent coordinates in some other way, it is your responsibility for converting to these coordinates when you send messages to the server, and converting back when you receive messages from the server.
Finally, scores for gold accumulation are maintained locally – nothing needs to be communicated to the server, and you do not need to maintain the scores of other players.
The server author presented the following protocol to you. These are the messages that the clients should send to the server, and correspondingly the messages that the server will send to the client. Eventually, your game will have to send/understand all of these:
Exercise 2 Change your WorldState data definition (and all relevant other data definitions) to be able to support multiplayer. Carefully think through what will be different and what can remain the same. Your choices now will hopefully allow you to mostly re-use the single-player functionality you have already implemented when you actually implement all the multiplayer functionality.
Exercise 3 Design a function to convert between the s-expression cells representation and your representation of the grid (you might call this sexp->cells or similar). Note that since not all s-expressions will be valid, this function should report appropriate errors if given invalid input. This will be a core part of the handler for the 'map message, though you don’t need to implement the handler yet. Note that you do not need to implement the reverse, as you will not be sending your map to the server!
Some example inputs your function should handle are:
sexp->cells('(((0 0) (grass (tnt 22)) ()) ((1 0) () ((0 left))) ((0 1) (rock gold) ((1 up))) ((1 1) (water) ())))
sexp->cells('(((0 0) () ((0 down) (1 right)))))
sexp->cells('(((0 0) () ()) ((1 0) () ()) ((0 1) () ()) ((1 1) () ())))
Exercise 4 Write a signature, purpose statement, and stub for the function that will be your on-receive handler, and describe in several sentences (no more than 4) how you anticipate that this function will work, in particular, paying attention to how you will re-use (or not) your existing code.