btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * $Id: mech.ice.c,v 1.1.1.1 2005/01/11 21:18:17 kstevens Exp $
 *
 * Author: Markus Stenberg <fingon@iki.fi>
 *
 *  Copyright (c) 1997 Markus Stenberg
 *  Copyright (c) 1998-2002 Thomas Wouters
 *  Copyright (c) 2000-2002 Cord Awtry
 *       All rights reserved
 *
 * Created: Thu Mar 20 20:29:14 1997 fingon
 * Last modified: Sat Jul 18 02:29:17 1998 fingon
 *
 */

#include "mech.h"
#include "mech.events.h"
#include "p.mech.update.h"
#include "p.bsuit.h"
#include "p.mech.utils.h"
#include "p.mech.pickup.h"
#include "p.mech.tag.h"

#define TMP_TERR '1'

static void swim_except(MAP * map, MECH * mech, int x, int y, char *msg,
    int isbridge)
{
    int i, j;
    MECH *t;

    if (!(Elevation(map, x, y)))
	return;
    for (i = 0; i < map->first_free; i++) {
	j = map->mechsOnMap[i];
	if (j < 0)
	    continue;
	t = getMech(j);
	if (!t || t == mech)
	    continue;
	if (MechX(t) != x || MechY(t) != y)
	    continue;
	MechTerrain(t) = WATER;
	if ((!isbridge && (MechZ(t) == 0) && (MechMove(t) != MOVE_HOVER)) ||
	    (isbridge && MechZ(t) == MechElev(t))) {
	    MechLOSBroadcast(t, msg);
	    MechFalls(t, MechElev(t) + isbridge, 0);
	    if (MechType(t) == CLASS_VEH_GROUND && !Destroyed(t)) {
		mech_notify(t, MECHALL,
			    "Water renders your vehicle inoperable.");
		MechLOSBroadcast(t,
			  "fizzles and pops as water renders it inoperable.");
		Destroy(t);
	    }
	}
    }
}

static void break_sub(MAP * map, MECH * mech, int x, int y, char *msg)
{
    int isbridge = GetRTerrain(map, x, y) == BRIDGE;

    SetTerrain(map, x, y, WATER);
    if (isbridge)
	SetElevation(map, x, y, 1);
    swim_except(map, mech, x, y, msg, isbridge);
}

/* Up -> down */
void drop_thru_ice(MECH * mech)
{
    MAP *map = FindObjectsData(mech->mapindex);

    mech_notify(mech, MECHALL, "You break the ice!");
    MechLOSBroadcast(mech, "breaks the ice!");
    if (MechMove(mech) != MOVE_FOIL) {
	if (MechElev(mech) > 0)
	    MechLOSBroadcast(mech, "vanishes into the waters!");
    }
    break_sub(map, mech, MechX(mech), MechY(mech), "goes swimming!");
    MechTerrain(mech) = WATER;
    if (MechMove(mech) != MOVE_FOIL) {
	if (MechElev(mech) > 0)
	    MechFalls(mech, MechElev(mech), 0);
    }
    if (MechElev(mech) > 0 && MechType(mech) == CLASS_VEH_GROUND &&
    	!Destroyed(mech)) {
	mech_notify(mech, MECHALL, "Water renders your vehicle inoperable.");
	MechLOSBroadcast(mech,
			 "fizzles and pops as water renders it inoperable.");
	Destroy(mech);
    }
}

/* Down -> up */
void break_thru_ice(MECH * mech)
{
    MAP *map = FindObjectsData(mech->mapindex);

    MarkForLOSUpdate(mech);
    mech_notify(mech, MECHALL, "You break through the ice!");
    MechLOSBroadcast(mech, "breaks through the ice!");
    break_sub(map, mech, MechX(mech), MechY(mech), "goes swimming!");
    MechTerrain(mech) = WATER;
}

/* CHANCE of dropping thru the ice based on 'mech weight */
int possibly_drop_thru_ice(MECH * mech)
{
    if ((MechMove(mech) == MOVE_HOVER) || (MechMove(mech) == MOVE_SUB) ||
	(MechType(mech) == CLASS_BSUIT))
	return 0;
    if (Number(1, 6) != 1)
	return 0;
    drop_thru_ice(mech);
    return 1;
}

static int watercount;

static void growable_callback(MAP *map, int x, int y)
{
    int terrain = GetRTerrain(map, x, y);
    if ((IsWater(terrain) && terrain != ICE) ||
        GetRTerrain(map, x, y) == TMP_TERR)
        watercount++;
}

int growable(MAP * map, int x, int y)
{
    watercount = 0;
    visit_neighbor_hexes(map, x, y, growable_callback);

    if (watercount <= 4 && (watercount < 2 || (Number(1, 6) > watercount)))
	return 1;
    return 0;
}

static void meltable_callback(MAP * map, int x, int y)
{
    if (GetRTerrain(map, x, y) == ICE)
    	watercount++;
}

int meltable(MAP * map, int x, int y)
{
    watercount = 0;
    visit_neighbor_hexes(map, x, y, meltable_callback);

    if (watercount > 4 && Number(1, 3) > 1)
	return 0;
    return 1;
}

void ice_growth(dbref player, MAP * map, int num)
{
    int x, y;
    int count = 0;

    for (x = 0; x < map->map_width; x++)
	for (y = 0; y < map->map_height; y++)
	    if (GetRTerrain(map, x, y) == WATER)
		if (Number(1, 100) <= num && growable(map, x, y)) {
		    SetTerrain(map, x, y, TMP_TERR);
		    count++;
		}
    for (x = 0; x < map->map_width; x++)
	for (y = 0; y < map->map_height; y++)
	    if (GetRTerrain(map, x, y) == TMP_TERR)
		SetTerrain(map, x, y, ICE);
    if (count)
	notify(player, tprintf("%d hexes 'iced'.", count));
    else
	notify(player, "No hexes 'iced'.");
}

void ice_melt(dbref player, MAP * map, int num)
{
    int x, y;
    int count = 0;

    for (x = 0; x < map->map_width; x++)
	for (y = 0; y < map->map_height; y++)
	    if (GetRTerrain(map, x, y) == ICE)
		if (Number(1, 100) <= num && meltable(map, x, y)) {
		    break_sub(map, NULL, x, y,
			"goes swimming as ice breaks!");
		    SetTerrain(map, x, y, TMP_TERR);
		    count++;
		}
    for (x = 0; x < map->map_width; x++)
	for (y = 0; y < map->map_height; y++)
	    if (GetRTerrain(map, x, y) == TMP_TERR)
		SetTerrain(map, x, y, WATER);
    if (count)
	notify(player, tprintf("%d hexes melted.", count));
    else
	notify(player, "No hexes melted.");
}


void map_addice(dbref player, MAP * map, char *buffer)
{
    char *args[2];
    int num;

    DOCHECK(mech_parseattributes(buffer, args, 2) != 1,
	"Invalid arguments!");
    DOCHECK(Readnum(num, args[0]), "Invalid number!");
    ice_growth(player, map, num);
}

void map_delice(dbref player, MAP * map, char *buffer)
{
    char *args[2];
    int num;

    DOCHECK(mech_parseattributes(buffer, args, 2) != 1,
	"Invalid arguments!");
    DOCHECK(Readnum(num, args[0]), "Invalid number!");
    ice_melt(player, map, num);
}

void possibly_blow_ice(MECH * mech, int weapindx, int x, int y)
{
    MAP *map = FindObjectsData(mech->mapindex);

    if (GetRTerrain(map, x, y) != ICE)
	return;
    if (Number(1, 15) > MechWeapons[weapindx].damage)
	return;
    HexLOSBroadcast(map, x, y, "The ice breaks from the blast!");
    break_sub(map, NULL, x, y, "goes swimming as ice breaks!");
}

void possibly_blow_bridge(MECH * mech, int weapindx, int x, int y)
{
    MAP *map = FindObjectsData(mech->mapindex);

    if (GetRTerrain(map, x, y) != BRIDGE)
	return;
    if (MapBridgesCS(map))
        return;
    if (Number(1, 10 * (1 + GetElev(map, x,
		    y))) > MechWeapons[weapindx].damage) {
	HexLOSBroadcast(map, x, y,
	    "The bridge at $H shudders from direct hit!");
	return;
    }
    HexLOSBroadcast(map, x, y, "The bridge at $H is blown apart!");
    break_sub(map, NULL, x, y,
	"goes swimming as the bridge is blown apart!");
}