Skip to content

Commit

Permalink
Merge branch 'lists'
Browse files Browse the repository at this point in the history
  • Loading branch information
joethephish committed Jan 10, 2017
2 parents 4a05d62 + 4379faa commit 2afb50d
Show file tree
Hide file tree
Showing 27 changed files with 2,797 additions and 107 deletions.
1,087 changes: 1,087 additions & 0 deletions Documentation/WritingWithInk.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions ink-engine-runtime/CallStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ public void SetTemporaryVariable(string name, Runtime.Object value, bool declare
throw new StoryException ("Could not find temporary variable to set: " + name);
}

Runtime.Object oldValue;
if( contextElement.temporaryVariables.TryGetValue(name, out oldValue) )
ListValue.RetainListOriginsForAssignment (oldValue, value);

contextElement.temporaryVariables [name] = value;
}

Expand Down
11 changes: 11 additions & 0 deletions ink-engine-runtime/ControlCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public enum CommandType
StartThread,
Done,
End,
ListFromInt,
ListRange,
//----
TOTAL_VALUES
}
Expand Down Expand Up @@ -132,6 +134,15 @@ public static ControlCommand SeedRandom ()
return new ControlCommand (CommandType.End);
}

public static ControlCommand ListFromInt () {
return new ControlCommand (CommandType.ListFromInt);
}

public static ControlCommand ListRange ()
{
return new ControlCommand (CommandType.ListRange);
}

public override string ToString ()
{
return commandType.ToString();
Expand Down
98 changes: 96 additions & 2 deletions ink-engine-runtime/JsonSerialisation.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Ink.Runtime
{
Expand Down Expand Up @@ -157,6 +158,10 @@ public static Runtime.Object JTokenToRuntimeObject(object token)
}

// Native functions
// "^" conflicts with the way to identify strings, so now
// we know it's not a string, we can convert back to the proper
// symbol for the operator.
if (str == "L^") str = "^";
if( NativeFunctionCall.CallExistsWithName(str) )
return NativeFunctionCall.CallWithName (str);

Expand Down Expand Up @@ -278,6 +283,22 @@ public static Runtime.Object JTokenToRuntimeObject(object token)
return new Runtime.Tag ((string)propValue);
}

// List value
if (obj.TryGetValue ("list", out propValue)) {
var listContent = (Dictionary<string, object>)propValue;
var rawList = new RawList ();
if (obj.TryGetValue ("origins", out propValue)) {
var namesAsObjs = (List<object>)propValue;
rawList.SetInitialOriginNames (namesAsObjs.Cast<string>().ToList());
}
foreach (var nameToVal in listContent) {
var item = new RawListItem (nameToVal.Key);
var val = (int)nameToVal.Value;
rawList.Add (item, val);
}
return new ListValue (rawList);
}

// Used when serialising save state only
if (obj ["originalChoicePath"] != null)
return JObjectToChoice (obj);
Expand Down Expand Up @@ -358,6 +379,11 @@ public static object RuntimeObjectToJToken(Runtime.Object obj)
return "^" + strVal.value;
}

var listVal = obj as ListValue;
if (listVal) {
return InkListToJObject (listVal);
}

var divTargetVal = obj as DivertTargetValue;
if (divTargetVal) {
var divTargetJsonObj = new Dictionary<string, object> ();
Expand Down Expand Up @@ -389,8 +415,14 @@ public static object RuntimeObjectToJToken(Runtime.Object obj)
}

var nativeFunc = obj as Runtime.NativeFunctionCall;
if (nativeFunc)
return nativeFunc.name;
if (nativeFunc) {
var name = nativeFunc.name;

// Avoid collision with ^ used to indicate a string
if (name == "^") name = "L^";
return name;
}


// Variable reference
var varRef = obj as VariableReference;
Expand Down Expand Up @@ -545,6 +577,66 @@ static Choice JObjectToChoice(Dictionary<string, object> jObj)
return jObj;
}

static Dictionary<string, object> InkListToJObject (ListValue listVal)
{
var rawList = listVal.value;

var dict = new Dictionary<string, object> ();

var content = new Dictionary<string, object> ();

foreach (var itemAndValue in rawList) {
var item = itemAndValue.Key;
int val = itemAndValue.Value;
content [item.ToString ()] = val;
}

dict ["list"] = content;

if (rawList.Count == 0 && rawList.originNames != null && rawList.originNames.Count > 0) {
dict ["origins"] = rawList.originNames.Cast<object> ().ToList ();
}

return dict;
}

public static Dictionary<string, object> ListDefinitionsToJToken (ListDefinitionsOrigin origin)
{
var result = new Dictionary<string, object> ();
foreach (ListDefinition def in origin.lists) {
var listDefJson = new Dictionary<string, object> ();
foreach (var itemToVal in def.items) {
RawListItem item = itemToVal.Key;
int val = itemToVal.Value;
listDefJson [item.itemName] = (object)val;
}
result [def.name] = listDefJson;
}
return result;
}

public static ListDefinitionsOrigin JTokenToListDefinitions (object obj)
{
var defsObj = (Dictionary<string, object>)obj;

var allDefs = new List<ListDefinition> ();

foreach (var kv in defsObj) {
var name = (string) kv.Key;
var listDefJson = (Dictionary<string, object>)kv.Value;

// Cast (string, object) to (string, int) for items
var items = new Dictionary<string, int> ();
foreach (var nameValue in listDefJson)
items.Add(nameValue.Key, (int)nameValue.Value);

var def = new ListDefinition (name, items);
allDefs.Add (def);
}

return new ListDefinitionsOrigin (allDefs);
}

static Json()
{
_controlCommandNames = new string[(int)ControlCommand.CommandType.TOTAL_VALUES];
Expand All @@ -568,6 +660,8 @@ static Json()
_controlCommandNames [(int)ControlCommand.CommandType.StartThread] = "thread";
_controlCommandNames [(int)ControlCommand.CommandType.Done] = "done";
_controlCommandNames [(int)ControlCommand.CommandType.End] = "end";
_controlCommandNames [(int)ControlCommand.CommandType.ListFromInt] = "listInt";
_controlCommandNames [(int)ControlCommand.CommandType.ListRange] = "range";

for (int i = 0; i < (int)ControlCommand.CommandType.TOTAL_VALUES; ++i) {
if (_controlCommandNames [i] == null)
Expand Down
77 changes: 77 additions & 0 deletions ink-engine-runtime/ListDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System.Collections.Generic;

namespace Ink.Runtime
{
internal class ListDefinition
{
public string name { get { return _name; } }

public Dictionary<RawListItem, int> items {
get {
if (_items == null) {
_items = new Dictionary<RawListItem, int> ();
foreach (var itemNameAndValue in _itemNameToValues) {
var item = new RawListItem (name, itemNameAndValue.Key);
_items [item] = itemNameAndValue.Value;
}
}
return _items;
}
}
Dictionary<RawListItem, int> _items;

public int ValueForItem (RawListItem item)
{
int intVal;
if (_itemNameToValues.TryGetValue (item.itemName, out intVal))
return intVal;
else
return 0;
}

public bool ContainsItem (RawListItem item)
{
if (item.originName != name) return false;

return _itemNameToValues.ContainsKey (item.itemName);
}

public bool TryGetItemWithValue (int val, out RawListItem item)
{
foreach (var namedItem in _itemNameToValues) {
if (namedItem.Value == val) {
item = new RawListItem (name, namedItem.Key);
return true;
}
}

item = RawListItem.Null;
return false;
}

public ListValue ListRange (int min, int max)
{
var rawList = new RawList ();
foreach (var nameAndValue in _itemNameToValues) {
if (nameAndValue.Value >= min && nameAndValue.Value <= max) {
var item = new RawListItem (name, nameAndValue.Key);
rawList [item] = nameAndValue.Value;
}
}
return new ListValue(rawList);
}

public ListDefinition (string name, Dictionary<string, int> items)
{
_name = name;
_itemNameToValues = items;
}

string _name;

// The main representation should be simple item names rather than a RawListItem,
// since we mainly want to access items based on their simple name, since that's
// how they'll be most commonly requested from ink.
Dictionary<string, int> _itemNameToValues;
}
}
62 changes: 62 additions & 0 deletions ink-engine-runtime/ListDefinitionsOrigin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Collections.Generic;

namespace Ink.Runtime
{
internal class ListDefinitionsOrigin
{
public List<Runtime.ListDefinition> lists {
get {
var listOfLists = new List<Runtime.ListDefinition> ();
foreach (var namedList in _lists) {
listOfLists.Add (namedList.Value);
}
return listOfLists;
}
}

public ListDefinitionsOrigin (List<Runtime.ListDefinition> lists)
{
_lists = new Dictionary<string, ListDefinition> ();
foreach (var list in lists) {
_lists [list.name] = list;
}
}

public bool TryGetDefinition (string name, out ListDefinition def)
{
return _lists.TryGetValue (name, out def);
}

public ListValue FindSingleItemListWithName (string name)
{
RawListItem item = RawListItem.Null;
ListDefinition list = null;

// Name could be in the form itemName or listName.itemName
var nameParts = name.Split ('.');
if (nameParts.Length == 2) {
item = new RawListItem (nameParts [0], nameParts [1]);
TryGetDefinition (item.originName, out list);
} else {
foreach (var namedList in _lists) {
var listWithItem = namedList.Value;
item = new RawListItem (namedList.Key, name);
if (listWithItem.ContainsItem (item)) {
list = listWithItem;
break;
}
}
}

// Manager to get the list that contains the given item?
if (list != null) {
int itemValue = list.ValueForItem (item);
return new ListValue (item, itemValue);
}

return null;
}

Dictionary<string, Runtime.ListDefinition> _lists;
}
}

0 comments on commit 2afb50d

Please sign in to comment.