📄 board.java
字号:
/* * MegaMek - Copyright (C) 2000,2001,2002,2003,2004 Ben Mazur (bmazur@sev.org) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */package megamek.common;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.Reader;import java.io.Serializable;import java.io.StreamTokenizer;import java.io.Writer;import java.util.Enumeration;import java.util.Vector;import megamek.common.event.BoardEvent;import megamek.common.event.BoardListener;import java.util.Hashtable;public class Board implements Serializable, IBoard { public static final String BOARD_REQUEST_ROTATION = "rotate:"; public static final int BOARD_MAX_WIDTH = Coords.MAX_BOARD_WIDTH; public static final int BOARD_MAX_HEIGHT = Coords.MAX_BOARD_HEIGHT; protected int width; protected int height; private IHex[] data; /** Building data structures. */ private Vector buildings = new Vector(); private transient Hashtable bldgByCoords = new Hashtable(); protected transient Vector boardListeners = new Vector(); /** * Record the infernos placed on the board. */ private Hashtable infernos = new Hashtable(); /** Option to turn have roads auto-exiting to pavement. */ private boolean roadsAutoExit = true; /** * Creates a new board with zero as its width and * height parameters. */ public Board() { this(0, 0); } /** * Creates a new board of the specified dimensions. * All hexes in the board will be null until otherwise * set. * * @param width the width dimension. * @param height the height dimension. */ public Board(int width, int height) { this.width = width; this.height = height; data = new IHex[width * height]; } /** * Creates a new board of the specified dimensions and specified * hex data. * * @param width the width dimension. * @param height the height dimension. * @param data */ public Board(int width, int height, IHex[] data) { this.width = width; this.height = height; this.data = new IHex[width * height]; for(int y=0; y<height; y++) { for(int x=0; x<width; x++) { this.data[y*width+x] = data[y*width+x]; } } } /** * Creates a new board of the specified dimensions, hexes, buildings, * and inferno trackers. Do *not* use this method unless you have * carefully examined this class. * * @param width The <code>int</code> width dimension in hexes. * @param height The <code>int</code> height dimension in hexes. * @param hexes The array of <code>Hex</code>es for this board. * This object is used directly without being copied. * This value should only be <code>null</code> if * either <code>width</code> or <code>height</code> is * zero. * @param bldgs The <code>Vector</code> of <code>Building</code>s * for this board. This object is used directly without * being copied. * @param infMap The <code>Hashtable</code> that map <code>Coords</code> * to <code>InfernoTracker</code>s for this board. This * object is used directly without being copied. */ public Board( int width, int height, IHex[] hexes, Vector bldgs, Hashtable infMap ) { this.width = width; this.height = height; data = hexes; buildings = bldgs; infernos = infMap; createBldgByCoords(); } /* (non-Javadoc) * @see megamek.common.IBoard#getHeight() */ public int getHeight() { return height; } /* (non-Javadoc) * @see megamek.common.IBoard#getWidth() */ public int getWidth() { return width; } /* (non-Javadoc) * @see megamek.common.IBoard#newData(int, int, megamek.common.IHex[]) */ public void newData(int width, int height, IHex[] data) { this.width = width; this.height = height; this.data = data; initializeAll(); processBoardEvent(new BoardEvent(this, null, BoardEvent.BOARD_NEW_BOARD)); } /* (non-Javadoc) * @see megamek.common.IBoard#newData(int, int) */ public void newData(int width, int height) { newData(width, height, new IHex[width * height]); } public Enumeration getHexesAtDistance(Coords coords, int distance) { // Initialize the one necessary variable. Vector retVal = new Vector(); // Handle boundary conditions. if (distance < 0) { return retVal.elements(); } if (distance == 0) { retVal.add(coords); return retVal.elements(); } // Okay, handle the "real" case. // This is a bit of a cludge. Is there a better way to do this? for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { if (coords.distance(x,y) == distance) { retVal.add(new Coords(x,y)); //retVal.add(getHex(x, y)); } } } return retVal.elements(); } /** * Determines if this Board contains the (x, y) Coords, * and if so, returns the Hex at that position. * * @return the Hex, if this Board contains the (x, y) * location; null otherwise. * * @param x the x Coords. * @param y the y Coords. */ public IHex getHex(int x, int y) { if(contains(x, y)) { return data[y * width + x]; } return null; } /** * Gets the hex in the specified direction from the specified starting * coordinates. */ public IHex getHexInDir(Coords c, int dir) { return getHexInDir(c.x, c.y, dir); } /** * Gets the hex in the specified direction from the specified starting * coordinates. * * Avoids calls to Coords.translated, and thus, object construction. */ public IHex getHexInDir(int x, int y, int dir) { return getHex(Coords.xInDir(x, y, dir), Coords.yInDir(x, y, dir)); } /** * Initialize all hexes */ protected void initializeAll() { // Initialize all buildings. buildings.removeAllElements(); if (bldgByCoords == null) { bldgByCoords = new Hashtable(); } else { bldgByCoords.clear(); } // Walk through the hexes, creating buildings. for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Does this hex contain a building? IHex curHex = getHex( x, y ); if (curHex != null && (curHex.containsTerrain(Terrains.BUILDING))) { // Yup, but is it a repeat? Coords coords = new Coords(x,y); if ( !bldgByCoords.containsKey(coords) ) { // Nope. Try to create an object for the new building. try { Building bldg = new Building(coords, this, Terrains.BUILDING); buildings.addElement( bldg ); // Each building will identify the hexes it covers. Enumeration iter = bldg.getCoords(); while ( iter.hasMoreElements() ) { bldgByCoords.put( iter.nextElement(), bldg ); } } catch (IllegalArgumentException excep) { // Log the error and remove the // building from the board. System.err.println( "Unable to create building." ); excep.printStackTrace(); curHex.removeTerrain(Terrains.BUILDING); } } // End building-is-new } // End hex-has-building if (curHex != null && (curHex.containsTerrain(Terrains.FUEL_TANK))) { // Yup, but is it a repeat? Coords coords = new Coords(x,y); if ( !bldgByCoords.containsKey(coords) ) { // Nope. Try to create an object for the new building. try { int magnitude = curHex.getTerrain(Terrains.FUEL_TANK_MAGN).getLevel(); FuelTank bldg = new FuelTank(coords, this, Terrains.FUEL_TANK, magnitude); buildings.addElement(bldg); // Each building will identify the hexes it covers. Enumeration iter = bldg.getCoords(); while ( iter.hasMoreElements() ) { bldgByCoords.put( iter.nextElement(), bldg ); } } catch (IllegalArgumentException excep) { // Log the error and remove the // building from the board. System.err.println( "Unable to create building." ); excep.printStackTrace(); curHex.removeTerrain(Terrains.BUILDING); } } // End building-is-new } // End hex-has-building if ( curHex != null && curHex.containsTerrain(Terrains.BRIDGE)) { // Yup, but is it a repeat? Coords coords = new Coords(x,y); if ( !bldgByCoords.containsKey(coords) ) { // Nope. Try to create an object for the new building. try { Building bldg = new Building( coords, this, Terrains.BRIDGE ); buildings.addElement( bldg ); // Each building will identify the hexes it covers. Enumeration iter = bldg.getCoords(); while ( iter.hasMoreElements() ) { bldgByCoords.put( iter.nextElement(), bldg ); } } catch ( IllegalArgumentException excep ) { // Log the error and remove the // building from the board. System.err.println( "Unable to create bridge." ); excep.printStackTrace(); curHex.removeTerrain( Terrains.BRIDGE ); } } // End bridge-is-new } // End hex-has-bridge } } // Initialize all exits. for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { initializeHex(x, y); } } // good time to ensure hex cache IdealHex.ensureCacheSize(width + 1, height + 1); } // End private void initializeAll() /** * Initialize a hex and the hexes around it */ public void initializeAround(int x, int y) { initializeHex(x, y); for (int i = 0; i < 6; i++) { initializeInDir(x, y, i); } } /** * Initializes a hex in a specific direction from an origin hex */ private void initializeInDir(int x, int y, int dir) { initializeHex(Coords.xInDir(x, y, dir), Coords.yInDir(x, y, dir)); } /** * Initializes a hex in its surroundings. Currently sets the connects * parameter appropriately to the surrounding hexes. * * If a surrounding hex is off the board, it checks the hex opposite the * missing hex. */ private void initializeHex(int x, int y) { IHex hex = getHex(x, y); if (hex == null) { return; } hex.clearExits(); for (int i = 0; i < 6; i++) { IHex other = getHexInDir(x, y, i); hex.setExits(other, i, this.roadsAutoExit); } processBoardEvent(new BoardEvent(this, new Coords(x, y), BoardEvent.BOARD_CHANGED_HEX)); } /** * Determines whether this Board "contains" the specified * Coords. * * @param x the x Coords. * @param y the y Coords.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -