Updating Coin Logic for a Python Mario Clone

Alex Kong
4 min readNov 2, 2018

--

For my initial Hacktoberfest PR I wanted to work on a Python based project to refresh my Python skills. I was browsing through the search filter for Hacktoberfest tagged issues when I stumbled upon the Python Terminal SuperMario project. The tagged issue that initially caught my attention was an issue asking for a new start screen for the game however the issue that I really intrigued me was implementing the coin capture logic.

screenshot of the project in action

During my initial pass through the code after reading the issue I could verify that the code currently scanned all coins active on the map to check if they could be collected. If the Coin identifier intersected with the Mario identifier the Coin is captured and the appropriate updates occur. While this logic works it is rather inefficient and won’t scale well if new levels have a large number of coins at once so I devised a few ideas to update this logic to improve its runtime and availability.

The Idea and First Attempt

As far as I’m aware, Python dictionaries are implemented as hash tables which means key lookup is constant (O(1)) which means the time it takes to retrieve a Coin will always remain the same as long as I am doing a direct lookup in the dictionary for it. Going off of this I thought, “instead of checking each individual Coin to see if they intersect why don’t we exploit Mario’s known coordinates?” If we stored the array index of each Coin in a 2 dimensional dictionary that stores the x and y coordinates of the Coin then we can check if a Coin exists at Mario’s location by passing Mario's location into the dictionary and checking if the keys exist. Doing this would reduce the number of Coins looked up to 1 instead of all.

I informed the maintainer of my idea on the issue who signed off on my theoretical concept so I set to work.

store_coin the new Coin storage function

After a bit of testing a kink in my plans appeared: Mario’s dimensions weren’t 1x1 so he was bigger then the Coins which means my logic would fail if the Coin didn’t touch a specific part of Mario. As I tried to use simple math to fix the issue I realized that it couldn’t be done without using introducing a number of loops which I knew was avoidable.

Code snippit from attempt 1

The Debugging Debacle and my Drive-by PR

When I was trying to debug my initial attempt I tried to debug the code using breakpoints in Visual Studio Code but I ran into an issue where VS Code’s terminal did not refresh fast enough to feasibly test the code’s functionality so I tried to go to my fallback: Windows Visual Studio. Unfortunately this was also unsuccessful as the code uses Python’s signal.alarm(time) function which is not supported on Windows machines.

This development meant that my debugging was mostly going to revolve around print statements to check and verify variables and values but this also means I found another issue that I can create a PR for: Add a warning in the README.md to warn others about the code’s incompatibility with Windows.

Attempt 2

When I first theorized my PR I wanted to go with the least intrusive approach that achieved the required result without changing the source logic too much. While this was the intent it wasn’t achievable but I also had a backup plan: Since I can’t rely on the coordinates stored in the Mario object I’ll rely on the locations being updated with the Mario identifier and perform my check when the board is being updated with the Mario M. I was cautious of this approach because it will add one additional check to every board update however I believe this is still more efficient then checking each individual coin during each board refresh.

I created debug statements to help me verify functionality and behavior to make sure I didn’t overlook any details.

The result was reworked Coin logic which should scale better then the current implementation.

--

--