public void TestGameStart( [Frozen] IGameConnector gameConnector, [Frozen] IDecisionMaker maker, string board, Moves nextMove, Game game) { maker.NextMove(board).Returns(nextMove); game.Start(); gameConnector.NewPosition += Raise.EventWith(new Object(), new NewPositionArgs(board)); gameConnector.Received().NextMove(nextMove.ToString()); }
public static ACar[] GetCarPath(Car self, Moves stack) { if (stack == null) return null; stack = stack.Clone(); var res = new List<ACar>(); var model = new ACar(self); while (stack.Count > 0) { var m = stack[0]; AMove.ModelMove(model, m, new PassedInfo(), Bonuses, OilSlicks, Tires, Others); m.Times--; stack.Normalize(); res.Add(model.Clone()); } return res.ToArray(); }
// Tell the character you want it to use this tool and what move of his weapon he should use public override void use(Transform caster, int toolMove) { if (activeMove == null || Time.time > activeMove.hitboxes[activeMove.CurrentHitboxIndex].duration + activeMove.hitboxes[activeMove.CurrentHitboxIndex].comboTime) { activeMove = moves [toolMove]; activeMove.caster = caster; activeMove.CurrentHitboxIndex = 0; FireAnimation (); } if ((Time.time > activeMove.hitboxes[activeMove.CurrentHitboxIndex].duration && Time.time <= activeMove.hitboxes[activeMove.CurrentHitboxIndex].duration + activeMove.hitboxes[activeMove.CurrentHitboxIndex].comboTime)) { if (activeMove.hitboxes [activeMove.CurrentHitboxIndex].combo) { activeMove.CurrentHitboxIndex++; FireAnimation (); } } }
private void SetLastMove(Moves lastMove, bool lastResult) { this.lastMove = lastMove; this.lastResult = lastResult; }
void Start() { Instance = this; }
public static int quieseSearch(int depth, int alpha, int beta, ulong WP, ulong WN, ulong WB, ulong WR, ulong WQ, ulong WK, ulong BP, ulong BN, ulong BB, ulong BR, ulong BQ, ulong BK, ulong EP, bool CWK, bool CWQ, bool CBK, bool CBQ, bool white) { int standPat = Evalue.evalue(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK, white); if (depth == 0) { return(standPat); } if (standPat > beta) { return(beta); } if (alpha > standPat) { alpha = standPat; } string captureMoves = Moves.captureMoves(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK, EP, CWK, CWQ, CBK, CBQ, white); for (int i = 0; i < captureMoves.Length; i += 4) { ulong WRt = Moves.makeMoveCastle(WR, WK | BK, captureMoves.Substring(i, 4), 'R'); ulong BRt = Moves.makeMoveCastle(BR, WK | BK, captureMoves.Substring(i, 4), 'r'); WRt = Moves.makeMove(WR, captureMoves.Substring(i, 4), 'R'); BRt = Moves.makeMove(BR, captureMoves.Substring(i, 4), 'r'); ulong WPt = Moves.makeMove(WP, captureMoves.Substring(i, 4), 'P'), WNt = Moves.makeMove(WN, captureMoves.Substring(i, 4), 'N'), WBt = Moves.makeMove(WB, captureMoves.Substring(i, 4), 'B'), WQt = Moves.makeMove(WQ, captureMoves.Substring(i, 4), 'Q'), WKt = Moves.makeMove(WK, captureMoves.Substring(i, 4), 'K'), BPt = Moves.makeMove(BP, captureMoves.Substring(i, 4), 'p'), BNt = Moves.makeMove(BN, captureMoves.Substring(i, 4), 'n'), BBt = Moves.makeMove(BB, captureMoves.Substring(i, 4), 'b'), BQt = Moves.makeMove(BQ, captureMoves.Substring(i, 4), 'q'), BKt = Moves.makeMove(BK, captureMoves.Substring(i, 4), 'k'), EPt = Moves.makeMoveEP(WP | BP, captureMoves.Substring(i, 4)); bool CWKt = CWK, CWQt = CWQ, CBKt = CBK, CBQt = CBQ; if (char.IsDigit(captureMoves[i + 3])) {//'regular' move int start = (captureMoves[i] - '0') * 8 + captureMoves[i + 1] - '0'; /*if (((1ul<<start)&(WP|BP))!=0) { * if (Math.abs(captureMoves[i)-captureMoves[i+2))==2) { * EPt=Moves.FileMasks8[captureMoves[i+1)-'0']; * } * } * else */ if (((1ul << start) & WK) != 0) { CWKt = false; CWQt = false; } else if (((1ul << start) & BK) != 0) { CBKt = false; CBQt = false; } else if (((1ul << start) & WR & (1ul << 63)) != 0) { CWKt = false; } else if (((1ul << start) & WR & (1ul << 56)) != 0) { CWQt = false; } else if (((1ul << start) & BR & (1ul << 7)) != 0) { CBKt = false; } else if (((1ul << start) & BR & 1ul) != 0) { CBQt = false; } } int score = -quieseSearch(depth - 1, -beta, -alpha, WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK, EP, CWK, CWQ, CBK, CBQ, white?false:true); if (score >= beta) { return(beta); } if (score > alpha) { alpha = score; } } return(alpha); }
public Moves Do(ACar car, Points pts) { // Проверка что данный путь был выбран if (_selectThisTick + 1 != MyStrategy.world.Tick) _lastSuccessStack = null; Self = car.Clone(); if (_lastCall == LastSuccess) LastSuccess = _lastCall; for (var t = 0; t < MyStrategy.world.Tick - _lastCall && _lastSuccessStack != null && _lastSuccessStack.Count > 0; t++) { _lastSuccessStack[0].Times--; _lastSuccessStack.Normalize(); } if (_lastSuccessStack != null && (_lastSuccessStack.Count == 0 || _useDist2 && _lastSuccessStack.ComputeTime() < 30)) _lastSuccessStack = null; _lastCall = MyStrategy.world.Tick; /* * Количество бонусов на расстоянии 0.5t * Если изменилось - пересчитывать сильно */ var bonusesCount05 = MyStrategy.Bonuses .Count(bonus => Self.GetDistanceTo(bonus) < Const.TileSize / 2); /* * Количество бонусов на расстоянии 2t * Если изменилось - чуть нужно пересчитать */ var bonusesCount2 = MyStrategy.Bonuses .Count( bonus => Self.GetDistanceTo(bonus) < Const.TileSize*2 && MyStrategy.CellDistance(Self, bonus) <= 2); // Если был success на прошлом тике, то продолжаем. Или каждые _interval тиков. if (Const.Game.InitialFreezeDurationTicks < MyStrategy.world.Tick && bonusesCount05 == _bonusesCount05 && LastSuccess < MyStrategy.world.Tick - 1 && (MyStrategy.world.Tick - (LastSuccess + 1))%_interval != 0) { _validateLastSuccessStack(); return _lastSuccessStack; } /* * Смотрим на шины, которые на расстоянии не более 6 тайлов */ var prevProj = _projCandidates; _projCandidates = MyStrategy.Tires .Where( proj => Self.GetDistanceTo(proj[0]) <= Const.TileSize * 6 && MyStrategy.CellDistance(Self, proj[0]) <= 6) .ToArray(); var extended = MyStrategy.ExtendWaySegments(pts, 50); _bruteWayPoints = extended.GetRange(0, Math.Min(_waypointsCount, extended.Count)).ToArray(); if (LastStageMove.IsUseNitro && _turnsCount(_bruteWayPoints) > 1) return null; #if DEBUG var bruteWayPoints = new Points(); bruteWayPoints.AddRange(_bruteWayPoints); Visualizer.SegmentsDrawQueue.Add(new object[]{ Brushes.Brown, bruteWayPoints, 0.0 }); #endif _needDist = Const.TileSize*0.5 - 3; _needDist2 = Const.TileSize - 3; _turnTo = _bruteWayPoints[_bruteWayPoints.Length - 1]; _turnTo2 = _bruteWayPoints[Math.Min(_bruteWayPoints.Length - 1, (int)(_bruteWayPoints.Length * 0.83))]; #if DEBUG Visualizer.CircleFillQueue.Add(new Tuple<Brush, ACircularUnit>(Brushes.OrangeRed, new ACircularUnit { X = _turnTo.X, Y = _turnTo.Y, Radius = 20})); Visualizer.CircleFillQueue.Add(new Tuple<Brush, ACircularUnit>(Brushes.Orange, new ACircularUnit { X = _turnTo2.X, Y = _turnTo2.Y, Radius = 20 })); #endif _patterns = Patterns.Select(pt => new PathPattern { From = pt.From, To = pt.To, Step = pt.Step, Move = pt.Move.Clone() }).ToArray(); foreach (var p in _patterns) { if (p.Move.WheelTurn is TurnPattern) { var turnPattern = p.Move.WheelTurn as TurnPattern; if (turnPattern.Pattern == TurnPatternType.ToNext) p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? -1 : 1; else if (turnPattern.Pattern == TurnPatternType.FromNext) p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? 1 : -1; } } _movesStack = new Moves(); _bestMovesStack = new Moves(); _bestTime = MyStrategy.Infinity; _bestImportance = 0; /* * Смотрим на бонусы, которые на расстоянии не более 4t * TODO: уменьшить приоритет бонусов, которые может быть возьмет другой (в.т.ч тиммейт) */ _bonusCandidates = MyStrategy.Bonuses .Where( bonus => MyStrategy.world.Tick > 270 && // Не смотреть на бонусы при старте!!! Self.GetDistanceTo(bonus) <= Const.TileSize * 4 && MyStrategy.CellDistance(Self, bonus) <= 4 ) .ToArray(); /* * Смотрим на лужи, которые на расстоянии не более 5 тайлов */ var prevSlicks = _slickCandidates; _slickCandidates = MyStrategy.OilSlicks .Where( slick => Self.GetDistanceTo(slick) <= Const.TileSize*5 && MyStrategy.CellDistance(Self, slick) <= 5 ) .ToArray(); /* * Пытаться объехать тех, которые * - Крашнулись * - Убиты * - Двигатель меньше чем на 0.5 мощности * - Двигаются по встречной * * - Если у меня нитро, или будет нитро * * - Своих */ var prevCars = _carCandidates; _carCandidates = MyStrategy.Others .Where(opp => opp[0].GetDistanceTo(Self) < Const.TileSize*9) .Where( opp => opp[0].Original.IsTeammate || MyStrategy.IsCrashed(opp[0].Original) || !DurabilityObserver.IsActive(opp[0].Original) || opp[0].EnginePower < 0.5 || Self.RemainingNitroTicks > 0 || Math.Abs(Geom.GetAngleBetween(Self.Speed, opp[0].Speed)) > Math.PI / 2 ) .Where(opp => MyStrategy.CellDistance(Self, opp[0]) <= 9) // 9 - потому что он может ехать по встречке .ToArray(); if (_cache != null) { for (var k = 0; k < _patterns.Length; k++) { var range = (prevSlicks == null || prevCars == null || prevProj == null || _bonusesCount2 != bonusesCount2 || prevSlicks.Length != _slickCandidates.Length || prevCars.Length != _carCandidates.Length || prevProj.Length != _projCandidates.Length) ? (k == 0 ? 6 : 4) : (k == 0 ? 6 : 2); if (_bonusesCount05 != bonusesCount05 || Special && k == 0) range = 10; _patterns[k].From = Math.Max(0, _cache[k].Times - range); _patterns[k].To = Math.Min(_patterns[k].To * 9 / 7, _cache[k].Times + range); _patterns[k].Step = 2; } } _bonusesCount05 = bonusesCount05; _bonusesCount2 = bonusesCount2; var wayPointRequired = false; for(var i = _bruteWayPoints.Length - 1; i >= 0; i--) { if (_bruteWayPoints[i].GetDistanceTo2(_turnTo) < _needDist*_needDist) { for (var j = 0; j < i; j++) wayPointRequired |= MyStrategy.GetNextWayPoint(Self.Original).Equals(MyStrategy.GetCell(_bruteWayPoints[j])); break; } } _doRecursive(Self, 0, new PassedInfo { WayPoint = !wayPointRequired }); _cache = null; if (_bestTime == MyStrategy.Infinity) return _lastSuccessStack; if (_bestMovesStack.ComputeTime() != _bestTime) throw new Exception("ComputeTime != BestTime"); LastSuccess = MyStrategy.world.Tick; _cache = _bestMovesStack.Clone(); if (_maxTicksInfo == null) _maxTicksInfo = new int[_bestMovesStack.Count]; for (var i = 0; i < _maxTicksInfo.Length; i++) _maxTicksInfo[i] = Math.Max(_maxTicksInfo[i], _bestMovesStack[i].Times); _bestMovesStack.Normalize(); _lastSuccessStack = _bestMovesStack.Clone(); return _bestMovesStack; }
public bool IsMatch(string move) => Moves.Any(v => move.Equals(v));
public void AddGameUpdate(GameUpdate update) { Moves.AddMove(update.resultPlayer); Updates.AddLast(update); }
/// <summary> /// Starts the iterative deepening search to find the best move for this player. /// http://chessprogramming.wikispaces.com/Iterative+Deepening /// </summary> /// <param name="player"> /// The player to play. /// </param> /// <param name="principalVariation"> /// Move in the principal variation will be added to this list. /// </param> /// <param name="recommendedSearchTime"> /// Recommended search time allotted. /// </param> /// <param name="maximumSearchTimeAllowed"> /// The maximum search time allowed. /// </param> /// <returns> /// The best move for the player. /// </returns> /// <exception cref="ForceImmediateMoveException"> /// Raised when the user requests for thinking to be terminated, and immediate move to made. /// </exception> public int IterativeDeepeningSearch( Player player, Moves principalVariation, TimeSpan recommendedSearchTime, TimeSpan maximumSearchTimeAllowed) { /* A new deeper ply of search will only be started, if the cutoff time hasnt been reached yet. Minimum search time = 2 seconds */ TimeSpan searchTimeCutoff = new TimeSpan(recommendedSearchTime.Ticks / 3); if (searchTimeCutoff.TotalMilliseconds < 2000) { searchTimeCutoff = new TimeSpan(0, 0, 0, 2); } this.MaxSearchTimeAllowed = maximumSearchTimeAllowed; this.forceExitWithMove = false; // Set to stop thread thinking and return best move this.PositionsSearched = 0; // Total number of positions considered so far this.Evaluations = 0; this.LastPrincipalVariation.Clear(); // A little counter to record the deepest Quiescence depth searched on this move. this.MaxQuiesenceDepthReached = 0; // A little counter to track the number of extensions on this move. this.MaxExtensions = 0; // Set max search depth, as defined is game difficulty settings this.MaxSearchDepth = Game.MaximumSearchDepth == 0 ? 32 : Game.MaximumSearchDepth; int score = player.Score; for (this.SearchDepth = MinSearchDepth; this.SearchDepth <= this.MaxSearchDepth; this.SearchDepth++) { KillerMoves.Clear(); // Clear killer moves from previous iteration. History.Clear(); // Clear history when from previous iteration. if (Game.CaptureMoveAnalysisData && Game.MoveAnalysis.Count > 0) { Game.MoveAnalysis.Clear(); } score = this.Aspirate(player, principalVariation, score, Game.MoveAnalysis); if (!Game.IsInAnalyseMode && Game.ClockFixedTimePerMove.TotalSeconds <= 0 && !this.MyBrain.IsPondering && (this.MyBrain.ThinkingTimeElpased) > searchTimeCutoff) { throw new ForceImmediateMoveException(); } // Copy current PV to previous PV. this.LastPrincipalVariation.Clear(); foreach (Move moveCopy in principalVariation) { this.LastPrincipalVariation.Add(moveCopy); } WinBoard.SendThinking( this.SearchDepth, score, DateTime.Now - player.Clock.TurnStartTime, this.PositionsSearched, this.MyBrain.PrincipalVariationText); if (score > 99999 || score < -99999) { break; // Checkmate found so dont bother searching any deeper } } return score; }
private bool canMove(int x, int y, Moves mov) { //14 es el numero max que puede tomar , porque el 15 es suelo , y hasta el 14 son tiles que representan obstaculos return(ViewController._currentGameModel._map[GlobalVariables._yPosPlayer + x, GlobalVariables._xPosPlayer + y] <= 14 || currentMove == mov); }
/// <summary> /// Performs a Static Exchange Evaluation to determine the value of a move after all possible re-captures are resolved. /// http://chessprogramming.wikispaces.com/Static+Exchange+Evaluation /// </summary> /// <param name="moveMade"> /// Move to be evaluated /// </param> /// <returns> /// The see. /// </returns> private int SEE(Move moveMade) { // Static Exchange Evaluator // Generate moves Moves movesFriendly = new Moves(); Moves movesEnemy = new Moves(); moveMade.To.AttackersMoveList(movesFriendly, moveMade.Piece.Player); moveMade.To.AttackersMoveList(movesEnemy, moveMade.Piece.Player.OpposingPlayer); // Remove piece I'm going to move first from my list of moves foreach (Move move in movesFriendly) { if (move.Piece == moveMade.Piece) { movesFriendly.Remove(move); break; } } // sort remaining moves by piece value foreach (Move move in movesFriendly) { move.Score = 20 - move.Piece.BasicValue; } movesFriendly.SortByScore(); if (movesEnemy.Count > 1) { // sort remaining moves by piece value foreach (Move move in movesEnemy) { move.Score = 20 - move.Piece.BasicValue; } movesEnemy.SortByScore(); } int intTotalFriendlyGain = moveMade.PieceCaptured.BasicValue; int intLastMovedPieceValue = moveMade.Piece.BasicValue; // Now make a virtual move from each players move list, in order, until one of the players has no remaining moves. for (int intIndex = 0;; intIndex++) { if (intIndex >= movesEnemy.Count) { break; } intTotalFriendlyGain -= intLastMovedPieceValue; intLastMovedPieceValue = movesEnemy[intIndex].Piece.BasicValue; if (intIndex >= movesFriendly.Count) { break; } intTotalFriendlyGain += intLastMovedPieceValue; intLastMovedPieceValue = movesFriendly[intIndex].Piece.BasicValue; } return intTotalFriendlyGain; }
/// <summary> /// Sorts moves so that the best moves are first /// </summary> /// <param name="movesToSort"> /// List of moves to be sorted. /// </param> /// <param name="variableDepth"> /// Depth which starts at one and INCREASES as the search deepens. Its value is altered by search extension and reductions. Quiesence starts at depth 0. /// http://chessprogramming.wikispaces.com/Depth /// </param> /// <param name="movePv"> /// Move from previous iteration's principal variation. /// </param> /// <param name="moveHash"> /// // Best move from hash table. /// </param> /// <param name="moveKillerA"> /// Best killer move from this ply. /// </param> /// <param name="moveKillerA2"> /// Second best killer move from this ply. /// </param> /// <param name="moveKillerB"> /// Best killer move from previous ply. /// </param> /// <param name="moveKillerB2"> /// Second best killer move from previous ply. /// </param> /// <param name="player"> /// The player. /// </param> private void SortBestMoves( Moves movesToSort, int variableDepth, Move movePv, Move moveHash, Move moveKillerA, Move moveKillerA2, Move moveKillerB, Move moveKillerB2, Player player) { foreach (Move movex in movesToSort) { this.AssignMoveOrderScore( movex, variableDepth, movePv, moveHash, moveKillerA, moveKillerA2, moveKillerB, moveKillerB2, player); } movesToSort.SortByScore(); }
/// <summary> /// The purpose of quiescence search is to only evaluate "quiet" positions, or positions where there are no winning tactical moves to be made. /// This search is needed to avoid the horizon effect. /// http://chessprogramming.wikispaces.com/Quiescence+Search /// </summary> /// <param name="player"> /// The player to play. The player is alternated at each new ply of search. /// </param> /// <param name="ply"> /// True depth in plies. Starts at the max search depth and is DECREMENTED as alpha beta get deeper. /// </param> /// <param name="variableDepth"> /// Depth which starts at one and INCREASES as the search deepens. /// Its value is altered by search extension and reductions. Quiesence starts at depth 0. /// http://chessprogramming.wikispaces.com/Depth /// </param> /// <param name="alpha"> /// Alpha (α) is the lower bound, representing the minimum score that a node must reach in order to change the value of a previous node. /// http://chessprogramming.wikispaces.com/Alpha /// </param> /// <param name="beta"> /// Beta (β) is the upper bound of a score for the node. If the node value exceeds or equals beta, it means that the opponent will avoid this node, /// since his guaranteed score (Alpha of the parent node) is already greater. Thus, Beta is the best-score the opponent (min-player) could archive so far... /// http://chessprogramming.wikispaces.com/Beta /// </param> /// <param name="parentMove"> /// Move from the parent alpha beta call. /// </param> /// <param name="principalVariation"> /// The Principal variation (PV) is a sequence of moves is considered best and therefore expect to be played. /// This list of moves is collected during the alpha beta search. /// http://chessprogramming.wikispaces.com/Principal+variation /// </param> /// <param name="analysisParentBranch"> /// When move analysis is enabled, a tree of search moves is collected in this variable, which can be viewed in the GUI. /// </param> /// <returns> /// The best move for the player. /// </returns> private int Quiesce( Player player, int ply, int variableDepth, int alpha, int beta, Move parentMove, Moves principalVariation, Moves analysisParentBranch) { // Gather some stats if (variableDepth < this.MaxQuiesenceDepthReached) { this.MaxQuiesenceDepthReached = variableDepth; } // Calculate the score this.Evaluations++; int standPat = player.Score; if (standPat > 1000000 || standPat < -1000000) { // TODO Unit test that negative depths produce score that reduce as they get deeper. The purpose here is to make deeper checks score less than shallower ones. // TODO Investigate whether reduced mate scores are constantly reduced when going in and out of hashtable. standPat /= this.MaxSearchDepth - ply; } if (standPat >= beta) { Comment(parentMove, "(Q:PAT-CUT) "); return beta; } if (alpha < standPat) { // Comment(parentMove, "(Q:PAT-ALPHA) "); alpha = standPat; } // Generate moves - Captures and promotions only Moves movesPossible = new Moves(); player.GenerateLazyMoves(0, movesPossible, Moves.MoveListNames.CapturesPromotions, null); // Get move at same ply from previous iteration's principal variation. int indexPv = this.MaxSearchDepth - ply; Move movePv = null; if (indexPv < this.LastPrincipalVariation.Count) { movePv = this.LastPrincipalVariation[indexPv]; } // Sort moves this.SortBestMoves(movesPossible, 0, movePv, null, null, null, null, null, player); Moves movesPv = new Moves(); foreach (Move move in movesPossible) { if (move.Score < 0) { // Losing capture from SEE, so skip this move. continue; } // Make capture, but skip illegal moves Move moveThis = move.Piece.Move(move.Name, move.To); if (player.IsInCheck) { Move.Undo(moveThis); continue; } this.PositionsSearched++; // If this is the deepest stage of iterative deepening, then capture move analysis data. if (Game.CaptureMoveAnalysisData && this.SearchDepth == this.MaxSearchDepth) { // Add moves to post-move analysis tree, if option set by user analysisParentBranch.Add(moveThis); moveThis.Moves = new Moves(); } moveThis.Score = -this.Quiesce( player.OpposingPlayer, ply - 1, variableDepth - 1, -beta, -alpha, parentMove, movesPv, moveThis.Moves); // Undo the capture move Move.Undo(moveThis); if (moveThis.Score >= beta) { Comment(parentMove, "(Q:CUT) "); return beta; } if (moveThis.Score > alpha) { alpha = moveThis.Score; // Comment(parentMove, "(Q:^ALPHA) "); // Collect the Prinicial Variation lock (principalVariation) { principalVariation.Clear(); principalVariation.Add(moveThis); foreach (Move moveCopy in movesPv) { principalVariation.Add(moveCopy); } } } } return alpha; }
/// <summary> /// Recursive element of Perft. /// </summary> /// <param name="player"> /// The player. /// </param> /// <param name="depth"> /// The depth. /// </param> private void PerftPly(Player player, int depth) { if (depth <= 0) { return; } Moves moves = new Moves(); player.GenerateLegalMoves(moves); foreach (Move move in moves) { Move moveUndo = move.Piece.Move(move.Name, move.To); this.PositionsSearched++; // Debug.WriteLine(move.DebugText + ","); this.PerftPly(player.OpposingPlayer, depth - 1); Move.Undo(moveUndo); } }
/// <summary> /// Apply reductions to the search node. /// http://chessprogramming.wikispaces.com/Reductions /// </summary> /// <param name="extensionOrReduction">Number of extensions or reductions applied in the search node. Extensions positive, reductions negative.</param> /// <param name="totalExtensionsOrReductions">Total number of extensions or reductions applied to the entire search tree. Extensions positive, reductions negative.</param> /// <param name="ply"> True depth in plies. Starts at the max search depth and is DECREMENTED as alpha beta get deeper. </param> /// <param name="variableDepth"> Variable depth which starts at the max search depth and is DECREMENTED as alpha beta get deeper. Its value is altered by search extension and reductions. Quiesence starts at depth 0. http://chessprogramming.wikispaces.com/Depth </param> /// <param name="isPvNode">True if the search node is part of the principal variant.</param> /// <param name="isInCheck">True if the play-to-play is in check.</param> /// <param name="alpha"> Alpha (α) is the lower bound, representing the minimum score that a node must reach in order to change the value of a previous node. http://chessprogramming.wikispaces.com/Alpha </param> /// <param name="player"> The player to play. The player is alternated at each new ply of search. </param> /// <param name="moveMade">Move made by the player-to-play.</param> /// <param name="legalMovesAttempted">Number of legal moves attempted.</param> /// <param name="movesPv">Prinipal variant at and below this search node.</param> private void ApplyReductions( ref int extensionOrReduction, int totalExtensionsOrReductions, int ply, int variableDepth, bool isPvNode, bool isInCheck, int alpha, Player player, Move moveMade, int legalMovesAttempted, Moves movesPv) { if (!Game.EnableReductions) { // Reductions disabled, so exit. return; } if (isPvNode) { // We're at a PV node, so not safe to reduce. return; } if (extensionOrReduction != 0) { // Extension has been applied, so don't reduce. return; } if (moveMade.PieceCaptured != null) { // Captures are too risky to reduce. // TODO Consider reducing LOSING captures, according to SEE. return; } if (isInCheck) { // Player-to-play is in check, so not safe to reduce. return; } if (moveMade.IsEnemyInCheck) { // Don't reduce move that put the enemy in check return; } // Margin futility based reductions if (Game.EnableReductionFutilityMargin && variableDepth > 2) { int[] margin = { 0, 0, 0, 5000, 5000, 7000, 7000, 9000, 9000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000 }; int intLazyEval = player.Score; if (alpha > intLazyEval + margin[variableDepth]) { extensionOrReduction = -1; Comment(moveMade, "R-MARG" + (margin[variableDepth] / 1000) + " "); } } // Futility Pruning http://chessprogramming.wikispaces.com/Futility+Pruning if (Game.EnableReductionFutilityFixedDepth && extensionOrReduction == 0) { switch (variableDepth) { case 2: case 3: // case 4: int intLazyEval = player.Score; switch (variableDepth) { case 2: // Standard Futility Pruning if (intLazyEval + 3000 <= alpha) { extensionOrReduction = -2; Comment(moveMade, "R-FUT3 "); } break; case 3: // Extended Futility Pruning if (intLazyEval + 5000 <= alpha) { extensionOrReduction = -3; Comment(moveMade, "R-FUT5 "); } break; case 4: // Deep Futility Pruning if (intLazyEval + 9750 <= alpha) { extensionOrReduction = -4; Comment(moveMade, "R-FUT9 "); } break; } break; } } // Late Move Reductions http://chessprogramming.wikispaces.com/Late+Move+Reductions // Reduce if move is 1) low in the search order and 2) has a poor history score and 3) not in check and 4) not already reduced or extended. if (Game.EnableReductionLateMove && extensionOrReduction == 0) { if (legalMovesAttempted > 3) { int historyScore = HistoryHeuristic.Retrieve( player.Colour, moveMade.From.Ordinal, moveMade.To.Ordinal); if (historyScore == 0) { int eval = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, variableDepth - 2, -alpha - 1, -alpha, moveMade, movesPv, totalExtensionsOrReductions, null); if (eval < alpha) { extensionOrReduction = -1; Comment(moveMade, "R-LMR "); } } } } }
/// <summary> /// Performs the search foe the best move, using a specialised form of alpha beta search, named Principal Variation Search (PVS) . http://chessprogramming.wikispaces.com/Alpha-Beta http://chessprogramming.wikispaces.com/Principal+Variation+Search /// </summary> /// <param name="player"> The player to play. The player is alternated at each new ply of search. </param> /// <param name="ply"> True depth in plies. Starts at the max search depth and is DECREMENTED as alpha beta get deeper. </param> /// <param name="variableDepth"> Variable depth which starts at the max search depth and is DECREMENTED as alpha beta get deeper. Its value is altered by search extension and reductions. Quiesence starts at depth 0. http://chessprogramming.wikispaces.com/Depth </param> /// <param name="alpha"> Alpha (α) is the lower bound, representing the minimum score that a node must reach in order to change the value of a previous node. http://chessprogramming.wikispaces.com/Alpha </param> /// <param name="beta"> Beta (β) is the upper bound of a score for the node. If the node value exceeds or equals beta, it means that the opponent will avoid this node, since his guaranteed score (Alpha of the parent node) is already greater. Thus, Beta is the best-score the opponent (min-player) could archive so far... http://chessprogramming.wikispaces.com/Beta </param> /// <param name="parentMove"> Move from the parent alpha beta call. </param> /// <param name="principalVariation"> The Principal variation (PV) is a sequence of moves is considered best and therefore expect to be played. This list of moves is collected during the alpha beta search. http://chessprogramming.wikispaces.com/Principal+variation </param> /// <param name="totalExtensionsOrReductions"> Holds a counter indicating the number of search extensions or reductions at the current search depth. A positive nunber indicates there have been extensions in a previous ply, negative indicates a reduction. http://chessprogramming.wikispaces.com/Extensions http://chessprogramming.wikispaces.com/Reductions </param> /// <param name="analysisParentBranch"> When move analysis is enabled, a tree of search moves is collected in this variable, which can be viewed in the GUI. </param> /// <returns> The score of the best move. </returns> /// <exception cref="ForceImmediateMoveException">Raised when the user requests for thinking to be terminated, and immediate move to made.</exception> private int AlphaBetaPvs( Player player, int ply, int variableDepth, int alpha, int beta, Move parentMove, Moves principalVariation, int totalExtensionsOrReductions, Moves analysisParentBranch) { // TODO Try hash and killer moves, before generating all moves. It will save time. // Score of the move being examined in the move loop. int val; // Type of hash entry that will be stored in the Transposition Table. http://chessprogramming.wikispaces.com/Transposition+Table HashTable.HashTypeNames hashType = HashTable.HashTypeNames.Alpha; // The best move found at this node. Assigned if/when alpha is improved. Move bestMove = null; // Indicates that this entire node is a PV Node. http://chessprogramming.wikispaces.com/Node+Types bool isPvNode = false; // A counter of the number of legal moves we've examines in this node so far. int legalMovesAttempted = 0; // Indicates whether the player-to-play is in check at this node. bool isInCheck = player.IsInCheck; // Exit immediately, if instructed to do so. i.e. the user has click the "Move Now" button. if (this.forceExitWithMove) { throw new ForceImmediateMoveException(); } // This node has reached 3-move-repetition, so return the current score, and don't bother searching any deeper. if (parentMove != null && parentMove.IsThreeMoveRepetition) { return player.Score; } if (totalExtensionsOrReductions > this.MaxExtensions) { this.MaxExtensions = totalExtensionsOrReductions; } // Check if this node (position) is in the tranposition (hash) table, and if appropriate, return the score stored there. if (ply != this.SearchDepth && (val = HashTable.ProbeForScore(Board.HashCodeA, Board.HashCodeB, ply, alpha, beta, player.Colour)) != HashTable.NotFoundInHashTable) { // High values of "val" indicate that a checkmate has been found if (val > 1000000 || val < -1000000) { Comment(parentMove, "Mate: " + (this.MaxSearchDepth - variableDepth) + " "); if (this.MaxSearchDepth - variableDepth > 0) { val /= this.MaxSearchDepth - variableDepth; } } return val; } // Depth <= 0 means we're into Quiescence searching if (variableDepth <= 0) { return this.Quiesce( player, ply, variableDepth, alpha, beta, parentMove, principalVariation, analysisParentBranch); } // Generate "lazy" moves (lazy means we include moves that put our own king in check) Moves movesPossible = new Moves(); player.GenerateLazyMoves(movesPossible, Moves.MoveListNames.All); // Stores the PV that is local to this node and it's children. Moves localPrincipalVariation = new Moves(); if (Game.EnableNullMovePruning) { // Adaptive Null-move pruning // http://chessprogramming.wikispaces.com/Null+Move+Pruning int r = variableDepth > 6 ? 3 : 2; if (variableDepth > (r + 1) && parentMove != null && parentMove.Name != Move.MoveNames.NullMove && Game.Stage != Game.GameStageNames.End && !isInCheck) { Move moveNull = new Move(Game.TurnNo, 0, Move.MoveNames.NullMove, null, null, null, null, 0, 0); val = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, variableDepth - r - 1, -beta, -beta + 1, moveNull, localPrincipalVariation, totalExtensionsOrReductions, null); if (val >= beta) { return beta; } } } // Get last iteration's best move from the transposition Table Move moveHash = HashTable.ProbeForBestMove(Board.HashCodeA, Board.HashCodeB, player.Colour); // Get Killers Move moveKillerA = KillerMoves.RetrieveA(ply); Move moveKillerB = KillerMoves.RetrieveB(ply); Move moveKillerA2 = KillerMoves.RetrieveA(ply + 2); Move moveKillerB2 = KillerMoves.RetrieveB(ply + 2); // Get move at same ply from previous iteration's principal variation. int indexPv = this.SearchDepth - ply; Move movePv = null; if (indexPv < this.LastPrincipalVariation.Count) { movePv = this.LastPrincipalVariation[indexPv]; } // Sort moves this.SortBestMoves( movesPossible, variableDepth, movePv, moveHash, moveKillerA, moveKillerA2, moveKillerB, moveKillerB2, player); if (ply == this.SearchDepth) { this.TotalPositionsToSearch = movesPossible.Count; this.SearchPositionNo = 0; } foreach (Move move in movesPossible) { // Make the move Move moveMade = move.Piece.Move(move.Name, move.To); this.PositionsSearchedThisTurn++; this.PositionsSearchedThisIteration++; moveMade.DebugComment += move.DebugComment; if (ply == this.SearchDepth) { this.SearchPositionNo++; this.CurrentMoveSearched = moveMade; if (this.SearchMoveConsideredEvent != null) { this.SearchMoveConsideredEvent(); } } // This move put our player in check, so abort, and skip to next move. if (player.IsInCheck) { Move.Undo(moveMade); continue; } legalMovesAttempted++; if (bestMove == null) { bestMove = moveMade; } if (Game.CaptureMoveAnalysisData) { // Add moves to post-move analysis tree, if option set by user if (parentMove == null || parentMove.Name != Move.MoveNames.NullMove) { if (analysisParentBranch != null) { analysisParentBranch.Add(moveMade); } } moveMade.Moves = new Moves(); } int extensionOrReduction = 0; // Extensions // http://chessprogramming.wikispaces.com/Extensions ApplyExtensions(ref extensionOrReduction, movesPossible, moveMade, parentMove); // Reductions // http://chessprogramming.wikispaces.com/Reductions this.ApplyReductions( ref extensionOrReduction, totalExtensionsOrReductions, ply, variableDepth, isPvNode, isInCheck, alpha, player, moveMade, legalMovesAttempted, localPrincipalVariation); if (Game.EnablePvsSearch && isPvNode) { // Attempt a Principal Variation Search (PVS) using a zero window. http://chessprogramming.wikispaces.com/Principal+Variation+Search val = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, (variableDepth + extensionOrReduction) - 1, -alpha - 1, -alpha, moveMade, localPrincipalVariation, totalExtensionsOrReductions + extensionOrReduction, moveMade.Moves); if ((val > alpha) && (val < beta)) { // PVS failed. Have to re-search using a full alpha-beta window. Comment(moveMade, "-PVS-WIN- "); if (Game.CaptureMoveAnalysisData && parentMove != null && parentMove.Name != Move.MoveNames.NullMove) { moveMade.Moves.Clear(); } val = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, (variableDepth + extensionOrReduction) - 1, -beta, -alpha, moveMade, localPrincipalVariation, totalExtensionsOrReductions + extensionOrReduction, moveMade.Moves); } else { Comment(moveMade, "-F- "); } } else { // Not a PV node, so just do a normal alpha-beta search. val = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, (variableDepth + extensionOrReduction) - 1, -beta, -alpha, moveMade, localPrincipalVariation, totalExtensionsOrReductions + extensionOrReduction, moveMade.Moves); } move.Score = moveMade.Score = val; // Take back the move Move.Undo(moveMade); if (val >= beta) { // Test for a beta cut-off http://chessprogramming.wikispaces.com/Beta-Cutoff alpha = beta; moveMade.Beta = beta; hashType = HashTable.HashTypeNames.Beta; bestMove = moveMade; Comment(parentMove, "(CUT) "); if (moveMade.PieceCaptured == null) { // Add this cut move to the history heuristic. HistoryHeuristic.Record(player.Colour, moveMade.From.Ordinal, moveMade.To.Ordinal, ply * ply); // Add this cut move to the killer move heuristic. KillerMoves.RecordPossibleKillerMove(ply, moveMade); } goto Exit; } if (val > alpha) { // Test if the move made can improve alpha. // If so, then it become the new best move, and local PV for this node. http://chessprogramming.wikispaces.com/Node Comment(moveMade, "*PV* " + alpha + "<" + val); isPvNode = true; /* This is a PV node */ alpha = val; hashType = HashTable.HashTypeNames.Exact; bestMove = moveMade; // Collect the Prinicial Variation lock (principalVariation) { principalVariation.Clear(); principalVariation.Add(moveMade); foreach (Move moveCopy in localPrincipalVariation) { principalVariation.Add(moveCopy); } } } moveMade.Alpha = alpha; moveMade.Beta = beta; if (!Game.IsInAnalyseMode && !this.MyBrain.IsPondering && this.SearchDepth > MinSearchDepth && this.MyBrain.ThinkingTimeElpased > this.MaxSearchTimeAllowed) { throw new ForceImmediateMoveException(); } } if (!isPvNode && parentMove != null) { // All positions were search at this node. It's not a PV node, and no beta cut-off occured, // therefore it's an ALL node. http://chessprogramming.wikispaces.com/Node+Types#ALL Comment(parentMove, "(ALL) "); } // Check for Stalemate if (legalMovesAttempted == 0) { alpha = player.Score; } Exit: // Record best move if (bestMove != null) { HashTable.RecordHash( Board.HashCodeA, Board.HashCodeB, ply, alpha, hashType, bestMove.From.Ordinal, bestMove.To.Ordinal, bestMove.Name, player.Colour); } else { HashTable.RecordHash( Board.HashCodeA, Board.HashCodeB, ply, alpha, hashType, -1, -1, Move.MoveNames.NullMove, player.Colour); } return alpha; }
/// <summary> /// Performs the search foe the best move, using a specialised form of alpha beta search, named Principal Variation Search (PVS) . /// http://chessprogramming.wikispaces.com/Alpha-Beta /// http://chessprogramming.wikispaces.com/Principal+Variation+Search /// </summary> /// <param name="player"> /// The player to play. The player is alternated at each new ply of search. /// </param> /// <param name="ply"> /// True depth in plies. Starts at the max search depth and is DECREMENTED as alpha beta get deeper. /// </param> /// <param name="variableDepth"> /// Variable depth which starts at the max search depth and is DECREMENTED as alpha beta get deeper. /// Its value is altered by search extension and reductions. Quiesence starts at depth 0. /// http://chessprogramming.wikispaces.com/Depth /// </param> /// <param name="alpha"> /// Alpha (α) is the lower bound, representing the minimum score that a node must reach in order to change the value of a previous node. /// http://chessprogramming.wikispaces.com/Alpha /// </param> /// <param name="beta"> /// Beta (β) is the upper bound of a score for the node. If the node value exceeds or equals beta, it means that the opponent will avoid this node, /// since his guaranteed score (Alpha of the parent node) is already greater. Thus, Beta is the best-score the opponent (min-player) could archive so far... /// http://chessprogramming.wikispaces.com/Beta /// </param> /// <param name="parentMove"> /// Move from the parent alpha beta call. /// </param> /// <param name="principalVariation"> /// The Principal variation (PV) is a sequence of moves is considered best and therefore expect to be played. /// This list of moves is collected during the alpha beta search. /// http://chessprogramming.wikispaces.com/Principal+variation /// </param> /// <param name="totalExtensionsAndReducations"> /// Holds a counter indicating the number of search extensions or reductions at the current search depth. /// A positive nunber indicates there have been extensions in a previous ply, negative indicates a reduction. /// http://chessprogramming.wikispaces.com/Extensions /// http://chessprogramming.wikispaces.com/Reductions /// </param> /// <param name="analysisParentBranch"> /// When move analysis is enabled, a tree of search moves is collected in this variable, which can be viewed in the GUI. /// </param> /// <returns> /// The score of the best move. /// </returns> /// <exception cref="ForceImmediateMoveException"> /// Raised when the user requests for thinking to be terminated, and immediate move to made. /// </exception> private int AlphaBetaPvs( Player player, int ply, int variableDepth, int alpha, int beta, Move parentMove, Moves principalVariation, int totalExtensionsAndReducations, Moves analysisParentBranch) { // TODO Don't generate hash or killer moves. int val; HashTable.HashTypeNames hashType = HashTable.HashTypeNames.Alpha; Move moveBest = null; bool blnPvNode = false; int intLegalMovesAttempted = 0; bool blnIsInCheck = player.IsInCheck; if (this.forceExitWithMove) { throw new ForceImmediateMoveException(); } this.PositionsSearched++; if (parentMove != null && parentMove.IsThreeMoveRepetition) { return player.Score; } if (ply != this.SearchDepth && (val = HashTable.ProbeHash(Board.HashCodeA, Board.HashCodeB, ply, alpha, beta, player.Colour)) != HashTable.NotFoundInHashTable) { // High values of "val" indicate that a checkmate has been found if (val > 1000000 || val < -1000000) { Comment(parentMove, "Mate: " + (this.MaxSearchDepth - variableDepth) + " "); if (this.MaxSearchDepth - variableDepth > 0) { val /= this.MaxSearchDepth - variableDepth; } } return val; } // Generate moves Moves movesPossible = new Moves(); player.GenerateLazyMoves(variableDepth, movesPossible, Moves.MoveListNames.All, null); // Depth <= 0 means we're into Quiescence searching if (variableDepth <= 0) { return this.Quiesce( player, ply, variableDepth, alpha, beta, parentMove, principalVariation, analysisParentBranch); } Moves movesPv = new Moves(); // Adaptive Null-move forward pruning int r = variableDepth > 6 ? 3 : 2; if (variableDepth > (r + 1) && parentMove != null && parentMove.Name != Move.MoveNames.NullMove && Game.Stage != Game.GameStageNames.End && !blnIsInCheck) { Move moveNull = new Move(Game.TurnNo, 0, Move.MoveNames.NullMove, null, null, null, null, 0, 0); val = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, variableDepth - r - 1, -beta, -beta + 1, moveNull, movesPv, totalExtensionsAndReducations, null); if (val >= beta) { return beta; } } // Get last iteration's best move from the transposition Table Move moveHash = HashTable.ProbeForBestMove(Board.HashCodeA, Board.HashCodeB, player.Colour); // Get Killers Move moveKillerA = KillerMoves.RetrieveA(ply); Move moveKillerB = KillerMoves.RetrieveB(ply); Move moveKillerA2 = KillerMoves.RetrieveA(ply + 2); Move moveKillerB2 = KillerMoves.RetrieveB(ply + 2); // Get move at same ply from previous iteration's principal variation. int indexPv = this.SearchDepth - ply; Move movePv = null; if (indexPv < this.LastPrincipalVariation.Count) { movePv = this.LastPrincipalVariation[indexPv]; } // Sort moves this.SortBestMoves( movesPossible, variableDepth, movePv, moveHash, moveKillerA, moveKillerA2, moveKillerB, moveKillerB2, player); if (ply == this.SearchDepth) { this.TotalPositionsToSearch = movesPossible.Count; this.SearchPositionNo = 0; } foreach (Move move in movesPossible) { Move moveThis = move.Piece.Move(move.Name, move.To); moveThis.DebugComment += move.DebugComment; if (ply == this.SearchDepth) { this.SearchPositionNo++; this.CurrentMoveSearched = moveThis; if (this.SearchMoveConsideredEvent != null) { this.SearchMoveConsideredEvent(); } } // This move put the player in check, so abort and move onto next move. if (player.IsInCheck) { Move.Undo(moveThis); continue; } intLegalMovesAttempted++; if (moveBest == null) { moveBest = moveThis; } if (Game.CaptureMoveAnalysisData) { // Add moves to post-move analysis tree, if option set by user if (parentMove == null || parentMove.Name != Move.MoveNames.NullMove) { analysisParentBranch.Add(moveThis); } moveThis.Moves = new Moves(); } // http://chessprogramming.wikispaces.com/Extensions // TODO Consider fractional extensions. // Search Extensions int intExtensionOrReduction = 0; if (movesPossible.Count == 1) { // Single Response intExtensionOrReduction = 1; Comment(moveThis, "E-1REP "); } else if (parentMove != null && parentMove.IsEnemyInCheck) { // Check evasion intExtensionOrReduction = 1; Comment(moveThis, "E-CHK "); } else if (parentMove != null && parentMove.PieceCaptured != null && moveThis.PieceCaptured != null && parentMove.PieceCaptured.BasicValue == moveThis.PieceCaptured.BasicValue && parentMove.To == moveThis.To) { // Recapture piece of same basic value (on the same square) intExtensionOrReduction = 1; Comment(moveThis, "E-RECAP "); } else if (moveThis.Piece.Name == Piece.PieceNames.Pawn && ((moveThis.Piece.Player.Colour == Player.PlayerColourNames.White && moveThis.To.Rank == 6) || (moveThis.Piece.Player.Colour == Player.PlayerColourNames.Black && moveThis.To.Rank == 1))) { // Pawn push to 7th rank intExtensionOrReduction = 1; Comment(moveThis, "E-PAWN7 "); } // Reductions // Only reduce if this move hasn't already been extended (or reduced). if (!blnPvNode && intExtensionOrReduction == 0) { if (variableDepth > 2 && !blnIsInCheck && moveThis.PieceCaptured == null && !moveThis.IsEnemyInCheck) { int[] margin = { 0, 0, 0, 5000, 5000, 7000, 7000, 9000, 9000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000 }; // int intLazyEval = this.TotalPieceValue - this.OtherPlayer.TotalPieceValue; int intLazyEval = player.Score; if (alpha > intLazyEval + margin[variableDepth]) { intExtensionOrReduction = -1; Comment(moveThis, "R-MARG" + (margin[variableDepth] / 1000) + " "); } } // Futility Pruning http://chessprogramming.wikispaces.com/Futility+Pruning if (!blnIsInCheck && intExtensionOrReduction == 0) { switch (variableDepth) { case 2: case 3: //case 4: if (moveThis.PieceCaptured == null && !move.IsEnemyInCheck) { int intLazyEval = player.Score; switch (variableDepth) { case 2: // Standard Futility Pruning if (intLazyEval + 3000 <= alpha) { intExtensionOrReduction = -1; Comment(moveThis, "R-FUT3 "); } break; case 3: // Extended Futility Pruning if (intLazyEval + 5000 <= alpha) { intExtensionOrReduction = -1; Comment(moveThis, "R-FUT5 "); } break; case 4: // Deep Futility Pruning if (intLazyEval + 9750 <= alpha) { intExtensionOrReduction = -1; Comment(moveThis, "R-FUT9 "); } break; } } break; } } // Late Move Reductions http://chessprogramming.wikispaces.com/Late+Move+Reductions // Reduce if move is 1) low in the search order and 2) has a poor history score. /* if (!blnIsInCheck && intExtensionOrReduction == 0 && moveThis.PieceCaptured == null) { if (intLegalMovesAttempted > 3) { int historyScore = History.Retrieve(player.Colour, moveThis.From.Ordinal, moveThis.To.Ordinal); if (historyScore == 0) { intExtensionOrReduction = -1; Comment(moveThis, "R-LMR "); } } } */ } /* if (intExtension>0 && intTotalExtensions>=m_intSearchDepth) { intExtension = 0; } */ if (totalExtensionsAndReducations > this.MaxExtensions) { this.MaxExtensions = totalExtensionsAndReducations; Comment(moveThis, "^MaxExt: " + totalExtensionsAndReducations + " "); } /* #if DEBUG // Avoid to break in a zero window research so alpha + 1 < beta if ((alpha + 1 < beta) && DebugMatchVariation(m_intSearchDepth - ply, moveThis)) Debugger.Break(); #endif */ if (blnPvNode) { // Attempt a Principal Variation Search (PVS) using a zero window. http://chessprogramming.wikispaces.com/Principal+Variation+Search val = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, (variableDepth + intExtensionOrReduction) - 1, -alpha - 1, -alpha, moveThis, movesPv, totalExtensionsAndReducations + intExtensionOrReduction, moveThis.Moves); if ((val > alpha) && (val < beta)) { // PVS failed. Have to re-search using a full alpha-beta window. Comment(moveThis, "-PVS-WIN- "); if (Game.CaptureMoveAnalysisData && parentMove != null && parentMove.Name != Move.MoveNames.NullMove) { moveThis.Moves.Clear(); } val = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, (variableDepth + intExtensionOrReduction) - 1, -beta, -alpha, moveThis, movesPv, totalExtensionsAndReducations + intExtensionOrReduction, moveThis.Moves); } else { Comment(moveThis, "-F- "); } } else { // Not a PV node, so just do a normal alpha-beta search. val = -this.AlphaBetaPvs( player.OpposingPlayer, ply - 1, (variableDepth + intExtensionOrReduction) - 1, -beta, -alpha, moveThis, movesPv, totalExtensionsAndReducations + intExtensionOrReduction, moveThis.Moves); } move.Score = moveThis.Score = val; Move.Undo(moveThis); if (val >= beta) { alpha = beta; moveThis.Beta = beta; hashType = HashTable.HashTypeNames.Beta; moveBest = moveThis; Comment(parentMove, "(CUT) "); if (moveThis.PieceCaptured == null) { // Add this cut move to the history heuristic. History.Record(player.Colour, moveThis.From.Ordinal, moveThis.To.Ordinal, ply * ply); // Add this cut move to the killer move heuristic. KillerMoves.RecordPossibleKillerMove(ply, moveThis); } goto Exit; } if (val > alpha) { Comment(moveThis, "*PV* " + alpha + "<" + val); blnPvNode = true; /* This is a PV node */ alpha = val; hashType = HashTable.HashTypeNames.Exact; moveBest = moveThis; // Collect the Prinicial Variation lock (principalVariation) { principalVariation.Clear(); principalVariation.Add(moveThis); foreach (Move moveCopy in movesPv) { principalVariation.Add(moveCopy); } } // #if DEBUG // Debug.WriteLineIf((ply == m_intSearchDepth) && (ply > 1), string.Format("{0} {1} {2}", ply, PvLine(principalVariation), alpha)); // #endif } moveThis.Alpha = alpha; moveThis.Beta = beta; if (!Game.IsInAnalyseMode && !this.MyBrain.IsPondering && this.SearchDepth > MinSearchDepth && MyBrain.ThinkingTimeElpased > this.MaxSearchTimeAllowed) { throw new ForceImmediateMoveException(); } } if (!blnPvNode && parentMove != null) { Comment(parentMove, "(ALL) "); } // Check for Stalemate if (intLegalMovesAttempted == 0) { alpha = player.Score; } Exit: // Record best move if (moveBest != null) { HashTable.RecordHash( Board.HashCodeA, Board.HashCodeB, ply, alpha, hashType, moveBest.From.Ordinal, moveBest.To.Ordinal, moveBest.Name, player.Colour); } else { HashTable.RecordHash( Board.HashCodeA, Board.HashCodeB, ply, alpha, hashType, -1, -1, Move.MoveNames.NullMove, player.Colour); } return alpha; }
public async Task <Game> StartAsync() { InitialTurn ^= 1; // 2回に1回開始局面を変更する if (ChangeOpening) { OpeningIndex = Random.Next(Openings.Length); } ChangeOpening = !ChangeOpening; Moves.Clear(); position.Set(RocketTanuki.Position.StartposSfen); foreach (var move in Util.Split(Openings[OpeningIndex])) { if (Moves.Count >= NumBookMoves) { break; } if (move == "startpos" || move == "moves") { continue; } Moves.Add(new Move { Best = move, Next = "none", Book = 1, }); position.DoMove(RocketTanuki.Move.FromUsiString(position, move)); } Turn = InitialTurn; foreach (var engine in Engines) { if (!await engine.IsreadyAsync()) { ShowErrorMessage($"isreadyコマンドの送信に失敗しました。エンジン({engine})が異常終了またはタイムアウトしました。"); } await engine.UsinewgameAsync(); } for (int engineIndex = 0; engineIndex < 2; ++engineIndex) { CurrentTimes[engineIndex] = InitialTimes[engineIndex]; NodesForThisGame[engineIndex] = Nodes[engineIndex]; if (NodesRandomPercent[engineIndex] != 0 && !NodesRandomEveryMove[engineIndex]) { var nodesRandom = NodesRandomPercent[engineIndex] * 0.01; var delta = NodesForThisGame[engineIndex] * ((Random.NextDouble() * nodesRandom * 2.0) - nodesRandom); NodesForThisGame[engineIndex] += (int)delta; } } // エンジン1とエンジン2の設定が、両方とも1局を通して乱数が同じで、 // その他の思考ノード数のパラメーターが等しい場合、思考ノード数を同じにする。 if (!NodesRandomEveryMove[0] && !NodesRandomEveryMove[1] && Nodes[0] == Nodes[1] && NodesRandomPercent[0] == NodesRandomPercent[1]) { NodesForThisGame[1] = NodesForThisGame[0]; } // 千日手判定用のデータをクリアする hashToCount.Clear(); // 対局開始 while (Moves.Count < MaxMovesToDraw) { // position await Engines[Turn].PositionAsync(Moves.Select(x => x.Best).ToList()); // 千日手の判定 var hash = position.Hash; if (!hashToCount.ContainsKey(hash)) { hashToCount[hash] = 0; } if (++hashToCount[hash] == 4) { Moves.Add(new Move() { Draw = true }); return(this); } // go int nodes = NodesForThisGame[Turn]; if (NodesRandomPercent[Turn] != 0 && NodesRandomEveryMove[Turn]) { var nodesRandom = NodesRandomPercent[Turn] * 0.01; var delta = nodes * ((Random.NextDouble() * nodesRandom * 2.0) - nodesRandom); nodes += (int)delta; } var nameAndValues = new Dictionary <string, int> { { "btime", CurrentTimes[InitialTurn] }, { "wtime", CurrentTimes[InitialTurn ^ 1] }, { "byoyomi", Byoyomis[Turn] }, { "binc", Incs[InitialTurn] }, { "winc", Incs[InitialTurn ^ 1] }, { "nodes", nodes }, { "rtime", Rtime[Turn] }, }; goDateTime = DateTime.Now; var move = await Engines[Turn].GoAsync(nameAndValues); // 持ち時間から思考時間を引く var bestmoveDateTime = DateTime.Now; var thinkingTime = bestmoveDateTime - goDateTime; CurrentTimes[Turn] += Incs[Turn]; CurrentTimes[Turn] -= (int)thinkingTime.TotalMilliseconds; CurrentTimes[Turn] = Math.Max(CurrentTimes[Turn], 0); Moves.Add(move); if (move.Resign || move.Win) { return(this); } // 対局終了時に、最後の手を指した側のエンジンを指すようにする。 Turn ^= 1; position.DoMove(RocketTanuki.Move.FromUsiString(position, move.Best)); } Moves.Add(new Move() { Draw = true }); return(this); }
/// <summary> /// Aspiration windows are a way to reduce the search space in an alpha-beta search. /// The technique is to use a guess of the expected value (usually from the last iteration in iterative deepening), /// and use a window around this as the alpha-beta bounds. Because the window is narrower, more beta cutoffs are achieved, /// and the search takes a shorter time. The drawback is that if the true score is outside this window, then a costly re-search must be made. /// Typical window sizes are 1/2 to 1/4 of a pawn on either side of the guess. /// http://chessprogramming.wikispaces.com/Aspiration+Windows /// http://chessprogramming.wikispaces.com/PVS+and+aspiration /// </summary> /// <param name="player"> /// The player to play. /// </param> /// <param name="principalVariation"> /// When move analysis is enabled, a tree of search moves is collected in this variable, which can be viewed in the GUI. /// </param> /// <param name="lastIterationsScore"> /// Score from the previous (iterative deepending) iteration. Used as the centre of the aspiration window. /// </param> /// <param name="analysisParentBranch"> /// The analysis Parent Branch. When move analysis is enabled, a tree of search moves is collected in this variable, which can be viewed in the GUI. /// </param> /// <returns> /// Score of the best move found. /// </returns> private int Aspirate( Player player, Moves principalVariation, int lastIterationsScore, Moves analysisParentBranch) { int alpha = MinScore; // Score of the best move found so far int beta = MaxScore; // Score of the best move found by the opponent int val = alpha; // TODO DISABLED: Investigate why aspiration is worse for SharpChess for (int intAttempt = 2; intAttempt < 3; intAttempt++) { switch (intAttempt) { case 0: alpha = lastIterationsScore - 500; beta = lastIterationsScore + 500; break; case 1: alpha = lastIterationsScore - 2000; beta = lastIterationsScore + 2000; break; case 2: alpha = MinScore; beta = MaxScore; break; } val = this.AlphaBetaPvs( player, this.SearchDepth, this.SearchDepth, alpha, beta, null, principalVariation, 0, analysisParentBranch); if (val > alpha && val < beta) { break; } } return val; }
/// <summary> /// The build hashtable. /// </summary> /// <param name="xmlnodeParent"> /// The xmlnode parent. /// </param> /// <param name="player"> /// The player. /// </param> private static void BuildHashtable(XmlElement xmlnodeParent, Player player) { Moves moves; Hashtable hashtable = player.Colour == Player.PlayerColourNames.White ? HashtableWhite : HashtableBlack; if (!hashtable.ContainsKey(Board.HashCodeA)) { moves = new Moves(); hashtable.Add(Board.HashCodeA, moves); } else { moves = (Moves)hashtable[Board.HashCodeA]; } foreach (XmlElement xmlnodeMove in xmlnodeParent.ChildNodes) { Move moveThis = Board.GetSquare(xmlnodeMove.GetAttribute("f")).Piece.Move(Move.MoveNameFromString(xmlnodeMove.GetAttribute("n")), Board.GetSquare(xmlnodeMove.GetAttribute("t"))); moveThis.Score = xmlnodeMove.ChildNodes.Count; moves.Add(moveThis); BuildHashtable(xmlnodeMove, player.OpposingPlayer); Move.Undo(moveThis); } }
public void SplitSolutions(string[] solutions) { int moves = 0; int actions = 0; for (int i = 0; i < solutions.Length; i++) { string s = solutions[i]; s = s.Remove (0, 4); if (s.StartsWith ("MOVETO", System.StringComparison.CurrentCultureIgnoreCase)) { moves++; } else { actions++; } } Moves[] moveArray = new Moves[moves]; Actions[] actionArray = new Actions[actions]; int movesIter = 0; int actionsIter = 0; for (int i = 0; i < solutions.Length; i++) { string s = solutions[i]; s = s.Remove (0, 4); if (s.StartsWith ("MOVETO", System.StringComparison.CurrentCultureIgnoreCase)) { int first = 6; int last = s.IndexOf(" "); string location = s.Substring(first, last - first); //s.Reverse(); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf ("N"); string character = s.Substring(nameindex, 5); moveArray[movesIter].index = i; moveArray[movesIter].location = location; moveArray[movesIter].character = character; movesIter++; } if (s.StartsWith("MINE", System.StringComparison.CurrentCultureIgnoreCase)) { int first = 4; int last = s.IndexOf(" "); string subject = s.Substring (first, last - first); //s.Reverse (); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf("N"); string character = s.Substring(nameindex, 5); actionArray[actionsIter].index = i; actionArray[actionsIter].action = "mine"; actionArray[actionsIter].subject = subject; actionArray[actionsIter].character = character; actionsIter++; } if (s.StartsWith("CUT", System.StringComparison.CurrentCultureIgnoreCase)) { int first = 3; int last = s.IndexOf(" "); string subject = s.Substring (first, last - first); //s.Reverse (); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf("N"); string character = s.Substring(nameindex, 5); actionArray[actionsIter].index = i; actionArray[actionsIter].action = "cut"; actionArray[actionsIter].subject = subject; actionArray[actionsIter].character = character; actionsIter++; } if (s.StartsWith("BUILD", System.StringComparison.CurrentCultureIgnoreCase)) { int first = 5; int last = s.IndexOf(" "); string subject = s.Substring (first, last - first); //s.Reverse (); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf("N"); string character = s.Substring(nameindex, 5); actionArray[actionsIter].index = i; actionArray[actionsIter].action = "build"; actionArray[actionsIter].subject = subject; actionArray[actionsIter].character = character; actionsIter++; } if (s.StartsWith("STORE", System.StringComparison.CurrentCultureIgnoreCase)) { int first = 5; int last = s.IndexOf(" "); string subject = s.Substring (first, last - first); //s.Reverse (); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf("N"); string character = s.Substring(nameindex, 5); actionArray[actionsIter].index = i; actionArray[actionsIter].action = "store"; actionArray[actionsIter].subject = subject; actionArray[actionsIter].character = character; actionsIter++; } if (s.StartsWith("SMELT", System.StringComparison.CurrentCultureIgnoreCase)) { //int first = 5; //int last = s.IndexOf(" "); string subject = "coal and ore"; //s.Reverse (); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf("N"); string character = s.Substring(nameindex, 5); actionArray[actionsIter].index = i; actionArray[actionsIter].action = "smelt"; actionArray[actionsIter].subject = subject; actionArray[actionsIter].character = character; actionsIter++; } if (s.StartsWith("QUARRY", System.StringComparison.CurrentCultureIgnoreCase)) { //int first = 3; //int last = s.IndexOf(" "); string subject = ""; //s.Reverse (); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf("N"); string character = s.Substring(nameindex, 5); actionArray[actionsIter].index = i; actionArray[actionsIter].action = "quarry"; actionArray[actionsIter].subject = subject; actionArray[actionsIter].character = character; actionsIter++; } if (s.StartsWith("SAW", System.StringComparison.CurrentCultureIgnoreCase)) { //int first = 3; //int last = s.IndexOf(" "); string subject = "timber"; //s.Reverse (); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf("N"); string character = s.Substring(nameindex, 5); actionArray[actionsIter].index = i; actionArray[actionsIter].action = "saw"; actionArray[actionsIter].subject = subject; actionArray[actionsIter].character = character; actionsIter++; } if (s.StartsWith("MAKE", System.StringComparison.CurrentCultureIgnoreCase)) { int first = 4; int last = s.IndexOf(" "); string subject = s.Substring (first, last - first); //s.Reverse (); //s = s.Remove (0, 6); //s.Reverse (); int nameindex = s.LastIndexOf("N"); string character = s.Substring(nameindex, 5); actionArray[actionsIter].index = i; actionArray[actionsIter].action = "make"; actionArray[actionsIter].subject = subject; actionArray[actionsIter].character = character; actionsIter++; } } parsedMoves = moveArray; parsedActions = actionArray; }
public static void DrawWay(Car self, Moves stack, Brush brush, double width) { if (stack == null) return; var pts = new Points(); pts.AddRange(MyStrategy.GetCarPath(self, stack).Select(car => new Point(car))); SegmentsDrawQueue.Add(new object[] { brush, pts, width }); }
// Use this for initialization void Start() { movesData = GameObject.FindGameObjectWithTag("Moves").GetComponent<Moves>(); GenerateList(); }
public static string negamaxRoot(int depth, int quieseDepth, string moveToStartWith, ulong WP, ulong WN, ulong WB, ulong WR, ulong WQ, ulong WK, ulong BP, ulong BN, ulong BB, ulong BR, ulong BQ, ulong BK, ulong EP, bool CWK, bool CWQ, bool CBK, bool CBQ, bool white) { string bestMove = ""; nodeProcessed = 0; int alpha = -100000, beta = 100000; string legalMove = Moves.LegalMoves(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK, EP, CWK, CWQ, CBK, CBQ, white); if (legalMove.Length == 0) { return(null); } legalMove = moveToStartWith + legalMove; int bestValue = -50000; int moveCount = legalMove.Length / 4; int[] childValues = new int[moveCount]; string[] moves = new string[moveCount]; for (int i = 0; i < moveCount; i++) { moves[i] = legalMove.Substring(i * 4, 4); } //Parallel.For(0, moveCount, i => for (int i = 0; i < moveCount; i++) { ulong WRt = Moves.makeMoveCastle(WR, WK | BK, moves[i], 'R'); ulong BRt = Moves.makeMoveCastle(BR, WK | BK, moves[i], 'r'); WRt = Moves.makeMove(WR, moves[i], 'R'); BRt = Moves.makeMove(BR, moves[i], 'r'); ulong WPt = Moves.makeMove(WP, moves[i], 'P'), WNt = Moves.makeMove(WN, moves[i], 'N'), WBt = Moves.makeMove(WB, moves[i], 'B'), WQt = Moves.makeMove(WQ, moves[i], 'Q'), WKt = Moves.makeMove(WK, moves[i], 'K'), BPt = Moves.makeMove(BP, moves[i], 'p'), BNt = Moves.makeMove(BN, moves[i], 'n'), BBt = Moves.makeMove(BB, moves[i], 'b'), BQt = Moves.makeMove(BQ, moves[i], 'q'), BKt = Moves.makeMove(BK, moves[i], 'k'), EPt = Moves.makeMoveEP(WP | BP, moves[i]); bool CWKt = CWK, CWQt = CWQ, CBKt = CBK, CBQt = CBQ; if (char.IsDigit(moves[i][3])) { int start = (moves[i][0] - '0') * 8 + moves[i][1] - '0'; if (((1ul << start) & WK) != 0) { CWKt = false; CWQt = false; } else if (((1ul << start) & BK) != 0) { CBKt = false; CBQt = false; } else if (((1ul << start) & WR & (1ul << 63)) != 0) { CWKt = false; } else if (((1ul << start) & WR & (1ul << 56)) != 0) { CWQt = false; } else if (((1ul << start) & BR & (1ul << 7)) != 0) { CBKt = false; } else if (((1ul << start) & BR & 1ul) != 0) { CBQt = false; } } childValues[i] = -negamaxWithAlphaBeta(-beta, -alpha, quieseDepth, depth - 1, WPt, WNt, WBt, WRt, WQt, WKt, BPt, BNt, BBt, BRt, BQt, BKt, EPt, CWKt, CWQt, CBKt, CBQt, white ? false : true); } for (int i = 0; i < moveCount; i++) { if (childValues[i] > bestValue) { bestValue = childValues[i]; bestMove = moves[i]; } } bestSearchedValue = bestValue; return(bestMove); }
public static void RenderMoveAnimation(RendererDestinationData destData, Moves.IMoveAnimation animation, Point pinnedPoint) { int animTime = 400; switch (animation.AnimType) { case Enums.MoveAnimationType.Normal: { #region Normal NormalMoveAnimation specifiedAnim = animation as NormalMoveAnimation; if (specifiedAnim.CompletedLoops < specifiedAnim.RenderLoops) { SpellSheet spriteSheet = GraphicsManager.GetSpellSheet(Enums.StationaryAnimType.Spell, specifiedAnim.AnimationIndex, false); Surface spriteToBlit = null; if (spriteSheet != null) { spriteToBlit = spriteSheet.Sheet; } else { specifiedAnim.Active = false; return; } Rectangle sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height, 0, spriteToBlit.Height, spriteToBlit.Height); pinnedPoint.X = pinnedPoint.X + Constants.TILE_WIDTH / 2 - spriteToBlit.Height / 2; pinnedPoint.Y = pinnedPoint.Y + Constants.TILE_HEIGHT / 2 - spriteToBlit.Height / 2; //blit destData.Blit(spriteToBlit, pinnedPoint, sourceRec); if (Globals.Tick > specifiedAnim.MoveTime + specifiedAnim.FrameLength) { specifiedAnim.MoveTime = Globals.Tick; specifiedAnim.Frame++; } if (specifiedAnim.Frame >= spriteToBlit.Width / spriteToBlit.Height) { specifiedAnim.CompletedLoops++; specifiedAnim.Frame = 0; } } else { specifiedAnim.Active = false; } #endregion } break; case Enums.MoveAnimationType.Arrow: { #region Arrow ArrowMoveAnimation specifiedAnim = animation as ArrowMoveAnimation; int time = Globals.Tick - specifiedAnim.TotalMoveTime; if (time < animTime) { SpellSheet spriteSheet = GraphicsManager.GetSpellSheet(Enums.StationaryAnimType.Arrow, specifiedAnim.AnimationIndex, false); Surface spriteToBlit = null; if (spriteSheet != null) { spriteToBlit = spriteSheet.Sheet; } else { specifiedAnim.Active = false; return; } Rectangle sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height / 8, GraphicsManager.GetAnimDirInt(specifiedAnim.Direction) * spriteToBlit.Height / 8, spriteToBlit.Height / 8, spriteToBlit.Height / 8); pinnedPoint.X = pinnedPoint.X + Constants.TILE_WIDTH / 2 - spriteToBlit.Height / 2 / 8; pinnedPoint.Y = pinnedPoint.Y + Constants.TILE_HEIGHT / 2 - spriteToBlit.Height / 2 / 8; switch (specifiedAnim.Direction) { case Enums.Direction.Up: { pinnedPoint.Y -= specifiedAnim.Distance * Constants.TILE_HEIGHT * time / animTime; } break; case Enums.Direction.Down: { pinnedPoint.Y += specifiedAnim.Distance * Constants.TILE_HEIGHT * time / animTime; } break; case Enums.Direction.Left: { pinnedPoint.X -= specifiedAnim.Distance * Constants.TILE_WIDTH * time / animTime; } break; case Enums.Direction.Right: { pinnedPoint.X += specifiedAnim.Distance * Constants.TILE_WIDTH * time / animTime; } break; case Enums.Direction.UpRight: case Enums.Direction.DownRight: case Enums.Direction.DownLeft: case Enums.Direction.UpLeft: break; } //blit destData.Blit(spriteToBlit, pinnedPoint, sourceRec); if (Globals.Tick > specifiedAnim.MoveTime + specifiedAnim.FrameLength) { specifiedAnim.MoveTime = Globals.Tick; specifiedAnim.Frame++; } if (specifiedAnim.Frame >= spriteToBlit.Width / (spriteToBlit.Height / 8)) { specifiedAnim.CompletedLoops++; specifiedAnim.Frame = 0; } } else { specifiedAnim.Active = false; } #endregion } break; case Enums.MoveAnimationType.Throw: { #region Throw ThrowMoveAnimation specifiedAnim = animation as ThrowMoveAnimation; int time = Globals.Tick - specifiedAnim.TotalMoveTime; if (time < animTime) { SpellSheet spriteSheet = GraphicsManager.GetSpellSheet(Enums.StationaryAnimType.Spell, specifiedAnim.AnimationIndex, false); Surface spriteToBlit = null; if (spriteSheet != null) { spriteToBlit = spriteSheet.Sheet; } else { specifiedAnim.Active = false; return; } Rectangle sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height, 0, spriteToBlit.Height, spriteToBlit.Height); double distance = Math.Sqrt(Math.Pow(specifiedAnim.XChange * Constants.TILE_WIDTH, 2) + Math.Pow(specifiedAnim.YChange * Constants.TILE_HEIGHT, 2)); int x = pinnedPoint.X + specifiedAnim.XChange * Constants.TILE_WIDTH * time / animTime; int y = (int)(pinnedPoint.Y + specifiedAnim.YChange * Constants.TILE_HEIGHT * time / animTime - ((-4) * distance * Math.Pow(time, 2) / animTime + 4 * distance * time) / animTime); x = x + Constants.TILE_WIDTH / 2 - spriteToBlit.Height / 2; y = y + Constants.TILE_HEIGHT / 2 - spriteToBlit.Height / 2; //blit destData.Blit(spriteToBlit, new Point(x, y), sourceRec); if (Globals.Tick > specifiedAnim.MoveTime + specifiedAnim.FrameLength) { specifiedAnim.MoveTime = Globals.Tick; specifiedAnim.Frame++; } if (specifiedAnim.Frame >= spriteToBlit.Width / spriteToBlit.Height) { specifiedAnim.CompletedLoops++; specifiedAnim.Frame = 0; } } else { specifiedAnim.Active = false; } #endregion } break; case Enums.MoveAnimationType.Beam: { #region Beam BeamMoveAnimation specifiedAnim = animation as BeamMoveAnimation; if (specifiedAnim.CompletedLoops < specifiedAnim.RenderLoops + specifiedAnim.Distance) { SpellSheet spriteSheet = GraphicsManager.GetSpellSheet(Enums.StationaryAnimType.Beam, specifiedAnim.AnimationIndex, false); Surface spriteToBlit = null; if (spriteSheet != null) { spriteToBlit = spriteSheet.Sheet; } else { specifiedAnim.Active = false; return; } int curDistance = specifiedAnim.Distance; Rectangle sourceRec = new Rectangle(); if (specifiedAnim.CompletedLoops < specifiedAnim.Distance) curDistance = specifiedAnim.CompletedLoops; for (int i = 0; i <= curDistance; i++) { if (i == 0) { //draw beginning sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height / 32, GraphicsManager.GetAnimDirInt(specifiedAnim.Direction) * 4 * spriteToBlit.Height / 32, spriteToBlit.Height / 32, spriteToBlit.Height / 32); } else if (i == curDistance) { if (curDistance == specifiedAnim.Distance) { sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height / 32, (GraphicsManager.GetAnimDirInt(specifiedAnim.Direction) * 4 + 3) * spriteToBlit.Height / 32, spriteToBlit.Height / 32, spriteToBlit.Height / 32); } else { sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height / 32, (GraphicsManager.GetAnimDirInt(specifiedAnim.Direction) * 4 + 2) * spriteToBlit.Height / 32, spriteToBlit.Height / 32, spriteToBlit.Height / 32); } } else { //draw body sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height / 32, (GraphicsManager.GetAnimDirInt(specifiedAnim.Direction) * 4 + 1) * spriteToBlit.Height / 32, spriteToBlit.Height / 32, spriteToBlit.Height / 32); } Point blitPoint = new Point(); switch (specifiedAnim.Direction) { case Enums.Direction.Up: { blitPoint = new Point(pinnedPoint.X, pinnedPoint.Y - i * Constants.TILE_HEIGHT); } break; case Enums.Direction.Down: { blitPoint = new Point(pinnedPoint.X, pinnedPoint.Y + i * Constants.TILE_HEIGHT); } break; case Enums.Direction.Left: { blitPoint = new Point(pinnedPoint.X - i * Constants.TILE_WIDTH, pinnedPoint.Y); } break; case Enums.Direction.Right: { blitPoint = new Point(pinnedPoint.X + i * Constants.TILE_WIDTH, pinnedPoint.Y); } break; case Enums.Direction.UpRight: case Enums.Direction.DownRight: case Enums.Direction.DownLeft: case Enums.Direction.UpLeft: break; } blitPoint.X = blitPoint.X + Constants.TILE_WIDTH / 2 - spriteToBlit.Height / 2 / 32; blitPoint.Y = blitPoint.Y + Constants.TILE_HEIGHT / 2 - spriteToBlit.Height / 2 / 32; //blit destData.Blit(spriteToBlit, blitPoint, sourceRec); } if (Globals.Tick > specifiedAnim.MoveTime + specifiedAnim.FrameLength) { specifiedAnim.MoveTime = Globals.Tick; specifiedAnim.Frame++; } if (specifiedAnim.Frame >= spriteToBlit.Width / (spriteToBlit.Height / 32)) { specifiedAnim.CompletedLoops++; specifiedAnim.Frame = 0; } } else { specifiedAnim.Active = false; } #endregion } break; case Enums.MoveAnimationType.Overlay: { #region Overlay OverlayMoveAnimation specifiedAnim = animation as OverlayMoveAnimation; if (specifiedAnim.CompletedLoops < specifiedAnim.RenderLoops) { SpellSheet spriteSheet = GraphicsManager.GetSpellSheet(Enums.StationaryAnimType.Spell, specifiedAnim.AnimationIndex, true); Surface spriteToBlit = null; if (spriteSheet != null) { spriteToBlit = spriteSheet.Sheet; } else { specifiedAnim.Active = false; return; } Rectangle sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height, 0, spriteToBlit.Height, spriteToBlit.Height); //blit for (int y = 0; y < Constants.TILE_HEIGHT * 15; y += spriteToBlit.Height) { for (int x = 0; x < Constants.TILE_WIDTH * 20; x += spriteToBlit.Height) { destData.Blit(spriteToBlit, new Point(x, y), sourceRec); } } if (Globals.Tick > specifiedAnim.MoveTime + specifiedAnim.FrameLength) { specifiedAnim.MoveTime = Globals.Tick; specifiedAnim.Frame++; } if (specifiedAnim.Frame >= spriteToBlit.Width / spriteToBlit.Height) { specifiedAnim.CompletedLoops++; specifiedAnim.Frame = 0; } } else { specifiedAnim.Active = false; } #endregion } break; case Enums.MoveAnimationType.Tile: { #region Tile TileMoveAnimation specifiedAnim = animation as TileMoveAnimation; if (specifiedAnim.CompletedLoops < specifiedAnim.RenderLoops) { SpellSheet spriteSheet = GraphicsManager.GetSpellSheet(Enums.StationaryAnimType.Spell, specifiedAnim.AnimationIndex, false); Surface spriteToBlit = null; if (spriteSheet != null) { spriteToBlit = spriteSheet.Sheet; } else { specifiedAnim.Active = false; return; } Rectangle sourceRec = new Rectangle(specifiedAnim.Frame * spriteToBlit.Height, 0, spriteToBlit.Height, spriteToBlit.Height); Point blitPoint = new Point(pinnedPoint.X + Constants.TILE_WIDTH / 2 - spriteToBlit.Height / 2, pinnedPoint.Y + Constants.TILE_HEIGHT / 2 - spriteToBlit.Height / 2); //blit switch (specifiedAnim.RangeType) { case Enums.MoveRange.FrontOfUserUntil: case Enums.MoveRange.LineUntilHit: { #region Front of user Until switch (specifiedAnim.Direction) { case Enums.Direction.Up: { int y = specifiedAnim.StartY; for (int i = 1; i <= specifiedAnim.Range; i++) { destData.Blit(spriteToBlit, new Point(blitPoint.X, blitPoint.Y - Constants.TILE_HEIGHT * i), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX, specifiedAnim.StartY - i)) { break; } } } break; case Enums.Direction.Down: { int y = specifiedAnim.StartY; for (int i = 1; i <= specifiedAnim.Range; i++) { destData.Blit(spriteToBlit, new Point(blitPoint.X, blitPoint.Y + Constants.TILE_HEIGHT * i), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX, specifiedAnim.StartY + i)) { break; } } } break; case Enums.Direction.Left: { int x = specifiedAnim.StartX; for (int i = 1; i <= specifiedAnim.Range; i++) { destData.Blit(spriteToBlit, new Point(blitPoint.X - Constants.TILE_WIDTH * i, blitPoint.Y), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX - i, specifiedAnim.StartY)) { break; } } } break; case Enums.Direction.Right: { int x = specifiedAnim.StartX; for (int i = 1; i <= specifiedAnim.Range; i++) { destData.Blit(spriteToBlit, new Point(blitPoint.X + Constants.TILE_WIDTH * i, blitPoint.Y), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX + i, specifiedAnim.StartY)) { break; } } } break; } #endregion } break; case Enums.MoveRange.StraightLine: case Enums.MoveRange.FrontOfUser: { #region Front of user switch (specifiedAnim.Direction) { case Enums.Direction.Up: { int y = specifiedAnim.StartY; for (int i = 1; i <= specifiedAnim.Range; i++) { destData.Blit(spriteToBlit, new Point(blitPoint.X, blitPoint.Y - Constants.TILE_HEIGHT * i), sourceRec); } } break; case Enums.Direction.Down: { int y = specifiedAnim.StartY; for (int i = 1; i <= specifiedAnim.Range; i++) { destData.Blit(spriteToBlit, new Point(blitPoint.X, blitPoint.Y + Constants.TILE_HEIGHT * i), sourceRec); } } break; case Enums.Direction.Left: { int x = specifiedAnim.StartX; for (int i = 1; i <= specifiedAnim.Range; i++) { destData.Blit(spriteToBlit, new Point(blitPoint.X - Constants.TILE_WIDTH * i, blitPoint.Y), sourceRec); } } break; case Enums.Direction.Right: { int x = specifiedAnim.StartX; for (int i = 1; i <= specifiedAnim.Range; i++) { destData.Blit(spriteToBlit, new Point(blitPoint.X + Constants.TILE_WIDTH * i, blitPoint.Y), sourceRec); } } break; } #endregion } break; case Enums.MoveRange.User: case Enums.MoveRange.Special: { #region user destData.Blit(spriteToBlit, blitPoint, sourceRec); #endregion } break; case Enums.MoveRange.Floor: { #region Floor for (int x = 0; x < 20; x++) { for (int y = 0; y < 15; y++) { destData.Blit(spriteToBlit, new Point(x * Constants.TILE_WIDTH + Constants.TILE_WIDTH / 2 - spriteToBlit.Height / 2, y * Constants.TILE_HEIGHT + Constants.TILE_HEIGHT / 2 - spriteToBlit.Height / 2), sourceRec); } } #endregion } break; case Enums.MoveRange.Room: { #region Room for (int x = (-specifiedAnim.Range); x <= specifiedAnim.Range; x++) { for (int y = (-specifiedAnim.Range); y <= specifiedAnim.Range; y++) { destData.Blit(spriteToBlit, new Point(blitPoint.X + x * Constants.TILE_WIDTH, blitPoint.Y + y * Constants.TILE_HEIGHT), sourceRec); } } #endregion } break; case Enums.MoveRange.FrontAndSides: { #region Front and Sides for (int r = 0; r <= specifiedAnim.Range; r++) { //check adjacent tiles switch (specifiedAnim.Direction) { case Enums.Direction.Down: { destData.Blit(spriteToBlit, new Point(blitPoint.X, blitPoint.Y + r * Constants.TILE_HEIGHT), sourceRec); for (int s = 1; s <= r; s++) { destData.Blit(spriteToBlit, new Point(blitPoint.X - s * Constants.TILE_WIDTH, blitPoint.Y + r * Constants.TILE_HEIGHT), sourceRec); destData.Blit(spriteToBlit, new Point(blitPoint.X + s * Constants.TILE_WIDTH, blitPoint.Y + r * Constants.TILE_HEIGHT), sourceRec); } } break; case Enums.Direction.Up: { destData.Blit(spriteToBlit, new Point(blitPoint.X, blitPoint.Y - r * Constants.TILE_HEIGHT), sourceRec); for (int s = 1; s <= r; s++) { destData.Blit(spriteToBlit, new Point(blitPoint.X - s * Constants.TILE_WIDTH, blitPoint.Y - r * Constants.TILE_HEIGHT), sourceRec); destData.Blit(spriteToBlit, new Point(blitPoint.X + s * Constants.TILE_WIDTH, blitPoint.Y - r * Constants.TILE_HEIGHT), sourceRec); } } break; case Enums.Direction.Left: { destData.Blit(spriteToBlit, new Point(blitPoint.X - r * Constants.TILE_WIDTH, blitPoint.Y), sourceRec); for (int s = 1; s <= r; s++) { destData.Blit(spriteToBlit, new Point(blitPoint.X - r * Constants.TILE_WIDTH, blitPoint.Y - s * Constants.TILE_HEIGHT), sourceRec); destData.Blit(spriteToBlit, new Point(blitPoint.X - r * Constants.TILE_WIDTH, blitPoint.Y + s * Constants.TILE_HEIGHT), sourceRec); } } break; case Enums.Direction.Right: { destData.Blit(spriteToBlit, new Point(blitPoint.X + r * Constants.TILE_WIDTH, blitPoint.Y), sourceRec); for (int s = 1; s <= r; s++) { destData.Blit(spriteToBlit, new Point(blitPoint.X + r * Constants.TILE_WIDTH, blitPoint.Y - s * Constants.TILE_HEIGHT), sourceRec); destData.Blit(spriteToBlit, new Point(blitPoint.X + r * Constants.TILE_WIDTH, blitPoint.Y + s * Constants.TILE_HEIGHT), sourceRec); } } break; } } #endregion } break; case Enums.MoveRange.ArcThrow: { #region Arc Throw bool stopattile = false; for (int r = 0; r <= specifiedAnim.Range; r++) { //check adjacent tiles switch (specifiedAnim.Direction) { case Enums.Direction.Down: { destData.Blit(spriteToBlit, new Point(blitPoint.X, blitPoint.Y + r * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX, specifiedAnim.StartY + r)) { stopattile = true; } if (stopattile) { break; } for (int s = 1; s <= r; s++) { destData.Blit(spriteToBlit, new Point(blitPoint.X - s * Constants.TILE_WIDTH, blitPoint.Y + r * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX - s, specifiedAnim.StartY + r)) { stopattile = true; } if (stopattile) { break; } destData.Blit(spriteToBlit, new Point(blitPoint.X + s * Constants.TILE_WIDTH, blitPoint.Y + r * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX + s, specifiedAnim.StartY + r)) { stopattile = true; } if (stopattile) { break; } } if (stopattile) { break; } } break; case Enums.Direction.Up: { destData.Blit(spriteToBlit, new Point(blitPoint.X, blitPoint.Y - r * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX, specifiedAnim.StartY - r)) { stopattile = true; } if (stopattile) { break; } for (int s = 1; s <= r; s++) { destData.Blit(spriteToBlit, new Point(blitPoint.X - s * Constants.TILE_WIDTH, blitPoint.Y - r * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX - s, specifiedAnim.StartY - r)) { stopattile = true; } if (stopattile) { break; } destData.Blit(spriteToBlit, new Point(blitPoint.X + s * Constants.TILE_WIDTH, blitPoint.Y - r * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX + s, specifiedAnim.StartY - r)) { stopattile = true; } if (stopattile) { break; } } } break; case Enums.Direction.Left: { destData.Blit(spriteToBlit, new Point(blitPoint.X - r * Constants.TILE_WIDTH, blitPoint.Y), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX - r, specifiedAnim.StartY)) { stopattile = true; } if (stopattile) { break; } for (int s = 1; s <= r; s++) { destData.Blit(spriteToBlit, new Point(blitPoint.X - r * Constants.TILE_WIDTH, blitPoint.Y - s * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX - r, specifiedAnim.StartY - s)) { stopattile = true; } if (stopattile) { break; } destData.Blit(spriteToBlit, new Point(blitPoint.X - r * Constants.TILE_WIDTH, blitPoint.Y + s * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX - r, specifiedAnim.StartY + s)) { stopattile = true; } if (stopattile) { break; } } } break; case Enums.Direction.Right: { destData.Blit(spriteToBlit, new Point(blitPoint.X + r * Constants.TILE_WIDTH, blitPoint.Y), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX + r, specifiedAnim.StartY)) { stopattile = true; } if (stopattile) { break; } for (int s = 1; s <= r; s++) { destData.Blit(spriteToBlit, new Point(blitPoint.X + r * Constants.TILE_WIDTH, blitPoint.Y - s * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX + r, specifiedAnim.StartY - s)) { stopattile = true; } if (stopattile) { break; } destData.Blit(spriteToBlit, new Point(blitPoint.X + r * Constants.TILE_WIDTH, blitPoint.Y + s * Constants.TILE_HEIGHT), sourceRec); if (IsRenderingTargetOnSprite(Logic.Maps.MapHelper.ActiveMap, specifiedAnim.StartX + r, specifiedAnim.StartY + s)) { stopattile = true; } if (stopattile) { break; } } } break; } if (stopattile) { break; } } #endregion } break; } //for (int y = specifiedAnim.StartY; y <= specifiedAnim.EndY; y++) { // for (int x = specifiedAnim.StartX; x <= specifiedAnim.EndX; x++) { // Point blitPoint = Screen.ScreenRenderer.ToTilePoint(new Point(x, y), useScrolling); // blitPoint.X = blitPoint.X + Constants.TILE_WIDTH / 2 - spriteToBlit.Height / 2; // blitPoint.Y = blitPoint.Y + Constants.TILE_HEIGHT / 2 - spriteToBlit.Height / 2; // destData.Blit(spriteToBlit, blitPoint, sourceRec); // } //} if (Globals.Tick > specifiedAnim.MoveTime + specifiedAnim.FrameLength) { specifiedAnim.MoveTime = Globals.Tick; specifiedAnim.Frame++; } if (specifiedAnim.Frame >= spriteToBlit.Width / spriteToBlit.Height) { specifiedAnim.CompletedLoops++; specifiedAnim.Frame = 0; } } else { specifiedAnim.Active = false; } #endregion } break; case Enums.MoveAnimationType.ItemArrow: { #region ItemArrow ItemArrowMoveAnimation specifiedAnim = animation as ItemArrowMoveAnimation; int time = Globals.Tick - specifiedAnim.TotalMoveTime; if (time < animTime) { if (specifiedAnim.AnimationIndex < 0) { specifiedAnim.Active = false; return; } Rectangle sourceRec = new Rectangle((specifiedAnim.AnimationIndex - (specifiedAnim.AnimationIndex / 6) * 6) * Constants.TILE_WIDTH, (specifiedAnim.AnimationIndex / 6) * Constants.TILE_HEIGHT, Constants.TILE_WIDTH, Constants.TILE_HEIGHT); switch (specifiedAnim.Direction) { case Enums.Direction.Up: { pinnedPoint.Y -= specifiedAnim.Distance * Constants.TILE_HEIGHT * time / animTime; } break; case Enums.Direction.Down: { pinnedPoint.Y += specifiedAnim.Distance * Constants.TILE_HEIGHT * time / animTime; } break; case Enums.Direction.Left: { pinnedPoint.X -= specifiedAnim.Distance * Constants.TILE_WIDTH * time / animTime; } break; case Enums.Direction.Right: { pinnedPoint.X += specifiedAnim.Distance * Constants.TILE_WIDTH * time / animTime; } break; case Enums.Direction.UpRight: case Enums.Direction.DownRight: case Enums.Direction.DownLeft: case Enums.Direction.UpLeft: break; } //blit destData.Blit(GraphicsManager.Items, pinnedPoint, sourceRec); //if (Globals.Tick > specifiedAnim.MoveTime + specifiedAnim.FrameLength) { // specifiedAnim.MoveTime = Globals.Tick; // specifiedAnim.Frame++; //} //if (specifiedAnim.Frame >= spriteToBlit.Width / spriteToBlit.Height) { // specifiedAnim.CompletedLoops++; // specifiedAnim.Frame = 0; //} } else { specifiedAnim.Active = false; } #endregion } break; case Enums.MoveAnimationType.ItemThrow: { #region ItemThrow ItemThrowMoveAnimation specifiedAnim = animation as ItemThrowMoveAnimation; int time = Globals.Tick - specifiedAnim.TotalMoveTime; if (time < animTime) { if (specifiedAnim.AnimationIndex < 0) { specifiedAnim.Active = false; return; } Rectangle sourceRec = new Rectangle((specifiedAnim.AnimationIndex - (specifiedAnim.AnimationIndex / 6) * 6) * Constants.TILE_WIDTH, (specifiedAnim.AnimationIndex / 6) * Constants.TILE_HEIGHT, Constants.TILE_WIDTH, Constants.TILE_HEIGHT); double distance = Math.Sqrt(Math.Pow(specifiedAnim.XChange * Constants.TILE_WIDTH, 2) + Math.Pow(specifiedAnim.YChange * Constants.TILE_HEIGHT, 2)); int x = pinnedPoint.X + specifiedAnim.XChange * Constants.TILE_WIDTH * time / animTime; int y = (int)(pinnedPoint.Y + specifiedAnim.YChange * Constants.TILE_HEIGHT * time / animTime - ((-4) * distance * Math.Pow(time, 2) / animTime + 4 * distance * time) / animTime); //blit destData.Blit(GraphicsManager.Items, new Point(x, y), sourceRec); //if (Globals.Tick > specifiedAnim.MoveTime + specifiedAnim.FrameLength) { // specifiedAnim.MoveTime = Globals.Tick; // specifiedAnim.Frame++; //} //if (specifiedAnim.Frame >= spriteToBlit.Width / spriteToBlit.Height) { // specifiedAnim.CompletedLoops++; // specifiedAnim.Frame = 0; //} } else { specifiedAnim.Active = false; } #endregion } break; } }
internal override void Compute(List <Node> allNodes) { Moves.FillArray(Move); Weights.FillArray(Weight); }
private Tuple<int, Moves[]> _doAndSelectBrute(PathBruteForcer[] brutes, Points pts) { TimerStart(); var bestMoveStacks = new Moves[brutes.Length]; for (var i = 0; i < brutes.Length; i++) { if (brutes[i].LastStageMove.IsUseNitro && self.NitroChargeCount == 0) continue; if (brutes[i].LastStageMove.IsUseNitro && self.RemainingOiledTicks > 0) continue; bestMoveStacks[i] = brutes[i].Do(new ACar(self), pts); } var sel = -1; double bestTime = Infinity; for (var i = 0; i < brutes.Length; i++) { if (bestMoveStacks[i] == null) continue; var time = bestMoveStacks[i].ComputeImportance(new ACar(self)); if (sel == -1 || brutes[i].LastSuccess > brutes[sel].LastSuccess || brutes[i].LastSuccess == brutes[sel].LastSuccess && time < bestTime) { sel = i; bestTime = time; } } TimerEndLog("brute"); return new Tuple<int, Moves[]>(sel, bestMoveStacks); }
/// <summary> /// Generate "lazy" moves for this piece, which is all usual legal moves, but also includes moves that put the king in check. /// </summary> /// <param name="moves"> /// Moves list that will be populated with lazy moves. /// </param> /// <param name="movesType"> /// Types of moves to include. e.g. All, or captures-only. /// </param> public void GenerateLazyMoves(Moves moves, Moves.MoveListNames movesType) { for (int i = 0; i < moveVectors.Length; i++) { Board.AppendPiecePath(moves, this.Base, this.Base.Player, moveVectors[i], movesType); } }
public Move(Move.Moves direction) { Direction = direction; }
public void CalculateExpansionMoves(Moves moves) { var armiesForExpansion = Math.Min(BotState.Settings.MinimumArmyBonus, BotState.MyIncome.Total - moves.GetTotalDeployment()); var armiesForTakeOver = BotState.MyIncome.Total - moves.GetTotalDeployment(); if (BotState.VisibleMap.GetOpponentBorderingTerritories().Count == 0) { armiesForExpansion = BotState.MyIncome.Total - moves.GetTotalDeployment(); } AddValueToImmediateBonuses(armiesForTakeOver); var sortedAccessibleBonuses = BotState.BonusExpansionValueCalculator.SortAccessibleBonuses(BotState.VisibleMap); var bonusesThatCanBeTaken = GetBonusesThatCanBeTaken(armiesForTakeOver); var takenOverBonuses = new List <BotBonus>(); var armiesUsedForTakeOver = 0; // calculate the moves for the bonuses that can be immediately taken foreach (var bonus in sortedAccessibleBonuses) { if (bonusesThatCanBeTaken.Contains(bonus)) { var expansionMoves = BotState.TakeTerritoriesTaskCalculator.CalculateTakeTerritoriesTask(armiesForTakeOver, bonus.GetNotOwnedTerritories(), BotTerritory.DeploymentType.Normal, "MovesCalculator.CalculateExpansionMoves"); MovesCommitter.CommittMoves(BotState, expansionMoves); moves.MergeMoves(expansionMoves); armiesForTakeOver -= expansionMoves.GetTotalDeployment(); bonusesThatCanBeTaken = GetBonusesThatCanBeTaken(armiesForTakeOver); takenOverBonuses.Add(bonus); armiesUsedForTakeOver += expansionMoves.GetTotalDeployment(); } else { break; } } var isExpandingAfterTakeOverSmart = IsExpandingAfterTakeOverSmart(); var opponentBorderPresent = BotState.VisibleMap.GetOpponentBorderingTerritories().Count > 0; armiesForExpansion = Math.Max(0, armiesForExpansion - armiesUsedForTakeOver); if (takenOverBonuses.Count == 0 || isExpandingAfterTakeOverSmart) { BotBonus bonusToExpand = null; foreach (var bonus in sortedAccessibleBonuses) { if (!takenOverBonuses.Contains(bonus)) { var condition1 = bonus.GetVisibleNeutralTerritories().Count > 0; var condition2 = bonus.Amount > 0; var condition3 = !opponentBorderPresent || bonus.ExpansionValueCategory > 0; if (condition1 && condition2 && condition3) { bonusToExpand = bonus; break; } } } if (bonusToExpand == null) { return; } var foundMoves = true; var firstStep = true; while (foundMoves) { BotState.BonusValueCalculator.CalculateBonusValues(BotState.WorkingMap, BotState.VisibleMap); foundMoves = false; if (firstStep == false) { if (bonusToExpand.ExpansionValueCategory == 0) { return; } if (opponentBorderPresent) { armiesForExpansion = 0; } if (bonusToExpand.GetOpponentNeighbors().Count > 0) { return; } } Moves oneStepMoves = null; if (!opponentBorderPresent) { oneStepMoves = BotState.TakeTerritoriesTaskCalculator.CalculateOneStepExpandBonusTask(armiesForExpansion, bonusToExpand, true, BotState.WorkingMap, BotTerritory.DeploymentType.Normal); } else { oneStepMoves = BotState.TakeTerritoriesTaskCalculator.CalculateOneStepExpandBonusTask(armiesForExpansion, bonusToExpand, false, BotState.WorkingMap, BotTerritory.DeploymentType.Normal); } if (oneStepMoves != null) { firstStep = false; armiesForExpansion -= oneStepMoves.GetTotalDeployment(); MovesCommitter.CommittMoves(BotState, oneStepMoves); moves.MergeMoves(oneStepMoves); foundMoves = true; } } } }
public void ScoreAdding(Moves myLastMove, Moves othersLastMove) { Scor.Add("" + myLastMove + othersLastMove, Score); }
// Update is called once per frame void Update() { BoardManager.Instance.UpdateSelection(); BoardManager.Instance.DrawChessBoard(); //BoardManager.Instance.CheckAttackedSquares(); if (!BoardManager.Instance.temAI) { if (Input.GetMouseButtonDown(0)) { //se o clique for dentro do tabuleiro if (BoardManager.Instance.selectionX >= 0 && BoardManager.Instance.selectionY >= 0) { //se nenhuma peça tiver sido selecionada o clique seleciona else move a peça selecionada if (BoardManager.Instance.selectedPeça == null) { BoardHighlight.Instance.HidehighLights(); //selecionar a peça BoardManager.Instance.SelecionePeça(BoardManager.Instance.selectionX, BoardManager.Instance.selectionY); } else { BoardHighlight.Instance.HidehighLights(); Vector3 a = BoardManager.Instance.GetTileCenter(BoardManager.Instance.selectionX, BoardManager.Instance.selectionY); if (BoardManager.Instance.selectedPeça.CurrentX != a.x && BoardManager.Instance.selectedPeça.CurrentY != a.z) { BoardManager.Instance.MovePeça(BoardManager.Instance.selectionX, BoardManager.Instance.selectionY); } //mova a peça //MovePeça(selectionX, selectionY); } } } } else if (BoardManager.Instance.temAI && BoardManager.Instance.isWhiteTurn) { if (Input.GetMouseButtonDown(0)) { //se o clique for dentro do tabuleiro if (BoardManager.Instance.selectionX >= 0 && BoardManager.Instance.selectionY >= 0) { //se nenhuma peça tiver sido selecionada o clique seleciona else move a peça selecionada if (BoardManager.Instance.selectedPeça == null) { BoardHighlight.Instance.HidehighLights(); //selecionar a peça BoardManager.Instance.SelecionePeça(BoardManager.Instance.selectionX, BoardManager.Instance.selectionY); } else { BoardHighlight.Instance.HidehighLights(); Vector3 a = BoardManager.Instance.GetTileCenter(BoardManager.Instance.selectionX, BoardManager.Instance.selectionY); if (BoardManager.Instance.selectedPeça.CurrentX != a.x && BoardManager.Instance.selectedPeça.CurrentY != a.z) { BoardManager.Instance.MovePeça(BoardManager.Instance.selectionX, BoardManager.Instance.selectionY); } //mova a peça //MovePeça(selectionX, selectionY); } } } } else if (BoardManager.Instance.temAI && !BoardManager.Instance.isWhiteTurn) { BoardManager.Instance.alfa.Clear(); BoardManager.Instance.beta.Clear(); for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (BoardManager.Instance.Chessmans[i, j] != null) { if (!BoardManager.Instance.Chessmans[i, j].isWhite) { PeçaDefault referencia = BoardManager.Instance.Chessmans[i, j]; AI.Instance.guardaMoves(BoardManager.Instance.alfa, referencia); } else if (BoardManager.Instance.Chessmans[i, j].isWhite) { PeçaDefault referencia = BoardManager.Instance.Chessmans[i, j]; AI.Instance.guardaMoves(BoardManager.Instance.beta, referencia); } } } } /*int sizeOfList = 0; * int gerarNumero; * sizeOfList = alfa.Count; * gerarNumero = Random.Range(1, sizeOfList); * * Debug.Log(gerarNumero); * Debug.Log(alfa[gerarNumero].x); */ Moves teste = AI.Instance.evaluateMove(BoardManager.Instance.alfa, BoardManager.Instance.beta); BoardManager.Instance.SelecionePeça(teste.peçaDoMove.CurrentX, teste.peçaDoMove.CurrentY); BoardManager.Instance.MovePeça(teste.x, teste.y); } if (BoardManager.Instance.capturedKing == true) { BoardManager.Instance.capturedKing = false; SceneManager.LoadScene("Menu"); } //Debug.Log(BoardManager.Instance.Chessmans[0, 0].neverMoved); //Debug.Log(BoardManager.Instance.Chessmans[4, 0].neverMoved); }
/// <summary> /// Apply Search Extensions /// </summary> /// <param name="extensionOrReduction">Number of extensions or reductions applied in the search node. Extensions positive, reductions negative.</param> /// <param name="movesPossible">List of possible modes at this search node.</param> /// <param name="moveMade">One of the candidate moves made from this search node.</param> /// <param name="parentMove">Move that is the parent of this search node.</param> private static void ApplyExtensions( ref int extensionOrReduction, Moves movesPossible, Move moveMade, Move parentMove) { if (Game.EnableExtensions) { if (movesPossible.Count == 1) { // Single Response extensionOrReduction = 1; Comment(moveMade, "E-1REP "); } else if (parentMove != null && parentMove.IsEnemyInCheck) { // Check evasion extensionOrReduction = 1; Comment(moveMade, "E-CHK "); } else if (parentMove != null && parentMove.PieceCaptured != null && moveMade.PieceCaptured != null && parentMove.PieceCaptured.BasicValue == moveMade.PieceCaptured.BasicValue && parentMove.To == moveMade.To) { // Recapture piece of same basic value (on the same square) extensionOrReduction = 1; Comment(moveMade, "E-RECAP "); } else if (moveMade.Piece.Name == Piece.PieceNames.Pawn && ((moveMade.Piece.Player.Colour == Player.PlayerColourNames.White && moveMade.To.Rank == 6) || (moveMade.Piece.Player.Colour == Player.PlayerColourNames.Black && moveMade.To.Rank == 1))) { // Pawn push to 7th rank extensionOrReduction = 1; Comment(moveMade, "E-PAWN7 "); } } }
/// <summary> /// Builds all possible right parts for given anchor /// </summary> /// <param name="partialWord">Word preceding right part</param> /// <param name="anchor">Tile from which to build up right part</param> /// <param name="boardArray">Board to work with</param> /// <param name="validCrossChecks">List of valid cross checks for all empty tiles</param> /// <param name="validMovesList">List of valid moves that gets updated</param> /// <param name="boardIsHorizontal">Board is untransposed or transposed</param> /// <param name="boardBeforeMove">Board before any moves were generated</param> /// <param name="tileExtendedWith">Tile that was used to extend the right part</param> public void ExtendRight(string partialWord, int[] anchor, BoardTile[,] boardArray, Dictionary <BoardTile, List <CharTile> > validCrossChecks, HashSet <GeneratedMove> validMovesList, bool boardIsHorizontal, BoardTile[,] boardBeforeMove, CharTile tileExtendedWith = null) { //If no tile is present.. if (boardArray[anchor[0], anchor[1]].CharTile == null) { //If word up until current tile is valid.. if (Helper.CheckWordValidity(Dawg, partialWord)) { //If the move (word, row and column indexes) has not been added already.. if (!Moves.Any(m => m.Word.Equals(partialWord))) { //Adds generated move to list of valid moves Dictionary <BoardTile, CharTile> tilesUsed = new Dictionary <BoardTile, CharTile>(); //Adds tiles that were used in move for (int i = 0; i < partialWord.Length; i++) { var letter = partialWord[i]; var boardTile = boardArray[anchor[0], anchor[1] - partialWord.Length + i]; if (boardTile.CharTile != null) { tilesUsed.Add(boardTile, boardTile.CharTile); } else { tilesUsed.Add(boardTile, tileExtendedWith); } } validMovesList.Add(new GeneratedMove(boardIsHorizontal, anchor[1] - partialWord.Length, anchor[1] - 1, anchor, tilesUsed, boardBeforeMove, RackOfCurrentPlayer)); } } //GEts all letters that can follow current right part word HashSet <string> labelsOfDawgEdges = new HashSet <string>(new DawgEdgeEqualityComparer()); var wordsWithCommonPreffix = Dawg.MatchPrefix(partialWord); foreach (var word in wordsWithCommonPreffix) { labelsOfDawgEdges.Add(word.Key.Substring(partialWord.Length)); } foreach (var label in labelsOfDawgEdges) { //If the valid letter is in our rack and can be played on the board tile, places it and extends right again //with the newly filled board tile used as anchor if board limit is not reached if (label == "") { continue; } if (RackOfCurrentPlayer.CheckIfTileIsInRack(label[0], true) && (!validCrossChecks.Any(c => c.Key == boardArray[anchor[0], anchor[1]]) || validCrossChecks.Any(c => c.Key == boardArray[anchor[0], anchor[1]] && c.Value.Any(x => x.Letter == label[0])))) { CharTile tileToWorkWith = null; if (RackOfCurrentPlayer.CheckIfTileIsInRack(label[0], false)) { tileToWorkWith = Dictionary.CharTiles.Where(c => c.Letter == label[0] && c.Score != 0).FirstOrDefault(); } else { tileToWorkWith = Dictionary.CharTiles.Where(c => c.Letter == '*').FirstOrDefault(); } RackOfCurrentPlayer.SubstractFromRack(tileToWorkWith); boardArray[anchor[0], anchor[1]].CharTile = Dictionary.CharTiles.Where(c => c.Letter == label[0] && c.Score == tileToWorkWith.Score).FirstOrDefault(); if (anchor[1] < boardArray.GetLength(1) - 1) { ExtendRight(partialWord + label[0], new int[] { anchor[0], anchor[1] + 1 }, boardArray, validCrossChecks, validMovesList, boardIsHorizontal, boardBeforeMove, tileToWorkWith); } //Otherwise places the tile on the last empty square of the board, checks if its valid and doesn't attempt to extend anymore else { var finalWord = partialWord + boardArray[anchor[0], anchor[1]].CharTile.Letter; if (Helper.CheckWordValidity(Dawg, finalWord)) { if (!Moves.Any(m => m.Word.Equals(finalWord))) { Dictionary <BoardTile, CharTile> tilesUsed = new Dictionary <BoardTile, CharTile>(); for (int i = 0; i < finalWord.Length; i++) { var letter = finalWord[i]; var boardTile = boardArray[anchor[0], anchor[1] - finalWord.Length + 1 + i]; if (boardTile.CharTile != null) { tilesUsed.Add(boardTile, boardTile.CharTile); } else { tilesUsed.Add(boardTile, tileToWorkWith); } } validMovesList.Add(new GeneratedMove(boardIsHorizontal, anchor[1] - finalWord.Length + 1, anchor[1], anchor, tilesUsed, boardBeforeMove, RackOfCurrentPlayer)); } } } RackOfCurrentPlayer.AddToRack(tileToWorkWith); boardArray[anchor[0], anchor[1]].CharTile = null; } } } //Otherwise if the current tile is already taken and not empty, used letter from board tile to build to the right again else { var tile = boardArray[anchor[0], anchor[1]].CharTile; HashSet <string> labelsOfDawgEdges = new HashSet <string>(new DawgEdgeEqualityComparer()); var wordsWithCommonPreffix = Dawg.MatchPrefix(partialWord + tile.Letter); foreach (var word in wordsWithCommonPreffix) { labelsOfDawgEdges.Add(word.Key.Substring((partialWord + tile.Letter).Length)); } //Extends right if any letters can follow the current right part if (labelsOfDawgEdges.Any() && anchor[1] < boardArray.GetLength(1) - 1) { ExtendRight(partialWord + tile.Letter, new int[] { anchor[0], anchor[1] + 1 }, boardArray, validCrossChecks, validMovesList, boardIsHorizontal, boardBeforeMove, tile); } } }
/// <summary> /// Generate "lazy" moves for this piece, which is all usual legal moves, but also includes moves that put the king in check. /// </summary> /// <param name="moves"> /// Moves list that will be populated with lazy moves. /// </param> /// <param name="movesType"> /// Types of moves to include. e.g. All, or captures-only. /// </param> public void GenerateLazyMoves(Moves moves, Moves.MoveListNames movesType) { Square square; switch (movesType) { case Moves.MoveListNames.All: for (int i = 0; i < moveVectors.Length; i++) { square = Board.GetSquare(this.Base.Square.Ordinal + moveVectors[i]); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } } if (this.CanCastleKingSide) { moves.Add(0, 0, Move.MoveNames.CastleKingSide, this.Base, this.Base.Square, Board.GetSquare(this.Base.Square.Ordinal + 2), null, 0, 0); } if (this.CanCastleQueenSide) { moves.Add(Game.TurnNo, this.Base.LastMoveTurnNo, Move.MoveNames.CastleQueenSide, this.Base, this.Base.Square, Board.GetSquare(this.Base.Square.Ordinal - 2), null, 0, 0); } break; case Moves.MoveListNames.CapturesPromotions: for (int i = 0; i < moveVectors.Length; i++) { square = Board.GetSquare(this.Base.Square.Ordinal + moveVectors[i]); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } } break; } }
public static Moves CalculateNoPlanCleanupDeploymentTask(BotMain state, int armiesToDeploy, Moves movesSoFar) { var outvar = new Moves(); if (armiesToDeploy > 0) { var bestDeploymentTerritory = GetBestDeploymentTerritory(state, movesSoFar); outvar.AddOrder(new BotOrderDeploy(state.Me.ID, bestDeploymentTerritory, armiesToDeploy)); } return(outvar); }
private Moves LoadMoves(string pv) { Moves moves = new Moves(Moves.GetMovesTable()); try { GameWrapper.SetFen(fen); string[] pvMoves = pv.Split(" ".ToCharArray()); int currentMoveNumber = 1; bool isWhite = true; int tempMoveNumber = currentMoveNumber; bool isWhiteMove = isWhite; Move m; foreach (string move in pvMoves) { if (string.IsNullOrEmpty(move)) { continue; } if (GameWrapper.IsLegalMove(move)) { m = App.Model.Move.NewMove(); m.Game = g; m.MoveNo = tempMoveNumber; m.IsWhite = isWhiteMove; m.From = move.Substring(0, 2); m.To = move.Substring(2, 2); m.Piece = Board.PieceFromString(GameWrapper.GetMovingPiece(move)); m.Flags.IsCapture = GameWrapper.IsCapturingMove(move); m.Flags.IsPromotion = GameWrapper.IsPromotionMove(move); m.Flags.IsLongCastling = GameWrapper.IsLongCastlingMove(move); m.Flags.IsShortCastling = GameWrapper.IsShortCastlingMove(move); m.Flags.IsInCheck = GameWrapper.IsCheckingMove(move); m.Flags.IsMated = GameWrapper.IsCheckMatingMove(move); m.Flags.IsStaleMated = GameWrapper.IsStaleMatingMove(move); m.Flags.IsAmbigousMove = GameWrapper.IsAmbiguousMove(move); m.Flags.IsAmbigousMoveColumn = GameWrapper.IsAmbiguousFile(move); m.Flags.IsAmbigousMoveRow = GameWrapper.IsAmbiguousRank(move); if (m.Flags.IsCapture) { m.CapturedPiece = Board.PieceFromString(GameWrapper.GetMovingPiece(move)); } if (m.Flags.IsMated) { m.Flags.IsInCheck = false; } GameWrapper.AppendMove(move); moves.DataTable.ImportRow(m.DataRow); isWhiteMove = !isWhiteMove; if (isWhiteMove) { tempMoveNumber++; } } } } catch (Exception ex) { TestDebugger.Instance.Write(ex); } return(moves); }
public PK5 convertToPK5() { // Double Check Location Data to see if we're already a PK5 if (Data[0x5F] < 0x10 && BitConverter.ToUInt16(Data, 0x80) > 0x4000) { return(new PK5(Data)); } DateTime moment = DateTime.Now; PK5 pk5 = new PK5(Data) // Convert away! { HeldItem = 0, OT_Friendship = 70, // Apply new met date Met_Year = moment.Year - 2000, Met_Month = moment.Month, Met_Day = moment.Day }; // Fix PP pk5.Move1_PP = getMovePP(pk5.Move1_PP, pk5.Move1_PPUps); pk5.Move2_PP = getMovePP(pk5.Move2_PP, pk5.Move2_PPUps); pk5.Move3_PP = getMovePP(pk5.Move3_PP, pk5.Move3_PPUps); pk5.Move4_PP = getMovePP(pk5.Move4_PP, pk5.Move4_PPUps); // Disassociate Nature and PID pk5.Nature = (int)(pk5.PID % 25); // Delete Platinum/HGSS Met Location Data BitConverter.GetBytes((uint)0).CopyTo(pk5.Data, 0x44); // Met / Crown Data Detection pk5.Met_Location = pk5.FatefulEncounter && Array.IndexOf(new[] { 251, 243, 244, 245 }, pk5.Species) >= 0 ? (pk5.Species == 251 ? 30010 : 30012) // Celebi : Beast : 30001; // Pokétransfer (not Crown) // Delete HGSS Data BitConverter.GetBytes((ushort)0).CopyTo(pk5.Data, 0x86); if (HGSSBall > 0 && HGSSBall != 4) { pk5.Ball = HGSSBall; } // Transfer Nickname and OT Name pk5.Nickname = Nickname; pk5.OT_Name = OT_Name; // Fix Level pk5.Met_Level = PKX.getLevel(pk5.Species, pk5.EXP); // Remove HM moves; Defog should be kept if both are learned. int[] banned = Moves.Contains(250) /*Whirlpool*/ && !Moves.Contains(432) /*Defog*/ ? new[] { 15, 19, 57, 70, 432, 249, 127, 431 } // No Defog : new[] { 15, 19, 57, 70, 250, 249, 127, 431 }; // No Whirlpool int[] newMoves = pk5.Moves; for (int i = 0; i < 4; i++) { if (banned.Contains(newMoves[i])) { newMoves[i] = 0; } } pk5.Moves = newMoves; pk5.FixMoves(); pk5.RefreshChecksum(); return(pk5); }
/// <summary> /// Generate "lazy" moves for this piece, which is all usual legal moves, but also includes moves that put the king in check. /// </summary> /// <param name="moves"> /// Moves list that will be populated with lazy moves. /// </param> /// <param name="movesType"> /// Types of moves to include. e.g. All, or captures-only. /// </param> public void GenerateLazyMoves(Moves moves, Moves.MoveListNames movesType) { Square square; switch (movesType) { case Moves.MoveListNames.All: square = Board.GetSquare(this.Base.Square.Ordinal - 1); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 15); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 16); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 17); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 1); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 15); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 16); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 17); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } if (this.CanCastleKingSide) { moves.Add(0, 0, Move.MoveNames.CastleKingSide, this.Base, this.Base.Square, Board.GetSquare(this.Base.Square.Ordinal + 2), null, 0, 0); } if (this.CanCastleQueenSide) { moves.Add(Game.TurnNo, this.Base.LastMoveTurnNo, Move.MoveNames.CastleQueenSide, this.Base, this.Base.Square, Board.GetSquare(this.Base.Square.Ordinal - 2), null, 0, 0); } break; case Moves.MoveListNames.CapturesPromotions: square = Board.GetSquare(this.Base.Square.Ordinal - 1); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 15); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 16); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 17); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 1); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 15); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 16); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 17); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } break; } }
// Use this for initialization void Start() { playerPath = new List <Vector2>(); currentMove = Moves.NOTHING; speed = GlobalVariables._playerVelocity; }
public IsAvailable(Moves available) { av = available; }
/// <summary> /// Calculates the total score for all child nodes. /// </summary> /// <param name="moves"> /// List of moves. /// </param> /// <returns> /// The total score. /// </returns> private static int CalculateChildNoteTotalScore(Moves moves) { int intTotal = 0; foreach (Move move in moves) { intTotal += move.Score; } return intTotal; }
public int getMove(GameCollection games, Moves pMoves, Moves cMoves, Moves av) { Random r = new Random(); Moves finalM = new Moves(); IsAvailable iA = new IsAvailable(av); /* * #################################################################### * #################################################################### * #################################################################### */ if (cMoves.getMoves().Length + pMoves.getMoves().Length == 0) // Console.WriteLine("### 000 ###"); { Moves z = games.toMoveMap(); for (int i = 0; i < 300; i++) { int mySelection = z.getMoves()[r.Next(z.getMoves().Length)]; if (iA.check(mySelection)) { Console.WriteLine("selected move: " + mySelection); return(mySelection); } if (i >= 299) { Console.WriteLine("giving up"); } } } /* * #################################################################### * #################################################################### * #################################################################### */ if (cMoves.getMoves().Length == 0 && pMoves.getMoves().Length == 1) // Console.WriteLine("### 001 ###"); { GameCollection mm = new GameCollection(); int theMove; theMove = pMoves.getMoves()[0]; Index myIdenx = games.getIndexGameContains(theMove); Console.WriteLine("index -> " + myIdenx); Console.WriteLine("games -> " + games); bool skip = false; for (int i = 0; i < games.getSize(); i++) { for (int j = 0; j < myIdenx.getSize(); j++) { if (i == myIdenx.getIndexArray()[j]) { skip = true; } } if (skip) { skip = false; continue; } mm.addGame(games.getGame(i)); } Console.WriteLine("selection -> " + mm); Moves z = mm.toMoveMap(); for (int i = 0; i < 300; i++) { int mySelection = z.getMoves()[r.Next(z.getMoves().Length)]; if (iA.check(mySelection)) { Console.WriteLine("selected move: " + mySelection); return(mySelection); } if (i >= 299) { Console.WriteLine("giving up"); } } } /* * #################################################################### * #################################################################### * #################################################################### */ if (cMoves.getMoves().Length + pMoves.getMoves().Length >= 3) // Console.WriteLine("### 002 ###"); { Gen lol = new Gen(); GameCollection p = new GameCollection(); GameCollection c = new GameCollection(); GameCollection playerSelection = new GameCollection(); GameCollection computerSelection = new GameCollection(); lol.combinations(pMoves.getMoves(), p); lol.combinations(cMoves.getMoves(), c); Console.WriteLine("player combination: " + p); Console.WriteLine("computer combination: " + c); // combinacoes prontas, pesquisar jogos for (int i = 0; i < p.getSize(); i++) { int myIdenx = games.getIndexGameContains(p.getGame(i).getGameArray()[0], p.getGame(i).getGameArray()[1]); if (myIdenx != -1) { playerSelection.addGame(games.getGame(myIdenx)); } } for (int i = 0; i < c.getSize(); i++) { int myIdenx = games.getIndexGameContains(c.getGame(i).getGameArray()[0], c.getGame(i).getGameArray()[1]); if (myIdenx != -1) { computerSelection.addGame(games.getGame(myIdenx)); } } Console.WriteLine("playerSelection = " + playerSelection); Console.WriteLine("computerSelection = " + computerSelection); Console.WriteLine("playerSelection.toMoveArray = " + playerSelection.toMoveArray()); Console.WriteLine("computerSelection.toMoveArray = " + computerSelection.toMoveArray()); if (computerSelection.getSize() > 0) { for (int i = 0; i < computerSelection.toMoveArray().getMoves().Length; i++) { int mySelection = computerSelection.toMoveArray().getMoves()[i]; Console.WriteLine("computer iA.check -> " + iA.check(mySelection)); Console.WriteLine("mySelection -> " + mySelection); if (iA.check(mySelection)) { return(mySelection); } } } if (playerSelection.getSize() > 0) { for (int i = 0; i < playerSelection.toMoveArray().getMoves().Length; i++) { int mySelection = playerSelection.toMoveArray().getMoves()[i]; Console.WriteLine("player iA.check -> " + iA.check(mySelection)); Console.WriteLine("mySelection -> " + mySelection); if (iA.check(mySelection)) { return(mySelection); } } } else { Console.WriteLine("foideus"); } /* * for (int i = 0; i < computerSelection.toMoveArray().getMoves().Length; i++) * { * int mySelection = computerSelection.toMoveArray().getMoves()[i]; * if (iA.check(mySelection)) * { * return mySelection; * } * } */ } Console.WriteLine("tudo errado."); /* * #################################################################### * #################################################################### * #################################################################### */ if (true) // last resort { GameCollection mm = new GameCollection(); int theMove; theMove = cMoves.getMoves()[0]; Index myIdenx = games.getIndexGameContains(theMove); Console.WriteLine("index -> " + myIdenx); Console.WriteLine("games -> " + games); for (int i = 0; i < games.getSize(); i++) { for (int j = 0; j < myIdenx.getSize(); j++) { if (i == myIdenx.getIndexArray()[j]) { mm.addGame(games.getGame(i)); } } } Console.WriteLine("selection -> " + mm); Moves z = mm.toMoveMap(); for (int i = 0; i < 300; i++) { int mySelection = z.getMoves()[r.Next(z.getMoves().Length)]; if (iA.check(mySelection)) { Console.WriteLine("selected move: " + mySelection); return(mySelection); } if (i >= 299) { Console.WriteLine("giving up"); } } } // real last resort if (true) { GameCollection mm = new GameCollection(); Console.WriteLine("Last Resort"); Console.WriteLine("Available moves -> " + av); Console.WriteLine("Games -> " + games); Console.WriteLine("cMoves -> " + cMoves); Console.WriteLine("pMoves -> " + pMoves); GameCollection gaminhoLastResourt = new GameCollection(); GameCollection pGames = new GameCollection(); for (int i = 0; i < cMoves.getMoves().Length; i++) { Index holyDog = games.getIndexGameContains(cMoves.getMoves()[i]); for (int j = 0; j < holyDog.getIndexArray().Length; j++) { gaminhoLastResourt.addGame(games.getGame(holyDog.getIndexArray()[j])); } } Console.WriteLine("gaminho -> " + gaminhoLastResourt.toMoveArray()); if (gaminhoLastResourt.getSize() > 0) { for (int i = 0; i < gaminhoLastResourt.toMoveArray().getMoves().Length; i++) { int mySelection = gaminhoLastResourt.toMoveArray().getMoves()[i]; Console.WriteLine("player iA.check -> " + iA.check(mySelection)); Console.WriteLine("mySelection -> " + mySelection); if (iA.check(mySelection)) { return(mySelection); } } } else { Console.WriteLine("foideus de novo, #semata"); } } return(-1); }
/// <summary> /// Generate "lazy" moves for this piece, which is all usual legal moves, but also includes moves that put the king in check. /// </summary> /// <param name="moves"> /// Moves list that will be populated with lazy moves. /// </param> /// <param name="movesType"> /// Types of moves to include. e.g. All, or captures-only. /// </param> public void GenerateLazyMoves(Moves moves, Moves.MoveListNames movesType) { Board.AppendPiecePath(moves, this.Base, this.Base.Player, 1, movesType); Board.AppendPiecePath(moves, this.Base, this.Base.Player, -1, movesType); Board.AppendPiecePath(moves, this.Base, this.Base.Player, -16, movesType); Board.AppendPiecePath(moves, this.Base, this.Base.Player, 16, movesType); }
public Round(Moves move1, Moves move2) { Move1 = move1; Move2 = move2; }
public static void DrawWays(Car self, Moves[] stacks, int sel) { if (stacks.Length > 0) DrawWay(self, stacks[0], Brushes.BlueViolet, sel == 0 ? 2 : 0); if (stacks.Length > 1) DrawWay(self, stacks[1], Brushes.Red, sel == 1 ? 2 : 0); if (stacks.Length > 2) DrawWay(self, stacks[2], Brushes.DeepPink, sel == 2 ? 2 : 0); if (stacks.Length > 3) DrawWay(self, stacks[3], Brushes.Black, sel == 3 ? 2 : 0); if (stacks.Length > 4) DrawWay(self, stacks[4], Brushes.SpringGreen, sel == 4 ? 2 : 0); if (stacks.Length > 5) DrawWay(self, stacks[5], Brushes.Coral, sel == 5 ? 2 : 0); if (stacks.Length > 6) DrawWay(self, stacks[6], Brushes.DarkGreen, sel == 6 ? 2 : 0); if (stacks.Length > 7) DrawWay(self, stacks[7], Brushes.DarkGreen, sel == 7 ? 2 : 0); if (stacks.Length > 8) DrawWay(self, stacks[8], Brushes.Black, sel == 8 ? 2 : 0); if (stacks.Length > 9) throw new NotImplementedException("Please select color for this path"); }
private void Move(Moves move) { _view.Move(move.Index, move.ToPlace, GetFreePosition(move.ToPlace)); _window.SetMoves(_moves.Count, _moves.Count - _current); }
public override void Compute(List <Node> allNodes) { Moves.FillArray(Move); }
public virtual List <string> EndTurn() { List <string> turnLog = new List <string>(); var newBuffs = new List <Buff>(); Buffs.ForEach(s => { s.turns -= 1; if (s.turns >= 1) { newBuffs.Add(s); } else { turnLog.Add($"{Name}'s {s.stat} normalizes."); } }); Buffs = newBuffs; defensiveMult = 1; offensiveMult = 1; if (IsAlive) { if (HPrecovery > 0 && Stats.HP < Stats.MaxHP) { turnLog.AddRange(Heal((uint)HPrecovery)); } if (PPrecovery > 0 && Stats.PP < Stats.MaxPP) { turnLog.AddRange(RestorePP((uint)PPrecovery)); } } RemoveCondition(Condition.Flinch); if (HasCondition(Condition.Poison)) { var damage = Math.Min(200, (uint)(Stats.MaxHP * Global.RandomNumber(5, 10) / 100)); turnLog.Add($"{Name} is damaged by the Poison."); turnLog.AddRange(DealDamage(damage)); } if (HasCondition(Condition.Venom)) { var damage = Math.Min(400, (uint)(Stats.MaxHP * Global.RandomNumber(10, 20) / 100)); turnLog.Add($"{Name} is damaged by the Venom."); turnLog.AddRange(DealDamage(damage)); } //Haunt Damage if (HasCondition(Condition.Haunt) && Global.RandomNumber(0, 2) == 0) { var hauntDmg = damageDoneThisTurn / 4; turnLog.AddRange(DealDamage(hauntDmg)); } //Chance to wake up if (HasCondition(Condition.Sleep) && !conditionsAppliedThisTurn.Contains(Condition.Sleep)) { if (Global.RandomNumber(0, 2) == 0) { RemoveCondition(Condition.Sleep); turnLog.Add($"{Name} wakes up."); } } //Chance to remove Stun if (HasCondition(Condition.Stun) && !conditionsAppliedThisTurn.Contains(Condition.Stun)) { if (Global.RandomNumber(0, 2) == 0) { RemoveCondition(Condition.Stun); turnLog.Add($"{Name} can move again."); } } //Chance to remove Seal if (HasCondition(Condition.Seal) && !conditionsAppliedThisTurn.Contains(Condition.Seal)) { if (Global.RandomNumber(0, 3) == 0) { RemoveCondition(Condition.Seal); turnLog.Add($"{Name}'s Psynergy is no longer sealed."); } } //Chance to remove Delusion if (HasCondition(Condition.Delusion) && !conditionsAppliedThisTurn.Contains(Condition.Delusion)) { if (Global.RandomNumber(0, 4) == 0) { RemoveCondition(Condition.Delusion); turnLog.Add($"{Name} can see clearly again."); } } if (HasCondition(Condition.DeathCurse)) { DeathCurseCounter--; if (DeathCurseCounter <= 0) { if (GetTeam().Count == 1 && this is PlayerFighter p) { p.Stats.HP = 1; RemoveCondition(Condition.DeathCurse); turnLog.Add($"<:DeathCurse1:583645163499552791> {Name} barely holds on."); } else { Kill(); turnLog.Add($":x: {Name}'s light goes out."); } } } RemoveCondition(Condition.Counter); conditionsAppliedThisTurn.Clear(); foreach (var item in EquipmentWithEffect) { if (item.IsUnleashable && !item.IsBroken && item.Unleash.AllEffects.Any(e => e.ValidSelection(this)) && Global.RandomNumber(0, 100) <= item.ChanceToActivate && !HasCondition(Condition.Decoy)) { turnLog.Add($"{item.IconDisplay} {Name}'s {item.Name} starts to Glow."); foreach (var effect in item.Unleash.AllEffects) { turnLog.AddRange(effect.Apply(this, this)); } if (Global.RandomNumber(0, 100) <= item.ChanceToBreak) { item.IsBroken = true; turnLog.Add($"{item.IconDisplay} {Name}'s {item.Name} breaks;"); } } } foreach (var djinn in Moves.OfType <Djinn>()) { turnLog.AddRange(djinn.EndTurn(this)); } damageDoneThisTurn = 0; if (!IsAlive) { selected = new Nothing(); hasSelected = true; } return(turnLog); }
public static int negamaxWithAlphaBeta(int alpha, int beta, int quieseDepth, int depth, ulong WP, ulong WN, ulong WB, ulong WR, ulong WQ, ulong WK, ulong BP, ulong BN, ulong BB, ulong BR, ulong BQ, ulong BK, ulong EP, bool CWK, bool CWQ, bool CBK, bool CBQ, bool white) { ulong hashCode = Zobrist.getZobristHash(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK, EP, CWK, CWQ, CBK, CBQ, white); if (transpositionTable.ContainsKey(hashCode) && transpositionTable[hashCode].depth >= depth) { NodeData data = transpositionTable[hashCode]; if (data.type == NodeData.Type.Exact) { return(data.value); } if (data.type == NodeData.Type.Alpha) { alpha = Math.Max(data.value, alpha); } else if (data.type == NodeData.Type.Beta) { beta = Math.Min(beta, data.value); } if (alpha >= beta) { return(data.value); } } if (depth == 0) { int value = Evalue.evalue(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK, white); return(value); } string legalMove = Moves.LegalMoves(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK, EP, CWK, CWQ, CBK, CBQ, white); if (legalMove.Length == 0) { if ((white && (WK & Moves.unSafeForWhite(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK)) == 0) || (!white && (BK & Moves.unSafeForBlack(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK)) == 0)) { return(0); } else { return(-20000); } } int bestValue = -20000; int moveCount = legalMove.Length / 4; string[] moves = new string[moveCount]; for (int i = 0; i < moveCount; i++) { moves[i] = legalMove.Substring(i * 4, 4); } for (int i = 0; i < moveCount; i++) { ulong WRt = Moves.makeMoveCastle(WR, WK | BK, moves[i], 'R'); ulong BRt = Moves.makeMoveCastle(BR, WK | BK, moves[i], 'r'); WRt = Moves.makeMove(WR, moves[i], 'R'); BRt = Moves.makeMove(BR, moves[i], 'r'); ulong WPt = Moves.makeMove(WP, moves[i], 'P'), WNt = Moves.makeMove(WN, moves[i], 'N'), WBt = Moves.makeMove(WB, moves[i], 'B'), WQt = Moves.makeMove(WQ, moves[i], 'Q'), WKt = Moves.makeMove(WK, moves[i], 'K'), BPt = Moves.makeMove(BP, moves[i], 'p'), BNt = Moves.makeMove(BN, moves[i], 'n'), BBt = Moves.makeMove(BB, moves[i], 'b'), BQt = Moves.makeMove(BQ, moves[i], 'q'), BKt = Moves.makeMove(BK, moves[i], 'k'), EPt = Moves.makeMoveEP(WP | BP, moves[i]); bool CWKt = CWK, CWQt = CWQ, CBKt = CBK, CBQt = CBQ; if (char.IsDigit(moves[i][3])) { int start = (moves[i][0] - '0') * 8 + moves[i][1] - '0'; if (((1ul << start) & WK) != 0) { CWKt = false; CWQt = false; } else if (((1ul << start) & BK) != 0) { CBKt = false; CBQt = false; } else if (((1ul << start) & WR & (1ul << 63)) != 0) { CWKt = false; } else if (((1ul << start) & WR & (1ul << 56)) != 0) { CWQt = false; } else if (((1ul << start) & BR & (1ul << 7)) != 0) { CBKt = false; } else if (((1ul << start) & BR & 1ul) != 0) { CBQt = false; } } int childValue = -negamaxWithAlphaBeta(-beta, -alpha, quieseDepth, depth - 1, WPt, WNt, WBt, WRt, WQt, WKt, BPt, BNt, BBt, BRt, BQt, BKt, EPt, CWKt, CWQt, CBKt, CBQt, white ? false : true); bestValue = Math.Max(bestValue, childValue); alpha = Math.Max(alpha, childValue); if (alpha >= beta) { break; } } hashCode = Zobrist.getZobristHash(WP, WN, WB, WR, WQ, WK, BP, BN, BB, BR, BQ, BK, EP, CWK, CWQ, CBK, CBQ, white); if (bestValue <= alpha) { transpositionTable.AddOrUpdate(hashCode, new NodeData(bestValue, depth, NodeData.Type.Beta, legalMove), (key, oldData) => oldData = new NodeData(bestValue, depth, NodeData.Type.Beta, legalMove)); } else if (bestValue >= beta) { transpositionTable.AddOrUpdate(hashCode, new NodeData(bestValue, depth, NodeData.Type.Alpha, legalMove), (key, oldData) => oldData = new NodeData(bestValue, depth, NodeData.Type.Alpha, legalMove)); } else { transpositionTable.AddOrUpdate(hashCode, new NodeData(bestValue, depth, NodeData.Type.Exact, ""), (key, oldData) => oldData = new NodeData(bestValue, depth, NodeData.Type.Exact, "")); } return(bestValue); }
public bool Select(IEmote emote) { string[] numberEmotes = new string[] { "0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣" }; var trySelected = Moves.FirstOrDefault(m => m.GetEmote().Equals(emote)); //var trySelected = Moves.Where(m => m.Emote == emote).FirstOrDefault() ?? Moves.Where(m => m.Emote.Contains(emote)).FirstOrDefault(); if (!IsAlive) { Console.WriteLine("Dead Players can't select"); return(false); } if (trySelected == null) { if (numberEmotes.Contains(emote.Name) && selected != null) { selected.TargetNr = Array.IndexOf(numberEmotes, emote.Name) - 1; hasSelected = true; } else { Console.WriteLine($"{Name}: {emote.Name} {emote} not in {string.Join(",", Moves.Select(m => m.Emote))}"); return(false); } } else { if (trySelected is Psynergy psynergy && psynergy.PPCost > Stats.PP) { Console.WriteLine("Not enough PP"); return(false); }
public void AddMove(BattleMove move) { Moves.Add(move); }
public override void Update(GameObject gameObject, GameTime gameTime) { moveTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds; // Event handling if (moveTimer <= 0) { movedThisTurn = false; gameObject.xPosition = targetPosX; gameObject.yPosition = targetPosY; List<GameEvent> events = eventHandler.Events; for (int i = 0; i < events.Count; i++) { if (movedThisTurn) // Players can only move one tile per turn, and not diagonally. break; if (events[i].ID == Events.Input && (events[i] as InputEvent).GameObjectID == gameObject.ID) { int positionX = (int)Math.Round((double)targetPosX / GameConstants.TileWidth, 0); int positionY = (int)Math.Round((double)targetPosY / GameConstants.TileHeight, 0); switch((events[i] as InputEvent).key) { case Keys.D: if (CanMoveToTile(positionX + 1, positionY)) { moveDirection = Moves.Right; targetPosX += GameConstants.TileWidth; moveTimer = moveTime; movedThisTurn = true; } break; case Keys.A: if (CanMoveToTile(positionX - 1, positionY)) { moveDirection = Moves.Left; targetPosX -= GameConstants.TileWidth; moveTimer = moveTime; movedThisTurn = true; } break; case Keys.S: if (CanMoveToTile(positionX, positionY + 1)) { moveDirection = Moves.Down; targetPosY += GameConstants.TileHeight; moveTimer = moveTime; movedThisTurn = true; } break; case Keys.W: if (CanMoveToTile(positionX, positionY - 1)) { moveDirection = Moves.Up; targetPosY -= GameConstants.TileHeight; moveTimer = moveTime; movedThisTurn = true; } break; default: break; } } } } else if (moveDirection != Moves.None) // This parts makes the move look smooth, rather than jump to next tile instantly and wait for moveduration. { switch (moveDirection) { case Moves.Down: gameObject.yPosition += (float)((GameConstants.TileHeight / moveTime) * gameTime.ElapsedGameTime.TotalSeconds); if (Math.Round(gameObject.yPosition, 0) == targetPosY) { gameObject.yPosition = targetPosY; moveDirection = Moves.None; } break; case Moves.Up: gameObject.yPosition -= (float)((GameConstants.TileHeight / moveTime) * gameTime.ElapsedGameTime.TotalSeconds); if (Math.Round(gameObject.yPosition, 0) == targetPosY) { gameObject.yPosition = targetPosY; moveDirection = Moves.None; } break; case Moves.Left: gameObject.xPosition -= (float)((GameConstants.TileHeight / moveTime) * gameTime.ElapsedGameTime.TotalSeconds); if (Math.Round(gameObject.xPosition, 0) == targetPosX) { gameObject.xPosition = (float)Math.Round(gameObject.xPosition, 0); moveDirection = Moves.None; } break; case Moves.Right: gameObject.xPosition += (float)((GameConstants.TileHeight / moveTime) * gameTime.ElapsedGameTime.TotalSeconds); break; default: break; } } // ----------------------- }
//Logic for moving pieces across the board. If returns false, game is over public bool MovePiece(int fromstack, int toStack, int player) { string color; string hisColor; //The currect user turn if (player == 0) { color = MY_COLOR; hisColor = His_COLOR; } //The other player's turn else { color = His_COLOR; hisColor = MY_COLOR; if (fromstack != -1) { fromstack = 23 - fromstack; } if (toStack != -2) { toStack = 23 - toStack; } } //Add move of current user to list of moves if (player == 0) { Move newMove = new Move(fromstack, toStack, RemoveDice(fromstack, toStack)); Moves.Add(newMove); } //Piece if from jail if (fromstack == -1) { Jail[player].Remove(color); } //Piece is on board else { Board[fromstack].Remove(color); } //Piece goes to end stack if (toStack == -2) { EndStack[player].Add(color); } //Piece goes to board else { Board[toStack].Add(color); //Another player's piece is in the toStack if (Board[toStack].Contains(hisColor)) { Board[toStack].Remove(hisColor); Jail[1 - player].Add(hisColor); } } if (IsWin(player)) { return(true); } CanPlayerMoveToEndStack(); //There are other moves in the player's turn if (Dice.Count != 0) { GetListOfPossibleMoves(); } return(false); }
private void _validateLastSuccessStack() { if (_lastSuccessStack == null) return; var car = new ACar(Self); var stack = _lastSuccessStack.Clone(); var info = new PassedInfo(); while (stack.Count > 0) { if (!AMove.ModelMove(car, stack[0], info, new ABonus[] {}, new AOilSlick[] {}, new AProjectile[][] {}, new ACar[][] {})) { _lastSuccessStack = null; return; } stack[0].Times--; stack.Normalize(); } }
/// <summary> /// Checks to make sure the direction can be taken, if not it tries the next move until going back on itself. /// </summary> /// <param name="toCheck">Move to check</param> /// <returns></returns> private bool CheckDirection(Moves toCheck) { switch (toCheck) { case Moves.Up: if (Physics.Raycast(transform.position, -transform.forward * 2f, out _hit)) { if (_hit.collider.CompareTag("Tile") && !_hit.collider.CompareTag("Em")) { return(true); } else { return(false); } } else { return(false); } case Moves.Down: if (Physics.Raycast(transform.position, transform.forward * 2f, out _hit)) { if (_hit.collider.CompareTag("Tile") && !_hit.collider.CompareTag("Em")) { return(true); } else { return(false); } } else { return(false); } case Moves.Left: if (Physics.Raycast(transform.position, transform.right * 2f, out _hit)) { if (_hit.collider.CompareTag("Tile") && !_hit.collider.CompareTag("Em")) { return(true); } else { return(false); } } else { return(false); } case Moves.Right: if (Physics.Raycast(transform.position, -transform.right * 2f, out _hit)) { if (_hit.collider.CompareTag("Tile") && !_hit.collider.CompareTag("Em")) { return(true); } else { return(false); } } else { return(false); } default: break; } return(false); }
/// <summary> /// Generate "lazy" moves for this piece, which is all usual legal moves, but also includes moves that put the king in check. /// </summary> /// <param name="moves"> /// Moves list that will be populated with lazy moves. /// </param> /// <param name="movesType"> /// Types of moves to include. e.g. All, or captures-only. /// </param> public void GenerateLazyMoves(Moves moves, Moves.MoveListNames movesType) { Square square; switch (movesType) { case Moves.MoveListNames.All: square = Board.GetSquare(this.Base.Square.Ordinal + 33); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 18); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 14); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 31); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 33); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 18); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 14); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 31); if (square != null && (square.Piece == null || (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } break; case Moves.MoveListNames.CapturesPromotions: square = Board.GetSquare(this.Base.Square.Ordinal + 33); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 18); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 14); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 31); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 33); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal - 18); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 14); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } square = Board.GetSquare(this.Base.Square.Ordinal + 31); if (square != null && (square.Piece != null && (square.Piece.Player.Colour != this.Base.Player.Colour && square.Piece.IsCapturable))) { moves.Add(0, 0, Move.MoveNames.Standard, this.Base, this.Base.Square, square, square.Piece, 0, 0); } break; } }
public Moves CreateMove(int x,int y) { Moves newMove = new Moves(x, y, isX); return newMove; }