/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package continuity;
import continuity.View.MapView;
import continuity.View.RoomView;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author FornetTeam
*/
public class Map {
/**
* A területen lévő helyiségek listája.
*/
private List<Room> rooms;
/**
* Map konstruktora.
* @param game A Communication interfész.
* @param characters A játék karakterei.
* @param filename A fájl neve, amiben a Map leírása van.
*/
public Map(Communication game, ArrayList<Character> characters, String filename) throws IOException {
rooms=new ArrayList<Room>();
int width, height, numberOfKeys, numberOfCompatible;
try {
BufferedReader br=new BufferedReader(new FileReader(filename));
String[] s=br.readLine().split(" ");
//4 szám beolvasása
height=Integer.parseInt(s[0]);
width=Integer.parseInt(s[1]);
numberOfKeys=Integer.parseInt(s[2]);
numberOfCompatible=Integer.parseInt(s[3]);
ArrayList<String> compatibles=new ArrayList<String>();
DoorElement door=new DoorElement(game, numberOfKeys);
//kompatibilitások beolvasása
for(int i=0;i<numberOfCompatible;i++) {
compatibles.add(br.readLine());
}
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++) {
ArrayList<String> description=new ArrayList<String>();
String line=br.readLine();
while(line != null &&
line.equals("") == false) {
description.add(line);
line=br.readLine();
}
//szoba létrehozása
rooms.add(new Room(game, characters, description, door));
}
//a külön sorban lévő szobák leírása között két üres sor van
br.readLine();
}
//kompatibilitások feldolgozása
for(int i=0;i<compatibles.size();i++) {
String[] str=compatibles.get(i).split(" ");
int a=Integer.parseInt(str[0]);
int b=Integer.parseInt(str[1]);
int c=Integer.parseInt(str[2]);
rooms.get(a).addCompatible(rooms.get(b), Direction.intToDirection(c));
}
//szomszédságok beállítása
for(int i=0;i<rooms.size();i++) {
Room r=rooms.get(i);
//nem alsó sor indexei
if(i<width*(height-1)) {
r.setNeighbor(rooms.get(i+width), Direction.Down);
}
//nem felső sor indexei
if(i>=width) {
r.setNeighbor(rooms.get(i-width), Direction.Up);
}
//nem bal oldal indexei
if(i%width!=0) {
r.setNeighbor(rooms.get(i-1), Direction.Left);
}
//nem jobb oldal indexei
if(i%width!=width-1) {
r.setNeighbor(rooms.get(i+1), Direction.Right);
}
}
} catch (IOException ex) {
Logger.getLogger(Map.class.getName()).log(Level.SEVERE, null, ex);
throw ex;
}
}
/**
* A megfelelő irányban cseréli az üres
* helyiséget valamelyik szomszédjával.
* Emellett beállítja a cserében résztvevő
* helyiségek kapcsolódó mezőinek kapcsolatait
* @param direction A mozgatás iránya
*/
public boolean swap(Direction direction) {
//emptyRoom megkeresése
Room empty=null;
for(int i=0;i<rooms.size();i++) {
Room r=rooms.get(i);
if(r.getBorderNode(Direction.Up, 0)==null &&
r.getBorderNode(Direction.Down, 0)==null &&
r.getBorderNode(Direction.Right, 0)==null &&
r.getBorderNode(Direction.Left, 0)==null) {
empty=r;
break;
}
}
if(empty==null) {
//nincs EmptyRoom a pályán, nem mozgathatunk szobákat.
return false;
}
//ha van a megfelelő oldalon szomszédja, csak akkor lesz csere + a végén return true, mert volt csere
if(empty.getNeighbor(direction) != null) {
Direction[] dirs = {Direction.Up, Direction.Down, Direction.Left, Direction.Right};
Room r=empty.getNeighbor(direction);
for(int i=0;i<dirs.length;i++) {
Direction actual=dirs[i];
/**
* Ha az aktuális I irány megegyezik a direction változóval
*/
if(actual==direction) {
if(r.getNeighbor(actual)!=null) {
r.getNeighbor(actual).setNeighbor(empty, actual.getOpposite());
}
empty.setNeighbor(r.getNeighbor(actual), actual);
r.setNeighbor(empty, actual);
}
/**
* Ha az aktuális I irány megegyezik a direction ellentétével
*/
else if(actual==direction.getOpposite()) {
if(empty.getNeighbor(actual) != null) {
empty.getNeighbor(actual).setNeighbor(r, actual.getOpposite());
}
r.setNeighbor(empty.getNeighbor(actual), actual);
empty.setNeighbor(r, actual);
}
/**
* Ha egyik előző sem teljesül
*/
else {
Room n1=empty.getNeighbor(actual);
Room n2=r.getNeighbor(actual);
if(n1!=null) {
n1.setNeighbor(r, actual.getOpposite());
}
if(n2!=null) {
n2.setNeighbor(empty, actual.getOpposite());
}
empty.setNeighbor(n2, actual);
r.setNeighbor(n1, actual);
}
}
//volt csere
return true;
}
//nem volt csere
return false;
}
private Room findLeftUpRoom() {
for(int i=0;i<rooms.size();i++) {
Room r = rooms.get(i);
if(r.getNeighbor(Direction.Left)==null &&
r.getNeighbor(Direction.Up)==null) {
return r;
}
}
return null;
}
@Override
public String toString() {
String eol=System.getProperty("line.separator");
String ret="";
int height=0;
int width=0;
Room r=findLeftUpRoom();
while(r != null) {
Room now=r;
while(now !=null) {
ret+=now.toString()+ eol;
now=now.getNeighbor(Direction.Right);
if(height==0) width++;
}
r=r.getNeighbor(Direction.Down);
if(r != null) {
ret+=eol;
}
height++;
}
ret=ret.substring(0, ret.length()-2);
ret=height + " " + width + eol + ret;
return ret;
}
public MapView createMapView() {
int height=0;
int width=0;
Room r=findLeftUpRoom();
//meghatározzuk, hogy hány szoba van egy oszlopban
Room temp=r;
while(temp!=null) {
height++;
temp=temp.getNeighbor(Direction.Down);
}
//meghatározzuk, hogy hány szoba van egy sorban
temp=r;
while(temp!=null) {
width++;
temp=temp.getNeighbor(Direction.Right);
}
//megfelelő méretű tömb létrehozása
RoomView[][] roomViews=new RoomView[height][width];
//bejárás balról jobbra, fentről le + empty room helyzet meghatározás
int emptyRoomPositionX=0;
int emptyRoomPositionY=0;
int nowx=0;
while(r!=null) {
Room now=r;
int nowy=0;
while(now!=null) {
RoomView tmp=now.createRoomView();
//ha ez az empty, elmentjük a koordinátáit
if(now.getBorderNode(Direction.Up, 0)==null &&
now.getBorderNode(Direction.Down, 0)==null &&
now.getBorderNode(Direction.Right, 0)==null &&
now.getBorderNode(Direction.Left, 0)==null) {
emptyRoomPositionX=nowx;
emptyRoomPositionY=nowy;
}
roomViews[nowx][nowy]=tmp;
nowy++;
now=now.getNeighbor(Direction.Right);
}
nowx++;
r=r.getNeighbor(Direction.Down);
}
return new MapView(roomViews, emptyRoomPositionX, emptyRoomPositionY);
}
}