<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jack Beresford</title>
    <description>The latest articles on DEV Community by Jack Beresford (@jberesford94).</description>
    <link>https://dev.to/jberesford94</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3239729%2F3cad5292-e8f5-494b-a0b6-f5bab88ebddc.jpg</url>
      <title>DEV Community: Jack Beresford</title>
      <link>https://dev.to/jberesford94</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jberesford94"/>
    <language>en</language>
    <item>
      <title>The 12 Days of Christmas - Programmed vs. Compressed</title>
      <dc:creator>Jack Beresford</dc:creator>
      <pubDate>Tue, 23 Dec 2025 11:04:35 +0000</pubDate>
      <link>https://dev.to/jberesford94/the-12-days-of-christmas-programmed-vs-compressed-cfd</link>
      <guid>https://dev.to/jberesford94/the-12-days-of-christmas-programmed-vs-compressed-cfd</guid>
      <description>&lt;p&gt;The famous 'Twelve days of Christmas' song has a cumulative nature, in that every day adds a gift, and therefore a line to the song.&lt;br&gt;
The fact that there are only 12 unique gifts, the numbers 1 through 12, yet about 90 lines in the song, should tempt an exercise to shorten it.&lt;/p&gt;

&lt;p&gt;The song can easily to be reproduced in a programming language, with the verbal ingredients as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;days = ["first","second","third","fourth",\
        "fifth","sixth","seventh","eighth",\
        "ninth","tenth","eleventh","twelth"]

gifts = ["A partridge in a pear tree.","Two turtle doves","Three French hens",\
         "Four calling birds","Five gold rings","Six geese a-laying",\
         "Seven swans a-swimming","Eight maids a-milking","Nine ladies dancing",\
         "Ten lords a-leaping","Eleven pipers piping","Twelve drummers drumming"]

onThe = "On the " 
gave = " day of Christmas my true love gave to me"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With some simple iteration in Python (working along the days/gifts), we can write the song in a new text file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;with open("12Days.txt", "w") as file:
    for i in range(len(days)):

        # First line of every day
        file.write(f"\n{onThe}{days[i]}{gave}:\n{gifts[i]}\n")

        # Avoid operations for first day
        if i == 0:
            continue

        # iterate until no more gifts to give
        next = i-1
        while next &amp;gt; 0:
            file.write(f"{gifts[next]}\n")
            next -= 1
        file.write(f"And {gifts[next].lower()}\n")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a text file ending like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9cb1oqsasnspkbnbd4n.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9cb1oqsasnspkbnbd4n.JPG" alt=" " width="500" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not bad. But one flaw of this reproduction is that it required understanding of the song's syntax and structure. Compression, which we see in zip files, jpegs, and so on, can 'shorten' without any understanding, as compression algorithms run on independent rules.&lt;/p&gt;

&lt;p&gt;You can see this with the zlib compression algorithm, imported from Python &lt;a href="https://docs.python.org/3/library/zlib.html" rel="noopener noreferrer"&gt;https://docs.python.org/3/library/zlib.html&lt;/a&gt;. It is highly performant with files like this, as repeated lines can be replaced with 'pointers' to refer back to an original reference (e.g. the first utterance of 'a partridge in a pear tree').&lt;/p&gt;

&lt;p&gt;Calling zlib.compress() with the original file will return a bytes object, looking like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0h6srtey6tjvq4oo2a7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0h6srtey6tjvq4oo2a7.png" alt=" " width="800" height="44"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This text might be incomprehensible, but at a size of 0.31 KB (just 13% of the size of the full song's 2.36 KB), the zlib algorithm shows its power and application for internet libraries and more.&lt;br&gt;
Most importantly, it can decompress(), allowing the file to return to its original format.&lt;/p&gt;

&lt;p&gt;To take this one step further, one can try the complete Works of Shakespeare: &lt;a href="https://www.gutenberg.org/cache/epub/100/pg100.txt" rel="noopener noreferrer"&gt;https://www.gutenberg.org/cache/epub/100/pg100.txt&lt;/a&gt;&lt;br&gt;
I got this down to 2MB with a quick attempt, but I'm sure it can be made even smaller!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfb4n9mywkqcayaps9ca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfb4n9mywkqcayaps9ca.png" alt=" " width="794" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Text Based Games and How to Make Them</title>
      <dc:creator>Jack Beresford</dc:creator>
      <pubDate>Sun, 29 Jun 2025 17:39:09 +0000</pubDate>
      <link>https://dev.to/jberesford94/text-based-games-and-how-to-make-them-4igj</link>
      <guid>https://dev.to/jberesford94/text-based-games-and-how-to-make-them-4igj</guid>
      <description>&lt;p&gt;After frustration at modern TV and film, I have returned to the ever reliable written word, by which I mean crude text-based games in Python.&lt;/p&gt;

&lt;p&gt;At its core the text based game is just conditional logic.&lt;br&gt;
If this, then print this, otherwise, print something else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;choice1 = input("What's your name?")


if choice1 == 'Eggbert':
    print ("Hello!")
else:
    print("Invalid name")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All fun and games. But in a text based game we want 1 of 2 or more specific options. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;choice1 = input("Are you better at ENGLISH or FRENCH?")


if choice1 == 'ENGLISH':
    print ("Hello!")
elif choice1 == 'FRENCH':
    print("Bonjour!")
else:
    print("Invalid entry")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fine enough but two weaknesses we can see are: &lt;br&gt;
 Case sensitivity. Writing ‘french’ or ‘French’ seems an equally valid entry, but it would be rejected as it is not == (equal to) ‘FRENCH’&lt;br&gt;
The else: statement doesn’t actually stop us, which is to say, we can get _past _choice1 by writing anything. In the case of text based games, there are right and wrong answers, so why let the player get past a stage by writing nonsense?&lt;/p&gt;

&lt;p&gt;To solve this, we do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;choice1 = input("Are you better at ENGLISH or FRENCH?").upper()


while choice1 != 'ENGLISH' and choice1 != 'FRENCH':
    choice1 = input('Invalid entry. Are you better at ENGLISH or FRENCH?:   ')


if choice1 == 'ENGLISH':
    print ("Hello!")

elif choice1 == 'FRENCH':
    print("Bonjour!")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The upper() function converts the user input into all caps (even if the user writes in all caps). Doing this at the end of the input() function means all subsequent conditionals will work, no need to put upper on anything else.&lt;/p&gt;

&lt;p&gt;Using a while loop with negative conditions keeps the user stuck until they have written 1 of these choices. What prevents this while loop from running indefinitely is that they have the chance to redefine the input. &lt;/p&gt;

&lt;p&gt;It is with this logic that we make a common starting feature of games: a player choosing their name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;player_name = input("What is your name?:    ")
print(f"Hello, {player_name}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use of an f string i.e. f” allows the variable player_name to be invoked in a string, in this case a greeting. But let me show you a flaw of this simple approach:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;What is your name?:    aaaaaaaaaaaaaaaaaaaaaaaaaa1111111111111111111111111111111111111111&lt;br&gt;
Hello, aaaaaaaaaaaaaaaaaaaaaaaaaa1111111111111111111111111111111111111111&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Not much good this; if your cat walked across your keyboard and pressed Enter, the name would be stuck like this and printed in all subsequent f strings. &lt;/p&gt;

&lt;p&gt;We should therefore insert some rules. I’ve decided 1) the name should not be more than 12 characters,  and 2) made up of only letters (no numbers, punctuation or spaces).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;player_name = input("What is your name?:    ")
while not player_name.isalpha() or len(player_name) &amp;gt; 12:
player_name = input("Invalid entry. Must be &amp;lt;12 characters and only letters A-Z.\nTry again:  ")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use a while not loop because it works well with isalpha(), a method of checking if a string is all letters (e.g. A-Z) or not. &lt;br&gt;
len() &amp;gt; 12  is True when the string is more than 12 characters&lt;br&gt;
Putting them together in an or loop, checks if 1, or both of these conditions is true.&lt;br&gt;
We’ll test it now:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;What is your name?:    john1&lt;br&gt;
Invalid entry. Must be &amp;lt;12 characters and only letters A-Z.&lt;br&gt;
Try again:  johnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn&lt;br&gt;
Invalid entry. Must be &amp;lt;12 characters and only letters A-Z.&lt;br&gt;
Try again:  john11111111111111111111111111111111111&lt;br&gt;
Invalid entry. Must be &amp;lt;12 characters and only letters A-Z.&lt;br&gt;
Try again:  john&lt;br&gt;
Hello, john&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You’ll note that the logic governing this is similar to the logic governing what constitutes a ‘strong’ password, valid email addresses and so on. &lt;/p&gt;

&lt;p&gt;You could probably make a decent text based game with just these features, but one thing I’ve learnt is that writing lines of text is the easy thing. Adding functionality, that’s the hard part. &lt;/p&gt;

&lt;p&gt;*Note - this is the first time I use the \n new line character. It is very helpful for f strings, inputs and so on, ensuring you can keep lines printed out in a user-friendly way. Basically, write \n, and everything after will appear on a new line.&lt;/p&gt;

&lt;p&gt;My final game (link below) uses 2 extra features: &lt;br&gt;
1) writing out the script via the sys.stdout.writeout() method, the speed of which can be user-defined, and 2) Dungeons and Dragons style combat using the random.randint() method. &lt;/p&gt;

&lt;p&gt;The combat is quite simple. Anyone who’s made a dice roll will have used it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import random
dice_roll = random.randint(1,6)
print(f"You rolled a {dice_roll}!")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import the random module. Random.randint(1,6) means, give me a random number between 1 and 6. Then print it. &lt;br&gt;
This can also be done without the variable assignment (printed straight away), and it makes for a big difference. I’ll show you with a more combat based example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import random

player_attack = random.randint(1,6)
enemy_health = 2
enemy_name = "Jeff"

print(f"{enemy_name} is on {enemy_health}health. Time to attack!")
print(f"You hit {enemy_name} for {player_attack} damage.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks fine right? Well, a problem is that the random.randint() will not run again and again and again, when we loop through a fight sequence. It will run one time, i.e. to assign the variable player_attack with the value of a random integer between 1 and 6. This means if you wanted a combat sequence, you could be hitting the same amount of damage every time you attack. This is not the point at all. &lt;/p&gt;

&lt;p&gt;That being said, smart code is lazy code, and you don’t want to write random.randint(1,6) every time. You may even want to modify the attack range if your player finds a brand new fancy weapon or something. This is where I came up with a ‘max damage’ for characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;player_max_damage = 6
print(
    f"You hit {enemy_name} for {random.randint(1, player_max_damage)} damage.")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key difference is that the random number is generated within each attack (between 1 and the max damage), not before and throughout.&lt;/p&gt;

&lt;p&gt;The next concern should be how to win or lose a battle? How do we make sure it continues until one or both of us is dead?&lt;/p&gt;

&lt;p&gt;Well first, we need to reassign values to health, such as:&lt;br&gt;
enemy_health -= 2&lt;br&gt;
This will subtract 2 from the current enemy health and then reassign that value to the variable.&lt;/p&gt;

&lt;p&gt;Then, we need to end the fight if the enemy’s or our health reaches 0 or less.&lt;/p&gt;

&lt;p&gt;Here’s how I achieved this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while True:
    print('--⚔--⚔--⚔--⚔--ATTACK--⚔--⚔--⚔--⚔--')
    input(f"You have {player_health} health. {mob_name} has {mob_healths[mob_name]} health")
    player_attack = random.randint(1, player_damage)
    mob_healths[mob_name] -= player_attack
    if mob_healths[mob_name] &amp;gt; 0:
        print(f"You hit the {mob_name} for {player_attack} damage.")
        print(f"{mob_name} is now on {mob_healths[mob_name]} health.\n")
    else:
        print(f"You hit the {mob_name} for {player_attack} damage and defeat it!\n")
        break
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Putting this in a while loop ensures the conditions are checked, and that the only way we can leave is DEATH…&lt;/p&gt;

&lt;p&gt;Jokes aside, most of these values are predefined, will show these later - they are easy to change.&lt;/p&gt;

&lt;p&gt;In short, we have an if statement for if the enemy has more than 0 health, and an else if they don’t (we defeated it!)&lt;/p&gt;

&lt;p&gt;Now within that same loop, we can put our defense (the enemy should get a turn to attack as well).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    print('--🛡--🛡--🛡--🛡--DEFEND--🛡--🛡--🛡--🛡--')
    input(f"You have {player_health} health. {mob_name} has {mob_healths[mob_name]} health")
    mob_attack = random.randint(1, mob_max_damages[mob_name])
    player_health -= mob_attack
    if player_health &amp;gt; 0:
        print(f"The {mob_name} hits you for {mob_attack} damage.")
        print(f"You are now on {player_health} health.\n")
    else:
        print(f"The {mob_name} hits you for {mob_attack} damage.")
        print("💀 You died! GAME OVER 💀\n")
        break
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrap this all together, within a combat() function, needing only the variables:(mob_name, player_health). Player_health is not so much a concern, when we run future combat() functions we can just put the {player_health} curly braced inside. I wanted the option to ‘level up’ the character at some point and therefore increase += their health.&lt;/p&gt;

&lt;p&gt;Anyway, what I think makes this combat function powerful is that the mob_name will reference an indexed position in 1 list and 2 dictionaries i.e. [0] or [2] in mob_name, mob_healths, and mob_damages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    mob_names = ["Bug 🐛", "Wolf 🐺", "Goblin 👺"]


    mob_healths = {
        mob_names[0]: 6,
        mob_names[1]: 8,
        mob_names[2]: 10
    }


    mob_max_damages = {  # a random.randint() will run between 1 and these numbers
        mob_names[0]: 3,
        mob_names[1]: 5,
        mob_names[2]: 6
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These run independent of the combat() function, and if you want to change the theme of the game then all you have to do is change the name. Nothing else needs to change, everything will print out and run for you. Of course you can change the healths and damages but be sure to consider balance in your game.&lt;/p&gt;

&lt;p&gt;Now for the text speed, which relates to parts of the sys and time module.&lt;br&gt;
I did this all in one place at the top, along with the random module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import time  # for time.sleep() printing text
import sys  # for text speed (optional)
import random  # for 'rolling' a dice etc.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write an introduction, or scene description. Give it a name and try and keep it all in one string. This can be done by avoiding a long line as so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    intro = (f"Welcome to {game_name}, a text-based adventure game.\n"
             f"{game_name} is set in {world}, in {time_or_setting}.\n"
             "Scenes will be read out for you, like this.\n"
             "Choices will be printed out in full and require you to type an answer.\n"
             "They will follow a ':' semicolon. You can only do 1 thing at a time. \n"
             "Let's begin with the first choice, your name.\n"
             )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using \n line breaks and keeping the quotation marks at the same indentation as the previous, ‘intro’ can be several lines long while still belonging to the same variable. That is all we need to have it written out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for char in intro:
        sys.stdout.write(char)
        sys.stdout.flush()
        time.sleep(text_speed)`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works for with a for loop. We say that for every char in intro (for every character in intro)&lt;/p&gt;

&lt;p&gt;Note that instead of char we could write anything, like ‘letter’, ‘thing’ and so on, as long as we correctly refer to it again in the sys.stdout.write() function. Anyway, char makes sense, and readability is important.&lt;/p&gt;

&lt;p&gt;sys.stdout.write() is very similar to print(), only different insofar as it prints every character, and doesn’t add spaces. It’s basically a precise printing tool.&lt;/p&gt;

&lt;p&gt;sys.stdout.flush() is very important here; it ensures that rerunning this loop still keeps the characters on the same line. Without it, the for loop would make each character print underneath itself. &lt;/p&gt;

&lt;p&gt;time.sleep() is what we use as the time gap between each character being printed. I reference text_speed, which I put at the top of my program, allowing the user to define speed as they like (they may read faster or slower than me).&lt;/p&gt;

&lt;p&gt;Wrapping up - I put the bulk of my game inside a main() function and indented the lot. This is a good idea because putting underneath the lot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if __name__ == "__main__":
    main()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will ensure that the program can only be run from the program directly; it’s best practice. I also like to hide the script this way and look at more ‘master’ items, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import time  # for time.sleep() printing text
import sys  # for text speed (optional)
import random  # for 'rolling' a dice etc.


# User-defined items
game_name = "The Project"  # *changeable - will be reflected everywhere else
title = (f"-💾-⌨-💻---{game_name}---💻-⌨-💾-")  # modify emojis as you wish
world = "Procrastinationland"  
# be conscious of grammar when printed
time_or_setting = "2025"
# get a feel for how fast you like the text speed when you run the code
text_speed = 0.05
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila. With those building blocks, more scenes, enemies, stories etc. can be fleshed out to make it more of a story.&lt;br&gt;
Additional improvements I would make would be: &lt;br&gt;
1) ‘dice rolls’ outside of combat to determine the possibility of doing things. I have made this before and it’s pretty easy - ‘if &amp;lt; 10, fail. If &amp;gt;10, pass. If == 1, spectacularly fail, etc. &lt;br&gt;
2) consequences for decisions by storing a boolean that can be referred to later. For example, if you did choose to help the hungry villagers, then help_village = True. In your character’s return weeks later , the villagers could either be gone, or alive and willing to repay you, simply based on that boolean. &lt;br&gt;
3) animations. While this technically contradicts the text based nature of the game, I am already using text read out, and a similar principle could do something like showing the character and an enemy get closer until they meet at crossed swords. There are lots of possibilities.&lt;/p&gt;

&lt;p&gt;I plan to return to make other games in Python and I look forward to publishing here.&lt;/p&gt;

&lt;p&gt;The full code for this project is on github for others to copy and change: &lt;a href="https://gist.github.com/JBeresford94/285ec3dc58f694dca51a482cffc6a5fa" rel="noopener noreferrer"&gt;https://gist.github.com/JBeresford94/285ec3dc58f694dca51a482cffc6a5fa&lt;/a&gt; &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Compound Interest Calculator in Python</title>
      <dc:creator>Jack Beresford</dc:creator>
      <pubDate>Mon, 02 Jun 2025 17:49:00 +0000</pubDate>
      <link>https://dev.to/jberesford94/compound-interest-calculator-in-python-3j45</link>
      <guid>https://dev.to/jberesford94/compound-interest-calculator-in-python-3j45</guid>
      <description>&lt;p&gt;If you’ve ever compared the effect of slightly different interest rates over the long term, you’ll agree with Albert Einstein that “Compound interest is the eighth wonder of the world.”&lt;br&gt;
Until recently, I had experimented with compound interest using websites and excel. But after using Python, I realised it would be superior to use for the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Python is better for delivery of an output from an input, via a terminal like the one you get in Visual Studio. This way, you put a few numbers in, and a user-friendly result comes out. This makes it easily repeatable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With well written code and comments, it is easy to understand and interrogate the calculation. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With an alternative like Excel, you may have to dig into the cell or read an adjacent line of text. With an app or a website, you run on trust since you are unable to interrogate the inner workings.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This blog details the considerations and building process. The final code is available on &lt;a href="https://gist.github.com/JBeresford94/af3143161e095efb8339e3d878e87ee7" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and at the end of this blog.&lt;/p&gt;

&lt;p&gt;What does the code need to do?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run a simple algebraic function using inputted variables&lt;/li&gt;
&lt;li&gt;Successfully apply interest rate. E.g. 5% turns £1 into £1.05, not £5 or £0.05 &lt;/li&gt;
&lt;li&gt;Provide an easy User Interface (UI) that anyone can use&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Function
&lt;/h1&gt;

&lt;p&gt;In pseudocode:&lt;br&gt;
Final sum = initial value x (interest rate x number of years)&lt;/p&gt;

&lt;p&gt;In Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# This function calculates an output based on initial value /
# Interest rate and number of years. These are all to be inputted by the user.
def compound_interest(initial_value, interest_rate, years):
    output = initial_value*(1 + interest_rate)**years
    return output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Inputs
&lt;/h1&gt;

&lt;p&gt;Now I need to define the variables: initial_value, interest_rate, years as all user-inputs, so that when we run the code, that is what the user is asked for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initial_value = float(input("Enter the initial value without currency or commas e.g. 1000 or 1000.99:"))
interest_rate = float(input("Enter the interest rate, as a decimal, e.g. 5% = 0.05:"))
years = int(input("Enter the number of years:"))
#Initial value is best used as a float, so you can use decimal values like £120.52
#Interest rate is also best used as a float, for functional reasons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The input() functions ensure the user will be prompted to enter a value, and the strings in quotation marks tell the user how to do so.&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing
&lt;/h1&gt;

&lt;p&gt;Before improving the UI, I decided to test that this code actually works. &lt;/p&gt;

&lt;p&gt;Running this code in the terminal we get the first input prompt:&lt;br&gt;
“Enter the initial value:”&lt;br&gt;
We type a figure. In this test we’ll use a float, because why go easy on it with an integer? &lt;br&gt;
We type “15420.99” and hit enter.&lt;br&gt;
Then we get the second input prompt:&lt;br&gt;
“Enter the interest rate, as a decimal, e.g. 5% = 0.05:”&lt;br&gt;
We type a figure. In this case we’ll use 8.5% or 0.085. Again, why be nice and use the example?&lt;br&gt;
Then we get the third input prompt:&lt;br&gt;
“Enter the number of years:” &lt;br&gt;
We type 5, press enter, and the final value is given as:&lt;br&gt;
23187.87478266996&lt;/p&gt;

&lt;p&gt;Here’s how it looks in the terminal on completion:&lt;br&gt;
Enter the initial value:15420.99&lt;br&gt;
Enter the interest rate, as a decimal, e.g. 5% = 0.05:0.085&lt;br&gt;
Enter the number of years:5&lt;br&gt;
23187.87478266996 &lt;/p&gt;

&lt;p&gt;Did it work?&lt;br&gt;
Let’s compare it to a compound interest calculator I found online: &lt;a href="https://www.thecalculatorsite.com/finance/calculators/compoundinterestcalculator.php" rel="noopener noreferrer"&gt;https://www.thecalculatorsite.com/finance/calculators/compoundinterestcalculator.php&lt;/a&gt; &lt;br&gt;
Answer: £23,187.87&lt;/p&gt;

&lt;p&gt;It works! 🙂&lt;/p&gt;
&lt;h1&gt;
  
  
  Ideas and improvements:
&lt;/h1&gt;

&lt;p&gt;The function would still work if years had the float data type rather than integer. This way you could enter 6.5 for 6 and a half years, etc. I confirmed with a test that it works, but returned the code to its simplest integer form. &lt;br&gt;
You don’t usually denote money with 11 decimal places… Using the round function I created the new output, adding an extra line to the function as so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def compound_interest(initial_value, interest_rate, years):
    output = initial_value*(1 + interest_rate)**years
    rounded_output = round(output, 2)
    return rounded_output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: 23187.87&lt;br&gt;
We can add some words and currency to make it look nice, by modifying the print() function to precede the output with words and a currency symbol&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print("Initial + interest = £",compound_interest(initial_value, interest_rate, years))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: Initial + interest = £ 23187.87&lt;/p&gt;

&lt;p&gt;Code (final):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# This function calculates an output based on initial value, interest rate, and number of years.
def compound_interest(initial_value, interest_rate, years):
    output = initial_value*(1 + interest_rate)**years
    rounded_output = round(output, 2)
    return rounded_output
initial_value = float(input("Enter the initial value:"))
interest_rate = float(
    input("Enter the interest rate, as a decimal, e.g. 5% = 0.05:"))
years = float(input("Enter the number of years:"))
#Initial value is best used as a float, so you can use decimal values like £120.52
#Interest rate is also best used as a float, for the function to work
print("Initial + interest = £",compound_interest(initial_value, interest_rate, years))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terminal output (example):&lt;br&gt;
Enter the initial value:15420.99&lt;br&gt;
Enter the interest rate, as a decimal, e.g. 5% = 0.05:0.085&lt;br&gt;
Enter the number of years:5&lt;br&gt;
Initial + interest = £ 23187.87&lt;/p&gt;

&lt;h1&gt;
  
  
  Reflections:
&lt;/h1&gt;

&lt;p&gt;I believe there is room to improve the UI. When I improve my skills I may return to this exercise and improve it; after all this is just project  number 1!&lt;br&gt;
Compound interest is usually done at annual intervals, as in this case, but it could easily be done with months, weeks, or days&lt;br&gt;
AI tools like ChatGPT / Copilot were not used to make anything in this exercise. They would have saved time but would’ve deprived me of the learning experience and satisfaction. I did run the final code through ChatGPT at the end to see if I missed anything, and it was as agreeable as always. Crucially, if there’s any error here, it’s 100% human.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
