This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Aiden's profile picture

Running Multiple loops at the same time

Started by Aiden, 03 July 2013 - 08:32 AM
Aiden #1
Posted 03 July 2013 - 10:32 AM
So I've been trying to make a program similar to tamigotchi and its not working but I think I now why,
it runs off a bunch of loops that alter the pet's state after a different amount of time for each stat (at the moment they are all 60 but that will change and they will have different sleep times), what I think is happening is that the program is only running the first loop, so here's my code; advice?


Health = 50
Hunger = 5
Full = 1
Happy = 4
Weight = 3
Sick = 0
Tired = 0
Age = 1
Clean = 5
Weak = 0
Heat = 2
Dead = 0

function Stats()
print("Health ", Health)
print("Hunger ", Hunger)
print("Fullness ", Full)
print("Happiness ", Happy)
print("Weight ", Weight)
print("Sick ", Sick)
print("Tired ", Tired)
print("Age ", Age)
print("Clean ", Clean)
print("Weak ", Weak)
print("Heat ", Heat)
if Happy <= 2 then print(":(/>/>/>") end
if Happy == 3 then print(":I") end
if Happy >= 4 then print(":)/>/>/>") end
if Hunger >= 7 then print("Hungry") end
if Weight > 4 then print("Obsese") end
if Weight < 2 then print("Underweight") end
if Full == 5 then print("Full") end
if Sick == 1 then print("Sick") end
if Tired == 1 then print("Tired") end
if Clean <= 2 then print("Unclean") end
if Weak > 0 then print("Weak") end
if Heat == 1 then print("Cold") end
if Heat == 3 then print("Hot") end
print("-------------------")
end

while true do
sleep(60)
Hunger = Hunger + 1
if Hunger == 11 then Hunger = 10 end
end

while true do
sleep(60)
if (math.random(1, 15) + Weak - Clean) > 11 then
Sick = 1
end
end

while true do
sleep(60)
if math.random(1, 5) == 5 then
Clean = Clean - 1
if Clean == 0 then Clean = 1 end
end
end


while true do
sleep(60)
if math.random(1, 10) == 1 then Heat = 1 end
if math.random(1, 10) == 10 then Heat = 3 end
end




while true do
sleep(60)
if Hunger == 10 then Health = Health - 1 end
if Sick == 1 then Health = Health - 1 end
if Weight == 5 then Health = Health - 1 end
if Weight == 1 then Health = Health - 1 end
if Health <= 0 then Dead = 1 end
end

while true do
sleep(60)
if Dead == 1 then
print("Tami is Died...")
break
end
end

while true do
sleep(60)
Stats()
end
Lyqyd #2
Posted 03 July 2013 - 01:11 PM
Split into new topic.

Of course it's only running the first one. Code executes in order, so it reaches the first loop and never exits. You'll want to put each loop into a function and then call parallel.waitForAny and pass it all of your functions.
Aiden #3
Posted 03 July 2013 - 01:53 PM
Ok, so I tried the parallel thing, and yes, it is running all the loops at once (thanks for the suggestion btw), however the program ends when any function finishes, is there a way to make it only stop when the "Info function" succeeds? Here's the new code, help is very much appreciated.



1.
2.
Health = 50
3.
Hunger = 5
4.
Full = 1
5.
Happy = 4
6.
Weight = 3
7.
Sick = 0
8.
Tired = 0
9.
Age = 1
10.
Clean = 5
11.
Weak = 0
12.
Heat = 2
13.
Dead = 0
14.

15.
Stats = function()
16.
print("Health ", Health)
17.
print("Hunger ", Hunger)
18.
print("Fullness ", Full)
19.
print("Happiness ", Happy)
20.
print("Weight ", Weight)
21.
print("Sick ", Sick)
22.
print("Tired ", Tired)
23.
print("Age ", Age)
24.
print("Clean ", Clean)
25.
print("Weak ", Weak)
26.
print("Heat ", Heat)
27.
if Happy <= 2 then print(":(/>/>/>") end
28.
if Happy == 3 then print(":I") end
29.
if Happy >= 4 then print(":)/>/>/>") end
30.
if Hunger >= 7 then print("Hungry") end
31.
if Weight > 4 then print("Obsese") end
32.
if Weight < 2 then print("Underweight") end
33.
if Full == 5 then print("Full") end
34.
if Sick == 1 then print("Sick") end
35.
if Tired == 1 then print("Tired") end
36.
if Clean <= 2 then print("Unclean") end
37.
if Weak > 0 then print("Weak") end
38.
if Heat == 1 then print("Cold") end
39.
if Heat == 3 then print("Hot") end
40.
print("-------------------")
41.
end
42.

43.
HungerI = function()
44.
sleep(120)
45.
Hunger = Hunger + 1
46.
if Hunger == 11 then Hunger = 10 end
47.
end
48.

49.
SickI = function()
50.
sleep(240)
51.
if (math.random(1, 15) + Weak - Clean) > 11 then
52.
Sick = 1
53.
end
54.
end
55.
56.
CleanD = function()
57.
sleep(150)
58.
if math.random(1, 5) == 5 then
59.
Clean = Clean - 1
60.
if Clean == 0 then Clean = 1 end
61.
end
62.
end
63.
64.

65.
HeatID = function()
66.
sleep(120)
67.
if math.random(1, 10) == 1 then Heat = 1 end
68.
if math.random(1, 10) == 10 then Heat = 3 end
69.
end
70.

71.
72.

73.
74.
HealthD = function()
75.
sleep(300)
76.
if Hunger == 10 then Health = Health - 1 end
77.
if Sick == 1 then Health = Health - 1 end
78.
if Weight == 5 then Health = Health - 1 end
79.
if Weight == 1 then Health = Health - 1 end
80.
if Health <= 0 then Dead = 1 end
81.
end
82.

83.
Die = function()
84.
sleep(60)
85.
if Dead == 1 then
86.
print("Tami is Died...")
87.
end
88.
end
89.
90.
Info = function()
91.
sleep(900)
92.
Stats()
93.
end
94.

95.
AgeI = function()
96.
sleep(3600)
97.
Age = Age + 1
98.
end
99.
100.
parallel.waitForAny (HungerI, SickI, CleanD, HeatID, HealthD, Die, Info, AgeI)

Lyqyd #4
Posted 03 July 2013 - 02:53 PM
I never said to take the code out of the loops, just to put the loops into functions. Why did you get rid of the loops as well?
Yevano #5
Posted 03 July 2013 - 03:08 PM
I don't see why you'd need to use the parallel API for this. From what I can tell, you could just combine all the loops into one, keeping just one sleep(60) at the top of the loop.
Aiden #6
Posted 03 July 2013 - 03:46 PM
Update: Thank you!
the loops seems to be working perfectly now, so thank you, if anyone else is interested I plan to add in a shop and inventory to buy things to keep the pet alive. Here's the code with all the loops working as intended for anyone who is interested.

And once again; Thank you



1.

2.
Health = 50

3.
Hunger = 5

4.
Full = 1

5.
Happy = 4

6.
Weight = 3

7.
Sick = 0

8.
Tired = 0

9.
Age = 1

10.
Clean = 5

11.
Weak = 0

12.
Heat = 2

13.
Dead = 0

14.


15.
Stats = function()

16.
print("Health ", Health)

17.
print("Hunger ", Hunger)

18.
print("Fullness ", Full)

19.
print("Happiness ", Happy)

20.
print("Weight ", Weight)

21.
print("Sick ", Sick)

22.
print("Tired ", Tired)

23.
print("Age ", Age)

24.
print("Clean ", Clean)

25.
print("Weak ", Weak)

26.
print("Heat ", Heat)

27.
if Happy <= 2 then print(":(/>") end

28.
if Happy == 3 then print(":I") end

29.
if Happy >= 4 then print(":)/>") end

30.
if Hunger >= 7 then print("Hungry") end

31.
if Weight > 4 then print("Obsese") end

32.
if Weight < 2 then print("Underweight") end

33.
if Full == 5 then print("Full") end

34.
if Sick == 1 then print("Sick") end

35.
if Tired >= 8 then print("Tired") end

36.
if Clean <= 2 then print("Unclean") end

37.
if Weak > 0 then print("Weak") end

38.
if Heat == 1 then print("Cold") end

39.
if Heat == 3 then print("Hot") end

40.
print("-------------------")

41.
end

42.


43.
HappyID = function()

44.
while true do

45.
sleep(120)

46.
if Health > 35 then x = 3 end

47.
if 35 >= Health then if Health >= 15 then x = 2 end end

48.
if Health < 15 then x = 1 end

49.
Happy = x + math.random(0, 2)

50.
end

51.
end

52.


53.

54.
HungerI = function()

55.
while true do

56.
sleep(180)

57.
Hunger = Hunger + 1

58.
if Hunger == 11 then Hunger = 10 end

59.
end

60.
end

61.

62.
FullD = function()

63.
while true do

64.
sleep(90)

65.
Full = Full - (math.random(1, 2))

66.
end

67.
end

68.


69.
WeightD = function()

70.
while true do

71.
sleep(180)

72.
Weight = Weight - (math.random(0, 1))

73.
end

74.
end

75.

76.
TiredI = function()

77.
while true do

78.
sleep(180)

79.
Tired = (Tired + (math.random(1, 3)))

80.
if Tired > 10 then Tired = 10 end

81.
end

82.
end

83.

84.


85.
SickI = function()

86.
while true do

87.
sleep(240)

88.
if (math.random(1, 15) + Weak - Clean + (Tired * 0.1)) > 11 then

89.
Sick = 1

90.
end

91.
end

92.
end

93.

94.
CleanD = function()

95.
while true do

96.
sleep(150)

97.
if math.random(1, 5) == 5 then

98.
Clean = Clean - 1

99.
if Clean == 0 then

100.
Clean = 1

101.
end

102.
end

103.
end

104.
end

105.

106.
HeatID = function()

107.
while true do

108.
sleep(120)

109.
if math.random(1, 10) == 1 then Heat = 1 end

110.
if math.random(1, 10) == 10 then Heat = 3 end

111.
end

112.
end

113.

114.


115.

116.
HealthD = function()

117.
while true do

118.
sleep(300)

119.
if Hunger == 10 then Health = Health - 1 end

120.
if Sick == 1 then Health = Health - 1 end

121.
if Weight == 5 then Health = Health - 1 end

122.
if Weight == 1 then Health = Health - 1 end

123.
if Health <= 0 then Dead = 1 end

124.
end

125.
end

126.


127.

128.
Die = function()

129.
while true do

130.
sleep(60)

131.
if Dead == 1 then

132.
print("Tami is Died...")

133.
end

134.
end

135.
end

136.


137.
Info = function()

138.
while true do

139.
sleep(10)

140.
Stats()

141.
print("Do what?")

142.
Choice = read()

143.
end

144.
end

145.

146.
AgeI = function()

147.
while true do

148.
sleep(3600)

149.
Age = Age + 1

150.
end

151.
end

152.


153.

154.
parallel.waitForAny (HappyID, FullD, WeightD, TiredI, HungerI, SickI, CleanD, HeatID, HealthD, Die, Info, AgeI)


Aiden #7
Posted 03 July 2013 - 07:14 PM
I don't see why you'd need to use the parallel API for this. From what I can tell, you could just combine all the loops into one, keeping just one sleep(60) at the top of the loop.

This is because in the actual program the times for each attribute will be different, so 60 wouldn't work as some are 240 and some are 3600
Lyqyd #8
Posted 03 July 2013 - 08:31 PM
Parallel still isn't really necessary, of course. You'd just use one event-handling loop that listened for different timers coming in, and each chunk of code would set its timer again after it ran.
TeamDman #9
Posted 04 July 2013 - 02:00 PM
If coroutines work in computercraft Lua then this should work.

Health = 50
Hunger = 5
Full = 1
Happy = 4
Weight = 3
Sick = 0
Tired = 0
Age = 1
Clean = 5
Weak = 0
Heat = 2
Dead = 0
function Stats()
print("Health ", Health)
print("Hunger ", Hunger)
print("Fullness ", Full)
print("Happiness ", Happy)
print("Weight ", Weight)
print("Sick ", Sick)
print("Tired ", Tired)
print("Age ", Age)
print("Clean ", Clean)
print("Weak ", Weak)
print("Heat ", Heat)
if Happy <= 2 then print(":(/>/>/>/>") end
if Happy == 3 then print(":I") end
if Happy >= 4 then print(":)/>/>/>/>") end
if Hunger >= 7 then print("Hungry") end
if Weight > 4 then print("Obsese") end
if Weight < 2 then print("Underweight") end
if Full == 5 then print("Full") end
if Sick == 1 then print("Sick") end
if Tired == 1 then print("Tired") end
if Clean <= 2 then print("Unclean") end
if Weak > 0 then print("Weak") end
if Heat == 1 then print("Cold") end
if Heat == 3 then print("Hot") end
print("-------------------")
end
coroutine.wrap(function()
while true do
  sleep(60)
  Hunger = Hunger + 1
  if Hunger == 11 then Hunger = 10 end
end
end)()
coroutine.wrap(function()
while true do
  sleep(60)
  if (math.random(1, 15) + Weak - Clean) > 11 then
   Sick = 1
  end
end
end)()
coroutine.wrap(function()
while true do
  sleep(60)
  if math.random(1, 5) == 5 then
   Clean = Clean - 1
   if Clean == 0 then Clean = 1 end
  end
end
end)()
coroutine.wrap(function()
while true do
  sleep(60)
  if math.random(1, 10) == 1 then Heat = 1 end
  if math.random(1, 10) == 10 then Heat = 3 end
end
end)()
coroutine.wrap(function()
while true do
  sleep(60)
  if Hunger == 10 then Health = Health - 1 end
  if Sick == 1 then Health = Health - 1 end
  if Weight == 5 then Health = Health - 1 end
  if Weight == 1 then Health = Health - 1 end
  if Health <= 0 then Dead = 1 end
end
end)()
coroutine.wrap(function()
while true do
  sleep(60)
  if Dead == 1 then
   print("Tami is Died...")
   break
  end
end
end)()
while true do
sleep(60)
Stats()
end
-- This part isn't coroutined because if it was the computer would think the program has stopped running and return to the main screen.
Lyqyd #10
Posted 04 July 2013 - 04:07 PM
Parallel uses coroutines, so they do work. All your code does, though, is wrap the functions as coroutines, it never actually resumes any of them, so that code would just exit after the declarations.
TeamDman #11
Posted 05 July 2013 - 09:11 AM
coroutine.wrap(function()
while true do
sleep(1)
print'asd'
end
end)()
It returns a function then it calls that function.
LBPHacker #12
Posted 05 July 2013 - 09:16 AM
-snip-
Resumes them once, okay. But they stop working at the first yield.
TeamDman #13
Posted 05 July 2013 - 03:53 PM
That's really all I need for a neverending loop.
LBPHacker #14
Posted 05 July 2013 - 04:11 PM
That's really all I need for a neverending loop.
Ahh you don't understand. It resumes them once, but if they never yeild, only the first will be resumed. If they do though, they will really be resumed only once. Coroutines are not threads.
danny_delmax1 #15
Posted 05 July 2013 - 05:18 PM
Parallel still isn't really necessary, of course. You'd just use one event-handling loop that listened for different timers coming in, and each chunk of code would set its timer again after it ran.


Here's an example of how you would do this:

Its not what Lyqyd meant, but this is a concept that could work
Just an FYI, this won't work as is- it would stop at the info() function, because of the read() function. You will have to make a custom read() to make it work, one that can handle the timers and input at the same time.


local tTimers = {}
function smartTimer(sTime, sRep)
  sID = os.startTimer(sTime)
  table.insert(tTimers, sID, sRep)
end
function smartPullEvent()
  local toRet = nil
  local ID
  event, ID = os.pullEvent("timer")
  toRet = tTimers[ID]
  return event, toRet
end
Health = 50
Hunger = 5
Full = 1
Happy = 4
Weight = 3
Sick = 0
Tired = 0
Age = 1
Clean = 5
Weak = 0
Heat = 2
Dead = 0
function Stats()
print("Health ", Health)
print("Hunger ", Hunger)
print("Fullness ", Full)
print("Happiness ", Happy)
print("Weight ", Weight)
print("Sick ", Sick)
print("Tired ", Tired)
print("Age ", Age)
print("Clean ", Clean)
print("Weak ", Weak)
print("Heat ", Heat)
if Happy <= 2 then print(":(/>/>/>/>") end
if Happy == 3 then print(":I") end
if Happy >= 4 then print(":)/>/>/>/>") end
if Hunger >= 7 then print("Hungry") end
if Weight > 4 then print("Obsese") end
if Weight < 2 then print("Underweight") end
if Full == 5 then print("Full") end
if Sick == 1 then print("Sick") end
if Tired >= 8 then print("Tired") end
if Clean <= 2 then print("Unclean") end
if Weak > 0 then print("Weak") end
if Heat == 1 then print("Cold") end
if Heat == 3 then print("Hot") end
print("-------------------")
end
function HappyID()
function smartTimer(120, HappyID)
if Health > 35 then x = 3 end
if 35 >= Health then if Health >= 15 then x = 2 end end
if Health < 15 then x = 1 end
Happy = x + math.random(0, 2)
end
function HungerI()
function smartTimer(180, HungerI)
Hunger = Hunger + 1
if Hunger == 11 then Hunger = 10 end
end
function FullD()
function smartTimer(90, FullD)
Full = Full - (math.random(1, 2))
end
function WeightD()
function smartTimer(180, WeightD)
Weight = Weight - (math.random(0, 1))
end
function TiredI()
function smartTimer(180, TiredI)
Tired = (Tired + (math.random(1, 3)))
if Tired > 10 then Tired = 10 end
end
function SickI()
function smartTimer(250, SickI)
if (math.random(1, 15) + Weak - Clean + (Tired * 0.1)) > 11 then
Sick = 1
end
end
function CleanD()
function smartTimer(150, CleanD)
if math.random(1, 5) == 5 then
Clean = Clean - 1
if Clean == 0 then
Clean = 1
end
end
end
function HeatID()
function smartTimer(120, HeatID)
if math.random(1, 10) == 1 then Heat = 1 end
if math.random(1, 10) == 10 then Heat = 3 end
end
function HealthD()
function smartTimer(300, HealthD)
if Hunger == 10 then Health = Health - 1 end
if Sick == 1 then Health = Health - 1 end
if Weight == 5 then Health = Health - 1 end
if Weight == 1 then Health = Health - 1 end
if Health <= 0 then Dead = 1 end
end
function Die()
function smartTimer(60, Die)
if Dead == 1 then
print("Tami is Dead...")
end
end
function Info()
function smartTimer(10, sRep)
Stats()
print("Do what?")
Choice = read() --# IMPORTANT! you need a custom read function to handle timers AND inputs
end
function AgeI()
function smartTimer(3600, AgeI)
Age = Age + 1
end
HappyID()
HungerI()
FullD()
WeightD()
WeightD()
TiredI()
SickI()
CleanD()
HeatID()
HealthD()
Die()
Info()
AgeI()  
while true do
tempFunc = smartPullEvent()
tempFunc()
end
Edited on 05 July 2013 - 06:28 PM
Lyqyd #16
Posted 05 July 2013 - 08:19 PM
Uh, no, that's not at all what I meant. Something more like:


local doOneThing = os.startTimer(10)
local doSomethingElse = os.startTimer(7)
while true do
  event = {os.pullEvent()}
  if event[1] == "timer" and event[2] == doOneThing then
    --do one thing
    doOneThing = os.startTimer(10)
  elseif event[1] == "timer" and event[2] == doSomethingElse then
    --do something else
    doSomethingElse = os.startTimer(7)
  end
end