def midpoint_to_actionpairs(mp): # transform (BefM, M, AftM) to [((BefM, rating, M)), (M, rating, AftM)] try: ap_str = "{}:{}".format(mp["Before Midpoint"][0], mp["Midpoint"][0]) ap_row = find_by_attribute(ACTION_PAIRS, "Action Pair", ap_str)[0] action_pair = (ap_row["Before"], ap_row["Tension"], ap_row["After"]) ap2_str = "{}:{}".format(mp["Midpoint"][0], mp["After Midpoint"][0]) ap2_row = find_by_attribute(ACTION_PAIRS, "Action Pair", ap2_str)[0] action_pair2 = (ap2_row["Before"], ap2_row["Tension"], ap2_row["After"]) except: return None # filter action pairs without tension rating if not action_pair[1] or not action_pair2[1]: if not action_pair[1]: logger.debug("No tension for action pair: {}, {}".format( action_pair[0], action_pair[2])) if not action_pair2[1]: logger.debug("No tension for action pair: {}, {}".format( action_pair2[0], action_pair2[2])) return None return (action_pair, action_pair2)
def choose_step(steps, current_rating, prev=True): # turn midpoint row into 2 actions: # (BeforeM, M, AfterM) --> (BeforeM, rating, M), (M, rating, AfterM) all_midpoint_steps = [] for step in steps: # TODO: if midpoint has more than one element, try with others try: ap_str = "{}:{}".format(step["Before Midpoint"][0], step["Midpoint"][0]) ap_row = find_by_attribute(ACTION_PAIRS, "Action Pair", ap_str)[0] action_pair = (ap_row["Before"], ap_row["Tension"], ap_row["After"]) ap2_str = "{}:{}".format(step["Midpoint"][0],step["After Midpoint"][0]) ap2_row = find_by_attribute(ACTION_PAIRS, "Action Pair", ap2_str)[0] action_pair2 = (ap2_row["Before"], ap2_row["Tension"], ap2_row["After"]) all_midpoint_steps.append((action_pair, action_pair2)) except: # the action-pair table doesn't contain an entry for such a midpoint continue print("All Midpoint rows ending on Befor-action of conflict:") pprint(all_midpoint_steps) print() # filter out all action-pair tuples that were not tension scored: filtered_midpoint_steps = [] for (ap1, ap2) in all_midpoint_steps: if ap1[1] and ap2[1]: filtered_midpoint_steps.append((ap1, ap2)) print("All Midpoint rows that have tension ratings for both pairs:") pprint(filtered_midpoint_steps) print() if len(filtered_midpoint_steps) == 0: raise Exception("Not enough rated action-pairs") # select action-pair tuple fitting to our curve fitting_midpoint_steps = [] for (ap1, ap2) in filtered_midpoint_steps: if prev: if float(ap2[1]) <= current_rating and float(ap1[1]) <= float(ap2[1]): fitting_midpoint_steps.append((ap1, ap2)) else: if float(ap1[1]) <= current_rating and float(ap2[1]) <= float(ap1[1]): fitting_midpoint_steps.append((ap1, ap2)) print("All Midpoint rows that fit tension curve:") pprint(fitting_midpoint_steps) print() if len(fitting_midpoint_steps) == 0: raise Exception("No midpoints that fit tension curve") random_midpoint = randint(0, len(fitting_midpoint_steps)-1) print(fitting_midpoint_steps[random_midpoint]) print() return fitting_midpoint_steps[random_midpoint]
def find_conflict_locations(): """ Find locations with at least one interaction that is in action pairs list and has the link: "but" Returns list of form: (location-row, action-name) """ buts = find_by_attribute(ACTION_PAIRS, "Link", "but") but_actions = [x["Before"] for x in buts] # get just the names print "num. of but-actions: ", len(but_actions) print "Like e.g. ", but_actions[:5] print conflict_locations = [] # contains tuples of (location, avail. but-action) for loc in LOCATIONS: # action-pairs use underscore in their actions, locations use spaces actions = [act.replace(" ", "_") for act in loc["Interactions"]] # find interactions that are but-actions for action in actions: if action in but_actions: conflict_locations.append((loc, action)) print "number of conflict locations:", len(conflict_locations) # each element is tuple of (location,action), so to see location # get first element of list, and first entry in this tuple loc_name = conflict_locations[0][0]["Location"] print "first suitable location: ", loc_name, ", action: ", conflict_locations[ 0][1] return conflict_locations
def create_story_graph_backw(climax_tension): logger.info("Backwards generating story graph from tension " + climax_tension) story_graph = Tree() climaxes = find_by_attribute(ACTION_PAIRS, "Tension", climax_tension) logger.debug(str(len(climaxes)) + " climaxes found") # create initial set of nodes to expand expand_nodes = [] for climax in climaxes: action_pair = (climax["Before"], climax["Tension"], climax["After"]) # put node in Graph story_graph[climax_tension][action_pair] ap_node = story_graph[climax_tension][action_pair] expand_nodes.append((ap_node, action_pair)) # expand nodes for current_ap_node, action_pair in expand_nodes: previous_steps = find_next_steps(action_pair, backw=True) for (BefMM, MAftM) in previous_steps: # rating prev ap current_ap_node[MAftM[1]][MAftM] penultimate_ap_node = current_ap_node[MAftM[1]][MAftM] # rating first ap penultimate_ap_node[BefMM[1]][BefMM] return story_graph
def get_location_by_tension(tension): ''' Get location dict by exact tension level Input: integer tension Output: list location(s) ''' locations_on_tension = find_by_attribute(LOCATIONS, "Tension", tension) return rand(locations_on_tension)
def get_location_by_name(name): ''' Get location dict by name Input: String name Output: dict location ''' location = find_by_attribute(LOCATIONS, "Location", name) return location[0]
def pick_climax(): """ Returns a climax action: (Before, 5, After) and its rating""" conflict_tension = str(float(pick_conflict_tension())) climaxes = find_by_attribute(ACTION_PAIRS, "Tension", conflict_tension) random_num = randint(0, len(climaxes)-1) climax = climaxes[random_num] action = (climax["Before"], climax["Tension"], climax["After"]) return action, int(float(conflict_tension))
def find_previous_steps(action): """ Returns a list of midpoint rows that each represents possible previous steps: [ {'After Midpoint': ['beg_forgiveness_from'], <-- possible step 1 'Before Midpoint': ['spy_on'], 'Midpoint': ['are_discovered_by']}, {...} <-- possible step 2 ] """ after_midpoint = action[0] try: steps = find_by_attribute(MIDPOINTS, "After Midpoint", after_midpoint) except KeyError: raise KeyError("Midpoints have no 'After Midpoint' for: {}" .format(after_midpoint)) return steps
def find_next_steps(action, backw=True): """ Returns a list of tuples of actionpairs, that each represents possible previous steps: action: ('beg_forgiveness_from', '5.0', 'are_indoctrinated_by') returns: [(('spy_on', '3.0', 'are_discovered_by'), ('are_discovered_by', '3.0', 'beg_forgiveness_from')), (('disfigure', '3.0', 'are_disgusted_by'), ('are_disgusted_by', '2.0', 'beg_forgiveness_from')), ] """ if backw: known_midpoint = action[0] column = "After Midpoint" logging.debug("Finding previous midpoint for " + known_midpoint) else: known_midpoint = action[2] column = "Before Midpoint" logging.debug("Finding next midpoint for " + known_midpoint) try: midpoints = find_by_attribute(MIDPOINTS, column, known_midpoint) except: # no midpoints for this action logging.debug("No Midpoint: " + known_midpoint) return [] # transform (BefM, M, AftM) to [((BefM, rating, M)), (M, rating, AftM)] ap_tuples = [] for mp in midpoints: ap_tuple = midpoint_to_actionpairs(mp) if ap_tuple: ap_tuples.append(ap_tuple) return ap_tuples
# find interactions that are but-actions for action in actions: if action in but_actions: conflict_locations.append((loc, action)) print "number of conflict locations:", len(conflict_locations) # each element is tuple of (location,action), so to see location # get first element of list, and first entry in this tuple loc_name = conflict_locations[0][0]["Location"] print "first suitable location: ", loc_name, ", action: ", conflict_locations[ 0][1] return conflict_locations char = pick_random_char() print "A random char:" print "Name: {}, weapon: {}".format(char.character, char.weapon_of_choice) print conflicts = find_by_attribute(ACTION_PAIRS, "Link", "but") some_conflict = Row(conflicts[0]) print "First conflict:" print "before action: ", some_conflict.before, "after: ", some_conflict.after print print "Try to find some nice conflict locations..." find_conflict_locations()
def get_location_at_random(): location = rand(find_by_attribute(LOCATIONS, "Preposition", "in")) return location
from __future__ import print_function from pprint import pprint from random import randint, choice import sys from data import ACTION_PAIRS, MIDPOINTS from data import find_by_attribute CONF_PROB = {5: 0.6, 4: 0.3, 3: 0.1} CONF_PROB = {5: 1} NUM_OF_CLIMAXES = len(find_by_attribute(ACTION_PAIRS, "Tension", "5.0")) # datatypes: # action -> triple: (Before, tension, After) # story_part -> triple (Before Midpoint, Midpoint, After midpoint) # story_graph -> [action, action, ...] def pick_conflict_tension(): """ Creates a probability distribution using probabilities in CONF_PROB and picks an tension-level by random. Returns int: tension level """ rating_dist = [] for rating, prob in CONF_PROB.items(): ratings = [rating] * int(prob * 10) rating_dist += ratings return choice(rating_dist)
def conjunction(actionPair): '''Find the conjunction of the action pair''' verb1, tension, verb2 = actionPair pair = find_by_attribute(ACTION_PAIRS, "Action Pair", verb1 + ':' + verb2) return pair[0]['Link']