package game;
import main.Main;
import model.Bonus.Bonus;
import model.Bonus.Effects.*;
import model.Snake.Snake;
import utils.MathUtils;
import utils.RandomUtils;
import websocket.message.EatBonusMessage;
import websocket.message.NewBonusMessage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* Created by egor on 22.04.15.
*/
public class BonusManager {
public static final int DEFAULT_BONUS_JITTER = 2 * 60;
public static final int BONUS_SPAWN_PADDING = 60;
private List<TemporaryEffect> activeEffects = new LinkedList<>();
private List<Snake> snakes;
private List<Bonus> bonuses = new LinkedList<>();
private Room room;
private int bonusProbSum = 0;
private List<Integer> bonusProbabilities;
private int bonusSpawnProbability;
public BonusManager(List<Snake> snakes, Room room) {
this.room = room;
this.snakes = snakes;
bonusSpawnProbability = Main.mechanicsConfig.getInt("bonusSpawnProbability");
bonusProbSum = 0;
bonusProbabilities = Main.mechanicsConfig.getIntList("bonusProbabilities");
bonusProbSum = bonusProbabilities.stream().reduce((n1, n2) -> n1 + n2).get();
}
public void addBonus(Bonus bonus) {
bonuses.add(bonus);
room.broadcastMessage(new NewBonusMessage(bonus));
}
private void applyTempEffect(TemporaryEffect effect) {
effect.activate();
activeEffects.add(effect);
}
private void applyBonus(Bonus bonus, Snake snake) {
switch (bonus.getKind()) {
case SPEED_SELF:
applyTempEffect(new SpeedSelfEffect(snake));
break;
case THIN_SELF:
applyTempEffect(new ThinSelfEffect(snake));
break;
case ERASE_SELF:
snake.eraseSelf();
break;
case SLOW_SELF:
applyTempEffect(new SlowSelfEffect(snake));
break;
case BIG_HOLE_SELF:
applyTempEffect(new BigHoleSelfEffect(snake));
break;
case TRAVERSE_WALLS_SELF:
applyTempEffect(new TravWallsSelfEffect(snake));
break;
case SHARP_CORNERS_SELF:
applyTempEffect(new SharpCornersSelfEffect(snake));
break;
case SPEED_ENEMY:
for (Snake other : snakes) {
if (other != snake) applyTempEffect(new SpeedSelfEffect(other));
}
break;
case THICK_ENEMY:
applyTempEffect(new ThickEnemyEffect(snake, snakes));
break;
case SLOW_ENEMY:
applyTempEffect(new SlowEnemyEffect(snake, snakes));
break;
case BIG_TURNS_ENEMY:
applyTempEffect(new BigTurnsEnemyEffect(snake, snakes));
break;
case TRAVERSE_WALLS_ALL:
applyTempEffect(new TraverseWallsAllEffect(snakes));
break;
case DEATH_ALL:
room.getGameField().killSnake(snakes.get(RandomUtils.randInt(0, snakes.size() - 1)));
break;
case REVERSE_ENEMY:
applyTempEffect(new ReverseEnemyEffect(snake, snakes));
break;
}
}
private int c = 0;
public void timeStep() {
for (Iterator<TemporaryEffect> iter = activeEffects.iterator(); iter.hasNext(); ) {
TemporaryEffect effect = iter.next();
if (effect.timeStep()) {
effect.deactivate();
iter.remove();
}
}
for (Snake snake : snakes) {
for (Iterator<Bonus> bonusIter = bonuses.iterator(); bonusIter.hasNext(); ) {
Bonus bonus = bonusIter.next();
if (bonus.isReachableBy(snake)) {
applyBonus(bonus, snake);
room.broadcastMessage(new EatBonusMessage(bonus.getId(), snake));
bonusIter.remove();
}
}
}
c++;
if (c % RandomUtils.randInt(bonusSpawnProbability, bonusSpawnProbability) == 0) {
spawnBonus();
}
}
private void spawnBonus() {
int x = RandomUtils.randInt(BONUS_SPAWN_PADDING,
Integer.valueOf(Main.mechanicsConfig.getInt("gameField.width")) - 2 * BONUS_SPAWN_PADDING);
int y = RandomUtils.randInt(BONUS_SPAWN_PADDING,
Integer.valueOf(Main.mechanicsConfig.getInt("gameField.height")) - 2 * BONUS_SPAWN_PADDING);
addBonus(new Bonus(x, y, getRandomBonusKind()));
}
private Bonus.Kind getRandomBonusKind() {
// TODO: probabilities
// int random = MathUtils.rand.nextInt(bonusProbSum);
// for(int i = 0; i < bonusProbabilities.length; ++i) {
// if (random >= bonusProbabilities[i]) {
// return Bonus.Kind.values()[i];
// }
// i++;
// }
return Bonus.Kind.values()[MathUtils.rand.nextInt(Bonus.Kind.values().length)];
}
}