//Translates the PlayerModelProto.PlayerModel objects read from socket into BoardModel object
//One command line argument is needed: port number for server to listen on
package com.hearthattack;
import com.protos.*;
import com.hearthattack.*;
import com.hearthsim.model.*;
import com.hearthsim.card.Card;
import com.hearthsim.card.Deck;
import com.hearthsim.card.CharacterIndex;
import com.hearthsim.card.minion.Minion;
import com.hearthsim.card.minion.Hero;
import com.hearthsim.card.ImplementedCardList;
import com.hearthsim.card.weapon.WeaponCard;
import com.hearthsim.exception.HSException;
import com.hearthsim.card.basic.weapon.FieryWarAxe;
import com.hearthsim.card.minion.heroes.TestHero;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.atomic.AtomicBoolean;
import java.lang.Runnable;
import java.lang.Thread;
import java.io.IOException;
import java.lang.reflect.*;
public class Handler {
public static void main(String[] args) throws IOException, HSException {
boolean gameOver = false;
BoardModel currentBoard;
moveGen movegen = new moveGen(10);
Messenger message = new Messenger();
int turn;
PlayerModelProto.PlayerModel playerProto = PlayerModelProto.PlayerModel.getDefaultInstance();
PlayerModelProto.PlayerModel opponentProto = PlayerModelProto.PlayerModel.getDefaultInstance();
ImplementedCardList cardList = ImplementedCardList.getInstance();
AtomicBoolean update = new AtomicBoolean(false);
AtomicBoolean terminate = new AtomicBoolean(false);
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock read = rwLock.readLock();
//Open Reader in new thread
(new Thread(new Reader(playerProto, opponentProto, update, terminate, rwLock, Integer.parseInt(args[0])))).start();
while(!terminate.get()) {
System.out.println("Waiting for update");
while(!update.get()); //wait for Reader to parse from log file
System.out.println("Received update");
read.lock();
PlayerModel playerModel = makePlayerModel(cardList, playerProto);
PlayerModel opponentModel = makePlayerModel(cardList, opponentProto);
currentBoard = new BoardModel(playerModel, opponentModel);
for(int i=0,j=0; i<playerProto.getMinionsCount() || j<opponentProto.getMinionsCount(); ){
if(i>=playerProto.getMinionsCount()){
currentBoard.placeMinion(PlayerSide.WAITING_PLAYER, makeMinion(cardList,opponentProto.getMinions(j)),
CharacterIndex.fromInteger(j));
++j;
} else if(j>=opponentProto.getMinionsCount()){
currentBoard.placeMinion(PlayerSide.CURRENT_PLAYER, makeMinion(cardList,playerProto.getMinions(i)),
CharacterIndex.fromInteger(i));
++i;
} else if(playerProto.getMinions(i).getTurnPlayed() < opponentProto.getMinions(j).getTurnPlayed()){
currentBoard.placeMinion(PlayerSide.CURRENT_PLAYER, makeMinion(cardList,playerProto.getMinions(i)),
CharacterIndex.fromInteger(i));
++i;
} else{
currentBoard.placeMinion(PlayerSide.WAITING_PLAYER, makeMinion(cardList,opponentProto.getMinions(j)),
CharacterIndex.fromInteger(j));
++j;
}
}
turn = playerProto.getTurnNumber();
update.set(false);
read.unlock();
if(currentBoard.isDead(PlayerSide.CURRENT_PLAYER) || currentBoard.isDead(PlayerSide.WAITING_PLAYER)) {
terminate.set(true);
break;
}
message.send(movegen.getMoves(turn, currentBoard));
}
}
public static Card makeCard(ImplementedCardList cardList, CardProto.Card in){
Card out = new Card();
if(cardList.getCardForName(in.getName())!=null)
out = cardList.getCardForName(in.getName()).createCardInstance();
out.setInHand(in.getInHand());
out.hasBeenUsed(in.getHasBeenUsed());
return out;
}
public static Minion makeMinion(ImplementedCardList cardList, MinionProto.Minion in){
Minion out = new Minion();
try{
if(cardList.getCardForName(in.getCard().getName())!=null)
out = (Minion)cardList.getCardForName(in.getCard().getName()).cardClass_.getConstructor().newInstance();
}
catch (NoSuchMethodException e) {
System.out.println("NoSuchMethodException");
}
catch (InstantiationException e) {
System.out.println("InstantiationException");
}
catch (IllegalAccessException e) {
System.out.println("IllegalAccessException");
}
catch (InvocationTargetException e) {
System.out.println("InvocationTargetException");
}
out.setInHand(in.getCard().getInHand());
out.hasBeenUsed(in.getCard().getHasBeenUsed());
if(in.hasTaunt())
out.setTaunt(in.getTaunt());
if(in.hasDivineShield())
out.setDivineShield(in.getDivineShield());
if(in.hasWindfury())
out.setWindfury(in.getWindfury());
if(in.hasCharge())
out.setCharge(in.getCharge());
if(in.hasImmune())
out.setImmune(in.getImmune());
if(in.hasHasAttacked())
out.hasAttacked(in.getHasAttacked());
if(in.hasHasWindfuryAttacked())
out.hasWindFuryAttacked(in.getHasWindfuryAttacked());
if(in.hasFrozen())
out.setFrozen(in.getFrozen());
//setSilenced() setter function is protected in Minion class
if(in.hasStealthedUntilRevealed())
out.setStealthedUntilRevealed(in.getStealthedUntilRevealed());
if(in.hasStealthedUntilNextTurn())
out.setStealthedUntilNextTurn(in.getStealthedUntilNextTurn());
if(in.hasHeroTargetable())
out.setHeroTargetable(in.getHeroTargetable());
if(in.hasHealth())
out.setHealth((byte)in.getHealth());
out.setMaxHealth((byte)in.getMaxHealth());
if(in.hasAuraHealth())
out.setAuraHealth((byte)in.getAuraHealth());
if(in.hasAttack())
out.setAttack((byte)in.getAttack());
if(in.hasExtraAttackUntilTurnEnd())
out.setExtraAttackUntilTurnEnd((byte)in.getExtraAttackUntilTurnEnd());
if(in.hasAuraAttack())
out.setAuraAttack((byte)in.getAuraAttack());
if(in.hasDestroyOnTurnStart())
out.setDestroyOnTurnStart(in.getDestroyOnTurnStart());
if(in.hasDestroyOnTurnEnd())
out.setDestroyOnTurnEnd(in.getDestroyOnTurnEnd());
if(in.hasSpellDamage())
out.setSpellDamage((byte)in.getSpellDamage());
//CantAttack has no setter function in Minion class
//Tribe cannot be set for Minion Class, always retrieved from ImplementedCardList
return out;
}
public static WeaponCard makeWeapon(ImplementedCardList cardList, WeaponProto.Weapon in){
WeaponCard out = new FieryWarAxe();
try{
if(cardList.getCardForName(in.getName())!=null)
out = (WeaponCard)cardList.getCardForName(in.getName()).cardClass_.getConstructor().newInstance();
}
catch (NoSuchMethodException e) {
System.out.println("NoSuchMethodException");
}
catch (InstantiationException e) {
System.out.println("InstantiationException");
}
catch (IllegalAccessException e) {
System.out.println("IllegalAccessException");
}
catch (InvocationTargetException e) {
System.out.println("InvocationTargetException");
}
out.setInHand(false);
out.hasBeenUsed(true);
out.setWeaponDamage((byte)in.getAttack());
out.setWeaponCharge((byte)in.getDurability());
return out;
}
public static Hero makeHero(ImplementedCardList cardList, HeroProto.Hero in){
Hero out = new TestHero();
try{
if(cardList.getCardForName(in.getMinion().getCard().getName())!=null)
out = (Hero)cardList.getCardForName(in.getMinion().getCard().getName()).cardClass_.getConstructor().newInstance();
}
catch (NoSuchMethodException e) {
System.out.println("NoSuchMethodException");
}
catch (InstantiationException e) {
System.out.println("InstantiationException");
}
catch (IllegalAccessException e) {
System.out.println("IllegalAccessException");
}
catch (InvocationTargetException e) {
System.out.println("InvocationTargetException");
}
out.setInHand(in.getMinion().getCard().getInHand());
out.hasBeenUsed(in.getMinion().getCard().getHasBeenUsed());
out.setWeapon(makeWeapon(cardList,in.getWeapon()));
out.setArmor((byte)in.getArmor());
if(in.getMinion().hasTaunt())
out.setTaunt(in.getMinion().getTaunt());
if(in.getMinion().hasDivineShield())
out.setDivineShield(in.getMinion().getDivineShield());
if(in.getMinion().hasWindfury())
out.setWindfury(in.getMinion().getWindfury());
if(in.getMinion().hasCharge())
out.setCharge(in.getMinion().getCharge());
if(in.getMinion().hasImmune())
out.setImmune(in.getMinion().getImmune());
if(in.getMinion().hasHasAttacked())
out.hasAttacked(in.getMinion().getHasAttacked());
if(in.getMinion().hasHasWindfuryAttacked())
out.hasWindFuryAttacked(in.getMinion().getHasWindfuryAttacked());
if(in.getMinion().hasFrozen())
out.setFrozen(in.getMinion().getFrozen());
//setSilenced() setter function is protected in Minion class
if(in.getMinion().hasStealthedUntilRevealed())
out.setStealthedUntilRevealed(in.getMinion().getStealthedUntilRevealed());
if(in.getMinion().hasStealthedUntilNextTurn())
out.setStealthedUntilNextTurn(in.getMinion().getStealthedUntilNextTurn());
if(in.getMinion().hasHeroTargetable())
out.setHeroTargetable(in.getMinion().getHeroTargetable());
if(in.getMinion().hasHealth())
out.setHealth((byte)in.getMinion().getHealth());
out.setMaxHealth((byte)in.getMinion().getMaxHealth());
if(in.getMinion().hasAuraHealth())
out.setAuraHealth((byte)in.getMinion().getAuraHealth());
if(in.getMinion().hasAttack())
out.setAttack((byte)in.getMinion().getAttack());
if(in.getMinion().hasExtraAttackUntilTurnEnd())
out.setExtraAttackUntilTurnEnd((byte)in.getMinion().getExtraAttackUntilTurnEnd());
if(in.getMinion().hasAuraAttack())
out.setAuraAttack((byte)in.getMinion().getAuraAttack());
if(in.getMinion().hasDestroyOnTurnStart())
out.setDestroyOnTurnStart(in.getMinion().getDestroyOnTurnStart());
if(in.getMinion().hasDestroyOnTurnEnd())
out.setDestroyOnTurnEnd(in.getMinion().getDestroyOnTurnEnd());
if(in.getMinion().hasSpellDamage())
out.setSpellDamage((byte)in.getMinion().getSpellDamage());
//CantAttack has no setter function in Minion class
//Tribe cannot be set for Minion Class, always retrieved from ImplementedCardList
return out;
}
public static Deck makeDeck(ImplementedCardList cardList, DeckProto.Deck in){
Card[] cards = new Card[in.getCardsCount()];
for(int i=0; i<in.getCardsCount(); ++i)
cards[i] = makeCard(cardList,in.getCards(i));
Deck out = new Deck(cards);
return out;
}
public static HandModel makeHand(ImplementedCardList cardList, PlayerModelProto.PlayerModel player){
HandModel hand = new HandModel();
for(int i=0; i<player.getHandCount(); ++i)
hand.add(makeCard(cardList,player.getHand(i)));
return hand;
}
public static PlayerModel makePlayerModel(ImplementedCardList cardList, PlayerModelProto.PlayerModel in){
PlayerModel out = new PlayerModel((byte)in.getPlayerId(),in.getName(),makeHero(cardList,in.getHero()),makeDeck(cardList,in.getDeck()));
if(in.hasMana())
out.setMana((byte)in.getMana());
out.setMaxMana((byte)in.getMaxMana());
if(in.hasDeckPos())
out.setDeckPos((byte)in.getDeckPos());
if(in.hasFatigueDamage())
out.setFatigueDamage((byte)in.getFatigueDamage());
/* for(int i=0; i<in.getMinionsCount(); ++i){
for(int j=0; j<in.getMinionsCount(); ++j){
if(in.getMinions(j).getPosition() == i)
out.addMinion(i,makeMinion(cardList,in.getMinions(i)));
}
}*/
out.setHand(makeHand(cardList,in));
if(in.hasOverload())
out.setOverload((byte)in.getOverload());
if(in.hasNumCardsUsed())
out.setNumCardsUsed((byte)in.getNumCardsUsed());
return out;
}
}