예제 #1
0
 public MoveModel newMove(MoveStats stats, bool right)
 {
     //foreach (MoveModel moveModel in moves) if (moveModel.Stats.Equals(stats)) return null;
     MoveModel move = new MoveModel(stats, right, playerIndex);
     moves.Add(move);
     return move;
 }
예제 #2
0
        public MoveModel newMove(MoveStats stats, bool right)
        {
            //foreach (MoveModel moveModel in moves) if (moveModel.Stats.Equals(stats)) return null;
            MoveModel move = new MoveModel(stats, right, playerIndex);

            moves.Add(move);
            return(move);
        }
예제 #3
0
        /// <summary>
        /// Returns the move found to have highest win-rate after performing, in parallel, the specified number of Monte-Carlo simulations on the input game.
        /// </summary>
        /// <param name="game">The current game.</param>
        /// <param name="simulations">The number of simulations to perform.</param>
        public static TMove ParallelSearch(TGame game, int simulations)
        {
            TPlayer      aiPlayer   = game.CurrentPlayer;
            List <TMove> legalMoves = game.GetLegalMoves();
            int          count      = legalMoves.Count;

            MoveStats[] moveStats = new MoveStats[count];

            ParallelNET35.Parallel.For(0, simulations,

                                       () => { return(ThreadLocalRandom.NewRandom()); },

                                       (i, loop, localRandom) =>
            {
                int moveIndex = localRandom.Next(0, count);
                TGame copy    = game.DeepCopy();
                copy.DoMove(legalMoves[moveIndex]);

                while (!copy.IsGameOver())
                {
                    copy.DoMove(
                        copy.GetLegalMoves().RandomItem(localRandom));
                }

                Interlocked.Add(ref moveStats[moveIndex].executions, 1);
                if (copy.IsWinner(aiPlayer))
                {
                    Interlocked.Add(ref moveStats[moveIndex].victories, 1);
                }

                return(localRandom);
            },

                                       (x) => { }

                                       );


            int    bestMoveFound  = 0;
            double bestScoreFound = 0f;

            for (int i = 0; i < count; i++)
            {
                double score = moveStats[i].Score();
                if (score > bestScoreFound)
                {
                    bestScoreFound = score;
                    bestMoveFound  = i;
                }
            }

            //for (int i = 0; i < legalMoves.Count; i++)
            //    Console.WriteLine("Move " + legalMoves[i] + " has " + moveStats[i].victories + " victories / " + moveStats[i].executions + " executions.");

            return(legalMoves[bestMoveFound]);
        }
예제 #4
0
 public MoveModel(MoveStats stats, bool right, int playerIndex)
 {
     Stats = stats;
     attackTimeLeft = stats.Duration;
     chargeTime = 0;
     Started = false;
     Ended = false;
     Xdirection = right ? new Vector2(1, 1) : new Vector2(-1, 1);
     PlayerIndexes = new List<int>();
     PlayerIndexes.Add(playerIndex);
 }
예제 #5
0
        public void StateChanged(CharacterState oldState, CharacterState newState, MoveStats move)
        {
            switch (newState)
            {
                case CharacterState.none:
                    if (oldState == CharacterState.running) AddAnimation(0, 2, true);
                    else if (oldState == CharacterState.falling || oldState == CharacterState.jumping)
                    {
                        StartAnimation(stats.ani_landStart, stats.ani_landEnd, false);
                        AddAnimation(stats.ani_noneStart, stats.ani_noneEnd, true);
                    }
                    else StartAnimation(stats.ani_noneStart, stats.ani_noneEnd, true);
                    break;
                case CharacterState.running:
                    if(oldState == CharacterState.falling || oldState == CharacterState.jumping)
                    {
                        StartAnimation(stats.ani_landStart, stats.ani_landEnd, false);
                        AddAnimation(stats.ani_runStart, stats.ani_runEnd, true);
                    }
                    else StartAnimation(stats.ani_runStart, stats.ani_runEnd, true);
                    break;
                case CharacterState.braking:
                    if(oldState == CharacterState.falling || oldState == CharacterState.jumping)
                    {
                        StartAnimation(stats.ani_landStart, stats.ani_landEnd, false);
                        AddAnimation(stats.ani_brake, stats.ani_brake, true);
                    }
                    else StartAnimation(stats.ani_brake, stats.ani_brake, true);
                    break;
                case CharacterState.jumping:
                    StartAnimation(stats.ani_jumpStart, stats.ani_jumpEnd, false);
                    AddAnimation(stats.ani_fallStart, stats.ani_fallEnd, true);
                    break;
                case CharacterState.falling:
                    StartAnimation(stats.ani_fallStart, stats.ani_fallEnd, true);
                    break;
                case CharacterState.takingHit:
                    StartAnimation(stats.ani_takeHitStart, stats.ani_takeHitEnd, true);
                    break;
                case CharacterState.attacking:
                    StartAnimation(move.AniFrom, move.AniTo, false, move.Duration);
                    break;
                case CharacterState.shielding:
                    break;
                case CharacterState.charging:
                    StartAnimation(move.AniStartChargeFrom, move.AniStartChargeTo, false, move.MinWait);
                    AddAnimation(move.AniChargeLoopFrom, move.AniChargeLoopTo, true);
                    break;
                default:
                    break;
            }

            if (newState != CharacterState.running) fps = Constants.FPS;
        }
예제 #6
0
            //add new move to GameTree
            internal MoveStats RegisterGameResult(BoardMove mv, bool win) // GameBoard brd, GameMove mv, bool win)
            {
                Tuple <GameMove, MoveStats> res = Tuple.Create(null as GameMove, null as MoveStats);

                if (tree.ContainsKey(mv.Board))
                {
                    //do we have this move registered for this board?
                    var brdMoves = tree[mv.Board];
                    if (brdMoves.ContainsKey(mv.Move.Position))
                    {
                        res = brdMoves[mv.Move.Position];
                        //register win
                        res.Item2.RegisterResult(win);
                        //store modified stats into moves dictionary
                        brdMoves[mv.Move.Position] = res;
                        //store modified move dictionary into boards disctionary
                        tree[mv.Board] = brdMoves;
                    }
                    else
                    {
                        //no make new entry for this board and register win
                        res = Tuple.Create(mv.Move, new MoveStats());
                        res.Item2.RegisterResult(win);
                        //add stats to moves dictionary
                        brdMoves.Add(mv.Move.Position, res);
                        //add gamemove to board dictionary
                        tree[mv.Board] = brdMoves;
                    }

                    //res.Parent = this;
                }
                else
                {
                    //board not found create new board
                    //create new move stat
                    var mvStat = new MoveStats();
                    mvStat.RegisterResult(win);
                    //create board entry
                    //add to board dictionary
                    var entry = new Dictionary <int, Tuple <GameMove, MoveStats> >()
                    {
                        { mv.Move.Position, Tuple.Create(mv.Move, mvStat) }
                    };

                    tree.Add(mv.Board, entry);
                }

                return(res.Item2);
            }
예제 #7
0
    private void Start()
    {
        body = GetComponent <Rigidbody>();

        switch (defaultMovePlane)
        {
        case MovementPlane.XY:
            rotationAxis = Vector3.forward;
            break;

        case MovementPlane.XZ:
            rotationAxis = Vector3.up;
            break;
        }

        stats = defaultStats;
    }
예제 #8
0
        /// <summary>
        /// Returns the move found to have highest win-rate after performing the specified number of Monte-Carlo simulations on the input game.
        /// </summary>
        /// <param name="game">The current game.</param>
        /// <param name="simulations">The number of simulations to perform.</param>
        public static TMove Search(TGame game, int simulations)
        {
            // hoist all declarations out of the main loop for performance
            TPlayer      aiPlayer   = game.CurrentPlayer;
            List <TMove> legalMoves = game.GetLegalMoves();
            int          count      = legalMoves.Count;

            MoveStats[] moveStats = new MoveStats[count];
            int         moveIndex;
            TGame       copy;
            Random      rng = new Random();

            for (int i = 0; i < simulations; i++)
            {
                moveIndex = rng.Next(0, count);
                copy      = game.DeepCopy();
                copy.DoMove(legalMoves[moveIndex]);

                while (!copy.IsGameOver())
                {
                    copy.DoMove(
                        copy.GetLegalMoves().RandomItem(rng));
                }

                moveStats[moveIndex].executions++;
                if (copy.IsWinner(aiPlayer))
                {
                    moveStats[moveIndex].victories++;
                }
            }

            int    bestMoveFound  = 0;
            double bestScoreFound = 0f;

            for (int i = 0; i < count; i++)
            {
                double score = moveStats[i].Score();
                if (score > bestScoreFound)
                {
                    bestScoreFound = score;
                    bestMoveFound  = i;
                }
            }

            return(legalMoves[bestMoveFound]);
        }
예제 #9
0
    private void ApplyMove(MoveStats stats, float deltaTime)
    {
        float currentXVelocity = Rigidbody.velocity.x;
        float targetXVelocity  = deltaXQueue * stats.MaxVelocity;
        float newVelocity      = currentXVelocity;

        if (currentXVelocity < targetXVelocity)
        {
            newVelocity = Mathf.Min(currentXVelocity + stats.Acceleration * deltaTime, targetXVelocity);
        }
        else if (currentXVelocity > targetXVelocity)
        {
            newVelocity = Mathf.Max(currentXVelocity - stats.Acceleration * deltaTime, targetXVelocity);
        }
        Rigidbody.velocity = new Vector2(newVelocity, Rigidbody.velocity.y);
        deltaXQueue        = 0;
    }
        void IJobChunk.Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            NativeArray <MoveStats>   _moveStatsArray   = chunk.GetNativeArray(_moveStatsHandle);
            NativeArray <Translation> _translationArray = chunk.GetNativeArray(_translationHandle);

            for (int i = 0; i < chunk.ChunkEntityCount; i++)
            {
                if (_moveStatsArray[i]._canMove == 1)
                {
                    _moveStatsArray[i] = new MoveStats
                    {
                        _canMove     = _moveStatsArray[i]._canMove,
                        _newPosition = _translationArray[i].Value + (_direction * _dt * _moveStatsArray[i]._moveSpeed),
                        _moveSpeed   = _moveStatsArray[i]._moveSpeed
                    };
                }
            }
        }
예제 #11
0
    private void Start()
    {
        body = GetComponent <Rigidbody>();
        anim = GetComponent <PlayerAnimator>();

        stats = defaultStats;

        switch (plane)
        {
        case MovementPlane.XY:
            horizontalAxis = Vector3.right;
            verticalAxis   = Vector3.up;
            break;

        case MovementPlane.XZ:
            horizontalAxis = Vector3.right;
            verticalAxis   = Vector3.forward;
            break;
        }
        rotationAxis = Vector3.Cross(horizontalAxis, verticalAxis);
    }
예제 #12
0
 public void ResetMoveStats()
 {
     stats = defaultStats;
 }
예제 #13
0
 public void SetMoveStats(MoveStats newStats)
 {
     stats = newStats;
 }
예제 #14
0
        public void StateChanged(CharacterState oldState, CharacterState newState, MoveStats move)
        {
            switch (newState)
            {
            case CharacterState.none:
                if (oldState == CharacterState.running)
                {
                    AddAnimation(0, 2, true);
                }
                else if (oldState == CharacterState.falling || oldState == CharacterState.jumping)
                {
                    StartAnimation(stats.ani_landStart, stats.ani_landEnd, false);
                    AddAnimation(stats.ani_noneStart, stats.ani_noneEnd, true);
                }
                else
                {
                    StartAnimation(stats.ani_noneStart, stats.ani_noneEnd, true);
                }
                break;

            case CharacterState.running:
                if (oldState == CharacterState.falling || oldState == CharacterState.jumping)
                {
                    StartAnimation(stats.ani_landStart, stats.ani_landEnd, false);
                    AddAnimation(stats.ani_runStart, stats.ani_runEnd, true);
                }
                else
                {
                    StartAnimation(stats.ani_runStart, stats.ani_runEnd, true);
                }
                break;

            case CharacterState.braking:
                if (oldState == CharacterState.falling || oldState == CharacterState.jumping)
                {
                    StartAnimation(stats.ani_landStart, stats.ani_landEnd, false);
                    AddAnimation(stats.ani_brake, stats.ani_brake, true);
                }
                else
                {
                    StartAnimation(stats.ani_brake, stats.ani_brake, true);
                }
                break;

            case CharacterState.jumping:
                StartAnimation(stats.ani_jumpStart, stats.ani_jumpEnd, false);
                AddAnimation(stats.ani_fallStart, stats.ani_fallEnd, true);
                break;

            case CharacterState.falling:
                StartAnimation(stats.ani_fallStart, stats.ani_fallEnd, true);
                break;

            case CharacterState.takingHit:
                StartAnimation(stats.ani_takeHitStart, stats.ani_takeHitEnd, true);
                break;

            case CharacterState.attacking:
                StartAnimation(move.AniFrom, move.AniTo, false, move.Duration);
                break;

            case CharacterState.shielding:
                break;

            case CharacterState.charging:
                StartAnimation(move.AniStartChargeFrom, move.AniStartChargeTo, false, move.MinWait);
                AddAnimation(move.AniChargeLoopFrom, move.AniChargeLoopTo, true);
                break;

            default:
                break;
            }

            if (newState != CharacterState.running)
            {
                fps = Constants.FPS;
            }
        }
예제 #15
0
        private bool Collision(Fixture chara, Fixture obj, Contact list)
        {
            bool returnValue = false;

            if (model.state == CharacterState.attacking &&
                (obj.CollisionCategories != Category.Cat20 || !((MoveModel)obj.Body.UserData).PlayerIndexes.Contains(model.playerIndex)) &&
                currentMove.Stats.Type == MoveType.Body &&
                (currentMove.Stats.StopAtHit || obj.CollisionCategories != Category.Cat11) &&
                currentMove.attackTimeLeft <= currentMove.Stats.Duration - currentMove.Stats.BodyStart)
            {
                moves.EndMove(currentMove);
                moves.RemoveMove(currentMove);
                view.Rotation          = 0;
                view.BoundBox.Rotation = 0;
                model.attackMode       = false;
                if ((obj.CollisionCategories == Category.Cat9 || obj.CollisionCategories == Category.Cat10) && chara.Body.Position.Y + view.size.Y / 2 <= obj.Body.Position.Y - (float)obj.Body.UserData / 2)
                {
                    model.inAir = false;
                    if (obj.CollisionCategories == Category.Cat10)
                    {
                        model.onSoftBox = true;
                    }
                    model.jumpsLeft = 3;
                }

                NaturalState();
                returnValue = true;
            }
            else if ((obj.CollisionCategories == Category.Cat9 || obj.CollisionCategories == Category.Cat10) &&
                     (chara.Body.Position.Y + view.size.Y / 2 <= obj.Body.Position.Y - (float)obj.Body.UserData / 2 && view.VelocityY >= -0.001))
            {
                model.inAir = false;
                if (obj.CollisionCategories == Category.Cat10)
                {
                    model.onSoftBox = true;
                }
                NaturalState();
                model.jumpsLeft = 3;
                returnValue     = true;
            }
            else if (obj.CollisionCategories == Category.Cat9)
            {
                returnValue = true;
            }
            else if (obj.CollisionCategories == Category.Cat20)
            {
                MoveModel move = (MoveModel)obj.Body.UserData;
                if (!move.PlayerIndexes.Contains(model.playerIndex) && !model.invounerable)
                {
                    move.PlayerIndexes.Add(model.playerIndex);

                    MoveStats stats = move.Stats;
                    float     ratio = 0;
                    if (stats.Type == MoveType.Charge && move.chargeTime < stats.MaxWait)
                    {
                        ratio = move.chargeTime / stats.MaxWait;
                    }
                    else
                    {
                        ratio = 1;
                    }
                    Vector2 power  = ratio * stats.Power;
                    int     damage = (int)ratio * stats.Damage;

                    view.Velocity = move.Xdirection * power * (1 + model.damagePoints / 100) * (100 / model.weight);
                    if (Math.Abs(view.VelocityY) == 0)
                    {
                        view.VelocityY = -1;
                    }
                    model.damagePoints += damage;
                    model.setState(CharacterState.takingHit);

                    if (OnHit != null)
                    {
                        OnHit.Invoke(ConvertUnits.ToDisplayUnits(obj.Body.Position), damage, model.damagePoints, move.PlayerIndexes.First(), model.playerIndex, stats.hitSound);
                    }

                    //if (move.Adjustable && ((AdjustableMove)move).StopAtHit) move.attackTimeLeft = 0;
                }
            }
            else if (obj.CollisionCategories == Category.Cat7 || obj.CollisionCategories == Category.Cat8)
            {
                OnCharacterDeath.Invoke(this, obj.CollisionCategories == Category.Cat7);
            }

            return(returnValue);
        }
예제 #16
0
        public void setState(CharacterState newState, MoveStats move = null)
        {
            if (newState == CharacterState.attacking || newState == CharacterState.charging || newState == CharacterState.shielding)
            {
                if(newState != CharacterState.shielding && move == null) throw new NotImplementedException();
                attackMode = true;
            }
            else attackMode = false;

            if(newState == CharacterState.jumping || newState == CharacterState.falling) inAir = true;

            if (newState != state)
            {
                view.StateChanged(state, newState, move);
                state = newState;
            }
        }