From c0d4e75f70f434c2da91f49932a53b0023b3419c Mon Sep 17 00:00:00 2001
From: edani95 <elekdani95@gmail.com>
Date: Sun, 15 May 2016 11:25:53 +0200
Subject: [PATCH] Map sequence bug fix

---
 core/app/Controller.java     |  33 ++++---
 core/app/GameController.java | 162 +++++++++++++++++++++++------------
 core/app/InitController.java |  19 +---
 core/game/Direction.java     |  12 +++
 core/game/Model.java         |  85 ++++++++++++++----
 5 files changed, 210 insertions(+), 101 deletions(-)

diff --git a/core/app/Controller.java b/core/app/Controller.java
index 3d7c36a..53d94fa 100644
--- a/core/app/Controller.java
+++ b/core/app/Controller.java
@@ -40,8 +40,8 @@ import view.ZPMView;
 public class Controller {
 	private View view;
 
-	private int colonelLife;
-	private int jaffaLife;
+	private int colonelInitLife;
+	private int jaffaInitLife;
 	private int maxLvl;
 	private boolean gameStarted = false;
 
@@ -82,8 +82,8 @@ public class Controller {
 	 */
 	public void startGame(int colonelLife, int jaffaLife, int maxLvl)
 	{
-		this.colonelLife = colonelLife;
-		this.jaffaLife = jaffaLife;
+		this.colonelInitLife = colonelLife;
+		this.jaffaInitLife = jaffaLife;
 		this.maxLvl = maxLvl;
 
 		// invoke main thread to run game
@@ -96,8 +96,13 @@ public class Controller {
 		int failure = 0;
 
 		InitController.generateValidPairs();
-		InitController.startColonelZPMs = 0;
-		InitController.startJaffaZPMs = 0;
+
+		// ZPM counts of each player in a
+		// specific order
+		int[] playerZPMs = new int[] {
+				InitController.startColonelZPMs,
+				InitController.startJaffaZPMs
+				};
 
 		for(; actualLvl <= maxLvl; actualLvl++)
 		{
@@ -114,8 +119,9 @@ public class Controller {
 				uploadMapDatas();
 
 				GameController game = new GameController(view, InitController.map.length, InitController.map[0].length);
-				game.startGameProcess();
-				//actualLvl++;
+
+				// Boxing: GameController updates ZPM count through reference
+				game.startGameProcess( playerZPMs );
 			} catch (FileNotFoundException e) {
 				System.err.println("Map with path " + mapPath + " not found");
 				continue;
@@ -137,7 +143,7 @@ public class Controller {
 		}
 
 		// end of game
-		this.view.finishGame(InitController.startColonelZPMs, InitController.startJaffaZPMs);
+		this.view.finishGame(playerZPMs[0], playerZPMs[1]);
 		System.exit(0);
 	}
 
@@ -151,6 +157,7 @@ public class Controller {
 	 */
 	private boolean initMap(String mapPath) throws IOException
 	{
+		Model.getInstance().restartMap();
 		BufferedReader br = new BufferedReader(new FileReader(mapPath));
 
 		String command;
@@ -173,12 +180,12 @@ public class Controller {
 	private void updateLifeSettings()
 	{
 		if(InitController.colonel != null)
-			InitController.colonel.setPlayerLives(colonelLife);
+			InitController.colonel.setPlayerLives(colonelInitLife);
 		else
 			System.err.println("No colonel found when game starts");
 
 		if(InitController.jaffa != null)
-			InitController.jaffa.setPlayerLives(jaffaLife);
+			InitController.jaffa.setPlayerLives(jaffaInitLife);
 		else
 			System.err.println("No jaffa found when game starts");
 	}
@@ -197,13 +204,13 @@ public class Controller {
 
 		if(InitController.colonel != null && InitController.jaffa != null)
 		{
-			view.showGame(InitController.map[0].length, InitController.map.length, colonelLife, jaffaLife,
+			view.showGame(InitController.map[0].length, InitController.map.length, colonelInitLife, jaffaInitLife,
 					InitController.startColonelZPMs + Model.getInstance().getColonel().getZpmCount(),
 					InitController.startJaffaZPMs + Model.getInstance().getJaffa().getZpmCount());
 		}
 		else
 		{
-			view.showGame(InitController.map[0].length, InitController.map.length, colonelLife, jaffaLife, 0, 0);
+			view.showGame(InitController.map[0].length, InitController.map.length, colonelInitLife, jaffaInitLife, 0, 0);
 			if(InitController.colonel == null)
 				System.err.println("No colonel found when game starts");
 			if(InitController.jaffa == null)
diff --git a/core/app/GameController.java b/core/app/GameController.java
index e4f22ec..e1a3ee4 100644
--- a/core/app/GameController.java
+++ b/core/app/GameController.java
@@ -1,6 +1,8 @@
 package app;
 
 import java.awt.event.KeyEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.util.ArrayList;
 
 import exceptions.GameRunningException;
@@ -14,25 +16,36 @@ import mapobjs.movobjs.Player;
 import view.View;
 import view.ViewElement;
 
-public class GameController {
+public class GameController implements PropertyChangeListener{
 	private View view;
 	private ArrayList<IElement>[][] map;
-	
+
+	@SuppressWarnings("unchecked")
 	public GameController(View view, int width, int height)
 	{
 		this.view = view;
-		map = InitController.map;
+		map = new ArrayList[InitController.map.length][InitController.map[0].length];
+		Model.getInstance().addPropertyChangeListener(this);
 	}
-	
-	public void startGameProcess() throws GameRunningException
+
+	/**
+	 * Starts and runs through a game process with a map.
+	 * @param rZPMCount Global ZPM counts which have to be updated.
+	 * <ul>
+	 * <li> 0 - colonel</li>
+	 * <li> 1 - jaffa </li>
+	 * </ul>
+	 * @throws GameRunningException
+	 */
+	public void startGameProcess( int[] rZPMCount) throws GameRunningException
 	{
-		Model.getInstance().restartMap();
-		
 		int failure = 0;
 		int counter = 0;
+
+		// previous values of the players lives
 		Integer tmpColonelLives = Model.getInstance().getColonel().getPlayerLives();
 		Integer tmpJaffaLives = Model.getInstance().getJaffa().getPlayerLives();
-		
+
 		while(true)
 		{
 			try {
@@ -48,7 +61,7 @@ public class GameController {
 					throw new GameRunningException();
 				}
 			}
-			
+
 			if(counter < 4)
 			{
 				counter++;
@@ -61,10 +74,14 @@ public class GameController {
 				}
 				counter = 0;
 			}
-			
+
 			Integer lastKey = view.getLastKey();
 			if(lastKey != null)
 			{
+				// previous values of the players ZPM counts
+				int prevColonelZpm = Model.getInstance().getColonel().getZpmCount();
+				int prevJaffaZpm = Model.getInstance().getJaffa().getZpmCount();
+
 				switch(lastKey)
 				{
 					// Colonel controls
@@ -187,24 +204,27 @@ public class GameController {
 					boxUp(Model.getInstance().getJaffa());
 					break;
 				}
-				
+
 				if(Model.getInstance().isMapFinished())
 				{
 					break;
 				}
-			}	
-		}
-		
-		endProcess();
-		
+
+				updateZPMCount( rZPMCount, prevColonelZpm, prevJaffaZpm );
+			} // end of if key pressed
+
+		} // end of while
+
+		Model.getInstance().removePropertyChangeListener(this);
+
 		return;	// Map finished
 	}
-	
+
 	private void updateViewToolbar(Integer beforeColonelLives, Integer beforeJaffaLives)
 	{
 		int afterColonelLives = Model.getInstance().getColonel().getPlayerLives();
 		int afterJaffaLives = Model.getInstance().getJaffa().getPlayerLives();
-		
+
 		if(beforeColonelLives.intValue() != afterColonelLives)
 		{
 			view.setColonelLivesDisplayed(afterColonelLives);
@@ -216,68 +236,98 @@ public class GameController {
 			beforeJaffaLives = afterJaffaLives;
 		}
 	}
-	
+
 	private void move(Player player)
 	{
 		player.step();
-		updateGameControllerMap();
-		ArrayList<ViewElement>[][] viewMap = uploadToView();
-		
-		view.setMap(viewMap);
 	}
-	
+
 	private void turn(Player player, Direction dir)
 	{
 		player.setDirection(dir);
-		updateGameControllerMap();
-		ArrayList<ViewElement>[][] viewMap = uploadToView();
-		
-		view.setMap(viewMap);
 	}
-	
+
 	private void shoot(Player player, PortalColor color)
 	{
 		player.fire(color);
-		updateGameControllerMap();
-		ArrayList<ViewElement>[][] viewMap = uploadToView();
-		
-		view.setMap(viewMap);
 	}
-	
+
 	private void boxDown(Player player)
 	{
 		player.putBoxDown();
-		updateGameControllerMap();
-		ArrayList<ViewElement>[][] viewMap = uploadToView();
-		
-		view.setMap(viewMap);
 	}
-	
+
 	private void boxUp(Player player)
 	{
 		player.getBoxUp();
-		updateGameControllerMap();
-		ArrayList<ViewElement>[][] viewMap = uploadToView();
-		
-		view.setMap(viewMap);
 	}
-	
+
 	private void moveReplicator()
 	{
 		Model.getInstance().getReplicator().setDirection(Direction.getRandomDir());
 		Model.getInstance().getReplicator().step();
-		updateGameControllerMap();
-		ArrayList<ViewElement>[][] viewMap = uploadToView();
-		
-		view.setMap(viewMap);
 	}
-	
-	private void endProcess()
+
+	/**
+	 * updates global ZPM count for each player.
+	 * @param rZPMCount ZPM count of each player
+	 * <ul>
+	 * <li> 0 - colonel</li>
+	 * <li> 1 - jaffa </li>
+	 * </ul>
+	 * @param prevJaffaZpm the previous ZPM count of jaffa
+	 *  on the current map
+	 * @param prevColonelZpm the previous ZPM count of
+	 *  the colonel on the current map
+	 */
+	private void updateZPMCount( int[] rZPMCount, int prevColonelZpm, int prevJaffaZpm)
 	{
-		InitController.startColonelZPMs += Model.getInstance().getColonel().getZpmCount();
-		InitController.startJaffaZPMs += Model.getInstance().getJaffa().getZpmCount();
+		if( rZPMCount == null)
+			rZPMCount = new int[] {0, 0};
+
+		// update global ZPM counts
+		rZPMCount[0] += Model.getInstance().getColonel().getZpmCount() - prevColonelZpm;
+		rZPMCount[1] += Model.getInstance().getJaffa().getZpmCount() - prevJaffaZpm;
+
+		// update previous values of ZPM's on the current map
+		prevColonelZpm = Model.getInstance().getColonel().getZpmCount();
+		prevJaffaZpm = Model.getInstance().getJaffa().getZpmCount();
+
+		this.view.setColonelZPMDisplayed(rZPMCount[0]);
+		this.view.setJaffaZPMDisplayed(rZPMCount[1]);
+	}
+
+	@Override
+	public void propertyChange(PropertyChangeEvent evt) {
+		// update whole map
+		if(evt.getPropertyName().equals("error"))
+		{
+			updateGameControllerMap();
+			ArrayList<ViewElement>[][] viewMap = uploadToView();
+			view.setMap(viewMap);
+
+			return;
+		}
+
+		// TODO coord is wrong (122 for me) for the second map
+		// indexOutOfBoundsException
+
+		// update only the changed fields
+		int coord = (int)evt.getNewValue();
+		System.out.println(coord);
+		int xCoord = coord / map[0].length;
+		int yCoord = coord % map[0].length;
+		Field changedField = (Field)evt.getOldValue();
+		ArrayList<ViewElement> fieldView = new ArrayList<>();
+
+		for(int i = 0; i < changedField.getElementNum(); i++)
+		{
+			fieldView.add(Controller.getViewOf(changedField.getElement(i)));
+		}
+
+		view.setElement(yCoord, xCoord, fieldView);
 	}
-	
+
 	@SuppressWarnings("unchecked")
 	private void updateGameControllerMap()
 	{
@@ -287,7 +337,7 @@ public class GameController {
 			tmp = Model.class.getDeclaredField("map");
 			tmp.setAccessible(true);
 			ArrayList<Field> tmpMap = (ArrayList<Field>)tmp.get(Model.getInstance());
-	
+
 			int rowLength = map[0].length;
 			int size = map.length * map[0].length;
 			for(int i = 0; i < size; i++)
@@ -304,7 +354,7 @@ public class GameController {
 			// omg
 		}
 	}
-	
+
 	@SuppressWarnings("unchecked")
 	private ArrayList<ViewElement>[][] uploadToView()
 	{
@@ -328,5 +378,5 @@ public class GameController {
 		}
 
 		return mapView;
-	} 
+	}
 }
diff --git a/core/app/InitController.java b/core/app/InitController.java
index 5be97e9..dd862ef 100644
--- a/core/app/InitController.java
+++ b/core/app/InitController.java
@@ -514,7 +514,7 @@ public class InitController {
 							if(map[x][y].get(i) instanceof Portal)
 							{
 								Portal tmp = (Portal)map[x][y].get(i);
-								if(tmp.side() == convertToDir(params.get(4)))
+								if(tmp.getSide() == convertToDir(params.get(4)))
 								{
 									return false;
 								}
@@ -556,11 +556,11 @@ public class InitController {
 							tmpNew.setDirection(convertToDir(params.get(4)));
 							if(tmpPair != null)
 							{
-								tmpPair.setOtherSide(tmpNew);
 								tmpNew.setOtherSide(tmpPair);
 							}
 							map[x][y].add(tmpNew);
-							((Wall)map[x][y].get(hasWall)).meet(new Bullet(null, convertToColor(params.get(3)), convertToInverse(convertToDir(params.get(4)))));
+							((Wall)map[x][y].get(hasWall)).meet(
+									new Bullet(null, convertToColor(params.get(3)), Direction.convertToInverse(convertToDir(params.get(4)))));
 						}
 					}
 				}
@@ -948,17 +948,4 @@ public class InitController {
 		default: throw new InvalidParameterFormatException();
 		}
 	}
-
-	// TODO: belerakni Directionbe
-	private static Direction convertToInverse(Direction dir)
-	{
-		switch(dir)
-		{
-		case UP: return Direction.DOWN;
-		case DOWN: return Direction.UP;
-		case RIGHT: return Direction.LEFT;
-		case LEFT: return Direction.RIGHT;
-		default: return null;
-		}
-	}
 }
\ No newline at end of file
diff --git a/core/game/Direction.java b/core/game/Direction.java
index 24a3b47..286cb15 100644
--- a/core/game/Direction.java
+++ b/core/game/Direction.java
@@ -23,6 +23,18 @@ public enum Direction {
 		default: return UP;
 		}
 	}
+	
+	public static Direction convertToInverse(Direction dir)
+	{
+		switch(dir)
+		{
+		case UP: return Direction.DOWN;
+		case DOWN: return Direction.UP;
+		case RIGHT: return Direction.LEFT;
+		case LEFT: return Direction.RIGHT;
+		default: return null;
+		}
+	}
 
 	@Override
 	public String toString()
diff --git a/core/game/Model.java b/core/game/Model.java
index 6bc7b33..21f622f 100644
--- a/core/game/Model.java
+++ b/core/game/Model.java
@@ -1,5 +1,8 @@
 package game;
 
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
 import java.util.ArrayList;
 import java.util.Random;
 
@@ -10,8 +13,10 @@ import mapobjs.defobjs.ZPM;
 import mapobjs.movobjs.Player;
 import mapobjs.movobjs.Replicator;
 
-public class Model
+public class Model implements PropertyChangeListener
 {
+	private final PropertyChangeSupport propSupp = new PropertyChangeSupport(this);
+
 	private ArrayList<Field> map = new ArrayList<Field>();
 	private Player colonel;
 	private Player jaffa;
@@ -19,7 +24,6 @@ public class Model
 	private Door specDoor;
 	private int specOpen = 1;
 	private Replicator replicator;
-	//private Gate mainGate;
 	private boolean isMapFinished = false;
 
 	public void setSpecDoor(Door specDoor) {
@@ -37,7 +41,22 @@ public class Model
 	        }
 	    }
 	    return instance;
+	}
 
+	public void addPropertyChangeListener(PropertyChangeListener listener)
+	{
+		if(listener != null)
+		{
+			propSupp.addPropertyChangeListener(listener);
+		}
+	}
+	
+	public void removePropertyChangeListener(PropertyChangeListener listener)
+	{
+		if(listener != null)
+		{
+			propSupp.removePropertyChangeListener(listener);
+		}
 	}
 
 	public void setColonel(Player colonel)
@@ -53,6 +72,7 @@ public class Model
 
 	public void addMapElement(Field field)
 	{
+		field.addProperyChangeListener(this);
 		map.add(field);
 	}
 
@@ -79,9 +99,10 @@ public class Model
 			}
 		}
 	}
-	
+
 	public void restartMap()
 	{
+		map = new ArrayList<>();
 		isMapFinished = false;
 	}
 
@@ -93,7 +114,7 @@ public class Model
 			sum += colonel.getZpmCount();
 		if(jaffa != null)
 			sum += jaffa.getZpmCount();
-		
+
 		if(specDoor != null)
 		{
 			if(sum >= specOpen)
@@ -101,11 +122,11 @@ public class Model
 				specDoor.setOpen(true);
 			}
 		}
-		
+
 		if(sum % 2 == 0)
 		{
 			ArrayList<Field> options = new ArrayList<>();
-			
+
 			for(int i = 0; i < map.size(); i++)
 			{
 				if(!map.get(i).hasElementOn())
@@ -115,10 +136,10 @@ public class Model
 			}
 			if(options.isEmpty())
 				return;
-			
+
 			Random rnd = new Random();
 			int rndNum = rnd.nextInt(options.size());
-			
+
 			Field tmp = options.get(rndNum);
 			tmp.addElement(new ZPM(tmp));
 			this.ZPMs++;
@@ -129,14 +150,29 @@ public class Model
 	{
 		int i = 0;
 		boolean found = false;
-		while(i<map.size() && found==false)
+		while(i<map.size() && !found)
 		{
-			if(map.get(i).leave(portal)==true) found=true;
+			if(map.get(i).leave(portal)) found=true;
 			i++;
 		}
 		return true;
 	}
 
+	public boolean openWormhole(Portal portal)
+	{
+		int i = 0;
+		while(i<map.size())
+		{
+			if(map.get(i).openWormhole(portal))
+			{
+				return true;
+			}
+			i++;
+		}
+
+		return false;
+	}
+
 	public void setSpecOpenNum(int num)
 	{
 		this.specOpen = num;
@@ -158,10 +194,6 @@ public class Model
 		return replicator;
 	}
 
-	/*public void setMainGate(Gate mainGate) {
-		this.mainGate = mainGate;
-	}*/
-
 	public int getSpecOpen()
 	{
 		return this.specOpen;
@@ -170,14 +202,35 @@ public class Model
 	public int getZPMs() {
 		return ZPMs;
 	}
-	
+
 	public void setZPMs(int zpms)
 	{
 		this.ZPMs = zpms;
 	}
-	
+
 	public boolean isMapFinished()
 	{
 		return this.isMapFinished;
 	}
+
+	@Override
+	public void propertyChange(PropertyChangeEvent evt)
+	{
+		int place = findField((Field)evt.getNewValue());
+		if(place < 0 || place >= map.size())
+		{
+			//propSupp.firePropertyChange("error", null, null);
+			System.err.println("changed field not found");
+		}
+		else
+		{
+			propSupp.firePropertyChange("change", evt.getNewValue(), place);
+		}
+	}
+
+	private int findField(Field field)
+	{
+		return map.indexOf(field);
+
+	}
 }
\ No newline at end of file
-- 
GitLab