コード例 #1
0
ファイル: Board.cs プロジェクト: hgabor/boardgame
 public Board(Coords size)
 {
     this.Size = size;
     lowerLeft = new Coords(Array.ConvertAll(size.ToInt32Array(), i => 1));
     this.Valid = RuleType.Invalid;
     Transformation = IdentityTransformation;
 }
コード例 #2
0
ファイル: MoveDefinition.cs プロジェクト: hgabor/boardgame
 internal MoveDefinition(string pieceType, string label, Coords from, Coords to, Game game)
 {
     this.PieceType = pieceType;
     this.Label = label;
     this.From = from;
     this.To = to;
     this.Game = game;
 }
コード例 #3
0
ファイル: Coords.cs プロジェクト: hgabor/boardgame
 public static bool Match(Coords c1, Coords c2)
 {
     if (c1.coords.Length != c2.coords.Length) return false;
     for (int i = 0; i < c1.coords.Length; i++)
     {
         if (c1.placeholder[i] || c2.placeholder[i]) continue;
         if (c1.coords[i] != c2.coords[i]) return false;
     }
     return true;
 }
コード例 #4
0
ファイル: CoordTransformer.cs プロジェクト: hgabor/boardgame
        public CoordTransformer(Coords[] game, Coords[] board)
        {
            if (game.Length != board.Length) throw new ArgumentException("Lengths must be equal");

            for (int i = 0; i < game.Length; i++)
            {
                if (board[i].Dimension != 2) throw new ArgumentException("Board coords must be in 2D!");
                game2board.Add(game[i], board[i]);
                board2game.Add(board[i], game[i]);
            }
        }
コード例 #5
0
ファイル: CoordTransformer.cs プロジェクト: hgabor/boardgame
 public Coords GameToBoard(Coords c)
 {
     Coords ret;
     if (game2board.TryGetValue(c, out ret))
     {
         return ret;
     }
     else
     {
         return new Coords(-1);
     }
 }
コード例 #6
0
ファイル: CoordTransformer.cs プロジェクト: hgabor/boardgame
 public Coords BoardToGame(Coords c)
 {
     Coords ret;
     if (board2game.TryGetValue(c, out ret))
     {
         return ret;
     }
     else
     {
         return new Coords(-1);
     }
 }
コード例 #7
0
ファイル: Game.cs プロジェクト: hgabor/boardgame
 public IEnumerable<MoveDefinition> EnumerateMovesFromCoord(GameState state, Coords c)
 {
     var ret = EnumeratePossibleMoves(state).Where(md => md.From != null && Coords.Match(c, md.From));
     return ret;
 }
コード例 #8
0
ファイル: Board.cs プロジェクト: hgabor/boardgame
 private void PossibleCoordsToArray(GameState state, int[] coords, int dimension, Player asker, List<Coords> outList)
 {
     if (dimension == Size.Dimension)
     {
         Coords c = new Coords(coords);
         if (IsValidByRules(state, c))
         {
             outList.Add(Transformation(asker, c));
         }
         return;
     }
     for (int i = 1; i <= Size[dimension]; i++)
     {
         var newCoords = new List<int>(coords);
         newCoords.Add(i);
         PossibleCoordsToArray(state, newCoords.ToArray(), dimension + 1, asker, outList);
     }
 }
コード例 #9
0
ファイル: Board.cs プロジェクト: hgabor/boardgame
 private bool IsValidByRules(GameState state, Coords c)
 {
     Context ctx = new Context(state);
     ctx.SetXYZ(c, null);
     if (Valid == RuleType.Valid)
     {
         // We must match at least one rule
         foreach (var exp in ruleList)
         {
             bool b = (bool)exp.Eval(state, ctx);
             if (b) return true;
         }
         return false;
     }
     else
     {
         // We mustn't match any rule
         foreach (var exp in ruleList)
         {
             bool b = (bool)exp.Eval(state, ctx);
             if (b) return false;
         }
         return true;
     }
 }
コード例 #10
0
ファイル: Board.cs プロジェクト: hgabor/boardgame
 private Coords IdentityTransformation(Player p, Coords c)
 {
     return c;
 }
コード例 #11
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;
        }
コード例 #12
0
ファイル: Game.cs プロジェクト: hgabor/boardgame
        internal bool MoveIsValidForRule(GameState currentState, MoveRule rule, Piece piece, Coords from, Coords to, Context ctx)
        {
            if (from != null) piece = board.PieceAt(currentState, from, currentState.CurrentPlayer);
            Piece oppPiece = board.PieceAt(currentState, to, currentState.CurrentPlayer);

            // Rule must be applicable to current piece
            if (rule.PieceType != piece.Type) return false;

            // Target should be empty
            if (rule.TargetMustBeEmpty && oppPiece != null) return false;

            if (rule.Condition != null)
            {
                bool cond = (bool)rule.Condition.Eval(currentState, ctx);
                if (!cond) return false;
            }

            if (rule.From == null)
            {
                if (!currentState.CurrentPlayer.GetOffboard(currentState).Contains(piece)) return false;
                //var toT = board.Transformation(CurrentPlayer, to);
                ///var toTExpr = board.Transformation(CurrentPlayer, (Coords)rule.To.Eval(ctx));
                if (!Coords.Match(to, (Coords)rule.To.Eval(currentState, ctx))) return false;
            }
            else if (rule.To == null)
            {
                throw new NotImplementedException();
            }
            else
            {
                // Check coords
                //var fromT = board.Transformation(CurrentPlayer, from);
                //var toT = board.Transformation(CurrentPlayer, to);
                //var fromTExpr = board.Transformation(CurrentPlayer, (Coords)rule.From.Eval(ctx));
                //var toTExpr = board.Transformation(CurrentPlayer, (Coords)rule.To.Eval(ctx));

                if (!Coords.Match(from, (Coords)rule.From.Eval(currentState, ctx))) return false;
                if (!Coords.Match(to, (Coords)rule.To.Eval(currentState, ctx))) return false;
            }
            return true;
        }
コード例 #13
0
ファイル: CoordTransformer.cs プロジェクト: hgabor/boardgame
 public bool IsValidBoardCoord(Coords c)
 {
     return board2game.ContainsKey(c);
 }
コード例 #14
0
ファイル: Game_globals.cs プロジェクト: hgabor/boardgame
 public static bool IsEmpty(Context ctx, Coords c)
 {
     return ctx.Game.board.PieceAt(ctx.GameState, c, ctx.GameState.CurrentPlayer) == null;
 }
コード例 #15
0
ファイル: Game_globals.cs プロジェクト: hgabor/boardgame
 public static bool Match(Context ctx, Coords from, Coords target, RegExp.Pattern.Direction direction, RegExp.Pattern pattern)
 {
     return pattern.Match(ctx.GameState, target, from, direction);
 }
コード例 #16
0
ファイル: Game_globals.cs プロジェクト: hgabor/boardgame
 public static IEnumerable<object> GetMatching(Context ctx, Coords from, Coords target, int direction, RegExp.Pattern pattern)
 {
     IEnumerable<Coords> c;
     if (pattern.CaptureAll(ctx.GameState, target, from, RegExp.Pattern.Direction.Any, out c))
     {
         return c;
     }
     else
     {
         return new List<object>();
     }
 }
コード例 #17
0
ファイル: Game.cs プロジェクト: hgabor/boardgame
 internal Coords Transform(Coords c, Player asker)
 {
     return board.Transformation(asker, c);
 }
コード例 #18
0
ファイル: Game.cs プロジェクト: hgabor/boardgame
        internal bool MoveIsValidGlobal(GameState currentState, Coords from, Coords to, Context ctx)
        {
            if (from != null && !board.IsValidPlace(currentState, from)) return false;
            if (to != null && !board.IsValidPlace(currentState, to)) return false;
            if (from == null && to == null) return false;

            if (from != null)
            {
                Piece piece = board.PieceAt(currentState, from, null);

                // Cannot move empty square
                if (piece == null) return false;

                // Cannot move opponent's piece
                if (piece.Owner != currentState.CurrentPlayer) return false;

                // Cannot stay in place
                // Why not? :)
                //if (Coords.Match(from, to)) return false;
            }

            return true;
        }
コード例 #19
0
ファイル: Board.cs プロジェクト: hgabor/boardgame
        public bool IsValidPlace(GameState state, Coords c)
        {
            if (c.IsPlaceHolder) throw new ArgumentOutOfRangeException("Non-placeholder coords needed.");

            for (int i = 0; i < c.Dimension; i++)
            {
                if (c[i] < 1 || c[i] > Size[i]) return false;
            }
            return IsValidByRules(state, c);
        }
コード例 #20
0
ファイル: MainWindow.xaml.cs プロジェクト: hgabor/boardgame
        public MainWindow()
        {
            InitializeComponent();

            offBoard.Selected += (sender, args) =>
            {
                switch (selectState)
                {
                    case SelectState.From:
                        FromOffboard = args.Piece;
                        selectState = SelectState.To;
                        break;
                    case SelectState.To:
                        if (FromOffboard == args.Piece)
                        {
                            // Unselect it
                            FromOffboard = null;
                            selectState = SelectState.From;
                        }
                        else if (FromOffboard != null)
                        {
                            FromOffboard = args.Piece;
                        }
                        else
                        {
                            // Unsupported
                        }
                        break;
                    case SelectState.Special:
                        if (mustSelectFrom.Contains(args.Piece))
                        {
                            SetSelected(args.Piece);
                        }
                        break;
                }
                gamePanel.InvalidateVisual();
                offBoard.InvalidateVisual();
            };

            gamePanel.Selected += (sender, args) =>
            {
                switch (selectState)
                {
                    case SelectState.From:
                        FromCoord = args.Coords;
                        if (FromCoord != null)
                        {
                            selectState = SelectState.To;
                        }
                        break;
                    case SelectState.To:
                        if (fromCoord != null && Coords.Match(fromCoord, args.Coords))
                        {
                            FromCoord = null;
                            selectState = SelectState.From;
                        }
                        else
                        {
                            toCoord = args.Coords;
                            MakeMove();
                        }
                        break;
                    case SelectState.Special:
                        foreach (var kvp in game.GetPieces(gameState))
                        {
                            if (Coords.Match(kvp.Key, args.Coords) && mustSelectFrom.Contains(kvp.Value))
                            {
                                SetSelected(kvp.Value);
                                return;
                            }
                        }
                        break;
                }
                gamePanel.InvalidateVisual();
                offBoard.InvalidateVisual();
            };

            App.Current.DispatcherUnhandledException += (sender, args) =>
            {
                InvalidGameException ex = args.Exception as InvalidGameException;
                if (ex != null)
                {
                    System.Windows.MessageBox.Show(ex.Message, "Invalid game", MessageBoxButton.OK, MessageBoxImage.Error);
                    args.Handled = true;
                }
            };
        }
コード例 #21
0
ファイル: Context.cs プロジェクト: hgabor/boardgame
 internal void SetXYZ(Coords cIn, Player asker)
 {
     var c = Game.Transform(cIn, asker);
     if (c.Dimension >= 1)
     {
         SetVariable("x", c[0]);
     }
     if (c.Dimension >= 2)
     {
         SetVariable("y", c[1]);
     }
     if (c.Dimension >= 3)
     {
         SetVariable("z", c[2]);
     }
 }
コード例 #22
0
ファイル: UnitTest1.cs プロジェクト: hgabor/boardgame
 private bool TenPredicate(GameState state, Coords coords)
 {
     return coords[1] == 10;
 }
コード例 #23
0
ファイル: Game_globals.cs プロジェクト: hgabor/boardgame
 public static Piece PieceAt(Context ctx, Coords c)
 {
     return ctx.Game.board.PieceAt(ctx.GameState, c, ctx.GameState.CurrentPlayer);
 }
コード例 #24
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;
        }
コード例 #25
0
ファイル: MainWindow.xaml.cs プロジェクト: hgabor/boardgame
        private void MakeMove()
        {
            if (fromOffboard != null && toCoord != null)
            {
                // From offboard to board
                var newGameState = game.TryMakeMoveFromOffboard(gameState, FromOffboard, toCoord);
                if (newGameState != null) gameState = newGameState;

                offBoard.Refresh();
                gamePanel.InvalidateVisual();
            }
            else if (fromCoord != null && toCoord != null)
            {
                // From coords to coords
                var newGameState = game.TryMakeMove(gameState, FromCoord, toCoord);
                if (newGameState != null) gameState = newGameState;

                offBoard.Refresh();
                gamePanel.InvalidateVisual();
            }

            if (game.GameOver)
            {
                if (game.PlayerCount == 1)
                {
                    if (game.Winners.Count() == 1)
                    {
                        System.Windows.MessageBox.Show("You won!");
                    }
                    else
                    {
                        System.Windows.MessageBox.Show("You lost!");
                    }
                }
                else
                {
                    if (game.Winners.Count() == 0)
                    {
                        System.Windows.MessageBox.Show("Game over!\nThe game ended in a tie!");
                    }
                    else if (game.Winners.Count() == 1)
                    {
                        System.Windows.MessageBox.Show("Game over!\nThe winner is: " + game.Winners.First().ToString());
                    }
                    else
                    {
                        System.Windows.MessageBox.Show("Game over!\nThe winners are: " + string.Join(", ", game.Winners));
                    }
                }
                NewGame();
            }
            selectState = SelectState.From;
            FromCoord = null;
            FromOffboard = null;
            toCoord = null;
            currentPlayerLabel.Content = gameState.CurrentPlayer.ToString();
        }
コード例 #26
0
ファイル: Game_globals.cs プロジェクト: hgabor/boardgame
 public static void Place(Context ctx, string piecetype, Coords c)
 {
     Piece p = new Piece(piecetype, ctx.GameState.CurrentPlayer, ctx.Game);
     ctx.Game.board.TryPut(ctx.GameState, c, p, ctx.GameState.CurrentPlayer);
 }
コード例 #27
0
ファイル: UnitTest1.cs プロジェクト: hgabor/boardgame
 private bool TargetPredicate(GameState state, Coords coords)
 {
     return Coords.Match(coords, new Coords(5, 7));
 }
コード例 #28
0
ファイル: Board.cs プロジェクト: hgabor/boardgame
 public Piece PieceAt(GameState state, Coords c, Player asker)
 {
     Piece p;
     if (state.Board.TryGetValue(Transformation(asker, c), out p)) return p;
     return null;
 }
コード例 #29
0
ファイル: UnitTest1.cs プロジェクト: hgabor/boardgame
 private bool TruePredicate(GameState state, Coords coords)
 {
     return true;
 }
コード例 #30
0
ファイル: Board.cs プロジェクト: hgabor/boardgame
        public bool TryRemove(GameState state, Coords cIn, Player asker)
        {
            Coords c = Transformation(asker, cIn);

            if (c.IsPlaceHolder) throw new ArgumentOutOfRangeException("Non-placeholder coords needed.");
            if (!IsValidPlace(state, c))
            {
                throw new ArgumentOutOfRangeException("Coords must be inside the board.");
            }
            if (!state.Board.ContainsKey(c)) return false;
            state.Board.Remove(c);
            return true;
        }