private async Task <GameActionResult> Harvest(GameAction action)
        {
            GameActionResult result = new GameActionResult(action.nActionType, action.gameId);

            var score = new Score(action.Pieces);

            action.player.NScore += score.Calculate();

            // add companion bonus
            action.player.NScore += action.nActionArguement;

            // increase score for each star
            foreach (var piece in action.Pieces)
            {
                // if bit 2 has not been set the piece has not been flipped
                if ((piece.NPieceStatus & 2) != 2)
                {
                    action.player.NScore++;
                }
            }

            // setup history object
            History history = new History();

            history.NPlayer     = action.player.NPlayer;
            history.NActionType = action.nActionType;
            history.GameId      = action.gameId;
            if (action.player.NPlayer == 1)
            {
                history.NScore1 = action.player.NScore;
                history.NScore2 = action.otherplayer.NScore;
                result.nScore1  = action.player.NScore;
                result.nScore2  = action.otherplayer.NScore;
            }
            else
            {
                history.NScore2 = action.player.NScore;
                history.NScore1 = action.otherplayer.NScore;
                result.nScore2  = action.player.NScore;
                result.nScore1  = action.otherplayer.NScore;
            }

            // Get turn count from nGameStatus (MSByte)
            int turns = (action.game.NGameStatus & 0b1111_1111_0000_0000) / 256;

            turns++;

            // flip player turn bit
            action.game.NGameStatus = (action.game.NGameStatus ^ 4);

            // reform nGameStatus
            action.game.NGameStatus = (action.game.NGameStatus & 0b0000_0000_1111_1111) + turns * 256;
            appDbContext.Game.Update(action.game);
            appDbContext.Player.Update(action.player);
            var historyResult = appDbContext.History.Add(history);

            // save required at this point to populate dBresult.HistoryId
            // and to allow the reload truck check to reflect the changes so far
            await appDbContext.SaveChangesAsync();

            // add linking HistoryPiece entries
            foreach (Piece piece in action.Pieces)
            {
                // we must get the piece tracked by the dB otherwise updating will
                // throw and exception
                var trackedPiece = await appDbContext.Piece.FindAsync(piece.PieceId);

                // mark piece as discarded
                trackedPiece.NOwner = (int)eOwner.discard;
                appDbContext.Piece.Update(trackedPiece);

                HistoryPiece historyPiece = new HistoryPiece
                {
                    HistoryId = historyResult.Entity.HistoryId,
                    PieceId   = trackedPiece.PieceId
                };
                appDbContext.HistoryPiece.Add(historyPiece);
            }

            await appDbContext.SaveChangesAsync();

            result.nGameStatus   = action.game.NGameStatus;
            result.nResponseCode = 1;   // OK
            return(result);
        }
        private async Task <GameActionResult> MovePiece(GameAction action)
        {
            GameActionResult result = new GameActionResult(action.nActionType, action.gameId);

            Piece piece;

            try
            {
                piece = await appDbContext.Piece.FindAsync(action.pieceId);
            }
            catch (Exception)
            {
                // piece has already been picked up
                result.nResponseCode = 11;
                return(result);
            }
            piece.NOwner = action.player.NPlayer;

            // setup history object
            History history = new History();

            history.NPlayer     = action.player.NPlayer;
            history.NActionType = action.nActionType;
            history.GameId      = piece.GameId;

            // check if placement will require piece to be turned over
            if (action.nActionArguement % 5 != piece.NPosition)
            {
                piece.NPieceStatus = (piece.NPieceStatus | 2); // set bit 2 - star side down
            }
            history.NSourcePos = piece.NPosition;
            history.NDestPos   = action.nActionArguement;
            piece.NPosition    = action.nActionArguement;
            appDbContext.Piece.Update(piece);

            var dBresult = appDbContext.History.Add(history);

            // save required at this point to populate dBresult.HistoryId
            // and to allow the reload truck check to reflect the changes so far
            await appDbContext.SaveChangesAsync();

            // add linking HistoryPiece entry
            HistoryPiece historyPiece = new HistoryPiece
            {
                HistoryId = history.HistoryId,
                PieceId   = piece.PieceId
            };

            appDbContext.HistoryPiece.Add(historyPiece);


            Piece unusedPiece;

            try
            {
                unusedPiece = await appDbContext.Piece.Where(p => p.GameId == action.gameId && p.NOwner == 0).FirstAsync();

                unusedPiece.NOwner    = (int)eOwner.mainboard;
                unusedPiece.NPosition = history.NSourcePos;
                appDbContext.Update(unusedPiece);
            }
            catch (Exception)
            {
                var truckPieces = appDbContext.Piece.Where(p => p.GameId == action.gameId && p.NOwner == 3);
                if (truckPieces.Count() == 0) // Game over condition
                {
                    action.game.NGameStatus = action.game.NGameStatus ^ 2;
                }
            }

            // Get turn count from nGameStatus (MSByte)
            int turns = (action.game.NGameStatus & 0b1111_1111_0000_0000) / 256;

            turns++;

            // flip player turn bit
            action.game.NGameStatus = (action.game.NGameStatus ^ 4);

            // reform nGameStatus
            action.game.NGameStatus = (action.game.NGameStatus & 0b0000_0000_1111_1111) + turns * 256;
            appDbContext.Game.Update(action.game);

            await appDbContext.SaveChangesAsync();

            result.nGameStatus   = action.game.NGameStatus;
            result.nResponseCode = 1;   // OK
            return(result);
        }