Example #1
0
static int tolua_region_create(lua_State * L)
{
    int x = (int)tolua_tonumber(L, 1, 0);
    int y = (int)tolua_tonumber(L, 2, 0);
    const char *tname = tolua_tostring(L, 3, 0);
    if (tname) {
        plane *pl = findplane(x, y);
        const terrain_type *terrain = get_terrain(tname);
        region *r, *result;
        if (!terrain) {
            return 0;
        }

        assert(!pnormalize(&x, &y, pl));
        r = result = findregion(x, y);

        if (r != NULL && r->units != NULL) {
            /* TODO: error message */
            result = NULL;
        }
        else if (r == NULL) {
            result = new_region(x, y, pl, 0);
        }
        if (result) {
            terraform_region(result, terrain);
            if (result->land) {
                fix_demand(result);
            }
        }

        tolua_pushusertype(L, result, TOLUA_CAST "region");
        return 1;
    }
    return 0;
}
Example #2
0
static void test_ships(CuTest * tc)
{
    const char * data = "{\"ships\": { \"boat\" : { "
        "\"construction\" : { \"maxsize\" : 20, \"reqsize\" : 10, \"minskill\" : 1 },"
        "\"coasts\" : [ \"plain\" ]"
        "}}}";

    cJSON *json = cJSON_Parse(data);
    const ship_type *st;
    const terrain_type *ter;

    test_cleanup();

    CuAssertPtrNotNull(tc, json);
    CuAssertPtrEquals(tc, 0, shiptypes);
    json_config(json);

    CuAssertPtrNotNull(tc, shiptypes);
    st = st_find("boat");
    CuAssertPtrNotNull(tc, st);
    CuAssertPtrNotNull(tc, st->construction);
    CuAssertIntEquals(tc, 10, st->construction->reqsize);
    CuAssertIntEquals(tc, 20, st->construction->maxsize);
    CuAssertIntEquals(tc, 1, st->construction->minskill);

    ter = get_terrain("plain");
    CuAssertPtrNotNull(tc, ter);

    CuAssertPtrNotNull(tc, st->coasts);
    CuAssertPtrEquals(tc, (void *)ter, (void *)st->coasts[0]);
    CuAssertPtrEquals(tc, 0, (void *)st->coasts[1]);

    test_cleanup();
}
Example #3
0
void gamemap::set_terrain(const map_location& loc, const t_translation::terrain_code & terrain, const terrain_type_data::merge_mode mode, bool replace_if_failed) {
	if(!on_board_with_border(loc)) {
		DBG_G << "set_terrain: " << loc << " is not on the map.\n";
		// off the map: ignore request
		return;
	}

	t_translation::terrain_code new_terrain = tdata_->merge_terrains(get_terrain(loc), terrain, mode, replace_if_failed);

	if(new_terrain == t_translation::NONE_TERRAIN) {
		return;
	}

	if(on_board(loc)) {
		const bool old_village = is_village(loc);
		const bool new_village = tdata_->is_village(new_terrain);

		if(old_village && !new_village) {
			villages_.erase(std::remove(villages_.begin(),villages_.end(),loc),villages_.end());
		} else if(!old_village && new_village) {
			villages_.push_back(loc);
		}
	}

	(*this)[loc] = new_terrain;
}
Example #4
0
void frame_title()
{
	static uint16_t gamepad_oldstate = gamepad_start;

	// move sprites from level 0
	if (gamepad_buttons[0] & ~gamepad_oldstate & gamepad_start) { 

		// reset game
		lives = START_LIVES;
		level = START_LEVEL;
		//
		enter_leveltitle();

	} else if (gamepad_buttons[0] & ~gamepad_oldstate & gamepad_select) {
		// XXX SFX
		load_next();
		enter_title(); // re-enter title
	}


	// kinda like animate_tilemap only simpler
	uint8_t tile_line = vga_frame%8; // tile line to process == 0-7
	for (int i=0;i<16;i++) { // process one line each frame.
		uint8_t *c = &data[(TILE_TITLE_Y*16+tile_line)*256+TILE_TITLE_X*16+i];
		if (get_terrain(*c)==terrain_animated_empty) {
			*c += (*c%4!=3) ? 1 : -3;
		}
	}

	gamepad_oldstate = gamepad_buttons[0];
}
Example #5
0
void gamemap::set_terrain(const map_location& loc, const t_translation::t_terrain & terrain, const terrain_type_data::tmerge_mode mode, bool replace_if_failed) {
	if(!on_board_with_border(loc)) {
		// off the map: ignore request
		return;
	}

	t_translation::t_terrain new_terrain = tdata_->merge_terrains(get_terrain(loc), terrain, mode, replace_if_failed);

	if(new_terrain == t_translation::NONE_TERRAIN) {
		return;
	}

	if(on_board(loc)) {
		const bool old_village = is_village(loc);
		const bool new_village = tdata_->is_village(new_terrain);

		if(old_village && !new_village) {
			villages_.erase(std::remove(villages_.begin(),villages_.end(),loc),villages_.end());
		} else if(!old_village && new_village) {
			villages_.push_back(loc);
		}
	}

	tiles_[loc.x + border_size_][loc.y + border_size_] = new_terrain;

	// Update the off-map autogenerated tiles
	map_location adj[6];
	get_adjacent_tiles(loc,adj);

	for(int n = 0; n < 6; ++n) {
		remove_from_border_cache(adj[n]);
	}
}
Example #6
0
// -- tilemap-related functions
void get_level_boundingbox(void)
{
	current_level_color=get_property(level,level_color);

	// scan level enclosing rectangle in tiles and fill level_x1,y1,x2,y2
	for (int x=0;x<16;x++) {
		for (int y=0;y<16;y++)
			// any one of the row is the level color ? ok this is the start
			if (get_terrain(y*16+x)==current_level_color) {
				level_x1=x;
				goto getx2;
			}
	}

	getx2:
	for (int x=15;x>=level_x1;x--) {
		for (int y=0;y<16;y++)
			// any one of the row is the level color ? ok this is the end
			if (get_terrain(y*16+x)==current_level_color) {
				level_x2=x;
				goto gety1;
			}
	}

	gety1:
	for (int y=0;y<16;y++) {
		for (int x=0;x<16;x++)
			// any one of the row is the level color ? ok this is the start
			if (get_terrain(y*16+x)==current_level_color) {
				level_y1=y;
				goto gety2;
			}
	}
	
	gety2: 
	for (int y=15;y>=level_y1;y--) {
		for (int x=0;x<16;x++)
			// any one of the row is the level color ? ok this is the end
			if (get_terrain(y*16+x)==current_level_color) {
				level_y2=y;
				goto finished;
			}
	}

	finished: 
	message("Level found to be from %dx%d-%dx%d\n",level_x1,level_y1,level_x2,level_y2);
}
Example #7
0
static void test_terrains(CuTest * tc)
{
    const char * data = "{\"terrains\": { \"plain\" : { \"flags\" : [ \"land\", \"fly\", \"walk\" ] } }}";
    const terrain_type *ter;

    cJSON *json = cJSON_Parse(data);

    test_cleanup();
    CuAssertPtrNotNull(tc, json);
    CuAssertPtrEquals(tc, 0, (void *)get_terrain("plain"));

    json_config(json);
    ter = get_terrain("plain");
    CuAssertPtrNotNull(tc, ter);
    CuAssertIntEquals(tc, ter->flags, LAND_REGION|FLY_INTO|WALK_INTO);

    test_cleanup();
}
Example #8
0
static int tolua_make_block(lua_State * L)
{
    int x = (int)tolua_tonumber(L, 1, 0);
    int y = (int)tolua_tonumber(L, 2, 0);
    int r = (int)tolua_tonumber(L, 3, 6);
    const char *str = tolua_tostring(L, 4, TOLUA_CAST "ocean");
    const struct terrain_type *ter = get_terrain(str);

    make_block(x, y, r, ter);
    return 0;
}
Example #9
0
static int tolua_region_set_terrain(lua_State * L)
{
    region *r = (region *)tolua_tousertype(L, 1, 0);
    const char *tname = tolua_tostring(L, 2, 0);
    if (tname) {
        const terrain_type *terrain = get_terrain(tname);
        if (terrain) {
            terraform_region(r, terrain);
        }
    }
    return 0;
}
Example #10
0
terrain_type *
test_create_terrain(const char * name, unsigned int flags)
{
  terrain_type * t;

  assert(!get_terrain(name));
  t = (terrain_type*)calloc(1, sizeof(terrain_type));
  t->_name = _strdup(name);
  t->flags = flags;
  register_terrain(t);
  return t;
}
std::set<map_location> editor_map::get_contiguous_terrain_tiles(const map_location& start) const
{
	t_translation::t_terrain terrain = get_terrain(start);
	std::set<map_location> result;
	std::deque<map_location> queue;
	result.insert(start);
	queue.push_back(start);
	//this is basically a breadth-first search along adjacent hexes
	do {
		map_location adj[6];
		get_adjacent_tiles(queue.front(), adj);
		for (int i = 0; i < 6; ++i) {
			if (on_board_with_border(adj[i]) && get_terrain(adj[i]) == terrain
			&& result.find(adj[i]) == result.end()) {
				result.insert(adj[i]);
				queue.push_back(adj[i]);
			}
		}
		queue.pop_front();
	} while (!queue.empty());
	return result;
}
gamemap editor_map::mask_to(const gamemap& target) const
{
	if (target.w() != w() || target.h() != h()) {
		throw editor_action_exception(_("The size of the target map is different from the current map"));
	}
	gamemap mask(target);
	map_location iter;
	for (iter.x = -border_size(); iter.x < w() + border_size(); ++iter.x) {
		for (iter.y = -border_size(); iter.y < h() + border_size(); ++iter.y) {
			if (target.get_terrain(iter) == get_terrain(iter)) {
				mask.set_terrain(iter, t_translation::FOGGED);
			}
		}
	}
	return mask;
}
Example #13
0
void animate_tilemap(void) {
	// process 1/16th of screen vertically each frame (or maybe just 1/16th of tiles if bigger screen)
	uint8_t tile_line = vga_frame%16; // tile line to process == 0-15 (assumes VGA_V_PIXELS <= 256 )

	// all tiles horizontally : 320/16 = 20 tiles
	for (int i=0;i<VGA_H_PIXELS/16;i++) {	
		uint8_t *c = &data[(camera_y/16+tile_line)*256+camera_x/16+i];
		uint8_t t = get_terrain(*c);
		if (t==terrain_animated_empty || t==terrain_anim_kill) {
			if (*c%4!=3) {
				*c +=1 ;
			} else {
				*c -= 3;
			}
		}
	}
}
Example #14
0
int json_import(struct stream * out) {
    cJSON *json, *child;
    char buffer[1024], *data = 0;
    size_t sz = 0;
    assert(out && out->api);
    while (!out->api->readln(out->handle, buffer, sizeof(buffer))) {
        size_t len = strlen(buffer);
        data = (char *)realloc(data, sz + len + 1);
        memcpy(data + sz, buffer, len);
        sz += len;
        data[sz] = 0;
    }
    json = cJSON_Parse(data);
    child = cJSON_GetObjectItem(json, "regions");
    if (child && child->type == cJSON_Object) {
        cJSON *j;
        for (j = child->child; j; j = j->next) {
            cJSON *attr;
            unsigned int id = 0;
            int x = 0, y = 0;
            region * r;

            id = (unsigned int)atol(j->string);
            if ((attr = cJSON_GetObjectItem(j, "x")) != 0 && attr->type == cJSON_Number) x = attr->valueint;
            if ((attr = cJSON_GetObjectItem(j, "y")) != 0 && attr->type == cJSON_Number) y = attr->valueint;
            r = new_region(x, y, 0, id);
            if ((attr = cJSON_GetObjectItem(j, "type")) != 0 && attr->type == cJSON_String) {
                const terrain_type *terrain = get_terrain(attr->valuestring);
                terraform_region(r, terrain);
            }
            if ((attr = cJSON_GetObjectItem(j, "name")) != 0 && attr->type == cJSON_String) {
                region_setname(r, attr->valuestring);
            }
        }
    }
    cJSON_Delete(json);
    return 0;
}
Example #15
0
	bool is_village(const map_location& loc) const
		{ return on_board(loc) && is_village(get_terrain(loc)); }
Example #16
0
	std::string get_terrain_editor_string(const map_location& loc) const
		{ return get_terrain_editor_string(get_terrain(loc)); }
Example #17
0
	const t_translation::t_list& underlying_union_terrain(const map_location& loc) const
		{ return underlying_union_terrain(get_terrain(loc)); }
Example #18
0
	/** Shortcut to get_terrain_info(get_terrain(loc)). */
	const terrain_type& get_terrain_info(const map_location &loc) const
		{ return get_terrain_info(get_terrain(loc)); }
Example #19
0
bool gamemap::is_castle(const map_location& loc) const
	{ return on_board(loc) && is_castle(get_terrain(loc)); }
Example #20
0
std::string gamemap::get_terrain_string(const map_location& loc) const
	{ return get_terrain_string(get_terrain(loc)); }
Example #21
0
/** Shortcut to get_terrain_info(get_terrain(loc)). */
const terrain_type& gamemap::get_terrain_info(const map_location &loc) const
{
	return tdata_->get_terrain_info(get_terrain(loc));
}
Example #22
0
// load sprites from tilemap if onscreen, or unload them to tilemap if offscreen
void manage_sprites( void )
{	
	int modified=0;

	// first unload offscreen sprites ( put them back on tilemap)
	for (int i=1;i<MAX_SPRITES;i++) { // 0 is the player :)
		if (sprite[i].type == SPRITE_FREE ) continue;
		else if (
			sprite[i].x/256 - camera_x + sprtype[sprite[i].type].w < -32 || 
			sprite[i].x/256 - camera_x > VGA_H_PIXELS+32 || 
			sprite[i].y/256 - camera_y + sprtype[sprite[i].type].h < -32 || 
			sprite[i].y/256 - camera_y > VGA_V_PIXELS+32 
			) {
			message("Hiding sprite %d (%d,%d) of type %d outside of screen\n",i,sprite[i].x/256, sprite[i].y/256, sprite[i].type);


			if (data[sprite[i].tx!=255 || sprite[i].ty!=255]) {
				uint8_t typ = sprite[i].type;
				bool respawn=true;

				// active : respawn, else re-spawn if typ has specific values
				if (typ>=SPRITE_INACTIVE) {
					typ-=SPRITE_INACTIVE;
					respawn = (typ == col_none || typ==col_kill);
				}
				
				// get type color & put back on tilemap if respawn
				if (respawn) 
					data[sprite[i].ty*256+sprite[i].tx] = get_property(typ+4,property_color); 
			}
			sprite[i].type=SPRITE_FREE;
			modified=1;
		}
	}

	// load sprites
	// TODO : scan only borders after initial scan of visible screen since center is normally done

	for (int j=-2;j<(240/16+2);j++)
		for (int i=-2;i<(320/16+2);i++)
		{
			uint8_t *c = &data[(camera_y/16+j)*256+camera_x/16+i]; // tile id
			for (int spt=0;spt<NB_SPRITETYPES;spt++)
				if (*c==sprtype[spt].color && *c != TRANSPARENT) {
					struct Sprite *spr = spawn_sprite(spt, 
						(camera_x/16+i)*16*256, 
						(camera_y/16+j)*16*256
						);

					// put where we found it in 
					spr->tx = camera_x/16+i;
					spr->ty = camera_y/16+j;
					modified=1;	// will display sth on console
					
					// modify tilemap with nearest empty (assumes at least one nearby)
					for (int dx=-1;dx<1;dx++)
						for (int dy=-1;dy<1;dy++) {
							uint8_t d=*(c+dx+dy*256);
							if (get_terrain(d)==terrain_empty) { // near one is an empty ? use it
								*c=d;
								goto done;
							}
						}
					*c=*(c-256); // in doubt, set to upper one

					done: 
					break; // found sprite color in index, done
				}
		}

	if (modified) {	
		message("now sprites :");
		for (int i=0;i<MAX_SPRITES;i++) {
		    if (sprite[i].type==SPRITE_FREE)
		    	message ("   ");
			else if (sprite[i].type>=SPRITE_INACTIVE)
	    		message("-%02x",sprite[i].type- SPRITE_INACTIVE );
	    	else 
				message("%02x ",sprite[i].type);
		}
		message("\n");
	}
}
Example #23
0
void gamemap::write_terrain(const map_location &loc, config& cfg) const
{
	cfg["terrain"] = t_translation::write_terrain_code(get_terrain(loc));
}
Example #24
0
void create_museum(void)
{
#if 0                           /* TODO: move this to Lua. It should be possible. */
    unsigned int museum_id = hashstring("museum");
    plane *museum = getplanebyid(museum_id);
    region *r;
    building *b;
    const terrain_type *terrain_hall = get_terrain("hall1");
    const terrain_type *terrain_corridor = get_terrain("corridor1");

    assert(terrain_corridor && terrain_hall);

    if (!museum) {
        museum = create_new_plane(museum_id, "Museum", 9500, 9550,
            9500, 9550, PFL_MUSEUM);
    }

    if (findregion(9525, 9525) == NULL) {
        /* Eingangshalle */
        r = new_region(9525, 9525, 0);
        terraform_region(r, terrain_hall);
        r->planep = museum;
        rsetname(r, "Eingangshalle");
        rsethorses(r, 0);
        rsetmoney(r, 0);
        rsetpeasants(r, 0);
        set_string(&r->display,
            "Die Eingangshalle des Großen Museum der 1. Welt ist bereits jetzt ein beeindruckender Anblick. Obwohl das Museum noch nicht eröffnet ist, vermittelt sie bereits einen Flair exotischer Welten. In den Boden ist ein großer Kompass eingelassen, der den Besuchern bei Orientierung helfen soll.");
    }

    r = findregion(9526, 9525);
    if (!r) {
        /* Lounge */
        r = new_region(9526, 9525, 0);
        terraform_region(r, terrain_hall);
        r->planep = museum;
        rsetname(r, "Lounge");
        rsethorses(r, 0);
        rsetmoney(r, 0);
        rsetpeasants(r, 0);
        set_string(&r->display,
            "Die Lounge des großen Museums ist ein Platz, in dem sich die Besucher treffen, um die Eindrücke, die sie gewonnen haben, zu verarbeiten. Gemütliche Sitzgruppen laden zum Verweilen ein.");
    }

    r = findregion(9526, 9525);
    if (!r->buildings) {
        const building_type *bt_generic = bt_find("generic");
        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im dämonischen Stil");
        set_string(&b->display,
            "Diese ganz im dämonischen Stil gehaltene Sitzgruppe ist ganz in dunklen Schwarztönen gehalten. Muster fremdartiger Runen bedecken das merkwürdig geformte Mobiliar, das unangenehm lebendig wirkt.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im elfischen Stil");
        set_string(&b->display,
            "Ganz in Grün- und Brauntönen gehalten wirkt die Sitzgruppe fast lebendig. Bei näherer Betrachtung erschließt sich dem Betrachter, daß sie tatsächlich aus lebenden Pflanzen erstellt ist. So ist der Tisch aus einem eizigen Baum gewachsen, und die Polster bestehen aus weichen Grassoden. Ein wunderschön gemusterter Webteppich mit tausenden naturgetreu eingestickter Blumensarten bedeckt den Boden.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im halblingschen Stil");
        set_string(&b->display,
            "Dieses rustikale Mobiliar ist aus einem einzigen, gewaltigen Baum hergestellt worden. Den Stamm haben fleißige Halblinge der Länge nach gevierteilt und aus den vier langen Viertelstämmen die Sitzbänke geschnitzt, während der verbleibende Stumpf als Tisch dient. Schon von weitem steigen dem Besucher die Gerüche der Köstlichkeiten entgegen, die auf dem Tisch stapeln.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im orkischen Stil");
        set_string(&b->display,
            "Grobgeschreinerte, elfenhautbespannte Stühle und ein Tisch aus Knochen, über deren Herkunft man sich lieber keine Gedanken macht, bilden die Sitzgruppe im orkischen Stil. Überall haben Orks ihre Namen, und anderes wenig zitierenswertes in das Holz und Gebein geritzt.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im Meermenschenstil");
        set_string(&b->display,
            "Ganz in Blau- und Grüntönen gehalten, mit Algen und Muscheln verziert wirken die aus altem Meerholz geschnitzten Stühle immer ein wenig feucht. Seltsammerweise hat der schwere aus alten Planken gezimmerte Tisch einen Mast mit kompletten Segel in der Mitte.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im Katzenstil");
        set_string(&b->display,
            "Die Wände dieses Séparée sind aus dunklem Holz. Was aus der Ferne wie ein chaotisch durchbrochenes Flechtwerk wirkt, entpuppt sich bei näherer Betrachtung als eine bis in winzige Details gestaltete dschungelartige Landschaft, in die eine Vielzahl von kleinen Bildergeschichten eingewoben sind. Wie es scheint hat sich der Künstler Mühe gegeben wirklich jedes Katzenvolk Eresseas zu porträtieren. Das schummrige Innere wird von einem Kamin dominiert, vor dem einige Sessel und weiche Kissen zu einem gemütlichen Nickerchen einladen. Feiner Anduner Sisal bezieht die Lehnen der Sessel und verlockt dazu, seine Krallen hinein zu versenken. Auf einem kleinen Ecktisch steht ein großer Korb mit roten Wollknäulen und grauen und braunen Spielmäusen.");
    } else {
        for (b = r->buildings; b; b = b->next) {
            b->size = b->type->maxsize;
        }
    }

    r = findregion(9524, 9526);
    if (!r) {
        r = new_region(9524, 9526, 0);
        terraform_region(r, terrain_corridor);
        r->planep = museum;
        rsetname(r, "Nördliche Promenade");
        rsethorses(r, 0);
        rsetmoney(r, 0);
        rsetpeasants(r, 0);
        set_string(&r->display,
            "Die Nördliche Promenade führt direkt in den naturgeschichtlichen Teil des Museums.");
    }
    r = findregion(9525, 9524);
    if (!r) {
        r = new_region(9525, 9524, 0);
        terraform_region(r, terrain_corridor);
        r->planep = museum;
        rsetname(r, "Südliche Promenade");
        rsethorses(r, 0);
        rsetmoney(r, 0);
        rsetpeasants(r, 0);
        set_string(&r->display,
            "Die Südliche Promenade führt den Besucher in den kulturgeschichtlichen Teil des Museums.");
    }
#endif
}
Example #25
0
/** create new island with up to nsize players
 * returns the number of players placed on the new island.
 */
int autoseed(newfaction ** players, int nsize, int max_agediff)
{
    region *r = NULL;
    region_list *rlist = NULL;
    int rsize = 0, tsize = 0;
    int isize = REGIONS_PER_FACTION;      /* target size for the island */
    int psize = 0;                /* players on this island */
    const terrain_type *volcano_terrain = get_terrain("volcano");
    static int nterrains = -1;
    static const terrain_type **terrainarr = 0;
    static int *distribution;

    assert(players);
    if (nterrains < 0) {
        int n = 0;
        const terrain_type *terrain = terrains();
        for (nterrains = 0; terrain; terrain = terrain->next) {
            if (terrain->distribution) {
                ++nterrains;
            }
        }
        terrainarr = malloc(sizeof(terrain_type *) * nterrains);
        distribution = malloc(sizeof(int) * nterrains);
        for (terrain = terrains(); terrain; terrain = terrain->next) {
            if (terrain->distribution) {
                terrainarr[n] = terrain;
                distribution[n++] = terrain->distribution;
            }
        }
    }
    frame_regions(16, newterrain(T_FIREWALL));

    if (listlen(*players) < MINFACTIONS)
        return 0;

    if (max_agediff > 0) {
        region *rmin = NULL;
        plane *hplane = get_homeplane();
        /* find a spot that's adjacent to the previous island, but virgin.
         * like the last land virgin ocean region adjacent to land.
         */
        for (r = regions; r; r = r->next) {
            struct plane *pl = rplane(r);
            if (r->age <= max_agediff && r->terrain == newterrain(T_OCEAN)
                && pl == hplane && virgin_region(r)) {
                direction_t d;
                for (d = 0; d != MAXDIRECTIONS; ++d) {
                    region *rn = rconnect(r, d);
                    if (rn && rn->land && rn->age <= max_agediff && virgin_region(rn)) {
                        /* only expand islands that aren't single-islands and not too big already */
                        int size, inhabitants, maxage;
                        get_island_info(rn, &size, &inhabitants, &maxage);
                        if (maxage <= max_agediff && size >= 2 && size < MAXISLANDSIZE) {
                            rmin = rn;
                            break;
                        }
                    }
                }
            }
        }
        if (rmin != NULL) {
            faction *f;
            quicklist *ql, *rlist = get_island(rmin);
            int qi;

            for (ql = rlist, qi = 0; ql; ql_advance(&ql, &qi, 1)) {
                region *r = (region *)ql_get(ql, qi);
                unit *u;
                for (u = r->units; u; u = u->next) {
                    f = u->faction;
                    if (!fval(f, FFL_MARK)) {
                        ++psize;
                        fset(f, FFL_MARK);
                    }
                }
            }
            ql_free(rlist);
            if (psize > 0) {
                for (f = factions; f; f = f->next) {
                    freset(f, FFL_MARK);
                }
            }
            if (psize < PLAYERS_PER_ISLAND) {
                r = rmin;
            }
        }
    }
    if (r == NULL) {
        region *rmin = NULL;
        direction_t dmin = MAXDIRECTIONS;
        plane *hplane = get_homeplane();
        /* find an empty spot.
         * rmin = the youngest ocean region that has a missing neighbour
         * dmin = direction in which it's empty
         */
        for (r = regions; r; r = r->next) {
            struct plane *pl = rplane(r);
            if (r->terrain == newterrain(T_OCEAN) && pl == hplane && (rmin == NULL
                || r->age <= max_agediff)) {
                direction_t d;
                for (d = 0; d != MAXDIRECTIONS; ++d) {
                    region *rn = rconnect(r, d);
                    if (rn == NULL)
                        break;
                }
                if (d != MAXDIRECTIONS) {
                    rmin = r;
                    dmin = d;
                }
            }
        }

        /* create a new region where we found the empty spot, and make it the first
         * in our island. island regions are kept in rlist, so only new regions can
         * get populated, and old regions are not overwritten */
        if (rmin != NULL) {
            plane *pl = rplane(rmin);
            int x = rmin->x + delta_x[dmin];
            int y = rmin->y + delta_y[dmin];
            pnormalize(&x, &y, pl);
            assert(virgin_region(rconnect(rmin, dmin)));
            r = new_region(x, y, pl, 0);
            terraform_region(r, newterrain(T_OCEAN));
        }
    }
    if (r != NULL) {
        add_regionlist(&rlist, r);
        fset(r, RF_MARK);
        rsize = 1;
    }

    while (rsize && (nsize || isize >= REGIONS_PER_FACTION)) {
        int i = rng_int() % rsize;
        region_list **rnext = &rlist;
        region_list *rfind;
        direction_t d;
        while (i--)
            rnext = &(*rnext)->next;
        rfind = *rnext;
        r = rfind->data;
        freset(r, RF_MARK);
        *rnext = rfind->next;
        free(rfind);
        --rsize;
        for (d = 0; d != MAXDIRECTIONS; ++d) {
            region *rn = rconnect(r, d);
            if (rn && fval(rn, RF_MARK))
                continue;
            if (rn == NULL) {
                plane *pl = rplane(r);
                int x = r->x + delta_x[d];
                int y = r->y + delta_y[d];
                pnormalize(&x, &y, pl);
                rn = new_region(x, y, pl, 0);
                terraform_region(rn, newterrain(T_OCEAN));
            }
            if (virgin_region(rn)) {
                add_regionlist(&rlist, rn);
                fset(rn, RF_MARK);
                ++rsize;
            }
        }
        if (volcano_terrain != NULL && (rng_int() % VOLCANO_CHANCE == 0)) {
            terraform_region(r, volcano_terrain);
        }
        else if (nsize && (rng_int() % isize == 0 || rsize == 0)) {
            newfaction **nfp, *nextf = *players;
            faction *f;
            unit *u;

            isize += REGIONS_PER_FACTION;
            terraform_region(r, preferred_terrain(nextf->race));
            prepare_starting_region(r);
            ++tsize;
            assert(r->land && r->units == 0);
            u = addplayer(r, addfaction(nextf->email, nextf->password, nextf->race,
                nextf->lang, nextf->subscription));
            f = u->faction;
            fset(f, FFL_ISNEW);
            f->alliance = nextf->allies;

            /* remove duplicate email addresses */
            nfp = &nextf->next;
            while (*nfp) {
                newfaction *nf = *nfp;
                if (strcmp(nextf->email, nf->email) == 0) {
                    *nfp = nf->next;
                    free_newfaction(nf);
                }
                else
                    nfp = &nf->next;
            }
            *players = nextf->next;
            free_newfaction(nextf);

            ++psize;
            --nsize;
            --isize;
            if (psize >= PLAYERS_PER_ISLAND)
                break;
        }
        else {
            terraform_region(r, random_terrain(terrainarr, distribution, nterrains));
            --isize;
        }
    }

    if (nsize != 0) {
        log_error(
            ("Could not place all factions on the same island as requested\n"));
    }

    if (rlist) {
#define MINOCEANDIST 3
#define MAXOCEANDIST 6
#define MAXFILLDIST 10
#define SPECIALCHANCE 80
        region_list **rbegin = &rlist;
        int special = 1;
        int oceandist = MINOCEANDIST + (rng_int() % (MAXOCEANDIST - MINOCEANDIST));
        while (oceandist--) {
            region_list **rend = rbegin;
            while (*rend)
                rend = &(*rend)->next;
            while (rbegin != rend) {
                direction_t d;
                region *r = (*rbegin)->data;
                rbegin = &(*rbegin)->next;
                for (d = 0; d != MAXDIRECTIONS; ++d) {
                    region *rn = rconnect(r, d);
                    if (rn == NULL) {
                        const struct terrain_type *terrain = newterrain(T_OCEAN);
                        plane *pl = rplane(r);
                        int x = r->x + delta_x[d];
                        int y = r->y + delta_y[d];
                        pnormalize(&x, &y, pl);
                        rn = new_region(x, y, pl, 0);
                        if (rng_int() % SPECIALCHANCE < special) {
                            terrain = random_terrain(terrainarr, distribution, nterrains);
                            special = SPECIALCHANCE / 3;      /* 33% chance auf noch eines */
                        }
                        else {
                            special = 1;
                        }
                        terraform_region(rn, terrain);
                        /* the new region has an extra 20% chance to have mallorn */
                        if (rng_int() % 100 < 20)
                            fset(r, RF_MALLORN);
                        add_regionlist(rend, rn);
                    }
                }
            }

        }
        while (*rbegin) {
            region *r = (*rbegin)->data;
            plane *pl = rplane(r);
            direction_t d;
            rbegin = &(*rbegin)->next;
            for (d = 0; d != MAXDIRECTIONS; ++d)
                if (rconnect(r, d) == NULL) {
                    int i;
                    for (i = 1; i != MAXFILLDIST; ++i) {
                        int x = r->x + delta_x[d] * i;
                        int y = r->y + delta_y[d] * i;
                        pnormalize(&x, &y, pl);
                        if (findregion(x, y)) {
                            break;
                        }
                    }
                    if (i != MAXFILLDIST) {
                        while (--i) {
                            region *rn;
                            int x = r->x + delta_x[d] * i;
                            int y = r->y + delta_y[d] * i;
                            pnormalize(&x, &y, pl);
                            rn = new_region(x, y, pl, 0);
                            terraform_region(rn, newterrain(T_OCEAN));
                        }
                    }
                }
        }
        while (rlist) {
            region_list *self = rlist;
            rlist = rlist->next;
            freset(self->data, RF_MARK);
            free(self);
        }
    }
    return tsize;
}
Example #26
0
/* Cheap hack of process_exit from overland.c for ships */
ch_ret process_shipexit( char_data * ch, short map, short x, short y, int dir )
{
   int sector = get_terrain( map, x, y ), move;
   room_index *from_room;
   ship_data *ship = ch->on_ship;
   ch_ret retcode;
   short fx, fy, fmap;

   from_room = ch->in_room;
   fx = ch->mx;
   fy = ch->my;
   fmap = ch->cmap;

   retcode = rNONE;
   if( ch->has_pcflag( PCFLAG_MAPEDIT ) )
   {
      ch->print( "Get off the ship before you start editing.\r\n" );
      return rSTOP;
   }

   if( sector == SECT_EXIT )
   {
      mapexit_data *mexit;
      room_index *toroom = NULL;

      mexit = check_mapexit( map, x, y );

      if( mexit != NULL )
      {
         if( mexit->tomap != -1 )   /* Means exit goes to another map */
         {
            if( !can_move_ship( ch, get_terrain( mexit->tomap, mexit->therex, mexit->therey ) ) )
               return rSTOP;

            enter_map( ch, NULL, mexit->therex, mexit->therey, mexit->tomap );
            if( ch->mount )
               enter_map( ch->mount, NULL, mexit->therex, mexit->therey, mexit->tomap );

            list < char_data * >::iterator ich;
            size_t chars = from_room->people.size(  );
            size_t count = 0;
            for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
            {
               char_data *fch = *ich;
               ++ich;
               ++count;

               if( fch != ch  /* loop room bug fix here by Thoric */
                   && fch->master == ch && ( fch->position == POS_STANDING || fch->position == POS_MOUNTED ) && fch->mx == fx && fch->my == fy && fch->cmap == fmap )
               {
                  if( !fch->isnpc(  ) )
                  {
                     act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[dir], TO_CHAR );
                     process_exit( fch, fch->cmap, x, y, dir, false );
                  }
                  else
                     enter_map( fch, NULL, mexit->therex, mexit->therey, mexit->tomap );
               }
            }
            return rSTOP;
         }

         if( !( toroom = get_room_index( mexit->vnum ) ) )
         {
            bug( "%s: Target vnum %d for map exit does not exist!", __FUNCTION__, mexit->vnum );
            ch->print( "Ooops. Something bad happened. Contact the immortals ASAP.\r\n" );
            return rSTOP;
         }

         if( !can_move_ship( ch, toroom->sector_type ) )
            return rSTOP;

         if( !str_cmp( ch->name, ship->owner ) )
            act_printf( AT_ACTION, ch, NULL, dir_name[dir], TO_ROOM, "%s sails off to the $T.", ship->name.c_str(  ) );

         ch->on_ship->room = toroom->vnum;

         leave_map( ch, NULL, toroom );

         list < char_data * >::iterator ich;
         size_t chars = from_room->people.size(  );
         size_t count = 0;
         for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
         {
            char_data *fch = *ich;
            ++ich;
            ++count;

            if( fch != ch  /* loop room bug fix here by Thoric */
                && fch->master == ch && fch->position == POS_STANDING && fch->mx == fx && fch->my == fy && fch->cmap == fmap )
            {
               if( !fch->isnpc(  ) )
               {
                  act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[dir], TO_CHAR );
                  process_shipexit( fch, fch->cmap, x, y, dir );
               }
               else
                  leave_map( fch, ch, toroom );
            }
         }
         return rSTOP;
      }
   }

   switch ( dir )
   {
      default:
         ch->print( "Alas, you cannot go that way...\r\n" );
         return rSTOP;

      case DIR_NORTH:
         if( y == -1 )
         {
            ch->print( "You cannot sail any further north!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_EAST:
         if( x == MAX_X )
         {
            ch->print( "You cannot sail any further east!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_SOUTH:
         if( y == MAX_Y )
         {
            ch->print( "You cannot sail any further south!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_WEST:
         if( x == -1 )
         {
            ch->print( "You cannot sail any further west!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_NORTHEAST:
         if( x == MAX_X || y == -1 )
         {
            ch->print( "You cannot sail any further northeast!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_NORTHWEST:
         if( x == -1 || y == -1 )
         {
            ch->print( "You cannot sail any further northwest!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_SOUTHEAST:
         if( x == MAX_X || y == MAX_Y )
         {
            ch->print( "You cannot sail any further southeast!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_SOUTHWEST:
         if( x == -1 || y == MAX_Y )
         {
            ch->print( "You cannot sail any further southwest!\r\n" );
            return rSTOP;
         }
         break;
   }

   if( !can_move_ship( ch, sector ) )
      return rSTOP;

   move = sect_show[sector].move;

   if( ship->fuel < move && !ch->is_immortal(  ) )
   {
      ch->print( "Your ship is too low on magical energy to sail further ahead.\r\n" );
      return rSTOP;
   }

   if( !ch->is_immortal(  ) && !str_cmp( ch->name, ship->owner ) )
      ship->fuel -= move;

   if( !str_cmp( ch->name, ship->owner ) )
      act_printf( AT_ACTION, ch, NULL, dir_name[dir], TO_ROOM, "%s sails off to the $T.", ship->name.c_str(  ) );

   ch->mx = x;
   ch->my = y;
   ship->mx = x;
   ship->my = y;

   if( !str_cmp( ch->name, ship->owner ) )
   {
      const char *txt = rev_exit( dir );
      act_printf( AT_ACTION, ch, NULL, NULL, TO_ROOM, "%s sails in from the %s.", ship->name.c_str(  ), txt );
   }

   list < char_data * >::iterator ich;
   size_t chars = from_room->people.size(  );
   size_t count = 0;
   for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
   {
      char_data *fch = *ich;
      ++ich;
      ++count;

      if( fch != ch  /* loop room bug fix here by Thoric */
          && fch->master == ch && ( fch->position == POS_STANDING || fch->position == POS_MOUNTED ) && fch->mx == fx && fch->my == fy )
      {
         if( !fch->isnpc(  ) )
         {
            act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[dir], TO_CHAR );
            process_exit( fch, fch->cmap, x, y, dir, false );
         }
         else
         {
            fch->mx = x;
            fch->my = y;
         }
      }
   }
   interpret( ch, "look" );
   return retcode;
}
Example #27
0
	int gives_healing(const map_location& loc) const
		{ return on_board(loc) ?  gives_healing(get_terrain(loc)) : 0; }
Example #28
0
const t_translation::t_list& gamemap::underlying_def_terrain(const map_location& loc) const
	{ return underlying_def_terrain(get_terrain(loc)); }
Example #29
0
	bool is_keep(const map_location& loc) const
		{ return on_board(loc) && is_keep(get_terrain(loc)); }
Example #30
0
bool region_isocean(const struct region *r)
{
    return r->terrain == get_terrain(T_OCEAN);
}