package ingsw.proj.cluedo.logica;
import ingsw.proj.cluedo.componenti.ArmiEnum;
import ingsw.proj.cluedo.componenti.Carta;
import ingsw.proj.cluedo.componenti.Casella;
import ingsw.proj.cluedo.componenti.CasellaPassaggioSegreto;
import ingsw.proj.cluedo.componenti.CasellaPorta;
import ingsw.proj.cluedo.componenti.Congettura;
import ingsw.proj.cluedo.componenti.Giocatore;
import ingsw.proj.cluedo.componenti.Pedina;
import ingsw.proj.cluedo.componenti.Soluzione;
import ingsw.proj.cluedo.componenti.StanzeEnum;
import ingsw.proj.cluedo.componenti.Tabellone;
import ingsw.proj.cluedo.componenti.Casella.CasellaRidotta;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
class ControlloreDiGioco {
private final Tabellone tabellone;
private final List<Giocatore> giocatori;
// TODO: getter + mostra alla fine gioco
private final Soluzione soluzione;
private final List<Pedina> pedineArmi;
private boolean giocoTerminato;
public ControlloreDiGioco(List<Giocatore> giocatori, Soluzione soluzione, Tabellone tabellone, List<Pedina> pedineArmi) throws NullPointerException {
if (giocatori == null || soluzione == null || tabellone == null || pedineArmi == null)
throw new NullPointerException("Un argomento � null.");
else {
this.giocatori = giocatori;
this.soluzione = soluzione;
this.tabellone = tabellone;
this.pedineArmi = pedineArmi;
this.giocoTerminato = false;
}
}
public Iterator<Point> getDestinazioniGiocatore(String nome) {
Giocatore giocatore = getGiocatore(nome);
List<Casella> dest = getPossibiliDestinazioni(giocatore.getPosizione());
ArrayList<Point> result = new ArrayList<Point>();
for (int i = 0; i < dest.size(); i++) {
result.add(tabellone.getPosizione(dest.get(i)));
}
giocatore.setUltimaAzione(AzioniEnum.MOVIMENTO);
return result.iterator();
}
private Giocatore getGiocatore(String nome) {
for (Giocatore giocatore : giocatori) {
if (giocatore.getNome().equals(nome))
return giocatore;
}
return null;
}
public Iterator<String> getNoteGiocatore(String nome) {
return getGiocatore(nome).getNote();
}
public Point getPosizioneGiocatore(String nome) {
Giocatore giocatore = getGiocatore(nome);
return tabellone.getPosizione(giocatore.getPosizione());
}
private List<Casella> getPossibiliDestinazioni(Casella partenza) {
ArrayList<Casella> dest = new ArrayList<Casella>();
if (partenza != null) {
if (partenza instanceof CasellaPorta) {
CasellaPorta destinazione = (CasellaPorta) tabellone.getCasella(((CasellaPorta) partenza).getDestinazione());
if (VerificaDestinazione((CasellaPorta) partenza, destinazione))
dest.add(destinazione);
}
if (partenza instanceof CasellaPassaggioSegreto) {
CasellaPassaggioSegreto destinazione = (CasellaPassaggioSegreto) tabellone.getCasella(((CasellaPassaggioSegreto) partenza).getDestinazione());
if (VerificaDestinazione((CasellaPassaggioSegreto) partenza, destinazione))
dest.add(destinazione);
}
Point coord_attuali = tabellone.getPosizione(partenza);
Casella destinazione = tabellone.getCasella(new Point(coord_attuali.x + 1, coord_attuali.y));
if (VerificaDestinazione(partenza, destinazione))
dest.add(destinazione);
destinazione = tabellone.getCasella(new Point(coord_attuali.x - 1, coord_attuali.y));
if (VerificaDestinazione(partenza, destinazione))
dest.add(destinazione);
destinazione = tabellone.getCasella(new Point(coord_attuali.x, coord_attuali.y + 1));
if (VerificaDestinazione(partenza, destinazione))
dest.add(destinazione);
destinazione = tabellone.getCasella(new Point(coord_attuali.x, coord_attuali.y - 1));
if (VerificaDestinazione(partenza, destinazione))
dest.add(destinazione);
}
return dest;
}
public StanzeEnum getStanzaGiocatore(String nome) {
Giocatore giocatore = getGiocatore(nome);
return giocatore.getPosizione().getStanza();
}
public boolean getStatoGiocatore(String nome) {
Giocatore giocatore = getGiocatore(nome);
return giocatore.getInGioco();
}
public CasellaRidotta[][] getTabelloneRidotto() {
return tabellone.getCaselleRidotte();
}
public boolean giocoAttivo() {
return !giocoTerminato;
}
private void notificaGiocatore(String messaggio, Giocatore giocatore) {
giocatore.aggiungiNota(messaggio);
}
private void notificaTutti(String messaggio) {
for (Giocatore giocatore : giocatori) {
giocatore.aggiungiNota(messaggio);
}
}
public void spostaGiocatore(String nome, Point destinazione) {
Giocatore giocatore = getGiocatore(nome);
giocatore.cambiaPosizione(tabellone.getCasella(destinazione));
giocatore.setUltimaAzione(AzioniEnum.MOVIMENTO);
}
public boolean verificaAccusa(Congettura accusa) {
Giocatore giocatore = getGiocatore(accusa.getAccusante());
Giocatore colpevole = getGiocatore(accusa.getAccusato());
Casella destinazione;
ArmiEnum arma = accusa.getArma();
StanzeEnum stanza = giocatore.getStanza();
notificaTutti(giocatore.getNome() + " accusa " + colpevole.getNome() + " di aver ucciso in " + stanza.toString() + " con l'arma " + arma.toString());
boolean esito = false;
if (verificaCongettura(accusa)) {
notificaTutti(giocatore.getNome() + " ha vinto!");
giocoTerminato = true;
esito = true;
} else {
notificaTutti(giocatore.getNome() + " ha perso!");
giocatore.setInGioco(false);
giocoTerminato = true;
for (Giocatore temp : giocatori) {
if (temp.getInGioco()) {
giocoTerminato = false;
break;
}
}
}
destinazione = tabellone.getCasellaVuotaInStanza(giocatore.getStanza());
colpevole.cambiaPosizione(destinazione);
for (Pedina pedina : pedineArmi) {
if (pedina.getNome().equals(accusa.getArma().toString())) {
destinazione = tabellone.getCasellaVuotaInStanza(giocatore.getStanza());
pedina.cambiaPosizione(destinazione);
}
}
giocatore.setUltimaAzione(AzioniEnum.ACCUSA);
return esito;
}
private boolean VerificaDestinazione(Casella partenza, Casella arrivo) {
// Se la destinazione esiste
if ((arrivo == null) || (partenza == null))
return false;
// Se la destinazione e' non vuota
else if (arrivo.getOccupante() == null) {
// Se la destinazione appartiene alla stessa
if (partenza.getStanza() == arrivo.getStanza())
return true;
// Se parto da una casella "porta" e arrivo su una simile
else if ((partenza instanceof CasellaPorta) && (arrivo instanceof CasellaPorta))
return true;
// Se parto da una casella "passaggio segreto" e arrivo su una
// simile
else if ((partenza instanceof CasellaPassaggioSegreto) && (arrivo instanceof CasellaPassaggioSegreto))
return true;
}
return false;
}
private boolean verificaCongettura(Congettura ipotesi) {
boolean flag = false;
String mostrata = null;
String colpevole = ipotesi.getAccusato();
ArmiEnum arma = ipotesi.getArma();
Giocatore daControllare = null;
Giocatore giocatore = getGiocatore(ipotesi.getAccusante());
StanzeEnum stanza = giocatore.getStanza();
if ((giocatore != null) && (arma != null) && (stanza != null) && (colpevole != "")) {
int miaPosizione = giocatori.indexOf(giocatore);
for (int i = miaPosizione - 1; i >= 0 && !flag; i--) {
daControllare = giocatori.get(i);
if (daControllare.haCarta(arma.toString())) {
flag = true;
mostrata = arma.toString();
}
if (daControllare.haCarta(stanza.toString())) {
flag = true;
mostrata = stanza.toString();
}
if (daControllare.haCarta(colpevole)) {
flag = true;
mostrata = colpevole;
}
}
for (int i = giocatori.size() - 1; i >= miaPosizione && !flag; i--) {
daControllare = giocatori.get(i);
if (daControllare.haCarta(arma.toString())) {
flag = true;
mostrata = arma.toString();
}
if (daControllare.haCarta(stanza.toString())) {
flag = true;
mostrata = stanza.toString();
}
if (daControllare.haCarta(colpevole)) {
flag = true;
mostrata = colpevole;
}
}
Casella destinazione = tabellone.getCasellaVuotaInStanza(giocatore.getStanza());
getGiocatore(colpevole).cambiaPosizione(destinazione);
for (Pedina pedina : pedineArmi) {
if (pedina.getNome().equals(ipotesi.getArma().toString())) {
destinazione = tabellone.getCasellaVuotaInStanza(giocatore.getStanza());
pedina.cambiaPosizione(destinazione);
}
}
if (flag && mostrata != null) {
notificaTutti(daControllare.getNome() + " ha confutato la teoria di " + giocatore.getNome());
notificaGiocatore(daControllare.getNome() + " ha confutato la mia teoria con la carta " + mostrata, giocatore);
notificaGiocatore("Ho confutato la teoria di " + giocatore.getNome() + " mostrando la carta " + mostrata, daControllare);
} else {
notificaTutti("Nessuno ha confutato la teoria di " + giocatore.getNome());
}
}
giocatore.setUltimaAzione(AzioniEnum.IPOTESI);
return !flag;
}
public boolean verificaIpotesi(Congettura ipotesi) {
String colpevole = ipotesi.getAccusato();
ArmiEnum arma = ipotesi.getArma();
Giocatore giocatore = getGiocatore(ipotesi.getAccusante());
StanzeEnum stanza = giocatore.getStanza();
notificaTutti(giocatore.getNome() + " pensa che " + colpevole + " ha ucciso in " + stanza.toString() + " con l'arma " + arma.toString());
giocatore.setUltimaAzione(AzioniEnum.IPOTESI);
return verificaCongettura(ipotesi);
}
public String getProssimoGiocatore(String attuale) {
if (attuale == null) {
Giocatore giocatore = giocatori.get(0);
giocatore.setUltimaAzione(AzioniEnum.INIZIA);
return giocatore.getNome();
} else {
int i;
Giocatore giocatore = getGiocatore(attuale);
Giocatore prossimo = null;
giocatore.setUltimaAzione(AzioniEnum.PASSA);
// Se il gioco e' finito e' inutile perdere tempo.
if (!giocoAttivo())
return null;
// Vedo in che posizione sono nel turno
for (i = 0; i < giocatori.size(); i++) {
if (giocatori.get(i).equals(giocatore))
break;
}
// Se sono l'ultimo, oppure io non sono presente (!!!ASSURDO!!!)
// Decido di scegliere il primo giocatore disponibile nell'array.
if (i >= giocatori.size() - 1) {
for (int j = 0; j < giocatori.size(); j++) {
if (giocatori.get(j).getInGioco()) {
prossimo = giocatori.get(j);
break;
}
}
} else {
// Altrimenti scorro da dopo di me fino alla fine dell'array
boolean found = false;
for (int j = i + 1; j < giocatori.size(); j++) {
if (giocatori.get(j).getInGioco()) {
prossimo = giocatori.get(j);
found = true;
break;
}
}
// Se non ho ancora trovato niente
if (!found) {
// Scorro dall'inizio fino a me (incluso)
for (int j = 0; j <= i; j++) {
if (giocatori.get(j).getInGioco()) {
prossimo = giocatori.get(j);
found = true;
break;
}
} // Se fallisco pure qui, ritorno null
if (!found)
return null;
}
}
prossimo.setUltimaAzione(AzioniEnum.INIZIA);
return prossimo.getNome();
}
}
public Iterator<AzioniEnum> getPossibiliAzioni(String nome) {
Giocatore giocatore = getGiocatore(nome);
AzioniEnum ultimaAzione = giocatore.getUltimaAzione();
ArrayList<AzioniEnum> scelte = new ArrayList<AzioniEnum>();
if (ultimaAzione == AzioniEnum.INIZIA)
scelte.add(AzioniEnum.MOVIMENTO);
if ((ultimaAzione == AzioniEnum.INIZIA) || (ultimaAzione == AzioniEnum.MOVIMENTO)) {
if (giocatore.getStanza() != StanzeEnum.CORRIDOIO) {
scelte.add(AzioniEnum.IPOTESI);
scelte.add(AzioniEnum.ACCUSA);
}
}
scelte.add(AzioniEnum.PASSA);
return scelte.iterator();
}
public Iterator<String> getCarteGiocatore(String giocatoreAttuale) {
Iterator<Carta> cartaIt = getGiocatore(giocatoreAttuale).getMazzo();
ArrayList<String> elenco = new ArrayList<String>();
while (cartaIt.hasNext()) {
elenco.add(cartaIt.next().getNome());
}
return elenco.iterator();
}
public Soluzione getSoluzione() {
return soluzione;
}
}