const double UNSTEALABLE_RATIO = 1.005D; // harder to steal from a higher number (0,5% to the value'th power) protected override double EstimatedScoreAfterAnotherThrow(RainyWorm wormToTake) { var div = WormsToSteal.Contains(wormToTake) ? BETTER_TO_STEAL : 1D; // when the worm to take can be stolen, that might be better than just rethrow var rdvs = RainyDiceValue.All.Where(rdv => ThrowFlow.DicesTaken.All(d => d.LastThrowDiceValue != rdv)); return CalcScore(ThrowFlow.DicesToThrow.Count(), ThrowFlow.TotalTakenValue, rdvs) / div; }
/// <summary> /// Take a specific block /// - If the given worm is null, this will end up in take nothing /// The method excepts a block that is free to take, else this will end up in an exception /// And go one with the rest of the game /// </summary> /// <returns></returns> public void TakeRainyWorm(RainyWorm worm) { if(worm == null) { TakeNothing(); return; } if (!CanTakeRainyWorm(worm)) { throw new InvalidOperationException("You can not take worm " + worm); } if (_wormsToTake.Contains(worm)) { // taking a worm from the untaken stack _wormsToTake.Remove(worm); CurrentPlayer.AddWorm(worm); } else { // stealing worm of other player var player = _players.First(p => p.TopWorm == worm); CurrentPlayer.AddWorm(player.TakeTopWorm()); } Next(); }
/// <summary> /// This method assumes the computer is not the clumsy guy that does another try when it's not possible anymore /// </summary> private bool ShouldTakeWorm(RainyWorm worm) { if (worm == null) { return false; } // if all dice value are used, STOP! if (ThrowFlow.DicesTaken.Select(d => d.LastThrowDiceValue).Distinct().Count() == RainyDiceValue.Count) { return true; } // if there are no dices left to throw with, STOP! if (!ThrowFlow.DicesToThrow.Any()) { return true; } // take worm if available and worse than possibility when throwing again if (worm.WormValue >= EstimatedScoreAfterAnotherThrow(worm)) { return true; } return false; }
/// <summary> /// Checks if a specific rainy worm can be taken /// </summary> /// <param name="worm"></param> /// <returns> /// True if - currentTurn is not null /// - AND Value of turn is at least as big as the throwvalue of the worm /// - AND There is already a worm taken in the turn /// - AND The worm can still be taken from the general stack /// - OR is on the top of one of the other players stack's /// </returns> public bool CanTakeRainyWorm(RainyWorm worm) { return _currentTurn != null && _currentTurn.TotalTakenValue >= worm.ThrowValue && _currentTurn.State != ThrowFlowState.Taking && _currentTurn.HasTakenWorm() && (_wormsToTake.Contains(worm) || (_currentTurn.TotalTakenValue == worm.ThrowValue && _players.Any(p => p != CurrentPlayer && p.TopWorm == worm) ) ); }
/// <summary> /// Puts the given worm on top of the stack /// </summary> /// <param name="worm"></param> public void AddWorm(RainyWorm worm) { _wormsWon.Push(worm); }
/// <summary> /// Estimated score you will have after doing another throw in the current throwflow /// - The worm that will be taken else is given as param, in case you want to put logic to that /// </summary> protected abstract double EstimatedScoreAfterAnotherThrow(RainyWorm wormToTake);
protected override double EstimatedScoreAfterAnotherThrow(RainyWorm wormToTake) { return 0; // always play safe }