When last we spoke, we had managed to draw a board with spaces and icons. Now it's time to fill in the players and finish up the web implementation.
Recall that we had left the server code in a state that if we called the new-game route without a :players keyword, we would default the new game to return a two-player game featuring tanya as orange and rusty as black. I decided to work forward from here, because it let me defer the decision about how to capture the player data up front. As it turns out, this was a great decision, because I'm terrible at user experience. :-)
Calling the endpoint resulted in the server giving us a set of game data with two players. The players start in jail. Now I needed to add the code that would actually display the players in that spot.
I also needed to add this bit of rendering code to the main-view function, which was easy.
The result was marvelously exciting!
Alright, I might've oversold that a little. But the fact of the matter is, I had a set of players on the board, in the right position! SO CLOSE TO BEING FINISHED!
...except that I really wasn't. How in the world was I going to handle moving the pieces around? Recall that the rules state that you can take three actions on a turn: playing a card to move a pirate forward, selecting a pirate to move backward in order to draw cards, and passing. At this point, I can't play any cards because I can't tell who all has what. I can't move backward, because there's nowhere to move backward to. I can't even pass, because there's no action button or keystroke that will allow me to do that.
It looks like I'm going to have to break down and build a player area. <insert ominous music here>
As I've already stated, I don't consider myself to be much of a user experience expert. This became doubly apparent as I iterated through several different versions of the player area. I finally landed on a design such that the player area is to the right of the game board. Here's the code. Notice that I baked it right into the main-view function, which makes that function needlessly cluttered. I'm unapologetic. It's not time to refactor yet... :-D
This also required a couple of handler functions: select-card!, unselect-card! and update-active-player! The update-active-player! function is actually a server request, since all of that logic is built into the game engine.
This set of code led to a usable UI, if not an aesthetically pleasing one.
Now we have the ability to choose cards (and unchoose them, if we accidentally clicked one) and pass, but we don't have the ability to choose a specific pirate to move forward or backward. We also don't have any code to display pirates on any board space except the jail. Time to add those bits to the appropriate spots.
Notice the prolific pirate-click! function. This is the function from whence the remaining server calls initiate. It and its associated functions are a decent chunk of code, but it all feels very similar to the code I did for the console version.
Now, FINALLY, I can click pirates and expect them to render properly. Every click of a pirate calls the server, passing the current game state, and receiving an updated board from the engine. I'm not completely satisfied with it, since I wound up duplicating some server code in the web implementation to check for the end game condition. However, given the amount of typing I'd already done and the fact that I want to make it multi-player next, I decided it wasn't worth the effort to clean up.
All that's left is gathering the initial player data. As you might've guessed, there was more than a little give-up in me at this point. I decided the simplest thing that could work would be to create a silly little set of inputs, one for each color. I won't bother showing you the hiccup for that, but the form looks like:
Are you impressed yet?!
As you might imagine, filling in names and pressing the Start button creates a players map that gets sent in the request to the new-game endpoint. The server initializes a game state given the player data, and away we go!
So this is the end. We've finally slogged through the initial web implementation for Cartagena. If you've followed me thus far, you deserve a medal for your determination. I certainly learned a lot along the way, and hope that you have too (or at least that you were entertained by my bumbling through it).
I do intend to implement the multi-player non-local version of this at some point in the future, but it might be a while. If you have a burning desire to see it done, let me know in the comments. Otherwise, thanks for sharing my adventures through this series, and stay tuned for non-Cartagena posts coming your way soon! :-D