My first game – Trader Joes

As noted in my previous post we were posed with creating a text based terminal game using Ruby. I wanted to create a game that was functionally similar to the game Drug Wars. The aim of the game is to buy/sell products to make as much profit as you could by the end of the term. I used to play this game a lot as a teenager and thought it was something that I could try to code myself. I decided to make the subject matter a little less risky so decided to buy/sell fruits/veg instead!

***DISCLAIMER : ***
This is my first project and I appreciate that the code looks pretty terrible and is all over the place. However I’m still learning and I will hopefully write better code soon! But if you have any thoughts/suggestions then I would love to hear them!
******************

If you would like to download the code then please feel free to take a look at my github repo.

The premise

As noted above, the aim of the game is to see what’s on offer at a certain location, buy/sell goods, then move to a different location with new prices and trade there. The ultimate aim is to make as much profit as possible. The game will have a deadline (set as 10 days) so all goods would need to be sold by this point.

For this I would need a few critical functions:

  1. buying goods
  2. selling goods
  3. moving locations
  4. changing prices

Initial setup

I started off by setting up the initial state for the game. This included setting the foods on offer, the locations you can visit, the players’ current balance, etc.

As I progressed with coding the project I learnt that I couldn’t change the value of a variable from within a function. This was due to ruby variables not having ‘lexical scope’. I got some useful help from stack overflow for this issue. During the week my instructor had said that a function shouldn’t change a global variable (I think!) but I didn’t know another way for me to achieve my goal of updating a current balance when goods were bought. In the end I figured a hash was mutable, so I decided to press on with that approach instead. As I said, this isn’t the right way to do it, but it worked!

The functions required to operate the game would be held in a big loop statement so that the user was prompted again and again what they wanted to do until the end of the game. I felt this worked well, although sometimes it was hard for me to visualise when I was breaking out of the loop.

Buying products

I decided that I wanted the user to be prompted with a list of options for the different types of goods that they could buy. Then they would be asked how much of that product did they want to purchase. The user would be prompted and an answer would be collected using a ‘gets.strip’ call. A simple case statement would return the name of the good from the number input:

Now, I ended up with this really horrible looking function that requires 6 parameters. As the stack overflow user noted, this wasn’t stylistically correct. At the time I didn’t know I was doing anything wrong. The user suggested using a class which is something I noted in my previous post that I didn’t have enough experience in. This is now one of my actions in the file features.txt which lists some of the things I want to do in the future. One of which is to refactor my code so it’s much cleaner so this is something I’ll look to do soon.

This function calculates a total price from the product and amount chosen. It then adjusts the value of the user’s balance from that point. It also updates a record of the amount of goods the user currently holds (updating myProducts[ ]). A feature that was later brought in was limiting the amount of goods a user can hold (currently set to 50). The code then updates the amount of space a user has left in their bag and outputs some messages.

A problem I first considered was if the user could actually buy that good/amount. Therefore I introduced a check function which runs through the following test cases:

  • can the user afford to buy the amount of products specified?
  • does the user have enough space to buy those products?

I also included a quick case that if they didn’t buy anything then a simple message would be outputted and the user would be taken back to the start menu:

Again, so many parameters!

One problem I encountered was knowing how many products we could actually buy. In earlier cases of the game there was no limit to your basket, you were only limited by the amount of your balance. But when I introduced a cap on the amount of items held, this mean I needed to create a formula to calculate the minimum of the amount you could afford to buy, or the amount of space you had remaining. This was done in the main body of our game:

Selling products

Similar to above, I created two functions to check whether the user could sell the goods specified and then actually sold them, updating the user’s data as they were called:

This was the main body of my game. Now I could buy/sell products, update my balance as transactions came through and also update my basket. Next I needed to to move locations and change the price of the goods as we went through to different places.

Moving locations

This was relatively straight forward. I created a global variable ticker that increased the day as I moved locations. The location was again shown as a list with a user prompt for where they would like to go, using a switch statement to map which location they picked from their input:

Here I change the ‘msgs[ ]’ which were triggers for when to show certain messages. For instance, I didn’t want a ‘Welcome’ message every time the user pressed an action button. So I set a flag to say once this was shown, don’t show again.

Changing the price of the goods

Initially I was just testing the buy/sell features using a constant price. However I wanted the prices to change every time I moved location. Again this was a simple fix. I created an if statement early on in the loop to randomise a price given a set range. This was dependent on whether the ‘intro’ message had been seen. In hindsight I don’t think this was the best thing to pivot on, but it got the job done:

I created a range for each product, made it into an array and took a random sample from that array. That way each time we moved location, the intro message was set to false which prompted a new price to be calculated for our goods. This meant that now our game was actually a bit of a game. Now we can buy/sell and try to increase our balance.

Other features

Along the way I included some other features too. One was a time limit on the amount of days you had. This was simple. As you can see in the moving locations code above I included a ‘day+=1’ line to increase our day ticker by one. However I wanted to prompt the user if they were on their last day, so that they knew the end of the game was nearing and they can maximise their score. I included a check for last day function which did the trick (again, many parameters!):

This function also provided a final score when the limit was breached. 

I’ve started reading Clean Code by Robert Martin which says that functions should do one thing only, but do it well. I’m concious that a lot of my code above does not meet this criteria but it’s something I’ll strive to incorporate in my code going forward.

Some smaller things I included was an option to show the price list from the main menu. I did output this when buying items so it was simple to make this it’s own section in the menu. I also had an entry which showed your current itinerary in case you were unsure of what you held, although in hindsight I’m not so sure how useful this is given it is shown when you come to sell items anyway.

To be completed

As noted I have a range of features that I’d like to incorporate into my game. These include:

  • ability to buy extra space in basket at random intervals
  • loans + interest
  • market crashes
  • save scores to leaderboard
  • refactoring and bug fixes, etc

I feel that these are all doable with my skillset so I’m hoping to get these included in the near future.

Conclusion

All in all I was really happy with where I got to with this project. As I’ve noted, I know my code isn’t nice, it leaves a lot to be desired! But functionally it does what I want to do for a v1 of my game. It actually feels like a game where I’m trying to increase my balance. 

I think the features noted above will help to improve the game but to be honest I was surprised I managed to do this well with it.

Although it looks like I won’t be using Ruby in my day job I was happy I kept with it and tried to learn something new. But it will be back to Javascript soon!

1 thought on “My first game – Trader Joes”

Comments are closed.