package Base;
import java.util.HashMap;
import java.util.LinkedList;
import Shared.* ;
/**
* This class should hold your grid, and also contains a method that will
* start the game.
*
* <p><u>You need to work out this class. Do not change the signature
* of the constructor and methods below.</u>.
*
*/
public class IGrid {
INodeStatus[][] grid;
LinkedList<Team> teams;
int N;
int speed;
int maxhp;
int round;
IGridStatus status;
/**
* Just a trivial constructor that will not do any initialization.
*/
public IGrid() { }
/**
* This is your main constructor for creating a grid. Parameters that you need to
* support are listed below.
*
* @param N Specify the grid's dimension (NxN).
*
* @param speed Specify the rider's speed. This is an integer in the range of 0..10,
* with 0 being the slowest and 10 the fastest. Low speed is useful for testing.
*
* @param maxhp Specify the riders' initial hit points. All riders have the same number
* of initial hit points.
*
* @param round Specify the maximum number of scanning-rounds. The game ends when
* this number is reached.
*
* <p><u>Implement this constructor</u>
*/
public IGrid(int N, int speed, int maxhp, int round) {
this.N = N;
this.speed = speed;
this.maxhp = maxhp;
this.round = round;
status = new IGridStatus();
// Initialize the grid
grid = new INodeStatus[N][N];
for(int x = 0; x<N; x++)
for(int y = 0; y<N; y++){
grid[x][y] = new INodeStatus(x, y, null, -1);
}
// Updating IGridStatus
status.freeNodes = N*N;
status.gameHasEnded = false;
status.numRemainingRounds = round;
status.takenNodes = 0;
status.numOfRemainingRiders = 0;
status.teamNames = new HashMap<Integer, String>();
teams = new LinkedList<Team>();
}
/**
* This is used to add a team to the grid. The team is assumed to already
* contain all the riders belonging to the team. For each rider in the team
* this method should assign to it a fresh instance of IRiderExecutor. Every
* rider will have an attribute to hold a pointer to such an executor.
*
* @param t The team to add.
* @return The team-number. This number is assigned your game engine.
*
* <p><u>Implement this method</u>
*/
public int addTeam(Team t) {
if(t==null)
throw new UnsupportedOperationException() ;
// Giving each rider their RiderExecutor
for(Rider r: t.riders){
r.ra = new YourRiderExecutor(this);
}
teams.add(t);
int teamID = teams.size();
this.placeRiders(teamID, t.riders);
// Updating IGridStatus
status.numOfRemainingRiders+=t.riders.length;
status.teamNames.put(teamID, t.name);
return teams.size();
}
/**
* This will start the game. This will start all riders that participate
* in the game, and also the game-daemon.
*
* <p>Make it so that the game can only be started once.
* In other words, calling this method once, all subsequent calls to it
* will just do nothing.
*
* <p><u>Implement this method</u>
*/
public void start() {
//for(int i = 0; i<2000; i++)
this.startRiders();
}
/**
* Will start the run methods of the placed riders
*/
private void startRiders() {
for(Team team: teams)
for(Rider r: team.riders){
Thread t = new Thread(r);
t.start();
}
}
/**
* Will place a rider of each team on an unoccupied node
* @param riders
* @param teamID
*/
private void placeRiders(int teamID, Rider[] riders) {
for(Rider r: riders)
this.placeRider(teamID, r.ra.status());
}
/**
* Will place a single rider on an unoccupied node on the grid
* @param teamID
*/
public synchronized void placeRider(int teamID, IRiderStatus status) {
// TODO: Plaatst nu nog een rider op eerst gevonden vrije node, dit aanpasssen dus
for(int x = N/3-2 /*+ (int)(Math.random()*10)*/; x<N; x++)
for(int y = N/3-2 /*+ (int)(Math.random()*10)*/; y<N; y++){
// Check to see if free
if(grid[x][y].wall==null && grid[x][y].teamID<0){
status.x = x;
status.y = y;
// Placing rider on the grid
this.updateNodeStatus(grid[x][y], teamID, IDirection.NEUTRAL);
return;
}
}
}
/**
* Returns the dimension of the grid
*/
public int getDimension() {
return N;
}
public INodeStatus getNodeStatus(int x, int y)
{
return grid[x][y];
}
/**
* Will update the status of a node
* @param nodeStatus
* @param teamID
* @param wall
*/
public synchronized void updateNodeStatus(INodeStatus nodeStatus, int teamID,
IDirection wall) {
synchronized(nodeStatus)
{
nodeStatus.teamID = teamID;
nodeStatus.wall = wall;
}
}
/**
*
*/
public IGridStatus getGridStatus(){
return this.status;
}
public synchronized IGridStatus updateGridStatus(){
int nrNodesLeft = 0, nrNodesTaken = 0;
for(int x = 0; x<N; x++)
for(int y = 0; y<N; y++){
if(grid[x][y].wall==null)
nrNodesLeft++;
else
nrNodesTaken++;
}
status.freeNodes = nrNodesLeft;
status.takenNodes = nrNodesTaken;
status.numRemainingRounds--;
if(status.numOfRemainingRiders == 1 || this.getTeamsAlive() == 1)
status.gameHasEnded = true;
return status;
}
private int getTeamsAlive() {
int teamsalive = 0;
for (Team t : this.teams)
{
for(Rider r : t.riders)
{
//System.out.println(r.ra.status().hp);
if (r.ra.status().isAlive())
{
teamsalive++;
break;
}
}
}
return teamsalive;
}
}