
###################################################
# A forest simulation involving lumberjacks, bears and trees

# An attempt at the https://www.reddit.com/r/dailyprogrammer/comments/27h53e/662014_challenge_165_hard_simulated_ecology_the/ challange

# First attempt at such a large program/simulation, requires complete restructing and refactoring. Need to use the MVC design pattern or similar
# achieve desired results, a logger or similar needs to be built and was missed in this version. Due to the poor architecture of the code many new
# features and additions/changes to the existing code would be very difficult and generation of bugs would occur. 

###################################################

import cells, os, time, random

sizeX, sizeY = 40, 40

# Generate grid and define the size of the grid
grid10x10 = cells.grid(sizeX,sizeY)
grid10x10.generate()

main_controller = cells.controller(grid10x10)

main_controller.randomly_distribute_object_in_grid(0, cells.plant, 10)
main_controller.randomly_distribute_object_in_grid(1, cells.lumberjack, 1)
main_controller.randomly_distribute_object_in_grid(2, cells.bear, 1)

def cell_gen(z):
	for row in grid10x10.grid_list:
		for column in row:
			yield (column[z])


def update_cells(month):
	plant_age_updates = []
	plant_reproduce_updates = []
	lumberjack_updates =[]
	bear_updates = []
	lumber_count = 0
	lumber_count_annual = 0
	mauled_count_annual = 0

	for item in cell_gen(0):
		try:

			if item[0].age >= 12:
				plant_reproduce_updates.append(item[0])
				plant_age_updates.append(item[0])
	

			elif item[0].age < 12:
				plant_age_updates.append(item[0])

		except IndexError:
			pass
		
	for item in cell_gen(1):
		try:
			if item[0].type == cells.lumberjack.type:
				lumberjack_updates.append(item[0])

		except IndexError:
			pass


	for item in cell_gen(2):
		try:
			if item[0].type == cells.bear.type:
				bear_updates.append(item[0])

		except IndexError:
			pass

	for plant in plant_age_updates:
		plant.increase_age()

	for plant in plant_reproduce_updates:
		plant.reproduce()

	for jack in lumberjack_updates:
		jack.move()
		lumber_count += jack.lumber_monthly
		jack.lumber_monthly = 0

	for bear in bear_updates:
		bear.move()
		bear.mauled_monthly = 0

	if month % 12 == 0:


		for jack in lumberjack_updates:
			lumber_count_annual += jack.lumber_annual
			jack.lumber_annual = 0

		if lumber_count_annual >= len(lumberjack_updates):
			N = 0
			while not(N <= lumber_count_annual and N + 9 >= lumber_count_annual):
				# print()
				N += 10


			for number in range(0, int(N / 10)):
				hire_new_object(cells.lumberjack, 1)


		elif lumber_count_annual < len(lumberjack_updates) and len(lumberjack_updates) > 1:
			lumberjack_removed = False
			while not(lumberjack_removed):
				try:
					rand_lumberjack = lumberjack_updates[random.randint(0,len(lumberjack_updates)) - 1]
					rand_lumberjack.remove()
					lumberjack_removed = True

				except IndexError:
					pass


		for bear in bear_updates:
			mauled_count_annual += bear.mauled_annual
			bear.mauled_annual = 0

		if mauled_count_annual < len(lumberjack_updates):
			hire_new_object(cells.bear, 2)


		elif mauled_count_annual > len(lumberjack_updates):
			bear_removed = False
			while not(bear_removed):
				try:
					rand_bear = bear_updates[random.randint(0,len(bear_updates)) - 1]
					rand_bear.remove()
					bear_removed = True

				except IndexError:
					pass
	return len(bear_updates), len(lumberjack_updates)

def hire_new_object(object, z):
	randX, randY = random.randint(0,sizeX - 1), random.randint(0,sizeX - 1)
	main_controller.append_object_to_cell(randX,randY,z, object)


def tick(N):

	for n in range(1,N + 1):
		grid10x10.print_grid()
		b, l = update_cells(n)

		print("month" , n, "bears", b, "lumberjacks", l)


		time.sleep(0.1)

		os.system("cls")



		# print("\n")
		# print(10 * "-")

tick(4500)
