11

http://wiki.ultimacodex.com/wiki/Quirks_of_the_Ultima_VII_Engine vaguely talks about this room being "necessary" to place seemingly "dead" NPCs and it was result of some challenge that programmers had to solve.

I can imagine dozens of simple solutions including a simple one bit "dead" flag that would just prevent NPC from being drawn and interacted.

Considering extensive recollections on everything Ultima, was it ever documented what problem this approach solves and how it is any better than simpler solutions?

  • 2
    What do you think is simpler and more effective? Carrying around another 1-bit flag so an NPC could be dead in any room or just say room==0 means "dead NPC" – Janka Dec 28 '18 at 21:03
  • 1
    @Janka, at very least it would be two bytes for X,Y - because as seen on screens, it is real quite extensive room on single map plane with "dead" standing on different tiles. Additionally, considering all the extra stuff U7 already keeps for every NPC and objects that are almost unlimited, I don't think a single bit per each NPC whose numbers are static, are relevant. Every NPC even have EXTRA object created to act as corpse on death. That takes far, far more than "dead" flag. – Oleg V. Volkov Dec 28 '18 at 21:09
  • 2
    Just guessing, but you'd need all those fields (X, Y, room number) anyway, so giving them special values is simpler than reserving an additional bit for a flag etc. "Marker values" were used in older programming with static record layouts and little memory much more often than today. – dirkt Dec 28 '18 at 21:31
  • @OlegV.Volkov NPCs aren't objects. They're implemented as characters, which means that they have separate code attached. The game assumes that they're never destroyed, and was probably programmed without initially taking death into account... I'd like a real answer to this, though. – wizzwizz4 Dec 28 '18 at 21:34
  • 2
    Wouldn't that question be more appropriate on a gaming site? Like Gaming.SE ? – Raffzahn Dec 28 '18 at 21:59
2

Reading the article on that wiki, it says that the NPCs could not be removed because the game could break.

This makes me think that when checking the sequence of events, the game engine also checks if there has already been an encounter with a specific NPC, and the status is saved on a property of the NPC itself.

This is speculation of course, but I think it's likely this way, because it's faster to check on a specific NPC a flag saying "already_encountered" rather than going through a list of encountered NPCs and checking for that single one.

Why does this matter? Because if the NPC was actually removed from the game, the engine would not be able to check the encounter status after said NPC died. So, one solution is to not remove them. But of course they have to not be encounterable (is it a word?) again.

Npw, suppose that you put a "is_alive" flag to false, to say that the NPC is dead. That would mean going through the NPC list in the room, checking if it's dead, display a different sprite in that case and handle the inventory.

But if you just move it to a different room and replace it with an object, it's a lot easier. You organize the NPCs by room, meaning that you access the room index, and inside that there is a list of NPCs and objects. You just go through the list and you don't need to handle any exception. You interact with NPCs that are there, you don't see the ones that have been moved, and you can get stuff from any container, including a dead body.

  • In this game, there isn't a "room index"; the whole game is one big map. – wizzwizz4 Jan 2 at 15:00
  • @wizzwizz4 That's interesting. How are rooms organized then? Is there a huge bunch of generic objects, like a list that the engine goes through to determine what to display and what not? Do you have any insight as to how the enter/exit room was implemented, not having rooms indexed? – ChatterOne Jan 2 at 15:21
  • I've absolutely no clue! :-) – wizzwizz4 Jan 2 at 15:23
2

This is a common technique to make memory management easier.

One major challenge with games of this nature is running out of memory after a long time. This can happen if there is no enough memory available, or if memory becomes fragmented to the point where a single large enough block is not available.

The simplest solution to this problem is to avoid doing things that allocate or free memory. Then it becomes possible to calculate the maximum amount of memory required no matter how long the game runs or what the player does. It also means you don't need any memory management code because everything is assigned by the compiler and never changed.

The game engine therefore sets up all NPCs at the start of the game, and rather than removing their corpses simply moves them to a special area.

The other issue is the behaviour of corpses. They can be looted and generally act more like objects than the more permanent NPCs, which have AI and other properties. Replacing dead NPCs with a corpse object makes managing and resurrecting them easier to implement.

  • 1
    Although I agree that a "dead room" is a common technique, this doesn't address the most obvious alternative (mentioned in the question) of having an "isDead" flag or similar. Using such a flag would also allow all NPCs to be created at the start of the game and avoid the memory issues you mention. – TripeHound Jan 2 at 14:07
  • That's a good question. It's because the corpses can be acted on by the player in ways that NPCs cannot, such as looting them. Teleporting the NPC away allows them to be resurrected with minimal hassle, and makes the corpse act like a transient object rather than the more permanent NPCs. – user Jan 2 at 15:37
1

If the game has a fixed number of NPCs that never really changes, other than states like "isAlive", then it's easier and higher-performance to implement it as a static array rather than a dynamic data structure requiring support for operations like "add", "delete", "new", "findByName", etc.

So if there is a static array of NPCs, the code that draws the screen may simply be going through the entire static list and drawing characters that match the current room number. So by setting the character's room number to 0, the engine will skip drawing it always.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.