Ethereum Simulation Game — Part 5 – Competing Against Other Players
Tags: ethereum
Published: 2020-05-15 18:15:27

---
title: Ethereum Simulation Game — Part 5 – Competing Against Other Players
published: true
date: 2020-05-14 17:31:14 UTC
tags: Ethereum,ethereum
canonical_url: https://blog.coincodecap.com/ethereum-simulation-game-part-5/?utm_source=rss&utm_medium=rss&utm_campaign=ethereum-simulation-game-part-5
---

![](https://cdn-images-1.medium.com/max/880/1*PlsbmMYAnVBYyAdu5HUoYg.jpeg)<figcaption>Photo by <a href="https://www.pexels.com/@rajtatavarthy?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels" rel="noreferrer noopener nofollow" target="_blank">Raj Tatavarthy</a> from <a href="https://www.pexels.com/photo/people-sitting-on-bench-watching-tennis-event-on-field-during-daytime-171568/?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels" rel="noreferrer noopener nofollow" target="_blank">Pexels</a></figcaption>

[_The code repo is on Github so it’s public and open to pull requests_](https://github.com/alexroan/tennis-manager)_. If you’re interested in helping out please to contribute!_

* * *

### Recap

In the [previous article](https://blog.coincodecap.com/building-an-ethereum-simulation-game-part-4-training-and-resting-players/), I walked through implementing Training and Resting players in the [DApp](https://blog.coincodecap.com/what-are-dapps-an-ultimate-guide/) interface. Since then I’ve made some fairly big changes to the game, which include:

- Segregating the game interface using Tabs.
- Deploying to the Kovan testnet
- The ability to compete against other players.

Here’s how I did it…

### Interface Update

Up until this point, the supported functionality in the interface was pretty limited. so displaying all functionality on a single page wasn’t much of an issue. However, adding new features to the interface meant restructuring it somewhat.

I decided to segregate the functionality into a few categories using Bootstrap Tabs. The `react-bootstrap` package came in handy here. Figures 1 and 2 show the interface before and after the new structure.

![Figure 1: Interface Before](https://cdn-images-1.medium.com/max/880/1*5PlfRibrHb61NA7wQuoIyw.png)<figcaption>Figure 1: Interface Before</figcaption>

![Figure 2: Interface After](https://cdn-images-1.medium.com/max/880/1*yrxg_MACHpVOkaCRaRzu1w.png)<figcaption>Figure 2: Interface After</figcaption>

Each set of functionality has a separate tab to manage the player. The “Details” tab shows all the information and attributes about your player, the “Training” tab is where you can train specific attributes and rest your player, the “Compete” tab is where you can enlist to compete and play matches against other enlisted players, and the “Results” tab will show the results of your player’s previous matches.

Organising the tabs is very easy using `react-bootstrap`. Figure 3 shows my `Content` component, which declares the interface structure.

| | import React, {Component} from 'react'; |
| | import {connect} from 'react-redux'; |
| | import {Container, Row, Col, Tabs, Tab} from 'react-bootstrap'; |
| | import Connections from './Connections'; |
| | import PlayerList from "./PlayerList"; |
| | import PlayerDetails from "./PlayerDetails"; |
| | import PlayerAttributes from './PlayerAttributes'; |
| | import Train from './Train'; |
| | import Compete from './Compete'; |
| | |
| | class Content extends Component { |
| | render() { |
| | return ( |
| | <Container> |
| | <Connections /> |
| | <Row> |
| | <Col md="3"> |
| | <PlayerList /> |
| | </Col> |
| | <Col md="9"> |
| | <Tabs> |
| | <Tab eventKey="details" title="Details"> |
| | <Row> |
| | <Col md="6"> |
| | <PlayerDetails /> |
| | </Col> |
| | <Col md="6"> |
| | <PlayerAttributes /> |
| | </Col> |
| | </Row> |
| | </Tab> |
| | <Tab eventKey="training" title="Training"> |
| | <Train /> |
| | </Tab> |
| | <Tab eventKey="compete" title="Compete"> |
| | <Compete /> |
| | </Tab> |
| | <Tab eventKey="results" title="Results"> |
| | Results Tab |
| | </Tab> |
| | </Tabs> |
| | </Col> |
| | </Row> |
| | </Container> |
| | ) |
| | } |
| | } |
| | |
| | function mapStateToProps(state){ |
| | return { |
| | } |
| | } |
| | |
| | export default connect(mapStateToProps)(Content); |

[view raw](https://gist.github.com/alexroan/08ba254b1526f1239975c7109edbc529/raw/6b9b33dfcc6f0396486b5a000a4ab79a5033dce1/Content.js)[Content.js](https://gist.github.com/alexroan/08ba254b1526f1239975c7109edbc529#file-content-js) hosted with ❤ by [GitHub](https://github.com)

  

Lines 21 to 41 show how easy it is to declare Tabs and the content within them.

* * *

I also removed the “Create Player” form from the main page and replaced for a modal which is shown when the button under the player list is clicked, shown in figure 4.

![Figure 4: Create player modal](https://cdn-images-1.medium.com/max/880/1*ZkK3-uBpDZffQ7rx2ZwnFg.gif)<figcaption>Figure 4: Create player modal</figcaption>

* * *

### Deploying To Public Testnet

Testing a DApp on a local [Blockchain](https://blog.coincodecap.com/what-is-blockchain-a-simple-guide-for-dummies/) is very different from testing it on a public one. For a start, you get used to the speedy response times and the immediate transactions. That, unfortunately, doesn’t happen on public testnets or the mainnet. This means your DApp needs to monitor the status of each transaction it executes on the Blockchain and provides sufficient feedback to the user.

Not only that, but if you’re subscribing to events in your DApp, listening for things like “Transfer” events, or in this game, “Train”, “Rest” and “MatchPlayed” events; **the events won’t be pushed to your DApp through HTTP**. No matter how many listeners you put in place, if you are connecting to the Blockchain with an HTTP connection, event listeners will never fire.

To catch the events, you need to maintain a Websocket connection, [which I write about in this article](https://medium.com/blockcentric/listening-for-smart-contract-events-on-public-blockchains-fdb5a8ac8b9a). Fortunately, Infura offers HTTP and Websockets, so it wasn’t an issue, it’s just a little frustrating making sure you’re keeping both connections stored in parallel in the Redux store. Even more frustrating is the fact that the Websocket API is very limited compared with the HTTP one. This means that transactions need to be sent through HTTP, and listeners set up through Websocket.

Figure 5 shows my `subscriptions.js` file.

| | import { loadOwnedPlayers, loadWalletDetails, unselectPlayer, loadSelectedPlayer, checkIfPlayerEnlisted } from "./interactions"; |
| | import { playerFinishedResting, playerFinishedTraining, playerCreated, matchFinished } from "./actions"; |
| | |
| | export const subscribeToTransferEvents = async (dispatch, tennisPlayer, tennisPlayerSocket, account) => { |
| | tennisPlayerSocket.events.Transfer({filter: {to: account}}) |
| | .on('data', async function(event){ |
| | await loadOwnedPlayers(dispatch, tennisPlayer, account); |
| | dispatch(playerCreated()); |
| | }) |
| | .on('error', console.error); |
| | } |
| | |
| | export const subscribeToTrainingEvents = async (dispatch, tennisPlayer, tennisPlayerSocket, playerId) => { |
| | tennisPlayerSocket.events.Train({filter: {playerId: playerId}}) |
| | .once('data', async function(event) { |
| | await loadSelectedPlayer(dispatch, tennisPlayer, tennisPlayerSocket, playerId); |
| | dispatch(playerFinishedTraining()); |
| | }) |
| | .on('error', console.error); |
| | |
| | tennisPlayerSocket.events.Rest({filter: {playerId: playerId}}) |
| | .once('data', async function(event) { |
| | await loadSelectedPlayer(dispatch, tennisPlayer, tennisPlayerSocket, playerId); |
| | dispatch(playerFinishedResting()); |
| | }) |
| | .on('error', console.error); |
| | } |
| | |
| | export const subscribeToMatchEvents = async (dispatch, tennisPlayer, tennisPlayerSocket, playerId) => { |
| | tennisPlayerSocket.events.Enlist({filter: {playerId: playerId}}) |
| | .once('data', async function(event) { |
| | await checkIfPlayerEnlisted(dispatch, tennisPlayer, playerId); |
| | }) |
| | .on('error', console.error); |
| | tennisPlayerSocket.events.Delist({filter: {playerId: playerId}}) |
| | .once('data', async function(event) { |
| | await checkIfPlayerEnlisted(dispatch, tennisPlayer, playerId); |
| | }) |
| | .on('error', console.error); |
| | |
| | tennisPlayerSocket.events.MatchPlayed({filter: {playerId: playerId}}) |
| | .once('data', async function(event) { |
| | await loadSelectedPlayer(dispatch, tennisPlayer, tennisPlayerSocket, playerId); |
| | dispatch(matchFinished(event.returnValues)); |
| | }) |
| | .on('error', console.error); |
| | } |
| | |
| | export const subscribeToAccountsChanging = async (dispatch, web3, web3Socket, tennisPlayer) => { |
| | window.ethereum.on('accountsChanged', function (accounts) { |
| | loadWalletDetails(dispatch, web3, web3Socket, tennisPlayer); |
| | unselectPlayer(dispatch); |
| | }); |
| | } |

[view raw](https://gist.github.com/alexroan/6005f44686e889e407f9de0ae0e000fc/raw/4439298b1f8bc59b8b393c6835e02939218c45a8/subscriptions.js)[subscriptions.js](https://gist.github.com/alexroan/6005f44686e889e407f9de0ae0e000fc#file-subscriptions-js) hosted with ❤ by [GitHub](https://github.com)

  

On line 29 the function `subscribeToMatchEvents` is declared, where “Enlist”, “Delist” and “MatchPlayed” events are listened to.

Taking a look at line 41, notice how `tennisPlayerWebsocket` variable is used, representing a Websocket connection to the `TennisPlayer` smart contract, to listen for the event. 

It still needs the HTTP connected contract (`tennisPlayer`) to reload the player after the match is played because Websockets don’t allow function calls to [smart contracts](https://blog.coincodecap.com/tag/smart-contact/). Line 43 shows a call to `loadSelectedPlayer` with `tennisPlayer` as a parameter to make the HTTP request.

* * *

### Playing Matches

The ability to play players against each other is the last major piece of the puzzle when it comes to the interface supporting all of the function calls in the [smart contract](https://blog.coincodecap.com/tag/smart-contact/) backend.

As I mentioned in [part 2](https://blog.coincodecap.com/building-an-ethereum-simulation-game-part-2/), players must be enlisted to compete and must meet certain attribute requirements to do so. Once enlisted, the user should be able to choose another enlisted player for their player to compete against, and await the result and subsequent XP gains.

Figure 6 shows the “Compete” tab when the user’s selected player is enlisted.

![](https://cdn-images-1.medium.com/max/880/1*8DtVEK0i1V8R-OBn8tvihQ.png)<figcaption>Figure 6: “Compete” tab</figcaption>

The “Find Opponent” section lists all the other enlisted players to compete against. (At the moment, the function that retrieves these from the blockchain gets every player. This will need to be changed as the player list grows to enable pagination, or even searching.) The bottom section enables the user to challenge a player using the player ID directly instead of selecting from the list.

Figure 7 shows how the matches are played. The player with ID 2 is the slightly better player, so when the player with ID 3 challenges in the first match, player 3 loses. When player 2 challenges player 3 in the second match, player 2 wins again.

<iframe title="Let's Make An Ethereum Simulation Game Part 5" width="640" height="360" src="https://www.youtube.com/embed/vhOLlhOF_nk?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

* * *

### Next Steps

There are several things wrong with the game that need to be addressed:

- The “Results” page isn’t done yet.
- The interface is disgusting. It doesn’t even look like a game. The feedback mechanisms need to be sharpened, and it needs a colour scheme, branding and artwork.
- After training, competing and resting, eventually, your player either runs out of XP or runs out of condition. There needs to be a time-based mechanism to replenish one, most likely the Condition. As well as this, I might add a paid “Super Rest” and call it something like “Physio Room” where it costs ETH to supercharge your player’s condition.
- The match playing algorithm in the Smart Contract is very primitive. The player with more attribute points always wins.
- Training player attributes should become more difficult as that attribute gets better. In other words, the higher the attribute level, the more difficult it should be to level up.

Initially, I’ll finish off the results page, and then after that, I’m not too sure. Design is not my strong-point, so coming up with fancy branding will likely be put off until I get the motivation to do it. I think that’s what is holding the game back from going to the next level. 

The code repo is on Github so it’s public and open to pull requests. If you’re interested in helping out please to contribute! Here is the repo: [**alexroan/tennis-manager**](https://github.com/alexroan/tennis-manager)

* * *

### Further Reading

If you’re interested in Blockchain Development, I write tutorials, walkthroughs, hints, and tips on how to get started and build a portfolio.

Check out some of these resources:[**Blockchain Development Resources To Follow Right Now**](https://medium.com/blockcentric/blockchain-development-resources-b44b752f3248)

#### **Also Read**

- [Building An Ethereum Simulation Game – Part 1 – Inception](https://blog.coincodecap.com/an-ethereum-simulation-game-part-1/)
- [Building An Ethereum Simulation Game – Part 2 – Playing Tennis Matches](https://blog.coincodecap.com/building-an-ethereum-simulation-game-part-2/)
- [Building An Ethereum Simulation Game – Part 3 – The Front End](https://blog.coincodecap.com/building-an-ethereum-simulation-game-part-3-the-front-end/)
- [Building an Ethereum Simulation Game – Part 4 – Training and Resting Players](https://blog.coincodecap.com/building-an-ethereum-simulation-game-part-4-training-and-resting-players/)
- [Ethereum Smart Contracts and the Oracle Problem](https://blog.coincodecap.com/ethereum-smart-contracts-and-the-oracle-problem/)
- [Proposing Future Ethereum Access Control](https://blog.coincodecap.com/proposing-future-ethereum-access-control/)
- [Tezos Cryptocurrency – An Ultimate Guide](https://blog.coincodecap.com/tezos-cryptocurrency-an-ultimate-guide/)
- [Ethereum Name Service (ENS)- An Overview](https://blog.coincodecap.com/ethereum-name-service-ens/)
- [Non-Fungible Tokens Explained](https://blog.coincodecap.com/non-fungible-tokens-explained/)
- [Tezos Blockchain – A Simple Overview For Beginners](https://blog.coincodecap.com/tezos-blockchain-a-simple-overview-for-beginners/)
- [Analyzing Developers in Cryptocurrency Projects](https://blog.coincodecap.com/analyzing-developers-in-cryptocurrency-projects/)

The post [Ethereum Simulation Game — Part 5 – Competing Against Other Players](https://blog.coincodecap.com/ethereum-simulation-game-part-5/) appeared first on [CoinCodeCap Blog](https://blog.coincodecap.com).