Skip to content
hajo4 edited this page Feb 22, 2014 · 3 revisions

Challenge-map TinyTown1

-- TinyTown1.lua - HaJo Gurt - 2014-02-22

local Prog="MapMaker-TinyTown1"
local dbg=1

--[[
Generate challenge-maps for trAInsported (maps for a single AI)

History:
2014-02-21	Original from: SmallTown5.lua
2014-02-22	first version - map 4x3


For documentation see:
* http://trainsportedgame.no-ip.org/maps.php
* https://github.com/Germanunkol/trAInsported/blob/master/MakingMaps.md
]]--


function myPrint(dbgLevel, ...)
	if dbg >= dbgLevel then  print(...)  end
end


local ch = {}

--ch.name = "TinyTestTown-1"
ch.version = "4"		-- req. version of trAInsported

ch.maxTrains  =  1
ch.startMoney = 25	-- 1 train costs 25

-- ##### ##### ##### ##### ##### ##### ##### ##### #####

local mapAuthor = "hajo4  2014-02-22"
local mapDescr  = "TinyTown1 - small map with minimal rendering time to test AIs."

ch.name = "TinyTestTown-1"
ch.maxTrains, ch.startMoney = 3, 25

--[[
local maxX, maxY = 5, 4
local _mapT1 =	
	"CSccc" ..
	"C.c--" ..
	"C.cHc" ..
	"CCCCC"

local _mapT2 =	
	"CCccc" ..
	"CScWH" ..
	"CCcHc" ..
	"CHcCC"
]]--

local maxX, maxY = 4, 3
local _mapT3 =	
	"CCCc" ..
	"CHCS" ..
	"CCCc"
	
local _map =	
	"cccC" ..
	"cHcS" ..
	"cccC"
--     ....+....1....+....2

-- 5x3 map has 1 house, 1 hotspot, 1 loop, 2 deadends.
-- 6 passengers are created to allow 2 trains to operate.
-- The map can be done in less than 60s.

local passengersRemaining, passengersCreated  = 6, false
local maxTime = 120
maxTime = 100           -- Map with 6 passengers: can be done in less than 60s 

--[[ Times for some AIs:
 AI_Rechenknecht_v2: 55s / Stupid-Fixed: 56s / winKI_v2: 56s / Marvin2: 59s / czAI20: 59s / 
 Optimum_S: 60s / Optimax: 64-66s / Fiete_02: 67s / buerokrat_120: 69s / Quetzal1000: 77s / 
 Dragon_09: 80s / GarchaKing: 80s / Geselle: 87s-89s / NinjAI_2: 94s / BigIron3: 98s-100s /

 Teilebahn-3: 57 / bernie3: 64s / BigIron2: 67s / Better_PF: 68s / PaziFist: 71s / RUR: 73s / 
 WybeJunior: 75s / agentOrange: 82s / Cecelia: 83s / AI2: 85s / Simple_PF: 94s /  
 brAIndead/Cooper: 99s / YUNOBringMeHome: 100s / Bethany: 103s / TestAI: loop / 

 Failed (100s +) :  CheapAIv3.1: loop / TrainBrain: loop / MazeRunner_004: 111s /
]]--

local startupMessage = "Welcome to TinyTestTown!\n"..
	"Transport the people around in TinyTown.\n"..
	"You have " .. maxTime .. " seconds!"

-- ##### ##### ##### ##### ##### ##### ##### ##### #####

-- create a new, empty map with known dimensions:
ch.map = challenges.createEmptyMap(maxX, maxY)

-- fill in mapdata:

local x,y,b = 1,1,0
for p = 1, string.len(_map) do
	s = string.sub(_map, p,p)
	if s == "#" then s = "C" end
	if s == "c" then s = "C" end
	if s == "." then s = " " end
	if s == "-" then s = " " end
	if s == "_" then s = " " end

	-- 1x1 buildings: / see mapRenderPart.lua
	if s == "h" then s = "H" end
	if s == "M" then s = "CINEMA"     end
	if s == "W" then s = "STORE"      end
	if s == "B" then s = "BOOKSTORE"  end
	if s == "P" then s = "PIESTORE"   end
	if s == "p" then s = "PLAYGROUND" end

	-- 2x2 buildings:
-- "SCHOOL" SCHOOL11,SCHOOL12,SCHOOL21,SCHOOL22 
-- "HOSPITAL" 11,12, 21,22
	if s == "L" then s = "SCHOOL"     end
	if s == "+" then s = "HOSPITAL"   end

	-- 3x3 buildings:
	if s == "1" then s = "H" end
	if s == "X" then s = "HOUSE_1_LARGE_11" end
	if s == "x" then s = "HOUSE_1_LARGE_12" end

	if s == "Y" then s = "HOUSE_2_LARGE_11" end
	if s == "y" then s = "HOUSE_2_LARGE_12" end

	if s == "Z" then s = "HOUSE_3_LARGE_11" end
	if s == "z" then s = "HOUSE_3_LARGE_12" end
	if s == "3" then s = "HOUSE_3_LARGE_21" end

	if s == "Q" then s = "HOUSE_4_LARGE_11" end
	if s == "q" then s = "HOUSE_4_LARGE_12" end
	if s == "4" then s = "HOUSE_4_LARGE_21" end
	
	if s ~= " " then
	      ch.map[x][y] = s
		b=b+1
	end
	if x >= maxX then
		x=1
		y=y+1
	else
		x=x+1
	end
end
myPrint(1,  "Map "..ch.name,  "ready:", maxX.."x"..maxY, b )
console.add("Map "..ch.name.." ready:"..maxX.."x"..maxY, colorGreen )

function directDistance(x1,y1, x2,y2)
	return math.sqrt( (x1-x2)^2 + (y1-y2)^2 )
end
function manhattanDistance(x1, y1, x2, y2)
    return math.abs(x1-x2) + math.abs(y1-y2)
end

function nearbyRail( x,y )
-- check where nearest rail is:
-- 0: tile at x,y is rail
-- 1: adjacent tile has rail (N,E,S,W)
-- 2: diagonally adjacent tile has rail (NE,NW,SE,SW)
-- 3: no rail in range

	if     ch.map[ x ][ y ] == "C" then return 0

	elseif ch.map[x+1][y  ] == "C" then return 1
	elseif ch.map[x-1][y  ] == "C" then return 1
	elseif ch.map[x  ][y+1] == "C" then return 1
	elseif ch.map[x  ][y-1] == "C" then return 1

	elseif ch.map[x+1][y+1] == "C" then return 2
	elseif ch.map[x+1][y-1] == "C" then return 2
	elseif ch.map[x-1][y+1] == "C" then return 2
	elseif ch.map[x-1][y-1] == "C" then return 2

	else return 3 end
end

--[[
function decr(x)
	return x-1
end
function incr(x)
	return x+1
end
]]--

function ch.start()
	challenges.setMessage(startupMessage)
	--clearConsole()
end


-- Colors for console-output:
local colorWhite = {r=255,g=255,b=255}
local colorGrey  = {r=128,g=128,b=128}
local colorGreen = {r=0,  g=255,b=0}

-- Watch the player:
function ch.newTrain(train)
	console.add("newTrain #"..train.ID, colorGreen )
	myPrint(1, "New train #"..train.ID.." created at:", train.x, train.y)
end

function ch.passengerBoarded(train, passenger)
	console.add("Train #"..train.ID.." picked up "..passenger.name, colorWhite )
	myPrint(1, "passengerBoarded:", train.ID)
end

function ch.passengerDroppedOff(train, psx)
	if train.tileX == psx.destX and train.tileY == psx.destY then		
		passengersRemaining = passengersRemaining - 1
		--console.add("passengersRemaining :"..passengersRemaining, {r=255,g=255,b=255})
		--myPrint(1, "passengersRemaining:", passengersRemaining)
	end
	console.add("Train #"..train.ID.." passengerDroppedOff ->"..passengersRemaining, colorWhite )
	myPrint(1, "passengerDroppedOff:", train.ID, psx.name, "->", passengersRemaining)

	challenges.removeMessage()	-- remove msgbox after first passenger is dropped off
end


function createPassengers()
--Todo: 
--provide several alternatives for creating passengers
--make some VIPs

	local psx, d,r, x,y, x1,y2, x1,y2, destX,destY, s

	myPrint(3,"# update: create passengers")
end

function ch.update(time)
-- This gets called every frame. 
-- Update the messagebox for remaining time, passengers etc.
-- and keep track of / generate passengers.

local psx, d,r, x,y, x1,y2, x1,y2, destX,destY
local s, timeLeft 

	if time > 3 and not passengersCreated then
		psx=0
--[[
		createPassengers()
		-- destX = 9	-- Location of warehouse as destination
		-- destY = 2
		-- passenger.new( x, y, destX, destY )
		-- passenger.new( 1, math.random(4) , 10, math.random(4) + 3 )

		-- put some psx at selected locations:

		--x1,y1       =  1, 1	-- fixed start-location of passenger
		--destX,destY =  6, 9	-- Location of destination (e.g. a store)

		x1,y1       = 10, 3	-- fixed start-location of passenger
		destX,destY =  3, 6	-- Location of destination (e.g. a store)

		r = 9
		while r>0 do
			x2 = math.random(destX-1,destX+1)  -- area around destination
			y2 = math.random(destY-1,destY+1)
			r = nearbyRail( x2,y2 )
			myPrint(5, "# nearbyRail: "..x2,y2, r )
		end
		psx=psx+1
		passenger.new( x1,y1, x2,y2 )
		myPrint(3, "### New passenger #".. psx..":", x1.."/"..y1, x2.."/"..y2 )
]]--
		-- fill up with psx from anywhere to anywhere-except-outer-ring
		while psx < passengersRemaining do
			r = 9
			while r>0 do
				x = math.random(maxX)			-- whole map
				y = math.random(maxY)
				--x = math.random(2,maxX-1)  -- no destinations on outer ring
				--y = math.random(2,maxY-1)

				r = nearbyRail( x,y )
				myPrint(5, "# nearbyRail: "..x,y, r )
			end
			x2,y2 = x,y

			d,r = 0,9
			while (d<1.4) or (r>0) do	-- ensure both spots are near rails,
								-- and some minimum travel-distance apart
				x = math.random(maxX)
				y = math.random(maxY)
				d = directDistance( x,y, x2,y2 )
				r = nearbyRail( x,y )
				myPrint(5, "## nearbyRail: "..x,y, r,d )
			end
			x1,y1 = x,y
		psx=psx+1
			passenger.new( x1,y1, x2,y2 )
			myPrint(3, "### New passenger #".. psx..":", x1.."/"..y1, x2.."/"..y2 )
		end
		passengersCreated = true

	end

    --challenges.setStatus("Map by "..mapAuthor.."\n" ..
    --	math.floor(maxTime-time) .. " seconds remaining.\n" ..

	timeLeft = math.floor(maxTime-time)
	challenges.setStatus("Map "..ch.name.." by "..mapAuthor.."\n" ..
		timeLeft .. " seconds remaining.\n" ..
		passengersRemaining .." passengers remaining.")

	if time > maxTime then
		console.add("game over: lost", colorGreen )
		myPrint(1, "# Game over: lost")
		return "lost", "Some passengers are still missing :-("
	end
	if passengersRemaining == 0 then
		--console.add("game over: won", colorGreen )
		console.add("game over: won", {r=44,g=255,b=44} )
		myPrint(1, "# Game over: won")
		s = "ok"
		if     timeLeft > (maxTime*0.60) then s = "Incredible !"
		elseif timeLeft > (maxTime*0.50) then s = "Impressive !"
		elseif timeLeft > (maxTime*0.40) then s = "Excellent !"
		elseif timeLeft > (maxTime*0.30) then s = "Very good !"
		elseif timeLeft > (maxTime*0.20) then s = "Good !"
		elseif timeLeft > (maxTime*0.10) then s = "Well done !"
		elseif timeLeft > (maxTime*0.05) then s = "Just in time !"
		else                                  
			s = "In the nick of time !"
		end
		return "won", s.."\n"..time.." / "..timeLeft.." / "..maxTime
	end

end

return ch

--.
Clone this wiki locally