Beispiel #1
0
 private void OnInventoryChanged(Ink.Runtime.InkList newList)
 {
     SetupInventoryItems(newList.all);
     list = newList;
     if (logInventoryChanges)
     {
         Debug.Log($"Inventory update: {newList}");
     }
     InventoryChanged?.Invoke(items.Where(i => newList.Contains(i.value)).ToArray());
 }
 /// <summary>
 /// Returns true if the current list contains all the items that are in the list that
 /// is passed in. Equivalent to calling (list1 ? list2) in ink.
 /// </summary>
 /// <param name="otherList">Other list.</param>
 public bool Contains(InkList otherList)
 {
     foreach (var kv in otherList)
     {
         if (!this.ContainsKey(kv.Key))
         {
             return(false);
         }
     }
     return(true);
 }
Beispiel #3
0
 /// <summary>
 /// Fast test for the existence of any intersection between the current list and another
 /// </summary>
 public bool HasIntersection(InkList otherList)
 {
     foreach (var kv in this)
     {
         if (otherList.ContainsKey(kv.Key))
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #4
0
        /// <summary>
        /// Returns true if the item values in the current list overlap or are all greater than
        /// the item values in the passed in list. None of the item values in the current list must
        /// fall below the item values in the passed in list. Equivalent to (list1 >= list2) in ink,
        /// or LIST_MIN(list1) >= LIST_MIN(list2) &amp;&amp; LIST_MAX(list1) >= LIST_MAX(list2).
        /// </summary>
        public bool GreaterThanOrEquals(InkList otherList)
        {
            if (Count == 0)
            {
                return(false);
            }
            if (otherList.Count == 0)
            {
                return(true);
            }

            return(minItem.Value >= otherList.minItem.Value && maxItem.Value >= otherList.maxItem.Value);
        }
Beispiel #5
0
        /// <summary>
        /// Returns true if all the item values in the current list are less than all the
        /// item values in the passed in list. Equivalent to calling (list1 &lt; list2) in ink.
        /// </summary>
        public bool LessThan(InkList otherList)
        {
            if (otherList.Count == 0)
            {
                return(false);
            }
            if (Count == 0)
            {
                return(true);
            }

            return(maxItem.Value < otherList.minItem.Value);
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        /// <summary>
        /// Returns true if all the item values in the current list are greater than all the
        /// item values in the passed in list. Equivalent to calling (list1 > list2) in ink.
        /// </summary>
        public bool GreaterThan(InkList otherList)
        {
            if (Count == 0)
            {
                return(false);
            }
            if (otherList.Count == 0)
            {
                return(true);
            }

            // All greater
            return(minItem.Value > otherList.maxItem.Value);
        }
Beispiel #8
0
        /// <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);
        }
        public ListValue ListRange(int min, int max)
        {
            var rawList = new InkList();

            foreach (var nameAndValue in _itemNameToValues)
            {
                if (nameAndValue.Value >= min && nameAndValue.Value <= max)
                {
                    var item = new InkListItem(name, nameAndValue.Key);
                    rawList [item] = nameAndValue.Value;
                }
            }
            return(new ListValue(rawList));
        }
        /// <summary>
        /// Converts an integer value into a list containing an item from a given list
        /// </summary>

        public static InkList FromValue(InkList list, int itemVal)
        {
            if (list.origins == null || list.origins.Count == 0)
            {
                throw new System.Exception("LIST_GET_ITEM: No origin exists in list passed into InkList.FromValue");
            }
            var         origin = list.origins[0];
            InkListItem foundItem;

            if (origin.TryGetItemWithValue(itemVal, out foundItem))
            {
                return(new Ink.Runtime.InkList {
                    { foundItem, itemVal }
                });
            }
            throw new System.Exception("LIST_GET_ITEM: Item with value " + itemVal + " couldn't be found in list " + origin.name);
        }
Beispiel #11
0
        public static Value Create(object val)
        {
            // Implicitly lose precision from any doubles we get passed in
            if (val is double)
            {
                double doub = (double)val;
                val = (float)doub;
            }

            // Implicitly convert bools into ints
            if (val is bool)
            {
                bool b = (bool)val;
                val = (int)(b ? 1 : 0);
            }

            if (val is int || val is long)
            {
                return(new IntValue(Convert.ToInt32(val)));
            }
            else if (val is float || val is double)
            {
                return(new FloatValue(Convert.ToSingle(val)));
            }
            else if (val is string)
            {
                return(new StringValue((string)val));
            }
            else if (val is Path)
            {
                return(new DivertTargetValue((Path)val));
            }
            else if (val is InkList)
            {
                return(new ListValue((InkList)val));
            }
            else if (val is IDictionary <string, object> )
            {
                var list = new InkList(val as IDictionary <string, object>);
                return(new ListValue(list));
            }

            throw new ArgumentException($"Can't create Value from object: {val}");
        }
Beispiel #12
0
    public Godot.Object create_ink_list_with_origin(string single_origin_list_name)
    {
        if (story == null)
        {
            PushNullStoryError();
            return(null);
        }

        try
        {
            var inkList = new Ink.Runtime.InkList(single_origin_list_name, story);
            return(inkBridger.MakeGDInkList(inkList));
        }
        catch (Exception e)
        {
            HandleException(e);
            return(null);
        }
    }
Beispiel #13
0
        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));
        }
Beispiel #14
0
    public Godot.Object MakeGDInkList(Ink.Runtime.InkList list)
    {
        var inkListBase = new Godot.Collections.Dictionary <string, int>();

        foreach (KeyValuePair <Ink.Runtime.InkListItem, int> kv in list)
        {
            inkListBase.Add(MakeGDInkListItem(kv.Key).Call("serialized") as string, kv.Value);
        }

        object[] inkListParams = new object[] {
            inkListBase,
            list.originNames.ToArray(),
            MakeGDInkListOrigins(list.origins)
        };

        var inkList = (Godot.Object)InkList.New();

        inkList.Call("_init_from_csharp", inkListParams);

        return(inkList);
    }
Beispiel #15
0
    public Ink.Runtime.InkList MakeSharpInkList(Godot.Object list, Ink.Runtime.Story story)
    {
        if (!IsInkObjectOfType(list, "InkList"))
        {
            throw new ArgumentException("Expected a 'Godot.Object' of class 'InkList'");
        }

        var underlyingDictionary =
            (Godot.Collections.Dictionary <Godot.Object, int>)list.Get("_dictionary");
        var originNames = (Godot.Collections.Array <string>)list.Get("origin_names");

        var inkList = new Ink.Runtime.InkList();

        inkList.SetInitialOriginNames(originNames.ToList());

        foreach (string originName in originNames)
        {
            if (story.listDefinitions.TryListGetDefinition(originName, out Ink.Runtime.ListDefinition definition))
            {
                if (!inkList.origins.Contains(definition))
                {
                    inkList.origins.Add(definition);
                }
            }
            else
            {
                throw new Exception(
                          $"InkList origin could not be found in story when reconstructing list: {originName}"
                          );
            }
        }

        foreach (KeyValuePair <Godot.Object, int> kv in underlyingDictionary)
        {
            inkList[MakeSharpInkListItem(kv.Key)] = kv.Value;
        }

        return(inkList);
    }
Beispiel #16
0
 /// <summary>
 /// Create a new ink list that contains the same contents as another list.
 /// </summary>
 public InkList(InkList otherList) : base(otherList)
 {
     _originNames = otherList.originNames;
 }
Beispiel #17
0
        // ----------------------
        // 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);
        }