How a Second Player Can Join the Game
Start course
2h 36m

In this course, we begin building a game in Solidity, and more specifically, we begin to look at defining the mechanics and the components of the game.


In the previous lecture, we were talking about the basic game functionality, how you can start a game basically. And in this lecture we are going to talk about this joinGame function because it is a little bit more complex than it looks like on the surface. Now, let's start with the very obvious parts. First of all, if you want to join a game, and because this is public, our player 2, it cannot have been set yet. So we have to make here an assertion. And that is not a requirement for me, that is an assertion but might be a requirement. Assertions and require, the difference is, require is used to validate inputs, user inputs, assertions is used to validate internal states. And I think here I'm going to validate an internal state that the player 2 must be the zero address. It cannot have been set yet. You can also have a Boolean here, where a player 2 join, there's a Boolean, and you can check Boolean, this player 2 join must be false. But in our case I'm going to use just the default address 0x0, which is going to be 0x000 with 40 zeros or 20 bytes. Then we are going to assign our player 2 is the message sender, which is the person who is joining. And then it gets a little bit tricky because obviously, when you play tic tac toe or three in a row, then usually the person who starts has slightly the upper hand or at least some beliefs, so we're going to add some pseudo-random selection. Is not going to be really random because we're not going to use any external oracles or random smart contracts. I'm going to use the block number here. And it's another public global object, a block object very similar to the message object. And I'm going to say, if the block number is even and the next player, the active player will be player 2, and if the block number is odd then will be player 1. For a game like this, as long as it doesn't get too popular, it's very hard to influence the block number, so, I think we are safe to use that one here. I'm going to use, if block number is even, else block number is odd. And here we have an active player. And that is something that we haven't added yet. We have a player 1 and player 2, but obviously we also have a state in our smart contract and that will be another variable called active player. And I'm going to add this here, address payable active player. So our active player was also a payable address and we set this here to active player is player 2, against player 1. Now we're not done yet. We also have to emit an event. And the event that I want to emit is going to be an event that determines whose players term is it because there are any external system that has to access the smart contract would have to read here, but we don't want to keep reading a function from a smart contract. We want to wait until somebody else has interacted with our smart contract. So when we think it back, our game manager, if you hit start a new game, then it will deploy a new instance of our smart contract. And then we have to wait, we have to wait until somebody join the game. And instead of constantly calling a smart construct function, like, has player joined? Has player joined? Or is there a player that joined? Why don't we just emit an event and then listen to these events? So you see slowly, slowly, I want to introduce events to you, and it really doesn't fit in a 10 minutes lecture when you have never heard of events in order to completely explain to you what they do. So, I will choose here another path, which is, we are going to slowly introduce events. I'm going to slowly show you what they do knowing that we have not really explained them thoroughly yet. And in the next section we're going to talk more in depth about events. All right, so we have an event that I want to introduce here to you, which is both player joined and next player. And I will tell you later why I want to have two different ones. First of all, I want to have an event, player joined, and this is going to be a player and an event next player. So why do I want to have two different events? The one event player joined, I want to emit this when a player join the game, so that is very straightforward. And the next player event, I want to emit who is the next player. So when you think back to the wire frame that I've shown you before, then you see there is one player whose turn it is and the other one has to wait. And then all of our frontend to determine whose turn it is. It will listen to the next player event, and we'll see, am I the next player? Then I will allow my frontend to be clicked. If I am not the next player then I have to wait until the next player event is fired and the frontend can be clicked again. Maybe it's not very clear yet, but let me show you how this is done. So first of all the player joined, so we have emit a player joined, player 2, and after we know who is the active player we emit the next player event with the active player. And those two are not necessarily the same players, because just because somebody joined doesn't mean that it's his turn. So the next player event really just determines whose turn it is. Okay, we can deploy the  smart contract now, but one very crucial thing is missing. So before I'm going to deploy the smart contract and interact with it, the coding challenge for this lecture is what is missing, and add this to this smart contract. If you want to do the coding challenge now then pause the video, or else I will explain it to you in a second. All right. Now, what is missing is obviously we are not checking if somebody is transferring the right amount of ether to the joinGame function, so we have to make sure that our player who is joining the game is really sending the right amount of ether a long, so message value must be the game cost or else submit more money. My friend, I'm aborting. And now let's deploy the smart contract and let's see if we can create a game, join the game, and see whose turn it is. Before I do that I'm going to reload the window because I want to have an empty transactional log here. I want to really start from scratch.  I'm going to choose Javascript VM, I hit deploy. I have my game manager deployed. And I'm going to start a new game. Doesn't work. Didn't send enough ether along. I'm going to send enough ether along, 0.1. I start a new game. I can have a look where is my smart contract that gets deployed by my game manager. And if that happens here, if I select this and it will not let me select this, then just keep the mouse button pressed, and at the same time hit 'Control+C' for copy or 'Command+C' for copy. If that happens on a Mac, it will still copy the address here. I don't know why this sometimes happens. And now I have the address of my three in a row smart contract, and I'm going to go select a three in a row smart contract in order to interact with the right contract. And let's say this one is under a specific address. And now I want my other address that I have in my account's list join this game. And I'm going to join the game. But it doesn't work because submit more money. I'm aborting, so that is working. I'm going to check the players. Yes, that's still zero. So I'm going to send along 0.1ether, I join the game and now my player 2 is the correct address. And now actually I could start playing player 1 against player 2, so who's whose turn is it? I can have a look into my transaction log, into the logs here. And when I look there I see the next player is the player which is selected here, which is the same player as the one who join. Doesn't necessarily always is that way. So in our case, if the other player would be the one who can set the stone, now we would have to select the other players at the stone 0001 or wherever you want to set the stone on the board. But in our case it's going to be this player. All right, that's it for this lecture. It was another long one, very intense one. And we are almost there with our game, with our three in a row game. Now, we're going to take care of the actual game mechanics. In our next lecture, we are going to define our game board. So I'll see you in the next lecture.


About the Author

Tom is a CTO, senior back-end developer, and systems architect with over twenty years of hands-on development experience in a variety of languages and systems. He has a CS master's degree and has been working with Ethereum and blockchain technologies since 2016.