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

Implement the RPG_RT Autobattle algorithm #1586

Closed
fmatthew5876 opened this issue Dec 19, 2018 · 6 comments · Fixed by #2331
Closed

Implement the RPG_RT Autobattle algorithm #1586

fmatthew5876 opened this issue Dec 19, 2018 · 6 comments · Fixed by #2331

Comments

@fmatthew5876
Copy link
Contributor

Figure out and implement the RPG_RT auto battle algorithm.

Using it for the AutoBattle command is a bit controversial. Using it for an actor with AutoBattle flag set however is not. If a game dev created an actor with auto battle, the game experience probably demands that actor does more than just attack random enemies. There can also be some smarts from RPG_RT we can reuse event if we don't want to change the AutoBattle command to use skills.

I did some testing and one thing I saw. I had an actor with no skills set on autobattle. He would always attack the first enemy. This is better AI than attacking randomly, as at least he works on killing 1 at a time instead of randomly spreading the damage.

Also I noticed he would attack a different enemy only if his weapon would kill that enemy in a single hit. Adjusting the enemy HP would change which target he chose.

That's all I've got for now.

@fdelapena fdelapena added this to the 0.6.x milestone Mar 1, 2019
@fmatthew5876
Copy link
Contributor Author

@CherryDT

Any help with this one?

@CherryDT
Copy link

CherryDT commented Mar 4, 2019

Hero AI:

  • If angry, attack random monster (regardless of whether the character would have the "attack all" modifier normally).
  • Else if confused, attack random party member (regardless of whether the character would have the "attack all" modifier normally).
  • Else:
    • Assign scores: (see details below)
      • Possible actions are basic attack and all skills that the character can use. For each action, scores are assigned for all possible targets (which can be enemies or allies, depending on the action), let's call these "secondary scores".
      • Then, primary scores are assigned to the action itself, based on the secondary scores of all possible targets for each action.
    • Find best option based on primary score
    • If best option is basic attack: If character has the "attack all" modifier, attack all. Otherwise, attack enemy with highest secondary score for the basic attack action.
    • Otherwise: If the skill has target "all enemies" or "all allies", target all enemies/allies. Otherwise, target the enemy/ally with the highest secondary score for this skill.

How secondary scores are assigned:

  • Attack:
    • Score = Ratio (i.e. 0 to 1 - never >1!) of HP the attack would deduct from the target, compared to current HP
    • If score is now 1, make it 1.5 (this prioritizes killing strikes)
    • If the target is the first alive one in the enemy group (based on array index), multiply the score by 1.5 and add an additional 0.5 at the end (this will make the character seem to attack the enemies more or less in order, unless there is a much better option)
    • Multiply the score by 1.5 (this prefers basic attacks of skills)
    • If score is nonzero, add a random value between 0 and 1 (this adds variance)
  • Skills:
    • If the score targets one or all allies, or "self":
      • If the target is dead and the skill is capable of reviving, the score is Skill.power / 1000 + 1
      • Else if the skill affects HP, score = Ratio (i.e. 0 to 1 - never >1!) of HP the skill would heal for the target, compared to (Max HP - current HP), minus half the MP modifier (see below)
      • Otherwise, the score is zero.
    • Else if the score targets one or all enemies:
      • If the skill affects HP (same logic as for basic attack, except for the x1.5 multiplication at the end, and with MP modifier instead):
        • Score = Ratio (i.e. 0 to 1 - never >1!) of HP the attack would deduct from the target
        • If score is now 1, make it 1.5 (this prioritizes killing strikes)
        • Full MP modifier is subtracted from score (see below)
        • If the target is the first alive one in the enemy group (based on array index), multiply the score by 1.5 and add an additional 0.5 at the end (this will make the character seem to attack the enemies more or less in order, unless there is a much better option)
      • Otherwise, the score is zero.

Only valid targets are considered.

MP modifier:

Above, there is an "MP modifier" mentioned. The MP modifier is the value of 0.25 * (MP Cost / Max MP). The case of 0/0 is handled as 0.

Subtracting the MP modifier can never make the score become negative, it will become zero in that case.

How primary scores are assigned:

  • Attack:
    • Primary score is the maximum of all secondary scores. (Possible oversight: If the hero has the "attacks all" modifier, it does not add the scores of all targets together!)
  • Skills:
    • If the skill targets one enemy or one ally, primary score is the maximum of all secondary scores.
    • If the skill targets "self", the primary score is the secondary score of "self".
    • If the skill targets all enemies or all allies, primary score is the sum of all secondary scores.
    • If primary score is nonzero, add a random value between 0 and 1 (this adds variance - note that unlike for the attack scores where it's done for the secondary scores, the variance is added to the primary score for skills!)

Auto-battle from the battle menu just works as if all characters had the auto-battle option set.

Monster AI

  • If angry or concentrated, attack random hero.
  • Else if confused, attack random monster.
  • Else:
    • Out of all actions defined for this monster, get those whose conditions are met and (in case of skills) whose MP cost are payable and mental/physical attributes are met based on possible inflicted conditions.
    • Out of those, remove all whose priority is less than the highest priority minus 10.
    • Normalize the priority values to have 10 as highest priority, by subtracting the highest priority minus 10 from each action's priority.
    • Remove those actions which have no targets on which they would be valid*.
    • Choose an action randomly using the (normalized) priority values as weight
    • Choose a target randomly out of those on which the action would be valid*.

*: An action is invalid on a target if the target is dead (unless it's a skill that can revive), if it's a reviving skill and the target is alive, if it's a skill that would heal a status and the target doesn't have this status, or if it's a skill that would increase elemental resistance and the target's resistance for that element is already increased. If a skill has multiple effects, it is invalid if all of them fall into one of the invalidness definitions above. (For example, a skill that heals a status and heals HP would always be valid, even if the status is not inflicted. The HP heal is unconditionally valid regardless of actual HP, since it's not in the list of invalid things above.)

@Ghabry
Copy link
Member

Ghabry commented Mar 5, 2019

So this means the AI is not cheating?

@CherryDT
Copy link

CherryDT commented Mar 5, 2019

No, it is, because this...

Score = Ratio (i.e. 0 to 1 - never >1!) of HP the attack would deduct from the target, compared to current HP

...uses information (an enemy's current HP) which would normally not be available to the player (at least not easily, only if the player knows the enemy's max HP and kept track of the damage dealt).

@fmatthew5876
Copy link
Contributor Author

When determining how much the effect of the attack would be.. Am I right to assume the autobattle algo ignores random variance?

@CherryDT
Copy link

CherryDT commented Mar 8, 2019

Basic attacks don't have variance as far as I know, and for skills, the variance is part of the effect calculation.

So, that means that the "prediction" from the AI will become more inaccurate the higher the skill's variance is, because the result of the effect calculation during AI decision-marking and the one during actual execution of the action can be wildly different... (Which is good, otherwise it would be even more cheating. However, I agree that it would sort of make sense to then not apply the variance at all during decision-making.)

@Ghabry Ghabry modified the milestones: 0.6.1, 0.6.2 May 5, 2019
@Ghabry Ghabry modified the milestones: 0.6.2, 0.6.3 Apr 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants