home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / enxle1f6 / src / games / battle / shared / comm / turndiff.java < prev    next >
Encoding:
Java Source  |  1996-08-14  |  8.5 KB  |  322 lines

  1. /*
  2.  * @(#)TurnDiff.java
  3.  */
  4. package games.Battle.shared.comm;
  5.  
  6. import java.util.*;
  7.  
  8. import games.Battle.shared.sys.*;
  9.  
  10. /**
  11.  * A TurnDiff is a delta of the game board sent to every player on every 
  12.  * "iteration" of the game. It only contains the differences in the game
  13.  * board that are the result of this turn to help keep transmission costs
  14.  * to a minimum.
  15.  *
  16.  * @version 1.00 02/02/96
  17.  * @author Jay Steele
  18.  * @author Alex Nicolaou
  19.  */
  20.  
  21. public class TurnDiff extends BattlePacket {
  22.     /**
  23.      * the board.
  24.      */
  25.     protected Board board;
  26.  
  27.     /**
  28.      * the player whose point of view this turndiff is from.
  29.      */
  30.     protected int player;
  31.  
  32.     /** 
  33.      * a tag for encoding a special additional message with the turn. used
  34.      * to indicate GAME OVER.
  35.      */
  36.     byte tag;
  37.  
  38.     /**
  39.      * NORMAL is the usual tag placed on a turndiff.
  40.      */
  41.     public static final byte NORMAL = 0x00;
  42.     /**
  43.      * GAMEOVER is the used to say hasta la vista, baby.
  44.      */
  45.     public static final byte GAMEOVER = 0x01;
  46.  
  47.     /**
  48.      * The most cells that can be run length encoded into one run.
  49.      */
  50.     static final int MAX_RUN = 16;
  51.     /**
  52.      * The amount of space we have to encode the TurnDiff.
  53.      */
  54.     static final int MAX_INDEX = Rules.rows * Rules.cols;
  55.  
  56.  
  57.     /**
  58.      * Constructor which indicates which game board this TurnDiff is
  59.      * going to be reading/writing to, and which player in the game
  60.      * the diff is being constructed for.
  61.      * @param board the board the turn diff is representing
  62.      * @param the player the turn diff is representing
  63.      */
  64.     public TurnDiff(Board board, int player) {
  65.         this.board = board;
  66.         this.player = player;
  67.         this.tag = NORMAL;
  68.     }
  69.     /**
  70.      * Constructor which indicates which game board this TurnDiff is
  71.      * going to be reading/writing to, and which player in the game
  72.      * the diff is being constructed for. Also takes a tag, so that
  73.      * the server can indicate game over.
  74.      * @param board the board the turn diff is representing
  75.      * @param player the player the turn diff is representing
  76.      * @param tag the tag for game over or not
  77.      */
  78.     public TurnDiff(Board board, int player, byte tag) {
  79.         this.board = board;
  80.         this.player = player;
  81.         this.tag = tag;
  82.     }
  83.  
  84.  
  85.     /**
  86.      * return the tag associated with this turn diff.
  87.      */
  88.     public final byte getTag() {
  89.         return tag;
  90.     }
  91.  
  92.     /**
  93.      * Run-length encodes a run of cells invisible to the player this
  94.      * turn diff is being constructed for.
  95.      * @param cells the array of Cells
  96.      * @param index the current index into cells
  97.      * @param result the vector of result, to which bytes will be added
  98.      */
  99.     int encodeInvisibleRun(Object[] cells, int index, Vector result) {
  100.         int i = 0;
  101.         while (true)
  102.         {
  103.             if (i+index >= MAX_INDEX) {
  104.                 break;
  105.             }
  106.             if (i >= MAX_RUN) {
  107.                 break;
  108.             }
  109.             Cell cell = (Cell)cells[i+index];
  110.             if (cell.isVisible(player)) {
  111.                 break;
  112.             }
  113.             i++;
  114.         }
  115.         int data = (int)Common.stuffOccupancyAndCount(Symbols.INVISIBLE, i-1);
  116.         result.addElement(new Integer(data));
  117.         return i;
  118.     }
  119.  
  120.     /**
  121.      * Run-length encodes a run of cells unmodified in the last turn.
  122.      * @param cells the array of Cells
  123.      * @param index the current index into cells
  124.      * @param result the vector of result, to which bytes will be added
  125.      */
  126.     int encodeUnmodifiedRun(Object[] cells, int index, Vector result) {
  127.         int i = 0;
  128.         while (true)
  129.         {
  130.             if (i+index >= MAX_INDEX) {
  131.                 break;
  132.             }
  133.             if (i >= MAX_RUN) {
  134.                 break;
  135.             }
  136.             Cell cell = (Cell)cells[i+index];
  137.             if (! cell.isVisible(player)) {
  138.                 break;
  139.             }
  140.             if (cell.isModified()) {
  141.                 break;
  142.             }
  143.             i++;
  144.         }
  145.         int data = (int)Common.stuffOccupancyAndCount(Symbols.UNMODIFIED, i-1);
  146.         result.addElement(new Integer(data));
  147.         return i;
  148.     }
  149.  
  150.     /**
  151.      * Run-length encodes a run of cells unoccupied in the last turn.
  152.      * @param cells the array of Cells
  153.      * @param index the current index into cells
  154.      * @param result the vector of result, to which bytes will be added
  155.      */
  156.     int encodeUnoccupiedRun(Object[] cells, int index, Vector result) {
  157.         int i = 0;
  158.         while (true)
  159.         {
  160.             if (i+index >= MAX_INDEX) {
  161.                 break;
  162.             }
  163.             if (i >= MAX_RUN) {
  164.                 break;
  165.             }
  166.             Cell cell = (Cell)cells[i+index];
  167.             if (cell.getOccupancy() != Symbols.UNOCCUPIED) {
  168.                 break;
  169.             }
  170.             if (! cell.isVisible(player)) {
  171.                 break;
  172.             }
  173.             i++;
  174.         }
  175.         int data = (int)Common.stuffOccupancyAndCount(Symbols.UNOCCUPIED, i-1);
  176.         result.addElement(new Integer(data));
  177.         return i;
  178.     }
  179.  
  180.     /**
  181.      * Encodes a cell occupied by a player in the last turn.
  182.      * @param cells the array of Cells
  183.      * @param index the current index into cells
  184.      * @param result the vector of result, to which bytes will be added
  185.      */
  186.     int encodePlayer(Object[] cells, int index, Vector result) {
  187.         Cell cell = (Cell)cells[index];
  188.         int occ = cell.getOccupancy();
  189.  
  190.         // Take troops in the range [0-MAX_SERVER_TROOPS] and convert
  191.         // to the range [0-MAX_CLIENT_TROOPS]
  192.         int troops = cell.getTroops();
  193.         float percent = troops / (float)Symbols.MAX_SERVER_TROOPS;
  194.         troops = (int)((float)Symbols.MAX_CLIENT_TROOPS * percent);
  195.         int pipes = cell.getPipeMask();
  196.         int data0 = (int)Common.stuffOccupancyAndTroops(occ, troops);
  197.         int data1 = (int)Common.stuffPipes(pipes);
  198.         result.addElement(new Integer(data0));
  199.         result.addElement(new Integer(data1));
  200.         return 1;
  201.     }
  202.  
  203.     /** 
  204.      * an array of bytes for the turn diff.
  205.      */
  206.     byte diffData[];
  207.     /**
  208.      * Produce an array of bytes representing the turn diff.
  209.      */
  210.     public void makeBytes() {
  211.         Vector result = new Vector();
  212.         Object[] data = board.getGrid().getData();
  213.  
  214.         boolean done = false;
  215.         int index = 0;
  216.         while (!done) {
  217.             Cell cell = (Cell)data[index];
  218.             if (! cell.isVisible(player))
  219.                 index = index + encodeInvisibleRun(data, index, result);
  220. /*
  221.             else if (! cell.isModified())
  222.                 index = index + encodeUnmodifiedRun(data, index, result);
  223. */
  224.             else if (cell.getOccupancy() == Symbols.UNOCCUPIED)
  225.                 index = index + encodeUnoccupiedRun(data, index, result);
  226.             else if (Common.isPlayer(cell.getOccupancy()))
  227.                 index = index + encodePlayer(data, index, result);
  228.             done = (index >= (Rules.rows * Rules.cols));
  229.         }
  230.  
  231.         // convert from the vector representation to the byte-array repr.
  232.         byte[] result_data = new byte[result.size()+1];
  233.         result_data[0] = tag;
  234.         for (int i=0; i<result.size(); i++) {
  235.             Integer ie = (Integer)result.elementAt(i);
  236.             result_data[i+1] = (byte)ie.intValue();
  237.         }
  238.  
  239.         diffData = result_data;
  240.     }
  241.  
  242.     /**
  243.      * return the bytes for the turn diff.
  244.      */
  245.     public byte[] toBytes() {
  246.         if (diffData == null)
  247.             makeBytes();
  248.         return diffData;
  249.     }
  250.  
  251.     /**
  252.      * Build a turn diff based on the data inside the given array of bytes
  253.      * @param array the array of bytes
  254.      */
  255.     public void fromBytes(byte[] array) {
  256.  
  257.         tag = array[0];
  258.  
  259.         Board cb = board;
  260.         Object[] data = cb.getGrid().getData();
  261.         int index = 0;
  262.  
  263.         for (int i=1; i<array.length; i++) {
  264.             byte b = array[i];
  265.             int occ = Common.extractOccupancy(b);
  266.             if (Common.isPlayer(occ)) {
  267.                 int troops = Common.extractTroops(b);
  268.                 b = array[++i];
  269.                 int pipes = Common.extractPipes(b);
  270.                 Cell cell = (Cell)data[index];
  271.                 cell.setOccupancy(occ);
  272.                 cell.setTroops(troops);
  273.                 cell.setPipes(pipes);
  274.                 // cell.update();
  275.                 index++;
  276.             } else {
  277.                 int count = Common.extractCount(b)+1;
  278.                 for (int j=index; j<index+count; j++) {
  279.                     Cell cell = (Cell)data[j];
  280.                     if (occ != Symbols.UNMODIFIED) {
  281.                         cell.setOccupancy(occ);
  282.                         // cell.update();
  283.                     }
  284.                 }
  285.                 index += count;
  286.             }
  287.         }
  288.     }
  289.  
  290.     /**
  291.      * Debugging output
  292.      */
  293.     public void asciiDump(byte[] array) {
  294.  
  295.         System.out.println("-- TurnDiff --");
  296.         for (int i=1; i<array.length; i++) {
  297.             byte b = array[i];
  298.             int occ = Common.extractOccupancy(b);
  299.             if (Common.isPlayer(occ)) {
  300.                 int troops = Common.extractTroops(b);
  301.                 b = array[++i];
  302.                 int pipes = Common.extractPipes(b);
  303.                 System.out.print("[");
  304.                 System.out.print(Symbols.occupancyString[occ]);
  305.                 System.out.print(" Troops="+troops);
  306.                 System.out.print(" Pipes=");
  307.                 if ((pipes & 0x08) != 0) System.out.print("1"); else System.out.print("0");
  308.                 if ((pipes & 0x04) != 0) System.out.print("1"); else System.out.print("0");
  309.                 if ((pipes & 0x02) != 0) System.out.print("1"); else System.out.print("0");
  310.                 if ((pipes & 0x01) != 0) System.out.print("1"); else System.out.print("0");
  311.                 System.out.println("]");
  312.             } else {
  313.                 int count = Common.extractCount(b)+1;
  314.                 System.out.print("[");
  315.                 System.out.print(Symbols.occupancyString[occ]);
  316.                 System.out.print(" Count="+count);
  317.                 System.out.println("]");
  318.             }
  319.         }
  320.     }
  321. }
  322.