Skip to content

Commit

Permalink
Merge pull request #13 from njunius/validation-tools-upgrade
Browse files Browse the repository at this point in the history
Validation tools upgrade
  • Loading branch information
njunius authored Sep 30, 2023
2 parents d631e1c + 5336077 commit 169f90a
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 31 deletions.
58 changes: 45 additions & 13 deletions src/secondary/npc_a_star.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,15 @@ def _puppitor_adjacencies(character_affecter, action_key_map, affect_tuple, goal
# calculates the magnitude of the change in value of the goal_emotion in affect_vector
def _puppitor_edge_cost(character_affecter, affect_vector, action, modifier, affects, goal_emotion, step_multiplier):

cost = abs(_affecter_action_modifier_product(character_affecter, action, modifier, goal_emotion, step_multiplier))
goal_delta = abs(_affecter_action_modifier_product(character_affecter, action, modifier, goal_emotion, step_multiplier))

max_val_affects = affecter.get_possible_affects(affect_vector)

curr_max_delta = abs(_affecter_action_modifier_product(character_affecter, action, modifier, max_val_affects[0], step_multiplier))

#cost = abs(_affecter_action_modifier_product(character_affecter, action, modifier, goal_emotion, step_multiplier))

cost = abs(curr_max_delta - goal_delta)
return cost

# multiplies the action, modifier, and step_multiplier values together
Expand Down Expand Up @@ -65,12 +72,47 @@ def _heuristic(current_affect, affect_vector, goal_emotion):
def _calc_distance_between_affects(affect_vector, first_affect, second_affect):
return affect_vector[first_affect] - affect_vector[second_affect]

# constructs the path to be returned by A* search
# each argument corresponds to the variable of the same name in npc_a_star_think()
# analysis is a flag which enables full path reconstruction for the purposes of analyzing the output as it is slower than partial reconstruction that is the default behavior
def _construct_path(curr_node, prev_node, character_affecter, step_multiplier, frontier, analysis = False):
path = []
while curr_node:
# add the number of steps it takes to reach the estimated distances
counter = 0
while counter < step_multiplier:
counter += 1
path.append(curr_node)
if prev_node[curr_node] == None:
break
curr_node = prev_node[curr_node]

final_path = path

if analysis:
reconst_path = []
counter = 0
for curr_node in reversed(path):
temp_av = dict(curr_node[0])

if counter > 0:
temp_av = dict(reconst_path[-1][0])
character_affecter.update_affect(temp_av, curr_node[1], curr_node[2])

updated_node = (temp_av, curr_node[1], curr_node[2], affecter.get_prevailing_affect(character_affecter, temp_av))
reconst_path.append(updated_node)
counter += 1
final_path = reconst_path

print('path length: ', len(final_path), 'frontier length: ', len(frontier))
return final_path

# A* search for use with Puppitor
# nodes are (affect_vector, action, modifier, prevailing_affect)
# start is a tuple of (affect_vector, action, modifier, prevailing_affect)
# NOTE: the traditional graph definition used for A* is split between the affecter and action_key_map modules
# NOTE: affect_vectors must be converted to tuples as part of making a node because nodes must be hashable
def npc_a_star_think(character_affecter, action_key_map, start, goal_emotion, step_multiplier = 1, max_queue_size = 18000):
def npc_a_star_think(character_affecter, action_key_map, start, goal_emotion, step_multiplier = 1, max_queue_size = 18000, analysis = False):
frontier = [] # queue of nodes to visit
visited_nodes = [] # list of nodes that have been visited
cost_so_far = {} # the smallest cost to reach a given node
Expand All @@ -86,17 +128,7 @@ def npc_a_star_think(character_affecter, action_key_map, start, goal_emotion, st

# if the node's prevailing affect is the affect we want to express, get the path there
if curr_node[3] == goal_emotion:
path = []
while curr_node:
# add the number of steps it actually takes to reach the estimated distance
counter = 0
while counter < step_multiplier:
counter += 1
path.append(curr_node)
curr_node = prev_node[curr_node]

print('path length: ', len(path), '\nfrontier length: ', len(frontier))
return path
return _construct_path(curr_node, prev_node, character_affecter, step_multiplier, frontier, analysis)

# check every adjacent node of the current node and if it is a new node or a more efficient way to get to next_node, add it to the frontier
for next in _puppitor_adjacencies(character_affecter, action_key_map, curr_node[0], goal_emotion, step_multiplier):
Expand Down
9 changes: 0 additions & 9 deletions tools/response_curve.csv

This file was deleted.

19 changes: 13 additions & 6 deletions tools/rule_file_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,28 @@ def main():
th.print_run_info(step_value, goal_emotion, character_av)

action_path = []
start_node = (character_av, action, modifier, character_test.current_affect)
action_path = npc_a_star.npc_a_star_think(character_test, test_actions, start_node, goal_emotion, step_value, queue_limit)
start_node = (character_av, action, modifier, affecter.get_prevailing_affect(character_test, character_av))
action_path = npc_a_star.npc_a_star_think(character_test, test_actions, start_node, goal_emotion, step_value, queue_limit, analysis = True)

if not action_path:
print('NO PATH FOUND')
return 0

response_curve = []
response_curve = th.find_all_affect_changes(action_path)
if len(action_path) > 1:
response_curve = th.find_all_affect_changes(action_path)
else:
response_curve.append(th.delta_info._make((0, action_path[0][3], action_path[0][3], action_path[0][3], action_path[0][1], action_path[0][2])))
with open('response_curve.csv', 'w', newline = '') as csvfile:
response_writer = csv.writer(csvfile, delimiter = ',', quotechar = '|', quoting = csv.QUOTE_MINIMAL)

print(action_path[-1])

start_state, start_action, start_mod, start_affect = action_path[len(action_path) - 1]

response_writer.writerow(['count', 'init_affect', 'prev_affect', 'curr_affect', 'curr_action', 'curr_modifier'])
response_writer.writerow([0, start_affect, start_affect, start_affect, start_action, start_mod]) # add initial state to file
if len(response_curve) > 1:
response_writer.writerow([0, start_affect, start_affect, start_affect, start_action, start_mod]) # add initial state to file

affect_step_cache = 0

Expand All @@ -103,8 +110,8 @@ def main():
print('\nnumber of steps for a new action or modifier to be used: ', step_diff, '\naction: ', node.curr_action, '\nmodifier: ', node.curr_mod)

response_writer.writerow([node.count, node.init_affect, node.prev_affect, node.curr_affect, node.curr_action, node.curr_mod])
last_index = len(response_curve) - 1
end = response_curve[last_index]

end = response_curve[-1]
response_writer.writerow([len(action_path), end.init_affect, end.curr_affect, end.curr_affect, end.curr_action, end.curr_mod]) # add the last step to the file

th.apply_print_path(action_path, character_test, character_av, step_value, verbose)
Expand Down
7 changes: 4 additions & 3 deletions tools/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import action_key_map
import affecter

delta_info = collections.namedtuple('delta_info', ['count', 'init_affect', 'prev_affect', 'curr_affect', 'curr_action', 'curr_mod'])

def update_from_path(path):
node = path.pop()
action = node[1]
Expand All @@ -26,6 +28,7 @@ def apply_print_path(path, char_affecter, character_av, step_value, verbose):

if verbose:
print('\naction and modifier: ' + action + ', ' + modifier)
print('\nprevailing affect: ' + affecter.get_prevailing_affect(char_affecter, character_av))
print('\ncharacter affect vector: ', character_av)
return

Expand Down Expand Up @@ -60,9 +63,7 @@ def find_first_affect_change(path):
# - the initial expressed affect
# - the previous expressed affect
# - the currently expressed affect
def find_all_affect_changes(path):
delta_info = collections.namedtuple('delta_info', ['count', 'init_affect', 'prev_affect', 'curr_affect', 'curr_action', 'curr_mod'])

def find_all_affect_changes(path):
start_node = path[len(path) - 1]
init_affect = start_node[3]
prev_affect = init_affect
Expand Down

0 comments on commit 169f90a

Please sign in to comment.