Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Replace the hand-copied character slot number with a real character handle

Open
#374 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
12/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Active
Tech stack
cpp
Domain
backend

Research direction

Start with char_control_array, register_npc_char, extract_char and free_char in src/handler.cpp, then target_data and its ch_num field in structs.h. Read how set_character() from #369 is used before adding a handle type with a non-reused identity. Done means target_data and the follower, memory, mount and reply links use the handle, and freeing a character clears a slot only for its owner. The issue asks for design decisions first, so check with the maintainer before coding.

Written by the indexing model from the issue text.

Description

Why engineers need this

The game decides whether a character it remembered is still around by a slot number that every caller copies by hand. The design has let two bugs sit unnoticed for years, and it will produce more.

How it works today:

  • char_control_array (src/handler.cpp) holds one bit per slot, 0 to 63999. register_npc_char / register_pc_char give a character a slot (abs_number); extract_char / free_char clear it.
  • Code that keeps a character for later stores the pointer and the slot number side by side (target_data::ptr.ch and target_data::ch_num, fol_number, enemy_number, mount_number, ...), and calls char_exists(number) before using the pointer.

What is wrong with it:

  1. "Not set" was the same value as a real slot. A forgotten number was 0, and slot 0 is the first mob loaded at boot. #369 changes "no slot" to -1; that makes a forgotten number harmless to others but does not stop it being forgotten.
  2. Pointer and slot are separate fields that must be set together, and nothing enforces it. damage(), hit(), damage_stat() and do_mental() never set the slot, so every hit in the game asked "does slot 0 exist?" instead of "does this victim exist?". #369 adds target_data::set_character() and uses it where the slot was missing; the other ~25 places that build a character target still set the two fields by hand.
  3. ch_num is shared with unrelated data. Depending on the target type it carries a direction, a spell number, a coin amount or a door sentinel, so nothing can tell a forgotten slot from a legitimate value.
  4. Slots are reused. The allocator wraps at 64000, so a number remembered long enough can point at a different character that now has that slot. The check then passes for the wrong character. (Not seen in practice; it follows from the allocator in register_npc_char.)
  5. Cleanup trusted the number. stat file and set file build a character that never gets a slot; freeing it cleared slot 0. On builds before #369 that switches off every mob's damage program, and so every shopkeeper's protection, until reboot.
What is wanted

One character handle that cannot be half-filled or point at the wrong character:

  • a single type holding the pointer and an identity that is never reused within a boot (a counter, or slot + generation);
  • one way to make it from a character, one way to ask "is it still alive, and still the same character";
  • used by target_data (in its own field, not shared with directions and amounts) and by the follower, memory, mount and reply links;
  • free_char / extract_char clearing a slot only for the character that owns it.
Scope and risk

Game-wide: structs.h, the command parser (interpre.cpp), handler.cpp, mobact.cpp, spec_pro.cpp, script.cpp, ranger.cpp, mudlle (SPECIAL_LIST_REFS). It can be done in steps: the handle type and its use in target_data first, the other links after. None of these structs are written to disk.

Raised while answering the review of #369, which carries the two small fixes (-1 for "no slot", set_character()).

Dominant language
C++
Stars
3
Forks
4
Avg merge
18h 36m
Merged PRs (30d)
87

Getting set up

  • Ships a Dockerfile or Docker Compose file
  • No pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from returnoftheshadow/RotS_Live

All issues in returnoftheshadow/RotS_Live

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.