Author Topic: Arnheim (WIP)- AI, Persistent Reputation, and Group Membership  (Read 603 times)

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« on: November 24, 2012, 10:36:40 pm »


               First, related threads and resources:
       I've decided to forge ahead with AI changes with regards to group membership, and reputation adjustment, before dealing with the spawning of unique creatures from a database. This thread is for discussion about what I am doing to integrate PRR with the AI, include group membership for NPCs in the AI, and anything AI related to allowing PCs to join or even command groups. Feel free to make use of the scripts I post. Credit is nice, but not expected. Better yet, join in on the discussion to let me know what you think. I am sure many of you can do a better job of this than I can.
    This first post contains the resources, and summarizes my findings. The discussion thread unspools below.

THE PROJECT's FILES:

Script Includes:Creature AI:FINDINGS:
               
               

               


                     Modifié par henesua, 05 décembre 2012 - 04:47 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #1 on: November 24, 2012, 11:12:33 pm »


               The first piece of this project that I have tackled is the default perception event. Before starting this project however I had cleaned up the bioware perception event, and added some fun behaviors for Sentries (watchmen, guard dogs) and Packs (wolves, herds). So keep in mind that the framework of the script is not the default. This one captures and responds to every kind of perception event.

The new addition to the script relating to Reputation and Group Membership is a new function


// Determine oSource's reaction type toward oTarget - (FILE: aa_inc_factions)
// Reputation is adjusted by PRR and Group Membership.
// return value of 0 = neutral, 1 = enemy, 2 = friend

int GetReputationReactionType(object oTarget, object oSource=OBJECT_SELF);


I gather the actual personal reputation, the adjustments to this stored in PRR, and then adjust for a charm effect if the PRR Charm duration is still extant. This results in a modified personal reputation for the perceived creature in the eyes of the perceiver (not necessarily a Beholder). Lastly, if the perceived creature is seen as an enemy by the perceiver (the creature executing the perception event) and yet they both belong to the same group, they are considered neutrals.

Then with this information at the top of the perception event, I change the Reaction of the perceiver toward the pereived to match the Reputation Reaction Type returned by the GetReputationReactionType function. I have made this reaction change temporary, as I have some concerns about handling it this way.

The reason why I did it is because I wanted the highlight of the creature to be appropriate for PCs. I didn't want PCs to defensively attack a hostile appearing neutral or friend. And I also thought - since the perception event happens before all of the other events when a PC approaches - that the rest of the AI could continue to use the GetIsEnemy and GetIsFriend functions rather than force myself to rerite every single AI script in the game.

However I am concenred by this because GetReputationReactionType will now respond to the new reputation value rather than the actual reputation value. While I am not recording this information in a database, it is tracked on the creature, and I want to track it on the creature, but I think I am working against myself by manipulating the reputation in a gross way, and potentially changing it because of this.

Advice on how to handle this in a more sensitive way is welcomed.

With regards to performance, this appears to be doing well. It doesn't appear to have any more overhead than the creature's heartbeat (other than the fact that perception events run more often when you have many creatures in an area). I tested this in an area with 7 sheep belonging to the same group and having pack behvior (faction domestic herbivore), and 3 dogs also belonging to the same group exhibiting pack behavior, and sentry behavior (faction domestic carnivore). Each of these creatures also runs my own modifications based on low Cash's work on SpecialBehavior. Sheep are Herbiovores, Dogs as carnivores. (How that works is a bit beyond the scope for the moment, but I wanted to include this as I've got a lot going on and do not appear to be adversely affecting resources). I then wandered off into the woods spawning thirteen creatures (mice, deer, boar) and the town spawning a watchmen with a patrol script and behaving as a sentry. (it was night time so all the others didn't spawn). I moved around between areas let it run for 20 minutes, played a bit. Impact on resources was no different than before. Profiling information seems a little higher, but still negligible 750 executions at 154 milliseconds.
               
               

               


                     Modifié par henesua, 24 novembre 2012 - 11:14 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #2 on: November 25, 2012, 04:08:18 pm »


               I've run more tests and found that the perception event is not adequate for controlling reaction type. This was also an opportunity to test out some harpies with a rewritten captivating song ability. I decided to make these harpies members of a farm. Other farm members include 3 dogs and some sheep, 5-7 usually. In the beginning all members of this motley group get along. Then as expected when a PC enters the scene, the harpies attack because they have the Hostile faction, which is hostile to PCs and - more interestingly for this case - all the factions in play during the test.

Combat is where the system breaks down. Once in combat mode, the harpies sometimes target other farm members. So I obviously will need to dig into more of the AI if I want to control reactions within combat as well. Other farm members are also targeted by their captivated song (which makes them hostile enough to attack) even though I have written this ability to select hostiles only as targets.

Functions I plan to investigate first:
  • spellsIsTarget()
  • DetermineCombatRound()
Also of interest, the perception event does not seem to execute in combat. I'm not sure what is going on, but once the dogs attack the harpies, they don't seem to perceive them. I have however noticed that dogs sometimes do not attack the harpy members of their group after combat has begun, even when they have previously engaged in combat. I suspect that a perception event allowed them to reset their assessment of the harpy they perceived, but I haven't found any evidence yet (I need better debug messages). Nevertheless I believe this is a potential problem and I need to increase the sophistication of GetReputationReactionType.
               
               

               


                     Modifié par henesua, 25 novembre 2012 - 04:10 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #3 on: November 25, 2012, 05:11:37 pm »


               More testing. The SetEnemy, SetFriend, SetNeutral functions do not appear to change the highlight color of the creature for a PC. I'm wondering if that will render the group name idea as a non-starter for creating organizations which both PCs and NPCs can belong to.

I wonder if I need to reciprocate the call for the perceived creature if it is a PC. I'll test that next.

I'll see what else I can do.

Potentially I could also create many custom factions to mirror these groups, and enable a creature to switch factions when they need to...
or I could avoid making any factions that are hostile or friendly to the PC. So that reaction type is changed (initially) from a neutral state.


After even more testing I discovered that I was incorrect in my assessment. SetIsTemporaryFriend does change the color of the NPC appropriately. SetIsTemporaryNeutral however... does not seem to work. I don't think so anyway. And I am not sure what effect SetIsTemporaryEnemy is having as it appeared to extend beyond the creatures that it was applied to.

FYI SetIsTemporaryFriend when executed successfully was run on creatures that started out as Neutrals. SetIsTemporaryNeutral failed when applied to creatures that were Enemies.
               
               

               


                     Modifié par henesua, 25 novembre 2012 - 06:27 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #4 on: November 25, 2012, 07:57:37 pm »


               TEST RESULTS
Based on the difficulties I had above with SetIsTemporaryNeutral, I decided to systematically test the results of this function and others. In each of these tests the NPC has not had a chance to have its reputation adjusted by PC actions. All tests run from NPC's Perception Event .

Green results are expected and useful. Red results are unexpected and not useful. Yellow resutls are expected but not useful. Purple results are expected, and can be of use, but make my life complicated.

Test 1: SetIsTemporaryFriend(PC, NPC) executed. NPC is Neutral or Enemy.
Result:  NPC displays as Friend

Test 2: SetIsTemporaryNeutral(PC, NPC) executed, NPC is Friend
Result:  NPC displays as Neutral

Test 3: SetIsTemporaryNeutral(PC, NPC) executed. NPC is Neutral.
Result:  NPC displays as Hostile

Test 4: SetIsTemporaryNeutral(PC, NPC) executed, NPC is Enemy 
Result:  No Change

Test 5: SetPCLike(PC, NPC) executed. NPC is Enemy
Result:  No Change

Test 6: ClearPersonalReputation(PC, NPC) executed. NPC is Enemy
Result:  No Change

Test 7: AdjustReputation(PC, NPC, 25) executed. NPC is Enemy
Result:  NPC Faction displays as Neutral
               
               

               


                     Modifié par henesua, 25 novembre 2012 - 08:02 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #5 on: November 25, 2012, 08:22:24 pm »


               Based on the above test results, I've arrived at the following choices for how to proceed:
  • allow hostile NPCs to appear hostile even though they are behaving neutrally
  • adjust the reputation of the hostile NPCs faction if you need them to behave as a Neutral
  • create factions for each "group" that appears in game, and when a creature belonging to a group is spawned, switch them to that faction. 
I am leaning toward the last choice because it enables the following:
  • trust faction adjustments for a group
  • eliminates the need to check for group membership in the perception event (maybe)
  • eliminates the need to track group reputation separately from faction reputation
  • simplifies AI amongst group members as it elimnates hostility between members
I still want to think about it for awhile. My original plan was to treat factions and groups as separate things, and allow NPCs to belong to both at the same time, which could make for some very interesting dynamics. I may however be able to script that behavior. We shall see.

Another thought... I may want to make unique factions for important Unique characters. This will enable me to have full control over what they think of PCs as AdjustReputation seems to be the only way to fully control an NPCs reputation values, yet it is a faction wide function.

Much to think about. Time for a break.
               
               

               


                     Modifié par henesua, 25 novembre 2012 - 08:24 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #6 on: November 27, 2012, 12:22:10 am »


               

henesua wrote...

TEST RESULTS
Based on the difficulties I had above with SetIsTemporaryNeutral, I decided to systematically test the results of this function and others. In each of these tests the NPC has not had a chance to have its reputation adjusted by PC actions. All tests run from NPC's Perception Event .

Green results are expected and useful. Red results are unexpected and not useful. Yellow resutls are expected but not useful. Purple results are expected, and can be of use, but make my life complicated.

Test 1: SetIsTemporaryFriend(PC, NPC) executed. NPC is Neutral or Enemy.
Result:  NPC displays as Friend

Test 2: SetIsTemporaryNeutral(PC, NPC) executed, NPC is Friend
Result:  NPC displays as Neutral

Test 3: SetIsTemporaryNeutral(PC, NPC) executed. NPC is Neutral.
Result:  NPC displays as Hostile

Test 4: SetIsTemporaryNeutral(PC, NPC) executed, NPC is Enemy 
Result:  No Change

Test 5: SetPCLike(PC, NPC) executed. NPC is Enemy
Result:  No Change

Test 6: ClearPersonalReputation(PC, NPC) executed. NPC is Enemy
Result:  No Change

Test 7: AdjustReputation(PC, NPC, 25) executed. NPC is Enemy
Result:  NPC Faction displays as Neutral

great work, very appriciated:wizard:
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #7 on: November 27, 2012, 12:25:34 am »


               Thanks!

Incidentally I neglected to post that SetIsTemporaryEnemy works just fine too - enemies neutrals and friends switch to enemy status when it is used on them. I'll update the test results later. I think I lost that line while trying to get the formatting of the post just right.
               
               

               
            

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #8 on: November 27, 2012, 01:16:21 am »


               I have goblins that will start bowing to npc's or pc's of high enough level and have a high faction reputation with said goblins.  It has never happened to any of my characters but I have seen it happen and one pc even raised a small goblin army which followed him into town.  It took 3 other pc's to clean up the mess. (of goblins).
Just a side for the kinds of things you can do once your get your system working as you want.  Of course it will be even better than anything extant since it incorporates the efforts of other Vendalus, DM Vecna, etc...and your own efforts.
IOW. Cool!
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #9 on: November 27, 2012, 01:53:40 am »


               That sounds awesome, ffbj. I would like to get behavior like you describe in Arnheim as well. Goblins bowing in reverence to the PCs is awesome! I guess I'm really just reinventing the same wheel many others have, but whatever. They didn't post their work to the vault for me to use.

I don't know if anything I am doing will be better than other's work, but I am standing on the shoulders of giants which helps one look tall. PRR is very useful. The implementation I describe above is really only that, an application of PRR to the perception event. Vendalus did most of the work for me by putting his ides in code.

The next step in this is to work on Factions. Since I am leaning towards option 3 - assign "group" members to the appropriate custom faction, I am going to need a system of factions that is easily extensible and makes sense. And I need a failsafe on the faction bug where creatures seem to behave as members of their parent faction rather than the faction they actually belong to. I'm still penciling it out, but will post it soon.

As soon as I finish some real life projects. I have 5 sets of construction documents due next monday. Thats a lot of work that I neglected over Thanksgiving holiday
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #10 on: November 27, 2012, 02:44:29 pm »


               I've had two thoughts recently about changing a creature to a faction related group if they belong to that group.

The first is that while this solves my problem with faction reputation it doesn't necessarily solve my problem with personal reputation. I am storing personal reputation data for some NPCs, and this could influence hostility/friendliness. The question remains as to how I handle this. I am thinking that for the few NPCs for which I need to finely adjust their personal reputation, they will need their own faction.

Another thought... if I hit a wall, and I need to salvage my present method of temporary reputation adjustment, the solution for making an enemy NPC neutral could be using two functions in succession: SetIsTemporaryFriend followed by SetIsTemporaryNeutral. Its ugly, but I suspect it would work. [Edit: on the first trial it did not work. Perhaps a timing issue?]

The second is that faction design is critically important for how this will work for me. I need factions for groups, and I need factions for special individuals. I'm not sure how I will tackle this yet, but since I am interested in expanding the parent factions. I presently plan on creating some generic parent factions which relate to one another. The default parent factions (Hostile, Commoner, Merchant, and Defender)  are interesting in that they define some basic relationships between classes of individuals within a village. I would like to expand on this model to define a few more basic roles. Leader for example would be a good one since I want to define special factions for the role filled by Unique NPCs. Hostile however seems to represent an outsider to the group, so I think it conceptually belongs to a different group of factions: Hostile, Neutral, Friend.

Concept for New parent factions:

Hostile
Neutral
Friend

Dissident   (a specific kind of hostile who belongs to the group - uncertain if I wil use this)
Commoner
Merchant (Gentry?)
Defender
Leader

(and... since Arnheim is focused on the conflict between civilized and wild super factions. i need a set of parent factions for wild groups and civilized groups and to make their members hostile to one another)
Civ - Dissident
Civ - Commoner
Civ - Merchant 
Civ - Defender
Civ - Leader

Wild - Dissident
Wild - Commoner
Wild - Merchant 
Wild - Defender
Wild - Leader
               
               

               


                     Modifié par henesua, 28 novembre 2012 - 10:53 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #11 on: November 30, 2012, 03:27:53 am »


               Has anyone else run into issues with the way PRR handles data? I think it is odd the way it uses the NBDE databases. The weakness of NBDE is that it has to check in and check out database objects. If you have say many db objects this can create performance problems for players. PRR creates a db for each PC, and each faction. This seems excessive to me.

Anyway... I need to rewrite this for myself. I'm thinking that one database object for PRR per campaign is plenty.
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #12 on: December 05, 2012, 01:15:38 pm »


               

henesua wrote...
the solution for making an enemy NPC neutral could be using two functions in succession: SetIsTemporaryFriend followed by SetIsTemporaryNeutral. Its ugly, but I suspect it would work.


Goal:
make a single Hostile NPC Neutral to another NPC or to the PC.

Prior Attempt:
SetIsTemporaryNeutral
result: failure. NPC remains Hostile. (Reputaion prior 0, after 0)

This Attempt:
SetIsTemporaryFriend followed by on next execution SetIsTemporaryNeutral
result: NPC becomes friendly on first pass (Reputaion prior 0, after 100), hostile on second pass (Reputaion prior 100, after 0)

What this suggests to me is that these functions do more than adjust reputation by a set amount. After testing various faction reputation values I discovered the following:
  • SetIsTemporaryFriend: Clears Rep then +100 to Rep
  • SetIsTemporaryNeutral: Clears Rep then -50 to Rep
  • SetIsTemporaryEnemy: Clears Rep then -100 to Rep

Example:
Test: Faction Rep 85. SetIsTemporaryNeutral
Result: Personal Rep set to 35 regardless of starting personal Rep.

The more I look at this the more I think that SetIsTemporaryNeutral has very limited use.

Next I am going to look at setting the temporary rep change to decay.
               
               

               


                     Modifié par henesua, 05 décembre 2012 - 03:18 .
                     
                  


            

Legacy_SHOVA

  • Hero Member
  • *****
  • Posts: 893
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #13 on: December 05, 2012, 02:56:58 pm »


               Did you try using clear all actions before SetIsNeutral? I would not presume that your scripting is the problem, but we all make boneheaded mistakes sometimes. Maybe post the script you made, so we can double check it '<img'>

After reading through, I see you using the Bio standard script functions: Set is friend- and the like, but not making custom ones for your custom factions. Will you be adding the custom factions to the available functions?

keep up the good work!
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Arnheim (WIP)- AI, Persistent Reputation, and Group Membership
« Reply #14 on: December 05, 2012, 03:26:53 pm »


               ClearAllActions? Why would I do that before SetIsTemporaryNeutral?

For these tests I have turned off the default Attack on Perceive behavior. See my perception script above. I have a Test creature (a "Test Cow" actually) which acts Neutral in my custom Perception Event, because GetReputationReactionType always returns 0 (Neutral) for Test Cows.

This enables me to track how reputation is changed by the default functions, without worrying about behavior. So I don't need to stop combat or any other incidental that one typically needs to worry about.

Regarding writing custom functions for SetIsTemporary....  I can't unless I had an NWNX hook into adjusting Personal Reputation between two creatures. Bioware's functions (other than SetIsTemporary...) at best adjust faction reputation relative to an individual. Adjusting Personal Rep between individuals is the sticky problem that forced me to rethink how I am handling groups because I am not using NWNX. I want my module to work with the vanilla client or server.

If I want fine grained control over individuals I think I will need to create factions for the groups they will be applied to.... or rewrite all AI scripts to take groups into account.I'm leaning toward making factions do the work for me, and adjust faction rep when I need to. BUT... this means that I can't have dynamic groups. They need to have factions to support them. And you can't make factions on the fly... so I don't believe I'll be able to allow players to create groups in real time.
               
               

               


                     Modifié par henesua, 05 décembre 2012 - 03:33 .