Skip to content
Snippets Groups Projects
Patient.java 7.12 KiB
Newer Older
  • Learn to ignore specific revisions
  • package model.doctorviruspatient;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Objects;
    
    import javafx.scene.paint.Color;
    import model.Board;
    import model.Entity;
    import model.Square;
    import util.Position;
    import util.PositionUtil;
    
    public class Patient implements Entity {
        private final int priority = 0;
        Position position;
        private int age;
        private final Color viewColor = Color.BLUE;
        private Virus carriedVirus;
        List<Entity> visitedPatients;
        private static int patientsCount = 0;
        private int patientID;
        private Position ennemy;
        private boolean wandering;
    
        public Patient(Position p) {
            this.wandering = true;
            patientID = patientsCount;
            patientsCount += 1;
            this.visitedPatients = new ArrayList<Entity>();
            this.position = p;
        }
    
        public Patient(Position p, int age) {
            this.wandering = true;
            patientID = patientsCount;
            patientsCount += 1;
            this.visitedPatients = new ArrayList<Entity>();
            this.position = p;
            this.age = age;
        }
    
        @Override
        public List<Position> nextTurn(Board<Square> board) {
    
    Yanis O's avatar
    Yanis O committed
            if(isInfected()){
                return moveToDoctor();
            }
    
            updateWanderingStatus(board);
        
            if (wandering) {
                return performWandering(board);
            }
        
            resetVisitedPatientsIfNecessary();
        
            Position target = determineTarget(board);
        
            if (target == null) {
                visitedPatients.clear();
                return List.of();
            }
        
            Position nextPos = determineNextPosition(target, board);
        
            if (nextPos != null && board.doesPositionExist(nextPos)) {
                
                List<Position> adjacentPositions = PositionUtil.generateAllAdjacentPositions(nextPos, board);
                List<Position> result = interactWithAdjacentPositions(adjacentPositions, board);
                result.addAll(moveToPosition(nextPos, board));
                result.addAll(adjacentPositions);
                result.add(position);
                return result;
            }
        
            return List.of();
        }
        
        
        private void updateWanderingStatus(Board<Square> board) {
        if (board.getStepNumber() % 8 == 0) {
            wandering = false;
        }
    }
    
    Yanis O's avatar
    Yanis O committed
    private List<Position> moveToDoctor(){
        return List.of();
    }
    
    private List<Position> performWandering(Board<Square> board) {
        List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, board);
        Collections.shuffle(adjacentPositions);
    
        Position oldPosition = position;
        Position newPosition = adjacentPositions.get(0);
    
        moveEntityOnBoard(oldPosition, newPosition, board);
        return List.of(newPosition, oldPosition);
    }
    
    private void resetVisitedPatientsIfNecessary() {
        if (visitedPatients.size() - 1 >= patientsCount) {
            visitedPatients.clear();
        }
    }
    
    private Position determineTarget(Board<Square> board) {
        return board.getNearestEntity(position, Patient.class, getVisitedPatients());
    }
    
    private Position determineNextPosition(Position target, Board<Square> board) {
        int enemyDistance = PositionUtil.getManhattanDistance(target, position);
    
        if (ennemy != null && enemyDistance < 2) {
            return PositionUtil.getNextPositionAwayFrom(position, target, board);
        } else if (target != null) {
            return PositionUtil.getNextPositionTowards(position, target, board);
        }
        return null;
    }
    
    private List<Position> moveToPosition(Position nextPos, Board<Square> board) {
        if (!board.isPositionFree(nextPos, priority)) {
            nextPos = findAlternativePosition(nextPos, board);
        }
    
        if (nextPos != null) {
            Position oldPosition = position;
            moveEntityOnBoard(oldPosition, nextPos, board);
        }
        
        return List.of(new Position(this.position.x(), this.position.y()), nextPos);
    }
    
    private Position findAlternativePosition(Position currentPos, Board<Square> board) {
        List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, board);
        for (Position p : adjacentPositions) {
            if (ennemy != null) {
                Position awayPos = PositionUtil.getNextPositionAwayFrom(p, ennemy, board);
                if (p.equals(awayPos)) {
                    // Si la position reste la même après avoir tenté de s'éloigner, on continue
                    continue;
                }
            }
            if (board.isPositionFree(p, priority)) {
                return p;
            }
        }
        return null;
    }
    
    
    private void moveEntityOnBoard(Position oldPosition, Position newPosition, Board<Square> board) {
        board.clearCaseFrom(this, oldPosition);
        board.addEntityAtSquare(this, newPosition);
        this.position = newPosition;
    }
    
    private List<Position> interactWithAdjacentPositions(List<Position> adjacentPositions, Board<Square> board) {
        List<Position> result = new ArrayList<>();
        for (Position p : adjacentPositions) {
            if (board.doesSquareContainEntity(p, Patient.class)) {
                handleEncounterWithPatient(p, board);
                if (isInfected()) {
                    result.addAll(adjacentPositions);
                }
            }
        }
        return result;
    }
    
    private void handleEncounterWithPatient(Position p, Board<Square> board) {
        this.wandering = true;
        Patient patient = (Patient) board.getStates(p).getEntities().stream()
            .filter(entity -> entity instanceof Patient)
            .findFirst()
            .orElse(null);
    
        if(isInfected()){
            patient.infect(carriedVirus);
        }
    
        if (patient != null) {
            this.ennemy = patient.getPosition();
            visitedPatients.add(patient);
        }
    }
    
    
        @Override
        public Position getPosition() {
            return this.position;
        }
    
        @Override
        public void setPosition(Position p) {
            this.position = p;
    
        }
    
        @Override
        public int getAge() {
            return this.age;
        }
    
        @Override
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public void incrementAge() {
            this.age += 1;
        }
    
        @Override
        public Color getViewColor() {
    
            return isInfected() ? Color.CYAN : this.viewColor;
    
        }
    
        @Override
        public int getPriority() {
            return this.priority;
        }
    
        public boolean isInfected(){
            return this.carriedVirus != null;
        }
    
        public void infect(Virus virus){
    
            if(this.carriedVirus != null) return;
    
            this.carriedVirus = virus;
        }
    
        public Virus getVirus(){
            return this.carriedVirus;
        }
        
        public List<Entity> getVisitedPatients(){
            return this.visitedPatients;
        }
    
        public boolean hasVisited(Patient patient){
            return this.getVisitedPatients().contains(patient);
        }
    
        public int getPatientId(){
            return this.patientID;
        }
    
    
    Yanis O's avatar
    Yanis O committed
        public void cure(){
            if(this.carriedVirus.tryToKill()){
                this.carriedVirus = null;
            }
        }
    
    
        @Override
        public boolean equals(Object obj) {
            if(obj instanceof Patient){
                Patient other = (Patient) obj;
                return this.patientID == other.getPatientId();
            }else{
                return false;
            }
            
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(patientID);
        }
    }