public boolean isAreaClearForNewUnit(int px, int py, int type_to_be_built) {
    myrect.x = px;
    myrect.y = py;

    Sprite s;
    for (int e = 0; e < sprites.size(); e++) {
      s = (Sprite) sprites.get(e);
      if (s.collideable) {
        if (s instanceof GameUnit) { // So bullets don't block us
          if (s.intersects(myrect)) {
            if (type_to_be_built == UnitStats.BOMBER) { // Bombers only block Bombers
              if (s instanceof UnitBomber) {
                return false;
              }
            } else {
              if (s instanceof UnitBomber == false) {
                return false;
              }
            }
          }
        }
      }
    }
    return true;
  }
  public void run() {
    while (!stop_now) {
      long start = System.currentTimeMillis();

      while (this.input_msgs.size() > 0) {
        Object o = this.input_msgs.get(0);
        this.input_msgs.remove(0);
        if (o instanceof MouseEvent) {
          MouseEvent evt = (MouseEvent) o;
          if (evt.getID() == MouseEvent.MOUSE_PRESSED) {
            if (this.i_game_stage == Main.STAGE_FIRST_TIME) {
              if (this.img_cache.areImagesLoaded()) {
                this.showGameMenu();
              }
            } else if (this.i_game_stage == Main.STAGE_GAME_MENU) {
              // if (evt.getButton() == MouseEvent.BUTTON1) {
              if (menus != null) {
                AbstractControl ac = null;
                for (int i = 0; i < menus.size(); i++) {
                  ac = (AbstractControl) menus.get(i);
                  if (ac.contains(evt.getX(), evt.getY())) {
                    ac.mouseDown(evt.getX(), evt.getY());
                    break;
                  }
                }
              }
            } else if (icon_panel != null && icon_panel.contains(mouse_pos)) {
              icon_panel.mouseDown(evt.getY() - icon_panel.y);
            } else if (icon_panel != null) {
              if (i_game_stage == Main.STAGE_PLAYING_GAME) {
                if (!this.paused) {
                  int mouse_x = (int) this.view_top_left.x + evt.getX() - (APPLET_SIZE / 2);
                  int mouse_y = (int) this.view_top_left.y + evt.getY() - (APPLET_SIZE / 2);
                  if (icon_panel.last_selected_icon != null) {
                    icon_panel.last_selected_icon.executeOnMap(mouse_x, mouse_y);
                  }
                } else {
                  addPausedLogEntry();
                }
              }
            }
          }
        } else if (o instanceof KeyEvent) {
          KeyEvent evt = (KeyEvent) o;
          if (evt.getKeyCode() == KeyEvent.VK_UP) {
            this.view_top_left.y -= MAP_SCROLL_SPEED;
          } else if (evt.getKeyCode() == KeyEvent.VK_DOWN) {
            this.view_top_left.y += MAP_SCROLL_SPEED;
          } else if (evt.getKeyCode() == KeyEvent.VK_LEFT) {
            this.view_top_left.x -= MAP_SCROLL_SPEED;
          } else if (evt.getKeyCode() == KeyEvent.VK_RIGHT) {
            this.view_top_left.x += MAP_SCROLL_SPEED;
          } else if (evt.getKeyCode() == KeyEvent.VK_C) {
            this.game_data.pdata[0].addCash(10);
            this.addLogEntry("CHEAT!");
          } else if (evt.getKeyCode() == KeyEvent.VK_D) {
            Main.DEBUG_AI = !Main.DEBUG_AI;
            this.addLogEntry("Debug toggled");
            /*} else if (evt.getKeyCode() == KeyEvent.VK_F || evt.getKeyCode() == KeyEvent.VK_3) {
            	this.icon_panel.last_selected_icon = this.icon_panel.getBuildMenuItem(UnitStats.BOMBER);
            } else if (evt.getKeyCode() == KeyEvent.VK_M || evt.getKeyCode() == KeyEvent.VK_1) {
            	this.icon_panel.last_selected_icon = this.icon_panel.getBuildMenuItem(UnitStats.MINE);*/
          } else if (evt.getKeyCode() == KeyEvent.VK_P) {
            togglePause();
          } else if (evt.getKeyCode() == KeyEvent.VK_R) {
            if (!this.paused) {
              if (this.img_cache.areImagesLoaded()) {
                this.showGameMenu();
              } else {
                log.add("Still loading images!  Please wait...");
              }
            } else {
              this.addPausedLogEntry();
            }
            /*} else if (evt.getKeyCode() == KeyEvent.VK_S || evt.getKeyCode() == KeyEvent.VK_2) {
            	this.icon_panel.last_selected_icon = this.icon_panel.getBuildMenuItem(UnitStats.MISSILE_SILO);
            } else if (evt.getKeyCode() == KeyEvent.VK_T || evt.getKeyCode() == KeyEvent.VK_4) {
            	this.icon_panel.last_selected_icon = this.icon_panel.getBuildMenuItem(UnitStats.TANK);*/
          } else if (evt.getKeyCode() == KeyEvent.VK_X) {
            this.game_data.pdata[1].addCash(10);
            this.addLogEntry("CPU CHEATED!");
          } else if (evt.getKeyCode() == KeyEvent.VK_1) {
            this.icon_panel.shortcutSelected(1);
          } else if (evt.getKeyCode() == KeyEvent.VK_2) {
            this.icon_panel.shortcutSelected(2);
          } else if (evt.getKeyCode() == KeyEvent.VK_3) {
            this.icon_panel.shortcutSelected(3);
          } else if (evt.getKeyCode() == KeyEvent.VK_4) {
            this.icon_panel.shortcutSelected(4);
          } else if (evt.getKeyCode() == KeyEvent.VK_F1) {
            if (this.i_game_stage == Main.STAGE_PLAYING_GAME) {
              this.show_threats = !this.show_threats;
              this.addLogEntry("Show threats? " + this.show_threats);
            }
          } else if (evt.getKeyCode() == KeyEvent.VK_F2) {
            if (this.i_game_stage == Main.STAGE_PLAYING_GAME) {
              this.show_targets = !this.show_targets;
              this.addLogEntry("Show targets? " + this.show_targets);
            }
          }
        } else {
          System.err.println("Unknown event type: " + o.toString());
        }
      }

      if (i_game_stage == Main.STAGE_PLAYING_GAME) {
        if (!this.paused) {
          this.game_data.time++;
          if (map_update_interval.hitInterval()) {
            if (this.check_mapsquare_owners) {
              this.getMapData().recalcOwners();
              this.check_mapsquare_owners = false;
              if (game_data.pdata[0].total_squares == 0) {
                won = false;
                this.addLogEntry("*************");
                this.addLogEntry("YOU HAVE LOST!");
                this.addLogEntry("*************");
                this.i_game_stage = Main.STAGE_GAME_FINISHED;
                // logWinOrLose(won);
              } else if (game_data.pdata[1].total_squares == 0) {
                won = true;
                this.addLogEntry("*************");
                this.addLogEntry("YOU HAVE WON!");
                this.addLogEntry("*************");
                this.i_game_stage = Main.STAGE_GAME_FINISHED;
                // logWinOrLose(won);
              }
            }
          }

          this.game_data.process();

          if (sprites != null) {
            Sprite sprite;
            for (int i = 0; i < sprites.size(); i++) {
              sprite = (Sprite) sprites.get(i);
              if (sprite != null) {
                sprite.process();
              }
            }
          }
        }
      }

      this.repaint();

      long wait = LOOP_DELAY - System.currentTimeMillis() + start;
      if (wait < 0) {
        p("Delay: " + wait);
      }
      Functions.delay(wait);
    }
  }
  public void update(Graphics g2) {
    try {
      Graphics g = this.img_back.getGraphics();

      g.setColor(Color.black);
      g.fillRect(0, 0, APPLET_SIZE, APPLET_SIZE);

      // Draw map
      if (getMapData() != null) {
        getMapData()
            .paint(
                g,
                (int) this.view_top_left.x,
                (int) this.view_top_left.y,
                this.show_map_owners,
                this.show_threats,
                this.show_targets);
      }

      if (sprites != null) {
        Sprite sprite;
        for (int i = 0; i < sprites.size(); i++) {
          sprite = (Sprite) sprites.get(i);
          if (sprite != null) {
            try {
              if (this.getMapData().map[sprite.getMapX()][sprite.getMapY()].seen) {
                sprite.paint(
                    g,
                    (int) this.view_top_left.x - (APPLET_SIZE / 2),
                    (int) this.view_top_left.y - (APPLET_SIZE / 2));
              }
            } catch (java.lang.ArrayIndexOutOfBoundsException ex) {
              // Do nothing
            }
          }
        }
      }

      if (menus != null) {
        g.setFont(font_large);
        AbstractControl ac = null;
        for (int i = 0; i < menus.size(); i++) {
          ac = (AbstractControl) menus.get(i);
          ac.paint(g);
        }
      }

      if (i_game_stage < Main.STAGE_GAME_MENU) {
        g.setColor(Color.yellow);
        g.setFont(font_xlarge);
        g.drawString(TITLE, 50, 200);
        g.setFont(font_large);
        g.drawString(VERSION, 60, 250);
        if (this.img_cache.areImagesLoaded()) {
          if (this.i_game_stage == Main.STAGE_FIRST_TIME) {
            g.drawString("Click to Start!", APPLET_SIZE / 2 - 100, APPLET_SIZE / 2 + 40);
          } else {
            g.drawString("Press S to Start!", APPLET_SIZE / 2 - 100, APPLET_SIZE / 2 + 40);
          }
        } else {
          g.drawString(
              "Please wait... (" + this.img_cache.percent + "%)",
              APPLET_SIZE / 2 - 100,
              APPLET_SIZE / 2 + 40);
        }
      } else if (i_game_stage == Main.STAGE_GAME_FINISHED) {
        g.setColor(Color.yellow);
        g.setFont(font_xlarge);
        if (won) {
          g.drawString("YOU HAVE WON!", 150, 200);
        } else {
          g.drawString("You have LOST!", 150, 200);
        }
        g.setFont(font_large);
        g.drawString("Press R to restart", APPLET_SIZE / 2, APPLET_SIZE / 2 + 40);
      }

      log.paint(g, 20, APPLET_SIZE - LogWindow.HEIGHT - 20);
      if (i_game_stage >= Main.STAGE_PLAYING_GAME) {
        stats.paint(g, 20, 20);
        if (icon_panel != null) {
          icon_panel.paint(g);
        }
      }

      g.setFont(font_small);
      g.setColor(Color.DARK_GRAY);
      g.drawString(VERSION, APPLET_SIZE - 50, 20);

      g2.drawImage(this.img_back, 0, 0, this);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(-1);
    }
  }
  private void updateIntel() {
    player_attack_units_threat = 0;

    // First, blank the intel rating
    for (int y = 0; y < map_height; y++) {
      for (int x = 0; x < map_width; x++) {
        threats_intel[x][y] = 0;
        targets_intel[x][y] = 0;
        allied_intel[x][y] = 0;
      }
    }

    // Now update the threat of each square
    ThreadSafeArrayList sprites = main.sprites;
    Sprite sprite;
    for (int i = 0; i < sprites.size(); i++) {
      sprite = (Sprite) sprites.get(i);
      if (sprite != null) {
        if (sprite instanceof GameUnit) {
          GameUnit gu = (GameUnit) sprite;
          if (gu.threat_value != 0) {
            if (gu.side != this.side) {
              if (gu instanceof UnitBomber || gu instanceof UnitTank) {
                player_attack_units_threat += gu.threat_value;
              }
            }

            int mapx = sprite.getMapX();
            int mapy = sprite.getMapY();

            // Update intel based on unit's view range
            int RANGE_SQ =
                (GameUnit.SHOT_RANGE
                    / MapData
                        .SQUARE_SIZE); // / 2; DONT HALVE IT SINCE THE AI WILL BULD MONES NEXT TO
            // SILOS!  // Halve it since it's the dist between our
            // enemies and squares owned by us

            for (int y2 = mapy - RANGE_SQ; y2 <= mapy + RANGE_SQ; y2++) {
              for (int x2 = mapx - RANGE_SQ; x2 <= mapx + RANGE_SQ; x2++) {
                double dist = Functions.distance(mapx, mapy, x2, y2);
                if (dist <= RANGE_SQ) {
                  try {
                    if (gu instanceof UnitMiningPlatform == false) {
                      if (gu.side != this.side) {
                        threats_intel[x2][y2] += gu.threat_value;
                      } else {
                        allied_intel[x2][y2] += gu.threat_value;
                      }
                    } else if (gu instanceof UnitMiningPlatform) {
                      if (gu.side != this.side) {
                        targets_intel[x2][y2] += gu.threat_value;
                      }
                    }
                  } catch (java.lang.ArrayIndexOutOfBoundsException ex) {
                    // Do nothing
                  }
                }
              }
            }

            // Update targets
            // Update intel based on unit's view range
            /*int TARGET_RANGE_SQ = (UnitStats.BOMBER_VIEW_RANGE / MapData.SQUARE_SIZE);

            for(int y2=mapy-TARGET_RANGE_SQ ; y2<=mapy+TARGET_RANGE_SQ ; y2++) {
            	for(int x2=mapx-TARGET_RANGE_SQ ; x2<=mapx+TARGET_RANGE_SQ ; x2++) {
            		double dist = Functions.distance(mapx, mapy, x2, y2);
            		if (dist <= TARGET_RANGE_SQ) {
            			try {
            				if (gu instanceof UnitMiningPlatform) {
            					if (gu.side != this.side) {
            						targets_intel[x2][y2] += gu.threat_value;
            					}
            				}
            			} catch (java.lang.ArrayIndexOutOfBoundsException ex) {
            				// Do nothing
            			}
            		}
            	}
            }*/
          }
        }
      }
    }

    // Get the top threat square
    int highest_threat = -1;
    int highest_target = -1;
    int highest_resources = -1;
    for (int y = 0; y < map_height; y++) {
      for (int x = 0; x < map_width; x++) {
        if (main.getMapData().map[x][y].owner
            == side) { // This is where we are going to build something, so it must be our square
          if (threats_intel[x][y] - allied_intel[x][y] > highest_threat) {
            if (main.isAreaClearForNewUnit(x * MapData.SQUARE_SIZE, y * MapData.SQUARE_SIZE, -1)) {
              highest_threat = threats_intel[x][y] - allied_intel[x][y];
              top_threat_location.x = x;
              top_threat_location.y = y;
            }
          }
          if (targets_intel[x][y] > highest_target) {
            if (main.isAreaClearForNewUnit(x * MapData.SQUARE_SIZE, y * MapData.SQUARE_SIZE, -1)) {
              highest_target = targets_intel[x][y];
              top_target_location.x = x;
              top_target_location.y = y;
            }
          }
          if (threats_intel[x][y] == 0) { // Don't build near an enemy!
            int minerals = (int) main.getMapData().map[x][y].minerals;
            if (minerals
                >= highest_resources) { // Needs to be ">=" otherwise the AI spreads itself all over
              // the map (was: Needs to be ">" so that if there's no
              // resources in starting squares, it moves up-left)
              // if (main.getMapData().map[x][y].owner == side) {
              if (main.isAreaClearForNewUnit(
                  x * MapData.SQUARE_SIZE, y * MapData.SQUARE_SIZE, -1)) {
                highest_resources = minerals;
                best_mine_location.x = x;
                best_mine_location.y = y;
              }
              // }
            }
          }
        }
      }
    }

    max_map_threat = 0;
    if (top_threat_location.x >= 0) {
      max_map_threat =
          this.threats_intel[top_threat_location.x][top_threat_location.y]
              - this.allied_intel[top_threat_location.x][top_threat_location.y];
    }

    max_map_target = 0;
    if (top_target_location.x >= 0) {
      max_map_target = this.targets_intel[top_target_location.x][top_target_location.y];
    }

    // Get the best mine location
    /*int highest_resources = -1;
    for (int y = 0 ; y<map_height ; y++) {
    	for (int x = 0 ; x<map_width ; x++) {
    		if (threats_intel[x][y] == 0) { // Don't build near an enemy!
    			int minerals = (int)main.getMapData().map[x][y].minerals;
    			if (minerals >= highest_resources) { // Needs to be ">=" otherwise the AI spreads itself all over the map (was: Needs to be ">" so that if there's no resources in starting squares, it moves up-left)
    				if (main.getMapData().map[x][y].owner == side) {
    					if (main.isAreaClearForNewUnit(x * MapData.SQUARE_SIZE, y * MapData.SQUARE_SIZE, -1)) {
    						highest_resources = minerals;
    						best_mine_location.x = x;
    						best_mine_location.y = y;
    					}
    				}
    			}
    		}
    	}
    }
    prev_highest_resources = highest_resources;*/
  }