Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package mu.nu.nullpo.game.subsystem.mode;
- import java.util.Random;
- import mu.nu.nullpo.game.component.SpeedParam;
- /** @author Romaji Milton Amulo.*/
- // This class is needed for Arrthmia modes.
- public class Heartbeat {
- /** allow cutting into Lock Delay?*/
- public boolean panicMode;
- /** midpoint of ARE probability curve*/
- public int meanARE;
- /** default lock delay. Always the lock delay if panicMode is disabled.*/
- public int lockDelay;
- /** randomness width. so ARE is [meanARE-delta,meanARE+delta] */
- public int delta;
- /** minimum length of a streak. */
- public int streakMin;
- /** chance in the middle of a streak, of suddenly switching length (1.0 is every possible chance) */
- public double spikeProbability;
- /** chance a spike could be "mini". that is to the same side as current streak */
- public double miniSpike;
- /** how many drops since a streak starts or finished that another spike can't happen */
- public int gracePeriod;
- /** chance that a streak longer than streakMin will continue. setting to 1.0 will make the current streak not end,
- * unless you set ContractionType to a value other than NONE
- */
- public double streakDecay;
- /**Chooses the kind of streak contraction to use
- * None: Doesn't do any Contraction
- * Harmonic: reduces the effective streakDecay in a way reminiscent of the Harmonic series, with harmonicScale = 1 being exactly it
- * Exponential: uses the exponentialScale to reduce the effective streakDecay
- * @author RomajiMiltonAmulo
- *
- */
- public enum ContractionType {NONE,HARMONIC,EXPONENTIAL};
- public ContractionType currentContraction;
- public double harmonicScale;
- public double exponentialScale;
- /** recompute all values when delta changes, or only after a streak or spike change? */
- public boolean instantDeltaChangeRecompute;
- /** Probability that a streak change will do a spike first */
- public double spikeIntoChange;
- private int[] current;
- private int cIndex; //current index of element to take
- private int oldDelta;
- private int[] alt;
- private int dropsSinceMinStreakLength;
- private int remainingGrace;
- private double contractionValue;//used for both exponent and harmonic. Please don't switch while contraction is happening
- private enum Status {STREAK,SPIKE,MINI,SWITCH};
- private Status currentStatus;
- /** creates a new heartbeat, with default settings
- * @param RNG randomness to establish settings
- */
- public Heartbeat(Random RNG) {
- reset(RNG);
- }
- /** creates a new Heartbeat with settings from Clone
- * @param clone heartbeat cloned from
- * @param RNG randomness to establish settings
- */
- public Heartbeat(Heartbeat clone, Random RNG) {
- copy(clone);
- reshuffle(RNG);
- }
- /** returns to default values. Will also re-roll highs and lows.
- * @param RNG randomness to establish settings
- */
- public void reset(Random RNG) {
- panicMode = false;
- meanARE = 24;
- lockDelay = 30;
- delta = 10;
- streakMin = 3;
- spikeProbability = 0.2;
- miniSpike = 0;
- gracePeriod = 2;
- streakDecay = 0.5;
- currentContraction = ContractionType.NONE;
- harmonicScale = 0.0; //does nothing at present
- exponentialScale = 1.0; //once again, doesn't do anything
- instantDeltaChangeRecompute = false;
- oldDelta = 10;
- spikeIntoChange = 0.4;
- reshuffle(RNG);
- }
- /** sets external settings to those of the clone. Hides changes to delta, doesn't reshuffle.
- * @param clone Heartbeat copied
- */
- public void copy(Heartbeat clone) {
- panicMode = clone.panicMode;
- meanARE = clone.meanARE;
- lockDelay = clone.lockDelay;
- delta = clone.delta;
- streakMin = clone.streakMin;
- spikeProbability = clone.spikeProbability;
- miniSpike = clone.miniSpike;
- gracePeriod = clone.gracePeriod;
- streakDecay = clone.streakDecay;
- currentContraction = clone.currentContraction;
- harmonicScale = clone.harmonicScale;
- exponentialScale = clone.exponentialScale;
- instantDeltaChangeRecompute = clone.instantDeltaChangeRecompute;
- oldDelta = delta;
- spikeIntoChange = clone.spikeIntoChange;
- }
- /** Changes delta and oldDelta. Warning, doing this while the Heartbeat is in use can cause issues.
- * @param newDelta the new delta
- */
- public void stealthChangeDelta(int newDelta) {
- delta = newDelta;
- oldDelta = newDelta;
- }
- /** Doesn't alter settings but refreshes the values.
- * @param RNG
- */
- public void reshuffle(Random RNG) {
- current = new int[2];
- current[0] = -1*(1+RNG.nextInt(delta));
- current[1] = 1+RNG.nextInt(delta);
- cIndex = RNG.nextInt(2);
- alt = new int[2];
- alt[0] = -1*(1+RNG.nextInt(delta));
- alt[1] = 1+RNG.nextInt(delta);
- dropsSinceMinStreakLength = -streakMin;
- remainingGrace = gracePeriod;
- currentStatus = Status.STREAK;
- contractionValue = 1.0;
- }
- /** In an Arrythmia gamemode, call this immediately after locking the piece.
- * updates the speed parameter using the Heartbeat settings.
- * @param oldSpeed your speed parameter from the engine.
- * @param RNG your Engine's randomness
- * @return a new speed parameter to feed into the engine, for the next piece.
- */
- public SpeedParam updateSpeed(SpeedParam oldSpeed, Random RNG) {
- SpeedParam ret = new SpeedParam(oldSpeed); //copy current parameter for modifying and returning
- if (delta!=oldDelta) { //did delta change since last update?
- if(instantDeltaChangeRecompute) { //do I recompute current whenever delta changes?
- current[0] = -1*(1+RNG.nextInt(delta));
- current[1] = 1+RNG.nextInt(delta);
- }
- alt[0] = -1*(1+RNG.nextInt(delta)); //always recompute the alt.
- alt[1] = 1+RNG.nextInt(delta);
- oldDelta = delta; //now the change has been recorded
- }
- int newARE = meanARE; //find out what ARE you're in for.
- switch(currentStatus) {
- case STREAK:
- newARE += current[cIndex];
- dropsSinceMinStreakLength++;
- if (dropsSinceMinStreakLength >0) {
- double effectiveStreakDecay = streakDecay;
- switch(currentContraction) {
- case NONE:
- break;
- case HARMONIC:
- contractionValue += harmonicScale;
- effectiveStreakDecay /= contractionValue;
- break;
- case EXPONENTIAL:
- contractionValue *= exponentialScale;
- effectiveStreakDecay *= contractionValue;
- }
- if(RNG.nextDouble()>effectiveStreakDecay) { //if the generated value is bigger than computed value, end the streak
- dropsSinceMinStreakLength = -streakMin; //reset everything
- contractionValue = 1.0;
- remainingGrace = gracePeriod;
- current[cIndex]= (2*cIndex -1)*(1+RNG.nextInt(delta)); //reshuffle the current value for later.
- cIndex= 1-cIndex; //flip the sides
- if(RNG.nextDouble()<spikeIntoChange) { // roll to see if using a spike change
- currentStatus = Status.SWITCH;
- }
- break; //in all cases, ignore possibility of a spike,
- }
- }
- remainingGrace--;
- if(remainingGrace <=0) { //if the grace period is over, try for a spike
- if(RNG.nextDouble() < spikeProbability) {
- remainingGrace = gracePeriod;
- if(RNG.nextDouble() < miniSpike) { // is this spike mini?
- currentStatus = Status.MINI;
- } else { //in the likely chance it isn't, go for normal spike.
- currentStatus = Status.SPIKE;
- }
- }
- }
- break;
- case SPIKE:
- newARE += alt[1-cIndex];//for the spike, use an alt of the opposite sign
- alt[1-cIndex] = (1- 2*cIndex)*(1+RNG.nextInt(delta)); //reset the alt for next time.
- currentStatus = Status.STREAK; // go back to continuing the streak.
- break;
- case MINI:
- case SWITCH: //these are the same, but different names to reflect the difference in arrival method.
- newARE += alt[cIndex]; //unlike normally, don't go for opposite.
- alt[cIndex]= (2*cIndex -1)*(1+RNG.nextInt(delta)); //reset the alt for next time.
- currentStatus = Status.STREAK; // go back to continuing/starting the streak.
- break;
- }
- if (newARE < 0) { //ARE can't actually be literally negative.
- //set the real ARE to zero, but keep the newARE for later use (such as panic mode
- ret.are=0;
- ret.areLine=0;
- } else {
- //otherwise, setting it to the var is fine.
- ret.are=newARE;
- ret.areLine=newARE;
- }
- if (panicMode) { //mess with lock delay??
- if(newARE < 0) {
- ret.lockDelay = this.lockDelay - newARE;
- if(ret.lockDelay < 0) {
- ret.lockDelay = 0; //just in case
- }
- } else {
- ret.lockDelay = this.lockDelay;//otherwise, reset
- }
- }
- return ret;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment