local min, max, huge = math.min, math.max, math.huge local machine = {state = {}} machine.counters = { ["@move player"] = 0, ["@[move up] is down"] = 0, ["@is [move up] down?"] = 0, ["@exit code"] = 0, ["@is [move left] down?"] = 0, ["@is [move down] down?"] = 0, ["handling input"] = 0, ["@is [move right] down?"] = 0, ["run main loop"] = 1, ["start polling inputs"] = 0, ["@shoot bullet"] = 0, ["poll input"] = 0, ["@move bullets"] = 0, ["@delete out of bounds bullets"] = 0, ["@draw bullets"] = 0, ["@update spawn timer"] = 0, ["@make the timer faster"] = 0, ["@reset timer"] = 0, ["@do player collisions"] = 0, ["@spawn a zombie"] = 0, ["@[move left] is down"] = 0, ["@[move down] is down"] = 0, ["@delete killed zombies"] = 0, ["@[move right] is down"] = 0, ["@event keyreleased"] = 0, ["@event mousemoved"] = 0, ["shoot bullet"] = 0, ["drawing scene"] = 0, ["@do bullet collisions"] = 0, ["draw player"] = 0, ["draw bullets"] = 0, ["@start polling"] = 0, ["draw zombies"] = 0, ["updating scene"] = 0, ["@quit love"] = 0, ["@dir up"] = 0, ["@dir down"] = 0, ["@poll input"] = 0, ["@clear screen"] = 0, ["@dir right"] = 0, ["moving player"] = 0, ["move bullets"] = 0, ["@sleep"] = 0, ["move zombies"] = 0, ["@ms"] = 0, ["check for player hit by zombie"] = 0, ["check for bullet hitting zombie"] = 0, ["update spawn timer"] = 0, ["@no events left"] = 0, ["@spawn timer expired"] = 0, ["spawn a zombie"] = 0, ["make the timer faster"] = 0, ["run current frame"] = 0, ["reset timer"] = 0, ["step timer"] = 0, ["sweep deleted entities"] = 0, ["clear the screen"] = 0, ["update scene state"] = 0, ["draw scene"] = 0, ["present current frame"] = 0, ["sleep for 1ms"] = 0, ["@event quit"] = 0, ["next cycle"] = 0, ["handle input"] = 0, ["@draw zombies"] = 0, ["@dir left"] = 0, ["@move zombies"] = 0, ["@print fps"] = 0, ["@present"] = 0, ["@event keypressed"] = 0, ["@event mousepressed"] = 0, ["@draw player"] = 0, ["move player"] = 0, ["check for collisions"] = 0, ["@step timer"] = 0, } machine.state = { ["player"] = {x = 400, y = 300, r = 10, health = 5}, ["bullets"] = {}, ["event_args"] = {}, ["spawn_timer"] = { time_left = 1, duration = 1 }, ["dt"] = 0, ["zombies"] = {}, } function machine:on_print_fps(counters) love.graphics.setColor(1, 0, 0) love.graphics.print( tostring(love.timer.getFPS()) .. " bullets: " .. tostring(#self.state.bullets) .. " zombies: " .. tostring(#self.state.zombies) , 10, 10) love.graphics.setColor(1, 1, 1) end function machine:on_draw_player(counters) local player = self.state.player love.graphics.setColor(0, 1, 0) love.graphics.circle("fill", player.x, player.y, player.r) love.graphics.setColor(1, 1, 1) end function machine:on_move_player(counters, dir_up, dir_down, dir_left, dir_right) local player = self.state.player local dir_y = (dir_down - dir_up) local dir_x = (dir_right - dir_left) player.x = player.x + dir_x * self.state.dt * 300 player.y = player.y + dir_y * self.state.dt * 300 end function machine:on_is_move_up_down(counters) if love.keyboard.isDown("w") then counters["@[move up] is down"] = 1 end end function machine:on_is_move_left_down(counters) if love.keyboard.isDown("a") then counters["@[move left] is down"] = 1 end end function machine:on_is_move_down_down(counters) if love.keyboard.isDown("s") then counters["@[move down] is down"] = 1 end end function machine:on_is_move_right_down(counters) if love.keyboard.isDown("d") then counters["@[move right] is down"] = 1 end end function machine:on_shoot_bullet(counters) local bullets = self.state.bullets local px, py = self.state.player.x, self.state.player.y local mx, my = love.mouse.getPosition() local angle = math.atan2(my - py, mx - px) table.insert(bullets, {x = px, y = py, angle = angle, r = 5}) end function machine:on_move_bullets(counters) local dt = self.state.dt local bullets = self.state.bullets for _, bullet in ipairs(bullets) do bullet.x = bullet.x + math.cos(bullet.angle) * 350 * dt bullet.y = bullet.y + math.sin(bullet.angle) * 350 * dt local in_bounds = -10 <= bullet.x and bullet.x <= 810 and -10 <= bullet.y and bullet.y <= 610 if not in_bounds then bullet.deleted = true end end end function machine:on_delete_bullets(counters) local bullets = self.state.bullets local survivers = {} for _, bullet in ipairs(bullets) do if not bullet.deleted then table.insert(survivers, bullet) end end self.state.bullets = survivers end function machine:on_draw_bullets(counters) local bullets = self.state.bullets for _, bullet in ipairs(bullets) do love.graphics.setColor(1, 1, 0) love.graphics.circle("fill", bullet.x, bullet.y, bullet.r) love.graphics.setColor(1, 1, 1) end end function machine:on_update_spawn_timer(counters) local spawn_timer = self.state.spawn_timer spawn_timer.time_left = spawn_timer.time_left - self.state.dt if 0 >= spawn_timer.time_left then counters["@spawn timer expired"] = 1 end end function machine:on_make_the_timer_faster(counters) local spawn_timer = self.state.spawn_timer spawn_timer.duration = spawn_timer.duration - 0.0125 end function machine:on_reset_timer(counters) local spawn_timer = self.state.spawn_timer spawn_timer.time_left = spawn_timer.duration end function machine:on_draw_zombies(counters) local zombies = self.state.zombies for _, zombie in ipairs(zombies) do love.graphics.setColor(1, 0, 0) love.graphics.circle("fill", zombie.x, zombie.y, zombie.r) love.graphics.setColor(1, 0, 0) end end function machine:on_spawn_a_zombie(counters) local angle = math.random() * math.pi * 2 local x, y = math.cos(angle) * 450 + 400, math.sin(angle) * 350 + 300 table.insert(self.state.zombies, {x = x, y = y, health = 2, r = 10}) end function machine:on_delete_killed_zombies(counters) local zombies = self.state.zombies local survivers = {} for _, zombie in ipairs(zombies) do if not zombie.dead then table.insert(survivers, zombie) end end self.state.zombies = survivers end function machine:on_move_zombies(counters) local player = self.state.player local zombies = self.state.zombies for _, zombie in ipairs(zombies) do local angle = math.atan2(player.y - zombie.y, player.x - zombie.x) zombie.x = zombie.x + self.state.dt * math.cos(angle) * 310 zombie.y = zombie.y + self.state.dt * math.sin(angle) * 310 end end function machine:on_do_bullet_collisions(counters) local bullets = self.state.bullets local zombies = self.state.zombies for _, bullet in ipairs(bullets) do if bullet.deleted then goto next_bullet end for _, zombie in ipairs(zombies) do if zombie.dead then goto next_zombie end local min_distance = bullet.r + zombie.r local distance = math.sqrt((bullet.x - zombie.x) ^ 2 + (bullet.y - zombie.y) ^ 2) if distance < min_distance then zombie.health = zombie.health - 1 if zombie.health < 0 then zombie.dead = true end bullet.deleted = true end ::next_zombie:: end ::next_bullet:: end end function machine:on_start_polling(counters) love.event.pump() self.state.event_iter = love.event.poll() end function machine:on_poll_input(counters) local name, a, b, c, d, e, f = self.state.event_iter() if name then local counter = "@event " .. name if counters[counter] then counters[counter] = 1 self.state.event_args[1] = a self.state.event_args[2] = b self.state.event_args[3] = c self.state.event_args[4] = d self.state.event_args[5] = e self.state.event_args[6] = f end else counters["@no events left"] = 1 end end function machine:on_quit_love(counters) counters["@exit code"] = self.state.event_args[1] or 0 end function machine:on_step_timer(counters) self.state.dt = love.timer.step() end function machine:on_clear_screen(counters) love.graphics.origin() love.graphics.clear(love.graphics.getBackgroundColor()) end function machine:on_present(counters) love.graphics.present() end function machine:on_sleep(counters, ms) love.timer.sleep(ms / 1000) end function match(self, counters) if counters["@print fps"] > 0 then self:on_print_fps(counters) counters["@print fps"] = 0 return true end if counters["@draw player"] > 0 then self:on_draw_player(counters) counters["@draw player"] = 0 return true end if counters["@move player"] > 0 then self:on_move_player(counters, counters["@dir up"], counters["@dir down"], counters["@dir left"], counters["@dir right"]) counters["@move player"] = 0 counters["@dir up"] = 0 counters["@dir down"] = 0 counters["@dir left"] = 0 counters["@dir right"] = 0 return true end if counters["@is [move up] down?"] > 0 then counters["@[move up] is down"] = 0 self:on_is_move_up_down(counters) counters["@is [move up] down?"] = 0 return true end if counters["@is [move left] down?"] > 0 then counters["@[move left] is down"] = 0 self:on_is_move_left_down(counters) counters["@is [move left] down?"] = 0 return true end if counters["@is [move down] down?"] > 0 then counters["@[move down] is down"] = 0 self:on_is_move_down_down(counters) counters["@is [move down] down?"] = 0 return true end if counters["@is [move right] down?"] > 0 then counters["@[move right] is down"] = 0 self:on_is_move_right_down(counters) counters["@is [move right] down?"] = 0 return true end if counters["@shoot bullet"] > 0 then self:on_shoot_bullet(counters) counters["@shoot bullet"] = 0 return true end if counters["@move bullets"] > 0 then self:on_move_bullets(counters) counters["@move bullets"] = 0 return true end if counters["@delete out of bounds bullets"] > 0 then self:on_delete_bullets(counters) counters["@delete out of bounds bullets"] = 0 return true end if counters["@draw bullets"] > 0 then self:on_draw_bullets(counters) counters["@draw bullets"] = 0 return true end if counters["@update spawn timer"] > 0 then counters["@spawn timer expired"] = 0 self:on_update_spawn_timer(counters) counters["@update spawn timer"] = 0 return true end if counters["@make the timer faster"] > 0 then self:on_make_the_timer_faster(counters) counters["@make the timer faster"] = 0 return true end if counters["@reset timer"] > 0 then self:on_reset_timer(counters) counters["@reset timer"] = 0 return true end if counters["@draw zombies"] > 0 then self:on_draw_zombies(counters) counters["@draw zombies"] = 0 return true end if counters["@spawn a zombie"] > 0 then self:on_spawn_a_zombie(counters) counters["@spawn a zombie"] = 0 return true end if counters["@delete killed zombies"] > 0 then self:on_delete_killed_zombies(counters) counters["@delete killed zombies"] = 0 return true end if counters["@move zombies"] > 0 then self:on_move_zombies(counters) counters["@move zombies"] = 0 return true end if counters["@do bullet collisions"] > 0 then self:on_do_bullet_collisions(counters) counters["@do bullet collisions"] = 0 return true end if counters["@start polling"] > 0 then self:on_start_polling(counters) counters["@start polling"] = 0 return true end if counters["@poll input"] > 0 then counters["@event keypressed"] = 0 counters["@event keyreleased"] = 0 counters["@event mousemoved"] = 0 counters["@event mousepressed"] = 0 counters["@no events left"] = 0 self:on_poll_input(counters) counters["@poll input"] = 0 return true end if counters["@quit love"] > 0 then counters["@exit code"] = 0 self:on_quit_love(counters) counters["@quit love"] = 0 return true end if counters["@step timer"] > 0 then self:on_step_timer(counters) counters["@step timer"] = 0 return true end if counters["@clear screen"] > 0 then self:on_clear_screen(counters) counters["@clear screen"] = 0 return true end if counters["@present"] > 0 then self:on_present(counters) counters["@present"] = 0 return true end if counters["@sleep"] > 0 then self:on_sleep(counters, counters["@ms"]) counters["@sleep"] = 0 counters["@ms"] = 0 return true end if counters["handling input"] > 0 and counters["@event mousepressed"] > 0 then local acc = huge acc = min(acc, counters["@event mousepressed"]) acc = min(acc, counters["handling input"]) counters["handling input"] = max(counters["handling input"] - acc, 0) counters["@event mousepressed"] = max(counters["@event mousepressed"] - acc, 0) counters["shoot bullet"] = counters["shoot bullet"] + acc * 1 return true end if counters["shoot bullet"] > 0 then local acc = counters["shoot bullet"] counters["shoot bullet"] = max(counters["shoot bullet"] - acc, 0) counters["@shoot bullet"] = counters["@shoot bullet"] + acc * 1 return true end if counters["drawing scene"] > 0 then local acc = counters["drawing scene"] counters["drawing scene"] = max(counters["drawing scene"] - acc, 0) counters["@print fps"] = counters["@print fps"] + acc * 1 counters["draw zombies"] = counters["draw zombies"] + acc * 1 counters["draw player"] = counters["draw player"] + acc * 1 counters["draw bullets"] = counters["draw bullets"] + acc * 1 return true end if counters["draw player"] > 0 then local acc = counters["draw player"] counters["draw player"] = max(counters["draw player"] - acc, 0) counters["@draw player"] = counters["@draw player"] + acc * 1 return true end if counters["draw bullets"] > 0 then local acc = counters["draw bullets"] counters["draw bullets"] = max(counters["draw bullets"] - acc, 0) counters["@draw bullets"] = counters["@draw bullets"] + acc * 1 return true end if counters["draw zombies"] > 0 then local acc = counters["draw zombies"] counters["draw zombies"] = max(counters["draw zombies"] - acc, 0) counters["@draw zombies"] = counters["@draw zombies"] + acc * 1 return true end if counters["updating scene"] > 0 then local acc = counters["updating scene"] counters["updating scene"] = max(counters["updating scene"] - acc, 0) counters["move bullets"] = counters["move bullets"] + acc * 1 counters["move player"] = counters["move player"] + acc * 1 counters["check for collisions"] = counters["check for collisions"] + acc * 1 counters["sweep deleted entities"] = counters["sweep deleted entities"] + acc * 1 counters["update spawn timer"] = counters["update spawn timer"] + acc * 1 counters["move zombies"] = counters["move zombies"] + acc * 1 return true end if counters["move player"] > 0 then local acc = counters["move player"] counters["move player"] = max(counters["move player"] - acc, 0) counters["@is [move right] down?"] = counters["@is [move right] down?"] + acc * 1 counters["@is [move up] down?"] = counters["@is [move up] down?"] + acc * 1 counters["@is [move left] down?"] = counters["@is [move left] down?"] + acc * 1 counters["moving player"] = counters["moving player"] + acc * 1 counters["@is [move down] down?"] = counters["@is [move down] down?"] + acc * 1 return true end if counters["moving player"] > 0 and counters["@[move up] is down"] > 0 then local acc = huge acc = min(acc, counters["moving player"]) acc = min(acc, counters["@[move up] is down"]) counters["moving player"] = max(counters["moving player"] - acc, 0) counters["@[move up] is down"] = max(counters["@[move up] is down"] - acc, 0) counters["moving player"] = counters["moving player"] + acc * 1 counters["@dir up"] = counters["@dir up"] + acc * 1 return true end if counters["moving player"] > 0 and counters["@[move left] is down"] > 0 then local acc = huge acc = min(acc, counters["moving player"]) acc = min(acc, counters["@[move left] is down"]) counters["moving player"] = max(counters["moving player"] - acc, 0) counters["@[move left] is down"] = max(counters["@[move left] is down"] - acc, 0) counters["@dir left"] = counters["@dir left"] + acc * 1 counters["moving player"] = counters["moving player"] + acc * 1 return true end if counters["moving player"] > 0 and counters["@[move down] is down"] > 0 then local acc = huge acc = min(acc, counters["moving player"]) acc = min(acc, counters["@[move down] is down"]) counters["moving player"] = max(counters["moving player"] - acc, 0) counters["@[move down] is down"] = max(counters["@[move down] is down"] - acc, 0) counters["moving player"] = counters["moving player"] + acc * 1 counters["@dir down"] = counters["@dir down"] + acc * 1 return true end if counters["moving player"] > 0 and counters["@[move right] is down"] > 0 then local acc = huge acc = min(acc, counters["moving player"]) acc = min(acc, counters["@[move right] is down"]) counters["moving player"] = max(counters["moving player"] - acc, 0) counters["@[move right] is down"] = max(counters["@[move right] is down"] - acc, 0) counters["moving player"] = counters["moving player"] + acc * 1 counters["@dir right"] = counters["@dir right"] + acc * 1 return true end if counters["@dir left"] > 0 and counters["@dir right"] > 0 then local acc = huge acc = min(acc, counters["@dir left"]) acc = min(acc, counters["@dir right"]) counters["@dir left"] = max(counters["@dir left"] - acc, 0) counters["@dir right"] = max(counters["@dir right"] - acc, 0) return true end if counters["@dir down"] > 0 and counters["@dir up"] > 0 then local acc = huge acc = min(acc, counters["@dir up"]) acc = min(acc, counters["@dir down"]) counters["@dir down"] = max(counters["@dir down"] - acc, 0) counters["@dir up"] = max(counters["@dir up"] - acc, 0) return true end if counters["moving player"] > 0 then local acc = counters["moving player"] counters["moving player"] = max(counters["moving player"] - acc, 0) counters["@move player"] = counters["@move player"] + acc * 1 return true end if counters["move bullets"] > 0 then local acc = counters["move bullets"] counters["move bullets"] = max(counters["move bullets"] - acc, 0) counters["@move bullets"] = counters["@move bullets"] + acc * 1 return true end if counters["move zombies"] > 0 then local acc = counters["move zombies"] counters["move zombies"] = max(counters["move zombies"] - acc, 0) counters["@move zombies"] = counters["@move zombies"] + acc * 1 return true end if counters["check for collisions"] > 0 then local acc = counters["check for collisions"] counters["check for collisions"] = max(counters["check for collisions"] - acc, 0) counters["check for player hit by zombie"] = counters["check for player hit by zombie"] + acc * 1 counters["check for bullet hitting zombie"] = counters["check for bullet hitting zombie"] + acc * 1 return true end if counters["check for player hit by zombie"] > 0 then local acc = counters["check for player hit by zombie"] counters["check for player hit by zombie"] = max(counters["check for player hit by zombie"] - acc, 0) counters["@do player collisions"] = counters["@do player collisions"] + acc * 1 return true end if counters["check for bullet hitting zombie"] > 0 then local acc = counters["check for bullet hitting zombie"] counters["check for bullet hitting zombie"] = max(counters["check for bullet hitting zombie"] - acc, 0) counters["@do bullet collisions"] = counters["@do bullet collisions"] + acc * 1 return true end if counters["update spawn timer"] > 0 then local acc = counters["update spawn timer"] counters["update spawn timer"] = max(counters["update spawn timer"] - acc, 0) counters["@update spawn timer"] = counters["@update spawn timer"] + acc * 1 return true end if counters["@spawn timer expired"] > 0 then local acc = counters["@spawn timer expired"] counters["@spawn timer expired"] = max(counters["@spawn timer expired"] - acc, 0) counters["make the timer faster"] = counters["make the timer faster"] + acc * 1 counters["spawn a zombie"] = counters["spawn a zombie"] + acc * 1 counters["reset timer"] = counters["reset timer"] + acc * 1 return true end if counters["spawn a zombie"] > 0 then local acc = counters["spawn a zombie"] counters["spawn a zombie"] = max(counters["spawn a zombie"] - acc, 0) counters["@spawn a zombie"] = counters["@spawn a zombie"] + acc * 1 return true end if counters["make the timer faster"] > 0 then local acc = counters["make the timer faster"] counters["make the timer faster"] = max(counters["make the timer faster"] - acc, 0) counters["@make the timer faster"] = counters["@make the timer faster"] + acc * 1 return true end if counters["reset timer"] > 0 then local acc = counters["reset timer"] counters["reset timer"] = max(counters["reset timer"] - acc, 0) counters["@reset timer"] = counters["@reset timer"] + acc * 1 return true end if counters["sweep deleted entities"] > 0 then local acc = counters["sweep deleted entities"] counters["sweep deleted entities"] = max(counters["sweep deleted entities"] - acc, 0) counters["@delete out of bounds bullets"] = counters["@delete out of bounds bullets"] + acc * 1 counters["@delete killed zombies"] = counters["@delete killed zombies"] + acc * 1 return true end if counters["handling input"] > 0 then local acc = counters["handling input"] counters["handling input"] = max(counters["handling input"] - acc, 0) return true end if counters["updating scene"] > 0 then local acc = counters["updating scene"] counters["updating scene"] = max(counters["updating scene"] - acc, 0) return true end if counters["drawing scene"] > 0 then local acc = counters["drawing scene"] counters["drawing scene"] = max(counters["drawing scene"] - acc, 0) return true end if counters["run main loop"] > 0 then local acc = counters["run main loop"] counters["run main loop"] = max(counters["run main loop"] - acc, 0) counters["poll input"] = counters["poll input"] + acc * 1 counters["run current frame"] = counters["run current frame"] + acc * 1 counters["start polling inputs"] = counters["start polling inputs"] + acc * 1 counters["handle input"] = counters["handle input"] + acc * 1 return true end if counters["start polling inputs"] > 0 then local acc = counters["start polling inputs"] counters["start polling inputs"] = max(counters["start polling inputs"] - acc, 0) counters["@start polling"] = counters["@start polling"] + acc * 1 return true end if counters["poll input"] > 0 then local acc = counters["poll input"] counters["poll input"] = max(counters["poll input"] - acc, 0) counters["@poll input"] = counters["@poll input"] + acc * 1 return true end if counters["handle input"] > 0 and counters["@no events left"] > 0 then local acc = huge acc = min(acc, counters["@no events left"]) acc = min(acc, counters["handle input"]) counters["handle input"] = max(counters["handle input"] - acc, 0) counters["@no events left"] = max(counters["@no events left"] - acc, 0) return true end if counters["handle input"] > 0 then local acc = counters["handle input"] counters["handle input"] = max(counters["handle input"] - acc, 0) counters["poll input"] = counters["poll input"] + acc * 1 counters["handling input"] = counters["handling input"] + acc * 1 counters["handle input"] = counters["handle input"] + acc * 1 return true end if counters["run current frame"] > 0 and counters["@event quit"] > 0 then local acc = huge acc = min(acc, counters["@event quit"]) acc = min(acc, counters["run current frame"]) counters["run current frame"] = max(counters["run current frame"] - acc, 0) counters["@event quit"] = max(counters["@event quit"] - acc, 0) counters["@quit love"] = counters["@quit love"] + acc * 1 return true end if counters["run current frame"] > 0 then local acc = counters["run current frame"] counters["run current frame"] = max(counters["run current frame"] - acc, 0) counters["present current frame"] = counters["present current frame"] + acc * 1 counters["sleep for 1ms"] = counters["sleep for 1ms"] + acc * 1 counters["next cycle"] = counters["next cycle"] + acc * 1 counters["step timer"] = counters["step timer"] + acc * 1 counters["clear the screen"] = counters["clear the screen"] + acc * 1 counters["update scene state"] = counters["update scene state"] + acc * 1 counters["draw scene"] = counters["draw scene"] + acc * 1 return true end if counters["step timer"] > 0 then local acc = counters["step timer"] counters["step timer"] = max(counters["step timer"] - acc, 0) counters["@step timer"] = counters["@step timer"] + acc * 1 return true end if counters["clear the screen"] > 0 then local acc = counters["clear the screen"] counters["clear the screen"] = max(counters["clear the screen"] - acc, 0) counters["@clear screen"] = counters["@clear screen"] + acc * 1 return true end if counters["update scene state"] > 0 then local acc = counters["update scene state"] counters["update scene state"] = max(counters["update scene state"] - acc, 0) counters["updating scene"] = counters["updating scene"] + acc * 1 return true end if counters["draw scene"] > 0 then local acc = counters["draw scene"] counters["draw scene"] = max(counters["draw scene"] - acc, 0) counters["drawing scene"] = counters["drawing scene"] + acc * 1 return true end if counters["present current frame"] > 0 then local acc = counters["present current frame"] counters["present current frame"] = max(counters["present current frame"] - acc, 0) counters["@present"] = counters["@present"] + acc * 1 return true end if counters["sleep for 1ms"] > 0 then local acc = counters["sleep for 1ms"] counters["sleep for 1ms"] = max(counters["sleep for 1ms"] - acc, 0) counters["@ms"] = counters["@ms"] + acc * 1 return true end if counters["next cycle"] > 0 then local acc = counters["next cycle"] counters["next cycle"] = max(counters["next cycle"] - acc, 0) counters["run main loop"] = counters["run main loop"] + acc * 1 return true end return false end function machine:run() local counters = self.counters while match(self, counters) do end end return machine