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"); }
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; }
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; }
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); }