REM Ini
sync on
sync rate 30
set display mode 1024, 768, 32
set window position 1, 1
set camera range 1, 100000
autocam off
 
REM Set
global num_islands as integer : num_islands = 5 `number of random islands
global rad_islands as float : rad_islands = 20 `island radius (avg) in matrix tile units
global environment_size as float : environment_size = 5000.0 `size of simulation in DB units
global seconds_to_starve as integer : seconds_to_starve = 60
global sink_speed as float : sink_speed = 1.0
 
f = 3
#Constant starting_corpses = 500/f
#Constant starting_prokaryotes = 500/f
#Constant starting_plankton = 500/f
#Constant starting_crab = 100/f
#Constant starting_krill = 200/f
#Constant starting_seal = 50/f
#Constant starting_squid = 100/f
#Constant starting_whale = 5/f
#Constant starting_penguin = 50/f
#Constant starting_fish = 100/f
#Constant starting_bird = 10/f
#Constant starting_nutrients = 500/f
 
REM Con
#Constant CORPSE 0
#Constant PROKARYOTES 1
#Constant PLANKTON 2
#Constant CRAB 3
#Constant KRILL 4
#Constant SEAL 5
#Constant SQUID 6
#Constant WHALE 7
#Constant PENGUIN 8
#Constant FISH 9
#Constant BIRD 10
#Constant NUTRIENTS 11
 
#Constant float_max_velocity 1.0
#Constant loops_to_turn_max 600
#Constant bird_minimum_height 100.0
#Constant bird_maximum_height 1300.0
#Constant bound_creatures 800
 
REM Typ
type xyz
	x as float
	y as float
	z as float
endtype
type creature_types
	name as string
	obj as integer
 
	days_to_grow as float
	start_weight as float
	adult_weight as float
 
	height as float
 
	max_vel as float
	move_mode as string
	sexually_reproduce as integer
	food_dec_per_loop as float
 
	prey_1 as integer
	prey_2 as integer
	prey_3 as integer
 
	r
	g
	b
endtype
type creatures
	kind as integer
	obj as integer
	gender as integer
	weight as float
	food as float
	age as float
	ang as xyz
	vel as xyz
	time_to_turn as integer
	remove as integer
	zonex
	zoney
	zonez
endtype
 
REM Var
global mtx_ocean as integer
global mtx_ground as integer
global calc_alt as integer
global oldmc
global mc
global return_x as float
global return_y as float
global return_z as float
 
REM Arr
global max_creatures as integer : max_creatures = 0
global max_a as integer : max_a = 15 : global amt_a as integer
#Constant max_creature_types 11
#Constant ocean_tiles 25
#Constant max_msg 10
DIM c(max_creatures) as creatures
DIM a(max_a) as integer
DIM t(max_creature_types) as creature_types
DIM w(ocean_tiles, ocean_tiles) as integer
dim msg(max_msg) as string
dim msg_species(max_creature_types) as integer
 
REM Load Environment
make_ground()
make_water()
position camera 800.0, 1600.0, 800.0
point camera environment_size/2.0, 0.0, environment_size/2.0
 
REM Load Creatures
` set_creature_type(i, name, days_to_grow, , adult_weight, max_vel, , , reproduce_mode, move_mode,
` prey_1, prey_2, prey_3, color_r, color_g, color_b, number of starting)
set_creature_type(0, "Corpse", 		0.0, 	5.0, 	0.0, 	-1, "Sink", -1, -1, -1, 0, 0, 0, starting_corpses)
set_creature_type(1, "Prokaryotes", 0.1, 	6.0, 	0.0, 	0, "Float", CORPSE, -1, -1, 255, 170, 0, starting_prokaryotes)
set_creature_type(2, "Plankton", 	0.1, 	6.0, 	0.0, 	0, "Float", NUTRIENTS, -1, -1, 0, 255, 0, starting_plankton)
set_creature_type(3, "Crab", 			1.0, 	10.0, 1.0, 	1, "Walk", CORPSE, -1, -1, 255, 0, 0, starting_crab)
set_creature_type(4, "Krill", 		0.5, 	8.0, 0.0, 	1, "Float", PLANKTON, -1, -1, 255, 255, 0, starting_krill)
set_creature_type(5, "Seal", 			10.0, 35.0, 5.0, 	1, "SwimWalk", KRILL, PENGUIN, FISH, 190, 190, 190, starting_seal)
set_creature_type(6, "Squid", 		5.0, 	12.0, 10.0, 1, "Swim", KRILL, -1, -1, 255, 128, 64, starting_squid)
set_creature_type(7, "Sperm Whale", 5.0, 	100.0,2.5, 	1, "Swim", KRILL, SEAL, SQUID, 0, 0, 255, starting_whale)
set_creature_type(8, "Penguin", 		10.0, 25.0, 1.0, 	1, "SwimWalk", SQUID, CRAB, -1, 32, 32, 32, starting_penguin)
set_creature_type(9, "Fish", 			0.1, 	20.0, 7.5, 	1, "Swim", SQUID, CRAB, -1, 100, 170, 220, starting_fish)
set_creature_type(10, "Albatross", 	5.0, 	25.0, 20.0, 1, "Fly", FISH, SQUID, -1, 240, 240, 240, starting_bird)
set_creature_type(11, "Nutrients", 	0.0, 	5.0, 	0.0, 	-1, "Float", -1, -1, -1, 255, 0, 255, starting_nutrients)
 
REM Main
do
	REM Display data for user
	set cursor 0,0
	print "FPS: " + str$(screen fps())
	print "Press (numpad '+') for max FPS or (numpad 'Enter') for 30 FPS"
	print
	print "Total creatures: " + str$(max_creatures)
 
	inc calc_alt
	if calc_alt = 15 then calc_alt = 0
 
	do_mouse()
	do_interface()
	do_waves()
	do_creatures()
 
	sync
loop
 
function do_interface()
	if calc_alt = 0
		for n = 0 to max_creature_types
			msg_species(n) = count_species(n)
		next n
	endif
 
	REM Display species data
	for n = 0 to max_creature_types
		ink rgb(t(n).r, t(n).g, t(n).b), 0
		print t(n).name + ": " + str$(msg_species(n))
	next n
 
	REM Display messages
	print
	ink rgb(255,255,0),0
	for n = 0 to max_msg
		print msg(n)
	next n
endfunction
 
function do_creatures()
	REM Remove creature (required to be in a separate do loop) (once per 15 loops)
	if calc_alt = 12
		for n = 1 to max_creatures
			if n < max_creatures or n = max_creatures
				if c(n).remove
					remove_creature(n)
				endif
			endif
		next n
	endif
 
	temp = max_creatures
	for n = 1 to temp
		REM calculate zone X Y and Z (Once per 15 loops)
		if calc_alt = 3
			c(n).zonex = int(object position x(c(n).obj) / 100.0)
			c(n).zoney = int(object position y(c(n).obj) / 100.0)
			c(n).zonez = int(object position z(c(n).obj) / 100.0)
		endif
		remstart
		REM Once per 15 loops, do AI (seek prey/mate, evade predator)
		if calc_alt = 2
			REM Fill array "a" with nearby creatures (in adjacent zones)
			fill_a_adjacent_zones(n)
 
			if c(n).food > c(n).weight
				REM If organism has enough food to make babies,
				a = check_for_mate_adj(n)
				if a
					REM If there is a mate, go towards it
					message_3d("Heart", object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj))
				endif
			else
				REM Otherwise, see if there's anything to eat
				a = check_for_prey_adj(n)
				if a
					REM If there is prey, go towards it
					message_3d("Yum", object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj))
				endif
			endif
 
			REM Check for predators
			a = check_for_predators(n)
			if a
				REM If there is a predator, run away from it
				message_3d("Uhoh", object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj))
			endif
		endif
		remend
		REM Once per 15 loops, EAT and REPRODUCE
		`if calc_alt = 8
		if calc_alt = 6	
			i = check_zone_for_prey(n)
			if i > 0
				inc c(n).food, c(i).weight
				c(i).remove = 1
				message_3d("Gulp", object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj))
				message_2d("A "+t(c(n).kind).name+" has eaten a "+t(c(i).kind).name)
			endif
		endif
 
		if calc_alt = 9
 
			if t(c(n).kind).sexually_reproduce = 0
				if c(n).food > c(n).weight
					c(n).food = c(n).weight / 2.0
					if c(n).kind = PROKARYOTES then add_creature(NUTRIENTS, object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj), 1) : message_2d("Prokaryotes produced Nutrients")
					add_creature(c(n).kind, object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj), 1)
					message_3d("Baby", object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj))
					message_2d("A "+t(c(n).kind).name+" was born")
				endif
			endif
 
			if t(c(n).kind).sexually_reproduce = 1
				i = check_zone_for_mate(n)
				if t(c(n).kind).sexually_reproduce = 1
					if i > 0 and c(n).food > c(n).weight and c(i).food > c(i).weight
						c(n).food = c(n).weight / 2.0
						c(i).food = c(i).weight / 2.0
						add_creature(c(n).kind, object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj), 1)
						message_3d("Baby", object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj))
						message_2d("A "+t(c(n).kind).name+" was born")
					endif
				endif
			endif
 
		endif
		`endif
 
		if c(n).kind = CORPSE or c(n).kind = NUTRIENTS
		else			
			REM Use up organism's food (each loop)
			dec c(n).food, t(c(n).kind).food_dec_per_loop
 
			REM Bound food (each loop)
			if c(n).food > c(n).weight * 2.0 then c(n).food = c(n).weight * 2.0
 
			REM See if organism starves (each loop) -- IF food value is less than zero
			if c(n).food < 0.0
				if c(n).kind = NUTRIENTS
					message_2d("nutrients decayed")
				else
					message_2d("A "+t(c(n).kind).name+" has died of starvation")
				endif
				message_3d("Starve", object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj))
				add_creature(CORPSE, object position x(c(n).obj), object position y(c(n).obj), object position z(c(n).obj), 1)
				c(n).remove = 1
			endif
		endif
 
 
		REM Orient and move organism (Every loop)
		select t(c(n).kind).move_mode
			case "Walk"
				do_organism_movement_walk(n)
			endcase
			case "SwimWalk"
				h# = get ground height(mtx_ground, object position x(c(n).obj), object position z(c(n).obj))
				if h# > 700.0
					do_organism_movement_walk(n)
				else
					do_organism_movement_swim(n)
				endif
			endcase
			case "Swim"
				do_organism_movement_swim(n)
			endcase
			case "Float"
				do_organism_movement_float(n)
			endcase
			case "Fly"
				do_organism_movement_fly(n)
			endcase
			case "Sink"
				do_organism_movement_sink(n)
			endcase
		endselect
 
	next n
endfunction
 
function check_zone_for_prey(n)
	for i = 1 to max_creatures
		if c(n).zonex = c(i).zonex and c(n).zoney = c(i).zoney and c(n).zonez = c(i).zonez
			if c(i).kind = t(c(n).kind).prey_1 or c(i).kind = t(c(n).kind).prey_2 or c(i).kind = t(c(n).kind).prey_3
				r = i
			endif
		endif
	next i
endfunction r
 
function check_zone_for_mate(n)
	for i = 1 to max_creatures
		if c(n).zonex = c(i).zonex and c(n).zoney = c(i).zoney and c(n).zonez = c(i).zonez
			if c(i).kind = c(n).kind
				if (c(n).gender = 0 and c(i).gender = 1) or (c(n).gender = 1 and c(i).gender = 0)
					r = i
				endif
			endif
		endif
	next i
endfunction r
 
function fill_a_adjacent_zones(n)
	REM Clear a()
	for i = 1 to max_a
		a(i) = 0
	next i
	amt_a = 0
 
	REM Get adjacents
	for i = 1 to max_creatures
		if i = n
		else
			if c(i).zonex = c(n).zonex or c(i).zonex = c(n).zonex - 1 or c(i).zonex = c(n).zonex + 1
				if c(i).zoney = c(n).zoney or c(i).zoney = c(n).zoney - 1 or c(i).zoney = c(n).zoney + 1
					if c(i).zonez = c(n).zonez or c(i).zonez = c(n).zonez - 1 or c(i).zonez = c(n).zonez + 1
						if amt_a < max_a
							inc amt_a
							a(amt_a) = i
						endif
					endif
				endif
			endif
		endif
	next i
endfunction
 
function check_for_mate_adj(n)
	if amt_a > 0
		for i = 1 to amt_a
			if c(a(i)).kind = c(n).kind `if same species
				if (c(a(i)).gender = 0 and c(n).gender = 1) or (c(a(i)).gender = 1 and c(n).gender = 0) `if diff gender
					return_x = object position x(c(a(i)).obj)
					return_y = object position y(c(a(i)).obj)
					return_z = object position z(c(a(i)).obj)
					r = 1
				endif
			endif
		next i
	endif
endfunction r
 
function check_for_prey_adj(n)
	if amt_a > 0
		for i = 1 to amt_a
			if c(a(i)).kind = t(c(n).kind).prey_1 or c(a(i)).kind = t(c(n).kind).prey_2 or c(a(i)).kind = t(c(n).kind).prey_3
				return_x = object position x(c(a(i)).obj)
				return_y = object position y(c(a(i)).obj)
				return_z = object position z(c(a(i)).obj)
				r = 1
			endif
		next i
	endif
endfunction r
 
function check_for_predators(n)
	for i = 1 to amt_a
		if t(c(a(i)).kind).prey_1 = c(n).kind or t(c(a(i)).kind).prey_2 = c(n).kind or t(c(a(i)).kind).prey_3 = c(n).kind
			return_x = object position x(c(a(i)).obj)
			return_y = object position y(c(a(i)).obj)
			return_z = object position z(c(a(i)).obj)
			r = 1
		endif
	next i
endfunction r
 
function message_2d(str as string)
	for i = 0 to max_msg
		if i < max_msg then msg(i) = msg(i+1)
	next i
	msg(max_msg) = str
endfunction
 
function message_3d(str as string, x as float, y as float, z as float)
 
endfunction
 
function do_organism_movement_sink(n)
	`get vars
	y# = object position y(c(n).obj)
	h_ground# = get ground height(mtx_ground, x#, z#) + 2.5
 
	if y# > h_ground# then dec y#, sink_speed
 
	position object c(n).obj, object position x(c(n).obj), y#, object position z(c(n).obj)
 
endfunction
 
function do_organism_movement_fly(n)
	`get vars
	x# = object position x(c(n).obj)
	y# = object position y(c(n).obj)
	z# = object position z(c(n).obj)
	h_ground# = get ground height(mtx_ground, x#, z#) + bird_minimum_height
	h_ocean# = get ground height(mtx_ocean, x#, z#) + matrix position y(mtx_ocean) + bird_minimum_height
 
	`get new velocity vector if its time to turn
	if c(n).time_to_turn = 0
		c(n).ang.y = rnd(360)
		c(n).ang.x = rnd(360)
		c(n).time_to_turn = rnd(loops_to_turn_max)
		rotate object c(n).obj, c(n).ang.x, c(n).ang.y, 0.0
	endif
 
	`keep above ground
	if y# < h_ground#
		position object c(n).obj, x#, h_ground#, z#
		y# = h_ground#
	endif
 
	`keep above water surface
	if y# < h_ocean#
		position object c(n).obj, x#, h_ocean#, z#
		y# = h_ocean#
	endif
 
	`keep below maximum height
	if y# > bird_maximum_height
		position object c(n).obj, x#, bird_maximum_height, z#
		y# = bird_maximum_height
	endif
 
	`bound position within environment
	if x# > environment_size then position object c(n).obj, environment_size, y#, z# : x# = environment_size
	if x# < 0.0 then position object c(n).obj, 0.0, y#, z# : x# = 0.0
	if z# > environment_size then position object c(n).obj, x#, y#, environment_size : z# = environment_size
	if z# < 0.0 then position object c(n).obj, x#, y#, 0.0 : z# = 0.0
 
	`adjust time to turn variable
	dec c(n).time_to_turn
 
	`adjust position based on direction organism is moving
	move object c(n).obj, t(c(n).kind).max_vel
 
endfunction
 
function do_organism_movement_swim(n)
	`get vars
	x# = object position x(c(n).obj)
	y# = object position y(c(n).obj)
	z# = object position z(c(n).obj)
	h_ground# = get ground height(mtx_ground, x#, z#)
	h_ocean# = get ground height(mtx_ocean, x#, z#) + matrix position y(mtx_ocean)
 
	`get new velocity vector if its time to turn
	if c(n).time_to_turn = 0
		c(n).ang.y = rnd(360)
		c(n).ang.x = rnd(360)
		c(n).time_to_turn = rnd(loops_to_turn_max)
		rotate object c(n).obj, c(n).ang.x, c(n).ang.y, 0.0
	endif
 
	`keep out of islands -- reposition it if stuck under island
	if h_ground# > 900.0
		x# = rnd(int(environment_size))
		y# = rnd(800)
		z# = rnd(int(environment_size))
 
		position object c(n).obj, x#, y#, z#
	endif
 
	`keep above ground
	if y# < h_ground#
		position object c(n).obj, x#, h_ground#, z#
		y# = h_ground#
	endif
 
	`keep below water surface
	if y# > h_ocean#
		position object c(n).obj, x#, h_ocean#, z#
		y# = h_ocean#
	endif
 
	`bound position within environment
	if x# > environment_size then position object c(n).obj, environment_size, y#, z# : x# = environment_size
	if x# < 0.0 then position object c(n).obj, 0.0, y#, z# : x# = 0.0
	if z# > environment_size then position object c(n).obj, x#, y#, environment_size : z# = environment_size
	if z# < 0.0 then position object c(n).obj, x#, y#, 0.0 : z# = 0.0
 
	`adjust time to turn variable
	dec c(n).time_to_turn
 
	`adjust position based on direction organism is moving
	move object c(n).obj, t(c(n).kind).max_vel
endfunction
 
function do_organism_movement_walk(n)
	`get vars
	x# = object position x(c(n).obj)
	y# = object position y(c(n).obj)
	z# = object position z(c(n).obj)
	h_ground# = get ground height(mtx_ground, x#, z#)
 
	`get new velocity vector if its time to turn
	if c(n).time_to_turn = 0
		c(n).ang.y = rnd(360)
		c(n).time_to_turn = rnd(loops_to_turn_max)
		rotate object c(n).obj, 0.0, c(n).ang.y, 0.0
	endif
 
	`bound position within environment
	if x# > environment_size then position object c(n).obj, environment_size, y#, z# : x# = environment_size
	if x# < 0.0 then position object c(n).obj, 0.0, y#, z# : x# = 0.0
	if z# > environment_size then position object c(n).obj, x#, y#, environment_size : z# = environment_size
	if z# < 0.0 then position object c(n).obj, x#, y#, 0.0 : z# = 0.0
 
	`adjust time to turn variable
	dec c(n).time_to_turn
 
	`adjust position based on direction organism is moving
	x# = newxvalue(x#, c(n).ang.y, t(c(n).kind).max_vel)
	z# = newzvalue(z#, c(n).ang.y, t(c(n).kind).max_vel)
	y# = get ground height(mtx_ground, x#, z#)
 
	`position creature object
	position object c(n).obj, x#, y#+t(c(n).kind).height, z#
endfunction
 
function do_organism_movement_float(n)
	`get vars
	x# = object position x(c(n).obj)
	y# = object position y(c(n).obj)
	z# = object position z(c(n).obj)
	h_ground# = get ground height(mtx_ground, x#, z#)
	h_ocean# = get ground height(mtx_ocean, x#, z#) + matrix position y(mtx_ocean)
 
	`randomize velocity vector (brownian motion)
	if calc_alt = 0 or calc_alt = 7
		inc c(n).vel.x, ((rnd(10)-5) / 10.0)
		inc c(n).vel.y, ((rnd(10)-5) / 10.0)
		inc c(n).vel.z, ((rnd(10)-5) / 10.0)
	endif
 
	`bound velocity
	if c(n).vel.x > float_max_velocity then c(n).vel.x = float_max_velocity
	if c(n).vel.x < -float_max_velocity then c(n).vel.x = -float_max_velocity
	if c(n).vel.y > float_max_velocity then c(n).vel.y = float_max_velocity
	if c(n).vel.y < -float_max_velocity then c(n).vel.y = -float_max_velocity
	if c(n).vel.z > float_max_velocity then c(n).vel.z = float_max_velocity
	if c(n).vel.z < -float_max_velocity then c(n).vel.z = -float_max_velocity
 
	`bound position within environment
	if x# > environment_size then position object c(n).obj, environment_size, y#, z# : x# = environment_size
	if x# < 0.0 then position object c(n).obj, 0.0, y#, z# : x# = 0.0
	if z# > environment_size then position object c(n).obj, x#, y#, environment_size : z# = environment_size
	if z# < 0.0 then position object c(n).obj, x#, y#, 0.0 : z# = 0.0
 
	`keep out of islands -- reposition it if stuck under island
	if h_ground# > 900.0
		x# = rnd(int(environment_size))
		y# = rnd(800)
		z# = rnd(int(environment_size))
 
		position object c(n).obj, x#, y#, z#
	endif
 
	`keep above ground
	if y# < h_ground#
		position object c(n).obj, x#, h_ground#, z#
		y# = h_ground#
	endif
 
	`keep below water surface
	if y# > h_ocean#
		position object c(n).obj, x#, h_ocean#, z#
		y# = h_ocean#
	endif
 
	`adjust organism position
	position object c(n).obj, x# + c(n).vel.x, y# + c(n).vel.y, z# + c(n).vel.z
endfunction
 
function minimum_four_floats(fa as float, fb as float, fc as float, fd as float)
	if fa < fb and fa < fc and fa < fd then r = 0
	if fb < fa and fb < fc and fb < fd then r = 1
	if fc < fb and fc < fa and fc < fd then r = 2
	if fd < fb and fd < fc and fd < fa then r = 3
endfunction r
 
function add_initial_creatures(creature_type as integer, move_mode as string, number as integer)
	local x as float
	local y as float
	local z as float
 
	for n = 1 to number
		REM This select structure finds a suitable XYZ coordinate to place the current organism to be added
		found = 0
		select move_mode
			case "Float"
				` Keep getting random XYZ until XYZ is in the ocean AND is above the ground/sand
				repeat
					x = rnd(environment_size)
					z = rnd(environment_size)
					y = rnd(800)
					if get ground height(mtx_ground, x, z) < 800.0 and get ground height(mtx_ground, x, z) < y
						found = 1
					endif
				until found
			endcase
			case "Walk"
				` Get random position with Y right above ground
				x = rnd(environment_size)
				z = rnd(environment_size)
				y = get ground height(mtx_ground, x, z) + (t(creature_type).adult_weight)
			endcase
			case "SwimWalk"
				` Get random position with Y right above ground
				x = rnd(environment_size)
				z = rnd(environment_size)
				y = get ground height(mtx_ground, x, z) + (t(creature_type).adult_weight)
			endcase
			case "Swim"
				` Keep getting random XYZ until XYZ is in the ocean AND is above the ground/sand
				repeat
					x = rnd(environment_size)
					z = rnd(environment_size)
					y = rnd(800)
					if get ground height(mtx_ground, x, z) < 800.0 and get ground height(mtx_ground, x, z) < y
						found = 1
					endif
				until found
			endcase
			case "Fly"
				` Get random position with Y position in the air
				x = rnd(environment_size)
				z = rnd(environment_size)
				y = rnd(200) + 1050.0
			endcase
		endselect
 
		add_creature(creature_type, x, y, z, 1)
	next n
endfunction
 
function remove_creature(id as integer)
	REM Remove object
	delete object c(id).obj
 
	REM Remove array slot
	array delete element c(), id
 
	REM Adjust max_creature variable
	dec max_creatures
endfunction
 
function add_creature(creature_type as integer, x as float, y as float, z as float, adult as integer)
	if count_species(creature_type) < bound_creatures
		REM Add slot to creature array and adjust max_creatures variable
		array insert at bottom c()
		inc max_creatures
 
		REM Set creature stats
		c(max_creatures).kind = creature_type
		c(max_creatures).ang.x = rnd(360)
		c(max_creatures).ang.y = rnd(360)
		c(max_creatures).gender = rnd(1)
		if adult = 0
			c(max_creatures).weight = t(creature_type).start_weight
			c(max_creatures).food = t(creature_type).start_weight / 2.0
			c(max_creatures).age = 0.0
		else
			c(max_creatures).weight = t(creature_type).adult_weight
			c(max_creatures).food = t(creature_type).adult_weight / 2.0
			c(max_creatures).age = t(creature_type).days_to_grow
		endif
 
		REM Add object
		c(max_creatures).obj = free_obj()
		instance object c(max_creatures).obj, t(creature_type).obj
		position object c(max_creatures).obj, x, y, z
		rotate object c(max_creatures).obj, c(max_creatures).ang.x, c(max_creatures).ang.y, 0.0
	endif
endfunction
 
function do_waves()
 
	for x = 0 to ocean_tiles
		for y = 0 to ocean_tiles
			set matrix height mtx_ocean,x,y,(sin(w(x,y)))*25.0
			if w(x,y) < 360
				inc w(x,y), 5
			else
				w(x,y) = 0
			endif
		next y
	next x
 
	update matrix mtx_ocean
 
endfunction
 
function make_water()
	REM Matrix texture
	ink rgb(113-100, 137-100, 253-100), 0
	box 0, 0, 64, 64
	ink rgb(90-50, 197-50, 254-50), 0
	for x = 0 to 64
		for y = 0 to 64
			if rnd(1) = 0 then box x, y, x+1, y+1
		next y
	next x
	img_ocean = free_img()
	get image img_ocean, 0, 0, 63, 63
 
	REM Make matrix
	mtx_ocean = free_mtx()
	make matrix mtx_ocean, environment_size, environment_size, ocean_tiles, ocean_tiles
	prepare matrix texture mtx_ocean, img_ocean, 1, 1
	fill matrix mtx_ocean, 0, 1
	randomize matrix mtx_ocean, 100
	position matrix mtx_ocean, 0, 800, 0
	set matrix mtx_ocean, 0,0,0,0,0,1,1
	ghost matrix on mtx_ocean, 1
	update matrix mtx_ocean
 
	REM Array with random starting heights
	for x = 0 to ocean_tiles
		for y = 0 to ocean_tiles
			w(x, y) = (rnd(72))*5
		next y
	next x
 
endfunction
 
function make_ground()
 
	REM Matrix textures
	ink rgb(247, 207, 115), 0
	box 0, 0, 64, 64
	ink rgb(251, 230, 179), 0
	for x = 0 to 64
		for y = 0 to 64
			if rnd(2) = 0 then box x, y, x+1, y+1
		next y
	next x
	ink rgb(86, 183, 15), 0
	box 64, 0, 128, 64
	ink rgb(21, 191, 81), 0
	for x = 64 to 128
		for y = 0 to 64
			if rnd(2) = 0 then box x, y, x+1, y+1
		next y
	next x
	img_matrix = free_img()
	get image img_matrix, 0, 0, 127, 63
 
	REM Make matrix
	mtx_ground = free_mtx()
	make matrix mtx_ground, environment_size, environment_size, 100, 100
	prepare matrix texture mtx_ground, img_matrix, 2, 1
	fill matrix mtx_ground, 0, 1
	randomize matrix mtx_ground, 50
	set matrix trim mtx_ground, 0.1, 0.1
 
	REM Set islands
	for n = 1 to num_islands
		island_x = rnd(100)
		island_y = rnd(100)
		island_r = (rnd(20)-10 + rad_islands)
 
		for x = 0 to 99
			for y = 0 to 99
 
				dist# = distance_2(x, y, island_x, island_y)
 
				if dist# < island_r
 
					if dist# < (island_r - 10)
						REM If top of island
						set matrix tile mtx_ground, x, y, 2
						set matrix height mtx_ground, x, y, rnd(50) + 1000.0
					else
						REM If shore
						dist2# = island_r - dist#
						set matrix height mtx_ground, x, y, bound_float(get matrix height(1, x, y) + 100.0*dist2#, 1000.0 + rnd(50))
 
					endif
 
				endif
 
			next y
		next x
	next n
 
	update matrix mtx_ground
 
endfunction
 
function bound_float(f as float, b as float)
	local r as float
 
	if f < b
		r = f
	else
		r = b
	endif
 
endfunction r
 
function distance_2(xa, ya, xb, yb)
 
	dx# = xa - xb
	dy# = ya - yb
	d# = sqrt(dx#*dx# + dy#*dy#)
 
endfunction d#
 
function do_mouse()
	local mmy as float
	local mmx as float
	local spd as float
 
	REM Var
	spd = 1.0
	oldmc = mc
	mc = mouseclick()
	mmy = mousemovey() / 5.0
	mmx = mousemovex() / 5.0
 
	REM Toggle FPS
	if keystate(78) then sync rate 0
	if keystate(156) then sync rate 30
 
	REM Look
	if mc = 2 and oldmc = 2
		`hide moues while looking around
		hide mouse
		position mouse 512, 384
		`turn camera
		xrotate camera wrapvalue(camera angle x() + mmy)
		yrotate camera wrapvalue(camera angle y() + mmx)
		`bound camera angle
		if camera angle x()>89 and camera angle x()<180 then xrotate camera 89
		if camera angle x()<271 and camera angle x()>180 then xrotate camera 271
	else
		show mouse
	endif
 
	REM Move
	if keystate(42)
		spd = spd * 10
	endif
	if keystate(17)
		move camera spd
	endif
	if keystate(31)
		move camera -spd
	endif          
	if keystate(30)
		position camera newxvalue(camera position x(), camera angle y()-90.0, spd), camera position y(), newzvalue(camera position z(), camera angle y()-90.0, spd)
	endif
	if keystate(32)
		position camera newxvalue(camera position x(), camera angle y()+90.0, spd), camera position y(), newzvalue(camera position z(), camera angle y()+90.0, spd)
	endif          
	if keystate(16)
		position camera camera position x(), camera position y() - spd, camera position z()
	endif
	if keystate(18)
		position camera camera position x(), camera position y() + spd, camera position z()
	endif
	if camera position y() < 1.0 then position camera camera position x(), 1.0, camera position z()
 
endfunction
 
function free_obj()
	repeat
		inc i
		if object exist(i)=0 then found=1
	until found
endfunction i
 
function free_img()
	repeat
		inc i
		if image exist(i)=0 then found=1
	until found
endfunction i
 
function free_mtx()
	repeat
		inc i
		if matrix exist(i)=0 then found=1
	until found
endfunction i
 
function set_creature_type(i as integer, name as string, days_to_grow as float, adult_weight as float, max_vel as float, reproduce_mode as integer, move_mode as string, prey_1 as integer, prey_2 as integer, prey_3 as integer, r, g, b, start_number)
	t(i).name = name
	t(i).days_to_grow = days_to_grow
	t(i).start_weight = adult_weight / 10.0
	t(i).height = adult_weight / 2.0
	t(i).adult_weight = adult_weight
	t(i).max_vel = max_vel
	t(i).move_mode = move_mode
	t(i).prey_1 = prey_1
	t(i).prey_2 = prey_2
	t(i).prey_3 = prey_3
	t(i).sexually_reproduce = reproduce_mode
	t(i).food_dec_per_loop = adult_weight / (seconds_to_starve * 60)
 
	t(i).r = r
	t(i).g = g
	t(i).b = b
 
	t(i).obj = free_obj()
	make object cube t(i).obj, t(i).adult_weight
	color object t(i).obj, rgb(r,g,b)
	hide object t(i).obj
 
	if start_number > 0
		add_initial_creatures(i, move_mode, start_number)
	endif
endfunction
 
function count_species(i)
	for n = 1 to max_creatures
		if c(n).kind = i then inc count
	next n
endfunction count