Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Making a traditional roguelike in Python, Part 1 - ft. Chat GPT

So, to briefly explain, I went through the Reddit approved roguelike tutorial a while back and with the rise of Chat GPT I thought of trying to get it to make the game for me. I'll ask it some questions and ultimately force it to develop a roguelike game with me. This is the conversation that ensued:


"What's a traditional roguelike game?"

A traditional roguelike game is a type of role-playing video game that is characterized by randomly generated levels, turn-based gameplay, and a high level of difficulty. The term "roguelike" is derived from the 1980 game Rogue, which was one of the first games in this genre.

In a traditional roguelike game, players control a character who must navigate through a series of procedurally generated levels, fighting monsters and collecting treasure along the way. The gameplay is typically turn-based, meaning that each player and enemy takes turns making their moves.

One of the defining features of traditional roguelike games is their high level of difficulty. Players often need to carefully manage their resources, such as health and ammunition, in order to survive. Death is also often permanent in traditional roguelike games, meaning that players must start from the beginning if their character is killed.

Despite the challenging gameplay, traditional roguelike games have gained a dedicated following over the years due to their unique blend of randomness, strategy, and resource management.


"How many people would you say play roguelikes?"

It's difficult to estimate the number of people who play roguelike games, as there is no central authority that tracks this information. However, the popularity of roguelike games has grown significantly in recent years, and there are many different roguelike games available on various platforms, including PC, console, and mobile.

According to Steam, one of the largest digital distribution platforms for PC games, several popular roguelike games have had millions of players, including "Enter the Gungeon," "Dead Cells," and "Spelunky." These numbers likely represent only a fraction of the total number of people who play roguelike games, as they do not include players on other platforms or those who play offline.

In addition to traditional roguelike games, there are also many games that incorporate elements of the roguelike genre, such as randomly generated levels and permadeath, into other types of games. These games may also attract a large number of players.

Overall, it's safe to say that there are many people who enjoy playing roguelike games and that the popularity of this genre continues to grow.


"So if I wanted to make a roguelike game using Python, how would I do that?"

If you want to create a roguelike game using Python, you will need to have some programming experience and be familiar with the Python language. Here are the general steps you can follow to create a basic roguelike game using Python:

  1. Set up a development environment: You will need to install Python and any necessary libraries, as well as choose an Integrated Development Environment (IDE) where you can write and debug your code.
  2. Design your game: Consider what type of game you want to create, including the setting, characters, gameplay mechanics, and overall goals. You should also plan out the layout and structure of your game, including the levels and any other features you want to include.
  3. Create the game engine: The game engine is the core of your game, responsible for managing the game's state, handling user input, and rendering the game to the screen. You will need to write code to handle these tasks, as well as any other features you want to include, such as character movement, combat, and inventory management.
  4. Generate the levels: In a roguelike game, the levels are typically procedurally generated, meaning that they are created by an algorithm rather than being designed by hand. You will need to write code to generate the levels randomly, taking into account any constraints or rules you want to apply.
  5. Add artwork and sound: To make your game more immersive, you may want to include artwork and sound effects. You can create these yourself or find resources online.
  6. Test and debug your game: As you develop your game, you will need to test it and fix any bugs or errors that you encounter. This is an ongoing process that will continue throughout the development of your game.

These are just the basic steps for creating a roguelike game using Python. Depending on the complexity of your game and your level of programming experience, you may need to do additional work to fully realize your vision. However, by following these steps and seeking out resources online, you can create a basic roguelike game using Python.


"Ok, I have my Python environment set up, but what would be the best roguelike game to develop in 2023?"

It's difficult to predict with certainty what the best roguelike game to develop in 2023 will be, as the success of a game is dependent on a variety of factors such as the quality of the gameplay, the art and sound design, and the marketing efforts of the developer.

However, there are certain elements that are commonly found in successful roguelike games, such as strong gameplay mechanics, engaging storylines, and replayability. You may want to consider incorporating these elements into your game, as well as finding ways to make your game stand out from other games in the genre.

In addition, you should consider the current trends in the gaming industry and the preferences of your target audience. For example, if you are targeting a younger demographic, you may want to consider incorporating more action-oriented gameplay, while if you are targeting a more hardcore audience, you may want to focus on deeper strategy and resource management.

Ultimately, the best roguelike game to develop in 2023 will be one that delivers a unique and engaging experience to players, and that stands out in a crowded market. By focusing on strong gameplay, a compelling storyline, and replayability, you can increase the chances of success for your game.


"Can you give me some random ideas to get started?"

Sure! Here are a few ideas to get you started on your roguelike game:

  1. A post-apocalyptic survival game: In this game, players must navigate a world that has been ravaged by a disaster, such as a nuclear war or a pandemic. They must scavenge for resources, build shelter, and fight off hostile creatures as they try to stay alive.
  2. A fantasy adventure game: In this game, players control a hero who must journey through a series of procedurally generated dungeons, fighting monsters and collecting treasure. The game could include a variety of character classes, such as warriors, mages, and thieves, each with their own unique abilities.
  3. A horror-themed game: In this game, players must navigate a haunted house or other creepy location, avoiding or fighting off supernatural creatures as they try to uncover the mystery behind the hauntings. The game could include elements of survival horror, such as limited resources and jump scares.
  4. A spacefaring adventure game: In this game, players control a spacecraft as they explore a procedurally generated universe, fighting off hostile aliens and scavenging for resources. The game could include a variety of ship types, such as fighters, cargo ships, and capital ships, each with their own strengths and weaknesses.
  5. A cyberpunk-themed game: In this game, players control a character in a futuristic city overrun by corporations and crime. They must hack into computer systems, fight off rival hackers and corporate operatives, and unravel a conspiracy that threatens to bring down the city.

These are just a few ideas to get you started. With a little creativity and some programming skills, you can turn these ideas into a fully-fledged roguelike game.


"Which of these examples would work best if I want the player to encounter companions that can be added to their parties to help in their journey?"

All of the ideas that I mentioned could potentially include companions that can be added to the player's party to help in their journey. However, some ideas may lend themselves better to this concept than others.

For example, the fantasy adventure game and the spacefaring adventure game both lend themselves well to the concept of adding companions to the player's party. In these games, players could encounter other characters, such as fellow adventurers or alien allies, who could join their party and assist them in combat and other tasks.

The post-apocalyptic survival game and the horror-themed game could also include companions, although they may need to be implemented differently to fit the theme of the game. In the survival game, players could encounter other survivors who join their group and help with tasks such as scavenging and building. In the horror game, players could encounter allies who help them navigate the haunted location or fight off supernatural threats.

The cyberpunk-themed game could also include companions, although they may be more focused on hacking and other non-combat abilities. Players could encounter other hackers or corporate operatives who join their group and help with tasks such as cracking computer systems or infiltrating enemy facilities.

Ultimately, the best game to include companions will depend on the specific themes and gameplay mechanics that you want to include in your game. By considering the overall concept and direction of your game, you can determine the best way to implement companions to enhance the player's experience.


"Well, considering this is my first roguelike I'll make a fantasy game in which the player can encounter allies, depending on their social skills, and adventure together. What's the best Python library to make it?"

There are several Python libraries that you can use to create a fantasy game in which the player can encounter allies and adventure together. Here are a few options:

  1. Pygame: Pygame is a popular library for creating games in Python. It includes a wide range of features such as sprite handling, sound and music playback, and input handling, which can be useful for creating a fantasy adventure game.
  2. Arcade: Arcade is a library for creating 2D games in Python. It includes features such as sprite rendering, physics simulation, and collision detection, which can be useful for creating a game with engaging gameplay mechanics.
  3. Pyglet: Pyglet is a library for creating games and other interactive applications in Python. It includes features such as OpenGL-based rendering, audio playback, and support for multiple windows, which can be useful for creating a game with rich graphics and sound.
  4. PyOpenGL: PyOpenGL is a library that provides Python bindings to the OpenGL graphics API. It can be used to create games and other interactive applications that require advanced graphics capabilities, such as 3D rendering.

Ultimately, the best Python library for your game will depend on your specific needs and the features that you want to include in your game. By considering the type of game you want to create and the features you want to include, you can choose the library that best fits your needs. 

"I've heard some people talk about libtcod, is that a good option as well?"

libtcod (short for "The Doryen Library") is a popular library for creating rogue-like games in Python. It includes features such as ASCII and tile-based graphics, pathfinding, and perlin noise generation, which can be useful for creating a fantasy adventure game with a retro aesthetic.

One of the benefits of using libtcod is that it provides a wide range of pre-built features that can save you time and effort when developing your game. It also has a large and active community of developers who can provide support and resources.

That being said, libtcod may not be the best choice for all types of games. It is primarily designed for creating ASCII and tile-based games, and may not be as well-suited for games that require more advanced graphics or gameplay mechanics.

Ultimately, whether or not libtcod is a good choice for your game will depend on your specific needs and the type of game you want to create. If you want to create a retro-style rogue-like game with ASCII or tile-based graphics, libtcod may be a good choice. However, if you want to create a game with more advanced graphics or gameplay mechanics, you may want to consider one of the other libraries mentioned earlier.


"I see. I think I want to iterate fast on my design, so the ability to make it using ASCII art would make it easier to me. So how can I get started?"

If you want to get started with libtcod, you can follow these steps:

  1. Install libtcod: To use libtcod, you will need to install it on your computer. You can do this by following the instructions on the libtcod website (https://python-tcod.readthedocs.io/en/latest/installation.html).
  2. Create a basic game loop: A game loop is the core of your game, responsible for updating the game state and rendering the game to the screen. You can create a basic game loop using libtcod by following the steps in the libtcod tutorial (https://python-tcod.readthedocs.io/en/latest/tutorial.html).
  3. Implement gameplay mechanics: Once you have a basic game loop set up, you can start adding gameplay mechanics to your game. This could include character movement, combat, and inventory management, among other things. You can find more information on implementing gameplay mechanics in libtcod in the libtcod documentation (https://python-tcod.readthedocs.io/en/latest/).
  4. Generate levels: In a rogue-like game, the levels are typically procedurally generated. You can use libtcod's perlin noise generation and other features to create randomly generated levels for your game.
  5. Add artwork and sound: To make your game more immersive, you may want to include ASCII art and sound effects. You can create these yourself or find resources online.

By following these steps and consulting the libtcod documentation and tutorial, you can create a basic rogue-like game using libtcod. As you develop your game, you can add more features and gameplay mechanics to make it more engaging and unique.


"Some links don't seem to work for me. Can you show me how could I render a console screen?"

Sure! Here is some example code that demonstrates how to render a console screen using libtcod:

import tcod
# Initialize the console with the desired dimensions
console = tcod.console.Console(width, height)
# Clear the console
console.clear()
# Set the background color of the console
console.bg[0:width, 0:height] = tcod.Color(0, 0, 0)
# Set the foreground color of the console
console.fg[0:width, 0:height] = tcod.Color(255, 255, 255)
# Draw a character on the console
console.draw_char(x, y, character, fg=tcod.Color(255, 255, 255), bg=tcod.Color(0, 0, 0))
# Blit the console to the root console (i.e., the main screen)
tcod.console_blit(console, 0, 0, width, height, 0, 0, 0)
# Update the screen
tcod.console_flush()

This code initializes a console with the desired dimensions, clears it, and sets the background and foreground colors. It then draws a character on the console using the draw_char function, and finally blits the console to the root console (i.e., the main screen) using the console_blit function.

You can customize the appearance of the console by modifying the background and foreground colors, as well as the character and its position on the screen. You can also draw other types of graphics, such as lines and circles, using the various drawing functions provided by libtcod.

I hope this helps! Let me know if you have any other questions.


"What is the recommended size for the console? I noticed you didn't specify any"

The recommended size for the console depends on the type of game you are creating and the platform you are targeting. In general, larger console sizes will allow you to display more information and provide a more immersive experience for the player, but may also require more processing power and may not be suitable for smaller screens or devices.

Here are a few general guidelines for selecting a console size:

  • For a traditional ASCII-based rogue-like game, a console size of 80x50 or 80x25 is common. This allows you to display a grid of characters on the screen, as well as text and other information.
  • For a tile-based rogue-like game, you may want to use a larger console size, such as 128x128 or 256x256. This will allow you to display a larger grid of tiles, which can be useful for creating more detailed environments and characters.
  • For a console game, you may want to use a console size that is similar to the resolution of the target platform. For example, the PlayStation 4 and Xbox One both have a resolution of 1920x1080, so you may want to use a console size that is close to this.

Ultimately, the best console size for your game will depend on the specific needs of your game and the platform you are targeting. By considering the type of game you are creating and the capabilities of the target platform, you can choose a console size that is appropriate for your needs.


"Awesome! I'll continue making a traditional ASCII roguelike with an 80x50 console. So how can I use a custom font? I have one prepared, but I don't know how I'd use it."

To use a custom font in your libtcod game, you can use the tcod.console_set_custom_font function. Here is an example of how to use this function to load a custom font from a file:

import tcod
# Load the font from a file
tcod.console_set_custom_font('myfont.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)
# Initialize the root console
tcod.console_init_root(80, 50, 'My Game', False)

In this example, the tcod.console_set_custom_font function is called with the file name of the font and a set of flags indicating the type and layout of the font. The tcod.FONT_TYPE_GREYSCALE flag indicates that the font is a greyscale image, while the tcod.FONT_LAYOUT_TCOD flag indicates that the font uses the layout used by the libtcod library.

You can then initialize the root console using the tcod.console_init_root function, specifying the dimensions of the console and the title of the window.

Keep in mind that the custom font must be in a format that libtcod can read, such as a PNG file with a greyscale image. You can find more information on custom fonts in the libtcod documentation (https://python-tcod.readthedocs.io/en/latest/console.html#custom-fonts).

I hope this helps! Let me know if you have any other questions.


"I noticed that when I launch the game, I get an error saying console doesn't have a method called "draw_char". Why is this happening?"

The console.draw_char method is used to draw a character on a console in libtcod. If you are getting an error saying that the console object doesn't have this method, it may be because you are using an older version of libtcod that doesn't include this method.

In libtcod 1.5 and earlier, the console.put_char method was used to draw a character on a console. If you are using an older version of libtcod, you can use the console.put_char method instead of console.draw_char.

Here is an example of how to use the console.put_char method to draw a character on a console:

import tcod
# Initialize the console with the desired dimensions
console = tcod.console.Console(width, height)
# Clear the console
console.clear()
# Set the background color of the console
console.bg[0:width, 0:height] = tcod.Color(0, 0, 0)
# Set the foreground color of the console
console.fg[0:width, 0:height] = tcod.Color(255, 255, 255)
"Oh, I see. After going through some revisions, my game renders a character to the screen using put_char, but as soon as it appears, it also shuts down. How can I ensure that the game keeps running?"

To ensure that your game keeps running, you will need to create a game loop that continuously updates the game state and renders the game to the screen.

Here is an example of a basic game loop using libtcod:

import tcod
while not tcod.console_is_window_closed():
    # Update the game state
    # Render the game to the screen
    tcod.console_flush()

This game loop will run continuously until the player closes the window, at which point the tcod.console_is_window_closed function will return True and the loop will exit.

Inside the loop, you can update the game state by processing player input, moving characters and objects, and handling other gameplay mechanics. You can then render the game to the screen by drawing the appropriate characters and graphics to the console and calling the tcod.console_flush function to update the screen.

By creating a game loop and continuously updating the game state and rendering the game to the screen, you can ensure that your game keeps running until the player closes the window.

I hope this helps! Let me know if you have any other questions.


"That's it! But I can't move around... How can I add some player input?

To add player input to your game, you can use the tcod.console_check_for_keypress function to check for keyboard input. Here is an example of how to use this function to move a character around the screen:

import tcod
while not tcod.console_is_window_closed():
    # Check for keyboard input
    key = tcod.console_check_for_keypress()
    # Move the character based on the input
    if key.vk == tcod.KEY_UP:
        y -= 1
    elif key.vk == tcod.KEY_DOWN:
        y += 1
    elif key.vk == tcod.KEY_LEFT:
        x -= 1
    elif key.vk == tcod.KEY_RIGHT:
        x += 1
    # Update the game state
    # Render the game to the screen
    tcod.console_flush()

In this example, the tcod.console_check_for_keypress function is called to check for keyboard input. If a key is pressed, the key variable is set to a tcod.Key object containing information about the key that was pressed.

The key.vk attribute of the tcod.Key object indicates the virtual key code of the pressed key. You can use this attribute to determine which key was pressed and take the appropriate action. In this case, the code checks for the arrow keys and moves the


"Hmm, it seems like there're some problems with that code. The controls are mirrored, so when I want to go left, it goes right. How can I fix it?"

I apologize for the mistake in the example code. The controls are indeed mirrored, so when you want to go left, the character goes right, and vice versa.

To fix this problem, you can reverse the direction of the character movement when the left and right arrow keys are pressed. Here is the corrected code:

import tcod
while not tcod.console_is_window_closed():
    # Check for keyboard input
    key = tcod.console_check_for_keypress()
    # Move the character based on the input
    if key.vk == tcod.KEY_UP:
        y -= 1
    elif key.vk == tcod.KEY_DOWN:
        y += 1
    elif key.vk == tcod.KEY_LEFT:
        x += 1
    elif key.vk == tcod.KEY_RIGHT:
        x -= 1
    # Update the game state
    # Render the game to the screen
    tcod.console_flush()

In this code, the direction of the character movement when the left and right arrow keys are pressed has been reversed, so the character will move in the expected direction.

I apologize for any confusion caused by the mistake in the previous example. I hope this corrected code helps you implement player input in your game. Let me know if you have any other questions. 


"Hmm, it seems like it should work but it doesn't actually block the player, and after some time after passing the boundary, if you change directions, it updates the character to the edge of the console. Why's that?"

There could be several reasons why the boundary checks are not working as expected. Here are a few possibilities to consider:

  • The x and y variables are not being updated correctly: Make sure that the x and y variables are being updated correctly based on the player input. You can add some debug statements to your code to check the values of these variables and see if they are being updated correctly.
  • The width and height variables are incorrect: Make sure that the width and height variables are set to the correct dimensions of the console. If these variables are not set correctly, the boundary checks will not work as expected.
  • The console_check_for_keypress function is being called too frequently: The console_check_for_keypress function may be called multiple times per frame, which could cause the character to move outside the boundaries of the console. You can try adding a delay to the game loop to reduce the number of times the function is called per frame.

By considering these possibilities and checking the values of the relevant variables, you should be able to identify the cause of the problem and fix it.

I hope this helps! Let me know if you have any other questions.


"Well, I tweaked some stuff with the variables and it seems to block the movement before going out of the screen. Although there're some graphical bugs still, I'd like to know how to make it so that the player moves continously if I hold down the movement keys. Can you show me some code?"

To make the player move continuously while holding down the movement keys, you can use the tcod.Key.pressed attribute of the tcod.Key object returned by the console_check_for_keypress function. This attribute is a boolean value that is True if the key is being held down, and False if it is not.

Here is an example of how to use the tcod.Key.pressed attribute to make the player move continuously while holding down the movement keys: 

import tcod
while not tcod.console_is_window_closed():
    # Check for keyboard input
    key = tcod.console_check_for_keypress()
    # Move the character based on the input
    if key.vk == tcod.KEY_UP and key.pressed:
        y = max(0, y - 1)
    elif key.vk == tcod.KEY_DOWN and key.pressed:
        y = min(height - 1, y + 1)
    elif key.vk == tcod.KEY_LEFT and key.pressed:
        x = max(0, x - 1)
    elif key.vk == tcod.KEY_RIGHT and key.pressed:
        x = min(width - 1, x + 1)
    # Update the game state
    # Render the game to the screen
    tcod.console_flush()
In this code, the key.pressed attribute is used to determine whether the key is being held down. If the key... [stopped for some reason]


"Now I can't move at all. Are you sure it's the correct way to do it?"

apologize for the mistake in the previous code example. The key.pressed attribute does not work as expected in libtcod and will not allow the player to move at all.

To make the player move continuously while holding down the movement keys, you can use the tcod.console_wait_for_keypress function instead of the tcod.console_check_for_keypress function. The console_wait_for_keypress function waits for a key press and release, and returns a tcod.Key object when a key is released.

Here is an example of how to use the tcod.console_wait_for_keypress function to make the player move continuously while holding down the movement keys:

import tcod

while not tcod.console_is_window_closed():
    # Wait for key press and release
    key = tcod.console_wait_for_keypress(True)
    # Move the character based on the input
    if key.vk == tcod.KEY_UP:
        y = max(0, y - 1)
    elif key.vk == tcod.KEY_DOWN:
        y = min(height - 1, y + 1)
    elif key.vk == tcod.KEY_LEFT:
        x = max(0, x - 1)
    elif key.vk == tcod.KEY_RIGHT:
        x = min(width - 1, x + 1)
    # Update the game state
    # Render the game to the screen
    t

And with that I'll end it, GPT seems to be missing stuff at the end by now so I think I'll let it rest for now. The player does indeed move continously. Although I have a pretty serious graphical error, but that's enough for now. You can view the code I got at the end of the conversation here. If you run the code, there's a pretty big graphical error I don't know why. Tell me about it if you can!

Support this post

Did you like this post? Tell us

Leave a comment

Log in with your itch.io account to leave a comment.