Example #1
0
    // Action Selection Thread, runs minimax on the current State to get the best Action. Also keeps a history and updates it based on the successes and fails of the AI
    protected static void selectAction(object arg)
    {
        Thread.Sleep(1000);         // Sleep to prevent race conditions on game load

        PaddleController __this = (PaddleController)arg;

        ActionStateMap.GameObjectState localState = new ActionStateMap.GameObjectState(Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, 0.0f);

        int maxHistory   = 1000;
        int historyIndex = 0;

        Tuple <ActionStateMap.GameAction, ActionStateMap.ActionState>[] previousActions = new Tuple <ActionStateMap.GameAction, ActionStateMap.ActionState> [maxHistory];

        while (!(__this.closeThreads.WaitOne(0)))
        {
            if (__this.currStateLock.WaitOne(1000))
            {
                localState.copy(__this.currState);
                __this.currStateLock.ReleaseMutex();

                ActionStateMap.GameObjectState currState = localState;
                Tuple <double, ActionStateMap.GameAction, ActionStateMap.ActionState> nextAction = __this.minimax(currState, 3);

                if (nextAction.Item2.getTag() != __this.currAction.getTag())
                {
                    __this.setNextAction(nextAction.Item2);
                }

                // Store history and adjust weight on success and fail
                previousActions[historyIndex] = Tuple.Create(nextAction.Item2, nextAction.Item3);
                historyIndex++;
                if (historyIndex >= maxHistory)
                {
                    bool success = __this.successEvent.WaitOne(0);
                    bool fail    = __this.failEvent.WaitOne(0);
                    __this.successEvent.Reset();
                    __this.failEvent.Reset();

                    historyIndex = 0;
                    for (int i = 0; i < maxHistory; i++)
                    {
                        if (success)
                        {
                            previousActions[i].Item2.updateActionProbabilities(previousActions[i].Item1, 1.0);
                        }
                        if (fail)
                        {
                            previousActions[i].Item2.updateActionProbabilities(previousActions[i].Item1, -1.0);
                        }
                    }
                }
            }
        }
    }
Example #2
0
    // Helper function for Minimax, traverses down a State's outecomes to get the best weight based on the predictions
    protected double minimax_helper(ActionStateMap.GameObjectState currState, int depth, bool maximizingPaddle)
    {
        if (maximizingPaddle)
        {
            List <Tuple <double, ActionStateMap.GameAction, ActionStateMap.ActionState> > bestActions = paddleStateMap.getBestActions(currState);
            if (depth == 0 || actionComplete.WaitOne(0) || minimaxTimeoutEvent.WaitOne(0))
            {
                return(bestActions[0].Item1);                // should be sorted from the getBestActions function
            }

            double bestAction = -1.0;
            foreach (var action in bestActions)
            {
                double actionResult = minimax_helper(action.Item2.predictNextState(currState), depth - 1, !maximizingPaddle);
                if (actionResult < 0.0)
                {
                    actionResult = action.Item1;
                }

                if (actionResult > bestAction)
                {
                    bestAction = actionResult;
                }
            }
            return(bestAction);
        }
        else         //maximizingPlayer
        {
            List <Tuple <double, ActionStateMap.GameAction, ActionStateMap.ActionState> > minActions = playerStateMap.getBestActions(currState);
            if (minActions.Count < 1)
            {
                return(-1.0);
            }

            if (depth == 0 || actionComplete.WaitOne(0) || minimaxTimeoutEvent.WaitOne(0))
            {
                return(minActions[0].Item1);                // should be sorted from the getBestActions function
            }

            double minAction = double.MaxValue;
            foreach (var action in minActions)
            {
                double actionResult = minimax_helper(action.Item2.predictNextState(currState), depth - 1, !maximizingPaddle);
                if (actionResult < minAction)
                {
                    minAction = actionResult;
                }
            }
            return(minAction);
        }
    }
Example #3
0
    // Update thread for the Player StateMap. Records movements of the Player
    protected static void updatePlayerMap(object arg)
    {
        Thread.Sleep(1000);         // Sleep to prevent race conditions on game load

        PaddleController __this = (PaddleController)arg;

        ActionStateMap.GameObjectState localState = new ActionStateMap.GameObjectState(Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, 0.0f);
        ActionStateMap.GameObjectState prevState  = new ActionStateMap.GameObjectState(Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, 0.0f);
        while (!(__this.closeThreads.WaitOne(0)))
        {
            if (__this.currStateLock.WaitOne(1000))
            {
                localState.copy(__this.currState);
                __this.currStateLock.ReleaseMutex();

                __this.playerStateMap.recordAction(prevState, localState);
                prevState.copy(localState);
                Thread.Sleep(100);
            }
        }
    }
Example #4
0
    // Update is called once per frame
    void Update()
    {
        // Start the Action Selection and Observation threads
        if (!threadsStarted)
        {
            actionSelectionThread.Start(this);
            playerObservationThread.Start(this);
            timeoutThread.Start(this);
            threadsStarted = true;
        }

        // Cap the velocity of the paddle
        Rigidbody rb = GetComponent <Rigidbody>();

        if (rb.velocity.magnitude > maximumVelocity)
        {
            rb.velocity = rb.velocity.normalized * maximumVelocity;
        }

        // Update the current state information
        controllerVel_R     = (controller_R.transform.position - lastControllerPos_R) / Time.deltaTime;
        lastControllerPos_R = controller_R.transform.position;
        if (currStateLock.WaitOne(0))
        {
            currState = new ActionStateMap.GameObjectState(controller_R.transform.position, controllerVel_R, transform.position, GetComponent <Rigidbody>().velocity, target.transform.position, Vector3.zero, Time.deltaTime);
            currStateLock.ReleaseMutex();
        }

        actionLock.WaitOne();         // Lock to prevent the Action from changing while executing
        if (currAction != null)
        {
            if (currAction.execute(gameObject, controller_R.gameObject, target))
            {
                actionComplete.Set();
            }
        }
        actionLock.ReleaseMutex();

        handleSuccessEvent();
    }
Example #5
0
    // Main minimax function. Finds the highest weighted Action the AI has access to
    protected Tuple <double, ActionStateMap.GameAction, ActionStateMap.ActionState> minimax(ActionStateMap.GameObjectState currState, int depth)
    {
        minimaxEndEvent.Reset();
        minimaxTimeoutEvent.Reset();


        List <Tuple <double, ActionStateMap.GameAction, ActionStateMap.ActionState> > bestActions = paddleStateMap.getBestActions(currState);

        if (depth == 0 || actionComplete.WaitOne(0) || minimaxTimeoutEvent.WaitOne(0))
        {
            return(bestActions[0]);            // should be sorted from the getBestActions function
        }

        Tuple <double, ActionStateMap.GameAction, ActionStateMap.ActionState> bestAction = Tuple.Create(Double.MinValue, bestActions[0].Item2, bestActions[0].Item3);

        foreach (var action in bestActions)
        {
            double actionResult = minimax_helper(action.Item2.predictNextState(currState), depth - 1, false);

            if (actionResult < 0.0)
            {
                actionResult = action.Item1;
            }

            if (actionResult > bestAction.Item1)
            {
                bestAction = Tuple.Create(actionResult, action.Item2, action.Item3);
            }
        }

        minimaxEndEvent.Set();
        return(bestAction);
    }