--Prevent standalone execution: if not TRAINSPORTED then print("To prevent players from harm, this file may only be executed by the trAInsported game.") return end --AI by javra: -- Tutorial 2: Left or Right? -- buy a train at round start and place it in the top left corner of the map: local myMap local routing local dist local passDist local bewertung local constVIP = 6 local constHouses = 3.5 local constKreuzung = 1 local constMittig = 0.4 local constKorrektur = 7 local constGefahren = 4 function ai.init( map, money ) myMap=map bewertung={} --init bewertung routing={} dist={} passDist={} for i=1,myMap.width do bewertung[i] = {} for j=1,myMap.height do if myMap[i][j]=="C" then istKreuzung=0 if streckentyp(i,j)=="Kreuzung" then istKreuzung=1 end mittigWert = myMap.height*myMap.width/euDist((myMap.width+1)/2,(myMap.height+1)/2,i,j) bewertung[i][j] = math.floor(constHouses*countHouses(i,j)+constKreuzung*istKreuzung+constMittig*mittigWert) else bewertung[i][j] = 0 end end end printMap(bewertung) ai.enoughMoney() end function nr2dir(nr) if nr==1 then return "N" elseif nr==2 then return "E" elseif nr==3 then return "S" else return "W" end end function countHouses(tmpX,tmpY) tmp=0 if tmpX>1 and myMap[tmpX-1][tmpY]=="H" then tmp=tmp+1 end if tmpY>1 and myMap[tmpX][tmpY-1]=="H" then tmp=tmp+1 end if tmpX1 and myMap[tmpX-1][tmpY]=="C" then tmp=tmp+1 end if tmpY>1 and myMap[tmpX][tmpY-1]=="C" then tmp=tmp+1 end if tmpX passenger distance nextX=x nextY=y if dist==nil then dist={} end tmpDist = {} -- matrices parent = {} for i=1,myMap.width do tmpDist[i] = {} -- create a new row parent[i] = {} for j=1,myMap.height do tmpDist[i][j] = math.huge parent[i][j] = "X" end end tmpDist[nextX][nextY] = 0 queue = {} table.insert(queue, {x=nextX, y=nextY}) while #queue>0 do tmpX = queue[1].x tmpY = queue[1].y --spread to west if tmpX>1 and myMap[tmpX-1][tmpY]=="C" and (parent[tmpX][tmpY]~="W" or streckentyp(tmpX,tmpY)=="Wende") then if tmpDist[tmpX-1][tmpY]==math.huge or streckentyp(tmpX,tmpY)=="Wende" then table.insert(queue, {x=tmpX-1, y=tmpY}) end if tmpDist[tmpX][tmpY]+11 and myMap[tmpX][tmpY-1]=="C" and (parent[tmpX][tmpY]~="N" or streckentyp(tmpX,tmpY)=="Wende") then if tmpDist[tmpX][tmpY-1]==math.huge or streckentyp(tmpX,tmpY)=="Wende" then table.insert(queue, {x=tmpX, y=tmpY-1}) end if tmpDist[tmpX][tmpY]+10 do tmpX = queue[1].x tmpY = queue[1].y --spread to west if tmpX>1 and myMap[tmpX-1][tmpY]=="C" and (parent[tmpX][tmpY]~="W" or streckentyp(tmpX,tmpY)=="Wende") then if dist[train.ID][tmpX-1][tmpY]==math.huge or streckentyp(tmpX,tmpY)=="Wende" then table.insert(queue, {x=tmpX-1, y=tmpY}) end if dist[train.ID][tmpX][tmpY]+11 and myMap[tmpX][tmpY-1]=="C" and (parent[tmpX][tmpY]~="N" or streckentyp(tmpX,tmpY)=="Wende") then if dist[train.ID][tmpX][tmpY-1]==math.huge or streckentyp(tmpX,tmpY)=="Wende" then table.insert(queue, {x=tmpX, y=tmpY-1}) end if dist[train.ID][tmpX][tmpY]+10 do tmpX=todoQueue[1].x tmpY=todoQueue[1].y if tmpY1 and myMap[tmpX][tmpY-1]=="C" and streckentyp(tmpX,tmpY-1)~="Kreuzung" and isInSet[tmpX][tmpY-1]==false then table.insert(rangeQueue,{x=tmpX,y=tmpY-1}) isInSet[tmpX][tmpY-1]=true table.insert(todoQueue,{x=tmpX,y=tmpY-1}) end if tmpX1 and myMap[tmpX-1][tmpY]=="C" and streckentyp(tmpX-1,tmpY)~="Kreuzung" and isInSet[tmpX-1][tmpY]==false then table.insert(rangeQueue,{x=tmpX-1,y=tmpY}) isInSet[tmpX-1][tmpY]=true table.insert(todoQueue,{x=tmpX-1,y=tmpY}) end table.remove(todoQueue,1) end for i=1,#rangeQueue do tmpBewertung=tmpBewertung+bewertung[rangeQueue[i].x][rangeQueue[i].y] end tmpBewertung=tmpBewertung/math.sqrt(#rangeQueue) return tmpBewertung end function ai.chooseDirection(train, possibleDirections, destX, destY) if train.passenger==nil then --smoothen bewertung bewertungS=0 bewertungN=0 bewertungE=0 bewertungW=0 if possibleDirections["S"]==true then bewertungS=bewertungTowards(train.nextX,train.nextY+1) end if possibleDirections["N"]==true then bewertungN=bewertungTowards(train.nextX,train.nextY-1) end if possibleDirections["E"]==true then bewertungE=bewertungTowards(train.nextX+1,train.nextY) end if possibleDirections["W"]==true then bewertungW=bewertungTowards(train.nextX-1,train.nextY) end --use bewertung print("bewertungen: S="..bewertungS..", N="..bewertungN..", E="..bewertungE..", W="..bewertungW) bestBewertung="X" bestIndex=-math.huge if possibleDirections["S"]==true and bewertungS>bestIndex then bestIndex=bewertungS bestBewertung="S" end if possibleDirections["N"]==true and bewertungN>bestIndex then bestIndex=bewertungN bestBewertung="N" end if possibleDirections["E"]==true and bewertungE>bestIndex then bestIndex=bewertungE bestBewertung="E" end if possibleDirections["W"]==true and bewertungW>bestIndex then bestIndex=bewertungW bestBewertung="W" end --passe bewertung fuers naechste mal an if bestBewertung=="S" then bewertung[train.nextX][train.nextY+1] = bewertung[train.nextX][train.nextY+1]-constGefahren elseif bestBewertung=="N" then bewertung[train.nextX][train.nextY-1] = bewertung[train.nextX][train.nextY-1]-constGefahren elseif bestBewertung=="E" then bewertung[train.nextX+1][train.nextY] = bewertung[train.nextX+1][train.nextY]-constGefahren elseif bestBewertung=="W" then bewertung[train.nextX-1][train.nextY] = bewertung[train.nextX-1][train.nextY]-constGefahren end print("at "..train.nextX..":"..train.nextY.." used bewertung") return bestBewertung end if routing[train.ID]==nil or routing[train.ID][train.nextX][train.nextY]==nil or routing[train.ID][train.nextX][train.nextY]=="X" then routing[train.ID]=nil doRouting(train, possibleDirections, train.passenger.destX, train.passenger.destY) end if routing[train.ID]~=nil and routing[train.ID][train.nextX][train.nextY]~=nil and routing[train.ID][train.nextX][train.nextY]~="X" then print("at "..train.nextX..":"..train.nextY.." used routing towards "..routing[train.ID][train.nextX][train.nextY]) return routing[train.ID][train.nextX][train.nextY] else print("at "..train.nextX..":"..train.nextY.." used random routing, restarting routing") routing[train.ID]=nil return nr2dir(math.random(1,4)) end end function ai.enoughMoney() bestBewertung=0 tmpX=1 tmpY=1 for i=1,myMap.width do for j=1,myMap.height do if bewertung[i][j]>bestBewertung then bestBewertung=bewertung[i][j] tmpX=i tmpY=j end end end buyTrain(tmpX,tmpY) end function ai.foundPassengers(train, passengers) --if already has a passenger, only change it when it's on the route if train~=nil and train.passenger~=nil then -- for i=1, #passengers do -- if routing~=nil and routing[train.ID]~=nil and routing[train.ID][passengers[i].destX][passengers[i].destY]~="X" then -- kommtNoch=false -- tmpX=train.x -- tmpY=train.y -- while routing[train.ID][tmpX][tmpY]~="X" do -- if routing[train.ID][tmpX][tmpY]=="S" then tmpY=tmpY+1 -- elseif routing[train.ID][tmpX][tmpY]=="N" then tmpY=tmpY-1 -- elseif routing[train.ID][tmpX][tmpY]=="E" then tmpX=tmpX+1 -- elseif routing[train.ID][tmpX][tmpY]=="W" then tmpX=tmpX-1 end -- if tmpX==passengers[i].destX and tmpY==passengers[i].destY then kommtNoch=true end -- end -- if kommtNoch==true then -- print("passagier gnadenlos fallen glasst!!!!") -- printMap(routing[train.ID]) -- print("alte dest war "..train.passenger.destX..":"..train.passenger.destY..", neue ist "..passengers[i].destX..":"..passengers[i].destY) -- if train.passenger~=nil then -- dropPassenger(train) -- return passenger[i] -- end -- end -- end -- end return end --take the passenger with minimal real or euklidean distance passMinDist=1 minDist=math.huge routing[train.ID]=nil for i=1, #passengers do --doRouting(train, nil, passengers[i].destX, passengers[i].destY) if passDist[passengers[i].name]~=nil then print("found "..passengers[i].name.." in table with dist "..passDist[passengers[i].name]) tmp=passDist[passengers[i].name] else tmp=euDist(train.x,train.y,passengers[i].destX,passengers[i].destY) end if not (#(passengers[i].name)>5) then tmp = tmp*constVIP end print("found "..passengers[i].name.." with value"..tmp) if tmp<=minDist then passMinDist=i minDist=euDist(train.x, train.y, passengers[i].destX, passengers[i].destY) end end return passengers[passMinDist] end function ai.foundDestination(train) dropPassenger(train) end function euDist(x1, y1, x2, y2) return (x1-x2)^2+(y1-y2)^2 end function printMap(map) str = {} for j = 1, myMap.height do str[j] = "" for i = 1, myMap.width do if map[i][j]==math.huge then str[j] = str[j] .. "+ " elseif map[i][j] then str[j] = str[j] .. map[i][j] .. " " else str[j] = str[j] .. "- " end end end for i = 1, #str do print(str[i]) end end