Exemple #1
0
        bool IsFlowCorrect(Spell.CompiledRune from, uint toDir)
        {
            var to = from.neighs[toDir];

            if (!IsFlowInterpretableRune(to.type))
            {
                return(false);
            }

            //Logger.Log(from.type + " " + to.type + " " + toDir);

            //Cross arrow is special
            if (to != null && to.type == RuneType.ArrowCross)
            {
                if (toDir == to.dir)
                {
                    isArrowCrossDirLeft = false;
                }
                else if (toDir == (to.dir + 5) % 6)
                {
                    isArrowCrossDirLeft = true;
                }
                else
                {
                    return(false);
                }
            }

            //TODO: cant enter "if" rune from two of its directions too...

            return(true);
        }
Exemple #2
0
        Spell.CompiledRune InterpretArrowSeq(Spell.CompiledRune r, bool onlyOneRune, bool setFlowDir)
        {
            do
            {
                if (!onlyOneRune)
                {
                    additionalInterpretedRunes.Add(r);
                }

                if (arrowsProcessed.Contains(r.relPos))
                {
                    arrowsProcessed.Clear();
                    return(null); //Cycle detected
                }
                arrowsProcessed.Add(r.relPos);

                uint fromDir = r.dir;

                uint dirChange;
                switch (r.type)
                {
                case RuneType.Arrow0: dirChange = 0; break;

                case RuneType.ArrowR60: dirChange = 1; break;

                case RuneType.ArrowR120: dirChange = 2; break;

                case RuneType.ArrowL120: dirChange = 4; break;

                case RuneType.ArrowL60: dirChange = 5; break;

                case RuneType.ArrowCross: dirChange = isArrowCrossDirLeft ? 5u : 0u; break;

                default: throw new Tools.AssertException();
                }

                uint toDir = (fromDir + dirChange) % 6;
                if (!IsFlowCorrect(r, toDir))
                {
                    arrowsProcessed.Clear();
                    return(null);
                }
                r = r.neighs[toDir];
                if (r == null)
                {
                    arrowsProcessed.Clear();
                    return(null);
                }
                if (!IsArrowRune(r.type))
                {
                    arrowsProcessed.Clear();
                    //if (setFlowDir)
                    //    flowDir = toDir;
                    return(r);
                }
            } while (!onlyOneRune);

            return(r);
        }
Exemple #3
0
        static bool IsArrowFrom(Spell.CompiledRune arrow, uint dir)
        {
            switch (arrow.type)
            {
            case RuneType.ArrowCross: return(arrow.dir == dir || arrow.dir == (dir + 1) % 6);

            default: return(arrow.dir == dir);
            }
        }
Exemple #4
0
 public Avatar(SpellExecuting spell, HexXY pos, uint dir, Spell.CompiledRune startRune, uint id)
 {
     this.spell    = spell;
     this.pos      = pos;
     this.dir      = dir;
     this.rune     = startRune;
     this.timeLeft = 0;
     this.id       = id;
 }
Exemple #5
0
 public float OnInterpret(Spell.CompiledRune rune, List <Spell.CompiledRune> additionalRunes)
 {
     if (Avatar.IsMovementCommandRune(rune.type))
     {
         return(movTime);
     }
     else
     {
         return(0);
     }
 }
Exemple #6
0
        void InterpretFlow()
        {
            uint forkCount = 0;

            Spell.CompiledRune nextRune = null;
            for (int i = 0; i < 6; i++)
            {
                var nrune = rune.neighs[i];
                if (nrune == null)
                {
                    continue;
                }

                bool isFlowArrow = IsArrowRune(nrune.type) || nrune.type == RuneType.If;
                if ((isFlowArrow && !IsArrowFrom(nrune, (uint)i)) || (!isFlowArrow && i != flowDir))
                {
                    continue;
                }
                if (i == flowDir && !IsFlowCorrect(rune, flowDir))
                {
                    continue;
                }

                if (forkCount == 0)
                {
                    nextRune = nrune;
                }
                else
                {
                    if (spell.caster.Mana >= avatarElement.ForkManaCost && avatarElement.CanAvatarFork())
                    {
                        spell.SpawnAvatar(nrune, this, pos, dir);
                    }
                    else
                    {
                        finishState = FinishedState.CantFork;
                        break;
                    }
                }

                ++forkCount;
            }

            if (forkCount == 0)
            {
                finishState = FinishedState.FlowFinished;
            }
            else
            {
                rune = nextRune;
            }
        }
Exemple #7
0
        public float OnInterpret(Spell.CompiledRune rune, List <Spell.CompiledRune> additionalRunes)
        {
            foreach (var litRune in litRunes)
            {
                litRune.isLit = false;
            }
            litRunes.Clear();

            var mainLitRune = avatar.spell.compiledSpell.GetRealRune(rune);

            litRunes.Add(mainLitRune);
            foreach (var arune in additionalRunes)
            {
                litRunes.Add(avatar.spell.compiledSpell.GetRealRune(arune));
            }

            foreach (var litRune in litRunes)
            {
                litRune.isLit = true;
            }

            float interTime;

            if (rune.type == RuneType.Wind)
            {
                interTime = 2;
            }
            else if (Avatar.IsArrowRune(rune.type))
            {
                interTime = 0.25f;
            }
            else if (Avatar.IsMovementCommandRune(rune.type))
            {
                interTime = movTime;
            }
            else
            {
                interTime = 1;
            }

            return(interTime);// * 0.1f;
        }
Exemple #8
0
        public void SpawnAvatar(Spell.CompiledRune rune, Avatar forkFrom, HexXY pos, uint dir)
        {
            Avatar av = new Avatar(this, pos, dir, rune, avatarLastID++);

            if (forkFrom != null)
            {
                caster.SpendMana(forkFrom.avatarElement.ForkManaCost);
                forkFrom.avatarElement.ForkTo(av);
                if (av.avatarElement is Entity)
                {
                    ((Entity)av.avatarElement).dir = av.dir;
                }
                av.avatarElement.OnSpawn();
            }

            avatars.Add(av);

            if (isLogging)
            {
                Logger.Log(av.id + " " + (av.avatarElement == null ? "[no element]" : av.avatarElement.GetType().Name) + " avatar spawned at " + pos);
            }
        }
Exemple #9
0
        public void Interpret()
        {
            if (rune == null)
            {
                finishState = FinishedState.FlowFinished;
                return;
            }

            if (SpellExecuting.isLogging)
            {
                Logger.Log(id + " " + (avatarElement == null ? "[no element]" : avatarElement.GetType().Name) + "> interpret " + rune.type + " at " + rune.relPos);
            }


            //This is written up here and not in the end for correct fork timing
            if (needsFlow && repeatCounter == 0)
            {
                InterpretFlow();
            }

            if (finishState != null)
            {
                return;
            }

            additionalInterpretedRunes.Clear();

            if (IsRepeatableByNumberRune(rune.type))
            {
                //Actually no need to reinterpret numbers, if repeatCounter > 0
                //but its needed for proper additionalInterpretedRunes highlight
                uint repCount = InterpretNearNumber();

                if (repeatCounter > 0)
                {
                    --repeatCounter;
                }
                else
                {
                    if (repCount > 0)
                    {
                        repeatCounter = repCount - 1;
                    }
                }
            }

            var currRune = rune;

            needsFlow = true;
            if (IsArrowRune(rune.type))
            {
                rune      = InterpretArrowSeq(rune, true, true);
                needsFlow = false;
            }
            else if (IsAvatarElementRune(rune.type))
            {
                InterpretChangeElement();
            }
            else if (IsMovementCommandRune(rune.type))
            {
                InterpretMovementCommand();
            }
            else if (rune.type == RuneType.If)
            {
                InterpretIf();
                needsFlow = false;
            }
            else
            {
                finishState = FinishedState.FlowFinished;
            }

            if (avatarElement != null)
            {
                timeLeft += avatarElement.OnInterpret(currRune, additionalInterpretedRunes);
            }
        }
Exemple #10
0
        void InterpretIf()
        {
            bool isTrue = false;

            //Checking only separate patterns
            //TODO: what if pattern is attached like this: (p) (if) (p) where (p)'s are connected elsewhere?
            //it will be evaluated twice!
            bool isPredAtZero = false, isPredAtPrev = false;

            for (int i = 0; i < 6; i++)
            {
                var nrune = rune.neighs[i];
                if (i != rune.dir && i != (rune.dir + 5) % 6 && nrune != null && IsArrowRune(nrune.type) && IsArrowFrom(nrune, (uint)i))
                {
                    //Find following arrows
                    nrune = InterpretArrowSeq(nrune, false, false);
                    if (nrune == null || !IsPredicateRune(nrune.type))
                    {
                        continue;
                    }

                    isTrue       = isTrue || InterpretPredicate(nrune); //using OR
                    isPredAtPrev = false;
                }
                else
                {
                    if (nrune == null || !IsPredicateRune(nrune.type))
                    {
                        isPredAtPrev = false;
                        continue;
                    }
                    if (isPredAtPrev || (i == 5 && isPredAtZero))
                    {
                        continue;
                    }

                    isTrue = isTrue || InterpretPredicate(nrune); //using OR

                    if (i == 0)
                    {
                        isPredAtZero = true;
                    }
                    isPredAtPrev = true;
                }
            }

            uint toDir;

            if (isTrue)
            {
                toDir = rune.dir;
            }
            else
            {
                toDir = (rune.dir + 5) % 6;
            }

            //flowDir = toDir;

            if (!IsFlowCorrect(rune, toDir))
            {
                rune = null;
            }
            else
            {
                rune = rune.neighs[toDir];
            }
        }
Exemple #11
0
        bool InterpretPredicate(Spell.CompiledRune predRune)
        {
            //Compute connected component and find avatar ref position
            Spell.CompiledRune avatarRefRune = null;

            blobFront.Enqueue(predRune);
            blobAll.Add(predRune);

            do
            {
                var c = blobFront.Dequeue();
                additionalInterpretedRunes.Add(c);
                if (c.type == RuneType.PredicateAvatarRef)
                {
                    if (avatarRefRune != null)
                    {
                        //Double avatar ref error
                        finishState = FinishedState.PredicateParseError;
                        return(false);
                    }
                    else
                    {
                        avatarRefRune = c;
                    }
                }

                foreach (var n in c.neighs)
                {
                    if (n == null || !IsPredicateRune(n.type) || blobAll.Contains(n))
                    {
                        continue;
                    }
                    blobFront.Enqueue(n);
                    blobAll.Add(n);
                }
            } while (blobFront.Count > 0);

            HexXY predRefPos;

            if (avatarRefRune != null)
            {
                predRefPos = avatarRefRune.relPos;
            }
            else
            {
                if (blobAll.Count > 1)
                {
                    //No avatar reference in predicate with more than one rune
                    finishState = FinishedState.PredicateParseError;
                    return(false);
                }
                else
                {
                    predRefPos = blobAll.First().relPos;
                }
            }

            //Check predicate
            bool isMatch = true;

            foreach (var prune in blobAll)
            {
                HexXY checkPos = prune.relPos - predRefPos;
                for (int i = 0; i < dir; i++)
                {
                    checkPos = checkPos.RotateRight(new HexXY(0, 0));
                }
                checkPos += this.pos;

                switch (prune.type)
                {
                case RuneType.PredicateTileEmpty:
                {
                    var blType = Level.S.GetPFBlockedMap(checkPos);
                    if (blType != WorldBlock.PFBlockType.Unblocked &&
                        blType != WorldBlock.PFBlockType.DynamicBlocked)
                    {
                        isMatch = false;
                    }
                    break;
                }

                case RuneType.PredicateTileWall:
                    if (Level.S.GetPFBlockedMap(checkPos) != WorldBlock.PFBlockType.EdgeBlocked &&
                        Level.S.GetPFBlockedMap(checkPos) != WorldBlock.PFBlockType.StaticBlocked &&
                        Level.S.GetPFBlockedMap(checkPos) != WorldBlock.PFBlockType.DoorBlocked)
                    {
                        isMatch = false;
                    }
                    break;

                case RuneType.PredicateTileMonster:
                    if (!Level.S.GetEntities(checkPos).Any(e => e is Mob))
                    {
                        isMatch = false;
                    }
                    break;
                }
                if (!isMatch)
                {
                    break;
                }
            }

            blobAll.Clear();

            if (SpellExecuting.isLogging)
            {
                Logger.Log("predicate at " + predRune.relPos + " is " + isMatch);
            }

            return(isMatch);
        }
Exemple #12
0
 public float OnInterpret(Spell.CompiledRune rune, List <Spell.CompiledRune> additionalRunes)
 {
     return(0);
 }