/// <summary> /// Returns a new list that is the intersection of the current list with another /// list that's passed in - i.e. a list of the items that are shared between the /// two other lists. Equivalent to calling (list1 ^ list2) in ink. /// </summary> public InkList Intersect(InkList otherList) { var intersection = new InkList(); foreach (var kv in this) { if (otherList.ContainsKey(kv.Key)) { intersection.Add(kv.Key, kv.Value); } } return(intersection); }
/// <summary> /// Returns a sublist with the elements given the minimum and maxmimum bounds. /// The bounds can either be ints which are indices into the entire (sorted) list, /// or they can be InkLists themselves. These are intended to be single-item lists so /// you can specify the upper and lower bounds. If you pass in multi-item lists, it'll /// use the minimum and maximum items in those lists respectively. /// WARNING: Calling this method requires a full sort of all the elements in the list. /// </summary> public InkList ListWithSubRange(object minBound, object maxBound) { if (this.Count == 0) { return(new InkList()); } var ordered = orderedItems; int minValue = 0; int maxValue = int.MaxValue; if (minBound is int) { minValue = (int)minBound; } else { if (minBound is InkList && ((InkList)minBound).Count > 0) { minValue = ((InkList)minBound).minItem.Value; } } if (maxBound is int) { maxValue = (int)maxBound; } else { if (minBound is InkList && ((InkList)minBound).Count > 0) { maxValue = ((InkList)maxBound).maxItem.Value; } } var subList = new InkList(); subList.SetInitialOriginNames(originNames); foreach (var item in ordered) { if (item.Value >= minValue && item.Value <= maxValue) { subList.Add(item.Key, item.Value); } } return(subList); }
Value CallListIncrementOperation(List <Object> listIntParams) { var listVal = (ListValue)listIntParams[0]; var intVal = (IntValue)listIntParams[1]; var resultRawList = new InkList(); foreach (var listItemWithValue in listVal.value) { var listItem = listItemWithValue.Key; var listItemValue = listItemWithValue.Value; // Find + or - operation var intOp = (BinaryOp <int>)_operationFuncs[ValueType.Int]; // Return value unknown until it's evaluated int targetInt = (int)intOp(listItemValue, intVal.value); // Find this item's origin (linear search should be ok, should be short haha) ListDefinition itemOrigin = null; foreach (var origin in listVal.value.origins) { if (origin.name == listItem.originName) { itemOrigin = origin; break; } } if (itemOrigin != null) { InkListItem incrementedItem; if (itemOrigin.TryGetItemWithValue(targetInt, out incrementedItem)) { resultRawList.Add(incrementedItem, targetInt); } } } return(new ListValue(resultRawList)); }
// ---------------------- // JSON ENCODING SCHEME // ---------------------- // // Glue: "<>", "G<", "G>" // // ControlCommand: "ev", "out", "/ev", "du" "pop", "->->", "~ret", "str", "/str", "nop", // "choiceCnt", "turns", "visit", "seq", "thread", "done", "end" // // NativeFunction: "+", "-", "/", "*", "%" "~", "==", ">", "<", ">=", "<=", "!=", "!"... etc // // Void: "void" // // Value: "^string value", "^^string value beginning with ^" // 5, 5.2 // {"^->": "path.target"} // {"^var": "varname", "ci": 0} // // Container: [...] // [..., // { // "subContainerName": ..., // "#f": 5, // flags // "#n": "containerOwnName" // only if not redundant // } // ] // // Divert: {"->": "path.target", "c": true } // {"->": "path.target", "var": true} // {"f()": "path.func"} // {"->t->": "path.tunnel"} // {"x()": "externalFuncName", "exArgs": 5} // // Var Assign: {"VAR=": "varName", "re": true} // reassignment // {"temp=": "varName"} // // Var ref: {"VAR?": "varName"} // {"CNT?": "stitch name"} // // ChoicePoint: {"*": pathString, // "flg": 18 } // // Choice: Nothing too clever, it's only used in the save state, // there's not likely to be many of them. // // Tag: {"#": "the tag text"} public static Runtime.Object JTokenToRuntimeObject(object token) { if (token is int || token is float) { return(Value.Create(token)); } if (token is string) { string str = (string)token; // String value char firstChar = str[0]; if (firstChar == '^') { return(new StringValue(str.Substring(1))); } else if (firstChar == '\n' && str.Length == 1) { return(new StringValue("\n")); } // Glue if (str == "<>") { return(new Runtime.Glue()); } // Control commands (would looking up in a hash set be faster?) for (int i = 0; i < _controlCommandNames.Length; ++i) { string cmdName = _controlCommandNames [i]; if (str == cmdName) { return(new Runtime.ControlCommand((ControlCommand.CommandType)i)); } } // 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)); } // Pop if (str == "->->") { return(Runtime.ControlCommand.PopTunnel()); } else if (str == "~ret") { return(Runtime.ControlCommand.PopFunction()); } // Void if (str == "void") { return(new Runtime.Void()); } } if (token is Dictionary <string, object> ) { var obj = (Dictionary <string, object>)token; object propValue; // Divert target value to path if (obj.TryGetValue("^->", out propValue)) { return(new DivertTargetValue(new Path((string)propValue))); } // VariablePointerValue if (obj.TryGetValue("^var", out propValue)) { var varPtr = new VariablePointerValue((string)propValue); if (obj.TryGetValue("ci", out propValue)) { varPtr.contextIndex = (int)propValue; } return(varPtr); } // Divert bool isDivert = false; bool pushesToStack = false; PushPopType divPushType = PushPopType.Function; bool external = false; if (obj.TryGetValue("->", out propValue)) { isDivert = true; } else if (obj.TryGetValue("f()", out propValue)) { isDivert = true; pushesToStack = true; divPushType = PushPopType.Function; } else if (obj.TryGetValue("->t->", out propValue)) { isDivert = true; pushesToStack = true; divPushType = PushPopType.Tunnel; } else if (obj.TryGetValue("x()", out propValue)) { isDivert = true; external = true; pushesToStack = false; divPushType = PushPopType.Function; } if (isDivert) { var divert = new Divert(); divert.pushesToStack = pushesToStack; divert.stackPushType = divPushType; divert.isExternal = external; string target = propValue.ToString(); if (obj.TryGetValue("var", out propValue)) { divert.variableDivertName = target; } else { divert.targetPathString = target; } divert.isConditional = obj.TryGetValue("c", out propValue); if (external) { if (obj.TryGetValue("exArgs", out propValue)) { divert.externalArgs = (int)propValue; } } return(divert); } // Choice if (obj.TryGetValue("*", out propValue)) { var choice = new ChoicePoint(); choice.pathStringOnChoice = propValue.ToString(); if (obj.TryGetValue("flg", out propValue)) { choice.flags = (int)propValue; } return(choice); } // Variable reference if (obj.TryGetValue("VAR?", out propValue)) { return(new VariableReference(propValue.ToString())); } else if (obj.TryGetValue("CNT?", out propValue)) { var readCountVarRef = new VariableReference(); readCountVarRef.pathStringForCount = propValue.ToString(); return(readCountVarRef); } // Variable assignment bool isVarAss = false; bool isGlobalVar = false; if (obj.TryGetValue("VAR=", out propValue)) { isVarAss = true; isGlobalVar = true; } else if (obj.TryGetValue("temp=", out propValue)) { isVarAss = true; isGlobalVar = false; } if (isVarAss) { var varName = propValue.ToString(); var isNewDecl = !obj.TryGetValue("re", out propValue); var varAss = new VariableAssignment(varName, isNewDecl); varAss.isGlobal = isGlobalVar; return(varAss); } // Tag if (obj.TryGetValue("#", out propValue)) { return(new Runtime.Tag((string)propValue)); } // List value if (obj.TryGetValue("list", out propValue)) { var listContent = (Dictionary <string, object>)propValue; var rawList = new InkList(); 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 InkListItem(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)); } } // Array is always a Runtime.Container if (token is List <object> ) { return(JArrayToContainer((List <object>)token)); } if (token == null) { return(null); } throw new System.Exception("Failed to convert token to runtime object: " + token); }