net.windward.Acquire.Framework.java Source code

Java tutorial

Introduction

Here is the source code for net.windward.Acquire.Framework.java

Source

/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE"
 * As long as you retain this notice you can do whatever you want with this
 * stuff. If you meet an employee from Windward some day, and you think this
 * stuff is worth it, you can buy them a beer in return. Windward Studios
 * ----------------------------------------------------------------------------
 */

package net.windward.Acquire;

import net.windward.Acquire.AI.MyPlayerBrain;

import net.windward.Acquire.AI.PlayerMerge;
import net.windward.Acquire.AI.PlayerPlayTile;
import net.windward.Acquire.AI.PlayerTurn;
import net.windward.Acquire.Units.GameMap;
import net.windward.Acquire.Units.HotelChain;
import net.windward.Acquire.Units.HotelStock;
import net.windward.Acquire.Units.Player;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;

import org.apache.log4j.*;

public class Framework implements IPlayerCallback {
    private TcpClient tcpClient;
    private MyPlayerBrain brain;
    private String ipAddress = "127.0.0.1";
    //private String ipAddress = "128.61.36.167";
    //private String ipAddress = "143.215.120.56";

    private String myGuid;

    private static Logger log = Logger.getLogger(IPlayerCallback.class);

    /**
     * Run the A.I. player. All parameters are optional.
     *
     * @param args I.P. address of server, name
     */
    public static void main(String[] args) throws IOException {
        if (log.isInfoEnabled())
            log.info("***** Acquire II starting *****");

        Framework framework = new Framework(Arrays.asList(args));
        framework.Run();
    }

    private Framework(java.util.List<String> args) {
        brain = new MyPlayerBrain(args.size() >= 2 ? args.get(1) : null);
        if (args.size() >= 1) {
            ipAddress = args.get(0);
        }
        String msg = String.format("Connecting to server %1$s for user: %2$s", ipAddress, brain.getName());
        if (log.isInfoEnabled())
            log.info(msg);
        System.out.println(msg);
    }

    private void Run() throws IOException {
        System.out.println("starting...");

        tcpClient = new TcpClient(this, ipAddress);
        tcpClient.Start();
        ConnectToServer();

        // It's all messages to us now.
        System.out.println("enter \"exit\" to exit program");
        while (true) {
            try {
                BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
                String line = in.readLine();
                if (line.equals("exit")) {
                    System.out.println("Exiting program...");
                    tcpClient.abort();
                    break;
                }
            } catch (Exception e) {
                System.out.println("ERROR restarting app (Exception: " + e.getMessage() + " )");
                log.error("restarting run(), Exception: " + e.getMessage());
            }

        }
    }

    public final void StatusMessage(String message) {
        System.out.println(message);
    }

    public final void IncomingMessage(String message) throws DocumentException, IOException {

        try {
            long startTime = System.currentTimeMillis();
            // get the xml - we assume we always get a valid message from the server.
            SAXReader reader = new SAXReader();
            Document xml = reader.read(new StringReader(message));

            String rootName = xml.getRootElement().getName();

            if (rootName.equals("setup")) {
                System.out.println("Received setup message");
                if (log.isInfoEnabled())
                    log.info("Recieved setup message");

                myGuid = xml.getRootElement().attribute("my-guid").getValue();
                Element elemMap = xml.getRootElement().element("map");
                GameMap map = new GameMap(Integer.parseInt(elemMap.attribute("width").getValue()),
                        Integer.parseInt(elemMap.attribute("height").getValue()));

                DataObjects dataSetup = xmlToData(xml);

                brain.Setup(map, dataSetup.me, dataSetup.hotels, dataSetup.players);

                // say ready
                Document docSetup = DocumentHelper.createDocument();
                Element elem = DocumentHelper.createElement("ready");
                docSetup.add(elem);
                tcpClient.SendMessage(docSetup.asXML());
            }

            else if (rootName.equals("query-card")) {
                DataObjects dataQuery = xmlToData(xml);
                int card = brain.QuerySpecialPowerBeforeTurn(dataQuery.map, dataQuery.me, dataQuery.hotels,
                        dataQuery.players);

                // send the selected card back
                Document docQueryCard = DocumentHelper.createDocument();
                Element elem = DocumentHelper.createElement("reply");
                docQueryCard.add(elem);
                elem.add(DocumentHelper.createAttribute(elem, "cmd", "query-card"));
                elem.add(DocumentHelper.createAttribute(elem, "msg-id",
                        xml.getRootElement().attribute("msg-id").getValue()));
                elem.add(DocumentHelper.createAttribute(elem, "card", "" + card));
                tcpClient.SendMessage(docQueryCard.asXML());
            }

            else if (rootName.equals("query-tile")) {
                DataObjects dataQueryTile = xmlToData(xml);
                PlayerPlayTile playTile = brain.QueryTileOnly(dataQueryTile.map, dataQueryTile.me,
                        dataQueryTile.hotels, dataQueryTile.players);

                // send the selected tile back
                Document docQueryCard = DocumentHelper.createDocument();
                Element elem = DocumentHelper.createElement("reply");
                docQueryCard.add(elem);
                elem.add(DocumentHelper.createAttribute(elem, "cmd", "query-tile"));
                elem.add(DocumentHelper.createAttribute(elem, "msg-id",
                        xml.getRootElement().attribute("msg-id").getValue()));

                if (playTile != null) {
                    if (playTile.tile != null) {
                        elem.add(DocumentHelper.createAttribute(elem, "tile-x", "" + playTile.tile.getX()));
                        elem.add(DocumentHelper.createAttribute(elem, "tile-y", "" + playTile.tile.getY()));
                    }
                    if (playTile.createdHotel != null) {
                        elem.add(DocumentHelper.createAttribute(elem, "created-hotel",
                                playTile.createdHotel.getName()));
                    }
                    if (playTile.mergeSurvivor != null) {
                        elem.add(DocumentHelper.createAttribute(elem, "merge-survivor",
                                playTile.mergeSurvivor.getName()));
                    }
                }
                tcpClient.SendMessage(docQueryCard.asXML());
            }

            else if (rootName.equals("query-tile-purchase")) {
                DataObjects dataQueryTilePur = xmlToData(xml);
                PlayerTurn playTurn = brain.QueryTileAndPurchase(dataQueryTilePur.map, dataQueryTilePur.me,
                        dataQueryTilePur.hotels, dataQueryTilePur.players);

                // send the selected card back
                Document docQueryCard = DocumentHelper.createDocument();
                Element elem = DocumentHelper.createElement("reply");
                docQueryCard.add(elem);
                elem.add(DocumentHelper.createAttribute(elem, "cmd", "query-tile-purchase"));
                elem.add(DocumentHelper.createAttribute(elem, "msg-id",
                        xml.getRootElement().attribute("msg-id").getValue()));

                if (playTurn != null) {
                    elem.add(DocumentHelper.createAttribute(elem, "card", "" + playTurn.getCard()));
                    if (playTurn.tile != null) {
                        elem.add(DocumentHelper.createAttribute(elem, "tile-x", "" + playTurn.tile.getX()));
                        elem.add(DocumentHelper.createAttribute(elem, "tile-y", "" + playTurn.tile.getY()));
                    }
                    if (playTurn.createdHotel != null) {
                        elem.add(DocumentHelper.createAttribute(elem, "created-hotel",
                                playTurn.createdHotel.getName()));
                    }
                    if (playTurn.mergeSurvivor != null) {
                        elem.add(DocumentHelper.createAttribute(elem, "merge-survivor",
                                playTurn.mergeSurvivor.getName()));
                    }
                    if (playTurn.getBuy() != null && playTurn.getBuy().size() > 0) {
                        StringBuilder buyStock = new StringBuilder();
                        for (HotelStock stock : playTurn.getBuy())
                            buyStock.append(stock.getChain().getName() + ':' + stock.getNumShares() + ';');
                        elem.add(DocumentHelper.createAttribute(elem, "buy", buyStock.toString()));
                    }
                    if (playTurn.getTrade() != null && playTurn.getTrade().size() > 0) {
                        StringBuilder tradeStock = new StringBuilder();
                        for (PlayerTurn.TradeStock trade : playTurn.getTrade())
                            tradeStock
                                    .append(trade.getTradeIn2().getName() + ':' + trade.getGet1().getName() + ';');
                        elem.add(DocumentHelper.createAttribute(elem, "trade", tradeStock.toString()));
                    }
                }
                tcpClient.SendMessage(docQueryCard.asXML());
            }

            else if (rootName.equals("query-merge")) {
                DataObjects dataQueryMerge = xmlToData(xml);

                HotelChain survivor = null;
                for (HotelChain hotel : dataQueryMerge.hotels)
                    if (hotel.getName().equals(xml.getRootElement().attribute("survivor").getValue())) {
                        survivor = hotel;
                        break;
                    }
                HotelChain defunct = null;
                for (HotelChain hotel : dataQueryMerge.hotels)
                    if (hotel.getName().equals(xml.getRootElement().attribute("defunct").getValue())) {
                        defunct = hotel;
                        break;
                    }

                PlayerMerge merge = brain.QueryMergeStock(dataQueryMerge.map, dataQueryMerge.me,
                        dataQueryMerge.hotels, dataQueryMerge.players, survivor, defunct);

                // send the selected card back
                Document docQueryMerge = DocumentHelper.createDocument();
                Element elem = DocumentHelper.createElement("reply");
                docQueryMerge.add(elem);
                elem.add(DocumentHelper.createAttribute(elem, "cmd", "query-card"));
                elem.add(DocumentHelper.createAttribute(elem, "msg-id",
                        xml.getRootElement().attribute("msg-id").getValue()));
                if (merge != null) {
                    elem.add(DocumentHelper.createAttribute(elem, "keep", "" + merge.getKeep()));
                    elem.add(DocumentHelper.createAttribute(elem, "sell", "" + merge.getSell()));
                    elem.add(DocumentHelper.createAttribute(elem, "trade", "" + merge.getTrade()));
                }
                tcpClient.SendMessage(docQueryMerge.asXML());
            }

            else if (xml.getRootElement().getName().equals("exit")) {
                System.out.println("Received exit message");
                if (log.isInfoEnabled()) {
                    log.info("Received exit message");
                }
                System.exit(0);

            } else {
                String msg = String.format("ERROR: bad message (XML) from server - root node %1$s",
                        xml.getRootElement().getName());
                log.warn(msg);
                //Trace.WriteLine(msg);
            }

            long turnTime = System.currentTimeMillis() - startTime;
            if (turnTime > 800) {
                System.out.println("WARNING - turn took " + turnTime / 1000 + " seconds");

            }
        } catch (RuntimeException ex) {
            System.out.println(String.format("Error on incoming message. Exception: %1$s", ex));
            ex.printStackTrace();
            log.error("Error on incoming message.", ex);
        }
    }

    private class DataObjects {
        public GameMap map;
        public ArrayList<Player> players;
        public Player me;
        public ArrayList<HotelChain> hotels;
    }

    private DataObjects xmlToData(Document xml) {

        DataObjects rtn = new DataObjects();
        rtn.players = Player.fromXml(xml.getRootElement().element("players"));
        rtn.hotels = HotelChain.fromXml(xml.getRootElement().element("hotels"));
        for (Player plyrOn : rtn.players)
            if (plyrOn.getGuid().equals(myGuid)) {
                rtn.me = plyrOn;
                break;
            }
        rtn.map = GameMap.fromXml(xml.getRootElement().element("map"), rtn.hotels);

        // now the ones that point to each other
        Player.readStockForPlayers(xml.getRootElement().element("players"), rtn.players, rtn.hotels);
        HotelChain.readOwnersForChains(xml.getRootElement().element("hotels"), rtn.hotels, rtn.players);
        return rtn;

    }

    public final void ConnectionLost(Exception ex) throws IOException, InterruptedException {

        System.out.println("Lost our connection! Exception: " + ex.getMessage());

        int delay = 500;
        while (true) {
            try {
                if (tcpClient != null) {
                    tcpClient.Close();
                }
                tcpClient = new TcpClient(this, ipAddress);
                tcpClient.Start();

                ConnectToServer();
                System.out.println("Re-connected");

                return;
            } catch (RuntimeException e) {

                System.out.println("Re-connection fails! Exception: " + e.getMessage());
                Thread.sleep(delay);
                delay += 500;
            }
        }
    }

    private void ConnectToServer() throws IOException {
        try {
            Document doc = DocumentHelper.createDocument();
            Element root = DocumentHelper.createElement("join");
            root.addAttribute("name", brain.getName());
            root.addAttribute("school", MyPlayerBrain.SCHOOL);
            root.addAttribute("language", "Java");

            byte[] data = brain.getAvatar();
            if (data != null) {
                Element avatarElement = DocumentHelper.createElement("avatar");
                BASE64Encoder encoder = new BASE64Encoder();
                avatarElement.setText(encoder.encode(data));
                root.add(avatarElement);
            }

            doc.add(root);

            tcpClient.SendMessage(doc.asXML());
        } catch (Exception e) {
            log.warn("ConnectToServer() threw Exception: " + e.getMessage());
        }
    }
}