Skip to content

Updated 2019 tutorial for using tcod 21.2.0, numpy 2.x and modern python#42

Open
Darky-Lucera wants to merge 1 commit into
TStand90:masterfrom
Darky-Lucera:updated_2019
Open

Updated 2019 tutorial for using tcod 21.2.0, numpy 2.x and modern python#42
Darky-Lucera wants to merge 1 commit into
TStand90:masterfrom
Darky-Lucera:updated_2019

Conversation

@Darky-Lucera

@Darky-Lucera Darky-Lucera commented Apr 23, 2026

Copy link
Copy Markdown

Summary

This PR updates the 2019 tutorial to work with tcod 21.2.0 and NumPy 2.x, bringing them in line with the current library API.

The changes are intentionally minimal and surgical: only API-level replacements, no rewriting of game logic or tutorial structure.


Changes

The 2019 series used the legacy libtcod API throughout. Every call has been replaced with its modern equivalent:

Old API New API
import tcod as libtcod import tcod
libtcod.console_set_custom_font(...) tcod.tileset.load_tilesheet(...)
libtcod.console_init_root(...) with tcod.context.new(...) as context:
libtcod.console_new(w, h) tcod.console.Console(w, h, order='F')
libtcod.console_flush() context.present(root_console)
while not libtcod.console_is_window_closed() while True: (context manager handles cleanup)
libtcod.sys_check_for_event(...) / console_check_for_keypress() for event in tcod.event.wait():
key.vk == libtcod.KEY_UP event.sym == tcod.event.KeySym.UP
key.lalt event.mod & tcod.event.Modifier.LALT
libtcod.map_new() / map_set_properties() / map_compute_fov() numpy array + tcod.map.compute_fov() with .T transpose
libtcod.map_is_in_fov(fov_map, x, y) fov_map[x, y] (array indexing)
libtcod.console_set_default_foreground + console_put_char con.print(x, y, char, fg=color)
libtcod.console_print_ex(...) console.print(x, y, text)
libtcod.console_get_height_rect(...) con.get_height_rect(...)
libtcod.console_print_rect_ex(...) window.print_box(...)
libtcod.console_blit(win, 0, 0, w, h, 0, x, y, 1.0, 0.7) window.blit(dest=root_console, dest_x=x, dest_y=y, fg_alpha=1.0, bg_alpha=0.7)
libtcod.Color(r, g, b) / named color constants RGB tuples (r, g, b)
libtcod.set_fullscreen(...) context.sdl_window.fullscreen = not context.sdl_window.fullscreen

The main_menu background image (libtcod.image_load / libtcod.image_blit_2x) has no equivalent in the modern API and was removed; the title text is now printed directly to the root console. The surrounding narrative was updated accordingly.

root_console was threaded through the call chain (menu, inventory_menu, level_up_menu, message_box, character_screen, render_all, play_game, main) as required by the new blit API.

Python minimum version updated to 3.8 (part-0).


Why these tutorials are still worth maintaining

I'd like to make a case for keeping both series alive and up to date.

These are still among the best beginner roguelike tutorials available. The structure — 14 parts, building a complete dungeon crawler from scratch, covering everything from a moving @ to saving/loading, inventory, spells, equipment and procedural generation — is genuinely hard to find elsewhere at this level of quality and completeness. The RogueBasin lineage gives them credibility, and the Python + tcod combination is still the most accessible entry point for someone who wants to write a roguelike without wrestling with C++ or a full game engine.

The 2019 series and v2 serve different audiences, and both have real value:

The 2019 series is the better tutorial for a complete beginner. Part 1 is 40 lines and you have a moving @ on screen. The patterns it teaches — handle_keys returning dicts, GameStates enum, step-by-step render functions — are "visible" complexity: the code looks like what it does. The fact that those patterns don't scale well is actually pedagogically useful: you experience the pain of an ever-growing if/elif in engine.py and discover why you'd want to refactor. That motivated discovery is worth more than copying a clean Action + EventHandler pattern without knowing what problem it solves.

The v2 series is the better tutorial if you already have some OOP experience and want to end up with a codebase you can actually extend. The Action-based input, interchangeable EventHandlers as a state machine, NumPy for the map and FOV, and pickle+lzma serialization of the whole Engine are all genuinely good architectural decisions that hold up as the codebase grows. The type hints and from __future__ import annotations also teach habits that matter in real Python projects.

In short: the 2019 series teaches you how to build a roguelike; the v2 teaches you how to build one well. Both are useful. Keeping them up to date means both remain usable entry points rather than historical artifacts that confuse beginners with deprecated API calls and AttributeError: module 'numpy' has no attribute 'bool'.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants