View difference between Paste ID: bGdCnPmp and fKqTDD5r
SHOW: | | - or go back to the newest paste.
1
--[[
2-
		Code Runner
2+
		Gold Runner
3-
		Inspired by the game by Doug 
3+
		Inspired by the game by Doug Smith (C) 1983
4
5
		Written by: Nitrogen Fingers
6
]]--
7
8
running = true
9
started = false
10
nextLevel = false
11
12
local drawOffsetX = 1
13
local drawOffsetY = 0
14
15
local map = {}
16
local goldMap = {}
17
local blockTimers = {}
18
local blockIntv = 5
19
20
local monks = {}
21
local monkTimer = -1
22
local monkSpawnIntv = 3
23
local monkTrapIntv = blockIntv/2
24
25
local goldCount = 0
26
local maxGoldCount = 0
27
local playerLives = 3
28
local playerScore = 0
29
local plspawnX = 0
30
local plspawnY = 0
31
32
local plX = 0
33
local plY = 0
34
local pfalling = false
35
local moveTimer = -1
36
local shootTimer = -1
37
local spawnTimer = -1
38
local moveIntv = 0.15
39
40
local exX = 0
41
local exY = 0
42
43
local levelList = {}
44
local currentLevel = 1
45
46
local function loadMap(_sPath)
47
  if not fs.exists(_sPath) then return end
48
  map = {}
49
  goldMap = {}
50
  monks = {}
51
  goldCount = 0
52
    
53
  local file = fs.open(_sPath, "r")
54
  local line = file:readLine()
55
  while line do
56
    goldMap[#map+1] = {}
57
    map[#map+1] = {}
58
    for i=1,math.min(#line,49) do
59
      local lchar = string.sub(line,i,i)
60
      if tonumber(lchar, 16) then
61
        lchar = math.pow(2, tonumber(lchar,16))
62
        
63
        if lchar == colours.blue then
64
          map[#map][i] = 0
65
        elseif lchar == colours.brown then
66
          map[#map][i] = 'H'
67
        elseif lchar == colours.yellow then
68
          goldMap[#map][i] = 1
69
          goldCount = goldCount + 1
70
        elseif lchar == colours.orange then
71
          map[#map][i] = 0
72
          goldMap[#map][i] = 1
73
          goldCount = goldCount + 1
74
        elseif lchar == colours.green then
75
          map[#map][i] = '-'
76
        elseif lchar == colours.lightGrey then
77
          map[#map][i] = 'h'
78
        elseif lchar == colours.grey then
79
          map[#map][i] = '#'
80
        elseif lchar == colours.white then
81
          plX = i
82
		  plspawnX = i
83
          plY = #map
84
		  plspawnY = #map
85
        elseif lchar == colours.lime then
86
          exX = i
87
          exY = #map
88
        elseif lchar == colours.red then
89
		  table.insert(monks, {
90
			--X and Y, clear enough
91
			x = i, y = #map;
92
			--Where they spawn when they die
93
			spawnX = i, spawnY = #map;
94
			-- Any gold they're carring- it's a 1 in 5
95
			gold = false;
96
			-- Whether or not they're falling
97
			falling = false;
98
			-- Timer if they're dead to respawn
99
			dead = nil;
100
			--Whether or not the monk has just spawned
101
			justSpawned = true;
102
			--Whether or not the monk has just escaped
103
			justEscaped = false;
104
			-- Current aim- it's "up", "down", "across" or "none"
105
			behaviour = "none";
106
			-- The desired x position to travel to, when one is necessary.
107
			desX = nil;
108
			-- The escape timer
109
			trapped = nil;
110
		  })
111
		end
112
      end
113
    end
114
    if #map == 18 then break end
115
    line = file:readLine()
116
  end
117
  file:close()
118
  maxGoldCount = goldCount
119
  return true
120
end
121
122
--When something moves or something needs to be drawn, we
123
--just change the appropriate tile with this method.
124
local function updateMap(x,y)
125
	term.setCursorPos(x + drawOffsetX, y + drawOffsetY)
126
	term.setBackgroundColour(colours.black)
127
    if plX == x and plY == y and map[y][x] ~= 0 then
128
      term.setTextColour(colours.white)
129
	  if map[y][x] == 1 then term.setBackgroundColour(colours.lightBlue) end
130
      term.write("&")
131
    elseif map[y][x] == 'H' or (map[y][x] == 'h' and
132
        goldCount == 0) then
133
      term.setTextColour(colours.brown)
134
      term.write("H")
135
    elseif map[y][x] == '-' then
136
      term.setTextColour(colours.brown)
137
      term.write(map[y][x])
138
    elseif map[y][x] == '#' then
139
      term.setBackgroundColour(colours.grey)
140
      term.write(" ")
141
    elseif type(map[y][x]) == "number" then
142
      local uchar = ' '
143
	  if map[y][x] == 3 then
144
		term.setBackgroundColour(colours.lightBlue)
145
      elseif map[y][x] == 2 and goldMap[y][x] == 1 then
146
        term.setTextColour(colours.yellow)
147
        uchar = '$'
148
      elseif map[y][x] == 1 then
149
        term.setBackgroundColour(colours.lightBlue)
150
      elseif map[y][x] == 0 then
151
        term.setBackgroundColour(colours.blue)
152
      end
153
      term.write(uchar)
154
    elseif goldMap[y][x] == 1 then
155
      term.setTextColour(colours.yellow)
156
      term.write('$')
157
    elseif exX == x and exY == y and goldCount == 0 then
158
      term.setTextColour(colours.lime)
159
      term.write("@")
160
    else
161
      term.write(" ")
162
    end
163
end
164
165
--It's silly to iterate through all monks when drawing tiles, so
166
--we do it separately.
167
local function drawMonk(monk)
168
	term.setCursorPos(monk.x + drawOffsetX, monk.y + drawOffsetY)
169
	if monk.justSpawned then term.setTextColour(colours.pink)
170
	else term.setTextColour(colours.red) end
171
	if map[monk.y][monk.x] == 1 then term.setBackgroundColour(colours.lightBlue)
172
	else term.setBackgroundColour(colours.black) end
173
	term.write("&")
174
end
175
176
--Draws the map for the first time. It barely changes, so we really
177
--only call this the once.
178
local function drawMap()
179
  for y=1,#map do
180
    for x=1,49 do
181
	  updateMap(x,y)
182
    end
183
  end
184
  for _,monk in pairs(monks) do drawMonk(monk)end
185
end
186
187
--When all coins have been collected, we add in invisble ladders and
188
--the end game portal.
189
local function drawEndgameMap()
190
  for y=1,#map do
191
    for x=1,49 do
192
	  if map[y][x] == 'h' or (exX == x and exY == y) then
193
		updateMap(x,y)
194
	  end
195
    end
196
  end
197
end
198
199
--Sets the map back to defaults, so we can start afresh
200
local function resetMap()
201
	goldCount = maxGoldCount
202
	for i=1,#goldMap do
203
		for j=1,49 do
204
			if goldMap[i][j] == 0 then goldMap[i][j] = 1 end
205
		end
206
	end
207
	for _,monk in pairs(monks) do
208
		monk.justSpawned = true
209
		monk.dead = nil
210
		monk.trapped = nil
211
		monk.justEscaped = false
212
		monk.falling = false
213
		monk.behaviour = "none"
214
		monk.x = monk.spawnX
215
		monk.y = monk.spawnY
216
	end
217
	
218
	for _,timer in pairs(blockTimers) do
219
		map[timer.y][timer.x] = 0
220
	end
221
	blockTimers = {}
222
	plX = plspawnX
223
	plY = plspawnY
224
	
225
	moveTimer = -1
226
	shootTimer = -1
227
	spawnTimer = -1
228
	monkTimer = -1
229
	pfalling = false
230
end
231
232
--Draws the HUD. This also rarely changes, so we update it when something happens.
233
local function drawHUD()
234
  term.setCursorPos(2,19)
235
  term.setBackgroundColour(colours.black)
236
  term.clearLine()
237
  term.setTextColour(colours.blue)
238
  term.write("Score: ")
239
  term.setTextColour(colours.yellow)
240
  term.write(string.rep("0", 5-math.floor(math.log10(playerScore + 1)))
241
    ..playerScore)
242
  term.setTextColour(colours.yellow)
243
  term.setCursorPos(25 - #levelList[currentLevel]/2, 19)
244
  term.write(levelList[currentLevel])
245
  local lstr = "Men: "
246
  term.setCursorPos(50 - #lstr - math.floor(math.log10(playerLives)), 19)
247
  term.setTextColour(colours.blue)
248
  term.write(lstr)
249
  term.setTextColour(colours.yellow)
250
  term.write(playerLives.."")
251
end
252
253
--Checks to see if any given desired move is legal. Monks and players both use this.
254
local function isLegalMove(initX,initY,finX,finY)
255
	if map[finY][finX] ~= 0 and map[finY][finX] ~= '#' then
256
		--This reports 'self moves' as being illegal, but that's fine
257
		for _,monk in pairs(monks) do
258
			if monk.x == finX and monk.y == finY then return false end
259
		end
260
261
		if finY == initY-1 and (map[initY][initX] == "H" or (map[initY][initX] == "h" and goldCount == 0))
262
			then return true
263
		elseif finY == initY+1 and (map[finY][finX] == "H" or (map[finY][finX] == "h" and goldCount == 0)
264
				or (type(map[finY][finX]) == "number" and map[finY][finX] > 0) or map[finY][finX] == nil or
265
				map[finY][finX] == "-") 
266
			then return true
267
		elseif finX == initX-1 or finX == initX+1 then return true 
268
		end
269
	end
270
end
271
272
--Moves the player to a given step.
273
local function movePlayer(x,y,ignoreLegal)
274
	if not ignoreLegal and not isLegalMove(plX,plY,x,y) then return false end
275
	
276
	local ox = plX
277
	local oy = plY
278
	plX = x
279
	plY = y
280
	
281
	updateMap(ox,oy)
282
	updateMap(x,y)
283
	if goldMap[y][x] == 1 then
284
		goldMap[y][x] = 0
285
		goldCount = goldCount - 1
286
		playerScore = playerScore + 5
287
		if playerScore % 200 == 0 then playerLives = playerLives + 1 end
288
		drawHUD()
289
		if (goldCount == 0) then
290
			drawEndgameMap()
291
		end
292
	elseif exX == plX and exY == plY and goldCount == 0 then
293
		started = false
294
		nextLevel = true
295
	end
296
	
297
	pfalling = (y < #map and map[y][x] ~= '-' and map[y][x] ~= 'H' and not (map[y][x] == 'h' and goldCount == 0) 
298
		and (map[y+1][x] == nil or map[y+1][x] == 2 or map[y+1][x] == '-'))
299
	for _,monk in pairs(monks) do
300
		if monk.x == plX and monk.y == plY + 1 then pfalling = false break end
301
	end
302
	return true
303
end
304
305
local function updateMonks()
306
	for _,monk in pairs(monks) do
307
		--Absolute first step- if he's trapped or dead, he's going nowhere
308
		if monk.trapped or monk.dead then
309
		--If he's just spawned he takes a second to orient himself
310
		elseif monk.justSpawned then
311
			monk.justSpawned = false
312
			--We evaluate their falling behaviour here (as freed monks CAN stand on air)
313
			monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and (map[monk.y+1][monk.x] == nil or 
314
				map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number"))
315
			for _,omonk in pairs(monks) do
316
				if omonk.x == monk.x and omonk.y == monk.y + 1 then monk.falling = false break end
317
			end
318
			if monk.x == plX and monk.y == plY + 1 then monk.falling = false end
319
		--Then we consider if he's just gotten out of a hole
320
		elseif monk.justEscaped then
321
			monk.justEscaped = false
322
			--He tries the player side first
323
			local playerSide = (plX-monk.x) / math.abs(plX-monk.x)
324
			if isLegalMove(monk.x, monk.y, monk.x + playerSide, monk.y) then
325
				monk.x = monk.x + playerSide
326
				updateMap(monk.x - playerSide, monk.y)
327
			elseif isLegalMove(monk.x, monk.y, monk.x - playerSide, monk.y) then
328
				monk.x = monk.x - playerSide
329
				updateMap(monk.x + playerSide, monk.y)
330
			end
331
			drawMonk(monk)
332
		--Then we evaluate falling
333
		elseif monk.falling then
334
			monk.behaviour = "none"
335
			monk.y = monk.y + 1
336
			updateMap(monk.x, monk.y-1)
337
			drawMonk(monk)
338
			monk.desX = nil
339
			if type(map[monk.y][monk.x]) == "number" then
340
				monk.trapped = os.startTimer(monkTrapIntv)
341
				monk.falling = false
342
			else
343
				monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and (map[monk.y+1][monk.x] == nil or 
344
					map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number"))
345
				for _,omonk in pairs(monks) do
346
					if omonk.x == monk.x and omonk.y == monk.y + 1 then monk.falling = false break end
347
				end
348
				if monk.x == plX and monk.y == plY + 1 then monk.falling = false end
349
				if monk.justEscaped then monk.falling = false end
350
			end
351
		--If he's on his feet and not trapped, he's allowed to think about where to move
352
		elseif monk.y == plY then
353
			--Is the monk on the same level as the player? How lucky! They'll just walk towards him
354
			monk.desX = plX
355
			monk.behaviour = "across"
356
		--Y difference takes precedence over X (as in the original, makes them a bit smarter)
357
		elseif monk.y < plY then
358
			--If they can move up, they will
359
			if isLegalMove(monk.x,monk.y,monk.x,monk.y+1) and not monk.justEscaped then
360
				monk.y = monk.y+1
361
				updateMap(monk.x, monk.y-1)
362
				drawMonk(monk)
363
				monk.desX = nil
364
				--A down move can lead to a fall, so we check if they're now falling.
365
				monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and (map[monk.y+1][monk.x] == nil or 
366
					map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number"))
367
				monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and (map[monk.y+1][monk.x] == nil or 
368
					map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number"))
369
				for _,omonk in pairs(monks) do
370
					if omonk.x == monk.x and omonk.y == monk.y + 1 then monk.falling = false break end
371
				end
372
				if monk.x == plX and monk.y == plY + 1 then monk.falling = false end
373
			--Otherwise, it's off to the nearest ladder, monkey bars or perilous ledge to jump off
374
			--assuming they haven't found one already
375
			elseif monk.desX == nil then
376
				if monk.behaviour ~= "down" then monk.desX = nil end
377
				monk.behaviour = "down"
378
				monk.desX = nil
379
				local cmLeft = true
380
				local cmRight = true
381
				--We try to find the nearest by searching alternate left and right at variable distance
382
				for i=1,math.max(monk.x - 1, 49 - monk.x) do
383
					if monk.x-i > 0 and cmLeft then
384
						--If a wall blocks the monks path, they can't keep going left or right
385
						cmLeft = map[monk.y][monk.x-i] ~= 0
386
						--But if it's all clear, they look for something to climb/jump down
387
						if cmLeft and (map[monk.y+1][monk.x-i] == "H" or (map[monk.y+1][monk.x-i] == 'h' and goldCount == 0)
388
							or map[monk.y+1][monk.x-i] == nil or map[monk.y][monk.x-i] == '-') then
389
							monk.desX = monk.x-i
390
							break
391
						end
392
					end
393
					if monk.x+i < 50 and cmRight then
394
						--If a wall blocks the monks path, they can't keep going left or right
395
						cmRight = map[monk.y][monk.x+i] ~= 0
396
						--But if it's all clear, they look for something to climb/jump down
397
						if cmRight and (map[monk.y+1][monk.x+i] == "H" or (map[monk.y+1][monk.x+i] == 'h' and goldCount == 0)
398
							or map[monk.y+1][monk.x+i] == nil or map[monk.y][monk.x+i] == '-') then
399
							monk.desX = monk.x+i
400
							break
401
						end
402
					end
403
				end
404
			end
405
		elseif monk.y > plY then
406
			if monk.behaviour ~= "up" then monk.desX = nil end
407
			monk.behaviour = "up"
408
			--Same deal again- try moving up first
409
			if isLegalMove(monk.x,monk.y,monk.x,monk.y-1) then
410
				monk.y = monk.y-1
411
				updateMap(monk.x, monk.y+1)
412
				drawMonk(monk)
413
				monk.desX = nil
414
				--You can never move up and start falling, so we don't bother to check
415
			--Otherwise they need ladders to climb up
416
			elseif monk.desX == nil then
417
				monk.behaviour = "up"
418
				monk.desX = nil
419
				local cmLeft = true
420
				local cmRight = true
421
				--We try to find the nearest by searching alternate left and right at variable distance
422
				for i=1,math.max(monk.x - 1, 49 - monk.x) do
423
					if monk.x-i > 0 and cmLeft then
424
						--If a wall blocks the monks path or a pit is in the way, they can't keep going left or right
425
						cmLeft = map[monk.y][monk.x-i] ~= 0 and (monk.y == #map or map[monk.y+1][monk.x-i] ~= nil
426
								or map[monk.y][monk.x-i] == '-')
427
						--But if it's all clear, they look for a ladder
428
						if cmLeft and (map[monk.y][monk.x-i] == "H" or (map[monk.y][monk.x-i] == 'h' and goldCount == 0)) then
429
							monk.desX = monk.x-i
430
							break
431
						end
432
					end
433
					if monk.x+i < 50 and cmRight then
434
						cmRight = map[monk.y][monk.x+i] ~= 0 and (monk.y == #map or map[monk.y+1][monk.x+i] ~= nil
435
								or map[monk.y][monk.x+i] == '-')
436
						if cmRight and (map[monk.y][monk.x+i] == "H" or (map[monk.y][monk.x+i] == 'h' and goldCount == 0)) then
437
							monk.desX = monk.x+i
438
							break
439
						end
440
					end
441
				end
442
			end
443
		end
444
		
445
		if not (monk.trapped or monk.dead) then
446
			--Has the monk decided on moving left or right? If so we try to move him
447
			if monk.desX and not monk.falling then
448
				local mdir = monk.desX - monk.x
449
				local mdir = mdir / math.abs(mdir)
450
				if isLegalMove(monk.x,monk.y,monk.x+mdir,monk.y) then
451
					monk.x = monk.x + mdir
452
					updateMap(monk.x - mdir, monk.y)
453
					drawMonk(monk)
454
				else
455
					--This allows re-evaluations if they get stuck- not ideal but good enough
456
					monk.desX = nil
457
				end
458
			end
459
			monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and (map[monk.y+1][monk.x] == nil or 
460
				map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number"))
461
			for _,omonk in pairs(monks) do
462
				if omonk.x == monk.x and omonk.y == monk.y + 1 then monk.falling = false break end
463
			end
464
			if monk.x == plX and monk.y == plY + 1 then monk.falling = false end
465
			--We have caught and killed the player
466
			if monk.x == plX and monk.y == plY and spawnTimer == -1 then
467
				spawnTimer = os.startTimer(2)
468
			end
469
		end
470
	end
471
end
472
473
local function updateBlockTimer(tid)
474
	local remAt = nil
475
	for i,v in ipairs(blockTimers) do
476
		if v.timer == tid then
477
			if map[v.y][v.x] == 3 then
478
				map[v.y][v.x] = 2
479
				v.timer = os.startTimer(blockIntv)
480
			elseif map[v.y][v.x] == 2 then
481
				map[v.y][v.x] = 1
482
				v.timer = os.startTimer(0.1)
483
			elseif map[v.y][v.x] == 1 then
484
				map[v.y][v.x] = 0
485
				--If the player is caught in a block, he dies
486
				if v.y == plY and v.x == plX then
487
					spawnTimer = os.startTimer(2)
488
				end
489
				for _,monk in pairs(monks) do
490
					if monk.x == v.x and monk.y == v.y then
491
						monk.dead = os.startTimer(monkSpawnIntv)
492
						--Easiest way to get them out of the way rather than evaluation
493
						monk.x = -1
494
						monk.y = -1
495
						monk.trapped = nil
496
					end
497
				end
498
				remAt = i
499
			end
500
			updateMap(v.x,v.y)
501
			break
502
		end
503
	end
504
	if remAt then table.remove(blockTimers,remAt) end
505
end
506
507
local function shootBlock(x,y)
508
	if y <= #map and map[y][x] == 0 and (map[y-1][x] == nil 
509
			or map[y-1][x] == 2 or (map[y-1][x] == 'h' and goldCount > 0)) then
510
		map[y][x] = 3
511
		table.insert(blockTimers, {x = x; y = y; timer = os.startTimer(0.1);} )
512
		updateMap(x,y)
513
	end
514
end
515
516
local function handleEvents()
517
	local id,p1,p2,p3 = os.pullEvent()
518
	
519
	if id == "key" then
520
		if p1 == keys.a and moveTimer == -1 and spawnTimer == -1 then
521
			movePlayer(plX-1,plY)
522
			moveTimer = os.startTimer(moveIntv)
523
		elseif p1 == keys.d and moveTimer == -1 and spawnTimer == -1 then
524
			movePlayer(plX+1,plY)
525
			moveTimer = os.startTimer(moveIntv)
526
		elseif p1 == keys.w and moveTimer == -1 and spawnTimer == -1 then
527
			movePlayer(plX,plY-1)
528
			moveTimer = os.startTimer(moveIntv)
529
		elseif p1 == keys.s and moveTimer == -1 and spawnTimer == -1 then
530
			movePlayer(plX,plY+1)
531
			moveTimer = os.startTimer(moveIntv)
532
		elseif p1 == keys.q and shootTimer == -1 and not pfalling and spawnTimer == -1 then
533
			shootBlock(plX-1,plY+1)
534
			shootTimer = os.startTimer(moveIntv)
535
		elseif p1 == keys.e and shootTimer == -1 and not pfalling and spawnTimer == -1 then
536
			shootBlock(plX+1,plY+1)
537
			shootTimer = os.startTimer(moveIntv)
538
		elseif p1 == keys.enter then
539
			started = false
540
		elseif p1 == keys.t then
541
			started = false
542
			running = false
543
		end
544
	elseif id == "timer" then
545
		if p1 == shootTimer then shootTimer = -1
546
		elseif p1 == spawnTimer then
547
			started = false
548
		elseif p1 == moveTimer then
549
			if pfalling then
550
				movePlayer(plX,plY+1)
551
				moveTimer = os.startTimer(moveIntv)
552
			else
553
				moveTimer = -1
554
			end
555
		elseif p1 == monkTimer then
556
			updateMonks()
557
			monkTimer = os.startTimer(moveIntv * 2)
558
		elseif updateBlockTimer(p1) then
559
		else
560
			for _,monk in pairs(monks) do
561
				if p1 == monk.trapped then
562
					--You can stand on a monk to force them to be killed- so we check for that
563
					--along with being buried in tunnels, etc.
564
					local stillTrapped = map[monk.y-1][monk.x] == 0 or (plX == monk.x and plY == monk.y-1)
565
					for _,omonk in pairs(monks) do
566
						if omonk.x == monk.x and omonk.y == monk.y-1 then
567
							stillTrapped = true
568
							break
569
						end
570
					end
571
					--Perpetually trapped monks will try to excape much more quickly
572
					if stillTrapped then
573
						--This needs to be tweaked
574
						monk.trapped = os.startTimer(0.75)
575
					else
576
						--When free, they head in your general direction, re-evaluate later
577
						monk.y = monk.y - 1
578
						--This is necessary to stop 'double jumping'
579
						monk.desX = nil
580
						monk.trapped = nil
581
						monk.behaviour = "none"
582
						monk.justEscaped = true
583
						
584
						updateMap(monk.x, monk.y+1)
585
						drawMonk(monk)
586
					end
587
					break
588
				elseif p1 == monk.dead then
589
					--Same deal- you can camp spawn
590
					local stillDead = plX == monk.spawnX and plY == monk.spawnY
591
					for _,omonk in pairs(monks) do
592
						if omonk.x == monk.spawnX and omonk.y == monk.spawnY then
593
							stillDead = true
594
							break
595
						end
596
					end
597
					--They'll spawn the second you give them the chance
598
					if stillDead then
599
						monk.dead = os.startTimer(0.5)
600
					else
601
						monk.x = monk.spawnX
602
						monk.y = monk.spawnY
603
						monk.dead = nil
604
						monk.justSpawned = true
605
						monk.behaviour = "none"
606
						drawMonk(monk)
607
						break
608
					end
609
				end
610
			end
611
		end
612
	end
613
end
614
615
term.clear()
616
if not fs.exists(shell.resolve(".").."/levels") then
617
	error("Level directory not present!")
618
end
619
levelList = fs.list(shell.resolve(".").."/levels")
620
if #levelList == 0 then
621
	error("Level directory is empty!")
622
end
623
624
loadMap(shell.resolve(".").."/levels/"..levelList[currentLevel])
625
while running do
626
	drawMap()
627
	drawHUD()
628
	os.pullEvent("key")
629
	monkTimer = os.startTimer(moveIntv * 1.5)
630
	
631
	started = true
632
	while started do
633
		handleEvents()
634
	end
635
	
636
	if nextLevel then
637
		if currentLevel == #levelList then 
638
			running = false
639
			break
640
		else
641
			currentLevel = currentLevel + 1
642
   resetMap()
643
			loadMap(shell.resolve(".").."/levels/"..levelList[currentLevel])
644
		end
645
		nextLevel = false
646
	else
647
		playerLives = playerLives-1
648
		if playerLives > 0 then resetMap()
649
		else running = false end
650
	end
651
end
652
653
if nextLevel then
654
	local msg = "All levels defeated, Code Runner!"
655
	term.setBackgroundColour(colours.black)
656
	term.setTextColour(colours.lime)
657
	term.setCursorPos(25 - #msg/2, 2)
658
	term.write(msg)
659
else
660
	local msg = "Game over!"
661
	term.setBackgroundColour(colours.black)
662
	term.setTextColour(colours.red)
663
	term.setCursorPos(25 - #msg/2, 2)
664
	term.write(msg)
665
end
666
sleep(2)
667
term.setCursorPos(19,51)
668
print("")