Пример #1
0
    /// <summary>
    /// Handles click events on this placement piece.
    /// </summary>
    public void OnMouseUpAsButton()
    {
        if (!placed)
        {
            // Piece shouldn't be null
            Debug.Assert(piece != null);

            // Selected this piece for placement
            if (turnHandler.GetCurrentPlayer().colour == piece.colour && turnHandler.state == TurnHandler.State.Placement)
            {
                turnHandler.PlacementPiece = this;
                turnHandler.UnhighlightPlacementTiles();

                RemovePlacementArrows();

                // Highlight the available placement tiles
                foreach (TileNode placementTile in turnHandler.PlacementTiles)
                {
                    if ((placementTile.edgeId + 3) % 6 == piece.direction && placementTile.tower == null)
                    {
                        placementTile.highlight();
                    }
                }
            }
        }
    }
Пример #2
0
    private void OnGenFinished(WorldMap world)
    {
        foreach (Vector2Int position in world.mapDict.Keys)
        {
            GameTile newGameTile = new GameTile();
            newGameTile.armies = 0;
            newGameTile.type   = world.mapDict[position];
            if (newGameTile.type != null)
            {
                gameMap.Add(position, newGameTile);
            }

            WorldRenderer.RenderWorld(gameMap);
        }


        remainingPlayers = new List <Player>(startingPlayers);
        PlayerSpawner.SpawnPlayers(remainingPlayers, 4);

        UpdateWorldRender();

        HUDManager.SetPlayerIndicator(TurnHandler.GetCurrentPlayer());

        OnSetupComplete?.Invoke();
        setupHasFinished = true;
    }
Пример #3
0
    public void RegisterClickOnTile(Vector2Int tilePos)
    {
        GameTile tile = GameController.instance.GetTile(tilePos);

        if (tile == null)
        {
            return;
        }
        // Verify that this is the current player's tile
        if (!firstTileSelected && tile.owner != TurnHandler.GetCurrentPlayer())
        {
            return;
        }

        if (!firstTileSelected)
        {
            if (tile == null)
            {
                return;
            }
            // Verify that this is the current player's tile
            if (tile.owner != TurnHandler.GetCurrentPlayer())
            {
                return;
            }

            FirstSelectedTile = new Vector3Int(tilePos.x, tilePos.y, 0);
            firstTileSelected = true;
            if (!placingArmies)
            {
                SelectionDisplayer.PlaceSelectionRing(new Vector2Int(FirstSelectedTile.x, FirstSelectedTile.y));
            }

            if (placingArmies)
            {
                if (TurnHandler.GetCurrentPlayer().armiesToPlace <= 0)
                {
                    placingArmies = false;
                }
                else
                {
                    GameController.instance.PlaceArmyIfAvailable(TurnHandler.GetCurrentPlayer(), new Vector2Int(tilePos.x, tilePos.y));
                    firstTileSelected  = false;
                    secondTileSelected = false;

                    if (TurnHandler.GetCurrentPlayer().armiesToPlace <= 0)
                    {
                        placingArmies = false;
                        HUDManager.HidePlaceArmyText();
                    }
                    else
                    {
                        HUDManager.ShowPlaceArmyText(TurnHandler.GetCurrentPlayer().armiesToPlace);
                    }
                    return;
                }
            }
        }
        else
        {
            SecondSelectedTile = new Vector3Int(tilePos.x, tilePos.y, 0);
            secondTileSelected = true;
        }

        if (firstTileSelected && secondTileSelected)
        {
            if (Mathf.Abs(FirstSelectedTile.x - SecondSelectedTile.x) == 1 &&
                Mathf.Abs(FirstSelectedTile.y - SecondSelectedTile.y) == 0 ||
                Mathf.Abs(FirstSelectedTile.x - SecondSelectedTile.x) == 0 &&
                Mathf.Abs(FirstSelectedTile.y - SecondSelectedTile.y) == 1)
            {
                if (GameController.instance.GetTile(new Vector2Int(FirstSelectedTile.x, FirstSelectedTile.y)).owner == TurnHandler.GetCurrentPlayer())
                {
                    if (GameController.instance.GetTile(new Vector2Int(SecondSelectedTile.x, SecondSelectedTile.y)).owner == TurnHandler.GetCurrentPlayer())
                    {
                        // Both tiles are the current player's
                        // Perform troop movement
                        GameController.instance.MoveArmies(new Vector2Int(FirstSelectedTile.x, FirstSelectedTile.y), new Vector2Int(SecondSelectedTile.x, SecondSelectedTile.y));
                    }
                    else if (GameController.instance.GetTile(new Vector2Int(SecondSelectedTile.x, SecondSelectedTile.y)).armies == 0)
                    {
                        // Move into empty territory
                        GameController.instance.MoveArmies(new Vector2Int(FirstSelectedTile.x, FirstSelectedTile.y), new Vector2Int(SecondSelectedTile.x, SecondSelectedTile.y));
                    }
                    else
                    {
                        // Player attacking enemy
                        GameController.instance.LaunchAttack(new Vector2Int(FirstSelectedTile.x, FirstSelectedTile.y), new Vector2Int(SecondSelectedTile.x, SecondSelectedTile.y));
                    }
                }
            }
            firstTileSelected  = false;
            secondTileSelected = false;
            SelectionDisplayer.ClearSelectionRing();
        }
    }
Пример #4
0
    static IEnumerator Train(int numGenerations, int modelsPerGen)
    {
        Dictionary <Vector2Int, GameTile> gameMap = GameController.instance.gameMap;

        int inputNodeCount    = gameMap.Keys.Count * 3;
        int outputNodeCount   = 1 + gameMap.Keys.Count * 2;
        int nodeCountPerLayer = inputNodeCount;

        int[] perceptronArray = new int[HIDDEN_LAYER_COUNT];
        for (int i = 0; i < perceptronArray.Length; i++)
        {
            // Have the number of perceptrons in each layer equal to number of inputs
            perceptronArray[i] = nodeCountPerLayer;
        }

        if (modelsPerGen % 2 != 0)
        {
            // Make sure the number of models per generation is even so we always
            // have two models to pit against each other
            Debug.LogWarning("Number of models per gen is odd. Fixing.");
            modelsPerGen++;
        }

        NeuralNetwork nn = new NeuralNetwork(inputNodeCount, outputNodeCount, perceptronArray);

        float[][][][] genWeights = new float[modelsPerGen][][][];



        // Randomize weights
        for (int m = 0; m < modelsPerGen; m++)
        {
            genWeights[m] = new float[HIDDEN_LAYER_COUNT][][];
            for (int l = 0; l < HIDDEN_LAYER_COUNT; l++)
            {
                genWeights[m][l] = new float[nodeCountPerLayer][];
                for (int p = 0; p < nodeCountPerLayer; p++)
                {
                    int weightCount = nn.GetInputCount(l, p);
                    genWeights[m][l][p] = new float[weightCount];
                    for (int w = 0; w < weightCount; w++)
                    {
                        genWeights[m][l][p][w] = Random.Range(WEIGHT_INIT_MIN, WEIGHT_INIT_MAX);
                    }
                }
            }
        }

        // TRAINING PROCESS
        // We'll be testing two models at a time, pitted against each other.
        for (int gen = 0; gen < numGenerations; gen++)
        {
            // One bool for each model in the current generation, to track whether it won
            bool[] wins = new bool[modelsPerGen];

            for (int model = 0; model < modelsPerGen; model += 2)
            {
                SceneManager.UnloadSceneAsync(MAIN_SCENE_INDEX);
                while (SceneManager.GetSceneByBuildIndex(MAIN_SCENE_INDEX).isLoaded)
                {
                    yield return(null);
                }
                SceneManager.LoadScene(MAIN_SCENE_INDEX, LoadSceneMode.Additive);
                yield return(null);

                SceneManager.SetActiveScene(SceneManager.GetSceneByBuildIndex(MAIN_SCENE_INDEX));

                if (!GameController.instance.setupHasFinished)
                {
                    Debug.Log("Waiting for setup");
                    bool setupFinished = false;
                    GameController.instance.OnSetupComplete += (() => setupFinished = true);
                    while (setupFinished == false)
                    {
                        // TODO timeout
                        yield return(null);
                    }
                }
                Debug.Log("Setup finished.");

                // Wait a frame for scene to load
                yield return(null);

                float[] model1LastInput = new float[inputNodeCount];
                float[] model2LastInput = new float[inputNodeCount];

                // Play through a game for every two models
                while (GameController.instance.gameEnded == false)
                {
                    if (TurnHandler.CurrentTurn > MAX_TURN_COUNT)
                    {
                        Debug.Log("Turn limit reached.");
                        // Hit max turn count; end the game
                        GameController.instance.gameEnded = true;
                        break;
                    }

                    // Set weights depending on whose turn it is
                    if (TurnHandler.CurrentTurn % 2 == 1)                     // Turn is odd (turns start on 1)
                    {
                        // Set NN to have weights for first model
                        nn.SetWeights(genWeights[model]);
                    }
                    else                     // Turn is even
                    {
                        // Set NN to have weights for second model
                        nn.SetWeights(genWeights[model + 1]);
                    }

                    float[] input  = GatherInputs();
                    float[] output = nn.Calculate(input);


                    while (true)                     // Repeat until turn end
                    {
                        // Find best starting tile
                        int bestStart = 0;

                        for (int i = 0; i < GameController.WORLD_X * GameController.WORLD_Y; i++)
                        {
                            int y = (i) / GameController.WORLD_X;
                            int x = (i) % GameController.WORLD_X;

                            // If this would not be a valid start tile, make it highly undesirable
                            GameTile tile = GameController.instance.gameMap[new Vector2Int(x, y)];
                            if (tile.owner != TurnHandler.GetCurrentPlayer() || (!InputHandler.instance.placingArmies && tile.armies == tile.expendedArmies))
                            {
                                output[i + 1] -= 1000;
                            }

                            if (output[i + 1] > output[bestStart + 1])
                            {
                                bestStart = i;
                            }
                        }

                        // Find best target tile
                        int offset     = 1 + GameController.WORLD_X * GameController.WORLD_Y;
                        int bestTarget = 0;

                        for (int i = 0; i < GameController.WORLD_X * GameController.WORLD_Y; i++)
                        {
                            int      y    = (i) / GameController.WORLD_X;
                            int      x    = (i) % GameController.WORLD_X;
                            GameTile tile = GameController.instance.gameMap[new Vector2Int(x, y)];

                            // Check if this tile is next to the start tile, and if not make it highly undesirable
                            bool nextToStartTile = false;
                            foreach (Vector2Int adjTile in GameController.instance.GetAdjacentTiles(new Vector2Int(x, y)))
                            {
                                if (adjTile.x == bestStart % GameController.WORLD_X && adjTile.y == bestStart / GameController.WORLD_X)
                                {
                                    nextToStartTile = true;
                                }
                            }
                            if (!nextToStartTile)
                            {
                                output[i + offset] -= 1000;
                            }

                            if (output[i + offset] > output[bestTarget + offset])
                            {
                                bestTarget = i;
                            }
                        }

                        if (output[0] > output[bestStart + 1])
                        {
                            // Agent decided end turn is best move
                            break;
                        }
                        else
                        {
                            // Input move
                            int startY  = bestStart / GameController.WORLD_X;
                            int startX  = bestStart % GameController.WORLD_X;
                            int targetY = bestTarget / GameController.WORLD_X;
                            int targetX = bestTarget % GameController.WORLD_X;

                            InputHandler.instance.ClearTileSelection();

                            InputHandler.instance.RegisterClickOnTile(new Vector2Int(startX, startY));

                            if (DoShowMoves)
                            {
                                yield return(null);
                            }

                            if (!InputHandler.instance.placingArmies)                             // Only input the second move if we're not placing armies
                            {
                                InputHandler.instance.RegisterClickOnTile(new Vector2Int(targetX, targetY));
                                if (DoShowMoves)
                                {
                                    yield return(null);
                                }
                            }
                        }

                        if (GameController.instance.gameEnded)
                        {
                            break;
                        }

                        input = GatherInputs();
                        if (!Enumerable.SequenceEqual(input, GatherInputs()))
                        {
                            Debug.Log(input[1]);
                            Debug.Log(GatherInputs()[1]);
                            Debug.LogError("input gathering is not deterministic");
                        }
                        output = nn.Calculate(input);
                    }
                    InputHandler.instance.OnEndTurnButton();
                }
                // The game is over.
                // Evaluate which player won:
                if (ScorePosition(GameController.instance.startingPlayers[0]) > ScorePosition(GameController.instance.startingPlayers[1]))
                {
                    Debug.Log("Win goes to " + GameController.instance.startingPlayers[0].nationName);
                    wins[model]     = true;
                    wins[model + 1] = false;
                }
                else if (ScorePosition(GameController.instance.startingPlayers[0]) < ScorePosition(GameController.instance.startingPlayers[1]))
                {
                    Debug.Log("Win goes to " + GameController.instance.startingPlayers[1].nationName);
                    wins[model]     = false;
                    wins[model + 1] = true;
                }
                else
                {
                    Debug.Log("A perfect draw.");
                    wins[model]     = false;
                    wins[model + 1] = false;
                }
            }
            // All the models in this generation have been tested. Time to breed.
            Debug.Log("Breeding winners of generation " + gen);
            List <float[][][]> breedingPool = new List <float[][][]>();
            for (int m = 0; m < modelsPerGen; m++)
            {
                if (wins[m] == true)
                {
                    breedingPool.Add(genWeights[m]);
                }
            }
            if (breedingPool.Count == 0)
            {
                breedingPool.Add(genWeights[0]);
                Debug.LogError("No models in gen " + gen + " survived to breed!");
            }
            for (int m = 0; m < modelsPerGen; m++)
            {
                for (int l = 0; l < HIDDEN_LAYER_COUNT; l++)
                {
                    for (int p = 0; p < nodeCountPerLayer; p++)
                    {
                        for (int w = 0; w < genWeights[m][l][p].Length; w++)
                        {
                            if (Random.value < MUTATION_CHANCE)
                            {
                                genWeights[m][l][p][w] = Random.Range(WEIGHT_INIT_MIN, WEIGHT_INIT_MAX);
                            }
                            else
                            {
                                int i = Random.Range(0, breedingPool.Count);
                                genWeights[m][l][p][w] = breedingPool[i][l][p][w];
                            }
                        }
                    }
                }
            }
        }
    }
Пример #5
0
    static float[] GatherInputs()
    {
        Dictionary <Vector2Int, GameTile> gameMap = GameController.instance.gameMap;
        int inputNodeCount = gameMap.Keys.Count * 3;

        float[] inputs = new float[inputNodeCount];

        Vector2Int[] mapKeys = new Vector2Int[gameMap.Keys.Count];
        gameMap.Keys.CopyTo(mapKeys, 0);

        System.Array.Sort(mapKeys, MathHelper.Vector2IntCompare);

        for (int i = 0; i < mapKeys.Length; i++)
        {
            switch (gameMap[mapKeys[i]].type.id)
            {
            case "water":
                inputs[i] = 0;
                break;

            case "plains":
                inputs[i] = 1;
                break;

            case "forest":
                inputs[i] = 2;
                break;

            case "farm":
            default:
                inputs[i] = 3;
                break;
            }
        }

        int baseIndex = mapKeys.Length;

        for (int i = 0; i < mapKeys.Length; i++)
        {
            if (gameMap[mapKeys[i]].owner == null)
            {
                inputs[i + baseIndex] = 0;                 // unoccupied
            }
            else if (gameMap[mapKeys[i]].owner == TurnHandler.GetCurrentPlayer())
            {
                inputs[i + baseIndex] = 1;                 // friendly territory
            }
            else
            {
                inputs[i + baseIndex] = 2;                 // enemy territory
            }
        }

        baseIndex = mapKeys.Length * 2;

        for (int i = 0; i < mapKeys.Length; i++)
        {
            inputs[i + baseIndex] = gameMap[mapKeys[i]].armies;
        }

        return(inputs);
    }
Пример #6
0
    //Recives event to play card, updating deck on all clients
    public void HandlePhotonEvents(EventData photonEvent)
    {
        byte eventCode = photonEvent.Code;

        switch (eventCode)
        {
        case 1:
            //------Playing Cards
        {
            if (view.IsMine)
            {
                //Stores the number of each trick card where the number matters
                byte[] cards = (byte[])photonEvent.CustomData;

                //A count of each trick card played
                //Aces = index[0] 2s = index[2] | 8s = index[2] | Jacks = index[3] | Black Queens = index[4] | Kings of Hearts = index[5]
                byte[] trickCards = new byte[6];

                #region Trick Card reading
                //Get a count of each trick card in the cards played
                foreach (byte id in cards)
                {
                    Card card = deck.FindCard(id);
                    switch (card.GetValue())
                    {
                    //Ace
                    case 1:
                        trickCards[0]++;
                        break;

                    //Twos
                    case 2:
                        trickCards[1]++;
                        break;

                    //Eights
                    case 8:
                        turnHandler.PlayerUseTurn();
                        trickCards[2]++;
                        break;

                    //Jacks
                    case 11:
                        turnHandler.ReverseOrder();
                        trickCards[3]++;
                        break;

                    //Black Queens
                    case 12:
                        if (card.GetCardId() == 102)
                        {
                            lights.DiscoMode();
                        }
                        break;

                    //King of Hearts
                    case 13:
                        if (card.GetSuit() == 1)
                        {
                            trickCards[5]++;
                        }
                        break;
                    }
                }

                twoCount  += trickCards[1];
                kingCount += trickCards[5];

                //Let player set ace value
                if (trickCards[0] > 0 && turnHandler.GetCurrentPlayer() == view.ViewID)
                {
                    playerHud.aceSelectionArea.GetComponent <CanvasGroup>().alpha = 1;
                }

                //Only use turn if jacks havn't reversed the order
                if (trickCards[3] % 2 == 0 || trickCards[3] == 0)
                {
                    turnHandler.PlayerUseTurn();
                }
                #endregion

                deck.PlayCard(cards);
                playerHud.topCardPrompt.GetComponent <Image>().sprite = deck.GetPlayDeckTopCard().GetCardSprite();
            }
        }
        break;

        case 2:
            //------Game Start
        {
            if (view.IsMine)
            {
                //Shuffles all players decks using the same seed, meaning all players will have the same randomization
                byte seed = (byte)photonEvent.CustomData;
                deck.Shuffle(seed);
                deck.PlayFirstCard();

                //Enables all UI buttons on game start
                playerHud.drawCardsButton.interactable = true;
                playerHud.sortCardsButton.interactable = true;
                playerHud.believeButton.interactable   = true;
                playerHud.lastCardButton.interactable  = true;
                gameStartButton.gameObject.SetActive(false);

                //Adds all the current players to the turn handler to be sorted through
                turnHandler.AddPlayers();
            }
        }
        break;

        case 3:
            //------Drawing Cards
        {
            if (view.IsMine)
            {
                if ((int)photonEvent.CustomData != view.ViewID)
                {
                    Card card = deck.DrawCard();
                }

                if ((int)photonEvent.CustomData == turnHandler.GetCurrentPlayer())
                {
                    turnHandler.PlayerUseTurn();
                }
            }
        }
        break;

        case 4:
            //------Game Start Card Dealing
        {
            int eventViewID = (int)photonEvent.CustomData;
            if (eventViewID == view.ViewID && view.IsMine)
            {
                DrawMultipleCards(5);
                DealStartCardsLoop();
            }
        }
        break;

        case 5:
            //------Game Start Card Loop
        {
            DealStartCards();
        }
        break;

        case 6:
            //------Set trick cards to be used
        {
            twoCount  = 0;
            kingCount = 0;
        }
        break;

        case 7:
            //------Update game log
        {
            if (view.IsMine)
            {
                string text = (string)photonEvent.CustomData;
                playerHud.SendChatboxMessage(text);
            }
        }
        break;

        case 8:
            //------Handle Game Over
        {
            if (view.IsMine)
            {
                string[] message = (string[])photonEvent.CustomData;

                playerHud.gameObject.SetActive(false);

                GameObject winnerScreen = GameObject.Find("WinnerScreen");
                winnerScreen.GetComponent <CanvasGroup>().alpha = 1;
                string gameOverMessage;

                //If someone won...
                if (message[1] == "Winner")
                {
                    //If they were also first winner, display flawless message
                    if (firstWinner == message[0])
                    {
                        gameOverMessage = winnerScreen.GetComponentInChildren <Text>().text = message[0] + "\n is flawless!";
                    }
                    //Else just display winner message
                    else
                    {
                        gameOverMessage = winnerScreen.GetComponentInChildren <Text>().text = message[0] + "\n is the winner!";
                    }
                }

                //If the deck ran out of cards...
                else
                {
                    gameOverMessage = winnerScreen.GetComponentInChildren <Text>().text = message[0] + "\n ruined the game...";
                }

                //Print the winner, time and game log to file
                string path = "GameLog.txt";

                StreamWriter writer = new StreamWriter(path, true);
                writer.WriteLine(DateTime.Now.ToString());
                writer.WriteLine(playerHud.chatBoxText.GetComponent <Text>().text);
                writer.WriteLine(gameOverMessage);
                writer.WriteLine("----------------------------<  Game End  >----------------------------");
                writer.Close();

                //Move back to the main menu
                StartCoroutine("ChangeScene");
            }
        }
        break;

        case 9:
            //------Set first winner
        {
            firstWinner = (string)photonEvent.CustomData;
        }
        break;

        case 10:
            //Blind play / belief button
        {
            if (view.IsMine)
            {
                Card card = deck.DrawCard();
            }
        }
        break;

        case 11:
            //Handle Black queen
        {
        }
        break;

        case 12:
            //Recieving your cards from a black queen target
        {
            short[] data = (short[])photonEvent.CustomData;
            if (data[0] == view.ViewID)
            {
                for (int i = 1; i < data.Length; i++)
                {
                    Card temp = deck.FindCard((byte)data[i]);
                    myCards.Add(temp.GetCardId(), temp);
                }
            }
        }
        break;
        }
    }