package Engine;
import java.util.Random;
import Board.Board;
import Board.Enum_Land;
import Board.Square;
import Character.GameCharacter;
import Character.GCInstances.Bowman;
import Character.GCInstances.King;
import Character.GCInstances.Knight;
import Character.GCInstances.KnightBowman;
import Character.GCInstances.Magus;
import Character.GCInstances.Warrior;
import Character.Races.Race;
import Character.Races.RInstances.KingRace;
import IHM.MainFrame;
import IHM.Popup;
public class Engine {
Board board;
boolean J1turn;
Player J1, J2;
Random luck;
MainFrame display;
public Engine(Race j1, Race j2, MainFrame mainFrame) {
display = mainFrame;
board = new Board();
J1 = new Player(j1);
J2 = new Player(j2);
initCharacters(board, j1, j2);
J1turn = true;
J1.stackToken();
luck = new Random();
}
private void initCharacters(Board initBoard, Race raceJ1, Race raceJ2) {
// First player characters
initBoard.getCase(2, 0).setCharac(new Bowman(raceJ1, J1));
initBoard.getCase(3, 0).setCharac(new Bowman(raceJ1, J1));
initBoard.getCase(4, 0).setCharac(new Magus(raceJ1, J1));
initBoard.getCase(5, 0).setCharac(new Knight(raceJ1, J1));
initBoard.getCase(6, 0).setCharac(new King(new KingRace(), J1));
initBoard.getCase(7, 0).setCharac(new KnightBowman(raceJ1, J1));
initBoard.getCase(8, 0).setCharac(new Knight(raceJ1, J1));
initBoard.getCase(9, 0).setCharac(new Magus(raceJ1, J1));
initBoard.getCase(10, 0).setCharac(new Bowman(raceJ1, J1));
initBoard.getCase(11, 0).setCharac(new Bowman(raceJ1, J1));
// Second player characters
initBoard.getCase(2, Board.COLUMNS - 1).setCharac(
new Bowman(raceJ2, J2));
initBoard.getCase(3, Board.COLUMNS - 1).setCharac(
new Bowman(raceJ2, J2));
initBoard.getCase(4, Board.COLUMNS - 1)
.setCharac(new Magus(raceJ2, J2));
initBoard.getCase(5, Board.COLUMNS - 1).setCharac(
new Knight(raceJ2, J2));
initBoard.getCase(6, Board.COLUMNS - 1).setCharac(
new KnightBowman(raceJ2, J2));
initBoard.getCase(7, Board.COLUMNS - 1).setCharac(
new King(new KingRace(), J2));
initBoard.getCase(8, Board.COLUMNS - 1).setCharac(
new Knight(raceJ2, J2));
initBoard.getCase(9, Board.COLUMNS - 1)
.setCharac(new Magus(raceJ2, J2));
initBoard.getCase(10, Board.COLUMNS - 1).setCharac(
new Bowman(raceJ2, J2));
initBoard.getCase(11, Board.COLUMNS - 1).setCharac(
new Bowman(raceJ2, J2));
// Colums of wariors
for (int i = 2; i < 12; i++) {
initBoard.getCase(i, 1).setCharac(new Warrior(raceJ1, J1));
initBoard.getCase(i, Board.COLUMNS - 2).setCharac(
new Warrior(raceJ2, J2));
}
}
// 2 squares given, we have to test if there are Character in it and what
// they can do
public synchronized boolean action(Square source, Square target) {
if (source.getCharac() == null) { // No GameCharacter in the square,
// no
// action available
return false;
} else {
// If it's the turn of the player
if (myTurn(source.getCharac().getTeam())) {
// If the player has one or more action token
if (source.getCharac().getTeam().canPerformAction()) {
boolean validAction = false;
if (target.getCharac() == null) // If the destination is
// empty
validAction = move(source, target);
else {
// If there is a character on the destination
validAction = attack(source, target);
}
if (validAction) { // If action performed, use token
if (myTurn(J1)) {
J1.performedAction();
if (!J1.canPerformAction())
changeTurn();
} else if (myTurn(J2)) {
J2.performedAction();
if (!J2.canPerformAction())
changeTurn();
}
}
if (someoneWin() == J1) { // J1 won
endTheGame();
new Popup("Joueur 1 a gagn� !!!");
} else if (someoneWin() == J2) { // J2 won
endTheGame();
new Popup("Joueur 2 a gagn� !!!");
}
return validAction;
} else { // No more token, change turn
changeTurn();
return false;
}
}
}
// Not the turn of the player or no action token
return false;
}
public boolean myTurn(Player team) {
return (J1turn && (team.equals(J1))) || (!J1turn && (team.equals(J2)));
}
private boolean move(Square source, Square target) {
// If Character can go on target
if (!target.canAccross())
return false;
int orix = source.get_X();
int oriy = source.get_Y();
int destx = target.get_X();
int desty = target.get_Y();
// Distance between source and target are below stamina
if (Math.max(Math.abs(destx - orix), Math.abs(desty - oriy)) <= source
.getCharac().getStamina()) {
// Testing if the path is clear
/*
* if (!canMoveTo(source, target)) return false;
*/
// Changing bonuses given by the land on the square
source.getCharac().changebonusesFromLand(source.getLand(),
target.getLand());
// Moving character on the board
target.setCharac(source.getCharac());
source.setCharac(null);
return true;
} else
return false;
}
// Not working, return true
private boolean canMoveTo(Square source, Square target) {
int orix = source.get_X();
int oriy = source.get_Y();
int destx = target.get_X();
int desty = target.get_Y();
boolean canAccross = true;
// Target from left to source
for (int i = orix; i <= destx; i++) {
for (int j = oriy; j < desty; j++) {
if (orix > 0 && orix < Board.LINES - 1) {
canAccross &= board.getCase(i - 1, j).canAccross()
| board.getCase(i + 1, j).canAccross()
| board.getCase(i, j).canAccross();
} else if (orix == 0) {
canAccross &= board.getCase(i + 1, j).canAccross()
| board.getCase(i, j).canAccross();
} else if (orix == Board.LINES - 1) {
canAccross &= board.getCase(i - 1, j).canAccross()
| board.getCase(i + 1, j).canAccross();
}
}
}
// Target from right to source
for (int i = orix; i >= destx; i--) {
for (int j = oriy; j < oriy; j++) {
if (orix > 0 && orix < Board.LINES - 1) {
canAccross &= board.getCase(i - 1, j).canAccross()
| board.getCase(i + 1, j).canAccross()
| board.getCase(i, j).canAccross();
} else if (orix == 0) {
canAccross &= board.getCase(i + 1, j).canAccross()
| board.getCase(i, j).canAccross();
} else if (orix == Board.LINES - 1) {
canAccross &= board.getCase(i - 1, j).canAccross()
| board.getCase(i + 1, j).canAccross();
}
}
}
// Target from right to source
for (int i = orix; i <= destx; i--) {
for (int j = oriy; j < oriy; j++) {
if (orix > 0 && orix < Board.LINES - 1) {
canAccross &= board.getCase(i - 1, j).canAccross()
| board.getCase(i + 1, j).canAccross()
| board.getCase(i, j).canAccross();
} else if (orix == 0) {
canAccross &= board.getCase(i + 1, j).canAccross()
| board.getCase(i, j).canAccross();
} else if (orix == Board.LINES - 1) {
canAccross &= board.getCase(i - 1, j).canAccross()
| board.getCase(i + 1, j).canAccross();
}
}
}
return true;
}
private boolean attack(Square source, Square target) {
// If source and target are players from the same team, don't attack !
if (source.getCharac().getTeam().equals(target.getCharac().getTeam()))
return false;
// Case if the Character is on an oasis and can't attack
if (!source.getCharac().canAttack())
return false;
int orix = source.get_X();
int oriy = source.get_Y();
int destx = target.get_X();
int desty = target.get_Y();
// Distance between source and target are below range
if (Math.max(Math.abs(destx - orix), Math.abs(desty - oriy)) <= source
.getCharac().getRange()) {
// If defender killed, deleted from the board
if (dealDommages(source.getCharac(), target.getCharac())) {
target.setCharac(null);
}
return true;
} else
return false;
}
// Return true if the defender is killed, false instead
private boolean dealDommages(GameCharacter attacker, GameCharacter defender) {
int touche = luck.nextInt(101); // Generate a number between 0 and 100
if (touche < attacker.getAccuracy()) { // Attacker performs his attack
int crit = luck.nextInt(101);
int dommagesDeal;
if (crit < attacker.getCriticalChance()) { // Attacker performs a
// critic shot
dommagesDeal = defender.getDommages(2 * attacker.getStrength());
display.reportGameInfo(attacker.toString() + " attacked "
+ defender.toString()
+ " and made a critical strike dealing " + dommagesDeal
+ " of damages to him.");
} else { // Normal attack
dommagesDeal = defender.getDommages(attacker.getStrength());
display.reportGameInfo(attacker.toString() + " attacked "
+ defender.toString() + " and dealt " + dommagesDeal
+ " of damages to him.");
}
if (defender.isDead()) { // Use of heritage
attacker.bonusHeritage();
return true;
}
} else { // Attack missed
display.reportGameInfo(attacker.toString() + " attacked "
+ defender.toString() + " and missed his attack");
}
return false;
}
public void changeTurn() {
for (int i = 0; i < Board.LINES; i++)
for (int j = 0; j < Board.COLUMNS; j++) {
if (board.getCase(i, j).getCharac() != null) { // Bonus from
// Oasis
if (board.getCase(i, j).getLand() == Enum_Land.OASIS)
board.getCase(i, j).getCharac().heal(10);
else
// If a Character left an oasis and a turn has ended, he
// can attack now
board.getCase(i, j).getCharac().setAttack(true);
}
}
J1turn = !J1turn;
if (J1turn) {
J1.stackToken();
} else {
J2.stackToken();
}
}
private void endTheGame() {
for (int i = 0; i < Board.LINES; i++)
for (int j = 0; j < Board.COLUMNS; j++)
board.getCase(i, j).removeMouseListener(board.getCase(i, j));
}
private Player someoneWin() {
if (board.noKing(J1))
return J2;
if (board.noKing(J2))
return J1;
return null;
}
public Player getJ1() {
return J1;
}
public Player getJ2() {
return J2;
}
public Board getBoard() {
return board;
}
}