The code around this assert is:

`void planquadrat_t::boden_ersetzen(grund_t *alt, grund_t *neu)`

{

assert(alt!=NULL && neu!=NULL && !alt->is_halt() );

...

Now neu and alt should always be valid (see below). is_halt here refers to actual stations rather than waypoints. So the most likely scenario I think is that you were doing something which required changing grounds at a station. A full backtrace from a reproducible error would of course be very handy

boden ersetzen itself is not called from that many places in simutrans:

`gebaeude_t* hausbauer_t::baue(karte_t* welt, spieler_t* sp, koord3d pos, int org_layout, const haus_besch_t* besch, void* param)`

{

...

for(k.y = 0; k.y < dim.y; k.y ++) {

for(k.x = 0; k.x < dim.x; k.x ++) {

...

grund_t *gr = welt->lookup_kartenboden(pos.get_2d() + k);

...

grund_t *gr2 = new fundament_t(welt, gr->get_pos(), gr->get_grund_hang());

welt->access(gr->get_pos().get_2d())->boden_ersetzen(gr, gr2);

...

Here there are numerous places before boden_ersetzen which assume gr is valid, and gr2 must be valid.

`fabrik_t::~fabrik_t()`

{

...

if (plan) {

grund_t *gr = plan->get_kartenboden();

...

plan->boden_ersetzen( gr, new boden_t( welt, gr->get_pos(), hang_t::flach ) );

...

Here plan and thus gr must be valid , as is new boden_t.

`void fabrik_t::baue(sint32 rotate, bool build_fields, bool force_initial_prodbase)`

{

...

for( uint16 i=0; i<fields.get_count(); i++ ) {

const koord k = fields[i].location;

grund_t *gr=welt->lookup_kartenboden(k);

...

grund_t *gr2 = new fundament_t(welt, gr->get_pos(), gr->get_grund_hang());

welt->access(k)->boden_ersetzen(gr, gr2);

...

Here gr should be valid assuming fields have been allocated valid positions.

`bool fabrik_t::add_random_field(uint16 probability)`

{

...

grund_t *gr = welt->lookup_kartenboden(pos.get_2d()+koord(xoff,yoff));

if (gr != NULL &&

...

build_locations.append(gr);

...

if (!build_locations.empty()) {

grund_t *gr = build_locations.at(simrand(build_locations.get_count()));

...

grund_t *gr2 = new fundament_t(welt, gr->get_pos(), gr->get_grund_hang());

welt->access(k)->boden_ersetzen(gr, gr2);

...

Here gr and gr2 must be valid.

`void planquadrat_t::kartenboden_setzen(grund_t *bd)`

{

assert(bd);

grund_t *tmp = get_kartenboden();

if(tmp) {

boden_ersetzen(tmp,bd);

Here tmp and bd must be valid.

`bool wkz_remover_t::wkz_remover_intern(spieler_t *sp, karte_t *welt, koord3d pos, const char *&msg)`

{

...

grund_t *gr = welt->lookup(pos);

if (!gr) {

msg = "";

return false;

}

...

koord k(pos.get_2d());

...

welt->access(k)->boden_ersetzen( gr, new boden_t(welt, gr->get_pos(), welt->recalc_natural_slope(k,dummy) ) );

...

Here gr and boden_t must be valid.

`...`

const char *wkz_wayremover_t::do_work( karte_t *welt, spieler_t *sp, const koord3d &start, const koord3d &end )

{

...

grund_t *gr=welt->lookup(verbindung.position_bei(i));

// ground can be missing after deleting a bridge ...

if(gr && !gr->ist_wasser()) {

...

grund_t *gr_new = new boden_t(welt, gr->get_pos(), gr->get_grund_hang());

welt->access(gr->get_pos().get_2d())->boden_ersetzen(gr, gr_new);

...

Here gr and gr_new must be valid.