/*
 * Copyright (C) 2002-2004, 2006-2007 by the Widelands Development Team
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
/*
The entire transport subsystem comes into this file.

What does _not_ belong in here: road renderer, client-side road building.

What _does_ belong in here:
Flags, Roads, the logic behind ware pulls and pushes.
*/

#include <cstdarg>
#include <stdio.h>
#include "cmd_queue.h"
#include "editor_game_base.h"
#include "error.h"
#include "fileread.h"
#include "filewrite.h"
#include "game.h"
#include "player.h"
#include "soldier.h"
#include "transport.h"
#include "tribe.h"
#include "warehouse.h"
#include "wexception.h"
#include "widelands_map_map_object_loader.h"
#include "widelands_map_map_object_saver.h"
#include "worker.h"

/*
==============================================================================

IdleWareSupply IMPLEMENTATION

==============================================================================
*/

/*
Whenever a WareInstance is idle, it issues an IdleWareSupply.
*/
class IdleWareSupply : public Supply {
public:
	IdleWareSupply(WareInstance* ware);
	virtual ~IdleWareSupply();

	void set_economy(Economy* e);

public: // implementation of Supply
	virtual PlayerImmovable* get_position(Game* g);
	virtual int get_amount(const int ware) const;
	virtual bool is_active() const throw ();

	virtual WareInstance* launch_item(Game* g, int ware);
	virtual Worker* launch_worker(Game* g, int ware) __attribute__ ((noreturn));

	virtual Soldier* launch_soldier(Game* g, int ware, Requeriments* req) __attribute__ ((noreturn));
	virtual int get_passing_requeriments (Game* g, int ware, Requeriments* r) __attribute__ ((noreturn));
	virtual void mark_as_used (Game* g, int ware, Requeriments* r);
private:
	WareInstance * m_ware;
	Economy      * m_economy;
};


/*
===============
IdleWareSupply::IdleWareSupply

Initialize the Supply and update the economy.
===============
*/
IdleWareSupply::IdleWareSupply(WareInstance* ware) : m_ware(ware), m_economy(0)
{set_economy(m_ware->get_economy());}


/*
===============
IdleWareSupply::~IdleWareSupply

Cleanup.
===============
*/
IdleWareSupply::~IdleWareSupply()
{
	set_economy(0);
}


/*
===============
IdleWareSupply::set_economy

Add/remove self from economies as necessary.
===============
*/
void IdleWareSupply::set_economy(Economy* e)
{
	if (e == m_economy)
		return;

	const Item_Ware_Descr::Index ware = m_ware->descr_index();

	if (m_economy)
		m_economy->remove_ware_supply(ware, this);

	m_economy = e;

	if (m_economy)
		m_economy->add_ware_supply(ware, this);
}


/*
===============
IdleWareSupply::get_position

Figure out the player immovable that this ware belongs to.
===============
*/
PlayerImmovable* IdleWareSupply::get_position(Game* g)
{
	Map_Object* loc = m_ware->get_location(g);

	if (loc->get_type() >= Map_Object::BUILDING)
		return (PlayerImmovable*)loc;

	if (loc->has_attribute(Map_Object::WORKER))
		return ((Worker*)loc)->get_location(g);

	return 0;
}


/*
===============
IdleWareSupply::get_amount
===============
*/
int IdleWareSupply::get_amount(const int ware) const
{return (ware == m_ware->descr_index()) ? 1 : 0;}


/*
===============
IdleWareSupply::is_active
===============
*/
bool IdleWareSupply::is_active()  const throw ()
{return not m_ware->is_moving();}


/*
===============
IdleWareSupply::launch_item

The item is already "launched", so we only need to return it.
===============
*/
WareInstance* IdleWareSupply::launch_item(Game *, int ware) {
	if (ware != m_ware->descr_index()) throw wexception
		("IdleWareSupply: ware(%u) (type = %i) requested for %i",
		 m_ware->get_serial(),
		 m_ware->descr_index(),
		 ware);

	return m_ware;
}


/*
===============
IdleWareSupply::launch_worker
===============
*/
Worker* IdleWareSupply::launch_worker(Game *, int)
{throw wexception("IdleWareSupply::launch_worker makes no sense");}


/*
===============
IdleWareSupply::launch_soldier
===============
*/
Soldier* IdleWareSupply::launch_soldier(Game *, int, Requeriments *)
{throw wexception("IdleWareSupply::launch_soldier makes no sense");}


/*
===============
IdleWareSupply::get_passing_requeriments
===============
*/
int IdleWareSupply::get_passing_requeriments(Game *, int, Requeriments *)
{throw wexception("IdleWareSupply::get_passing_requeriments makes no sense");}

/*
===============
IdleWareSupply::get_passing_requeriments
===============
*/
void IdleWareSupply::mark_as_used (Game *, int, Requeriments *) {
	// By now, wares have not need to have this method
}


/*
==============================================================================

WareInstance IMPLEMENTATION

==============================================================================
*/


/*
===============
WareInstance::WareInstance
===============
*/
WareInstance::WareInstance
(const Item_Ware_Descr::Index i, const Item_Ware_Descr * const ware_descr)
:
Map_Object   (ware_descr),
m_economy    (0),
m_descr_index(i),
m_ware_descr (ware_descr),
m_supply     (0),
m_transfer   (0)
{}


/*
===============
WareInstance::~WareInstance
===============
*/
WareInstance::~WareInstance()
{
	if (m_supply) {
		molog("Ware %u still has supply %p\n", m_descr_index, m_supply);
		delete m_supply;
	}
}


/*
===============
WareInstance::get_type
===============
*/
int WareInstance::get_type() const throw () {return WARE;}


/*
===============
WareInstance::init
===============
*/
void WareInstance::init(Editor_Game_Base* g)
{
	Map_Object::init(g);
}


/*
===============
WareInstance::cleanup
===============
*/
void WareInstance::cleanup(Editor_Game_Base* g)
{
	//molog("WareInstance::cleanup\n");

	Map_Object* location = m_location.get(g);

	// Unlink from our current location, if necessary
	if (location && location->get_type() == FLAG) {
		Flag* flag = (Flag*)location;

		flag->remove_item(g, this);
	}

		delete m_supply;
		m_supply = 0;

	if (Game * const game = dynamic_cast<Game * const>(g)) {
		cancel_moving();
		set_location(game, 0);
	}

	//molog("  done\n");

	Map_Object::cleanup(g);
}


/*
===============
WareInstance::set_economy

Ware accounting
===============
*/
void WareInstance::set_economy(Economy* e)
{
	if (m_economy == e)
		return;

	if (m_economy) m_economy->remove_wares(m_descr_index, 1);

	m_economy = e;
	if (m_supply)
		m_supply->set_economy(e);

	if (m_economy) m_economy->add_wares(m_descr_index, 1);
}


/*
===============
WareInstance::set_location

Change the current location.
Once you've assigned a ware to its new location, you usually have to call
update() as well.
===============
*/
void WareInstance::set_location(Editor_Game_Base* g, Map_Object* location)
{
	Map_Object* oldlocation = m_location.get(g);

	if (oldlocation == location)
		return;

	m_location = location;

	if (location)
	{
		Economy* eco = 0;

		if (location->get_type() >= BUILDING)
			eco = ((PlayerImmovable*)location)->get_economy();
		else if (location->has_attribute(WORKER))
			eco = ((Worker*)location)->get_economy();

		if (oldlocation && get_economy()) {
			if (get_economy() != eco)
				throw wexception("WareInstance::set_location() implies change of economy");
		} else {
			set_economy(eco);
		}
	}
	else
	{
		set_economy(0);
	}
}


/*
===============
WareInstance::act

Callback for the return-to-warehouse timer.
===============
*/
void WareInstance::act(Game *, uint) {}


/*
===============
WareInstance::update

Performs the state updates necessary for the current location:
- if it's a building, acknowledge the Request or incorporate into warehouse
- if it's a flag and we have no request, start the return to warehouse timer
  and issue a Supply

Note: update() may result in the deletion of this object.
===============
*/
void WareInstance::update(Game* g)
{
	Map_Object* loc = m_location.get(g);

   if(!m_ware_descr) // Upsy, we're not even intialized. Happens on load
      return;

	// Reset our state if we're not on location or outside an economy
	if (!loc || !get_economy()) {
		cancel_moving();
		return;
	}

	// Update whether we have a Supply or not
	if (!m_transfer || m_transfer->is_idle()) {
		if (!m_supply)
			m_supply = new IdleWareSupply(this);
	} else {
			delete m_supply;
			m_supply = 0;
	}

	// Deal with transfers
	if (m_transfer)
	{
		bool success;
		PlayerImmovable* location;
		PlayerImmovable* nextstep;

		if (loc->get_type() >= BUILDING)
			location = (PlayerImmovable*)loc;
		else
			return; // wait

		nextstep = m_transfer->get_next_step(location, &success);
		m_transfer_nextstep = nextstep;

		if (!nextstep) {
			Transfer* t = m_transfer;

			m_transfer = 0;

			if (success) {
				t->has_finished();
				return;
			} else {
				t->has_failed();

				cancel_moving();
				update(g);
				return;
			}
		}

		switch(location->get_type()) {
		case BUILDING:
			if (nextstep != location->get_base_flag())
				throw wexception("MO(%u): ware: move from building to non-baseflag", get_serial());

			// There are some situations where we might end up in a warehouse as
			// part of a requested route, and we need to move out of it again, e.g.:
			//  - we were requested just when we were being carried into the warehouse
			//  - we were carried into a harbour/warehouse to be shipped across the sea,
			//    but a better, land-based route has been found
			if (location->has_attribute(WAREHOUSE))
			{
				Warehouse* wh = (Warehouse*)location;

				wh->do_launch_item(g, this);
				return;
			}

			throw wexception("MO(%u): ware: can't move from building %u to %u (not a warehouse)",
							get_serial(), location->get_serial(), nextstep->get_serial());

		case FLAG:
			if (nextstep->get_type() == BUILDING && nextstep->get_base_flag() != location)
				((Flag*)location)->call_carrier(g, this, nextstep->get_base_flag());
			else
				((Flag*)location)->call_carrier(g, this, nextstep);
			break;
		}

		return;
	}
}


/*
===============
WareInstance::set_transfer

Set ware state so that it follows the given transfer.
===============
*/
void WareInstance::set_transfer(Game* g, Transfer* t)
{
	// Reset current transfer
	if (m_transfer) {
		m_transfer->has_failed();
		m_transfer = 0;
	}

	// Set transfer state
	m_transfer = t;

	update(g);
}


/*
===============
WareInstance::cancel_transfer

The transfer has been cancelled, just stop moving.
===============
*/
void WareInstance::cancel_transfer(Game* g)
{
	m_transfer = 0;

	update(g);
}



/*
===============
WareInstance::is_moving

We are moving when there's a transfer, it's that simple.
===============
*/
bool WareInstance::is_moving() const throw () {return m_transfer;}


/*
===============
WareInstance::cancel_moving

Call this function if movement + potential request need to be cancelled for
whatever reason.
===============
*/
void WareInstance::cancel_moving() {
	if (m_transfer) {
		m_transfer->has_failed();
		m_transfer = 0;
	}
}


/*
===============
WareInstance::get_next_move_step

Return the next flag we should be moving to, or the final target if the route
has been completed successfully.
===============
*/
PlayerImmovable* WareInstance::get_next_move_step(Game* g)
{
	if (m_transfer)
		return (PlayerImmovable*)m_transfer_nextstep.get(g);
	else
		return 0;
}



/*
==============================================================================

Flag IMPLEMENTATION

==============================================================================
*/

// dummy class because Map_Object needs a description
class Flag_Descr : public Map_Object_Descr {
public:
	Flag_Descr();
};

Flag_Descr::Flag_Descr()
{
}

Flag_Descr g_flag_descr;

/*
===============
Flag::Flag

Create the flag. Initially, it doesn't have any attachments.
===============
*/
Flag::Flag() :
PlayerImmovable(g_flag_descr),
m_anim(0),
m_building(0),
m_item_capacity(8),
m_item_filled(0),
m_items(new PendingItem[m_item_capacity]),
m_always_call_for_flag(0)
{for (uint i = 0; i < 6; ++i) m_roads[i] = 0;}


/*
===============
Flag::~Flag

Shouldn't be necessary to do anything, since die() always calls
cleanup() first.
===============
*/
Flag::~Flag()
{
	if (m_item_filled)
		log("Flag: ouch! items left\n");
	delete[] m_items;

	if (m_building)
		log("Flag: ouch! building left\n");

	if (m_flag_jobs.size())
		log("Flag: ouch! flagjobs left\n");

	for(int i = 0; i < 6; i++)
		if (m_roads[i])
			log("Flag: ouch! road left\n");
}

/*
===============
Flag::create [static]

Create a flag at the given location
===============
*/
Flag *Flag::create(Editor_Game_Base *g, Player *owner, Coords coords)
{
	Road *road = 0;
	BaseImmovable *imm = g->get_map()->get_immovable(coords);

	Flag *flag = new Flag();
	flag->set_owner(owner);
	flag->m_position = coords;

	if (imm && imm->get_type() == Map_Object::ROAD)
	{
		// we split a road
		road = (Road*)imm;
		road->get_economy()->add_flag(flag);
	}
	else
	{
		// a new, standalone flag is created
		(new Economy(owner))->add_flag(flag);
	}

	if (road)
		road->presplit(g, coords);
	flag->init(g);
	if (road)
		road->postsplit(g, flag);
	return flag;
}


/*
===============
Flag::get_type
Flag::get_size
Flag::get_passable
Flag::get_base_flag
===============
*/
int Flag::get_type() const throw () {return FLAG;}

int Flag::get_size() const throw () {return SMALL;}

bool Flag::get_passable() const throw () {return true;}

Flag *Flag::get_base_flag()
{
	return this;
}


/*
===============
Flag::set_economy

Call this only from Economy code!
===============
*/
void Flag::set_economy(Economy *e)
{
	Economy *old = get_economy();

	if (old == e)
		return;

	PlayerImmovable::set_economy(e);

	for(int i = 0; i < m_item_filled; i++)
		m_items[i].item->set_economy(e);

	if (m_building)
		m_building->set_economy(e);

	for(std::list<FlagJob>::const_iterator it = m_flag_jobs.begin(); it != m_flag_jobs.end(); ++it)
		it->request->set_economy(e);

	for(int i = 0; i < 6; i++) {
		if (m_roads[i])
			m_roads[i]->set_economy(e);
	}
}

/*
===============
Flag::attach_building

Call this only from the Building init!
===============
*/
void Flag::attach_building(Editor_Game_Base *g, Building *building)
{
	assert(!m_building || m_building==building);

	m_building = building;

	Map *map = g->get_map();
	Coords tln;

	map->get_tln(m_position, &tln);
	map->get_field(tln)->set_road(Road_SouthEast, Road_Normal);

	m_building->set_economy(get_economy());
}


/*
===============
Flag::detach_building

Call this only from the Building cleanup!
===============
*/
void Flag::detach_building(Editor_Game_Base *g)
{
	assert(m_building);

	m_building->set_economy(0);

	Map *map = g->get_map();
	Coords tln;

	map->get_tln(m_position, &tln);
	map->get_field(tln)->set_road(Road_SouthEast, Road_None);

	m_building = 0;
}


/*
===============
Flag::attach_road

Call this only from the Road init!
===============
*/
void Flag::attach_road(int dir, Road *road)
{
   assert(!m_roads[dir-1] || m_roads[dir-1]==road);

	m_roads[dir-1] = road;
	m_roads[dir-1]->set_economy(get_economy());
}


/*
===============
Flag::detach_road

Call this only from the Road init!
===============
*/
void Flag::detach_road(int dir)
{
	assert(m_roads[dir-1]);

	m_roads[dir-1]->set_economy(0);
	m_roads[dir-1] = 0;
}


/*
===============
Flag::get_neighbours

Return neighbouring flags.
===============
*/
void Flag::get_neighbours(Neighbour_list *neighbours)
{
	for(int i = 0; i < 6; i++) {
		Road *road = m_roads[i];
		if (!road)
			continue;

		Neighbour n;
		n.road = road;
		n.flag = road->get_flag(Road::FlagEnd);
		if (n.flag != this)
			n.cost = road->get_cost(Road::FlagStart);
		else {
			n.flag = road->get_flag(Road::FlagStart);
			n.cost = road->get_cost(Road::FlagEnd);
		}

		assert(n.flag != this);
		neighbours->push_back(n);
	}

	// I guess this would be the place to add other ports if a port building
	// is attached to this flag
	// Or maybe other hosts of a carrier pigeon service, or a wormhole connection
	// point or whatever ;)
}

/*
===============
Flag::get_road

Return the road that leads to the given flag.
===============
*/
Road *Flag::get_road(Flag *flag)
{
	for(int i = 0; i < 6; i++) {
		Road *road = m_roads[i];
		if (!road)
			continue;

		if (road->get_flag(Road::FlagStart) == flag || road->get_flag(Road::FlagEnd) == flag)
			return road;
	}

	return 0;
}


/*
===============
Flag::has_capacity

Returns true if the flag can hold more items.
===============
*/
bool Flag::has_capacity()
{
	return (m_item_filled < m_item_capacity);
}


/*
===============
Flag::wait_for_capacity

Signal the given bob by interrupting its task as soon as capacity becomes free.
===============
*/
void Flag::wait_for_capacity(Game *, Worker* bob)
{m_capacity_wait.push_back(bob);}


/*
===============
Flag::add_item
===============
*/
void Flag::add_item(Game* g, WareInstance* item)
{
	PendingItem* pi;

	assert(m_item_filled < m_item_capacity);

	pi = &m_items[m_item_filled++];
	pi->item = item;
	pi->pending = false;
	pi->nextstep = 0;

	item->set_location(g, this);
	item->update(g); // will call call_carrier() if necessary
}


/*
===============
Flag::has_pending_item

Returns true if an item is currently waiting for a carrier to the given Flag.

Note: Due to fetch_from_flag() semantics, this function makes no sense for a
      building destination.
===============
*/
bool Flag::has_pending_item(Game *, Flag * dest) {
	int i;

	for(i = 0; i < m_item_filled; i++) {
		if (!m_items[i].pending)
			continue;

		if (m_items[i].nextstep != dest)
			continue;

		return true;
	}

	return false;
}


/*
===============
Flag::ack_pending_item

Called by carrier code to indicate that the carrier is moving to pick up an
item.
Returns true if an item is actually waiting for the carrier.
===============
*/
bool Flag::ack_pending_item(Game *, Flag * destflag) {
	int i;

	for(i = 0; i < m_item_filled; i++) {
		if (!m_items[i].pending)
			continue;

		if (m_items[i].nextstep != destflag)
			continue;

		m_items[i].pending = false;
		return true;
	}

	return false;
}


/*
===============
Flag::wake_up_capacity_queue

Wake one sleeper from the capacity queue.
===============
*/
void Flag::wake_up_capacity_queue(Game* g)
{
	while(m_capacity_wait.size()) {
		Worker* w = (Worker*)m_capacity_wait[0].get(g);

		m_capacity_wait.erase(m_capacity_wait.begin());

		if (!w)
			continue;

		molog("Flag: wake up one from wait queue.\n");

		if (w->wakeup_flag_capacity(g, this))
			break;
	}
}


/*
===============
Flag::fetch_pending_item

Called by carrier code to retrieve one of the items on the flag that is meant
for that carrier.
This function may return 0 even if ack_pending_item() has already been called
successfully.
===============
*/
WareInstance* Flag::fetch_pending_item(Game* g, PlayerImmovable* dest)
{
	WareInstance* item;
	int best_index = -1;

	for(int i = 0; i < m_item_filled; i++) {
		if (m_items[i].nextstep != dest)
			continue;

		// We prefer to retrieve items that have already been acked
		if (best_index < 0 || !m_items[i].pending)
			best_index = i;
	}

	if (best_index < 0)
		return 0;

	// move the other items up the list and return this one
	item = m_items[best_index].item;
	m_item_filled--;
	memmove(&m_items[best_index], &m_items[best_index+1], sizeof(m_items[0]) * (m_item_filled - best_index));

	item->set_location(g, 0);

	// wake up capacity wait queue
	wake_up_capacity_queue(g);

	return item;
}


/*
===============
Flag::remove_item

Force a removal of the given item from this flag.
Called by WareInstance::cleanup()
===============
*/
void Flag::remove_item(Editor_Game_Base* g, WareInstance* item)
{
	for(int i = 0; i < m_item_filled; i++) {
		if (m_items[i].item != item)
			continue;

		m_item_filled--;
		memmove(&m_items[i], &m_items[i+1], sizeof(m_items[0]) * (m_item_filled - i));

		Game * const game = dynamic_cast<Game * const>(g);
		if (game) wake_up_capacity_queue(game);

		return;
	}

	throw wexception("MO(%u): Flag::remove_item: item %u not on flag",
	                 get_serial(), item->get_serial());
}


/*
===============
Flag::call_carrier

If nextstep is not null, a carrier will be called to move this item to
the given flag or building.
If nextstep is null, the internal data will be reset to indicate that the
item isn't going anywhere right now.

nextstep is compared with the cached data, and a new carrier is only called
if that data hasn't changed.
This behaviour is overriden by m_always_call_for_step, which is set by
update_items() to ensure that new carriers are called when roads are split,
for example.
===============
*/
void Flag::call_carrier(Game* g, WareInstance* item, PlayerImmovable* nextstep)
{
	PendingItem* pi = 0;
	int i;

	// Find the PendingItem entry
	for(i = 0; i < m_item_filled; i++) {
		if (m_items[i].item != item)
			continue;

		pi = &m_items[i];
		break;
	}

	assert(pi);

	// Deal with the non-moving case quickly
	if (!nextstep) {
		pi->nextstep = 0;
		pi->pending = false;
		return;
	}

	// Find out whether we need to do anything
	if (pi->nextstep == nextstep && pi->nextstep != m_always_call_for_flag)
		return; // no update needed

	pi->nextstep = nextstep;
	pi->pending = false;

	// Deal with the building case
	if (nextstep == get_building())
	{
		molog("Flag::call_carrier(%u): Tell building to fetch this item\n", item->get_serial());

		if (!get_building()->fetch_from_flag(g)) {
			pi->item->cancel_moving();
			pi->item->update(g);
		}

		return;
	}

	// Deal with the normal (flag) case
	assert(nextstep->get_type() == FLAG);

	for(int dir = 1; dir <= 6; dir++) {
		Road* road = get_road(dir);
		Flag* other;
		Road::FlagId flagid;

		if (!road)
			continue;

		if (road->get_flag(Road::FlagStart) == this) {
			flagid = Road::FlagStart;
			other = road->get_flag(Road::FlagEnd);
		} else {
			flagid = Road::FlagEnd;
			other = road->get_flag(Road::FlagStart);
		}

		if (other != nextstep)
			continue;

		// Yes, this is the road we want; inform it
		if (road->notify_ware(g, flagid))
			return;

		// If the road doesn't react to the ware immediately, we try other roads:
		// They might lead to the same flag!
	}

	// Nothing found, just let it be picked up by somebody
	pi->pending = true;
	return;
}


/*
===============
Flag::update_items

Called whenever a road gets broken or split.
Make sure all items on this flag are rerouted if necessary.

Note: When two roads connect the same two flags, and one of these roads
      is removed, this might cause the carrier(s) on the other road to
		move unnecessarily. Fixing this could potentially be very expensive and
		fragile.
		A similar thing can happen when a road is split.
===============
*/
void Flag::update_items(Game* g, Flag* other)
{
	m_always_call_for_flag = other;

	for(int i = 0; i < m_item_filled; i++)
		m_items[i].item->update(g);

	m_always_call_for_flag = 0;
}


/*
===============
Flag::init
===============
*/
void Flag::init(Editor_Game_Base *g)
{
	PlayerImmovable::init(g);

	set_position(g, m_position);

	m_anim = owner().tribe().get_flag_anim();
	m_animstart = g->get_gametime();
}

/*
===============
Flag::cleanup

Detach building and free roads.
===============
*/
void Flag::cleanup(Editor_Game_Base *g)
{
	//molog("Flag::cleanup\n");

	while(m_flag_jobs.size()) {
		delete m_flag_jobs.begin()->request;
		m_flag_jobs.erase(m_flag_jobs.begin());
	}

	while(m_item_filled) {
		WareInstance* item = m_items[--m_item_filled].item;

		item->set_location((Game*)g, 0);
		item->destroy((Game*)g);
	}

	//molog("  items destroyed\n");

	if (m_building) {
		m_building->remove(g); // immediate death
		assert(!m_building);
	}

	for(int i = 0; i < 6; i++) {
		if (m_roads[i]) {
			m_roads[i]->remove(g); // immediate death
			assert(!m_roads[i]);
		}
	}

	get_economy()->remove_flag(this);

	unset_position(g, m_position);

	//molog("  done\n");

	PlayerImmovable::cleanup(g);
}


/*
===============
Flag::destroy

Destroy the building as well.

Note that this is needed in addition to the call to m_building->remove() in
Flag::cleanup(). This function is needed to ensure a fire is created when a
player removes a flag.
===============
*/
void Flag::destroy(Editor_Game_Base* g)
{
	if (m_building) {
		m_building->destroy(g);
		assert(!m_building);
	}

	PlayerImmovable::destroy(g);
}


/*
==============
Flag::add_flag_job

Add a new flag job to request the worker with the given ID, and to execute
the given program once it's completed.
==============
*/
void Flag::add_flag_job(Game *, int workerware, std::string programname) {
	FlagJob j;

	j.request = new Request(this, workerware,
	                        &Flag::flag_job_request_callback, this, Request::WORKER);
	j.program = programname;

	m_flag_jobs.push_back(j);
}


/*
==============
Flag::flag_job_request_callback [static]

This function is called when one of the flag job workers arrives on
the flag. Give him his job.
==============
*/
void Flag::flag_job_request_callback
(Game *, Request * rq, int, Worker * w, void * data)
{
	Flag* flag = (Flag*)data;

	assert(w);

	for(std::list<FlagJob>::iterator it = flag->m_flag_jobs.begin(); it != flag->m_flag_jobs.end(); ++it) {
		if (it->request != rq)
			continue;

		delete rq;

		w->start_task_program(it->program);

		flag->m_flag_jobs.erase(it);
		return;
	}

	flag->molog("BUG: flag_job_request_callback: worker not found in list\n");
}


/*
==============================================================================

Road IMPLEMENTATION

==============================================================================
*/

// dummy class because Map_Object needs a description
class Road_Descr : public Map_Object_Descr {
public:
	Road_Descr();
};

Road_Descr::Road_Descr()
{
}

Road_Descr g_road_descr;


/*
===============
Road::Road
Road::~Road

Construction and destruction. Most of the actual work is done in init/cleanup.
===============
*/
Road::Road() :
PlayerImmovable  (g_road_descr),
m_type           (0),
m_desire_carriers(0),
m_carrier_request(0)
{
	m_flags[0] = m_flags[1] = 0;
	m_flagidx[0] = m_flagidx[1] = -1;
}

Road::~Road()
{
	if (m_carrier_request) {
		log("Road::~Road: carrier request left\n");
		delete m_carrier_request;
	}
}


/*
===============
Road::create [static]

Create a road between the given flags, using the given path.
===============
*/
Road *Road::create(Editor_Game_Base *g, int type, Flag *start, Flag *end, const Path &path)
{
	assert(start->get_position() == path.get_start());
	assert(end->get_position() == path.get_end());

	Road *r = new Road();
	r->set_owner(start->get_owner());
	r->m_type = type;
	r->m_flags[FlagStart] = start;
	r->m_flags[FlagEnd] = end;
	// m_flagidx is set when attach_road() is called, i.e. in init()
	r->set_path(g, path);
	r->init(g);

	return r;
}

/*
===============
Road::get_type
Road::get_size
Road::get_passable
Road::get_base_flag
===============
*/
int Road::get_type() const throw () {return ROAD;}

int Road::get_size() const throw () {return SMALL;}

bool Road::get_passable() const throw () {return true;}

Flag *Road::get_base_flag()
{
	return m_flags[FlagStart];
}


/*
===============
Road::get_cost

Return the cost of getting from fromflag to the other flag.
===============
*/
int Road::get_cost(FlagId fromflag)
{
	return m_cost[fromflag];
}


/*
===============
Road::set_path

Set the new path, calculate costs.
You have to set start and end flags before calling this function.
===============
*/
void Road::set_path(Editor_Game_Base *g, const Path &path)
{
	assert(path.get_nsteps() >= 2);
	assert(path.get_start() == m_flags[FlagStart]->get_position());
	assert(path.get_end() == m_flags[FlagEnd]->get_position());

	m_path = path;
	g->get_map()->calc_cost(path, &m_cost[FlagStart], &m_cost[FlagEnd]);

	// Figure out where carriers should idle
	m_idle_index = path.get_nsteps() / 2;
}


/*
===============
Road::mark_map

Add road markings to the map
===============
*/
void Road::mark_map(Editor_Game_Base *g)
{
	Map *map = g->get_map();
	FCoords curf(m_path.get_start(), map->get_field(m_path.get_start()));

	const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
	for (Path::Step_Vector::size_type steps = 0; steps <= nr_steps; ++steps) {
		if (steps > 0 && steps < m_path.get_nsteps())
			set_position(g, curf);

		// mark the road that leads up to this field
		if (steps > 0) {
			const Direction dir  = get_reverse_dir(m_path[steps - 1]);
			const Direction rdir = 2 * (dir - Map_Object::WALK_E);

			if (rdir >= 0 && rdir <= 4)
				curf.field->set_road(rdir, m_type);
		}

		// mark the road that leads away from this field
		if (steps < m_path.get_nsteps()) {
			const Direction dir  = m_path[steps];
			const Direction rdir = 2 * (dir - Map_Object::WALK_E);

			if (rdir >= 0 && rdir <= 4)
				curf.field->set_road(rdir, m_type);

			map->get_neighbour(curf, dir, &curf);
		}
	}
}

/*
===============
Road::unmark_map

Remove road markings from the map
===============
*/
void Road::unmark_map(Editor_Game_Base *g)
{
	Map *map = g->get_map();
	FCoords curf(m_path.get_start(), map->get_field(m_path.get_start()));

	const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
	for (Path::Step_Vector::size_type steps = 0; steps <= nr_steps; ++steps) {
		if (steps > 0 && steps < m_path.get_nsteps())
			unset_position(g, curf);

		// mark the road that leads up to this field
		if (steps > 0) {
			const Direction dir  = get_reverse_dir(m_path[steps - 1]);
			const Direction rdir = 2 * (dir - Map_Object::WALK_E);

			if (rdir >= 0 && rdir <= 4)
				curf.field->set_road(rdir, Road_None);
		}

		// mark the road that leads away from this field
		if (steps < m_path.get_nsteps()) {
			const Direction  dir = m_path[steps];
			const Direction rdir = 2 * (dir - Map_Object::WALK_E);

			if (rdir >= 0 && rdir <= 4)
				curf.field->set_road(rdir, Road_None);

			map->get_neighbour(curf, dir, &curf);
		}
	}
}

/*
===============
Road::init

Initialize the road.
===============
*/
void Road::init(Editor_Game_Base *gg)
{
   PlayerImmovable::init(gg);

   if(m_path.get_nsteps() >=2 ) {
      link_into_flags(gg);
   }

}

/*
 * This links into the flags, calls a carrier
 * and so on. This was formerly done in init (and
 * still is for normal games). But for save game loading
 * we needed to have this road already registered
 * as Map Object, thats why this is moved
 */
void Road::link_into_flags(Editor_Game_Base* gg) {
   assert(m_path.get_nsteps() >= 2);

	// Link into the flags (this will also set our economy)

	{
		const Direction dir = m_path[0];
	m_flags[FlagStart]->attach_road(dir, this);
	m_flagidx[FlagStart] = dir;
	}


	const Direction dir =
		get_reverse_dir(m_path[m_path.get_nsteps() - 1]);
	m_flags[FlagEnd]->attach_road(dir, this);
	m_flagidx[FlagEnd] = dir;

	Economy::check_merge(m_flags[FlagStart], m_flags[FlagEnd]);

	// Mark Fields
	mark_map(gg);

	if (Game * const game = dynamic_cast<Game * const>(gg)) {
		Carrier * const carrier =
			static_cast<Carrier * const>(m_carrier.get(game));
      m_desire_carriers = 1;
		if (not carrier) {if (not m_carrier_request) request_carrier(game);}
		else {
         // This happens after a road split. Tell the carrier what's going on
         carrier->set_location(this);
         carrier->update_task_road(game);
      }
   }
}


/*
===============
Road::cleanup

Cleanup the road
===============
*/
void Road::cleanup(Editor_Game_Base *gg)
{
	Game* g = static_cast<Game*>(gg);

	// Release carrier
	m_desire_carriers = 0;

		delete m_carrier_request;
		m_carrier_request = 0;

	m_carrier = 0; // carrier will be released via PlayerImmovable::cleanup

	// Unmark Fields
	unmark_map(g);

	// Unlink from flags (also clears the economy)
	m_flags[FlagStart]->detach_road(m_flagidx[FlagStart]);
	m_flags[FlagEnd]->detach_road(m_flagidx[FlagEnd]);

	Economy::check_split(m_flags[FlagStart], m_flags[FlagEnd]);

	m_flags[FlagStart]->update_items(g, m_flags[FlagEnd]);
	m_flags[FlagEnd]->update_items(g, m_flags[FlagStart]);

	PlayerImmovable::cleanup(g);
}


/*
===============
Road::set_economy

Workers' economies are fixed by PlayerImmovable, but we need to handle
any requests ourselves.
===============
*/
void Road::set_economy(Economy *e)
{
	PlayerImmovable::set_economy(e);
	if (m_carrier_request)
		m_carrier_request->set_economy(e);
}


/*
===============
Road::request_carrier

Request a new carrier.
Only call this if the road can handle a new carrier, and if no request has been
issued.
===============
*/
void Road::request_carrier(Game * g) {
	assert(!m_carrier.get(g) && !m_carrier_request);

	m_carrier_request = new Request(this, get_owner()->get_tribe()->get_safe_worker_index("carrier"),
	                                &Road::request_carrier_callback, this, Request::WORKER);
}


/*
===============
Road::request_carrier_callback [static]

The carrier has arrived successfully.
===============
*/
void Road::request_carrier_callback
(Game *, Request * rq, int, Worker * w, void * data)
{
	assert(w);

	Road* road = (Road*)data;
	Carrier* carrier = (Carrier*)w;

	delete rq;
	road->m_carrier_request = 0;

	road->m_carrier = carrier;
	carrier->start_task_road();
}


/*
===============
Road::remove_worker

If we lost our carrier, re-request it.
===============
*/
void Road::remove_worker(Worker *w)
{
	Editor_Game_Base & egbase = owner().egbase();
	Carrier* carrier = dynamic_cast<Carrier * const>(m_carrier.get(&egbase));

	if (carrier == w)
		m_carrier = carrier = 0;

	Game * const game = dynamic_cast<Game * const>(&egbase);
	if (not carrier and not m_carrier_request and m_desire_carriers and game)
		request_carrier(game);

	PlayerImmovable::remove_worker(w);
}


/*
===============
Road::presplit

A flag has been placed that splits this road. This function is called before
the new flag initializes. We remove markings to avoid interference with the
flag.
===============
*/
void Road::presplit(Editor_Game_Base * g, Coords) {unmark_map(g);}


/*
===============
Road::postsplit

The flag that splits this road has been initialized. Perform the actual
splitting.
After the split, this road will span [start...new flag]. A new road will
be created to span [new flag...end]
===============
*/
void Road::postsplit(Editor_Game_Base *g, Flag *flag)
{
   Flag *oldend = m_flags[FlagEnd];

   // detach from end
   m_flags[FlagEnd]->detach_road(m_flagidx[FlagEnd]);

   // build our new path and the new road's path
	CoordPath path(g->map(), m_path);
   CoordPath secondpath(path);
   int index = path.get_index(flag->get_position());

	assert(index > 0);
	assert(static_cast<const uint>(index) < path.get_nsteps() - 1);

   path.truncate(index);
   secondpath.starttrim(index);

   // change road size and reattach
   m_flags[FlagEnd] = flag;
   set_path(g, path);

	const Direction dir = get_reverse_dir(m_path[m_path.get_nsteps() - 1]);
   m_flags[FlagEnd]->attach_road(dir, this);
   m_flagidx[FlagEnd] = dir;

   // recreate road markings
   mark_map(g);

   // create the new road
   Road *newroad = new Road();
   newroad->set_owner(get_owner());
   newroad->m_type = m_type;
   newroad->m_flags[FlagStart] = flag; // flagidx will be set on init()
   newroad->m_flags[FlagEnd] = oldend;
   newroad->set_path(g, secondpath);

   // Find workers on this road that need to be reassigned
   // The algorithm is pretty simplistic, and has a bias towards keeping
   // the worker around; there's obviously nothing wrong with that.
   Carrier *carrier = (Carrier *)m_carrier.get(g);
   const std::vector<Worker*> workers = get_workers();
   std::vector<Worker*> reassigned_workers;

   for(std::vector<Worker*>::const_iterator it = workers.begin(); it != workers.end(); ++it) {
      Worker* w = *it;
      int idx = path.get_index(w->get_position());

      // Careful! If the worker is currently inside the building at our
      // starting flag, we *must not* reassign him.
      // If he is in the building at our end flag or at the other road's
      // end flag, he can be reassigned to the other road.
      if (idx < 0)
      {
         Map* map = g->get_map();
         BaseImmovable* imm = map->get_immovable(w->get_position());

         if (imm && imm->get_type() == BUILDING) {
            Coords pos;

            g->get_map()->get_brn(w->get_position(), &pos);

            if (pos == path.get_start())
               idx = 0;
         }
      }

      molog("Split: check %u -> idx %i\n", w->get_serial(), idx);

      if (idx < 0)
      {
         reassigned_workers.push_back(w);

         if (carrier == w) {
            // Reassign the carrier. Note that the final steps of reassigning
            // are done in newroad->init()
            m_carrier = 0;
            newroad->m_carrier = carrier;
         }
      }

      // Cause a worker update in any case
	   Game * const game = dynamic_cast<Game * const>(g);
	   if (game) w->send_signal(game, "road");
   }

   // Initialize the new road
   newroad->init(g);

   // Actually reassign workers after the new road has initialized,
   // so that the reassignment is safe
   for(std::vector<Worker*>::const_iterator it = reassigned_workers.begin(); it != reassigned_workers.end(); ++it)
      (*it)->set_location(newroad);

   // Do the following only if in game
	Game * const game = dynamic_cast<Game * const>(g);
	if (game) {

      // Request a new carrier for this road if necessary
      // This must be done _after_ the new road initializes, otherwise request
      // routing might not work correctly
      if (!m_carrier.get(g) && !m_carrier_request)
         request_carrier(game);

      // Make sure items waiting on the original endpoint flags are dealt with
      m_flags[FlagStart]->update_items(static_cast<Game*>(g), oldend);
      oldend->update_items(game, m_flags[FlagStart]);
   }
}


/*
===============
Road::notify_ware

Called by Flag code: an item should be picked up from the given flag.
Return true if a carrier has been sent on its way, or false otherwise.
===============
*/
bool Road::notify_ware(Game* g, FlagId flagid)
{
	Carrier* carrier = (Carrier*)m_carrier.get(g);

	if (!carrier)
		return false;

	return carrier->notify_ware(g, flagid);
}


/*
==============================================================================

Route IMPLEMENTATION

==============================================================================
*/

/*
===============
Route::Route

Set sane defaults
===============
*/
Route::Route()
{
	m_totalcost = 0;
}

/*
===============
Route::clear

Completely clear the route
===============
*/
void Route::clear()
{
	m_totalcost = 0;
	m_route.clear();
}


/*
===============
Route::get_flag

Return the flag with the given number.
idx == 0 is the start flag, idx == get_nrsteps() is the end flag.
Every route has at least one flag.
===============
*/
Flag * Route::get_flag
(Editor_Game_Base * const g, const std::vector<Flag *>::size_type idx) const
{
	assert(idx < m_route.size());
	return (Flag*)m_route[idx].get(g);
}

/*
===============
Route::starttrim

Remove the first count steps from the route.
===============
*/
void Route::starttrim(int count)
{
	assert(count < (int)m_route.size());

	m_route.erase(m_route.begin(), m_route.begin()+count);
}


/*
===============
Route::truncate

Keep the first count steps, truncate the rest.
===============
*/
void Route::truncate(int count)
{
	assert(count < (int)m_route.size());

	m_route.erase(m_route.begin()+count+1, m_route.end());
}


/*
==============================================================================

Transfer IMPLEMENTATION

==============================================================================
*/


/*
===============
Transfer::Transfer

Start the transfer
===============
*/
Transfer::Transfer(Game* g, Request* req, WareInstance* it)
{
	m_game = g;
	m_request = req;
	m_item = it;
	m_worker = 0;
	m_soldier = 0;

	m_idle = false;

	m_item->set_transfer(g, this);
}

Transfer::Transfer(Game* g, Request* req, Worker* w)
{
	m_game = g;
	m_request = req;
	m_worker = w;
	m_item = 0;
	m_soldier = 0;

	m_idle = false;

	m_worker->start_task_transfer(g, this);
}


Transfer::Transfer(Game* g, Request* req, Soldier* s)
{
	m_game = g;
	m_request = req;
	m_soldier = s;
	m_worker = 0;
	m_item = 0;

	m_idle = false;

	m_soldier->start_task_transfer(g, this);
}

/*
===============
Transfer::~Transfer

Cleanup.
===============
*/
Transfer::~Transfer()
{
	if (m_worker)
	{
		assert(!m_item);
		assert(!m_soldier);

      if(m_game->get_objects()->object_still_available(m_worker))
         m_worker->cancel_task_transfer(m_game);
	}
	else if (m_item)
	{
		assert(!m_soldier);
		if(m_game->get_objects()->object_still_available(m_item))
			m_item->cancel_transfer(m_game);
	}
	else if (m_soldier)
	{
		if(m_game->get_objects()->object_still_available(m_soldier))
			m_soldier->cancel_task_transfer(m_game);
	}
}


/*
===============
Transfer::set_idle

An idle transfer can be fail()ed by the controlled item whenever a better
Request is available.
===============
*/
void Transfer::set_idle(bool idle)
{
	m_idle = idle;
}


/*
===============
Transfer::get_next_step

Determine where we should be going from our current location.
===============
*/
PlayerImmovable* Transfer::get_next_step(PlayerImmovable* location, bool* psuccess)
{
	PlayerImmovable * const destination = m_request->get_target();
	Flag* locflag;
	Flag* destflag;

	// Catch the simplest cases
	if (location->get_economy() !=
         destination->get_economy()) {
		tlog("Economy mismatch -> fail\n");

		*psuccess = false;
		return 0;
	}

	*psuccess = true;

	if (location == destination) {
		tlog("location == destination\n");
		return 0;
	}

	locflag = location->get_base_flag();
	destflag = destination->get_base_flag();

	if (locflag == destflag) {
		tlog("location flag == destination flag\n");

		if (locflag == location)
			return destination;

		return locflag;
	}

	// Brute force: recalculate the best route every time
	if (!locflag->get_economy()->find_route(locflag, destflag, &m_route))
		throw wexception("Transfer::get_next_step: inconsistent economy");

	if (m_route.get_nrsteps() >= 1 && location->get_type() == Map_Object::ROAD) {
		Road* road = (Road*)location;
		Flag* oflag = m_route.get_flag(m_game, 1);

		if (road->get_flag(Road::FlagEnd) == oflag) {
			tlog("trim start flag (road)\n");
			m_route.starttrim(1);
		}
	}

	if (m_route.get_nrsteps() >= 1 && destination->get_type() == Map_Object::ROAD) {
		Road* road = (Road*)destination;
		Flag* oflag = m_route.get_flag(m_game, m_route.get_nrsteps()-1);

		if (road->get_flag(Road::FlagEnd) == oflag) {
			tlog("trim end flag (road)\n");
			m_route.truncate(m_route.get_nrsteps()-1);
		}
	}

	// Now decide where we want to go
	if (location->get_type() == Map_Object::FLAG) {
		assert(m_route.get_flag(m_game, 0) == location);

		// special rule to get items into buildings
		if (m_item) {
			if (m_route.get_nrsteps() == 1 && destination->get_type() == Map_Object::BUILDING) {
				assert(m_route.get_flag(m_game, 1) == destination->get_base_flag());

				return destination;
			}
		}

		if (m_route.get_nrsteps() >= 1) {
			return m_route.get_flag(m_game, 1);
		}

		tlog("move from flag to destination\n");
		return destination;
	}

	tlog("move to first flag\n");
	return m_route.get_flag(m_game, 0);
}


/**
 * Transfer finished successfully.
 * This Transfer object will be deleted indirectly by finish().
 * The caller might be destroyed, too.
 */
void Transfer::has_finished()
{
   m_request->transfer_finish(m_game, this);
}


/*
===============
Transfer::fail

Transfer failed for reasons beyond our control.
This Transfer object will be deleted indirectly by fail().
===============
*/
void Transfer::has_failed()
{
   m_request->transfer_fail(m_game, this);
}


/*
===============
Transfer::tlog
===============
*/
void Transfer::tlog(const char* fmt, ...)
{
	char buf[1024];
	va_list va;
	char id;
	uint serial;

	va_start(va, fmt);
	vsnprintf(buf, sizeof(buf), fmt, va);
	va_end(va);

	if (m_worker) {
		id = 'W';
		serial = m_worker->get_serial();
	} else if (m_item) {
		id = 'I';
		serial = m_item->get_serial();
	} else if (m_soldier) {
		id = 'S';
		serial = m_soldier->get_serial();
	} else {
		id = '?';
		serial = 0;
	}

	log("T%c(%u): %s", id, serial, buf);
}

/*
===============================================================================
	Requeriments IMPLEMENTATION
===============================================================================
*/

Requeriments::Requeriments ()
{
	m_hp.min = -1;
	m_attack.min = -1;
	m_defense.min = -1;
	m_evade.min = -1;
   m_total.min = -1;

	m_hp.max = 100;
	m_attack.max = 100;
	m_defense.max = 100;
	m_evade.max = 100;
   m_total.max = 400;
}

void Requeriments::set (tAttribute at, int min, int max)
{
	switch (at)
	{
	case atrHP:
		m_hp.min = min;
								m_hp.max = max;
								break;
	case atrAttack:
		m_attack.min = min;
								m_attack.max = max;
								break;
	case atrDefense:
		m_defense.min = min;
								m_defense.max = max;
								break;
	case atrEvade:
		m_evade.min = min;
								m_evade.max = max;
								break;
	case atrTotal:
		m_total.min = min;
								m_total.max = max;
								break;
		default:
			throw wexception ("Requeriments::set Unknown attribute %d.", at);
	}
}

bool Requeriments::check (int hp, int attack, int defense, int evade)
{
	bool result = false;

   int total = hp + attack + defense + evade;

	if(((m_hp.min <= hp)           && (hp <= m_hp.max)) &&
	   ((m_attack.min <= attack)   && (attack <= m_attack.max)) &&
		((m_defense.min <= defense) && (defense <= m_defense.max)) &&
		((m_evade.min <= evade)     && (evade <= m_evade.max)) &&
      ((m_total.min <= total)     && (total <= m_total.max)))
			result = true;

	return result;
}

// Modified to allow Requeriments and Soldiers
#define REQUERIMENTS_VERSION 1
/*
 * Read this requeriment from a file
 *
 * it is most probably created by some init function,
 * It's called problably by some request loader, militarysite or trainingsite loader.
 *
 */
void Requeriments::Read
(FileRead * fr, Editor_Game_Base *, Widelands_Map_Map_Object_Loader *)
{
   uint version=fr->Unsigned16();

   if(version==REQUERIMENTS_VERSION) {

		// HitPoints Levels
		m_hp.min = fr->Unsigned8();
		m_hp.max = fr->Unsigned8();

		// Attack Levels
		m_attack.min = fr->Unsigned8();
		m_attack.max = fr->Unsigned8();

		// Defense levels
		m_defense.min = fr->Unsigned8();
		m_defense.max = fr->Unsigned8();

		// Evade
		m_evade.min = fr->Unsigned8();
		m_evade.max = fr->Unsigned8();

		// DONE
      return;
   }
   throw wexception("Unknown requeriment version %i in file!\n", version);
}

/*
 * Write this requeriment to a file
 */
void Requeriments::Write
(FileWrite * fw, Editor_Game_Base *, Widelands_Map_Map_Object_Saver *)
{
   // First, write version
	fw->Unsigned16(REQUERIMENTS_VERSION);

	// Hit Points
	fw->Unsigned8(m_hp.min);
	fw->Unsigned8(m_hp.max);

	// Attack
	fw->Unsigned8(m_attack.min);
	fw->Unsigned8(m_attack.max);

	// Defense
	fw->Unsigned8(m_defense.min);
	fw->Unsigned8(m_defense.max);

	// Evade
	fw->Unsigned8(m_defense.min);
	fw->Unsigned8(m_defense.max);
   // DONE
}


/*
==============================================================================

Request IMPLEMENTATION

==============================================================================
*/

/*
===============
Request::Request
Request::~Request
===============
*/
Request::Request(PlayerImmovable *target, int index, callback_t cbfn, void* cbdata, Type w)
{
	m_type=w;
   m_target = target;
	m_economy = m_target->get_economy();
	m_index = index;
	m_idle = false;

	m_count = 1;
	m_required_time = target->owner().egbase().get_gametime();
	m_required_interval = 0;

	m_callbackfn = cbfn;
	m_callbackdata = cbdata;

   if (m_economy)
      m_economy->add_request(this);

	m_requeriments = 0;
}


Request::~Request()
{
	// Remove from the economy
	if (is_open())
	{
		if (m_economy)
			m_economy->remove_request(this);
	}

	// Cancel all ongoing transfers
	while(m_transfers.size())
		cancel_transfer(0);

	// Remove requeriments
		delete m_requeriments;
	m_requeriments = 0;
}

// Modified to allow Requeriments and SoldierRequests
#define REQUEST_VERSION 2
/**
 * Read this request from a file
 *
 * it is most probably created by some init function,
 * so ad least target/economy is correct. Some Transports
 * might have been initialized. We have to kill them and replace
 * them through the data in the file
 */
void Request::Read(FileRead* fr, Editor_Game_Base* egbase, Widelands_Map_Map_Object_Loader* mol) {
   uint version=fr->Unsigned16();

   if(version==REQUEST_VERSION) {
      m_type=static_cast<Type>(fr->Unsigned8());
      m_index=fr->Unsigned32();
      m_idle=fr->Unsigned8();
      m_count=fr->Unsigned32();
      m_required_time=fr->Unsigned32();
      m_required_interval=fr->Unsigned32();

      assert(!m_transfers.size());

      uint nr_transfers=fr->Unsigned16();
      uint i=0;
      for(i=0; i<nr_transfers; i++) {
         uint what_is=fr->Unsigned8();
         uint reg=fr->Unsigned32();
         Transfer* trans=0;
         Game * const game = dynamic_cast<Game * const>(egbase);
         if (game) {
            assert(mol->is_object_known(reg));
            if(what_is==WARE) {
               WareInstance* ware=static_cast<WareInstance*>(mol->get_object_by_file_index(reg));
               trans = new Transfer(game, this, ware);
            } else if (what_is==WORKER){
               Worker* worker=static_cast<Worker*>(mol->get_object_by_file_index(reg));
               trans = new Transfer(game, this, worker);
            } else if (what_is==SOLDIER){
               Soldier* soldier=static_cast<Soldier*>(mol->get_object_by_file_index(reg));
               trans = new Transfer(game, this, soldier);
            }
            trans->set_idle(fr->Unsigned8());
            m_transfers.push_back(trans);

				// Requeriments
				bool has_requ = fr->Unsigned8();
				if (has_requ) {
					m_requeriments = new Requeriments();
					m_requeriments->Read (fr, egbase, mol);
				}
         }
      }

      if(!is_open() && m_economy)
         m_economy->remove_request(this);

      // DONE
      return;
   }
   throw wexception("Unknown request version %i in file!\n", version);
}

/**
 * Write this request to a file
 */
void Request::Write(FileWrite* fw, Editor_Game_Base* egbase, Widelands_Map_Map_Object_Saver* mos) {
   // First, write version
   fw->Unsigned16(REQUEST_VERSION);

   // target and econmy should be set,
   // same is true for callback stuff

   // Write type
   fw->Unsigned8(m_type);

   // Write ware
   fw->Unsigned32(m_index);

   // Write idle
   fw->Unsigned8(m_idle);

   // Write count
   fw->Unsigned32(m_count);

   // Write required time
   fw->Unsigned32(m_required_time);
   fw->Unsigned32(m_required_interval);

   // Write number of current transfers
   fw->Unsigned16(m_transfers.size());
   uint i=0;
   for(i=0; i<m_transfers.size(); i++) {
      Transfer* trans=m_transfers[i];
      // Is this a ware (or a worker)
		fw->Unsigned8(m_type);
      // Write ware/worker
      if(trans->m_item) {
         assert(mos->is_object_known(trans->m_item));
         fw->Unsigned32(mos->get_object_file_index(trans->m_item));
      } else if (trans->m_worker){
         assert(mos->is_object_known(trans->m_worker));
         fw->Unsigned32(mos->get_object_file_index(trans->m_worker));
      } else if (trans->m_soldier){
         assert(mos->is_object_known(trans->m_soldier));
         fw->Unsigned32(mos->get_object_file_index(trans->m_soldier));
      }
      // Write idle
      fw->Unsigned8(trans->is_idle());

		// Requeriments
		//fw->Unsigned8(m_requeriments ? true: false);

		if (m_requeriments) {
			fw->Unsigned8(true);
			m_requeriments->Write (fw, egbase, mos);
		}
		else
			fw->Unsigned8(false);
   }
   // DONE
}

/*
===============
Request::get_target_flag

Figure out the flag we need to deliver to.
===============
*/
Flag *Request::get_target_flag() {return get_target()->get_base_flag();}


/*
===============
Request::get_base_required_time

Return the point in time at which we want the item of the given number to
be delivered. nr is in the range [0..m_count[
===============
*/
int Request::get_base_required_time(Editor_Game_Base* g, int nr)
{
	int curtime = g->get_gametime();

	if (!nr || !m_required_interval)
		return m_required_time;

	if ((curtime - m_required_time) > (m_required_interval * 2)) {
		if (nr == 1)
			return m_required_time + (curtime - m_required_time) / 2;

		return curtime + (nr-2) * m_required_interval;
	}

	return m_required_time + nr * m_required_interval;
}


/*
===============
Request::get_required_time

Return the time when the requested ware is needed.
Can be in the past, indicating that we have been idling, waiting for the ware.
===============
*/
int Request::get_required_time()
{
	return
		get_base_required_time(&m_economy->owner().egbase(), m_transfers.size());
}


/*
===============
Request::set_economy

Change the Economy we belong to.
===============
*/
void Request::set_economy(Economy* e)
{
	if (m_economy == e)
		return;

	if (m_economy && is_open())
		m_economy->remove_request(this);

	m_economy = e;

	if (m_economy && is_open())
		m_economy->add_request(this);
}


/*
===============
Request::set_idle

Make a Request idle or not idle.
===============
*/
void Request::set_idle(bool idle)
{
	bool wasopen = is_open();

	if (m_idle == idle)
		return;

	m_idle = idle;

	// Idle requests are always added to the economy
	if (m_economy) {
		if (wasopen && !is_open())
			m_economy->remove_request(this);
		else if (!wasopen && is_open())
			m_economy->add_request(this);
	}
}


/*
===============
Request::set_count

Change the number of wares we need.
===============
*/
void Request::set_count(int count)
{
	bool wasopen = is_open();

	m_count = count;

	// Cancel unneeded transfers. This should be more clever about which
	// transfers to cancel. Then again, this loop shouldn't execute during
	// normal play anyway
	while(m_count < (int)m_transfers.size())
		cancel_transfer(m_transfers.size() - 1);

	// Update the economy
	if (m_economy) {
		if (wasopen && !is_open())
			m_economy->remove_request(this);
		else if (!wasopen && is_open())
			m_economy->add_request(this);
	}
}


/*
===============
Request::set_required_time

Change the time at which the first item to be delivered is needed.
Default is the gametime of the Request creation.
===============
*/
void Request::set_required_time(int time)
{
	m_required_time = time;
}


/*
===============
Request::set_required_interval

Change the time between desired delivery of items.
===============
*/
void Request::set_required_interval(int interval)
{
	m_required_interval = interval;
}


/*
===============
Request::start_transfer

Begin transfer of the requested ware from the given warehouse.
This function does not take ownership of route, i.e. the caller is responsible
for its deletion.
===============
*/
void Request::start_transfer(Game* g, Supply* supp)
{
	assert(is_open());
	Transfer* t = 0;
	try
	{
		if (get_type()==SOLDIER)
		{
			// Begin the transfer of a soldier.
			// launch_soldier() creates the worker, set_job_request() makes sure the
			// worker starts walking
			log("Request: start soldier transfer for %i\n", get_index());

			Soldier* s = supp->launch_soldier(g, get_index(), get_requeriments());
			t = new Transfer(g, this, s);
		}
		else if (get_type()==WORKER)
		{
			// Begin the transfer of a worker.
			// launch_worker() creates the worker, set_job_request() makes sure the
			// worker starts walking
			log("Request: start worker transfer for %i\n", get_index());

			Worker* w = supp->launch_worker(g, get_index());

			t = new Transfer(g, this, w);
		}
		else
		{
			// Begin the transfer of an item. The item itself is passive.
			// launch_item() ensures the WareInstance is transported out of the warehouse
			// Once it's on the flag, the flag code will decide what to do with it.
			WareInstance* item = supp->launch_item(g, get_index());

			t = new Transfer(g, this, item);
		}
	}
	catch(...)
	{
			delete t;

		throw;
	}

	t->set_idle(m_idle);

	m_transfers.push_back(t);
	if (!is_open())
		m_economy->remove_request(this);
}


/*
===============
Request::transfer_finish

Callback from ware/worker code that the requested ware has arrived.
This will call a callback function in the target, which is then responsible
for removing and deleting the request.
===============
*/
void Request::transfer_finish(Game *g, Transfer* t)
{
	Worker* w = 0;
	Soldier* s = 0;

	if (t->m_worker)
		w = t->m_worker;
	else
		s = t->m_soldier;

	if (t->m_item)
		t->m_item->destroy(g);

	t->m_soldier = 0;
	t->m_worker = 0;
	t->m_item = 0;

	remove_transfer(find_transfer(t));

	if (!m_idle) {
		set_required_time(get_base_required_time(g, 1));
		m_count--;
	}

		delete m_requeriments;
	m_requeriments = 0;

   // the callback functions are likely to delete us,
   // therefore we musn't access member variables behind this
   // point
	if (w)
		(*m_callbackfn)(g, this, m_index, w, m_callbackdata);
	else
		(*m_callbackfn)(g, this, m_index, s, m_callbackdata);


log ("<<Transfer::has_finished()\n");
}


/*
===============
Request::transfer_fail

Callback from ware/worker code that the scheduled transfer has failed.
The calling code has already dealt with the worker/item.

Re-open the request.
===============
*/
void Request::transfer_fail(Game *, Transfer * t) {
	bool wasopen = is_open();

	t->m_soldier = 0;
	t->m_worker = 0;
	t->m_item = 0;

   remove_transfer(find_transfer(t));

   if (!wasopen)
		m_economy->add_request(this);

		delete m_requeriments;
	m_requeriments = 0;
}


/*
===============
Request::cancel_transfer

Cancel the transfer with the given index.
Note that this does *not* update whether the Request is registered with the
Economy or not.
===============
*/
void Request::cancel_transfer(uint idx)
{
	remove_transfer(idx);
}


/**
 * Remove and free the transfer with the given index.
 * This does not update the Transfer's worker or item, and it does not update
 * whether the Request is registered with the Economy.
 */
void Request::remove_transfer(uint idx)
{
	Transfer* t = m_transfers[idx];

	m_transfers.erase(m_transfers.begin()+idx);

	delete t;
}


/*
===============
Request::find_transfer

Lookup a Transfer in the transfers array.
Throws an exception if the Transfer is not registered with us.
===============
*/
uint Request::find_transfer(Transfer* t)
{
	TransferList::iterator it = std::find(m_transfers.begin(), m_transfers.end(), t);

	if (it == m_transfers.end())
		throw wexception("Request::find_transfer(): not found");

	return it - m_transfers.begin();
}


/*
==============================================================================

SupplyList IMPLEMENTATION

==============================================================================
*/


/*
===============
SupplyList::SupplyList

Zero-initialize
===============
*/
SupplyList::SupplyList()
{
}


/*
===============
SupplyList::~SupplyList

A supply list should be empty when it's destroyed.
===============
*/
SupplyList::~SupplyList()
{
}


/*
===============
SupplyList::add

Add a supply to the list.
===============
*/
void SupplyList::add_supply(Supply* supp)
{
	m_supplies.push_back(supp);
}


/*
===============
SupplyList::remove_supply

Remove a supply from the list.
===============
*/
void SupplyList::remove_supply(Supply* supp)
{
	for(uint idx = 0; idx < m_supplies.size(); idx++) {
		if (m_supplies[idx] == supp) {
			if (idx != m_supplies.size()-1)
				m_supplies[idx] = m_supplies[m_supplies.size()-1];
			m_supplies.pop_back();
			return;
		}
	}

	throw wexception("SupplyList::remove: not in list");
}


/*
==============================================================================

WaresQueue IMPLEMENTATION

==============================================================================
*/

/*
===============
WaresQueue::WaresQueue

Pre-initialize a WaresQueue
===============
*/
WaresQueue::WaresQueue(PlayerImmovable* bld)
{
	m_owner = bld;
	m_ware = -1;
	m_size = 0;
	m_filled = 0;
	m_request = 0;
	m_consume_interval = 0;

	m_callback_fn = 0;
	m_callback_data = 0;
}


/*
===============
WaresQueue::~WaresQueue

cleanup() must be called!
===============
*/
WaresQueue::~WaresQueue()
{
	assert(m_ware == -1);
}


/*
===============
WaresQueue::init

Initialize the queue. This also issues the first request, if necessary.
===============
*/
void WaresQueue::init(const int ware, const uint size) {
	assert(m_ware == -1);

	m_ware = ware;
	m_size = size;
	m_filled = 0;

	update();
}


/*
===============
WaresQueue::cleanup

Clear the queue appropriately.
===============
*/
void WaresQueue::cleanup() {
	assert(m_ware != -1);

	if (m_filled)
		m_owner->get_economy()->remove_wares(m_ware, m_filled);

	m_filled = 0;
	m_size = 0;

	update();

	m_ware = -1;
}


/*
===============
WaresQueue::update

Fix filled <= size and requests.
You must call this after every call to set_*()
===============
*/
void WaresQueue::update() {
	assert(m_ware != -1);

	if (m_filled > m_size) {
		m_owner->get_economy()->remove_wares(m_ware, m_filled - m_size);
		m_filled = m_size;
	}

	if (m_filled < m_size)
	{
		if (!m_request)
			m_request = new Request(m_owner, m_ware, &WaresQueue::request_callback, this, Request::WARE);

		m_request->set_count(m_size - m_filled);
		m_request->set_required_interval(m_consume_interval);
	}
	else
	{
			delete m_request;
			m_request = 0;
	}
}


/*
===============
WaresQueue::set_callback

Set the callback function that is called when an item has arrived.
===============
*/
void WaresQueue::set_callback(callback_t* fn, void* data)
{
	m_callback_fn = fn;
	m_callback_data = data;
}


/*
===============
WaresQueue::request_callback [static]

Called when an item arrives at the owning building.
===============
*/
void WaresQueue::request_callback
(Game * g, Request *, int ware, Worker * w, void * data)
{
	WaresQueue* wq = (WaresQueue*)data;

	assert(!w); // WaresQueue can't hold workers
	assert(wq->m_filled < wq->m_size);
	assert(wq->m_ware == ware);

	// Update
	wq->set_filled(wq->m_filled + 1);
	wq->update();

	if (wq->m_callback_fn)
		(*wq->m_callback_fn)(g, wq, ware, wq->m_callback_data);
}


/*
===============
WaresQueue::remove_from_economy

Remove the wares in this queue from the given economy (used in accounting).
===============
*/
void WaresQueue::remove_from_economy(Economy* e)
{
   if(m_ware==-1) return;

	e->remove_wares(m_ware, m_filled);
	if (m_request)
		m_request->set_economy(0);
}


/*
===============
WaresQueue::add_to_economy

Add the wares in this queue to the given economy (used in accounting)
===============
*/
void WaresQueue::add_to_economy(Economy* e)
{
	if(m_ware==-1) return;

   e->add_wares(m_ware, m_filled);
	if (m_request)
		m_request->set_economy(e);
}


/*
===============
WaresQueue::set_size
WaresQueue::set_filled

Change size and fill status of the queue.
Important: that you must call update() after calling any of these functions.
===============
*/
void WaresQueue::set_size(const uint size) throw () {m_size = size;}

void WaresQueue::set_filled(const uint filled) throw() {
	if (filled > m_filled)
		m_owner->get_economy()->add_wares(m_ware, filled - m_filled);
	else if (filled < m_filled)
		m_owner->get_economy()->remove_wares(m_ware, m_filled - filled);

	m_filled = filled;
}


/*
===============
WaresQueue::set_consume_interval

Set the time between consumption of items when the owning building
is consuming at full speed.
This interval is merely a hint for the Supply/Request balancing code.
===============
*/
void WaresQueue::set_consume_interval(const uint time) throw ()
{m_consume_interval = time;}

/*
 * Read and write
 */
#define WARES_QUEUE_DATA_PACKET_VERSION 1
void WaresQueue::Write(FileWrite* fw, Editor_Game_Base* egbase, Widelands_Map_Map_Object_Saver* os) {

   fw->Unsigned16(WARES_QUEUE_DATA_PACKET_VERSION);

	// Owner and callback is not saved, but this should be obvious on load
   fw->CString(m_owner->get_owner()->get_tribe()->get_ware_descr(m_ware)->get_name());
   fw->Signed32(m_size);
   fw->Signed32(m_filled);
   fw->Signed32(m_consume_interval);
   if(m_request) {
      fw->Unsigned8(1);
      m_request->Write(fw,egbase,os);
   } else
      fw->Unsigned8(0);
}
void WaresQueue::Read(FileRead* fr, Editor_Game_Base* egbase, Widelands_Map_Map_Object_Loader* ol) {
   int version=fr->Unsigned16();

   if(version==WARES_QUEUE_DATA_PACKET_VERSION) {
      m_ware=m_owner->get_owner()->get_tribe()->get_ware_index(fr->CString());
      m_size=fr->Signed32();
      m_filled=fr->Signed32();
      m_consume_interval=fr->Signed32();
      bool request=fr->Unsigned8();
         delete m_request;
      if(request) {
         m_request = new Request(m_owner, 0, &WaresQueue::request_callback, this, Request::WORKER);
         m_request->Read(fr,egbase,ol);
      } else {
         m_request=0;
      }

      // Now Economy stuff. We have to add our filled items to the economy
      add_to_economy(m_owner->get_economy());
      return;
   }
   throw wexception("WaresQueue::Read: Unknown WaresQueueVersion %i!\n", version);
}

/*
==============================================================================

Economy IMPLEMENTATION

==============================================================================
*/

/*
===============
Economy::Economy
Economy::~Economy
===============
*/
Economy::Economy(Player *player) :
m_owner(player),
m_rebuilding(false),
m_request_timer(false),
mpf_cycle(0)
{
   m_worker_supplies.resize( player->get_tribe()->get_nrworkers() );
   m_workers.set_nrwares( player->get_tribe()->get_nrworkers() );
   m_ware_supplies.resize( player->get_tribe()->get_nrwares() );
   m_wares.set_nrwares( player->get_tribe()->get_nrwares() );

   player->add_economy(this);
}

Economy::~Economy()
{
	assert(!m_rebuilding);

   m_owner->remove_economy(this);

	if (m_requests.size())
		log("Warning: Economy still has requests left on destruction\n");
	if (m_flags.size())
		log("Warning: Economy still has flags left on destruction\n");
	if (m_warehouses.size())
		log("Warning: Economy still has warehouses left on destruction\n");
}


/*
===============
Economy::check_merge [static]

Two flags have been connected; check whether their economies should be
merged.
Since we could merge into both directions, we preserve the economy that is
currently bigger (should be more efficient).
===============
*/
void Economy::check_merge(Flag *f1, Flag *f2)
{
	Economy *e1 = f1->get_economy();
	Economy *e2 = f2->get_economy();

	if (e1 == e2)
		return;

	if (e2->get_nrflags() > e1->get_nrflags())
		std::swap(e1, e2);

	e1->do_merge(e2);
}

/*
===============
Economy::check_split [static]

If the two flags can no longer reach each other (pathfinding!), the economy
gets split.
===============
*/
void Economy::check_split(Flag *f1, Flag *f2)
{
	assert(f1 != f2);
	assert(f1->get_economy() == f2->get_economy());

	Economy *e = f1->get_economy();

	if (e->find_route(f1, f2, 0))
		return;

	// Should we split off f1 or f2? Ideally, we'd split off so that the
	// new economy will be relatively small.
	// Unfortunately, there's no easy way to tell in advance which of the two
	// resulting economies will be smaller
	// Using f2 is just a guess, but if anything f2 is probably best:
	// it will be the end point of a road. Since roads are typically built
	// from the center of a country outwards, and since splits
	// are more likely to happen outwards, the economy at the end point is
	// probably smaller in average. It's all just guesswork though ;)
	e->do_split(f2);
}

/*
class FlagQueue

Provides the flexible priority queue to maintain the open list.
This is more flexible than a standard priority_queue (fast boost() to
adjust cost)
*/
class FlagQueue {
	std::vector<Flag*> m_data;

public:
	FlagQueue() { }
	~FlagQueue() { }

	void flush() { m_data.clear(); }

	// Return the best node and readjust the tree
	// Basic idea behind the algorithm:
	//  1. the top slot of the tree is empty
	//  2. if this slot has both children:
	//       fill this slot with one of its children or with slot[_size], whichever
	//       is best;
	//       if we filled with slot[_size], stop
	//       otherwise, repeat the algorithm with the child slot
	//     if it doesn't have any children (l >= _size)
	//       put slot[_size] in its place and stop
	//     if only the left child is there
	//       arrange left child and slot[_size] correctly and stop
	Flag* pop()
	{
		if (m_data.empty())
			return 0;

		Flag* head = m_data[0];

		unsigned nsize = m_data.size()-1;
		unsigned fix = 0;
		while(fix < nsize) {
			unsigned l = fix*2 + 1;
			unsigned r = fix*2 + 2;
			if (l >= nsize) {
				m_data[fix] = m_data[nsize];
				m_data[fix]->mpf_heapindex = fix;
				break;
			}
			if (r >= nsize) {
				if (m_data[nsize]->cost() <= m_data[l]->cost()) {
					m_data[fix] = m_data[nsize];
					m_data[fix]->mpf_heapindex = fix;
				} else {
					m_data[fix] = m_data[l];
					m_data[fix]->mpf_heapindex = fix;
					m_data[l] = m_data[nsize];
					m_data[l]->mpf_heapindex = l;
				}
				break;
			}

			if (m_data[nsize]->cost() <= m_data[l]->cost() && m_data[nsize]->cost() <= m_data[r]->cost()) {
				m_data[fix] = m_data[nsize];
				m_data[fix]->mpf_heapindex = fix;
				break;
			}
			if (m_data[l]->cost() <= m_data[r]->cost()) {
				m_data[fix] = m_data[l];
				m_data[fix]->mpf_heapindex = fix;
				fix = l;
			} else {
				m_data[fix] = m_data[r];
				m_data[fix]->mpf_heapindex = fix;
				fix = r;
			}
		}

		m_data.pop_back();

		debug(0, "pop");

		head->mpf_heapindex = -1;

		return head;
	}

	// Add a new node and readjust the tree
	// Basic idea:
	//  1. Put the new node in the last slot
	//  2. If parent slot is worse than self, exchange places and recurse
	// Note that I rearranged this a bit so swap isn't necessary
	void push(Flag *t)
	{
		unsigned slot = m_data.size();
		m_data.push_back(0);

		while(slot > 0) {
			unsigned parent = (slot - 1) / 2;

			if (m_data[parent]->cost() < t->cost())
				break;

			m_data[slot] = m_data[parent];
			m_data[slot]->mpf_heapindex = slot;
			slot = parent;
		}
		m_data[slot] = t;
		t->mpf_heapindex = slot;

		debug(0, "push");
	}

	// Rearrange the tree after a node has become better, i.e. move the
	// node up
	// Pushing algorithm is basically the same as in push()
	void boost(Flag *t)
	{
		unsigned slot = t->mpf_heapindex;

#if defined(DEBUG) && defined(__i386__)
      /* This is here temporarilly till the bugs are fixed
       * which trigger the asserts below
       */
      log("DBG: slot: %i, m_data.size(): %i\n", slot, m_data.size());
      if(slot >= m_data.size()) asm("int $3");
      log("DBG: m_data[slot]: %p, t: %p\n", m_data[slot], t);
      if(m_data[slot] != t) asm("int $3");
#endif
		assert(slot < m_data.size());
		assert(m_data[slot] == t);

		while(slot > 0) {
			unsigned parent = (slot - 1) / 2;

			if (m_data[parent]->cost() <= t->cost())
				break;

			m_data[slot] = m_data[parent];
			m_data[slot]->mpf_heapindex = slot;
			slot = parent;
		}
		m_data[slot] = t;
		t->mpf_heapindex = slot;

		debug(0, "boost");
	}

	// Recursively check integrity
	void debug(unsigned node, const char *str)
	{
		unsigned l = node*2 + 1;
		unsigned r = node*2 + 2;
		if (m_data[node]->mpf_heapindex != (int)node) {
			fprintf(stderr, "%s: mpf_heapindex integrity!\n", str);
			abort();
		}
		if (l < m_data.size()) {
			if (m_data[node]->cost() > m_data[l]->cost()) {
				fprintf(stderr, "%s: Integrity failure\n", str);
				abort();
			}
			debug(l, str);
		}
		if (r < m_data.size()) {
			if (m_data[node]->cost() > m_data[r]->cost()) {
				fprintf(stderr, "%s: Integrity failure\n", str);
				abort();
			}
			debug(r, str);
		}
	}

};

/*
===============
Economy::find_route

Route between the two flags.
Store the route in route if it is not null. Note that route will be cleared
before storing the result.
Returns true if a route has been found.

If cost_cutoff is >= 0, the function will stop and return false if it can't
find a route that is better than cost_cutoff.

This function should always be successfull, except for when it's called from
check_split().
===============
*/
bool Economy::find_route(Flag *start, Flag *end, Route *route, int cost_cutoff)
{
	assert(start->get_economy() == this);
	assert(end->get_economy() == this);

	Map & map = owner().egbase().map();

	// advance the path-finding cycle
	mpf_cycle++;
	if (!mpf_cycle) { // reset all cycle fields
		for(uint i = 0; i < m_flags.size(); i++)
			m_flags[i]->mpf_cycle = 0;
		mpf_cycle++;
	}

	// Add the starting flag into the open list
	FlagQueue Open;
	Flag *current;

	start->mpf_cycle = mpf_cycle;
	start->mpf_backlink = 0;
	start->mpf_realcost = 0;
	start->mpf_estimate = map.calc_cost_estimate
		(start->get_position(), end->get_position());

	Open.push(start);

	while((current = Open.pop())) {
		if (current == end)
			break; // found our goal

		if (cost_cutoff >= 0 && current->mpf_realcost > cost_cutoff)
			return false;

		// Loop through all neighbouring flags
		Neighbour_list neighbours;

		current->get_neighbours(&neighbours);

		for(uint i = 0; i < neighbours.size(); i++) {
			Flag *neighbour = neighbours[i].flag;
			int cost;

			// don't need to find the optimal path if we're just checking connectivity
			if (neighbour == end && !route)
				return true;

			cost = current->mpf_realcost + neighbours[i].cost;

			if (neighbour->mpf_cycle != mpf_cycle) {
				// add to open list
				neighbour->mpf_cycle = mpf_cycle;
				neighbour->mpf_realcost = cost;
				neighbour->mpf_estimate = map.calc_cost_estimate
					(neighbour->get_position(), end->get_position());
				neighbour->mpf_backlink = current;
				Open.push(neighbour);
			} else if (neighbour->cost() > cost+neighbour->mpf_estimate) {
				// found a better path to a field that's already Open
				neighbour->mpf_realcost = cost;
				neighbour->mpf_backlink = current;
            if( neighbour->mpf_heapindex != -1 ) // This neighbour is already 'popped', skip it
               Open.boost(neighbour);
			}
		}
	}

	if (!current) // path not found
		return false;

	// Unwind the path to form the route
	if (route) {
		Flag *flag;

		route->clear();
		route->m_totalcost = end->mpf_realcost;

		flag = end;
		for(;;) {
			route->m_route.insert(route->m_route.begin(), flag);
			if (flag == start)
				break;
			flag = flag->mpf_backlink;
		}
	}

	return true;
}


/*
===============
Economy::find_nearest_warehouse

Find the nearest warehouse, starting from the given start flag.
Returns the best warehouse (or 0 if none can be found) and stores the route to
it in the given route.
===============
*/
Warehouse *Economy::find_nearest_warehouse(Flag *start, Route *route)
{
	int best_totalcost = -1;
	Warehouse *best_warehouse = 0;

	assert(start->get_economy() == this);

	for(uint i = 0; i < m_warehouses.size(); i++) {
		Warehouse *wh = m_warehouses[i];
		Route buf_route;

		if (!find_route(start, wh->get_base_flag(), &buf_route, best_totalcost))
			continue;

		best_totalcost = buf_route.get_totalcost();
		best_warehouse = wh;
		*route = buf_route;
	}

	return best_warehouse;
}


/*
===============
Economy::add_flag

Add a flag to the flag array.
Only call from Flag init and split/merger code!
===============
*/
void Economy::add_flag(Flag *flag)
{
	assert(flag->get_economy() == 0);

	m_flags.push_back(flag);
	flag->set_economy(this);
	flag->mpf_cycle = 0;
}

/*
===============
Economy::remove_flag

Remove a flag from the flag array.
Only call from Flag cleanup and split/merger code!
===============
*/
void Economy::remove_flag(Flag *flag)
{
	assert(flag->get_economy() == this);

	do_remove_flag(flag);

	// automatically delete the economy when it becomes empty.
	if (!m_flags.size())
		delete this;
}

/*
===============
Economy::do_remove_flag [private]

Remove the flag, but don't delete the economy automatically.
This is called from the merge code.
===============
*/
void Economy::do_remove_flag(Flag *flag)
{
	flag->set_economy(0);

	// fast remove
	uint i;
	for(i = 0; i < m_flags.size(); i++) {
		if (m_flags[i] == flag) {
			if (i < m_flags.size()-1)
				m_flags[i] = m_flags[m_flags.size()-1];
			break;
		}
	}
	assert(i != m_flags.size());
	m_flags.pop_back();
}

/*
===============
Economy::add_wares

Call this whenever some entity created a ware, e.g. when a lumberjack
has felled a tree.
This is also called when a ware is added to the economy through trade or
a merger.
===============
*/
void Economy::add_wares(int id, int count)
{
	//log("%p: add(%i, %i)\n", this, id, count);

	m_wares.add(id, count);

	// TODO: add to global player inventory?
}
void Economy::add_workers(int id, int count)
{
	//log("%p: add(%i, %i)\n", this, id, count);

	m_workers.add(id, count);

	// TODO: add to global player inventory?
}


/*
===============
Economy::remove_wares

Call this whenever a ware his destroyed or consumed, e.g. food has been
eaten or a warehouse has been destroyed.
This is also called when a ware is removed from the economy through trade or
a split of the Economy.
===============
*/
void Economy::remove_wares(int id, int count)
{
	//log("%p: remove(%i, %i) from %i\n", this, id, count, m_wares.stock(id));

	m_wares.remove(id, count);


	// TODO: remove from global player inventory?
}
void Economy::remove_workers(int id, int count)
{
	//log("%p: remove(%i, %i) from %i\n", this, id, count, m_workers.stock(id));

	m_workers.remove(id, count);

	// TODO: remove from global player inventory?
}


/*
===============
Economy::add_warehouse

Add the warehouse to our list of warehouses.
This also adds the wares in the warehouse to the economy. However, if wares are
added to the warehouse in the future, add_wares() must be called.
===============
*/
void Economy::add_warehouse(Warehouse *wh)
{
	m_warehouses.push_back(wh);
}

/*
===============
Economy::remove_warehouse

Remove the warehouse and its wares from the economy.
===============
*/
void Economy::remove_warehouse(Warehouse *wh)
{
   // fast remove
   uint i;
   for(i = 0; i < m_warehouses.size(); i++) {
      if (m_warehouses[i] == wh) {
         if (i < m_warehouses.size()-1)
            m_warehouses[i] = m_warehouses[m_warehouses.size()-1];
         break;
      }
   }
   /*
    * This assert was modified, since on
    * loading, warehouses might try to remove
    * themselves from their own economy,
    * though they weren't added (since they weren't
    * initialized)
    *
    */
   assert(i != m_warehouses.size() || !m_warehouses.size());
   if(m_warehouses.size())
      m_warehouses.pop_back();
}


/*
===============
Economy::add_request

Consider the request, try to fulfill it immediately or queue it for later.
Important: This must only be called by the Request class.
===============
*/
void Economy::add_request(Request* req)
{
	assert(req->is_open());
   assert(!have_request(req));

   if(!get_owner()) // our owner is deleted, we are cleaning up. So ignore this
      return;

	m_requests.push_back(req);

	// Try to fulfill the request
	start_request_timer();
}


/*
===============
Economy::have_request

Return true if the given Request is registered with the Economy.
===============
*/
bool Economy::have_request(Request* req)
{
	RequestList::iterator it = std::find(m_requests.begin(), m_requests.end(), req);

	return it != m_requests.end();
}


/*
===============
Economy::remove_request

Remove the request from this economy.
Important: This must only be called by the Request class.
===============
*/
void Economy::remove_request(Request* req)
{
	RequestList::iterator it = std::find(m_requests.begin(), m_requests.end(), req);

	if (it == m_requests.end()) {
		log("WARNING: remove_request(%p) not in list\n", req);
		return;
	}

	if (it != m_requests.end()-1)
		*it = *m_requests.rbegin();

	m_requests.pop_back();
}


/*
===============
Economy::add_worker_supply

Add a worker_supply to our list of supplies.
===============
*/
void Economy::add_worker_supply(int ware, Supply* supp)
{
	//log("add_worker_supply(%i, %p)\n", ware, supp);

	if (ware >= (int)m_worker_supplies.size())
		m_worker_supplies.resize(ware+1);

	m_worker_supplies[ware].add_supply(supp);

	start_request_timer();
}

/*
===============
Economy::have_worker_supply

Return true if the given worker_supply is registered with the economy.
===============
*/
bool Economy::have_worker_supply(int ware, Supply* supp)
{
	if (ware >= (int)m_worker_supplies.size())
		return false;

	for(int i = 0; i < m_worker_supplies[ware].get_nrsupplies(); i++)
		if (m_worker_supplies[ware].get_supply(i) == supp)
			return true;

	return false;
}


/*
===============
Economy::remove_worker_supply

Remove a worker_supply from our list of supplies.
===============
*/
void Economy::remove_worker_supply(int ware, Supply* supp)
{
	//log("remove_worker_supply(%i, %p)\n", ware, supp);

	m_worker_supplies[ware].remove_supply(supp);
}


/*
===============
Economy::add_soldier_supply

Add a soldier_supply to our list of supplies.
===============
*/
void Economy::add_soldier_supply(int ware, Supply* supp)
{
	//log("add_soldier_supply(%i, %p)\n", ware, supp);

	if (ware >= (int)m_worker_supplies.size())
		m_worker_supplies.resize(ware+1);

	m_worker_supplies[ware].add_supply(supp);

	start_request_timer();
}

/*
===============
Economy::have_soldier_supply

Return true if the given soldier_supply is registered with the economy.
===============
*/
bool Economy::have_soldier_supply(int ware, Supply* supp, Requeriments *) {
	if (ware >= (int)m_worker_supplies.size())
		return false;

	for(int i = 0; i < m_worker_supplies[ware].get_nrsupplies(); i++)
		if (m_worker_supplies[ware].get_supply(i) == supp)
			return true;

	return false;
}


/*
===============
Economy::remove_soldier_supply

Remove a soldier_supply from our list of supplies.
===============
*/
void Economy::remove_soldier_supply(int ware, Supply* supp)
{
	//log("remove_soldier_supply(%i, %p)\n", ware, supp);

	m_worker_supplies[ware].remove_supply(supp);
}



/*
===============
Economy::add_ware_supply

Add a ware_supply to our list of supplies.
===============
*/
void Economy::add_ware_supply(int ware, Supply* supp)
{
	//log("add_ware_supply(%i, %p)\n", ware, supp);

	if (ware >= (int)m_ware_supplies.size())
		m_ware_supplies.resize(ware+1);

	m_ware_supplies[ware].add_supply(supp);

	start_request_timer();
}


/*
===============
Economy::have_ware_supply

Return true if the given ware_supply is registered with the economy.
===============
*/
bool Economy::have_ware_supply(int ware, Supply* supp)
{
	if (ware >= (int)m_ware_supplies.size())
		return false;

	for(int i = 0; i < m_ware_supplies[ware].get_nrsupplies(); i++)
		if (m_ware_supplies[ware].get_supply(i) == supp)
			return true;

	return false;
}


/*
===============
Economy::remove_ware_supply

Remove a ware_supply from our list of supplies.
===============
*/
void Economy::remove_ware_supply(int ware, Supply* supp)
{
   assert(ware>=0);
   //log("remove_ware_supply(%i, %p)\n", ware, supp);

	m_ware_supplies[ware].remove_supply(supp);
}



/*
===============
Economy::do_merge

Add e's flags to this economy.
Also transfer all wares and wares request. Try to resolve the new ware requests
if possible.
===============
*/
void Economy::do_merge(Economy *e)
{
	int i;

	m_rebuilding = true;

	// Be careful around here. The last e->remove_flag() will cause the other
	// economy to delete itself.
	i = e->get_nrflags();
	while(i--) {
		assert(i+1 == e->get_nrflags());

		Flag *flag = e->m_flags[0];

		e->do_remove_flag(flag);
		add_flag(flag);
	}

	// Fix up Supply/Request after rebuilding
	m_rebuilding = false;

	// implicitly delete the economy
	delete e;
}


/*
===============
Economy::do_split

Flag f and all its direct and indirect neighbours are put into a new economy.
===============
*/
void Economy::do_split(Flag *f)
{
	log("Economy: split %i\n", get_nrflags());

	Economy *e = new Economy(m_owner);

	m_rebuilding = true;
	e->m_rebuilding = true;

	std::set<Flag*> open;

	open.insert(f);
	while(open.size()) {
		f = *open.begin();
		open.erase(open.begin());

		// move this flag to the new economy
		remove_flag(f);
		e->add_flag(f);

		//  check all neighbours; if they aren't in the new economy yet, add them
		// to the list (note: roads and buildings are reassigned via Flag::set_economy)
		Neighbour_list neighbours;
		f->get_neighbours(&neighbours);

		for(uint i = 0; i < neighbours.size(); i++) {
			Flag *n = neighbours[i].flag;

			if (n->get_economy() == this)
				open.insert(n);
		}
	}

	log("  split %i flags\n", e->get_nrflags());

	// Fix Supply/Request after rebuilding
	m_rebuilding = false;
	e->m_rebuilding = false;
}


/*
===============
Economy::start_request_timer

Make sure the request timer is running.
===============
*/
void Economy::start_request_timer(int delta)
{
	if (Game * const game = dynamic_cast<Game * const>(&m_owner->egbase())) {
		const int gametime = game->get_gametime();

		if (m_request_timer and m_request_timer_time - (gametime + delta) <= 0)
		return;

	Cmd_Queue* cq = game->get_cmdqueue();

	m_request_timer = true;
	m_request_timer_time = game->get_gametime() + delta;
   cq->enqueue (new Cmd_Call_Economy_Balance(m_request_timer_time, m_owner->get_player_number(), this));

#if 0
	cq->queue
		(m_request_timer_time,
		 SENDER_MAPOBJECT, CMD_CALL,
		 static_cast<const long>(&Economy::request_timer_cb),
		 m_trackserial,
		 0);
#endif
	}
}


/*
===============
Economy::find_best_supply

Find the supply that is best suited to fulfill the given request.
Returns 0 if no supply is found.
===============
*/
Supply* Economy::find_best_supply(Game* g, Request* req, int ware, int* pcost, std::vector<SupplyList>* use_supply)
{
	assert(req->is_open());

	Route buf_route0, buf_route1;
	Supply *best_supply = 0;
	Route *best_route = 0;
	int best_cost = -1;
	Flag * const target_flag = req->get_target_flag();

	// Look for matches in all possible supplies in this economy
	if (ware >= (int)use_supply->size())
		return false; // tough luck, we have definitely no supplies for this ware

	for(int i = 0; i < ((*use_supply)[ware]).get_nrsupplies(); i++) {
		Supply* supp = ((*use_supply)[ware]).get_supply(i);
		Route* route;

		// idle requests only get active supplies
		if (req->is_idle() and not supp->is_active())
			continue;

		// Check requeriments
		if (req->get_type() == Request::SOLDIER)
			if (req->has_requeriments())
				if (supp->get_passing_requeriments (g, ware,  req->get_requeriments()) < 1)
				{
					log ("No pasado %d\n", supp->get_passing_requeriments (g, ware,  req->get_requeriments()));
					continue;
				}
				else
					log ("PASADO\n");


		route = (best_route != &buf_route0) ? &buf_route0 : &buf_route1;
		// will be cleared by find_route()

		int cost_cutoff = best_cost;

		if (!find_route(supp->get_position(g)->get_base_flag(), target_flag, route, cost_cutoff)) {
			if (!best_route)
				throw wexception("Economy::find_best_supply: COULDN'T FIND A ROUTE!");
			continue;
		}

		//supp->mark_as_used(g, req->get_index(), req->get_requeriments());
		// cost_cutoff guarantuees us that the route is better than what we have
		best_supply = supp;
		best_route = route;
		best_cost = route->get_totalcost();
	}

	if (!best_route)
		return 0;

	*pcost = best_cost;
	return best_supply;
}


struct RequestSupplyPair {
   bool                 is_item;
   bool                 is_worker;
   bool                 is_soldier;
	int               ware;
	TrackPtr<Request> request;
	TrackPtr<Supply>  supply;
	int               priority;

	struct Compare {
		bool operator()(const RequestSupplyPair& p1, const RequestSupplyPair& p2) {
			return p1.priority < p2.priority;
		}
	};
};

typedef std::priority_queue<RequestSupplyPair, std::vector<RequestSupplyPair>,
				RequestSupplyPair::Compare> RSPairQueue;

struct RSPairStruct {
	RSPairQueue queue;
	int         nexttimer;
};


/*
===============
Economy::process_requests

Walk all Requests and find potential transfer candidates.
===============
*/
void Economy::process_requests(Game* g, RSPairStruct* s)
{
	for(RequestList::iterator it = m_requests.begin(); it != m_requests.end(); ++it) {
		Request* req = *it;
		Supply* supp;
		int cost; // estimated time in milliseconds to fulfill Request
		int idletime;

      if(req->get_type()==Request::WARE)
         supp = find_best_supply(g, req, req->get_index(), &cost, &m_ware_supplies);
      else
         supp = find_best_supply(g, req, req->get_index(), &cost, &m_worker_supplies);

		if (!supp)
			continue;

		if (req->is_idle()) {
			idletime = 0;
		} else {
			// Calculate the time the building will be forced to idle waiting
			// for the request
			idletime = g->get_gametime() + 15000 + 2*cost - req->get_required_time();

			if (not supp->is_active()) {
				// If the building wouldn't have to idle, we wait with the request
				if (idletime < -200) {
					if (s->nexttimer < 0 || s->nexttimer > (-idletime))
						s->nexttimer = -idletime;

					continue;
				}
			} else {
				// If the Supply is active (i.e. idle ware), we always fulfill
				// a Request
				if (idletime < 1)
					idletime = 1;
			}

			// TODO: priorities?

			if (idletime <= 0)
				idletime = 1;
		}

		// If its a soldier, then mark to prevent re-request this soldier.
		// If we don't do this, then the same soldier can be re-requested, this cause a
		// degrade of soldier levels
		if (req->get_type() == Request::SOLDIER)
		{
			// This is to prevent a soldier to try to supply more than one Request.
			// With this also ensures that you have enought soldiers
			if (supp->get_passing_requeriments(g, req->get_index(), req->get_requeriments()) > 0)
			{
				supp->mark_as_used (g, req->get_index(), req->get_requeriments());
			}
			else
				continue;
		}

		// Otherwise, consider this request/supply pair for queueing
		RequestSupplyPair rsp;

		rsp.is_item = false;
		rsp.is_worker = false;
		rsp.is_soldier = false;

		switch (req->get_type())
		{
		case Request::WARE:    rsp.is_item    = true; break;
		case Request::WORKER:  rsp.is_worker  = true; break;
		case Request::SOLDIER: rsp.is_soldier = true; break;
		}

		rsp.ware = req->get_index();
		rsp.request = req;
		rsp.supply = supp;
		rsp.priority = idletime;

		log
			("REQ: %u (%i) <- %u (ware %i), priority %i\n",
			 req->get_target()->get_serial(),
			 req->get_required_time(), supp->get_position(g)->get_serial(),
			 rsp.ware, rsp.priority);

		s->queue.push(rsp);
	}

	// TODO: This function should be called from time to time
	create_requested_workers (g);
}

/*
===============
Economy::create_requested_workers

Walk all Requests and find requests of workers than aren't supplied. Then try to create
the worker at warehouses.
===============
*/
void Economy::create_requested_workers(Game* g)
{
	/*
		Find the request of workers that can not be supplied
	*/
	if (get_nr_warehouses() > 0) {
		for(RequestList::iterator it = m_requests.begin(); it != m_requests.end(); ++it) {
			Request* req = *it;

			if (!req->is_idle() && ((req->get_type()==Request::WORKER) || (req->get_type()==Request::SOLDIER))) {
				int index = req->get_index();
				int num_wares = 0;
            Worker_Descr* w_desc=get_owner()->get_tribe()->get_worker_descr(index);

				// Ignore it if is a worker that cann't be buildable
				if (!w_desc->get_buildable())
					continue;

				for(int i = 0; i < m_worker_supplies[index].get_nrsupplies(); i++) {
					Supply* supp = m_worker_supplies[index].get_supply(i);

					if (not supp->is_active()) {
						if (req->has_requeriments())
						{
							if (supp->get_passing_requeriments (g, index, req->get_requeriments()))
								num_wares++;
						}
						else
						{
							num_wares++;
							continue;
						}
					} // if (supp->is_active)
				} // for(int i = 0; i < m_worker_supplies)

				// If there aren't enough supplies...
				if (num_wares == 0) {

					uint n_wh = 0;
					while (n_wh < get_nr_warehouses()) {
						if (m_warehouses[n_wh]->can_create_worker(g, index)) {
log("Economy::process_request-- Created a '%s' needed\n", w_desc->get_name());
							m_warehouses[n_wh]->create_worker(g, index);
							//break;
						} // if (m_warehouses[n_wh]
						n_wh++;
					} // while (n_wh < get_nr_warehouses())
				} // if (num_wares == 0)
			} // if (req->is_open())
		} // for (RequestList::iterator
	} // if (get_nr_warehouses())
}


/*
===============
Economy::balance_requestsupply

Balance Requests and Supplies by collecting and weighing pairs, and
starting transfers for them.
===============
*/
void Economy::balance_requestsupply()
{
	RSPairStruct rsps;

   m_request_timer = false;

	rsps.nexttimer = -1;

	if (Game *const game = dynamic_cast<Game * const>(&m_owner->egbase())) {

	// Try to fulfill non-idle Requests
	process_requests(game, &rsps);

	// Now execute request/supply pairs
	while(rsps.queue.size()) {
		RequestSupplyPair rsp = rsps.queue.top();

		rsps.queue.pop();

		if (!rsp.request || !rsp.supply ||
			!have_request(rsp.request) ||
			(((rsp.is_soldier)  && !have_worker_supply(rsp.ware, rsp.supply)) ||
			((rsp.is_worker)  && !have_worker_supply(rsp.ware, rsp.supply)) ||
			((rsp.is_item) && !have_ware_supply(rsp.ware, rsp.supply)))) {
			log("NO: ware %i, priority %i\n", rsp.ware, rsp.priority);

			rsps.nexttimer = 200;
			continue;
		}

		log
			("HANDLE: %u -> %u, ware %i, priority %i\n",
			 rsp.request->get_target()->get_serial(),
			 rsp.supply->get_position(game)->get_serial(),
			 rsp.ware,
			 rsp.priority);

		rsp.request->start_transfer(game, rsp.supply);

		// for multiple wares
		if (rsp.request && have_request(rsp.request)) {
			log("  request is still around, reschedule timer\n");
			rsps.nexttimer = 200;
		}
	}

	// restart the timer, if necessary
	if (rsps.nexttimer > 0) {
		log("  nexttimer: %i\n", rsps.nexttimer);
		start_request_timer(rsps.nexttimer);
	}
	}
}

/*
===============
Cmd_Call_Economy_Balance

Called by Cmd_Queue as requested by start_request_timer().
Call economy functions to balance supply and request.
===============
*/
void Cmd_Call_Economy_Balance::execute(Game* g) {
   Player* plr=g->get_player(m_player);

   // If this economy has vanished, drop this
   // call silently
   if(!plr->has_economy(m_economy))
      return;

   if(!m_economy->should_run_balance_check(g->get_gametime()) && !m_force_balance)
      return;

   m_force_balance = false;
   m_economy->balance_requestsupply();
}

/*
 * Read and write
 */
#define CURRENT_CMD_CALL_ECONOMY_VERSION 1
void Cmd_Call_Economy_Balance::Read(FileRead* fr, Editor_Game_Base* egbase, Widelands_Map_Map_Object_Loader* mol) {
   int version=fr->Unsigned16();

   if(version==CURRENT_CMD_CALL_ECONOMY_VERSION) {
      // Read Base Commands
      BaseCommand::BaseCmdRead(fr,egbase,mol);

      m_player= fr->Unsigned8();
      bool exists=fr->Unsigned8();
      if(!exists)
         m_economy=((Economy*) 0xffffffff);
      else
         m_economy=egbase->get_player(m_player)->get_economy_by_number(fr->Unsigned16());

      m_force_balance = true; // on load, the first balance has to been forced
   } else
      throw wexception("Unknown version %i in Cmd_Call_Economy_Balance::Read()!\n", version);
}
void Cmd_Call_Economy_Balance::Write(FileWrite* fw, Editor_Game_Base* egbase, Widelands_Map_Map_Object_Saver* mos) {
   fw->Unsigned16(CURRENT_CMD_CALL_ECONOMY_VERSION);

   // Write Base Commands
   BaseCommand::BaseCmdWrite(fw,egbase,mos);

   fw->Unsigned8(m_player);

   // Economy
   Player* plr = egbase->get_player(m_player);
   bool has_eco=plr->has_economy(m_economy);

   fw->Unsigned8(has_eco);

   if(has_eco)
      fw->Unsigned16(plr->get_economy_number(m_economy));
}
