Beispiel #1
0
void setup_land()
{
	int x, y, xw, yw;
	int aridity = global_aridity;

	distance_to_river();

	for (y = 0; y < WORLD_SIDE_LEN; y++) {
		for (x = 0; x < WORLD_SIDE_LEN; x++) {
			int d2w_min = 2 * WORLD_SIDE_LEN * WORLD_SIDE_LEN;
			int r;
			int arid = aridity;
			//int alt0 = 0;

			/* test against IS_RIVER to prevent terrible recursion */
			if (IS_RIVER(x, y))
				continue;

			d2w_min = lmap.dist2w[x][y];

			/* near river lower aridity */
			if (aridity > 0) {
				if (d2w_min < 5)
					arid = aridity / 3;
				else if (d2w_min < 17)
					arid = (aridity * 2) / 3;
			}
			/* Altitude has same effect as distance */
			r = rand() % (d2w_min / 3 + 1) \
			    + arid \
			    + abs(ALT(x, y) * 15 / alt_step) \
			    + 3 * (ALT(x, y) * ALT(x, y)) / 1000000;

			lmap.ecotable[x][y] = r;
			/* needed to setup quasi randome land. The flag is set below */
			MP_FLAG(x, y) |= FLAG_HAS_UNDERGROUND_WATER;
			do_rand_ecology(x, y);

			/* preserve rivers, so that we can connect port later */
			if (MP_TYPE(x, y) == WATER) {
				int navigable = MP_FLAG(x, y) & FLAG_IS_RIVER;
				set_mappoint(x, y, WATER);
				MP_FLAG(x, y) |= navigable;
				MP_FLAG(x, y) |= FLAG_HAS_UNDERGROUND_WATER;
			}
			/* set undergroung water according to first random land setup */
			if (MP_TYPE(x, y) == DESERT) {
				MP_FLAG(x, y) &= (0xffffffff - FLAG_HAS_UNDERGROUND_WATER);
			}
		}
	}
	for (y = 0; y < WORLD_SIDE_LEN; y++)
		for (x = 0; x < WORLD_SIDE_LEN; x++)
			if (MP_TYPE(x, y) == WATER)
				MP_FLAG(x, y) |= FLAG_HAS_UNDERGROUND_WATER;

	//connect_rivers();
}
void 
debug_mappoints (void)
{
  int x, y;
  for (x = 0; x < WORLD_SIDE_LEN; x++) {
    for (y = 0; y < WORLD_SIDE_LEN; y++) {
      if ((MP_TYPE(x,y) < 0) || (MP_TYPE(x,y) > 400)) {
	printf ("Error in mappoint %d %d (%d)\n", x, y, MP_TYPE(x,y));
	exit(-1);
      }
    }
  }
}
void
fire_area (int xx, int yy)
{
    /* this happens when a rocket crashes or on random_fire. */
    int x = xx;
    int y = yy;
    int size;
    if (MP_GROUP(x,y) == GROUP_WATER || MP_GROUP(x,y) == GROUP_FIRE)
        return;
    if (MP_TYPE(x,y) == CST_USED) {
        x = MP_INFO(xx,yy).int_1;
        y = MP_INFO(xx,yy).int_2;
    }
    size = MP_SIZE(x,y);

    /* Destroy the content of the building to prevent special management
     * when bulldozed.
     */

    /* Kill 'only' half of the people (bulldoze item put them in people_pool)
     * lincity NG 1.1 and previous killed all the people!
     */
    if ((MP_INFO(x,y).flags & FLAG_FIRE_COVER) !=0)
        MP_INFO(x,y).population = MP_INFO(x,y).population / 2;
    else
        MP_INFO(x,y).population = 0;
    MP_INFO(x,y).flags = 0;
    MP_INFO(x,y).int_1 = 0;
    MP_INFO(x,y).int_2 = 0;
    MP_INFO(x,y).int_3 = 0;
    MP_INFO(x,y).int_4 = 0;
    MP_INFO(x,y).int_5 = 0;
    MP_INFO(x,y).int_6 = 0;
    MP_INFO(x,y).int_7 = 0;

    /* Correctly remove buildings (substations...) and adjust count,
     * but don't count bulldoze cost
     * */
    adjust_money(+main_groups[MP_GROUP(x,y)].bul_cost);
    bulldoze_item(x, y);

    /* put fire */
    for (int i = 0; i < size; i++)
        for (int j = 0; j < size; j++) {
            bulldoze_mappoint (CST_FIRE_1, x + i, y + j);
            MP_GROUP(x + i, y + j) = GROUP_FIRE;
        }


    /* AL1: is it necessary ? It is the only place in lincity/. with such a call
     *  all other are in lincity-ng/.
     */
    refresh_main_screen ();

  /* 
    // update transport or we get stuff put in
    // the area from connected tracks etc.
    // FIXME: AL1: NG 1.1: do the right thing and/or remove this comment
  */
}
void 
handle_msg_map_types (void)
{
    int x, y;
    MsgBuf* msg = &recvbuf;
    Int16* msgp = (Int16*) MSG_BODY(msg);

    printf ("Client received MSG_MAP_TYPES.\n");
    for (y = 0; y < WORLD_SIDE_LEN; y++) {
	for (x = 0; x < WORLD_SIDE_LEN; x++) {
	    MP_TYPE(x,y) = ntohs(*msgp++);
	    if (MP_TYPE(x,y) != CST_USED && MP_TYPE(x,y) != CST_GREEN) {
		set_mappoint (x, y, MP_TYPE(x,y));
	    }
	}
    }
}
/*
  // int_1 is the rated capacity 
  // int_2 is the tech level when built
  // int_3 is the sail count - to choose the right sail.
  // int_4 is the last real time that a sail was turned
  // int_5 is the power produced (basically _if_ power produced)
  // int_6 is the grid it's on
  // int_7 is a timestamp for mapping
*/
void
do_windmill (int x, int y) 
{
  int anim_tile; 

  if (get_jobs (x, y, WINDMILL_JOBS) != 0) {
    MP_INFO(x,y).int_5 = MP_INFO(x,y).int_1;
    grid[MP_INFO(x,y).int_6]->avail_power += MP_INFO(x,y).int_1;
  } else {
    MP_INFO(x,y).int_4 = real_time + MODERN_WINDMILL_ANIM_SPEED;
    return;
  }

  /* update animation */
  if (real_time > MP_INFO(x,y).int_4) {
    MP_INFO(x,y).int_3++;
    if (MP_INFO(x,y).int_2 < MODERN_WINDMILL_TECH) {
      MP_INFO(x,y).int_4 = real_time + ANTIQUE_WINDMILL_ANIM_SPEED;
    } else {
      MP_INFO(x,y).int_4 = real_time + MODERN_WINDMILL_ANIM_SPEED;
    }
  }

  /* figure out which tile to use */
  anim_tile = (MP_INFO(x,y).int_3 % 3);

  if (MP_INFO(x,y).int_2 < MODERN_WINDMILL_TECH)
    MP_TYPE(x,y) = CST_WINDMILL_1_W + anim_tile;
  else
    switch(grid[MP_INFO(x,y).int_6]->powered) 
      {
      case -1: 
	MP_TYPE(x,y) = CST_WINDMILL_1_R + anim_tile; 
	break;
      case 0 : 
	MP_TYPE(x,y) = CST_WINDMILL_1_RG + anim_tile;
	break;
      case 1 : 
	MP_TYPE(x,y) = CST_WINDMILL_1_G + anim_tile;
	break;
      default : 
	printf("Default case in do_power_substation\n");
	break;
      }      
}
void
inventory(int x, int y)
{

    switch(get_group_of_type(MP_TYPE(x,y))) {

    case GROUP_MARKET: 
	inventory_market(x, y); 
	break;
    
    default: {
	printf("Default in inventory(%d,%d): got %d\n", 
	    x, y, get_group_of_type(MP_TYPE(x,y)));
	break;
    }

    }
}
Beispiel #7
0
void 
do_power_substation (int x, int y) 
{
    switch(grid[MP_INFO(x,y).int_6]->powered) {
    case -1: {
	MP_TYPE(x,y) = CST_SUBSTATION_R; 
    } break;
    case 0 : {
	MP_TYPE(x,y) = CST_SUBSTATION_RG;
    } break;
    case 1 : {
	MP_TYPE(x,y) = CST_SUBSTATION_G;
    } break;
    default : {
	printf("Default case in do_power_substation\n");
    } break;
    }
}
void
check_bulldoze_area (int x, int y)
{
    //no need to bulldoze desert
    if( MP_GROUP( x, y ) == GROUP_DESERT ) 
        return;
    
  int xx, yy, g;
  if (MP_TYPE(x,y) == CST_USED)
    {
      xx = MP_INFO(x,y).int_1;
      yy = MP_INFO(x,y).int_2;
    }
  else
    {
      xx = x;
      yy = y;
    }
  g = MP_GROUP(xx,yy);

  if (g == GROUP_MONUMENT && monument_bul_flag == 0)
    {
        if( last_message_group != GROUP_MONUMENT ){
            new Dialog( BULLDOZE_MONUMENT, xx, yy ); // deletes itself
            last_message_group = GROUP_MONUMENT;
        }
        return;
    }
  else if (g == GROUP_RIVER && river_bul_flag == 0)
    {
        if( last_message_group != GROUP_RIVER ){
            new Dialog( BULLDOZE_RIVER, xx, yy ); // deletes itself
            last_message_group = GROUP_RIVER;
        }
        return;
    }
  else if (g == GROUP_SHANTY && shanty_bul_flag == 0)
    {
        if( last_message_group != GROUP_SHANTY ){
            new Dialog( BULLDOZE_SHANTY, xx, yy ); // deletes itself
            last_message_group = GROUP_SHANTY;
        }
        return;
    }
  else if (g == GROUP_TIP)
    {
      if( last_message_group != GROUP_TIP ){
        ok_dial_box ("nobull-tip.mes", BAD, 0L);
        last_message_group = GROUP_TIP;
      }
      return;
    }
  last_message_group = 0;
  getSound()->playSound( "Raze" );
  bulldoze_item (xx,yy);
}
/* XXX: WCK: What is up with this?  Why not just use set_mappoint?! */
static void
quick_start_add (int x, int y, short type, int size)
{
  int xx, yy;
  if (size == 1) {
      MP_TYPE(x,y) = type;
      MP_GROUP(x,y) = get_group_of_type(type);
      return;
  }
  for (yy = 0; yy < size; yy++) {
    for (xx = 0; xx < size; xx++) {
	if (xx == 0 && yy == 0)
	  continue;
	set_mappoint_used (x, y, x + xx, y + yy);
      }
  }
  MP_TYPE(x,y) = type;
  MP_GROUP(x,y) = get_group_of_type(type);
}
void
set_map_groups (void)
{
    int x, y;
    for (x = 0; x < WORLD_SIDE_LEN; x++) {
        for (y = 0; y < WORLD_SIDE_LEN; y++) {
            MP_GROUP(x,y) = get_group_of_type(MP_TYPE(x,y));
        }
    }
}
int 
bulldoze_item (int x, int y)
{
    int g, size;

    if (MP_TYPE(x,y) == CST_USED) {
	/* This is considered "improper" input.  Silently ignore. */
	return -1;
    }

    size = MP_SIZE(x,y);
    g = MP_GROUP(x,y);

    if (g == GROUP_BARE) {
	/* Nothing to do. */
	return -1;
    }
    else if (g == GROUP_SHANTY) {
	fire_area (x, y);
	adjust_money(-GROUP_SHANTY_BUL_COST);
    }
    else if (g == GROUP_FIRE) {
	if (MP_INFO(x,y).int_2 >= FIRE_LENGTH)
	    return -1;  /* Can't bulldoze ? */
	MP_INFO(x,y).int_2 = FIRE_LENGTH + 1;
	MP_TYPE(x,y) = CST_FIRE_DONE1;
	MP_GROUP(x,y) = GROUP_BURNT;
	adjust_money(-GROUP_BURNT_BUL_COST);
    }
    else {
	adjust_money(-main_groups[g].bul_cost);
	do_bulldoze_area (CST_GREEN, x, y);
	if (g == GROUP_OREMINE)
	{
	    int i, j;
	    for (j = 0; j < 4; j++)
		for (i = 0; i < 4; i++)
		    if (MP_INFO(x + i,y + j).ore_reserve < ORE_RESERVE / 2)
			do_bulldoze_area (CST_WATER, x + i, y + j);
	}
    }
    return size;  /* No longer used... */
}
void
setup_river (void)
{
    int x, y, i, j;
    x = WORLD_SIDE_LEN / 2;
    y = WORLD_SIDE_LEN - 1;
    i = (rand () % 12) + 6;
    for (j = 0; j < i; j++) {
	x += (rand () % 3) - 1;
	MP_TYPE(x,y) = CST_WATER;
	MP_GROUP(x,y) = GROUP_WATER;
	MP_INFO(x,y).flags |= FLAG_IS_RIVER;
	MP_TYPE(x+1,y) = CST_WATER;
	MP_GROUP(x+1,y) = GROUP_WATER;
	MP_INFO(x+1,y).flags |= FLAG_IS_RIVER;
	MP_TYPE(x-1,y) = CST_WATER;
	MP_GROUP(x-1,y) = GROUP_WATER;
	MP_INFO(x-1,y).flags |= FLAG_IS_RIVER;
	y--;
    }
    MP_TYPE(x,y) = CST_WATER;
    MP_GROUP(x,y) = GROUP_WATER;
    MP_INFO(x,y).flags |= FLAG_IS_RIVER;
    MP_TYPE(x+1,y) = CST_WATER;
    MP_GROUP(x+1,y) = GROUP_WATER;
    MP_INFO(x+1,y).flags |= FLAG_IS_RIVER;
    MP_TYPE(x-1,y) = CST_WATER;
    MP_GROUP(x-1,y) = GROUP_WATER;
    MP_INFO(x-1,y).flags |= FLAG_IS_RIVER;

    setup_river2 (x - 1, y, -1);	/* left tributary */
    setup_river2 (x + 1, y, 1);	/* right tributary */
}
/*
  int_5 is animation schedule
  int_6 is the grid it is on
  int_7 is a grid timestamp
*/
void
do_power_line (int x, int y)
{
    if (grid[MP_INFO(x,y).int_6]->powered == -1)
	return;

    switch(MP_INFO(x,y).int_5) 
    {
    case 0: 
	MP_INFO(x,y).int_5 = POWER_MODULUS;
	break;
    case 1:
	if (!(MP_TYPE(x,y) <= 11 && MP_TYPE(x,y) >= 1))
	    break;
	MP_TYPE(x,y) += 11;
	break;
    case 2:
	if (!(MP_TYPE(x,y) >= 11 && MP_TYPE(x,y) <= 22))
	    break;
	MP_TYPE(x,y) -= 11;
	break;
    }

    MP_INFO(x,y).int_5--;
}
void
do_bulldoze_area (short fill, int xx, int yy)
{
  int size, x, y;
  if (MP_TYPE(xx,yy) == CST_USED)
    {
      x = MP_INFO(xx,yy).int_1;
      y = MP_INFO(xx,yy).int_2;
    }
  else
    {
      x = xx;
      y = yy;
    }
  size = MP_SIZE(x,y);
  if (MP_GROUP(x,y) == GROUP_SUBSTATION
      || MP_GROUP(x,y) == GROUP_WINDMILL)
    remove_a_substation (x, y);
  else if (MP_GROUP(x,y) == GROUP_MARKET)
    remove_a_market (x, y);
  else if (MP_GROUP(x,y) == GROUP_SHANTY)
    numof_shanties--;
  else if (MP_GROUP(x,y) == GROUP_COMMUNE)
    numof_communes--;

  people_pool += MP_INFO(x,y).population;
  clear_mappoint (fill, x, y);
  if (size > 1)			/* do size 2 */
    {
      clear_mappoint (fill, x + 1, y);
      clear_mappoint (fill, x, y + 1);
      clear_mappoint (fill, x + 1, y + 1);
    }
  if (size > 2)			/* do size 3 */
    {
      clear_mappoint (fill, x + 2, y);
      clear_mappoint (fill, x + 2, y + 1);
      clear_mappoint (fill, x + 2, y + 2);
      clear_mappoint (fill, x, y + 2);
      clear_mappoint (fill, x + 1, y + 2);
    }
  if (size > 3)			/* do size 4 */
    {
      clear_mappoint (fill, x + 3, y);
      clear_mappoint (fill, x + 3, y + 1);
      clear_mappoint (fill, x + 3, y + 2);
      clear_mappoint (fill, x + 3, y + 3);
      clear_mappoint (fill, x, y + 3);
      clear_mappoint (fill, x + 1, y + 3);
      clear_mappoint (fill, x + 2, y + 3);
    }
}
void 
handle_msg_map_types_region (void)
{
  int x, y, xx, yy, size;
  MsgBuf* msg = &recvbuf;
  Int16* msgp16 = (Int16*) MSG_BODY(msg);
  Int32* msgp32 = (Int32*) MSG_BODY(msg);

  printf ("Client received MSG_MAP_TYPES_REGION.\n");
  x = ntohl(*msgp32++);
  y = ntohl(*msgp32++);
  size = ntohl(*msgp32++);
  msgp16 = (Int16*) msgp32;
  for (yy = y; yy < y + size; yy++) {
    for (xx = x; xx < x + size; xx++) {
      MP_TYPE(xx,yy) = ntohs(*msgp16++);
      if (MP_TYPE(xx,yy) != CST_USED) {
	set_mappoint (xx, yy, MP_TYPE(xx,yy));
      }
    }
  }
}
void 
handle_msg_rocket_fired (void)
{
    int x, y, result;
    MsgBuf* msg = &recvbuf;
    Int32* msgp = (Int32*) MSG_BODY(msg);

    printf ("Client received MSG_ROCKET_FIRED\n");
    x = ntohl(*msgp++);
    y = ntohl(*msgp++);
    result = ntohl(*msgp++);
    MP_TYPE(x,y) = CST_ROCKET_FLOWN;
    display_rocket_result_dialog (result);
}
void
setup_river2 (int x, int y, int d)
{
    int i, j, r;
    i = (rand () % 55) + 15;
    for (j = 0; j < i; j++)
    {
	r = (rand () % 3) - 1 + (d * (rand () % 3));
	if (r < -1)
	    r = -1;
	else if (r > 1)
	    r = 1;
	x += r;
	if (MP_TYPE(x+(d+d),y) != 0
	    || MP_TYPE(x+(d+d+d),y) != 0)
	    return;
	if (x > 5 && x < WORLD_SIDE_LEN - 5)
	{
	    MP_TYPE(x,y) = CST_WATER;
	    MP_GROUP(x,y) = GROUP_WATER;
	    MP_INFO(x,y).flags |= FLAG_IS_RIVER;
	    MP_TYPE(x + d,y) = CST_WATER;
	    MP_GROUP(x+d,y) = GROUP_WATER;
	    MP_INFO(x+d,y).flags |= FLAG_IS_RIVER;
	}
	if (--y < 10 || x < 5 || x > WORLD_SIDE_LEN - 5)
	    break;
    }
    if (y > 20)
    {
	if (x > 5 && x < WORLD_SIDE_LEN - 5)
	    setup_river2 (x, y, -1);
	if (x > 5 && x < WORLD_SIDE_LEN - 5)
	    setup_river2 (x, y, 1);
    }
}
void 
clear_mappoint (short fill, int x, int y)
{
    MP_TYPE(x,y) = fill;
    MP_GROUP(x,y) = get_group_of_type(fill);
    if (MP_GROUP(x,y) < 0) MP_GROUP(x,y) = GROUP_BARE;
    MP_INFO(x,y).population = 0;
    MP_INFO(x,y).flags = 0;
    MP_INFO(x,y).int_1 = 0;
    MP_INFO(x,y).int_2 = 0;
    MP_INFO(x,y).int_3 = 0;
    MP_INFO(x,y).int_4 = 0;
    MP_INFO(x,y).int_5 = 0;
    MP_INFO(x,y).int_6 = 0;
    MP_INFO(x,y).int_7 = 0;
}
void 
count_all_groups (int* group_count)
{
    int x, y;
    unsigned short t, g;
    for (x = 0; x < NUM_OF_GROUPS; x++)
	group_count[x] = 0;
    for (y = 0; y < WORLD_SIDE_LEN; y++) {
	for (x = 0; x < WORLD_SIDE_LEN; x++) {
	    t = MP_TYPE(x,y);
	    if (t != CST_USED && t != CST_GREEN) {
		g = get_group_of_type(t);
		group_count[g]++;
	    }
	}
    }
}
void
do_fire_health_and_cricket_cover (void)
{
  int x, y;
  for (y = 0; y < WORLD_SIDE_LEN; y++)
    for (x = 0; x < WORLD_SIDE_LEN; x++)
      {
	/*  The next few lines need changing to test for */
	/*  the group if these areas are animated. */

	if (MP_GROUP(x,y) == GROUP_FIRESTATION)
	  do_fire_cover (x, y);
	else if (MP_TYPE(x,y) == CST_HEALTH)
	  do_health_cover (x, y);
	else if (MP_GROUP(x,y) == GROUP_CRICKET)
	  do_cricket_cover (x, y);
      }
}
static void 
bulldoze_mappoint (short fill, int x, int y)
{
    /* bulldoze preserve underground resources */
    MP_TYPE(x,y) = fill;
    MP_GROUP(x,y) = get_group_of_type(fill);
    if (MP_GROUP(x,y) < 0)
        MP_GROUP(x,y) = GROUP_BARE;
    MP_INFO(x,y).population = 0;
    MP_INFO(x,y).flags &= FLAG_HAS_UNDERGROUND_WATER;
    MP_INFO(x,y).int_1 = 0;
    MP_INFO(x,y).int_2 = 0;
    MP_INFO(x,y).int_3 = 0;
    MP_INFO(x,y).int_4 = 0;
    MP_INFO(x,y).int_5 = 0;
    MP_INFO(x,y).int_6 = 0;
    MP_INFO(x,y).int_7 = 0;
}
void
do_bulldoze_area (short fill, int xx, int yy)
{
  int size, x, y;
  if (MP_TYPE(xx,yy) == CST_USED)
    {
      x = MP_INFO(xx,yy).int_1;
      y = MP_INFO(xx,yy).int_2;
    }
  else
    {
      x = xx;
      y = yy;
    }
  size = MP_SIZE(x,y);
  for (int i = 0; i < size; i++)
      for (int j = 0; j < size; j++)  
          bulldoze_mappoint (fill, x+i, y+j);
}
void launch_rocket(int x, int y)
{
    int i, r, xx, yy, xxx, yyy;
    rockets_launched++;
    MP_TYPE(x, y) = CST_ROCKET_FLOWN;
    update_main_screen(0);
    /* The first five failures gives 49.419 % chances of 5 success
     * TODO: some stress could be added by 3,2,1,0 and animation of rocket with sound...
     */
    r = rand() % MAX_TECH_LEVEL;
    if (r > tech_level || rand() % 100 > (rockets_launched * 15 + 25)) {
        /* the launch failed */
        display_rocket_result_dialog(ROCKET_LAUNCH_BAD);
        rockets_launched_success = 0;
        xx = ((rand() % 40) - 20) + x;
        yy = ((rand() % 40) - 20) + y;
        for (i = 0; i < 20; i++) {
            xxx = ((rand() % 20) - 10) + xx;
            yyy = ((rand() % 20) - 10) + yy;
            if (xxx > 0 && xxx < (WORLD_SIDE_LEN - 4)
                && yyy > 0 && yyy < (WORLD_SIDE_LEN - 4)) {
                /* don't crash on it's own area */
                if (xxx >= x && xxx < (x + 4) && yyy >= y && yyy < (y + 4))
                    continue;
                fire_area(xxx, yyy);
                /* make a sound perhaps */
            }
        }
    } else {
        rockets_launched_success++;
        /* TODO: Maybe should generate some pollution ? */
        if (rockets_launched_success > 5) {
            remove_people(1000);
            if (people_pool || housed_population)
                display_rocket_result_dialog(ROCKET_LAUNCH_EVAC);
        } else {
            display_rocket_result_dialog(ROCKET_LAUNCH_GOOD);
        }
    }
}
int
put_stuff (int x, int y, int stuff, int stuff_type)
{
    int res = 0;
    short *type = &MP_TYPE(x,y);
    Map_Point_Info *minfo = &MP_INFO(x,y);
    switch (MP_SIZE(x,y))
    {
    case 2:
	res = put_stuff2 (minfo, type, stuff, stuff_type);
	break;
    case 3:
	res = put_stuff3 (minfo, type, stuff, stuff_type);
	break;
    case 4:
	res = put_stuff4 (minfo, type, stuff, stuff_type);
	break;
    default:
	do_error ("Bad area size in put_stuff()");
    }
    return res;
}
int
sust_fire_cover (void)
{
  int x, y;
  for (x = 0; x < WORLD_SIDE_LEN; x++)
    for (y = 0; y < WORLD_SIDE_LEN; y++)
      {
	if (MP_GROUP(x,y) == GROUP_BARE
	    || MP_TYPE(x,y) == CST_USED
	    || MP_GROUP(x,y) == GROUP_WATER
	    || MP_GROUP(x,y) == GROUP_POWER_LINE
	    || MP_GROUP(x,y) == GROUP_OREMINE
	    || MP_GROUP(x,y) == GROUP_ROCKET
	    || MP_GROUP(x,y) == GROUP_MONUMENT
	    || MP_GROUP(x,y) == GROUP_BURNT)
	  ;			/* do nothing */

	else if ((MP_INFO(x,y).flags & FLAG_FIRE_COVER) == 0)
	  return (0);
      }
  return (1);
}
void
sanity_check (void)
{
    static int flag = 0;
    int x, y, xx, yy;
    for (x = 0; x < WORLD_SIDE_LEN; x++)
	for (y = 0; y < WORLD_SIDE_LEN; y++) {
	    if (MP_TYPE(x,y) == CST_USED) {
		xx = MP_INFO(x,y).int_1;
		yy = MP_INFO(x,y).int_2;
		if (xx < (x - 4) || yy < (y - 4) || xx > x || yy > y ||
		    xx < 0 || xx > WORLD_SIDE_LEN ||
		    yy < 0 || yy > WORLD_SIDE_LEN) {
		    printf (_("Sanity failed at %d %d, points to %d %d\n"), x, y, xx, yy);
		    if (flag == 0)
			yn_dial_box (_("MP sanity check error")
				     ,_("Please mail  [email protected]")
				     ,_("telling me what you just did.")
				     ,_("Do you think I'll find this bug?"));
		    flag = 1;
		}
	    }
	}
}
void
sanity_check (void)
{
    static int flag = 0;
    int x, y, xx, yy;
    for (x = 0; x < WORLD_SIDE_LEN; x++)
	for (y = 0; y < WORLD_SIDE_LEN; y++) {
	    if (MP_TYPE(x,y) == CST_USED) {
		xx = MP_INFO(x,y).int_1;
		yy = MP_INFO(x,y).int_2;
		if (xx < (x - 4) || yy < (y - 4) || xx > x || yy > y ||
		    xx < 0 || xx > WORLD_SIDE_LEN ||
		    yy < 0 || yy > WORLD_SIDE_LEN) {
		    printf ("Sanity failed at %d %d, points to %d %d\n", x, y, xx, yy);
		    if (flag == 0)
			yn_dial_box ("MP sanity check error",
				     "Please mail  [email protected]",
				     "telling me what you just did.",
				     "Do you think I'll find this bug?");
		    flag = 1;
		}
	    }
	}
}
/*
   // spiral round from startx,starty until we hit a 2x2 space.
   // return the x y coords encoded as x+y*WORLD_SIDE_LEN
   // return -1 if we don't find one.
 */
int
spiral_find_2x2 (int startx, int starty)
{
  int i, j, x, y;
  x = startx;
  y = starty;
  /* let's just do a complete spiral for now, work out the bounds later */
  for (i = 1; i < (WORLD_SIDE_LEN + WORLD_SIDE_LEN); i++)
    {
      for (j = 0; j < i; j++)
	{
	  x--;
	  if (x > 1 && x < WORLD_SIDE_LEN - 2 && y > 1
	      && y < WORLD_SIDE_LEN - 2)
	    if (MP_TYPE(x,y) == CST_GREEN
		&& MP_TYPE(x + 1,y) == CST_GREEN
		&& MP_TYPE(x,y + 1) == CST_GREEN
		&& MP_TYPE(x + 1,y + 1) == CST_GREEN)
	      return (x + y * WORLD_SIDE_LEN);
	}
      for (j = 0; j < i; j++)
	{
	  y--;
	  if (x > 1 && x < WORLD_SIDE_LEN - 2 && y > 1
	      && y < WORLD_SIDE_LEN - 2)
	    if (MP_TYPE(x,y) == CST_GREEN
		&& MP_TYPE(x + 1,y) == CST_GREEN
		&& MP_TYPE(x,y + 1) == CST_GREEN
		&& MP_TYPE(x + 1,y + 1) == CST_GREEN)
	      return (x + y * WORLD_SIDE_LEN);
	}
      i++;
      for (j = 0; j < i; j++)
	{
	  x++;
	  if (x > 1 && x < WORLD_SIDE_LEN - 2 && y > 1
	      && y < WORLD_SIDE_LEN - 2)
	    if (MP_TYPE(x,y) == CST_GREEN
		&& MP_TYPE(x + 1,y) == CST_GREEN
		&& MP_TYPE(x,y + 1) == CST_GREEN
		&& MP_TYPE(x + 1,y + 1) == CST_GREEN)
	      return (x + y * WORLD_SIDE_LEN);
	}
      for (j = 0; j < i; j++)
	{
	  y++;
	  if (x > 1 && x < WORLD_SIDE_LEN - 2 && y > 1
	      && y < WORLD_SIDE_LEN - 2)
	    if (MP_TYPE(x,y) == CST_GREEN
		&& MP_TYPE(x + 1,y) == CST_GREEN
		&& MP_TYPE(x,y + 1) == CST_GREEN
		&& MP_TYPE(x + 1,y + 1) == CST_GREEN)
	      return (x + y * WORLD_SIDE_LEN);
	}
    }
  return (-1);
}
void
do_random_fire (int x, int y, int pwarning)	/* well random if x=y=-1 */
{
  int xx, yy;
  if (x == -1 && y == -1)
    {
      x = rand () % WORLD_SIDE_LEN;
      y = rand () % WORLD_SIDE_LEN;
    }
  else
    {
      if (x < 0 || x >= WORLD_SIDE_LEN || y < 0 || y >= WORLD_SIDE_LEN)
	return;
    }
  if (MP_TYPE(x,y) == CST_USED)
    {
      xx = MP_INFO(x,y).int_1;
      yy = MP_INFO(x,y).int_2;
      x = xx;
      y = yy;
    }
  xx = rand () % 100;
  if (xx >= (main_groups[MP_GROUP(x,y)].fire_chance))
    return;
  if ((MP_INFO(x,y).flags & FLAG_FIRE_COVER) != 0)
    return;
  if (pwarning)
    {
      if (MP_GROUP(x,y) == GROUP_POWER_LINE)
	ok_dial_box ("fire.mes", BAD, _("It's at a power line."));
      else if (MP_GROUP(x,y) == GROUP_SOLAR_POWER)
	ok_dial_box ("fire.mes", BAD, _("It's at a solar power station."));
      else if (MP_GROUP(x,y) == GROUP_SUBSTATION)
	ok_dial_box ("fire.mes", BAD, _("It's at a substation."));
      else if (MP_GROUP_IS_RESIDENCE(x,y))
	ok_dial_box ("fire.mes", BAD, _("It's at a residential area."));
      else if (MP_GROUP(x,y) == GROUP_ORGANIC_FARM)
	ok_dial_box ("fire.mes", BAD, _("It's at a farm."));
      else if (MP_GROUP(x,y) == GROUP_MARKET)
	ok_dial_box ("fire.mes", BAD, _("It's at a market."));
      else if (MP_GROUP(x,y) == GROUP_TRACK)
	ok_dial_box ("fire.mes", BAD, _("It's at a track."));
      else if (MP_GROUP(x,y) == GROUP_COALMINE)
	ok_dial_box ("fire.mes", BAD, _("It's at a coal mine."));
      else if (MP_GROUP(x,y) == GROUP_RAIL)
	ok_dial_box ("fire.mes", BAD, _("It's at a railway."));
      else if (MP_GROUP(x,y) == GROUP_COAL_POWER)
	ok_dial_box ("fire.mes", BAD, _("It's at a coal power station."));
      else if (MP_GROUP(x,y) == GROUP_ROAD)
	ok_dial_box ("fire.mes", BAD, _("It's at a road."));
      else if (MP_GROUP(x,y) == GROUP_INDUSTRY_L)
	ok_dial_box ("fire.mes", BAD, _("It's at light industry."));
      else if (MP_GROUP(x,y) == GROUP_UNIVERSITY)
	ok_dial_box ("fire.mes", BAD, _("It's at a university."));
      else if (MP_GROUP(x,y) == GROUP_COMMUNE)
	ok_dial_box ("fire.mes", BAD, _("It's at a commune."));
      else if (MP_GROUP(x,y) == GROUP_TIP)
	ok_dial_box ("fire.mes", BAD, _("It's at a tip."));
      else if (MP_GROUP(x,y) == GROUP_PORT)
	ok_dial_box ("fire.mes", BAD, _("It's at a port."));
      else if (MP_GROUP(x,y) == GROUP_INDUSTRY_H)
	ok_dial_box ("fire.mes", BAD, _("It's at a steel works."));
      else if (MP_GROUP(x,y) == GROUP_RECYCLE)
	ok_dial_box ("fire.mes", BAD, _("It's at a recycle centre."));
      else if (MP_GROUP(x,y) == GROUP_HEALTH)
	ok_dial_box ("fire.mes", BAD, _("It's at a health centre."));
      else if (MP_GROUP(x,y) == GROUP_ROCKET)
	ok_dial_box ("fire.mes", BAD, _("It's at a rocket site."));
      else if (MP_GROUP(x,y) == GROUP_WINDMILL)
	ok_dial_box ("fire.mes", BAD, _("It's at a windmill."));
      else if (MP_GROUP(x,y) == GROUP_SCHOOL)
	ok_dial_box ("fire.mes", BAD, _("It's at a school."));
      else if (MP_GROUP(x,y) == GROUP_BLACKSMITH)
	ok_dial_box ("fire.mes", BAD, _("It's at a blacksmith."));
      else if (MP_GROUP(x,y) == GROUP_MILL)
	ok_dial_box ("fire.mes", BAD, _("It's at a mill."));
      else if (MP_GROUP(x,y) == GROUP_POTTERY)
	ok_dial_box ("fire.mes", BAD, _("It's at a pottery."));
      else if (MP_GROUP(x,y) == GROUP_FIRESTATION)
	ok_dial_box ("fire.mes", BAD, _("It's at a fire station!!!."));
      else if (MP_GROUP(x,y) == GROUP_CRICKET)
	ok_dial_box ("fire.mes", BAD, _("It's at a cricket pitch!!!."));
      else if (MP_GROUP(x,y) == GROUP_SHANTY)
	ok_dial_box ("fire.mes", BAD, _("It's at a shanty town."));
      else
	ok_dial_box ("fire.mes", BAD, _("UNKNOWN!"));
    }
  fire_area (x, y);
}
int 
bulldoze_item (int x, int y)
{
    int g, size;

    if (MP_TYPE(x,y) == CST_USED) {
	/* This is considered "improper" input.  Silently ignore. */
#ifdef DEBUG
        fprintf(stderr," try to improperly bulldoze_item CST_USED\n");
#endif
	return -1;
    }

    size = MP_SIZE(x,y);
    g = MP_GROUP(x,y);
    people_pool += MP_INFO(x,y).population;

    if (g == GROUP_DESERT) {
	/* Nothing to do. */
	return -1;
    }
    else if (g == GROUP_SHANTY) {
	remove_a_shanty(x, y);
	adjust_money(-GROUP_SHANTY_BUL_COST);
        numof_shanties--;
    }
    else if (g == GROUP_FIRE) {
	if (MP_INFO(x,y).int_2 >= FIRE_LENGTH)
	    return -1;  /* Can't bulldoze ? */
	MP_INFO(x,y).int_2 = FIRE_LENGTH + 1;
	MP_TYPE(x,y) = CST_FIRE_DONE1;
	MP_GROUP(x,y) = GROUP_BURNT;
	adjust_money(-GROUP_BURNT_BUL_COST);
    }
    else {
	adjust_money(-main_groups[g].bul_cost);
         
        if (g == GROUP_COMMUNE)
             numof_communes--;

        if (g == GROUP_MARKET)
            remove_a_market (x, y);
 
        if (g == GROUP_SUBSTATION || g == GROUP_WINDMILL)
             remove_a_substation (x, y);
 
	if (g == GROUP_OREMINE)	{
	    int i, j;
	    for (j = 0; j < 4; j++)
		for (i = 0; i < 4; i++)
		    if (MP_INFO(x + i,y + j).ore_reserve < ORE_RESERVE / 2)
			do_bulldoze_area (CST_WATER, x + i, y + j);
	} else {
            /* keep compatibility for saving pre_waterwell loaded game */
            if (use_waterwell)
                do_bulldoze_area (CST_DESERT, x, y);
            else
                do_bulldoze_area (CST_GREEN, x, y);
        }
    }

    /* Tell mps about it, in case its selected */
    mps_update();
    return size;  /* No longer used... */
}