package dev.llan.model; import dev.llan.events.Events.*; import dev.llan.events.SwitchStateEvent; import dev.llan.model.board.GameMap; import dev.llan.model.board.Point; import dev.llan.events.GameEvent; import dev.llan.model.pieces.Entity; import dev.llan.model.pieces.GamePieces; import dev.llan.model.pieces.inanimates.Inanimate; import dev.llan.model.pieces.enemies.Enemy; import dev.llan.model.pieces.player.Player; import dev.llan.model.state.*; import dev.llan.model.state.combat.CombatManager.CombatPhase; import dev.llan.model.state.combat.TurnInfo; import java.util.ArrayList; import java.util.List; import java.util.Optional; import static dev.llan.model.Constants.*; public class Game { private GameMap map; private Player player; private List enemies; private List inanimates; private GameState state; private int floor; private int score; public Game(int size) { score = 0; floor = 1; map = new GameMap(this, size); this.initGamePieces(); this.state = new Exploration(this); map.updateGameState(State.EXPLORATION); } public void nextFloor() { floor++; score += floor * FLOOR_BONUS; if (floor <= MAX_FLOOR) { this.generateNextFloor(); } else { this.win(); } } private void initGamePieces() { GamePieces initialized = map.init(); player = initialized.player(); enemies = initialized.enemies(); inanimates = initialized.inanimates(); } private void generateNextFloor() { GamePieces nextInitialized = map.initNext(player); enemies = nextInitialized.enemies(); inanimates = nextInitialized.inanimates(); } public void addScore(int score) { this.score += score; } public List setState(State newState) { List events = new ArrayList<>(); switch (newState) { case COMBAT -> state = new Combat(this); case EXPLORATION -> state = new Exploration(this); default -> throw new IllegalArgumentException("Input is not a valid game state"); } map.updateGameState(newState); events.addAll(state.onSwapTo()); events.add(new SwitchStateEvent(newState)); return events; } public State getState() { return this.state.getState(); } public CombatPhase getPhase() { if (state instanceof Combat) { return ((Combat) state).getPhase(); } return CombatPhase.NONE; } public Optional getTurn() { if (state.getState() == State.COMBAT) { Entity entity = ((Combat) state).getCurrentTurn(); if(entity != null) { return Optional.of(entity); } } return Optional.empty(); } public List getTurnsList() { if(state.getState() == State.COMBAT) { return ((Combat) state).getTurnsList(); } return List.of(); } public List tryMoveTo(Point position) { return state.tryMoveTo(position); } public List moveActivePath() { return state.moveActivePath(); } public List endTurn() { return state.endTurn(); } public List waitTurn() { return state.waitTurn(); } public List useCardOn(Point position) { return state.useCardOn(position); } public List swapCards(int first, int second) { return state.swapCards(first, second); } public List selectCard(int cardIndex) { return state.selectCard(cardIndex); } public List removeCard(int index) { return state.removeCard(index); } public List equip(int index) { return state.equip(index); } public List swapEquipment(int first, int second) { return state.swapEquipment(first, second); } public List removeEquipment(int index) { return state.removeEquipment(index); } public List setHighlighted(Point point, boolean highlighted) { return state.setHighlighted(point, highlighted); } public GameMap getMap() { return map; } public Player getPlayer() { return player; } public List getEnemies() { return enemies; } public List getInanimates() { return inanimates; } public int getFloor() { return floor; } public int getScore() { return score; } public void removeEnemy(Enemy enemy) { enemies.remove(enemy); } public void removeInanimate(Inanimate inanimate) { inanimates.remove(inanimate); } public void end() { state = new End(this); } public void win() { state = new Win(this); } public GameRecord getImmutableSnapshot(EventType eventType) { return new GameRecord(this, eventType); } }