Exemplo n.º 1
0
def next_id(story, type):
  """
  Scans through the given story and returns the next ID number for the given
  object type.
  """
  highest = -1
  for (schema, binding) in ans.bindings({"id": ID_PATTERN}, story):
    id_type = dequote(str(binding["id.Type"].name))
    id_int = int(binding["id.ID"].name)
    if id_type == type and id_int > highest:
      highest = id_int
  return highest + 1
Exemplo n.º 2
0
def glean_nouns(story):
  result = {}
  for sc, binding in ans.bindings(NOUN_SCHEMAS, story):
    n = binding["st.property.inst.Key"].unquoted()
    t = binding["st.property.inst.Type"].unquoted()
    if n not in result:
      result[n] = nouns.Noun(n, TR_TYPE[t] if t in TR_TYPE else "thing")
    if sc == "name":
      result[n].name = binding["st.property.Name"].unquoted()
    elif sc == "number":
      result[n].number = binding["st.property.Number"].unquoted()
    elif sc == "gender":
      result[n].gender = binding["st.property.Gender"].unquoted()
    elif sc == "person":
      result[n].person = binding["st.property.Person"].unquoted()
    elif sc == "determined":
      d = binding["st.property.Determination"].unquoted()
      result[n].determined = d == "true"
  return result
Exemplo n.º 3
0
def filter_keep(story):
  result = []
  for sch, bnd in ans.bindings(KEEP, story):
    result.append(bnd[sch])
  # Unique key handling:
  max_unique_key = None
  for pr in story:
    b = ans.bind(SC["unique_key_used"], pr)
    if b:
      k = int(str(b["unique_key_used.Key"]))
      if max_unique_key == None or k > max_unique_key:
        max_unique_key = k
    b = ans.bind(SC["max_unique"], pr)
    if b:
      k = int(str(b["max_unique.Key"]))
      if max_unique_key == None or k > max_unique_key:
        max_unique_key = k
  if max_unique_key == None:
    result.append(Pr("max_unique", Pr(0)))
  else:
    result.append(Pr("max_unique", Pr(max_unique_key)))
  return result
Exemplo n.º 4
0
def filter_keep(story):
    result = []
    for sch, bnd in ans.bindings(KEEP, story):
        result.append(bnd[sch])
    # Unique key handling:
    max_unique_key = None
    for pr in story:
        b = ans.bind(SC["unique_key_used"], pr)
        if b:
            k = int(str(b["unique_key_used.Key"]))
            if max_unique_key == None or k > max_unique_key:
                max_unique_key = k
        b = ans.bind(SC["max_unique"], pr)
        if b:
            k = int(str(b["max_unique.Key"]))
            if max_unique_key == None or k > max_unique_key:
                max_unique_key = k
    if max_unique_key == None:
        result.append(Pr("max_unique", Pr(0)))
    else:
        result.append(Pr("max_unique", Pr(max_unique_key)))
    return result
Exemplo n.º 5
0
    def gen(t):
        nonlocal name, code, source
        if not t.mem.code:
            raise ASPTaskError(
                "Task '{}' has no code (missing t.mem.code)!".format(name))
        if type(t.net.mem.code.story) == obj.EmptyObj:
            raise ASPTaskError(
                "No story found (missing t.net.mem.code.story)!")
        if type(t.net.mem.code.universal) == obj.EmptyObj:
            raise ASPTaskError(
                "No universal constraints object (missing t.net.mem.code.universal)!"
            )
        problem = assemble_problem(t)
        predicates = asp.solve(problem)

        #    print("Predicates:")
        #    for p in predicates:
        #      print(p)

        errors = []
        status = None
        story_predicates = set()
        to_run = []
        to_spawn = {}
        lmemlist = []
        gmemlist = []
        for (schema, binding) in ans.bindings(story_schemas, predicates):
            story_predicates.add(binding[schema])
        for (schema, binding) in ans.bindings(active_schemas, predicates):
            if schema == "error":
                print("Error in Clingo output!")
                errors.append(dequote(str(binding["error.Message"])))
            elif schema == "status":
                s = dequote(str(binding["status.String"]))
                if status == None:
                    status = s
                else:
                    status = status + " and " + s
            elif schema == "local_mem":
                lmemlist.append(
                    (dequote(str(binding["local_mem.Address"].name)),
                     binding["local_mem.Value"]))
            elif schema == "global_mem":
                gmemlist.append((dequote(str(binding["global_mem.Address"])),
                                 binding["global_mem.Value"]))
            elif schema == "spawn_task":
                tid = str(binding["spawn_task.Id"])
                tname = dequote(str(binding["spawn_task.TaskName"]))
                if tid not in to_spawn:
                    to_spawn[tid] = {
                        "name": "<unknown>",
                        "args": {},
                    }
                to_spawn[tid]["name"] = tname
            elif schema == "task_arg":
                tid = str(binding["task_arg.Id"])
                tkey = dequote(str(binding["task_arg.Key"]))
                tval = dequote(str(binding["task_arg.Value"]))
                if tid not in to_spawn:
                    to_spawn[tid] = {
                        "name": "<unknown>",
                        "args": {},
                    }
                to_spawn[tid]["args"][tkey] = tval
            elif schema == "run_code":
                to_run.append(unquote(binding["run_code.QuotedCode"]))

        if errors:
            raise ASPTaskError("Error(s) while resolving answer set task:\n" +
                               '\n'.join(errors))

        if status in tn.TaskStatus.aliases:
            status = tn.TaskStatus.aliases[status]
        elif status == None:
            status = tn.TaskStatus.Final.Completed
        else:
            raise ASPTaskError(
                "Error: answer set produced invalid status '{}'.".format(
                    status))

        # Run code blocks before additions and removals are processed:
        for code in to_run:
            code_locals = {
                "status": status,
                "task": t,
                "story_predicates": story_predicates,
                "lmemlist": lmemlist,
                "gmemlist": gmemlist,
            }
            compiled = compile(
                code,
                "<snippet from ASP task '{}' in {}>".format(name,
                                                            source), 'exec')
            exec(compiled, {}, code_locals)
            status = code_locals["status"]
            story_predicates = code_locals["story_predicates"]
            lmemlist = code_locals["lmemlist"]
            gmemlist = code_locals["gmemlist"]

        # Process the new story and memory elements:
        t.set_story(story_predicates)

        for (addr, val) in lmemlist:
            t.mem[addr] = val

        for (addr, val) in gmemlist:
            t.net.mem[addr] = val

        # Spawn tasks:
        for id in to_spawn:
            spawn_task(t.net, to_spawn[id]["name"], **to_spawn[id]["args"])

        # We're finally done, so yield the indicated status:
        yield status
Exemplo n.º 6
0
def filter_keep(story):
  result = []
  for sch, bnd in ans.bindings(KEEP, story):
    result.append(bnd[sch])
  return result
Exemplo n.º 7
0
def build_story_text(story, root=None):
  node_templates = {}

  # First, build all of the templates for the entire story:
  for sc, bnd in ans.bindings(TEXT_SCHEMAS, story):
    node = bnd["txt.Node"].unquoted()
    print("Adding {} template for node '{}'.".format(sc, node))
    if node not in node_templates:
      node_templates[node] = {
        "name": node,
        "intro": "",
        "situation": "",
        "options": {},
        "outcomes": {},
        # TODO: state-change text
      }
    txt = bnd["txt.Text"].unquoted()
    if sc == "intro_text":
      node_templates[node]["intro"] = txt
    elif sc == "potential_text":
      if node_templates[node]["situation"]:
        node_templates[node]["situation"] += " and "
      node_templates[node]["situation"] += txt
    elif sc == "option_text":
      opt = bnd["txt.option.Opt"].unquoted()
      node_templates[node]["options"][opt] = txt
    elif sc == "action_text":
      opt = bnd["txt.option.Opt"].unquoted()
      node_templates[node]["outcomes"][opt] = txt

  # Next, use the node structure to recursively render the story text in
  # ChoiceScript:
  nouns = glean_nouns(story)
  node_structure = find_node_structure(story)
  base_pnslots = {
    "I": [0, set()],
    "we": [0, set()],
    "you": [0, { "the_party" }],
    "he": [0, set()],
    "she": [0, set()],
    "it": [0, set()],
    "they": [0, set()],
  }
  base_introduced = { "the_party" }
  # Start with all root nodes on our open list:
  olist = [
    (n, base_pnslots, base_introduced) for n in node_templates.keys()
      if len(node_structure[n]["predecessors"]) == 0
  ]
  print("Root nodes: {}".format([n for (n, bp, bi) in olist]))
  # The ready dictionary keeps track of introduction and pronoun information
  # propagating between non-root nodes and has enough information to know when
  # a node is ready to be rendered:
  ready = {
    n: { pr: None for pr in node_structure[n]["predecessors"]}
      for n in node_templates.keys()
        if len(node_structure[n]["predecessors"]) > 0
  }
  results = []
  while olist:
    target, pnslots, introduced = olist.pop(0)
    print("Processing node: '{}'.".format(target))
    # build node text:
    txt, outgoing = build_node_text(
      node_templates[target],
      node_structure,
      nouns,
      pnslots,
      introduced
    )
    results.append(txt)
    # update our readiness information and propagate nodes to the open list as
    # they're fully ready:
    for n in [x for x in outgoing if x in ready]:
      # DEBUG:
      if None not in ready[n].values():
        raise RuntimeError("""
Updating readiness of already-ready node '{}' from node '{}'.
Readiness is: {}\
""".format(n, target, ready[n])
        )
      ready[n][target] = outgoing[n]
      if None not in ready[n].values():
        pns, intr = merge_txt_states(list(ready[n].values()))
        # TODO: Get rid of pnslots merging altogether?
        #olist.append((n, pns, intr))
        olist.append((n, base_pnslots, intr))
  return ("\n\n*comment " + '-'*72 + "\n\n").join(results)
Exemplo n.º 8
0
  def gen(t):
    nonlocal name, code, source
    if not t.mem.code:
      raise ASPTaskError(
        "Task '{}' has no code (missing t.mem.code)!".format(name)
      )
    if type(t.net.mem.code.story) == obj.EmptyObj:
      raise ASPTaskError("No story found (missing t.net.mem.code.story)!")
    if type(t.net.mem.code.universal) == obj.EmptyObj:
      raise ASPTaskError(
        "No universal constraints object (missing t.net.mem.code.universal)!"
      )
    problem = assemble_problem(t)
    predicates = asp.solve(problem)

#    print("Predicates:")
#    for p in predicates:
#      print(p)

    errors = []
    status = None
    story_predicates = set()
    to_run = []
    to_spawn = {}
    lmemlist = []
    gmemlist = []
    for (schema, binding) in ans.bindings(story_schemas, predicates):
      story_predicates.add(binding[schema])
    for (schema, binding) in ans.bindings(active_schemas, predicates):
      if schema == "error":
        print("Error in Clingo output!")
        errors.append(dequote(str(binding["error.Message"])))
      elif schema == "status":
        s = dequote(str(binding["status.String"]))
        if status == None:
          status = s
        else:
          status = status + " and " + s
      elif schema == "local_mem":
        lmemlist.append(
          (
            dequote(str(binding["local_mem.Address"].name)),
            binding["local_mem.Value"]
          )
        )
      elif schema == "global_mem":
        gmemlist.append(
          (
            dequote(str(binding["global_mem.Address"])),
            binding["global_mem.Value"]
          )
        )
      elif schema == "spawn_task":
        tid = str(binding["spawn_task.Id"])
        tname = dequote(str(binding["spawn_task.TaskName"]))
        if tid not in to_spawn:
          to_spawn[tid] = {
            "name": "<unknown>",
            "args": {},
          }
        to_spawn[tid]["name"] = tname
      elif schema == "task_arg":
        tid = str(binding["task_arg.Id"])
        tkey = dequote(str(binding["task_arg.Key"]))
        tval = dequote(str(binding["task_arg.Value"]))
        if tid not in to_spawn:
          to_spawn[tid] = {
            "name": "<unknown>",
            "args": {},
          }
        to_spawn[tid]["args"][tkey] = tval
      elif schema == "run_code":
        to_run.append(unquote(binding["run_code.QuotedCode"]))

    if errors:
      raise ASPTaskError(
        "Error(s) while resolving answer set task:\n" + '\n'.join(errors)
      )

    if status in tn.TaskStatus.aliases:
      status = tn.TaskStatus.aliases[status]
    elif status == None:
      status = tn.TaskStatus.Final.Completed
    else:
      raise ASPTaskError(
        "Error: answer set produced invalid status '{}'.".format(status)
      )

    # Run code blocks before additions and removals are processed:
    for code in to_run:
      code_locals={
        "status": status,
        "task": t,
        "story_predicates": story_predicates,
        "lmemlist": lmemlist,
        "gmemlist": gmemlist,
      }
      compiled = compile(
        code,
        "<snippet from ASP task '{}' in {}>".format(name, source),
        'exec'
      )
      exec(
        compiled,
        {},
        code_locals
      )
      status = code_locals["status"]
      story_predicates = code_locals["story_predicates"]
      lmemlist = code_locals["lmemlist"]
      gmemlist = code_locals["gmemlist"]

    # Process the new story and memory elements:
    t.set_story(story_predicates)

    for (addr, val) in lmemlist:
      t.mem[addr] = val

    for (addr, val) in gmemlist:
      t.net.mem[addr] = val

    # Spawn tasks:
    for id in to_spawn:
      spawn_task(
        t.net,
        to_spawn[id]["name"],
        **to_spawn[id]["args"]
      )

    # We're finally done, so yield the indicated status:
    yield status
Exemplo n.º 9
0
def viz(story, error=False, lasttarget=None):
    """
  Visualize the given set of predicates (writes out to a file).
  """
    nodes = set()
    node_properties = {}
    links = {}
    for sch, bnd in ans.bindings(SCHEMAS, story):
        if sch == "story_node":
            node = bnd["story_node.Node"].unquoted()
            nodes.add(node)
            if node not in node_properties:
                node_properties[node] = {}
        elif sch == "node_type":
            node = bnd["node_type.Node"].unquoted()
            typ = bnd["node_type.Type"].unquoted()
            nodes.add(node)
            if node not in node_properties:
                node_properties[node] = {}
            node_properties[node]["type"] = typ
        elif sch == "node_status_reached":
            node = bnd["node_status_reached.Node"].unquoted()
            status = bnd["node_status_reached.Status"].unquoted()
            nodes.add(node)
            if node not in node_properties:
                node_properties[node] = {}
            if ("status" not in node_properties[node]) or (
                    NODE_STATUSES.index(node_properties[node]["status"]) <
                    NODE_STATUSES.index(status)):
                node_properties[node]["status"] = status
        elif sch == "successor":
            src = bnd["successor.From"].unquoted()
            opt = bnd["successor.option.Opt"].unquoted()
            dst = bnd["successor.To"].unquoted()
            if src not in links:
                links[src] = {}
            links[src][opt] = dst
        elif sch == "action":
            src = bnd["at.Node"].unquoted()
            opt = bnd["at.action.option.Opt"].unquoted()
            act = bnd["at.action.Action"].unquoted()
            if src not in links:
                links[src] = {}
            if "actions" not in links[src]:
                links[src]["actions"] = {}
            links[src]["actions"][opt] = act
        elif sch == "vignette":
            node = bnd["vignette.Node"].unquoted()
            root = bnd["vignette.Root"].unquoted()
            nodes.add(node)
            if node not in node_properties:
                node_properties[node] = {}
            node_properties[node]["vignette"] = root
        elif sch == "setup":
            node = bnd["setup.Node"].unquoted()
            setup = bnd["setup.Which"].unquoted()
            nodes.add(node)
            if node not in node_properties:
                node_properties[node] = {}
            node_properties[node]["setup"] = setup

    # Write out the graphviz graph:
    gv = """\
digraph "story" {
  graph [
    fontname = "TeXGyre-Pagella",
    fontsize = 12
  ];
"""
    for node in nodes:

        if "status" not in node_properties[node]:
            color = "gray"
        elif node_properties[node]["status"] == "uninitialized":
            color = "red"
        elif node_properties[node]["status"] == "polished":
            color = "green"
        else:
            color = "yellow"

        gvattrs = [
            'color = {}'.format(color),
        ]

        if error and node == lasttarget:
            shape = "diamond"
        elif "type" not in node_properties[node]:
            shape = "polygon"
        elif node_properties[node]["type"] == "event":
            shape = "box"
        elif node_properties[node]["type"] == "choice":
            shape = "oval"
        elif node_properties[node]["type"] == "ending":
            shape = "invtriangle"
        gvattrs.append('shape = {}'.format(shape))

        if "setup" in node_properties[node]:
            gvattrs.append('label = "s:{}"'.format(
                node_properties[node]["setup"]))
        gv += '  "{}" [{}];\n'.format(node, ', '.join(gvattrs))

    for src in links:
        if src not in nodes:
            continue
        for opt in [o for o in links[src] if o != "actions"]:
            dst = links[src][opt]
            if dst not in nodes:
                continue
            if "actions" in links[src] and opt in links[src]["actions"]:
                act = links[src]["actions"][opt]
            else:
                act = "unknown"
            linkattrs = ['label = "{}"'.format(act)]
            if (node_properties[src].get("vignette")
                    and (node_properties[src].get("vignette")
                         == node_properties[dst].get("vignette"))):
                linkattrs.append('style = bold')
            gvattrs = ''
            if linkattrs:
                gvattrs = ' [{}]'.format(', '.join(linkattrs))
            gv += '  "{}" -> "{}"{};\n'.format(src, dst, gvattrs)
    gv += "}"
    with open(VIZ_GV, 'w') as fout:
        fout.write(gv)
    subprocess.call(VIZ_EXE + [VIZ_GV, "-Tsvg", "-o", VIZ_SVG])