Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the infinite loop of trying to spawn a blacklisted monster #76966

Merged
merged 5 commits into from
Oct 28, 2024

Conversation

cknight828
Copy link
Contributor

@cknight828 cknight828 commented Oct 11, 2024

Summary

None

Purpose of change

Fix #75212

When trying to spawn monsters from a monster group, the quantity of monster to be spawn is not decreased when a sub group of top level monster group is selected, because it should be decreased in the sub group. But if some monsters are blacklisted and they are selected in the sub group, they are replaced with the default monster of the top level group but the quantity is not decreased.
For this, extra monsters may be spawn but it normally does not cause serious problems, because the valid monster in the sub group or the individual monster entry of the top level group is selected eventually in the loop. But at the worst case, the top level group contains only monster groups and all monsters in the group are blacklisted (like GROUP_VANILLA with Only Wildlife), the game will freeze.

Describe the solution

The quantity of monster is decreased when a sub group is selected but a blacklisted monster is seleceted in it.

Describe alternatives you've considered

Testing

Start game with Only Wildlife mod and reach FEMA camp.

Additional context

@github-actions github-actions bot added [C++] Changes (can be) made in C++. Previously named `Code` <Bugfix> This is a fix for a bug (or closes open issue) astyled astyled PR, label is assigned by github actions json-styled JSON lint passed, label assigned by github actions BasicBuildPassed This PR builds correctly, label assigned by github actions labels Oct 11, 2024
Copy link
Member

@RenechCDDA RenechCDDA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually changes spawn behavior quite significantly, take the following example:

GROUP, PICK ONE
---FULLY_BLACKLISTED_GROUP, weight 1
---NOT_BLACKLISTED_MONSTER, weight 1

Current behavior will be that the not blacklisted monster will always spawn, because the blacklisted group is excluded as a valid choice.

With your change, it's a 50% chance to spawn nothing at all.

A better approach would be loop detection, even a hacky solution of counting the number of times it's loop as some very high number (e.g. 100,000+) and then breaking if we hit that count.

@cknight828
Copy link
Contributor Author

cknight828 commented Oct 12, 2024

GROUP, PICK ONE
---FULLY_BLACKLISTED_GROUP, weight 1
---NOT_BLACKLISTED_MONSTER, weight 1

Current behavior will be that the not blacklisted monster will always spawn, because the blacklisted group is excluded as a valid choice.

No. The blacklisted group is not excluded in MonsterGroupManager::FinalizeMonsterGroups and still exists when spawning.
If FULLY_BLACKLISTED_GROUP is selected, an empty vector is returned from recursive call of GetResultFromGroup and the default monster of GROUP is added to result. Currently, the quantity of monster is not decreased in this case, so the default monster continues to be spawned until NOT_BLACKLISTED_MONSTER is spawned.

Is this behavior intended?

With your change, it's a 50% chance to spawn nothing at all.

Either of NOT_BLACKLISTED_MONSTER or default monster of GROUP is spawned.
I think it works well in local test.

@cknight828
Copy link
Contributor Author

cknight828 commented Oct 12, 2024

This PR fixes multi spawning monsters like place_monsters of mapgen.
Spawning once, like place_monster, works well currently because it doesn't check quantity.

@cknight828 cknight828 requested a review from RenechCDDA October 12, 2024 17:20
@RenechCDDA
Copy link
Member

No. The blacklisted group is not excluded in MonsterGroupManager::FinalizeMonsterGroups and still exists when spawning. If FULLY_BLACKLISTED_GROUP is selected, an empty vector is returned from recursive call of GetResultFromGroup and the default monster of GROUP is added to result. Currently, the quantity of monster is not decreased in this case, so the default monster continues to be spawned until NOT_BLACKLISTED_MONSTER is spawned.

Is this behavior intended?

It looks like your assessment is completely correct(!?). That is really, REALLY not how I believed it worked and appears to be contrary to how blacklists work with item groups.

I'm going to go ahead and say that behavior is a bug, but also you don't have to deal with it in this PR.

@RenechCDDA
Copy link
Member

I think this is still 'double counting' the quantity? If we find a monster inside the for-loop, quantity is decremented. But then we exit the loop and decrease it again, regardless of whether or not we found a monster. The check should probably be

    if( quantity && !monster_found && is_recursive ) {
        ( *quantity )--;
    }

I would love to verify the behavior, but I have been unable to get place_monsters to spawn any monsters, at all. So I literally cannot test this.

@cknight828
Copy link
Contributor Author

cknight828 commented Oct 14, 2024

I think this is still 'double counting' the quantity? If we find a monster inside the for-loop, quantity is decremented. But then we exit the loop and decrease it again, regardless of whether or not we found a monster. The check should probably be

    if( quantity && !monster_found && is_recursive ) {
        ( *quantity )--;
    }

Quantity is not decremented when spawn_details is empty, so double counting does not occur. But monster_found is not set properly, it should be fixed and the check can depend on it.

I would love to verify the behavior, but I have been unable to get place_monsters to spawn any monsters, at all. So I literally cannot test this.

Spawning is guaranteed when density is set higher than 0.1

@github-actions github-actions bot removed the astyled astyled PR, label is assigned by github actions label Oct 14, 2024
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions github-actions bot added astyled astyled PR, label is assigned by github actions and removed BasicBuildPassed This PR builds correctly, label assigned by github actions labels Oct 14, 2024
@github-actions github-actions bot added the BasicBuildPassed This PR builds correctly, label assigned by github actions label Oct 15, 2024
@cknight828
Copy link
Contributor Author

@RenechCDDA Is there something wrong? I found the same issue in 0.H and want to backport this pr.

@RenechCDDA
Copy link
Member

It's just waiting on merger review right now. I don't personally have merge permissions.

@Night-Pryanik Night-Pryanik merged commit c6e6192 into CleverRaven:master Oct 28, 2024
26 checks passed
@cknight828 cknight828 mentioned this pull request Oct 28, 2024
Maleclypse pushed a commit that referenced this pull request Nov 2, 2024
* Decrement spawn quantity when no monster is selected in sub group

* Set mon_found properly when select monster from subgroup

* Update src/mongroup.cpp

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
astyled astyled PR, label is assigned by github actions BasicBuildPassed This PR builds correctly, label assigned by github actions <Bugfix> This is a fix for a bug (or closes open issue) [C++] Changes (can be) made in C++. Previously named `Code` json-styled JSON lint passed, label assigned by github actions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Game freeze near FEMA camp with Only Wildlife mod
3 participants