예제 #1
0
 object ICallable.Call(GameState state, Context ctx, params object[] args)
 {
     if (argList.Length != args.Length) throw new InvalidGameException("Invalid parameter count!");
     Context local = new Context(ctx);
     for (int i = 0; i < argList.Length; i++)
     {
         local.SetVariable(argList[i], args[i]);
     }
     body.Run(state, local);
     return local.GetVariable(state, "_Return");
 }
예제 #2
0
파일: Game.cs 프로젝트: hgabor/boardgame
        public GameState TryMakeMove(GameState oldState, Coords from, Coords to)
        {
            GameState newState = oldState.Clone();
            Context ctx = new Context(newState.GlobalContext);
            // Special vars x, y are from coordinates
            ctx.SetXYZ(from, newState.CurrentPlayer);
            ctx.SetVariable("from", Transform(from, newState.CurrentPlayer));
            ctx.SetVariable("to", Transform(to, newState.CurrentPlayer));
            ctx.SetVariable("NewGameState", newState);

            if (!MoveIsValidGlobal(newState, from, to, ctx)) return null;

            Piece piece = board.PieceAt(newState, from, null);
            Piece oppPiece = board.PieceAt(newState, to, null);

            bool isInlist = EnumerateMovesFromCoord(newState, from).Any(
                md => Coords.Match(md.From, from) && Coords.Match(md.To, to));
            if (!isInlist) return null;

            foreach (var rule in moveRules)
            {
                // No offboard rules here
                if (rule.OffboardRule) continue;

                var fromT = Transform(from, newState.CurrentPlayer);
                var toT = Transform(to, newState.CurrentPlayer);
                if (!MoveIsValidForRule(newState, rule, null, fromT, toT, ctx)) continue;

                // Move is valid
                rule.RunAction(newState, ctx);

                // Perform the move
                piece = board.PieceAt(newState, from, null);
                if (!board.TryRemove(newState, from, null))
                {
                    // Original piece was removed, should not happen!
                    throw new InvalidGameException("Cannot move from " + from.ToString() + ", piece " + oppPiece.ToString() + " was removed!");
                }
                if (!board.TryPut(newState, to, piece, null))
                {
                    // Piece was not captured
                    throw new InvalidGameException("Cannot move to " + to.ToString() + ", piece " + oppPiece.ToString() + " is in the way!");
                }

                ctx.SetXYZ(to, newState.CurrentPlayer);

                // Move was performed
                oldStates.Add(oldState);

                newState.CurrentPlayer.PostMove(newState, ctx);
                PostMoveActions(newState);

                return newState;
            }
            // No suitable rule found.
            return null;
        }
예제 #3
0
파일: Game.cs 프로젝트: hgabor/boardgame
        public GameState TryMakeMoveFromOffboard(GameState oldState, Piece piece, Coords to)
        {
            GameState newState = oldState.Clone();
            Context ctx = new Context(newState.GlobalContext);
            ctx.SetVariable("to", Transform(to, newState.CurrentPlayer));
            ctx.SetVariable("NewGameState", newState);

            // piece cannot be null
            if (piece == null) return null;
            // Cannot move opponent's piece
            if (piece.Owner != newState.CurrentPlayer) return null;

            bool isInlist = EnumerateMovesFromOffboard(newState, piece).Any(
                md => md.From == null && Coords.Match(md.To, to) && md.PieceType == piece.Type);
            if (!isInlist) return null;

            if (!MoveIsValidGlobal(newState, null, to, ctx)) return null;

            Piece oppPiece = board.PieceAt(newState, to, null);
            foreach (var rule in moveRules)
            {
                // Only offboard rules here
                if (!rule.OffboardRule) continue;

                if (!MoveIsValidForRule(newState, rule, piece, null, to, ctx)) continue;

                // Move is valid
                rule.RunAction(newState, ctx);

                // Perform the move
                if (!newState.CurrentPlayer.RemoveOffBoard(newState, piece))
                {
                    // Original piece was removed, should not happen!
                    throw new InvalidGameException("Cannot move from offboard, piece " + oppPiece.ToString() + " was removed!");
                }
                if (!board.TryPut(newState, to, piece, null))
                {
                    // Piece was not captured
                    throw new InvalidGameException("Cannot move to " + to.ToString() + ", piece " + oppPiece.ToString() + " is in the way!");
                }

                ctx.SetXYZ(to, newState.CurrentPlayer);

                // Move was performed
                oldStates.Add(oldState);

                newState.CurrentPlayer.PostMove(newState, ctx);
                PostMoveActions(newState);

                return newState;
            }
            // No suitable rule found.
            return null;
        }
예제 #4
0
파일: Game.cs 프로젝트: hgabor/boardgame
        public IEnumerable<MoveDefinition> EnumeratePossibleMoves(GameState state)
        {
            HashSet<MoveDefinition> moves = new HashSet<MoveDefinition>();

            foreach (var p in state.CurrentPlayer.GetOffboard(state))
            {
                foreach (var c in board.EnumerateCoords(state, null))
                {
                    foreach (var rule in this.moveRules)
                    {
                        if (rule.From != null) continue;
                        Context ctx = new Context(state.GlobalContext);
                        ctx.SetXYZ(c, state.CurrentPlayer);
                        var cT = Transform(c, state.CurrentPlayer);
                        ctx.SetVariable("to", cT);
                        if (MoveIsValidGlobal(state, null, c, ctx) && MoveIsValidForRule(state, rule, p, null, cT, ctx))
                        {
                            moves.Add(new MoveDefinition(pieceType: p.Type, label: rule.Label, from: null, to: c, game: this));
                        }
                    }
                }
            }
            foreach (var from in board.EnumerateCoords(state, null))
            {
                foreach (var to in board.EnumerateCoords(state, null))
                {
                    foreach (var rule in this.moveRules)
                    {
                        if (rule.OffboardRule) continue;
                        Context ctx = new Context(state.GlobalContext);
                        ctx.SetXYZ(from, state.CurrentPlayer);
                        var fromT = Transform(from, state.CurrentPlayer);
                        var toT = Transform(to, state.CurrentPlayer);
                        ctx.SetVariable("from", fromT);
                        ctx.SetVariable("to", toT);
                        if (MoveIsValidGlobal(state, from, to, ctx) && MoveIsValidForRule(state, rule, null, fromT, toT, ctx))
                        {
                            moves.Add(new MoveDefinition(pieceType: board.PieceAt(state, from, null).Type, label: rule.Label, from: from, to: to, game: this));
                        }
                    }
                }
            }
            return state.AllowedMoves == null ? moves : moves.Intersect(state.AllowedMoves);
        }