<commit_before>
#include "world.hh"
#include "actor.hh"
#include "common.hh"
#include "logger.hh"

namespace {

	Tile TileBuilder(std::string type) {
		Tile tile;
		if (type == "window") {
			tile = Tile('*', COLOR_BLUE, BLOCKS);
			tile.blocks_vision_dist = 2;
		} else if (type == "door_open") {
			tile = Tile('/', COLOR_YELLOW, !BLOCKS);
		} else if (type.substr(0,4) == "door") {
			tile = Tile('+', COLOR_RED, BLOCKS);
		}
		return tile;
	}

	static const Tile ground('.', COLOR_GREEN, !BLOCKS);
	static const Tile grass('"', COLOR_GREEN, !BLOCKS);
	static const Tile plaza(':', COLOR_GREEN, !BLOCKS);
	static const Tile housefloor('.', COLOR_YELLOW, !BLOCKS);

	static const Tile wall('#', COLOR_CYAN, BLOCKS);
	static const Tile window(TileBuilder("window"));
	static const Tile tree('T', COLOR_GREEN, BLOCKS);

	static const Tile door_open(TileBuilder("door_open"));
	static const Tile door_closed(TileBuilder("door_closed"));
	static const Tile door_locked(TileBuilder("door_locked"));

}

void World::createCity(int xhouses, int yhouses) {
	int housew = 12;
	int househ = 9;
	int streetwidth = 5;
	int offset = 2;
	int maxfurnit = 8;

	if (xhouses < 0) xhouses = 10;
	if (yhouses < 0) yhouses = 10;
	width = xhouses * (housew + streetwidth) + streetwidth + 2;
	height = yhouses * (househ + streetwidth) + streetwidth + 2;

	for (int j = 0; j < height; j++) {
		tilerow row;
		for (int i = 0; i < width; i++) row.push_back(Tile());
		tiles.push_back(row);
	}

	// Array for special house locations
	int CityPlan[xhouses][yhouses];
	for (int j = 0; j < yhouses; ++j)
		for (int i = 0; i < xhouses; ++i)
			CityPlan[i][j] = 0;

	// Array for amounts of special buildings
	int BuildingPlan[6];
	int total = 0;
	// Create amounts for special buildings
	do {
		BuildingPlan[1] = randint(1,5); // plazas
		BuildingPlan[2] = randint(1,2) + randint(0,4); // inns
		BuildingPlan[3] = randint(1,2) + randint(0,4); // smiths/shops
		BuildingPlan[4] = randint(0,1) + randint(0,1) + randint(0,1); // churches
		BuildingPlan[5] = randint(0,1) + randint(0,1) + randint(0,1); // stables
		total = BuildingPlan[1]+BuildingPlan[2]+BuildingPlan[3]+BuildingPlan[4]+BuildingPlan[5];
	} while (total > xhouses * yhouses - 4);
	// Put Town Hall in the middle
	int townhallx, townhally;
	if ((xhouses % 2) == 0) townhallx = xhouses/2; else townhallx = floor(xhouses/2.0) + randint(2);
	if ((yhouses % 2) == 0) townhally = yhouses/2; else townhally = floor(yhouses/2.0) + randint(2);
	CityPlan[townhallx][townhally] = 10;
	CityPlan[townhallx+1][townhally] = 11;
	CityPlan[townhallx][townhally+1] = 11;
	CityPlan[townhallx+1][townhally+1] = 11;
	// Position rest of the special buildings (roughly)
	for (int k = 0; k < total; ++k) {
		int i,j,b;
		while (CityPlan[i=randint(xhouses)][j=randint(yhouses)]);
		while (!BuildingPlan[b = randint(1,5)]);
		BuildingPlan[b]--;
		CityPlan[i][j] = b;
	}
	// Fine tune positioning and generate the structures
	for (int j = 0; j < yhouses; ++j) {
		for (int i = 0; i < xhouses; ++i) {
			int x1 = 1 + streetwidth + i * (housew+streetwidth);
			int y1 = 1 + streetwidth + j * (househ+streetwidth);
			int x2 = x1 + housew;
			int y2 = y1 + househ;
			switch (CityPlan[i-1][j-1]) {
				case 1:
					createPlaza(x1, y1, x2, y2); break;
				//case 2:
					//createInn(x1 + randint(0,offset/2), y1 + randint(0,offset/2), x2 - randint(0,offset/2), y2 - randint(0,offset)/2); break;
				//case 3:
					//createShop(x1 + randint(0,offset), y1 + randint(0,offset), x2 - randint(0,offset), y2 - randint(0,offset)); break;
				//case 4:
					//createChurch(x1 + randint(0,offset/2), y1 + randint(0,offset/2), x2 - randint(0,offset/2), y2 - randint(0,offset/2)); break;
				//case 5:
					//createStable(x1 + randint(0,offset), y1 + randint(0,offset), x2 - randint(0,offset), y2 - randint(0,offset)); break;
				//case 10:
					//createTownHall(x1, y1, x1 + streetwidth + 2*housesize, y1 + streetwidth + 2*housesize); break;
				case 11:
					break;
				default:
					createHouse(x1 + randint(-offset,offset), y1 + randint(-offset,offset), x2 - randint(-offset,offset), y2 - randint(-offset,offset), randint(4,maxfurnit), randint(0,1)); break;
			}
		}
	}
	// Do outer wall and make rest of tiles ground
	for (int j = 0; j < height; ++j) {
		for (int i = 0; i < width; ++i) {
			if (i == 0 || j == 0 || i == width-1 || j == height-1) tiles[j][i] = wall;
			else if (tiles[j][i].ch == ' ') tiles[j][i] = ground;
		}
	}
}


void World::createHouse(int x1, int y1, int x2, int y2, int furnit, int locked) {
	makeWallsAndFloor(x1,y1,x2,y2,housefloor);
	int housetype = randint(0,2);
	if (housetype) { // Split house
		bool horiz = randint(1);
		int doorx, doory;
		if (horiz) { // Horizontal wall
			int wy = randint(y1+3,y2-3);
			doorx = randint(x1+1,x2-1);
			doory = wy;
			for (int i = x1; i <= x2; ++i) {
				if (i != doorx || housetype == 2) tiles[wy][i] = wall;
			}
			//AddFurniture(x1+1,y1+1,x2-1,wy-1,furnit/2);
			//AddFurniture(x1+1,wy+1,x2-1,y2-1,furnit/2);
		} else { // Vertical wall
			int wx = randint(x1+3,x2-3);
			doory = randint(y1+1,y2-1);
			doorx = wx;
			for (int j = y1; j <= y2; ++j) {
				if (j != doory || housetype == 2) tiles[j][wx] = wall;
			}
			//AddFurniture(x1+1,y1+1,wx-1,y2-1,furnit/2);
			//AddFurniture(wx+1,y1+1,x2-1,y2-1,furnit/2);
		}
		// Create doors
		if (housetype == 1) { // Two-room house
			makeDoor(doorx,doory,randint(-1,1));
			randDoor(x1,y1,x2,y2,(randint(0,9)==0));
		} else if (housetype == 2) { // Two separate houses
			if (horiz) { // Horizontal wall
				makeDoor(randint(x1+1,x2-1),y1,(randint(0,9)==0));
				makeDoor(randint(x1+1,x2-1),y2,(randint(0,9)==0));
			} else { // Vertical wall
				makeDoor(x1,randint(y1+1,y2-1),(randint(0,9)==0));
				makeDoor(x2,randint(y1+1,y2-1),(randint(0,9)==0));
			}
		}

	} else { // No wall / single-room house
		//AddFurniture(x1+1,y1+1,x2-1,y2-1,furnit)
		randDoor(x1,y1,x2,y2,(randint(0,9)==0));
	}
}


void World::createPlaza(int x1, int y1, int x2, int y2) {
	if (randint(1)) {
		Tile tex = randint(3) ? plaza : grass;
		for (int j = y1; j <= y2; ++j) {
			for (int i = x1; i <= x2; ++i) {
				tiles[j][i] = tex;
			}
		}
	}
}


/*
void World::CreateTownHall(x1,y1,x2,y2)
	makeWallsAndFloor(x1,y1,x2,y2,diamondpat)
	xx = (x1+x2)/2
	yy = (y1+y2)/2
	if (randint(0,1) = 0) { // horizontal
		wy1 = y1 + (y2-y1)/3
		wy2 = y1 + (y2-y1)/3*2
		wx = x1 + (x2-x1)/3*randint(1,2)
		wx1 = x1 + randint((x2-x1)/3,(x2-x1)/3*2)
		wx2 = x1 + randint((x2-x1)/3,(x2-x1)/3*2)
		wx3 = x1 + randint((x2-x1)/3,(x2-x1)/3*2)
		wx4 = x1 + randint((x2-x1)/3,(x2-x1)/3*2)
		for (int i = x1;  <= x2
			tiles[i,wy1) = wall
			tiles[i,wy2) = wall
			tiles[i,(y1+wy1)/2) = wall
			tiles[i,(y2+wy2)/2) = wall
		}
		for (int j = wy1;  <= wy2; tiles[wx,j) = wall; }
		for (int j = y1;  <= (y1+wy1)/2; tiles[wx1,j) = wall; }
		for (int j = (y1+wy1)/2;  <= wy1; tiles[wx2,j) = wall; }
		for (int j = wy2;  <= (wy2+y2)/2; tiles[wx3,j) = wall; }<commit_msg>Fine tune generator (smaller scale), add parks.<commit_after>
#include "world.hh"
#include "actor.hh"
#include "common.hh"
#include "logger.hh"

namespace {

	Tile TileBuilder(std::string type) {
		Tile tile;
		if (type == "window") {
			tile = Tile('*', COLOR_BLUE, BLOCKS);
			tile.blocks_vision_dist = 2;
		} else if (type == "door_open") {
			tile = Tile('/', COLOR_YELLOW, !BLOCKS);
		} else if (type.substr(0,4) == "door") {
			tile = Tile('+', COLOR_RED, BLOCKS);
		}
		return tile;
	}

	static const Tile ground('.', COLOR_GREEN, !BLOCKS);
	static const Tile grass('"', COLOR_GREEN, !BLOCKS);
	static const Tile plaza(':', COLOR_GREEN, !BLOCKS);
	static const Tile housefloor('.', COLOR_YELLOW, !BLOCKS);

	static const Tile wall('#', COLOR_CYAN, BLOCKS);
	static const Tile window(TileBuilder("window"));
	static const Tile tree('T', COLOR_GREEN, BLOCKS);

	static const Tile door_open(TileBuilder("door_open"));
	static const Tile door_closed(TileBuilder("door_closed"));
	static const Tile door_locked(TileBuilder("door_locked"));

}

void World::createCity(int xhouses, int yhouses) {
	int housew = 8;
	int househ = 6;
	int streetwidth = 3;
	int offset = 1;
	int maxfurnit = 6;

	if (xhouses < 0) xhouses = 10;
	if (yhouses < 0) yhouses = 10;
	width = xhouses * (housew + streetwidth + 1) + streetwidth + 2;
	height = yhouses * (househ + streetwidth + 1) + streetwidth + 2;
	int xyhouses = xhouses * yhouses;

	for (int j = 0; j < height; j++) {
		tilerow row;
		for (int i = 0; i < width; i++) row.push_back(Tile());
		tiles.push_back(row);
	}

	// Array for special house locations
	int CityPlan[xhouses][yhouses];
	for (int j = 0; j < yhouses; ++j)
		for (int i = 0; i < xhouses; ++i)
			CityPlan[i][j] = 0;

	// Array for amounts of special buildings
	int BuildingPlan[6];
	int total = 0;
	// Create amounts for special buildings
	do {
		BuildingPlan[1] = xyhouses / randint(6,12); // plazas
		BuildingPlan[2] = randint(1,2) + randint(0,4); // inns
		BuildingPlan[3] = randint(1,2) + randint(0,4); // smiths/shops
		BuildingPlan[4] = randint(1,2) + randint(0,1) + randint(0,1); // churches
		BuildingPlan[5] = randint(1,2) + randint(0,1) + randint(0,1); // stables
		total = BuildingPlan[1]+BuildingPlan[2]+BuildingPlan[3]+BuildingPlan[4]+BuildingPlan[5];
	} while (total > xhouses * yhouses - 4); // 4 is for town hall
	// Put Town Hall in the middle
	int townhallx, townhally;
	if ((xhouses % 2) == 0) townhallx = xhouses/2; else townhallx = floor(xhouses/2.0) + randint(2);
	if ((yhouses % 2) == 0) townhally = yhouses/2; else townhally = floor(yhouses/2.0) + randint(2);
	CityPlan[townhallx][townhally] = 10;
	CityPlan[townhallx+1][townhally] = 11;
	CityPlan[townhallx][townhally+1] = 11;
	CityPlan[townhallx+1][townhally+1] = 11;
	// Position rest of the special buildings (roughly)
	for (int k = 0; k < total; ++k) {
		int i,j,b;
		while (CityPlan[i=randint(xhouses)][j=randint(yhouses)]);
		while (!BuildingPlan[b = randint(1,5)]);
		BuildingPlan[b]--;
		CityPlan[i][j] = b;
	}
	// Fine tune positioning and generate the structures
	for (int j = 0; j < yhouses; ++j) {
		for (int i = 0; i < xhouses; ++i) {
			int x1 = 1 + streetwidth + i * (housew+streetwidth+1);
			int y1 = 1 + streetwidth + j * (househ+streetwidth+1);
			int x2 = x1 + housew;
			int y2 = y1 + househ;
			switch (CityPlan[i][j]) {
				case 1:
					createPlaza(x1, y1, x2, y2); break;
				//case 2:
					//createInn(x1 + randint(0,offset/2), y1 + randint(0,offset/2), x2 - randint(0,offset/2), y2 - randint(0,offset)/2); break;
				//case 3:
					//createShop(x1 + randint(0,offset), y1 + randint(0,offset), x2 - randint(0,offset), y2 - randint(0,offset)); break;
				//case 4:
					//createChurch(x1 + randint(0,offset/2), y1 + randint(0,offset/2), x2 - randint(0,offset/2), y2 - randint(0,offset/2)); break;
				//case 5:
					//createStable(x1 + randint(0,offset), y1 + randint(0,offset), x2 - randint(0,offset), y2 - randint(0,offset)); break;
				//case 10:
					//createTownHall(x1, y1, x1 + streetwidth + 2*housesize, y1 + streetwidth + 2*housesize); break;
				case 11:
					break;
				default:
					createHouse(x1 + randint(-offset,offset), y1 + randint(-offset,offset), x2 - randint(-offset,offset), y2 - randint(-offset,offset), randint(4,maxfurnit), randint(0,1)); break;
			}
		}
	}
	// Do outer wall and make rest of tiles ground
	for (int j = 0; j < height; ++j) {
		for (int i = 0; i < width; ++i) {
			if (i == 0 || j == 0 || i == width-1 || j == height-1) tiles[j][i] = wall;
			else if (tiles[j][i].ch == ' ') tiles[j][i] = ground;
		}
	}
}


void World::createHouse(int x1, int y1, int x2, int y2, int furnit, int locked) {
	makeWallsAndFloor(x1,y1,x2,y2,housefloor);
	int housetype = randint(0,2);
	if (housetype) { // Split house
		bool horiz = randint(1);
		int doorx, doory;
		if (horiz) { // Horizontal wall
			int wy = randint(y1+3,y2-3);
			doorx = randint(x1+1,x2-1);
			doory = wy;
			for (int i = x1; i <= x2; ++i) {
				if (i != doorx || housetype == 2) tiles[wy][i] = wall;
			}
			//AddFurniture(x1+1,y1+1,x2-1,wy-1,furnit/2);
			//AddFurniture(x1+1,wy+1,x2-1,y2-1,furnit/2);
		} else { // Vertical wall
			int wx = randint(x1+3,x2-3);
			doory = randint(y1+1,y2-1);
			doorx = wx;
			for (int j = y1; j <= y2; ++j) {
				if (j != doory || housetype == 2) tiles[j][wx] = wall;
			}
			//AddFurniture(x1+1,y1+1,wx-1,y2-1,furnit/2);
			//AddFurniture(wx+1,y1+1,x2-1,y2-1,furnit/2);
		}
		// Create doors
		if (housetype == 1) { // Two-room house
			makeDoor(doorx,doory,randint(-1,1));
			randDoor(x1,y1,x2,y2,(randint(0,9)==0));
		} else if (housetype == 2) { // Two separate houses
			if (horiz) { // Horizontal wall
				makeDoor(randint(x1+1,x2-1),y1,(randint(0,9)==0));
				makeDoor(randint(x1+1,x2-1),y2,(randint(0,9)==0));
			} else { // Vertical wall
				makeDoor(x1,randint(y1+1,y2-1),(randint(0,9)==0));
				makeDoor(x2,randint(y1+1,y2-1),(randint(0,9)==0));
			}
		}

	} else { // No wall / single-room house
		//AddFurniture(x1+1,y1+1,x2-1,y2-1,furnit)
		randDoor(x1,y1,x2,y2,(randint(0,9)==0));
	}
}


void World::createPlaza(int x1, int y1, int x2, int y2) {
	bool park = randint(2);
	bool style = randint(2);
	for (int j = y1; j <= y2; ++j) {
		for (int i = x1; i <= x2; ++i) {
			Tile tile(ground);
			if (park) tile = randint(6) ? grass : tree;
			else if (style) tile = plaza;
			tiles[j][i] = tile;
		}
	}
}


/*
void World::CreateTownHall(x1,y1,x2,y2)
	makeWallsAndFloor(x1,y1,x2,y2,diamondpat)
	xx = (x1+x2)/2
	yy = (y1+y2)/2
	if (randint(0,1) = 0) { // horizontal
		wy1 = y1 + (y2-y1)/3
		wy2 = y1 + (y2-y1)/3*2
		wx = x1 + (x2-x1)/3*randint(1,2)
		wx1 = x1 + randint((x2-x1)/3,(x2-x1)/3*2)
		wx2 = x1 + randint((x2-x1)/3,(x2-x1)/3*2)
		wx3 = x1 + randint((x2-x1)/3,(x2-x1)/3*2)
		wx4 = x1 + randint((x2-x1)/3,(x2-x1)/3*2)
		for (int i = x1;  <= x2
			tiles[i,wy1) = wall
			tiles[i,wy2) = wall
			tiles[i,(y1+wy1)/2) = wall
			tiles[i,(y2+wy2)/2) = wall
		}
		for (int j = wy1;  <= wy2; tiles[wx,j) = wall; }
		for (int j = y1;  <= (y1+wy1)/2; tiles[wx1,j) = wall; }
		for (int j = (y1+wy1)/2;  <= wy1; tiles[wx2,j) = wall; }
		for (int j = wy2;  <= (wy2+y2)/2; tiles[wx3,j) = wall; }
{'fraction_non_alphanumeric': 0.1978811149032992, 'fraction_numerical': 0.05688282138794084, 'mean_word_length': 3.571010724731882, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '48129', 'n_tokens_mistral': 6879, 'n_tokens_neox': 6182, 'n_words': 1352}