/// <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(); }
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> /// 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> /// 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); }
protected override double EstimatedScoreAfterAnotherThrow(RainyWorm wormToTake) { return(0); // always play safe }
/// <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);