41380


In episode 1 of New Game 2, around 9:40, there is a shot of the code that Nene
has written:

[![enter image description
here](https://i.stack.imgur.com/JRFI2.png)](https://i.stack.imgur.com/JRFI2.png)

Here is it in text form with the comments translated:

[code]

    // the calculation of damage when attacked
    void DestructibleActor::ReceiveDamage(float sourceDamage) 
    {
        // apply debuffs
        auto resolvedDamage = sourceDamage;
        for (const auto& debuf:m_debufs)
        {
            resolvedDamage = debuf.ApplyToDamage(resolvedDamage);
            m_currentHealth -= resolvedDamage
            if (m_currentHealth <= 0.f)
            {
                m_currentHealth = 0.f;
                DestroyMe();
            }
        }
    }
    
[/code]

After the shot, Umiko, pointing at the for loop, said that the reason why the
code crashed is that there is an infinite loop.

I don't really know C++ so I'm not sure whether what she is saying is true.

From what I can see, the for loop is just iterating through the debufs that
the Actor currently has. Unless the Actor has an infinite amount of debufs, I
don't think it can possibly become an infinite loop.

But I'm not sure because the only reason that there is a shot of the code is
that they wanted to put an easter egg here, right? We would have just gotten a
shot of the back of the laptop and heard Umiko saying "Oh you've got an
infinite loop there". The fact that they actually showed some code makes me
think that somehow the code is an easter egg of some sort.

Will the code actually create an infinite loop?


CC BY-SA 3.0
2017-07-14T10:44:03.757
41372
2023-04-30T15:17:33.697
33156
question
new-game
Is code in episode 1 of New Game 2 actually an infinite loop?


The code does not seem to create an infinite loop.

The only way the loop would be infinite would be if

[code]

    debuf.ApplyToDamage(resolvedDamage);
    
[/code]

or

[code]

    DestroyMe();
    
[/code]

were to add new items to the `m_debufs` container.

This seems unlikely. And if it were the case, the program could crash because
of changing the container while being iterated.

The program would most likely crash because of the call to `DestroyMe();`
which presumably destroys the current object that is currently running the
loop.

We can think of it as the cartoon where the 'bad guy' saws a branch to have
the 'good guy' fall with it, but realizes too late that he's on the wrong side
of the cut. Or the Midgaard Snake eating it's own tail.

* * *

I should also add that the most common symptom of an infinite loop is that it
freezes the program or makes it not responsive. It will crash the program if
it allocates memory repeatedly, or does something that ends up dividing by
zero, or the likes.

* * *

Based on the comment by [Aki Tanaka
](https://anime.stackexchange.com/users/2516/aki-tanaka),

> Probably helpful: [additional
> screenshot](https://i.stack.imgur.com/I5vHa.jpg) of Umiko saying that "It
> was calling the same operation over and over again", which might not be
> shown in the code.

_" It was calling the same operation over and over again"_ This is more
likely.

Assuming that `DestroyMe();` is not designed to be called more than once, it
is more likely to cause a crash.

A way to fix this issue would be to change the `if` for something like this:

[code]

        if (m_currentHealth <= 0.f)
        {
            m_currentHealth = 0.f;
            DestroyMe();
            break;
        }
    
[/code]

This would exit the loop when the DestructibleActor is destroyed, making sure
that 1) the `DestroyMe` method is called only once and 2) don't apply buffs
uselessly once the object is already considered dead.


CC BY-SA 4.0
2017-07-14T12:01:36.123
41378
2023-04-30T15:17:33.697
2023-04-30T15:17:33.697
19307
41372
answer


The code is not an infinite loop but it is a bug.

There's two (possibly three) issues:

  * If no debufs are present no damage will be applied at all
  * Excessive damage will be applied if there is more than 1 debuf
  * If DestroyMe() immediately deletes the object and there are still m_debufs to be processed the loop will be executing over a deleted object and trashing memory. Most game engines have a destroy queue to work around this and more so that may not be an issue.

The application of damage should be outside the loop.

Here's the corrected function:

[code]

    // the calculation of damage when attacked
    void DestructibleActor::ReceiveDamage(float sourceDamage) 
    {
        // apply debuffs
        auto resolvedDamage = sourceDamage;
        for (const auto& debuf:m_debufs)
        {
            resolvedDamage = debuf.ApplyToDamage(resolvedDamage);
        }
        m_currentHealth -= resolvedDamage
        if (m_currentHealth <= 0.f)
        {
            m_currentHealth = 0.f;
            DestroyMe();
        }
    }
    
[/code]


CC BY-SA 3.0
2017-07-14T12:07:56.093
41380
2017-07-14T12:37:18.997
2017-07-14T12:37:18.997
34613
34613
41372
answer


There are several issues with the code:

  1. If there are no debufs, no damage would be taken.
  2. `DestroyMe()` function name sounds dangerous. Depending on how its implemented, it might or might not be an issue. If it's just a call to the destructor of the current object wrapped in a function, then there is an issue, as the object would be destroyed in the middle of it executing code. If it's a call to a function which queues the deletion event of the current object, then there is no issue, as the object would be destroyed after it completes its execution and the event loop kicks in.
  3. The actual issue that seems to be mentioned in the anime, the "It was calling the same operation over and over again" -- it will call `DestroyMe()` as long as `m_currentHealth <= 0.f` and there are more debuffs left to iterate, which might result in `DestroyMe()` being called multiple times, over and over again. The loop should stop after the first `DestroyMe()` call, because deleting an object more than once results in memory corruption, which will likely result in a crash in the long run.

I'm not really sure why every debuf takes away the health, instead of the
health being taken away only once, with the effects of all debuffs being
applied on the initial damage taken, but I will assume that's the correct game
logic.

The correct code would be

[code]

    // the calculation of damage when attacked
    void DestructibleActor::ReceiveDamage(float sourceDamage) 
    {
        // apply debuffs
        auto resolvedDamage = sourceDamage;
        for (const auto& debuf:m_debufs)
        {
            resolvedDamage = debuf.ApplyToDamage(resolvedDamage);
            m_currentHealth -= resolvedDamage
            if (m_currentHealth <= 0.f)
            {
                m_currentHealth = 0.f;
                DestroyMe();
                break;
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2017-07-14T18:07:42.637
41386
2017-07-14T18:07:42.637
34618
41372
answer