Fishy error

This is a simplified code of my fishing game, interestingly it starts working normally but I know things are fishy so I adjust it a bit

  1. I added two fish timers instead of 1 fish timer per room in the original game
  2. I increased the randomchance to catching a fish from 1% to 11%
  3. I reduced the fish timer interval from 3 seconds to 1 second
  4. The other chunks of unrelated huge game codes are removed

As you might have expected, I dun say things for nothing, these 4 situations might be the cause of the fishy error or that these 4 situations might lead to a further understanding of the issue at its core

Unfortunately this simplified code still works better than the original fat game code, so you might need to catch a few more fishes before the errors starts appearing

Even though I am waiting for mrangel's reply for this profound error, I am happy to read everyone's comment


Fishy error

Error running script: Error evaluating expression 'GetAllChildObjects(room)': Collection was modified; enumeration operation may not execute. You caught a time cod $0 have been added. Error running script: Collection was modified; enumeration operation may not execute. Error running script: Error evaluating expression 'GetAllChildObjects(newParent)': Collection was modified; enumeration operation may not execute. Error running script: Error evaluating expression 'ListCombine(ScopeReachableNotHeldForRoom(room), ScopeVisibleNotReachableForRoom(room))': Value cannot be null.Parameter name: collection Error running script: Cannot foreach over '' as it is not a list Error running script: Error evaluating expression 'ListExclude(ScopeVisibleNotHeldNotScenery(), game.pov)': Object reference not set to an instance of an object.

Simplified fishing game code


<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="test">
    <gameid>d1d77751-bc11-4993-9b37-cc7a5061a6f0</gameid>
    <version>1.0</version>
    <firstpublished>2024</firstpublished>
    <showmoney />
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="fish">
      <inherit name="editor_object" />
      <catch type="script">
        msg ("You caught a "+this.alias)
        msg ("$"+this.price+ " have been added.")
        add = ToInt(this.price)
        player.money = player.money + add
        this.parent = null
      </catch>
      <displayverbs type="stringlist" />
    </object>
  </object>
  <verb>
    <property>catch</property>
    <pattern>catch</pattern>
    <defaultexpression>"You can't catch " + object.article + "."</defaultexpression>
  </verb>
  <timer name="fish timer">
    <interval>1</interval>
    <script>
      for (repeat, 1, 40, 1) {
        rng = GetRandomInt(1,40)
        if (rng=1) {
          game.fishname = "monkfish"
          game.fishprice = "1"
        }
        if (rng=2) {
          game.fishname = "rainbow trout"
          game.fishprice = "2"
        }
        if (rng=3) {
          game.fishname = "electric eel"
          game.fishprice = "2"
        }
        if (rng=4) {
          game.fishname = "lionfish"
          game.fishprice = "5"
        }
        if (rng=5) {
          game.fishname = "flying fish"
          game.fishprice = "6"
        }
        if (rng=6) {
          game.fishname = "swordfish"
          game.fishprice = "20"
        }
        if (rng=7) {
          game.fishname = "mirror carp"
          game.fishprice = "50"
        }
        if (rng=8) {
          game.fishname = "slippery snook"
          game.fishprice = "0"
        }
        if (rng=9) {
          game.fishname = "jellyfish"
          game.fishprice = "2"
        }
        if (rng=10) {
          game.fishname = "gigagoldfish"
          game.fishprice = "40"
        }
        if (rng=11) {
          game.fishname = "mystery mackerel"
          game.fishprice = "1"
        }
        if (rng=12) {
          game.fishname = "time trout"
          game.fishprice = "2"
        }
        if (rng=13) {
          game.fishname = "flaming fin"
          game.fishprice = "4"
        }
        if (rng=14) {
          game.fishname = "piranha"
          game.fishprice = "5"
        }
        if (rng=15) {
          game.fishname = "bananafish"
          game.fishprice = "10"
        }
        if (rng=16) {
          game.fishname = "axolotl"
          game.fishprice = "22"
        }
        if (rng=17) {
          game.fishname = "betta fish"
          game.fishprice = "0"
        }
        if (rng=18) {
          game.fishname = "discus fish"
          game.fishprice = "8"
        }
        if (rng=19) {
          game.fishname = "sea dragon"
          game.fishprice = "30"
        }
        if (rng=20) {
          game.fishname = "moon jellyfish"
          game.fishprice = "40"
        }
        if (rng=21) {
          game.fishname = "koi"
          game.fishprice = "2"
        }
        if (rng=22) {
          game.fishname = "thunder crayfish"
          game.fishprice = "3"
        }
        if (rng=23) {
          game.fishname = "mandarin fish"
          game.fishprice = "1"
        }
        if (rng=24) {
          game.fishname = "dwarf pufferfish"
          game.fishprice = "1"
        }
        if (rng=25) {
          game.fishname = "peacock mantis shrimp"
          game.fishprice = "19"
        }
        if (rng=26) {
          game.fishname = "fire shrimp"
          game.fishprice = "1"
        }
        if (rng=27) {
          game.fishname = "fancy snail"
          game.fishprice = "0"
        }
        if (rng=28) {
          game.fishname = "african dwarf frog"
          game.fishprice = "2"
        }
        if (rng=29) {
          game.fishname = "angelfish"
          game.fishprice = "4"
        }
        if (rng=30) {
          game.fishname = "lobster"
          game.fishprice = "6"
        }
        if (rng=31) {
          game.fishname = "datastream darter"
          game.fishprice = "20"
        }
        if (rng=32) {
          game.fishname = "neon ripplefish"
          game.fishprice = "11"
        }
        if (rng=33) {
          game.fishname = "chromeback salmon"
          game.fishprice = "15"
        }
        if (rng=34) {
          game.fishname = "solar sailfish"
          game.fishprice = "16"
        }
        if (rng=35) {
          game.fishname = "hypercurrent eel"
          game.fishprice = "25"
        }
        if (rng=36) {
          game.fishname = "plasma pike"
          game.fishprice = "50"
        }
        if (rng=37) {
          game.fishname = "bio-luminescent leviathan"
          game.fishprice = "100"
        }
        if (rng=38) {
          game.fishname = "magnetic manta"
          game.fishprice = "40"
        }
        if (rng=39) {
          game.fishname = "hydrodynamic hologram"
          game.fishprice = "2"
        }
        if (rng=40) {
          game.fishname = "quantum quagga"
          game.fishprice = "60"
        }
        if (RandomChance(11)) {
          fish.alias = ""+game.fishname
          fish.price = ""+game.fishprice
          CloneObjectAndMoveHere (fish)
        }
        else {
          foreach (object, GetDirectChildren (game.pov.parent)) {
            if (object.alias = ""+game.fishname) {
              object.parent = null
            }
          }
        }
      }
    </script>
    <enabled />
  </timer>
  <timer name="fish timer2">
    <interval>1</interval>
    <script>
      for (repeat, 1, 40, 1) {
        rng = GetRandomInt(1,40)
        if (rng=1) {
          game.fishname = "largemouth bass"
          game.fishprice = "3"
        }
        if (rng=2) {
          game.fishname = "trout"
          game.fishprice = "0"
        }
        if (rng=3) {
          game.fishname = "bluegill"
          game.fishprice = "1"
        }
        if (rng=4) {
          game.fishname = "catfish"
          game.fishprice = "1"
        }
        if (rng=5) {
          game.fishname = "salmon"
          game.fishprice = "8"
        }
        if (rng=6) {
          game.fishname = "northern pike"
          game.fishprice = "11"
        }
        if (rng=7) {
          game.fishname = "perch"
          game.fishprice = "2"
        }
        if (rng=8) {
          game.fishname = "striped bass"
          game.fishprice = "3"
        }
        if (rng=9) {
          game.fishname = "crabfish"
          game.fishprice = "4"
        }
        if (rng=10) {
          game.fishname = "mini squid"
          game.fishprice = "6"
        }
        if (rng=11) {
          game.fishname = "mystery tuna"
          game.fishprice = "0"
        }
        if (rng=12) {
          game.fishname = "time cod"
          game.fishprice = "0"
        }
        if (rng=13) {
          game.fishname = "freezing fin"
          game.fishprice = "1"
        }
        if (rng=14) {
          game.fishname = "firetail tetra"
          game.fishprice = "2"
        }
        if (rng=15) {
          game.fishname = "golden perch"
          game.fishprice = "10"
        }
        if (rng=16) {
          game.fishname = "emerald goby"
          game.fishprice = "22"
        }
        if (rng=17) {
          game.fishname = "rainbow darter"
          game.fishprice = "7"
        }
        if (rng=18) {
          game.fishname = "sapphire cichlid"
          game.fishprice = "18"
        }
        if (rng=19) {
          game.fishname = "platinum piranha"
          game.fishprice = "15"
        }
        if (rng=20) {
          game.fishname = "diamond guppy"
          game.fishprice = "20"
        }
        if (rng=21) {
          game.fishname = "orange koi"
          game.fishprice = "10"
        }
        if (rng=22) {
          game.fishname = "ruby redfish"
          game.fishprice = "4"
        }
        if (rng=23) {
          game.fishname = "england fish"
          game.fishprice = "0"
        }
        if (rng=24) {
          game.fishname = "spiky pufferfish"
          game.fishprice = "0"
        }
        if (rng=25) {
          game.fishname = "raining tree shrimp"
          game.fishprice = "0"
        }
        if (rng=26) {
          game.fishname = "yellow shrimp"
          game.fishprice = "0"
        }
        if (rng=27) {
          game.fishname = "nerite snail"
          game.fishprice = "0"
        }
        if (rng=28) {
          game.fishname = "blue dart frog"
          game.fishprice = "1"
        }
        if (rng=29) {
          game.fishname = "angelic fin"
          game.fishprice = "14"
        }
        if (rng=30) {
          game.fishname = "giant lobster"
          game.fishprice = "6"
        }
        if (rng=31) {
          game.fishname = "streaming nova"
          game.fishprice = "12"
        }
        if (rng=32) {
          game.fishname = "tetra ripplefish"
          game.fishprice = "14"
        }
        if (rng=33) {
          game.fishname = "dragon eye"
          game.fishprice = "16"
        }
        if (rng=34) {
          game.fishname = "sailing fin"
          game.fishprice = "19"
        }
        if (rng=35) {
          game.fishname = "thunderous snake"
          game.fishprice = "2"
        }
        if (rng=36) {
          game.fishname = "crazy fish"
          game.fishprice = "0"
        }
        if (rng=37) {
          game.fishname = "bio-luminescent pike"
          game.fishprice = "50"
        }
        if (rng=38) {
          game.fishname = "tortoise manta"
          game.fishprice = "10"
        }
        if (rng=39) {
          game.fishname = "weather eel"
          game.fishprice = "20"
        }
        if (rng=40) {
          game.fishname = "sister lullaby"
          game.fishprice = "20"
        }
        if (RandomChance(11)) {
          fish.alias = ""+game.fishname
          fish.price = ""+game.fishprice
          CloneObjectAndMoveHere (fish)
        }
        else {
          foreach (object, GetDirectChildren (game.pov.parent)) {
            if (object.alias = ""+game.fishname) {
              object.parent = null
            }
          }
        }
      }
    </script>
    <enabled />
  </timer>
</asl>

The only thing I can think of is that your timer is removing an object from the room while the objects list is refreshing; but that seems kind of weird. Scripts shouldn't be running simultaneously. But if those two entry points can conflict, that could indicate a general problem with creating objects in a timer script.

Can you try not having two separate timers with the same interval? If the game is trying to run them both at the same time, then one of them might finish and set the object list in the sidebar updating while the other is still running. In that case, you might be able to make the issue go away by putting both scripts into a single timer, one after the other.


I turned off one of the fish timer, which you can do it by unticking start timer when the game begins,
But I am still getting error even with one fish timer, albeit the error occurrences are rarer

I finally understood the 4 situations that I pointed out, unfortunately it is just a smoke bomb and does not point out the real issue, because if a generator is creating errors, doubling the appearance of generator will simply double the errors as well

I guess the issue is a combination of lag and the bottom-most code where the generator is trying to trim off objects which creates the effect of fishes have ranaway

I chopped off rng3 fish to rng40 fish, leaving me with 2 fishes to appear, and this drastically decreases the frequency of errors happening

So, now I am guessing I overdid with the for loop of 40 times per second, which searches for 40 fishes per second and deletes X number of fishes per second

But, because the theme of fishing is to have a variety of fishes to catch or discover, I am still interested in having this issue resolved


that could indicate a general problem with creating objects in a timer script.

This seems to help me rephrase my thoughts, perhaps there is a general problem with deleting objects in a timer script, even though there might be other non-timer ways to delete objects like deleting all fishes at the same time, it wouldn't look natural to create the effect of fishes running away in a randomized way


EDIT: Fixed a silly mistake in the code below
EDIT2: Some more errors
EDIT3: More sophisticated logic
EDIT4: Still finding typos!

I'm still trying to figure out how this can happen, because Quest is normally very good at not letting multiple scripts run at the same time. Maybe it would be smoother if, instead of creating and destroying so many fish, you instead make a list of fish to create/destroy, and then process it at the end.

That way, at least, the fish which are created and then destroyed in the same run of the script will never actually be created, leaving less objects sitting around outside player space for the engine to deal with.

Using your algorithm (so the numbers created and the time they stay around for will be the same), you could do something like:

  <timer name="fish timer">
    <interval>1</interval>
    <script><![CDATA[
      // First, make a list to keep track of the "deleted" fish so we can reuse them:
      if (not HasAttribute(this, "sparefish")) {
        this.sparefish = NewObjectList()
      }
      // Then we make a record of how many fish currently exist:
      game.pov.parent.fishcounts = NewDictionary()
      foreach (obj, FilterByAttribute (GetDirectChildren(game.pov.parent), "visible", true)) {
        if (obj.prototype = fish) {
          if (DictionaryContains (game.pov.parent.fishcounts, obj.alias)) {
            count = DictionaryItem (game.pov.parent.fishcounts, obj.alias)
            dictionary remove (game.pov.parent.fishcounts, obj.alias)
            dictionary add (game.pov.parent.fishcounts, obj.alias, count + 1)
          }
          else {
            dictionary add (game.pov.parent.fishcounts, obj.alias, 1)
          }
        }
      }
      // Make a copy of the dictionary of how many fish we have.
      // I think that applying it to a different object gives us a quick way to make a deep copy of the dictionary
      this.wantedfish = game.pov.parent.fishcounts

      for (repeat, 1, 40, 1) {
        rng = PickOneString(Split("monkfish;rainbow trout;electric eel;lionfish;flying fish;swordfish;mirror carp;slippery snook;jellyfish;gigagoldfish;mystery mackerel;time trout;flaming fin;piranha;bananafish;axolotl;betta fish;discus fish;sea dragon;moon jellyfish;koi;thunder crayfish;mandarin fish;dwarf pufferfish;peacock mantis shrimp;fire shrimp;fancy snail;african dwarf frog;angelfish;lobster;datastream darter;neon ripplefish;chromeback salmon;solar sailfish;hypercurrent eel;plasma pike;bio-luminescent leviathan;magnetic manta;hydrodynamic hologram;quantum quagga"))
        if (RandomChance(11)) {
          if (DictionaryContains (this.wantedfish, rng)) {
            count = DictionaryItem (this.wantedfish, rng)
            dictionary remove (this.wantedfish, rng)
            dictionary add (this.wantedfish, rng, count + 1)
          }
          else {
            dictionary add (this.wantedfish, rng, 1)
          }
        }
        else if (DictionaryContains (this.wantedfish, rng)) {
          // delete the fish if there are any
          dictionary remove (this.wantedfish, rng)
          dictionary add (this.wantedfish, rng, 0)
        }
      }
      // Do the same again for the second list:
      for (repeat, 1, 40, 1) {
        rng = PickOneString(Split("largemouth bass;trout;bluegill;catfish;salmon;northern pike;perch;striped bass;crabfish;mini squid;mystery tuna;time cod;freezing fin;firetail tetra;golden perch;emerald goby;rainbow darter;sapphire cichlid;platinum piranha;diamond guppy;orange koi;ruby redfish;england fish;spiky pufferfish;raining tree shrimp;yellow shrimp;nerite snail;blue dart frog;angelic fin;giant lobster;streaming nova;tetra ripplefish;dragon eye;sailing fin;thunderous snake;crazy fish;bio-luminescent pike;tortoise manta;weather eel;sister lullaby"))
        if (RandomChance(11)) {
          if (DictionaryContains (this.wantedfish, rng)) {
            count = DictionaryItem (this.wantedfish, rng)
            dictionary remove (this.wantedfish, rng)
            dictionary add (this.wantedfish, rng, count + 1)
          }
          else {
            dictionary add (this.wantedfish, rng, 1)
          }
        }
        else if (DictionaryContains (this.wantedfish, rng)) {
          // delete the fish if there are any
          dictionary remove (this.wantedfish, rng)
          dictionary add (this.wantedfish, rng, 0)
        }
      }
      // at this point, game.pov.parent.fishcounts is a dictionary of what fish exist
      // and this.wantedfish is a dictionary of how many fish should exist for the next second

      // so now, we compare the two lists, and create or remove fish as necessary
      foreach (fishtype, this.wantedfish) {
        wantednumber = DictionaryItem(this.wantedfish, fishtype)
        if (DictionaryContains (game.pov.parent.fishcounts, fishtype)) {
          currentnumber = DictionaryItem(game.pov.parent.fishcounts, fishtype)
        }
        else {
          currentnumber = 1
        }

        // If there's too many, remove some
        if(currentnumber > wantednumber) {
          fishlist = FilterByAttribute (GetDirectChildren(game.pov.parent), "alias", fishtype)
          for (i, 1, wantednumber - currentnumber) {
            gonefish = ListItem(fishlist, 0)
            list remove (fishlist, gonefish)
            // Note that I'm adding it to the list of "spare fish" as well as removing it
            // So we can bring it back later instead of cloning a new one
            list add (this.sparefish, gonefish)
            gonefish.visible = false
          }
        }
        else if (wantednumber > currentnumber) {
          // We need to create new fish, so let's work out how much it's worth
          switch (fishtype) {
            case ("monkfish", "mystery mackerel", "mandarin fish", "dwarf pufferfish", "fire shrimp", "bluegill", "catfish", "freezing fin", "blue dart frog") {
              price = "1"
            }
            case ("rainbow trout", "electric eel", "jellyfish", "time trout", "koi", "african dwarf frog", "hydrodynamic hologram", "perch", "firetail tetra", "thunderous snake") {
              price = "2"
            }
            case ("thunder crayfish", "largemouth bass", "striped bass") {
              price = "3"
            }
            case ("flaming fin", "angelfish", "crabfish", "ruby redfish") {
              price = "4"
            }
            case ("lionfish", "piranha") {
              price = "5"
            }
            case ("flying fish", "lobster", "mini squid", "giant lobster") {
              price = "6"
            }
            case ("rainbow darter") {
              price = "7"
            }
            case ("discus fish", "salmon") {
              price = "8"
            }
            case ("bananafish", "golden perch", "orange koi", "tortoise manta") {
              price = "10"
            }
            case ("neon ripplefish", "northern pike") {
              price = "11"
            }
            case ("streaming nova") {
              price = "12"
            }
            case ("angelic fin", "tetra ripplefish") {
              price = "14"
            }
            case ("chromeback salmon", "platinum piranha") {
              price = "15"
            }
            case ("solar sailfish", "dragon eye") {
              price = "16"
            }
            case ("sapphire cichlid") {
              price = "18"
            }
            case ("peacock mantis shrimp", "sailing fin") {
              price = "19"
            }
            case ("swordfish", "datastream darter", "diamond guppy", "weather eel", "sister lullaby") {
              price = "20"
            }
            case ("axolotl", "emerald goby") {
              price = "22"
            }
            case ("hypercurrent eel") {
              price = "25"
            }
            case ("sea dragon") {
              price = "30"
            }
            case ("gigagoldfish", "moon jellyfish", "magnetic manta") {
              price = "40"
            }
            case ("mirror carp", "plasma pike", "bio-luminescent pike") {
              price = "50"
            }
            case ("quantum quagga") {
              price = "60"
            }
            case ("bio-luminescent leviathan") {
              price = "100"
            }
            default {
              price = "0"
            }
          }
          // Now, let's create those fish…
          for (i, 1, wantednumber - currentnumber) {
            // If we've got a spare fish, use it
            if (ListCount (this.sparefish) > 0) {
              newfish = ListItem(this.sparefish, 0)
              list remove (this.sparefish, newfish)
            }
            else {
              newfish = CloneObjectAndMoveHere(fish)
            }
            newfish.alias = fishtype
            newfish.price = price
            newfish.visible = true
          }
        }
      }
    ]]></script>
    <enabled />
  </timer>

Not sure if that will work any better; but it should be a little quicker to run.


It sounds like you are working on the invincible error from my own game. I recognize it as one I haven't been able to find the cause of, or fix. I will be glad of it if you find a solution (I think, but, then, your work looks more complicating than mine was), so I am already excited that you are looking into it. I hope both of our similar or related issues can be resolved (or yours at least, but even better, mine as well).


There is an error on mrangel quick fish timer, but your theory is probably correct as you always are, unfortunately it will take months for me to understand a bit of it, irregardless, I have already learnt a few tricks from it, so your effort is not wasted

  1. "this" can be referred to timers and functions, this is very helpful as this might mean I can make a generator that generates generators
  2. Attributes can be set to timers and functions, I would have never known this if I never saw your code, this is helpful, as I stack many attributes into game object, creating a very disorganized work template
  3. "if(not )", this is super useful, I have no idea why I dun know this, it would be sad if this is not written in the quest documentation guide, or perhaps it is written and I am just blind

I have spend loads of time to fix the fishy error, but they all do not work including

  1. Disabling fish timer when catching fishes then enabling again
  2. Turning the fishes invisible rather than deleting them, after being turned invisible 10 times, they are deleted

But I feel like I am getting closer to the truth or perhaps I am already at it, I just do not know how to code it
The error stems from foreach being looped 40 times per second,
When foreach is triggered and executed, the room objects cannot be changed or moved around, thus
my code will possibly foreach and delete 100%-11% = 89%x 40=35.6 times per second, chances are the room objects are going to be changed, deleted or moved, no matter how you change the code

So, unfortunately it seems like we are being limited to deleting once per second or per fish timer interval, from my coding skills, I can't do it
But judging from your dictionary and objectlist, it is probably possible to delete all the targeted fishes at the same time/second
The most important to remember is that the delete function must be put outside the for loop of 40 times per second, so that the delete function/foreach loop only executes once


And nope, it did not worked, I tried my theory and separated the delete function into its own timer but it still shows the same error
I am back to square one

Separated delete fish timer

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="test">
    <gameid>d1d77751-bc11-4993-9b37-cc7a5061a6f0</gameid>
    <version>1.0</version>
    <firstpublished>2024</firstpublished>
    <showmoney />
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
  <verb>
    <property>catch</property>
    <pattern>catch</pattern>
    <defaultexpression>"You can't catch " + object.article + "."</defaultexpression>
  </verb>
  <object name="roomhidden">
    <inherit name="editor_room" />
    <object name="fish">
      <inherit name="editor_object" />
      <displayverbs type="stringlist" />
      <catch type="script">
        msg ("You caught a "+this.alias)
        msg ("$"+this.price+ " have been added.")
        add = ToInt(this.price)
        player.money = player.money + add
        this.runaway = true
        this.visible = false
      </catch>
      <deleteseconds type="int">0</deleteseconds>
    </object>
  </object>
  <timer name="fish timer">
    <interval>1</interval>
    <enabled />
    <script><![CDATA[
      for (repeat, 1, 40, 1) {
        rng = GetRandomInt(1,40)
        if (rng=1) {
          game.fishname = "monkfish"
          game.fishprice = "1"
        }
        if (rng=2) {
          game.fishname = "rainbow trout"
          game.fishprice = "2"
        }
        if (rng=3) {
          game.fishname = "electric eel"
          game.fishprice = "2"
        }
        if (rng=4) {
          game.fishname = "lionfish"
          game.fishprice = "5"
        }
        if (rng=5) {
          game.fishname = "flying fish"
          game.fishprice = "6"
        }
        if (rng=6) {
          game.fishname = "swordfish"
          game.fishprice = "20"
        }
        if (rng=7) {
          game.fishname = "mirror carp"
          game.fishprice = "50"
        }
        if (rng=8) {
          game.fishname = "slippery snook"
          game.fishprice = "0"
        }
        if (rng=9) {
          game.fishname = "jellyfish"
          game.fishprice = "2"
        }
        if (rng=10) {
          game.fishname = "gigagoldfish"
          game.fishprice = "40"
        }
        if (rng=11) {
          game.fishname = "mystery mackerel"
          game.fishprice = "1"
        }
        if (rng=12) {
          game.fishname = "time trout"
          game.fishprice = "2"
        }
        if (rng=13) {
          game.fishname = "flaming fin"
          game.fishprice = "4"
        }
        if (rng=14) {
          game.fishname = "piranha"
          game.fishprice = "5"
        }
        if (rng=15) {
          game.fishname = "bananafish"
          game.fishprice = "10"
        }
        if (rng=16) {
          game.fishname = "axolotl"
          game.fishprice = "22"
        }
        if (rng=17) {
          game.fishname = "betta fish"
          game.fishprice = "0"
        }
        if (rng=18) {
          game.fishname = "discus fish"
          game.fishprice = "8"
        }
        if (rng=19) {
          game.fishname = "sea dragon"
          game.fishprice = "30"
        }
        if (rng=20) {
          game.fishname = "moon jellyfish"
          game.fishprice = "40"
        }
        if (rng=21) {
          game.fishname = "koi"
          game.fishprice = "2"
        }
        if (rng=22) {
          game.fishname = "thunder crayfish"
          game.fishprice = "3"
        }
        if (rng=23) {
          game.fishname = "mandarin fish"
          game.fishprice = "1"
        }
        if (rng=24) {
          game.fishname = "dwarf pufferfish"
          game.fishprice = "1"
        }
        if (rng=25) {
          game.fishname = "peacock mantis shrimp"
          game.fishprice = "19"
        }
        if (rng=26) {
          game.fishname = "fire shrimp"
          game.fishprice = "1"
        }
        if (rng=27) {
          game.fishname = "fancy snail"
          game.fishprice = "0"
        }
        if (rng=28) {
          game.fishname = "african dwarf frog"
          game.fishprice = "2"
        }
        if (rng=29) {
          game.fishname = "angelfish"
          game.fishprice = "4"
        }
        if (rng=30) {
          game.fishname = "lobster"
          game.fishprice = "6"
        }
        if (rng=31) {
          game.fishname = "datastream darter"
          game.fishprice = "20"
        }
        if (rng=32) {
          game.fishname = "neon ripplefish"
          game.fishprice = "11"
        }
        if (rng=33) {
          game.fishname = "chromeback salmon"
          game.fishprice = "15"
        }
        if (rng=34) {
          game.fishname = "solar sailfish"
          game.fishprice = "16"
        }
        if (rng=35) {
          game.fishname = "hypercurrent eel"
          game.fishprice = "25"
        }
        if (rng=36) {
          game.fishname = "plasma pike"
          game.fishprice = "50"
        }
        if (rng=37) {
          game.fishname = "bio-luminescent leviathan"
          game.fishprice = "100"
        }
        if (rng=38) {
          game.fishname = "magnetic manta"
          game.fishprice = "40"
        }
        if (rng=39) {
          game.fishname = "hydrodynamic hologram"
          game.fishprice = "2"
        }
        if (rng=40) {
          game.fishname = "quantum quagga"
          game.fishprice = "60"
        }
        if (RandomChance(11)) {
          fish.alias = ""+game.fishname
          fish.price = ""+game.fishprice
          CloneObjectAndMoveHere (fish)
        }
        else {
          foreach (object, GetDirectChildren (game.pov.parent)) {
            if (object.alias = ""+game.fishname) {
              if (object.name<>"fish") {
                object.runaway = true
              }
            }
          }
        }
      }
    ]]></script>
  </timer>
  <timer name="fish timer2">
    <interval>1</interval>
    <enabled />
    <script><![CDATA[
      for (repeat, 1, 40, 1) {
        rng = GetRandomInt(1,40)
        if (rng=1) {
          game.fishname = "largemouth bass"
          game.fishprice = "3"
        }
        if (rng=2) {
          game.fishname = "trout"
          game.fishprice = "0"
        }
        if (rng=3) {
          game.fishname = "bluegill"
          game.fishprice = "1"
        }
        if (rng=4) {
          game.fishname = "catfish"
          game.fishprice = "1"
        }
        if (rng=5) {
          game.fishname = "salmon"
          game.fishprice = "8"
        }
        if (rng=6) {
          game.fishname = "northern pike"
          game.fishprice = "11"
        }
        if (rng=7) {
          game.fishname = "perch"
          game.fishprice = "2"
        }
        if (rng=8) {
          game.fishname = "striped bass"
          game.fishprice = "3"
        }
        if (rng=9) {
          game.fishname = "crabfish"
          game.fishprice = "4"
        }
        if (rng=10) {
          game.fishname = "mini squid"
          game.fishprice = "6"
        }
        if (rng=11) {
          game.fishname = "mystery tuna"
          game.fishprice = "0"
        }
        if (rng=12) {
          game.fishname = "time cod"
          game.fishprice = "0"
        }
        if (rng=13) {
          game.fishname = "freezing fin"
          game.fishprice = "1"
        }
        if (rng=14) {
          game.fishname = "firetail tetra"
          game.fishprice = "2"
        }
        if (rng=15) {
          game.fishname = "golden perch"
          game.fishprice = "10"
        }
        if (rng=16) {
          game.fishname = "emerald goby"
          game.fishprice = "22"
        }
        if (rng=17) {
          game.fishname = "rainbow darter"
          game.fishprice = "7"
        }
        if (rng=18) {
          game.fishname = "sapphire cichlid"
          game.fishprice = "18"
        }
        if (rng=19) {
          game.fishname = "platinum piranha"
          game.fishprice = "15"
        }
        if (rng=20) {
          game.fishname = "diamond guppy"
          game.fishprice = "20"
        }
        if (rng=21) {
          game.fishname = "orange koi"
          game.fishprice = "10"
        }
        if (rng=22) {
          game.fishname = "ruby redfish"
          game.fishprice = "4"
        }
        if (rng=23) {
          game.fishname = "england fish"
          game.fishprice = "0"
        }
        if (rng=24) {
          game.fishname = "spiky pufferfish"
          game.fishprice = "0"
        }
        if (rng=25) {
          game.fishname = "raining tree shrimp"
          game.fishprice = "0"
        }
        if (rng=26) {
          game.fishname = "yellow shrimp"
          game.fishprice = "0"
        }
        if (rng=27) {
          game.fishname = "nerite snail"
          game.fishprice = "0"
        }
        if (rng=28) {
          game.fishname = "blue dart frog"
          game.fishprice = "1"
        }
        if (rng=29) {
          game.fishname = "angelic fin"
          game.fishprice = "14"
        }
        if (rng=30) {
          game.fishname = "giant lobster"
          game.fishprice = "6"
        }
        if (rng=31) {
          game.fishname = "streaming nova"
          game.fishprice = "12"
        }
        if (rng=32) {
          game.fishname = "tetra ripplefish"
          game.fishprice = "14"
        }
        if (rng=33) {
          game.fishname = "dragon eye"
          game.fishprice = "16"
        }
        if (rng=34) {
          game.fishname = "sailing fin"
          game.fishprice = "19"
        }
        if (rng=35) {
          game.fishname = "thunderous snake"
          game.fishprice = "2"
        }
        if (rng=36) {
          game.fishname = "crazy fish"
          game.fishprice = "0"
        }
        if (rng=37) {
          game.fishname = "bio-luminescent pike"
          game.fishprice = "50"
        }
        if (rng=38) {
          game.fishname = "tortoise manta"
          game.fishprice = "10"
        }
        if (rng=39) {
          game.fishname = "weather eel"
          game.fishprice = "20"
        }
        if (rng=40) {
          game.fishname = "sister lullaby"
          game.fishprice = "20"
        }
        if (RandomChance(11)) {
          fish.alias = ""+game.fishname
          fish.price = ""+game.fishprice
          CloneObjectAndMoveHere (fish)
        }
        else {
          foreach (object, GetDirectChildren (game.pov.parent)) {
            if (object.alias = ""+game.fishname) {
              if (object.name<>"fish") {
                object.runaway = true
              }
            }
          }
        }
      }
    ]]></script>
  </timer>
  <timer name="runaway fish timer">
    <interval>1</interval>
    <enabled />
    <script><![CDATA[
      foreach (object, GetDirectChildren (game.pov.parent)) {
        if (HasAttribute(object, "runaway")) {
          object.visible = false
          object.deleteseconds = object.deleteseconds+1
          if (object.deleteseconds>10) {
            object.parent = null
          }
        }
      }
    ]]></script>
  </timer>
</asl>

Making the fish invisible is a great idea… that way they don't leave the room's children.

I changed the script above to do that; as well as fixing a typo in one of the dictionary names (fishcount instead of fishcounts). This also means that my script isn't doing a foreach over the children of the room anymore - it does a foreach over an objectlist variable created by the FilterByAttribute function.

As my code should "create" new fish by taking one of the invisible ones, changing its alias and price, and making it visible again, that means that the number of fish in the room actually only changes when the number of fish reaches its highest level so far.

So… now, even if lag means that the script is running twice at the same time, it should only generate the error if the very first step (loop over the fish in the room, and make a separate list of just the visible ones) coincides with cloning a new fish into the room because there aren't enough there. There might still be a chance of an error because of the foreach in the sidebar update code; but I think that's less likely.


EDIT: Typo (again)

Actually… this might be more efficient:

Click for code (not saving copies of the dictionaries; and making it a dictionary of objectlists)
  <timer name="fish timer">
    <interval>1</interval>
    <script><![CDATA[
      // First, make a list to keep track of the "deleted" fish so we can reuse them:
      if (not HasAttribute(this, "sparefish")) {
        this.sparefish = NewObjectList()
      }
      // Then we make a record of how many fish currently exist:
      fishcounts = NewDictionary()
      foreach (obj, FilterByAttribute (GetDirectChildren(game.pov.parent), "visible", true)) {
        if (obj.prototype = fish) {
          if (not DictionaryContains (fishcounts, obj.alias)) {
            dictionary add (fishcounts, obj.alias, NewObjectList())
          }
          fishlist = DictionaryItem (fishcounts, obj.alias)
          list add (fishlist, obj)
        }
      }

      // Make a separate dictionary for how many fish of each type we want
      wantedfish = NewDictionary()

      for (repeat, 1, 40, 1) {
        rng = PickOneString(Split("monkfish;rainbow trout;electric eel;lionfish;flying fish;swordfish;mirror carp;slippery snook;jellyfish;gigagoldfish;mystery mackerel;time trout;flaming fin;piranha;bananafish;axolotl;betta fish;discus fish;sea dragon;moon jellyfish;koi;thunder crayfish;mandarin fish;dwarf pufferfish;peacock mantis shrimp;fire shrimp;fancy snail;african dwarf frog;angelfish;lobster;datastream darter;neon ripplefish;chromeback salmon;solar sailfish;hypercurrent eel;plasma pike;bio-luminescent leviathan;magnetic manta;hydrodynamic hologram;quantum quagga"))
        if (RandomChance(11)) {
          if (DictionaryContains (wantedfish, rng)) {
            count = DictionaryItem (wantedfish, rng)
            dictionary remove (wantedfish, rng)
            dictionary add (wantedfish, rng, count + 1)
          }
          else if (DictionaryContains (fishcounts, rng)) {
            existingfish = DictionaryItem (fishcounts, rng)
            dictionary add (wantedfish, rng, 1 + ListCount (existingfish))
          }
          else {
            dictionary add (wantedfish, rng, 1)
          }
        }
        else if (DictionaryContains (wantedfish, rng)) {
          // delete the fish if there are any
          dictionary remove (wantedfish, rng)
          dictionary add (wantedfish, rng, 0)
        }
        else if (DictionaryContains (fishcounts, rng)) {
          dictionary add (wantedfish, rng, 0)
        }
      }
      // Do the same again for the second list:
      for (repeat, 1, 40, 1) {
        rng = PickOneString(Split("largemouth bass;trout;bluegill;catfish;salmon;northern pike;perch;striped bass;crabfish;mini squid;mystery tuna;time cod;freezing fin;firetail tetra;golden perch;emerald goby;rainbow darter;sapphire cichlid;platinum piranha;diamond guppy;orange koi;ruby redfish;england fish;spiky pufferfish;raining tree shrimp;yellow shrimp;nerite snail;blue dart frog;angelic fin;giant lobster;streaming nova;tetra ripplefish;dragon eye;sailing fin;thunderous snake;crazy fish;bio-luminescent pike;tortoise manta;weather eel;sister lullaby"))
        if (RandomChance(11)) {
          if (DictionaryContains (wantedfish, rng)) {
            count = DictionaryItem (wantedfish, rng)
            dictionary remove (wantedfish, rng)
            dictionary add (wantedfish, rng, count + 1)
          }
          else if (DictionaryContains (fishcounts, rng)) {
            existingfish = DictionaryItem (fishcounts, rng)
            dictionary add (wantedfish, rng, 1 + ListCount (existingfish))
          }
          else {
            dictionary add (wantedfish, rng, 1)
          }
        }
        else if (DictionaryContains (wantedfish, rng)) {
          // delete the fish if there are any
          dictionary remove (wantedfish, rng)
          dictionary add (wantedfish, rng, 0)
        }
        else if (DictionaryContains (fishcounts, rng)) {
          dictionary add (wantedfish, rng, 0)
        }
      }
      // at this point, fishcounts is a dictionary of all fish, grouped by alias
      // and wantedfish is a dictionary of how many fish should exist for the next second

      // so now, we compare the two lists, and create or remove fish as necessary
      foreach (fishtype, wantedfish) {
        wantednumber = DictionaryItem(wantedfish, fishtype)
        if (DictionaryContains (fishcounts, fishtype)) {
          currentfish = DictionaryItem(fishcounts, fishtype)
        }
        else {
          currentfish = NewObjectList()
        }

        // If there's too many, remove some
        while (ListCount(currentfish) > wantednumber) {
          gonefish = ListItem(currentfish, 0)
          list remove (currentfish, gonefish)
          // Note that I'm adding it to the list of "spare fish" as well as removing it
          // So we can bring it back later instead of cloning a new one
          list add (this.sparefish, gonefish)
          gonefish.visible = false
        }
        if (wantednumber > ListCount (currentfish)) {
          // We need to create new fish, so let's work out how much it's worth
          switch (fishtype) {
            case ("monkfish", "mystery mackerel", "mandarin fish", "dwarf pufferfish", "fire shrimp", "bluegill", "catfish", "freezing fin", "blue dart frog") {
              price = "1"
            }
            case ("rainbow trout", "electric eel", "jellyfish", "time trout", "koi", "african dwarf frog", "hydrodynamic hologram", "perch", "firetail tetra", "thunderous snake") {
              price = "2"
            }
            case ("thunder crayfish", "largemouth bass", "striped bass") {
              price = "3"
            }
            case ("flaming fin", "angelfish", "crabfish", "ruby redfish") {
              price = "4"
            }
            case ("lionfish", "piranha") {
              price = "5"
            }
            case ("flying fish", "lobster", "mini squid", "giant lobster") {
              price = "6"
            }
            case ("rainbow darter") {
              price = "7"
            }
            case ("discus fish", "salmon") {
              price = "8"
            }
            case ("bananafish", "golden perch", "orange koi", "tortoise manta") {
              price = "10"
            }
            case ("neon ripplefish", "northern pike") {
              price = "11"
            }
            case ("streaming nova") {
              price = "12"
            }
            case ("angelic fin", "tetra ripplefish") {
              price = "14"
            }
            case ("chromeback salmon", "platinum piranha") {
              price = "15"
            }
            case ("solar sailfish", "dragon eye") {
              price = "16"
            }
            case ("sapphire cichlid") {
              price = "18"
            }
            case ("peacock mantis shrimp", "sailing fin") {
              price = "19"
            }
            case ("swordfish", "datastream darter", "diamond guppy", "weather eel", "sister lullaby") {
              price = "20"
            }
            case ("axolotl", "emerald goby") {
              price = "22"
            }
            case ("hypercurrent eel") {
              price = "25"
            }
            case ("sea dragon") {
              price = "30"
            }
            case ("gigagoldfish", "moon jellyfish", "magnetic manta") {
              price = "40"
            }
            case ("mirror carp", "plasma pike", "bio-luminescent pike") {
              price = "50"
            }
            case ("quantum quagga") {
              price = "60"
            }
            case ("bio-luminescent leviathan") {
              price = "100"
            }
            default {
              price = "0"
            }
          }
          // Now, let's create those fish…
          while (ListCount (currentfish) < wantednumber) {
            // If we've got a spare fish, use it
            if (ListCount (this.sparefish) > 0) {
              newfish = ListItem(this.sparefish, 0)
              list remove (this.sparefish, newfish)
            }
            else {
              newfish = CloneObjectAndMoveHere(fish)
            }
            newfish.alias = fishtype
            newfish.price = price
            newfish.visible = true
            list add (currentfish, newfish)
          }
        }
      }
    ]]></script>
    <enabled />
  </timer>

This time I actually tried it; and wasn't able to replicate your error. Not sure if there's a difference between the desktop and web versions in that respect, but it works for me online.


The AI changed your code
from

fishlist = FilterByAttribute (GetDirectChildren(game.pov.parent, "alias", fishtype))

to

fishlist = FilterByAttribute (GetDirectChildren(game.pov.parent), "alias", fishtype)

The fishtimer finally started but doesn't delete fishes, overall I think your code is too complicated for me, my code that I gave is just a simplified version of my fishing game, the player's stats like fishing rod power, player level, casted spell, room constructed upsized more fishing spots, the appearance of dangerous animals like crocodiles scaring away fishes, seasonal fishes in different months, buy baits that attract different fishes, they all need to be inserted back into the code, and I can't do all that, because your code is too advanced for me to understand

I still treasure your code just like infinite maze and I will read it occassionally like a bible, but for my current games, I can't really implement it


If Jennifer Wren is interested, maybe you can write out your simplified code from your game for us to investigate this in an easier approach?


I was referring to your earlier code, my reply is on 9.08pm and your even newer code is on 9.07pm, we missed each other message while typing

I tried online editor, it doesn't suits me, lots of lag just like visiting the textadventure website itself, my conclusion was that because I live 10,954 km away from UK
Also, in online editor, I can't find full game code edit view
I tried pasting into timer script, and I just keep getting internal error

So, I am returning to desktop editor which works fine


mrangel's 9.07pm fish timer is working flawlessly without errors

I am adding back the fish object, game.money (tick box) and catch verb back into mrangel's code
You guys can make your own fishing game now, thanks to mrangel

Working fish timer, feel free to change the fishes name and prices

To paste the code

  1. Startup your quest gamebook/textadventure, on the right side of the big play button, you can see a code view button </>
  2. Copy the code to replace the code in the text box, click code view button again.
  3. Viola, it is done, press play button to test out the game and modify the code to your preference.
<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="test2">
    <gameid>c571b143-5f0d-4722-adf8-78c496454ef7</gameid>
    <version>1.0</version>
    <firstpublished>2024</firstpublished>
    <showmoney />
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="fish">
      <inherit name="editor_object" />
      <catch type="script">
        msg ("You caught a "+this.alias)
        msg ("$"+this.price+ " have been added.")
        add = ToInt(this.price)
        player.money = player.money + add
        this.parent = null
      </catch>
      <displayverbs type="stringlist" />
      <visible type="boolean">false</visible>
    </object>
  </object>
  <verb>
    <property>catch</property>
    <pattern>catch</pattern>
    <defaultexpression>"You can't catch " + object.article + "."</defaultexpression>
  </verb>
  <timer name="fish timer">
    <interval>1</interval>
    <enabled />
    <script><![CDATA[
      // First, make a list to keep track of the "deleted" fish so we can reuse them:
      if (not HasAttribute(this, "sparefish")) {
        this.sparefish = NewObjectList()
      }
      // Then we make a record of how many fish currently exist:
      fishcounts = NewDictionary()
      foreach (obj, FilterByAttribute (GetDirectChildren(game.pov.parent), "visible", true)) {
        if (obj.prototype = fish) {
          if (not DictionaryContains (fishcounts, obj.alias)) {
            dictionary add (fishcounts, obj.alias, NewObjectList())
          }
          fishlist = DictionaryItem (fishcounts, obj.alias)
          list add (fishlist, obj)
        }
      }
      // Make a separate dictionary for how many fish of each type we want
      wantedfish = NewDictionary()
      for (repeat, 1, 40, 1) {
        rng = PickOneString(Split("monkfish;rainbow trout;electric eel;lionfish;flying fish;swordfish;mirror carp;slippery snook;jellyfish;gigagoldfish;mystery mackerel;time trout;flaming fin;piranha;bananafish;axolotl;betta fish;discus fish;sea dragon;moon jellyfish;koi;thunder crayfish;mandarin fish;dwarf pufferfish;peacock mantis shrimp;fire shrimp;fancy snail;african dwarf frog;angelfish;lobster;datastream darter;neon ripplefish;chromeback salmon;solar sailfish;hypercurrent eel;plasma pike;bio-luminescent leviathan;magnetic manta;hydrodynamic hologram;quantum quagga"))
        if (RandomChance(11)) {
          if (DictionaryContains (wantedfish, rng)) {
            count = DictionaryItem (wantedfish, rng)
            dictionary remove (wantedfish, rng)
            dictionary add (wantedfish, rng, count + 1)
          }
          else if (DictionaryContains (fishcounts, rng)) {
            existingfish = DictionaryItem (fishcounts, rng)
            dictionary add (wantedfish, rng, 1 + ListCount (existingfish))
          }
          else {
            dictionary add (wantedfish, rng, 1)
          }
        }
        else if (DictionaryContains (wantedfish, rng)) {
          // delete the fish if there are any
          dictionary remove (wantedfish, rng)
          dictionary add (wantedfish, rng, 0)
        }
        else if (DictionaryContains (fishcounts, rng)) {
          dictionary add (wantedfish, rng, 0)
        }
      }
      // Do the same again for the second list:
      for (repeat, 1, 40, 1) {
        rng = PickOneString(Split("largemouth bass;trout;bluegill;catfish;salmon;northern pike;perch;striped bass;crabfish;mini squid;mystery tuna;time cod;freezing fin;firetail tetra;golden perch;emerald goby;rainbow darter;sapphire cichlid;platinum piranha;diamond guppy;orange koi;ruby redfish;england fish;spiky pufferfish;raining tree shrimp;yellow shrimp;nerite snail;blue dart frog;angelic fin;giant lobster;streaming nova;tetra ripplefish;dragon eye;sailing fin;thunderous snake;crazy fish;bio-luminescent pike;tortoise manta;weather eel;sister lullaby"))
        if (RandomChance(11)) {
          if (DictionaryContains (wantedfish, rng)) {
            count = DictionaryItem (wantedfish, rng)
            dictionary remove (wantedfish, rng)
            dictionary add (wantedfish, rng, count + 1)
          }
          else if (DictionaryContains (fishcounts, rng)) {
            existingfish = DictionaryItem (fishcounts, rng)
            dictionary add (wantedfish, rng, 1 + ListCount (existingfish))
          }
          else {
            dictionary add (wantedfish, rng, 1)
          }
        }
        else if (DictionaryContains (wantedfish, rng)) {
          // delete the fish if there are any
          dictionary remove (wantedfish, rng)
          dictionary add (wantedfish, rng, 0)
        }
        else if (DictionaryContains (fishcounts, rng)) {
          dictionary add (wantedfish, rng, 0)
        }
      }
      // at this point, fishcounts is a dictionary of all fish, grouped by alias
      // and wantedfish is a dictionary of how many fish should exist for the next second
      // so now, we compare the two lists, and create or remove fish as necessary
      foreach (fishtype, wantedfish) {
        wantednumber = DictionaryItem(wantedfish, fishtype)
        if (DictionaryContains (fishcounts, fishtype)) {
          currentfish = DictionaryItem(fishcounts, fishtype)
        }
        else {
          currentfish = NewObjectList()
        }
        // If there's too many, remove some
        while (ListCount(currentfish) > wantednumber) {
          gonefish = ListItem(currentfish, 0)
          list remove (currentfish, gonefish)
          // Note that I'm adding it to the list of "spare fish" as well as removing it
          // So we can bring it back later instead of cloning a new one
          list add (this.sparefish, gonefish)
          gonefish.visible = false
        }
        if (wantednumber > ListCount (currentfish)) {
          // We need to create new fish, so let's work out how much it's worth
          switch (fishtype) {
            case ("monkfish", "mystery mackerel", "mandarin fish", "dwarf pufferfish", "fire shrimp", "bluegill", "catfish", "freezing fin", "blue dart frog") {
              price = "1"
            }
            case ("rainbow trout", "electric eel", "jellyfish", "time trout", "koi", "african dwarf frog", "hydrodynamic hologram", "perch", "firetail tetra", "thunderous snake") {
              price = "2"
            }
            case ("thunder crayfish", "largemouth bass", "striped bass") {
              price = "3"
            }
            case ("flaming fin", "angelfish", "crabfish", "ruby redfish") {
              price = "4"
            }
            case ("lionfish", "piranha") {
              price = "5"
            }
            case ("flying fish", "lobster", "mini squid", "giant lobster") {
              price = "6"
            }
            case ("rainbow darter") {
              price = "7"
            }
            case ("discus fish", "salmon") {
              price = "8"
            }
            case ("bananafish", "golden perch", "orange koi", "tortoise manta") {
              price = "10"
            }
            case ("neon ripplefish", "northern pike") {
              price = "11"
            }
            case ("streaming nova") {
              price = "12"
            }
            case ("angelic fin", "tetra ripplefish") {
              price = "14"
            }
            case ("chromeback salmon", "platinum piranha") {
              price = "15"
            }
            case ("solar sailfish", "dragon eye") {
              price = "16"
            }
            case ("sapphire cichlid") {
              price = "18"
            }
            case ("peacock mantis shrimp", "sailing fin") {
              price = "19"
            }
            case ("swordfish", "datastream darter", "diamond guppy", "weather eel", "sister lullaby") {
              price = "20"
            }
            case ("axolotl", "emerald goby") {
              price = "22"
            }
            case ("hypercurrent eel") {
              price = "25"
            }
            case ("sea dragon") {
              price = "30"
            }
            case ("gigagoldfish", "moon jellyfish", "magnetic manta") {
              price = "40"
            }
            case ("mirror carp", "plasma pike", "bio-luminescent pike") {
              price = "50"
            }
            case ("quantum quagga") {
              price = "60"
            }
            case ("bio-luminescent leviathan") {
              price = "100"
            }
            default {
              price = "0"
            }
          }
          // Now, let's create those fish…
          while (ListCount (currentfish) < wantednumber) {
            // If we've got a spare fish, use it
            if (ListCount (this.sparefish) > 0) {
              newfish = ListItem(this.sparefish, 0)
              list remove (this.sparefish, newfish)
            }
            else {
              newfish = CloneObjectAndMoveHere(fish)
            }
            newfish.alias = fishtype
            newfish.price = price
            newfish.visible = true
            list add (currentfish, newfish)
          }
        }
      }
    ]]></script>
  </timer>
</asl>

If I were making a game like this…

Click for a lot of untested ideas I don't think I'd attempt to spawn/despawn fish so often. Instead, I'd fill each fishing spot using the room's _initialise_ or beforefirstenter scripts. Something like:
fishtimer.enabled = false
for (i, 1, 8) {
  do (CloneObjectAndMoveHere (carp), "_initialise_"))
}
for (i, 1, 3) {
  do (CloneObjectAndMoveHere (carp), "_initialise_"))
}
for (i, 1, GetRandomInt(5,10)) {
  do (CloneObjectAndMoveHere (flatfish), "_initialise_"))
}
fishtimer.enabled = true

Then make the fish members of a type:

<type name="fish">
  <attr name="_initialise_" type="script"><![CDATA[
    this.visible = GetRandomInt (1-this.maxhidden, this.maxvisible) > 0
    this.dead = false
    this.timeleft = GetRandomInt(1,10)
  ]]></attr>
  <price type="int">0</price>
  <maxvisible type="int">6</maxvisible>
  <minvisible type="int">4</minvisible>
  <maxhidden type="int">8</maxhidden>
  <minhidden type="int">4</minhidden>
  <dead type="boolean">false</dead>
  <deathchance type="int">3</deathchance>
  <breedchance type="int">19</breedchance>
</type>

These objects are outside player space so we can clone them as necessary:

<object name="cod">
  <inherit name="fish"/>
  <price>8</price>
</object>
<object name="carp">
  <inherit name="fish"/>
  <price>25</price>
  <predator type="int">12</predator>
</object>
<object name="flatfish">
  <inherit name="fish"/>
  <price>17</price>
  <maxhidden type="int">12</maxhidden>
</object>

Then have a timer which just hides and unhides the fish. The fish listed above will be visible for 4-6 seconds, then hidden for 4-8 seconds; but there's attributes you can change so that a particular type of fish comes out for a shorter time, or less often. So there's a bunch of fish in the lake, becoming visible and invisible so you don't see them all the time. And then you can have a chance of them actually dying or reproducing, but much less often.

<timer name="fishtimer">
<deathtimer type="int">0</deathtimer>
<script><![CDATA[
  fishhere = FilterByNotAttribute (FilterByType (GetDirectChildren (game.pov.parent), "fish"), "dead", true)
  foreach (f, fishhere) {
    f.timeleft = f.timeleft - 1
    this.deathtimer = this.deathtimer % 30 - 1
    if (this.deathtimer = 0 and RandomChance(f.deathchance)) {
      f.dead = true
      f.visible = false
    }
    else if (f.timeleft <= 0) {
      // fish should become visible/invisible
      f.visible = not f.visible
      if (f.visible) {
        f.timeleft = GetRandomInt (f.minvisible, f.maxvisible)
      }
      else {
        f.timeleft = GetRandomInt (f.minhidden, f.maxhidden)
      }
    }
  }
  // Then check if any fish eat each other or breed:
  firstfish = PickOneObject (fishlist)
  secondfish = PickOneObject (fishlist)
  if (firstfish.prototype = secondfish.prototype and RandomChance(firstfish.breedchance)) {
    // Fish breeding!
    // Check if there's a dead fish we can revive first:
    offspring = PickOneObject (FilterByAttribute (FilterByAttribute (GetDirectChildren (game.pov.parent), "dead", true), "prototype", firstfish.prototype))
    if (offspring = null) {
      offspring = CloneObjectAndMoveHere (firstfish.prototype)
    }
    do (offsprint, "_initialise_")
  }
  else if (HasInt (firstfish, "predator")) {
    if (RandomChance (firstfish.predator)) {
      secondfish.dead = true
      secondfish.visible = false
    }
  }
]]></script>
</timer>

So… this would create a set of fish objects which alternate between visible and invisible at slightly random intervals. Every 30th fish checked (governed by deathtimer) has a deathchance% chance of dying and being removed from the pool. (If you checked them every second, deathchances would probably want to be less than 1%). Each second, it also chooses two fish at random (which may or may not be the visible ones) to encounter each other. If they're the same species, they have a breedchance% chance of creating another one of the same type. If they have the predator attribute set, the first one has a predator% chance of killing the second.

This means that fish caught by the player will be replenished, but they won't be created quite so often. And most of the time fish just swim deeper so they're out of sight rather than actually vanishing. This is a lot less work for Quest, because it doesn't need to create and destroy objects; but I like it because it means that if the player keeps on catching fish of the same type, eventually they'll run out (there's more than just the ones you can see, but not an infinite supply). It also means you can make a fish which rarely comes out; so it's harder to catch even if there's one there.

As far as the bug with the unexpected foreach, I do think it's being triggered by the updates to the sidebar. Which means that in theory, you could modify some of the core functions to reduce the problem. For example, you could do this with ScopeVisibleNotReachableForRoom (and similar things for ScopeReachableNotHeldForRoom, ScopeVisibleInventory, and ScopeReachableInventory)

  <function name="ScopeVisibleNotReachableForRoom" type="objectlist" parameters="room">
    if (not HasAttribute (room, "lastvisiblescope")) {
      room.lastvisiblescope = NewObjectList()
    }
    if (GetBoolean (game, "freezesidebars")) {
      return (room.lastvisiblescope)
    }
    result = NewObjectList()
    exclude = ScopeReachableForRoom(room)
    list add(exclude, game.pov)
    newParent = GetNonTransparentParent(room)
    foreach (obj, GetAllChildObjects(newParent)) {
      if (ContainsVisible(newParent, obj) and not ListContains(exclude, obj)) {
        list add(result, obj)
      }
      if (GetBoolean (game, "freezesidebars")) {
        return (room.lastvisiblescope)
      }
    }
    room.lastvisiblescope = result
    return (result)
  </function>

This basically creates an objectlist with what the room's contents was last time we looked. So if you're using a timer to create/destroy/move a lot of objects from the current room, you can set game.freezesidebars to true when you start, and false again once you're done. It will prevent the sidebars from updating in that time, but that's probably better than showing an error message.


Actually… looking at that again [the above suggestion of how I would implement a fishing system], if you have multiple fishing spots it might be better to organise the scripts a little more. This variation lets you set a minimum and maximum number for each fish species, on a per-location basis, as well as automating the process of cloning fish into a new location (useful if you're using random map generation…)

Click for more untested ideas

So you'd have something like:

<type name="fishing_location">
  <attr name="maxfish" type="dictionary"/>
  <attr name="minfish" type="dictionary"/>
  <attr name="startfish" type="dictionary"/>
  <attr name="fish_initialised" type="boolean">false</attr>
</type>

and then set up a room like:

<object name="tiny pond">
  <inherit name="fishing_location"/>
  <attr name="minfish" type="dictionary">
    <item><key>carp</key><value type="int">1</value></item>
    <item><key>cod</key><value type="int">6</value></item>
  </attr>
  <attr name="maxfish" type="dictionary">
    <item><key>cod</key><value type="int">18</value></item>
  </attr>
  <attr name="startfish" type="dictionary">
    <item><key>flatfish</key><value type="int">2</value></item>
  </attr>
</object>

And then in roomenter you would have:

fishtimer.enabled = false
room = game.pov.parent
if (DoesInherit (room, "fishing_location")) {
  if (not room.fish_initialised) {
    // Make a list of the fish types which can be found here
    fishtypes = NewObjectList()
    foreach (typename, room.minfish) list add (fishtypes, GetObject (typename))
    foreach (typename, room.maxfish) list add (fishtypes, GetObject (typename))
    foreach (typename, room.startfish) list add (fishtypes, GetObject (typename))
    foreach (fishtype, ListCompact (fishtypes)) {
      number = 0
      if (DictionaryContains (room.startfish, fishtype.name)) {
        number = DictionaryItem(room.startfish, fishtype.name)
      }
      else if (DictionaryContains (room.minfish, fishtype.name) and DictionaryContains (room.maxfish, fishtype.name)) {
        number = DictionaryItem(room.minfish, fishtype.name)
        maxnumber = DictionaryItem(room.maxfish, fishtype.name)
        number = GetRandomInt (number, maxnumber)
      }
      else if (DictionaryContains (room.minfish, fishtype.name)) {
        number = DictionaryItem(room.minfish, fishtype.name)
      }
      for (i, 1, number) {
        CloneObjectAndMoveHere (fishtype)
      }
    }
  }
  foreach (currentfish, FilterByType (GetDirectChildren (room), "fish")) {
    if ((currentfish.dead and RandomChance (95)) or RandomChance (currentfish.deathchance)) {
      currentfish.dead = true
      currentfish.visible = false
    }
    else {
      do (currentfish, "_initialise_")
    }
  }
  room.fish_initialised = true
  fishtimer.enabled = true
}

This basically sets up the initial fish in a room when the player enters, so you don't need to write a script for every room. It also gives the fish a chance to become visible/hidden when the player reenters a room, giving the impression that the fish have still been moving around while the player was away. And has the side effect of disabling the timer automatically when the player is in a room that doesn't have fish.

And at the end of the timer, you would add:

foreach (typename, game.pov.parent.minfish) {
  number = DictionaryItem (game.pov.parent.minfish, typename)
  fishoftype = FilterByAttribute (FilterByAttribute (FilterByType (GetDirectChildren(game.pov.parent), "fish"), "dead", false), "prototype", GetObject (typename))
  while (ListCount (fishoftype) < number) {
    newfish = FilterByAttribute (FilterByAttribute (FilterByType (GetDirectChildren(game.pov.parent), "fish"), "dead", true), "prototype", GetObject (typename))
    if (newfish = null) {
      newfish = CloneObjectAndMoveHere (GetObject (typename))
    }
    do (newfish, "_initialise_")
    list add (fishoftype, newfish)
  }
}
foreach (typename, game.pov.parent.maxfish) {
  number = DictionaryItem (game.pov.parent.maxfish, typename)
  fishoftype = FilterByAttribute (FilterByAttribute (FilterByType (GetDirectChildren(game.pov.parent), "fish"), "dead", false), "prototype", GetObject (typename))
  while (ListCount (fishoftype) > number) {
    deadfish = PickOneObject (fishoftype)
    list remove (fishoftype, deadfish)
    deadfish.dead = true
    deadfish.visible = false
  }
}

This would be a little more work for the engine, but I don't think it would be excessive.


freezesidebars sounds like the code I need, but despite trying everything the error still persists

  1. I did the code on ScopeVisibleNotReachableForRoom and ScopeReachableNotHeldForRoom
  2. I added game.freezesidebars to true to both timers and game.freezesidebars to false at end of code
  3. I added game.freezesidebars to true and false to catch verb

Deathchance and breedchance will simulate a realistic fishing environment which other players might want, but for me, I am just making a game which have to be fun, so it attempts to please the players by having as randomized results as possible including number of different fishes and multiples of same fishes

Fishing location using object type is a new code for me that I haven't knew existed, so this will probably take me a long time to figure what it does

Your 9:07 PM fish timer works flawlessly as tested again, which is kinda annoying because I dun understand it, so it is hard to make modifications to it

The thing is that you keep trying to attempt to stop generating fishes, which might be the key to resolving the error, but for me, I need to keep the code of generating fishes intact so as to make the results varied

Unfortunately, I might have to do walkarounds for the current game,

  1. If player construct new fishing spot, +1 second time interval for each fishing spot in that room
  2. Make fishing rod power less powerful, every 3 power = 1% randomchance to catching a fish (Copied from inner code, fishes running away, not really about catching)
  3. The base of fish timer interval is increased to 6 seconds, through various methods, players can decrease it to 3 seconds but no further
  4. Considering the possibility of using one timer for all fishing spots, if players unlock either fishing spot or is at either fishing room, the timer will call the responding fishing function
  5. Player.level will increase the fishes' price despite the illogicalness of it
  6. Seasonal fishes and baited fishes will all be slot into fishing functions and call when necessary
  7. Crocodile scaring away fishes will be simplified to disabling fish timer for 30 seconds
  8. Casted spell will increase the chances of catching fishes, this means that it is now possible for players to catch fishes and fail

Inspired by your no fish generation rule, I spawned a set of random fishes and had them turn visible and invisible instead of running away
When fishes are caught, the fishes turn invisible instead of being deleted away

Yes, it works
I know, I can change the fish generation to 1 second or instant, I am just tired now

Another reason for avoiding 9:07 PM fish timer is because the code is too long, I expect to keep making more fish timers or even have randomly generated fish timers with random names and prices, it will be hard for me to tweak your code and it takes a long time as well

Working fish timer, turning invisible instead of being deleted away

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="test">
    <gameid>d1d77751-bc11-4993-9b37-cc7a5061a6f0</gameid>
    <version>1.0</version>
    <firstpublished>2024</firstpublished>
    <showmoney />
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <enter type="script">
      SetTimeout (9) {
        DisableTimer (fish timer)
        DisableTimer (fish timer2)
        EnableTimer (fish hider)
      }
    </enter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="fish">
      <inherit name="editor_object" />
      <displayverbs type="stringlist" />
      <catch type="script">
        msg ("You caught a "+this.alias)
        msg ("$"+this.price+ " have been added.")
        add = ToInt(this.price)
        player.money = player.money + add
        this.visible = false
      </catch>
    </object>
  </object>
  <verb>
    <property>catch</property>
    <pattern>catch</pattern>
    <defaultexpression>"You can't catch " + object.article + "."</defaultexpression>
  </verb>
  <timer name="fish timer">
    <interval>1</interval>
    <enabled />
    <script>
      for (repeat, 1, 40, 1) {
        rng = GetRandomInt(1,40)
        if (rng=1) {
          game.fishname = "monkfish"
          game.fishprice = "1"
        }
        if (rng=2) {
          game.fishname = "rainbow trout"
          game.fishprice = "2"
        }
        if (rng=3) {
          game.fishname = "electric eel"
          game.fishprice = "2"
        }
        if (rng=4) {
          game.fishname = "lionfish"
          game.fishprice = "5"
        }
        if (rng=5) {
          game.fishname = "flying fish"
          game.fishprice = "6"
        }
        if (rng=6) {
          game.fishname = "swordfish"
          game.fishprice = "20"
        }
        if (rng=7) {
          game.fishname = "mirror carp"
          game.fishprice = "50"
        }
        if (rng=8) {
          game.fishname = "slippery snook"
          game.fishprice = "0"
        }
        if (rng=9) {
          game.fishname = "jellyfish"
          game.fishprice = "2"
        }
        if (rng=10) {
          game.fishname = "gigagoldfish"
          game.fishprice = "40"
        }
        if (rng=11) {
          game.fishname = "mystery mackerel"
          game.fishprice = "1"
        }
        if (rng=12) {
          game.fishname = "time trout"
          game.fishprice = "2"
        }
        if (rng=13) {
          game.fishname = "flaming fin"
          game.fishprice = "4"
        }
        if (rng=14) {
          game.fishname = "piranha"
          game.fishprice = "5"
        }
        if (rng=15) {
          game.fishname = "bananafish"
          game.fishprice = "10"
        }
        if (rng=16) {
          game.fishname = "axolotl"
          game.fishprice = "22"
        }
        if (rng=17) {
          game.fishname = "betta fish"
          game.fishprice = "0"
        }
        if (rng=18) {
          game.fishname = "discus fish"
          game.fishprice = "8"
        }
        if (rng=19) {
          game.fishname = "sea dragon"
          game.fishprice = "30"
        }
        if (rng=20) {
          game.fishname = "moon jellyfish"
          game.fishprice = "40"
        }
        if (rng=21) {
          game.fishname = "koi"
          game.fishprice = "2"
        }
        if (rng=22) {
          game.fishname = "thunder crayfish"
          game.fishprice = "3"
        }
        if (rng=23) {
          game.fishname = "mandarin fish"
          game.fishprice = "1"
        }
        if (rng=24) {
          game.fishname = "dwarf pufferfish"
          game.fishprice = "1"
        }
        if (rng=25) {
          game.fishname = "peacock mantis shrimp"
          game.fishprice = "19"
        }
        if (rng=26) {
          game.fishname = "fire shrimp"
          game.fishprice = "1"
        }
        if (rng=27) {
          game.fishname = "fancy snail"
          game.fishprice = "0"
        }
        if (rng=28) {
          game.fishname = "african dwarf frog"
          game.fishprice = "2"
        }
        if (rng=29) {
          game.fishname = "angelfish"
          game.fishprice = "4"
        }
        if (rng=30) {
          game.fishname = "lobster"
          game.fishprice = "6"
        }
        if (rng=31) {
          game.fishname = "datastream darter"
          game.fishprice = "20"
        }
        if (rng=32) {
          game.fishname = "neon ripplefish"
          game.fishprice = "11"
        }
        if (rng=33) {
          game.fishname = "chromeback salmon"
          game.fishprice = "15"
        }
        if (rng=34) {
          game.fishname = "solar sailfish"
          game.fishprice = "16"
        }
        if (rng=35) {
          game.fishname = "hypercurrent eel"
          game.fishprice = "25"
        }
        if (rng=36) {
          game.fishname = "plasma pike"
          game.fishprice = "50"
        }
        if (rng=37) {
          game.fishname = "bio-luminescent leviathan"
          game.fishprice = "100"
        }
        if (rng=38) {
          game.fishname = "magnetic manta"
          game.fishprice = "40"
        }
        if (rng=39) {
          game.fishname = "hydrodynamic hologram"
          game.fishprice = "2"
        }
        if (rng=40) {
          game.fishname = "quantum quagga"
          game.fishprice = "60"
        }
        if (RandomChance(11)) {
          fish.alias = ""+game.fishname
          fish.price = ""+game.fishprice
          CloneObjectAndMoveHere (fish)
        }
      }
    </script>
  </timer>
  <timer name="fish timer2">
    <interval>1</interval>
    <enabled />
    <script>
      for (repeat, 1, 40, 1) {
        rng = GetRandomInt(1,40)
        if (rng=1) {
          game.fishname = "largemouth bass"
          game.fishprice = "3"
        }
        if (rng=2) {
          game.fishname = "trout"
          game.fishprice = "0"
        }
        if (rng=3) {
          game.fishname = "bluegill"
          game.fishprice = "1"
        }
        if (rng=4) {
          game.fishname = "catfish"
          game.fishprice = "1"
        }
        if (rng=5) {
          game.fishname = "salmon"
          game.fishprice = "8"
        }
        if (rng=6) {
          game.fishname = "northern pike"
          game.fishprice = "11"
        }
        if (rng=7) {
          game.fishname = "perch"
          game.fishprice = "2"
        }
        if (rng=8) {
          game.fishname = "striped bass"
          game.fishprice = "3"
        }
        if (rng=9) {
          game.fishname = "crabfish"
          game.fishprice = "4"
        }
        if (rng=10) {
          game.fishname = "mini squid"
          game.fishprice = "6"
        }
        if (rng=11) {
          game.fishname = "mystery tuna"
          game.fishprice = "0"
        }
        if (rng=12) {
          game.fishname = "time cod"
          game.fishprice = "0"
        }
        if (rng=13) {
          game.fishname = "freezing fin"
          game.fishprice = "1"
        }
        if (rng=14) {
          game.fishname = "firetail tetra"
          game.fishprice = "2"
        }
        if (rng=15) {
          game.fishname = "golden perch"
          game.fishprice = "10"
        }
        if (rng=16) {
          game.fishname = "emerald goby"
          game.fishprice = "22"
        }
        if (rng=17) {
          game.fishname = "rainbow darter"
          game.fishprice = "7"
        }
        if (rng=18) {
          game.fishname = "sapphire cichlid"
          game.fishprice = "18"
        }
        if (rng=19) {
          game.fishname = "platinum piranha"
          game.fishprice = "15"
        }
        if (rng=20) {
          game.fishname = "diamond guppy"
          game.fishprice = "20"
        }
        if (rng=21) {
          game.fishname = "orange koi"
          game.fishprice = "10"
        }
        if (rng=22) {
          game.fishname = "ruby redfish"
          game.fishprice = "4"
        }
        if (rng=23) {
          game.fishname = "england fish"
          game.fishprice = "0"
        }
        if (rng=24) {
          game.fishname = "spiky pufferfish"
          game.fishprice = "0"
        }
        if (rng=25) {
          game.fishname = "raining tree shrimp"
          game.fishprice = "0"
        }
        if (rng=26) {
          game.fishname = "yellow shrimp"
          game.fishprice = "0"
        }
        if (rng=27) {
          game.fishname = "nerite snail"
          game.fishprice = "0"
        }
        if (rng=28) {
          game.fishname = "blue dart frog"
          game.fishprice = "1"
        }
        if (rng=29) {
          game.fishname = "angelic fin"
          game.fishprice = "14"
        }
        if (rng=30) {
          game.fishname = "giant lobster"
          game.fishprice = "6"
        }
        if (rng=31) {
          game.fishname = "streaming nova"
          game.fishprice = "12"
        }
        if (rng=32) {
          game.fishname = "tetra ripplefish"
          game.fishprice = "14"
        }
        if (rng=33) {
          game.fishname = "dragon eye"
          game.fishprice = "16"
        }
        if (rng=34) {
          game.fishname = "sailing fin"
          game.fishprice = "19"
        }
        if (rng=35) {
          game.fishname = "thunderous snake"
          game.fishprice = "2"
        }
        if (rng=36) {
          game.fishname = "crazy fish"
          game.fishprice = "0"
        }
        if (rng=37) {
          game.fishname = "bio-luminescent pike"
          game.fishprice = "50"
        }
        if (rng=38) {
          game.fishname = "tortoise manta"
          game.fishprice = "10"
        }
        if (rng=39) {
          game.fishname = "weather eel"
          game.fishprice = "20"
        }
        if (rng=40) {
          game.fishname = "sister lullaby"
          game.fishprice = "20"
        }
        if (RandomChance(11)) {
          fish.alias = ""+game.fishname
          fish.price = ""+game.fishprice
          CloneObjectAndMoveHere (fish)
        }
      }
    </script>
  </timer>
  <timer name="fish hider">
    <interval>1</interval>
    <script>
      foreach (object, GetDirectChildren (game.pov.parent)) {
        if (RandomChance(90)) {
          MakeObjectInvisible (object)
        }
        if (RandomChance(10)) {
          MakeObjectVisible (object)
        }
      }
    </script>
  </timer>
</asl>

Yes this makes the fish variety set in the room less randomized, I expect casting spells or changing seasons to respawn or regenerate the fishes in every single room, I just need to take a break now


Looking again at your 40-random-fish algorithm, I realised that each fish created has a 33.3% chance of being removed again before the end of the timer script - before the player ever sees it. And then a 60% chance of being removed just one second later. That's even more clones than I realised.

With such a fast turnover, it might make more sense to do something like this before first entering the room:

this.fishlist = NewObjectList()
for (i, 1, 10) {
  newfish = CloneObjectAndMoveHere (fish)
  list add (this.fishlist, newfish)
  newfish.visible = false
}

and then your timer can just do:

fish_to_create = GetRandomInt (5, 8)
foreach (obj, game.pov.parent.fishlist) {
  if (fish_to_create > 0) {
    fish_to_create = fish_to_create - 1
    obj.visible = true
    obj.alias = PickOneString ("cod;carp;herring;goldfish;etc;etc")
    // code here to set obj's price and other attributes based on its alias
  }
  else {
    obj.visible = false
  }
}

That way, it only has to pick one random number for each fish; the probabilities are around the same as for your original script, but the computer is doing much less work, so less lag.


Another weird thought… you don't actually need to put fish objects in the room. This would guarantee there's no problem with the timer scripts running into the sidebar updates. You can keep the fish in a room the player can't visit, and use the background scope script to add them to the "reachable" scope so that commands work on them. This might be even simpler than messing with visible/invisible.

Each room would have an objectlist attribute, a list of the fish that should be visible there. And then you'd make the background scope script something like:

if (HasAttribute (game.pov.parent, "fishlist")) {
  foreach (obj, game.pov.parent.fishlist) {
    list add (items, obj)
  }
}

This effectively makes the objects on the list appear to be in the room even if they aren't really there. I can see a few advantages to doing it this way - for example, you could put the same fish in multiple rooms, so you need fewer clones.


Another reason for avoiding 9:07 PM fish timer is because the code is too long, I expect to keep making more fish timers or even have randomly generated fish timers with random names and prices, it will be hard for me to tweak your code and it takes a long time as well

That's one of the reasons that in my later version, I thought it would be better to make fish visible/invisible on a cycle. Events, spells, etc can add fish to the room, and the timer doesn't need any modifications.


So I created a timer to count how many objects were created and deleted per second, this can help us to visualize the limits of quest app

Seconds passed: 60, objects created: 525, objects deleted: 525
Caculating average would be: 1 second, 8.75 objects created + 8.75 objects deleted = 17.5 objects moved per second

Simplified fishing game code (1st original code) + count timer

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="test">
    <gameid>d1d77751-bc11-4993-9b37-cc7a5061a6f0</gameid>
    <version>1.0</version>
    <firstpublished>2024</firstpublished>
    <showmoney />
    <createdobjs type="int">0</createdobjs>
    <delobjs type="int">0</delobjs>
    <timerx type="int">0</timerx>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="fish">
      <inherit name="editor_object" />
      <displayverbs type="stringlist" />
      <catch type="script">
        msg ("You caught a "+this.alias)
        msg ("$"+this.price+ " have been added.")
        add = ToInt(this.price)
        player.money = player.money + add
        this.parent = null
      </catch>
    </object>
  </object>
  <verb>
    <property>catch</property>
    <pattern>catch</pattern>
    <defaultexpression>"You can't catch " + object.article + "."</defaultexpression>
  </verb>
  <timer name="fish timer">
    <interval>1</interval>
    <enabled />
    <script>
      for (repeat, 1, 40, 1) {
        rng = GetRandomInt(1,40)
        if (rng=1) {
          game.fishname = "monkfish"
          game.fishprice = "1"
        }
        if (rng=2) {
          game.fishname = "rainbow trout"
          game.fishprice = "2"
        }
        if (rng=3) {
          game.fishname = "electric eel"
          game.fishprice = "2"
        }
        if (rng=4) {
          game.fishname = "lionfish"
          game.fishprice = "5"
        }
        if (rng=5) {
          game.fishname = "flying fish"
          game.fishprice = "6"
        }
        if (rng=6) {
          game.fishname = "swordfish"
          game.fishprice = "20"
        }
        if (rng=7) {
          game.fishname = "mirror carp"
          game.fishprice = "50"
        }
        if (rng=8) {
          game.fishname = "slippery snook"
          game.fishprice = "0"
        }
        if (rng=9) {
          game.fishname = "jellyfish"
          game.fishprice = "2"
        }
        if (rng=10) {
          game.fishname = "gigagoldfish"
          game.fishprice = "40"
        }
        if (rng=11) {
          game.fishname = "mystery mackerel"
          game.fishprice = "1"
        }
        if (rng=12) {
          game.fishname = "time trout"
          game.fishprice = "2"
        }
        if (rng=13) {
          game.fishname = "flaming fin"
          game.fishprice = "4"
        }
        if (rng=14) {
          game.fishname = "piranha"
          game.fishprice = "5"
        }
        if (rng=15) {
          game.fishname = "bananafish"
          game.fishprice = "10"
        }
        if (rng=16) {
          game.fishname = "axolotl"
          game.fishprice = "22"
        }
        if (rng=17) {
          game.fishname = "betta fish"
          game.fishprice = "0"
        }
        if (rng=18) {
          game.fishname = "discus fish"
          game.fishprice = "8"
        }
        if (rng=19) {
          game.fishname = "sea dragon"
          game.fishprice = "30"
        }
        if (rng=20) {
          game.fishname = "moon jellyfish"
          game.fishprice = "40"
        }
        if (rng=21) {
          game.fishname = "koi"
          game.fishprice = "2"
        }
        if (rng=22) {
          game.fishname = "thunder crayfish"
          game.fishprice = "3"
        }
        if (rng=23) {
          game.fishname = "mandarin fish"
          game.fishprice = "1"
        }
        if (rng=24) {
          game.fishname = "dwarf pufferfish"
          game.fishprice = "1"
        }
        if (rng=25) {
          game.fishname = "peacock mantis shrimp"
          game.fishprice = "19"
        }
        if (rng=26) {
          game.fishname = "fire shrimp"
          game.fishprice = "1"
        }
        if (rng=27) {
          game.fishname = "fancy snail"
          game.fishprice = "0"
        }
        if (rng=28) {
          game.fishname = "african dwarf frog"
          game.fishprice = "2"
        }
        if (rng=29) {
          game.fishname = "angelfish"
          game.fishprice = "4"
        }
        if (rng=30) {
          game.fishname = "lobster"
          game.fishprice = "6"
        }
        if (rng=31) {
          game.fishname = "datastream darter"
          game.fishprice = "20"
        }
        if (rng=32) {
          game.fishname = "neon ripplefish"
          game.fishprice = "11"
        }
        if (rng=33) {
          game.fishname = "chromeback salmon"
          game.fishprice = "15"
        }
        if (rng=34) {
          game.fishname = "solar sailfish"
          game.fishprice = "16"
        }
        if (rng=35) {
          game.fishname = "hypercurrent eel"
          game.fishprice = "25"
        }
        if (rng=36) {
          game.fishname = "plasma pike"
          game.fishprice = "50"
        }
        if (rng=37) {
          game.fishname = "bio-luminescent leviathan"
          game.fishprice = "100"
        }
        if (rng=38) {
          game.fishname = "magnetic manta"
          game.fishprice = "40"
        }
        if (rng=39) {
          game.fishname = "hydrodynamic hologram"
          game.fishprice = "2"
        }
        if (rng=40) {
          game.fishname = "quantum quagga"
          game.fishprice = "60"
        }
        if (RandomChance(11)) {
          fish.alias = ""+game.fishname
          fish.price = ""+game.fishprice
          CloneObjectAndMoveHere (fish)
          game.createdobjs = game.createdobjs+1
        }
        else {
          foreach (object, GetDirectChildren (game.pov.parent)) {
            if (object.alias = ""+game.fishname) {
              object.parent = null
              game.delobjs = game.delobjs+1
            }
          }
        }
      }
      game.timerx = game.timerx+1
      msg ("Seconds passed: "+game.timerx+" objects created: "+game.createdobjs+ " objects deleted: "+game.createdobjs)
    </script>
  </timer>
  <timer name="fish timer2">
    <interval>1</interval>
    <enabled />
    <script>
      for (repeat, 1, 40, 1) {
        rng = GetRandomInt(1,40)
        if (rng=1) {
          game.fishname = "largemouth bass"
          game.fishprice = "3"
        }
        if (rng=2) {
          game.fishname = "trout"
          game.fishprice = "0"
        }
        if (rng=3) {
          game.fishname = "bluegill"
          game.fishprice = "1"
        }
        if (rng=4) {
          game.fishname = "catfish"
          game.fishprice = "1"
        }
        if (rng=5) {
          game.fishname = "salmon"
          game.fishprice = "8"
        }
        if (rng=6) {
          game.fishname = "northern pike"
          game.fishprice = "11"
        }
        if (rng=7) {
          game.fishname = "perch"
          game.fishprice = "2"
        }
        if (rng=8) {
          game.fishname = "striped bass"
          game.fishprice = "3"
        }
        if (rng=9) {
          game.fishname = "crabfish"
          game.fishprice = "4"
        }
        if (rng=10) {
          game.fishname = "mini squid"
          game.fishprice = "6"
        }
        if (rng=11) {
          game.fishname = "mystery tuna"
          game.fishprice = "0"
        }
        if (rng=12) {
          game.fishname = "time cod"
          game.fishprice = "0"
        }
        if (rng=13) {
          game.fishname = "freezing fin"
          game.fishprice = "1"
        }
        if (rng=14) {
          game.fishname = "firetail tetra"
          game.fishprice = "2"
        }
        if (rng=15) {
          game.fishname = "golden perch"
          game.fishprice = "10"
        }
        if (rng=16) {
          game.fishname = "emerald goby"
          game.fishprice = "22"
        }
        if (rng=17) {
          game.fishname = "rainbow darter"
          game.fishprice = "7"
        }
        if (rng=18) {
          game.fishname = "sapphire cichlid"
          game.fishprice = "18"
        }
        if (rng=19) {
          game.fishname = "platinum piranha"
          game.fishprice = "15"
        }
        if (rng=20) {
          game.fishname = "diamond guppy"
          game.fishprice = "20"
        }
        if (rng=21) {
          game.fishname = "orange koi"
          game.fishprice = "10"
        }
        if (rng=22) {
          game.fishname = "ruby redfish"
          game.fishprice = "4"
        }
        if (rng=23) {
          game.fishname = "england fish"
          game.fishprice = "0"
        }
        if (rng=24) {
          game.fishname = "spiky pufferfish"
          game.fishprice = "0"
        }
        if (rng=25) {
          game.fishname = "raining tree shrimp"
          game.fishprice = "0"
        }
        if (rng=26) {
          game.fishname = "yellow shrimp"
          game.fishprice = "0"
        }
        if (rng=27) {
          game.fishname = "nerite snail"
          game.fishprice = "0"
        }
        if (rng=28) {
          game.fishname = "blue dart frog"
          game.fishprice = "1"
        }
        if (rng=29) {
          game.fishname = "angelic fin"
          game.fishprice = "14"
        }
        if (rng=30) {
          game.fishname = "giant lobster"
          game.fishprice = "6"
        }
        if (rng=31) {
          game.fishname = "streaming nova"
          game.fishprice = "12"
        }
        if (rng=32) {
          game.fishname = "tetra ripplefish"
          game.fishprice = "14"
        }
        if (rng=33) {
          game.fishname = "dragon eye"
          game.fishprice = "16"
        }
        if (rng=34) {
          game.fishname = "sailing fin"
          game.fishprice = "19"
        }
        if (rng=35) {
          game.fishname = "thunderous snake"
          game.fishprice = "2"
        }
        if (rng=36) {
          game.fishname = "crazy fish"
          game.fishprice = "0"
        }
        if (rng=37) {
          game.fishname = "bio-luminescent pike"
          game.fishprice = "50"
        }
        if (rng=38) {
          game.fishname = "tortoise manta"
          game.fishprice = "10"
        }
        if (rng=39) {
          game.fishname = "weather eel"
          game.fishprice = "20"
        }
        if (rng=40) {
          game.fishname = "sister lullaby"
          game.fishprice = "20"
        }
        if (RandomChance(11)) {
          fish.alias = ""+game.fishname
          fish.price = ""+game.fishprice
          CloneObjectAndMoveHere (fish)
          game.createdobjs = game.createdobjs+1
        }
        else {
          foreach (object, GetDirectChildren (game.pov.parent)) {
            if (object.alias = ""+game.fishname) {
              object.parent = null
              game.delobjs = game.delobjs+1
            }
          }
        }
      }
    </script>
  </timer>
</asl>

Your 6.11pm fish timer did not work until I realized I have to change the catch fish verb to turning fishes invisible instead of deleting them, it works now

With some AI explanation I can finally understand how your 6.11pm code works, and it is just the short kind of code I need

Random fish name generator modification into your code would probably look like this

obj.alias1 = PickOneString ("bioluminescence;double-tailed;herring;goldfish;rare;deep sea")
obj.alias2 = PickOneString ("leviathan;koi;dragon;giant;cod;carp")
obj.alias = obj.alias1+ " " +obj.alias2

And the price would be probably be from both fishes prices added together or multiplied


I probably dun understand background scope script, but it does not seems too interesting for me, hiding stuffs in dictionaries or in other rooms just messes with my brain logic, and I can't really tell what is going on easily

Infinite fishing maze demonstration is available at
https://textadventures.co.uk/games/view/wyxv0ib9jkopqyza1nhsww/v2-infinite-fishing-maze-2021
This game is used for coding practice ground, therefore new errors may appear

I understand this demo have errors, It will be easier to apply 6.11pm fish timer on a whole new game


Edit: The errors for this game stop appearing even if I increase to 10 fishes, this is just so confusing

Infinite fishing maze code

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Infinite Maze Redo 1">
    <gameid>6b54aba7-6a1c-492f-bbcc-59999b7289ae</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
    <x type="int">0</x>
    <y type="int">0</y>
    <direction type="int">0</direction>
    <attr name="slim corner" type="int">0</attr>
    <attr name="hide x y" type="int">0</attr>
    <attr name="hide slim corner" type="int">0</attr>
    <gridmap type="boolean">false</gridmap>
    <showmoney />
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <exit name="roomnorth" alias="north" to="room north">
      <inherit name="northdirection" />
      <runscript />
      <script type="script">
        game.y = game.y+1
        game.direction = 1
        All Functions
      </script>
    </exit>
    <exit name="roomsouth" alias="south" to="room south">
      <inherit name="southdirection" />
      <runscript />
      <script type="script">
        game.y = game.y-1
        game.direction = 2
        All Functions
      </script>
    </exit>
    <exit name="roomeast" alias="east" to="room east">
      <inherit name="eastdirection" />
      <runscript />
      <script type="script">
        game.x = game.x+1
        game.direction = 3
        All Functions
      </script>
    </exit>
    <exit name="roomwest" alias="west" to="room west">
      <inherit name="westdirection" />
      <runscript />
      <script type="script">
        game.x = game.x-1
        game.direction = 4
        All Functions
      </script>
    </exit>
    <object name="Time Monster Pet">
      <inherit name="editor_object" />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <take />
      <look>Interesting hybrid of a machine and a living organism.</look>
      <hidexycoordinates type="script">
        if (game.hide x y=1) {
          game.hide x y = 0
          msg ("x y shown.")
        }
        else {
          game.hide x y = 1
          msg ("x y hidden.")
        }
      </hidexycoordinates>
      <clearscreen type="script">
        ClearScreen
      </clearscreen>
      <unhideslimcorner type="script">
        thischair = CloneObjectAndMoveHere (Chair)
        thischair.x = game.x
        thischair.y = game.y
      </unhideslimcorner>
    </object>
    <object name="mrangel">
      <inherit name="editor_object" />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
      <look>This game is made with codes from mrangel</look>
    </object>
    <object name="DarkLizerd">
      <inherit name="editor_object" />
      <usestandardverblist type="boolean">false</usestandardverblist>
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <displayverbs type="stringlist">
        <value>Take</value>
      </displayverbs>
      <take />
    </object>
    <object name="foxrain4">
      <inherit name="editor_object" />
      <visible />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <look>Errors: I am aware there could be errors, this is a coding practice ground for me, if you have any fixes, let me know directly</look>
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
    </object>
  </object>
  <object name="room north">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="south" to="room">
      <inherit name="southdirection" />
    </exit>
  </object>
  <object name="room south">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="north" to="room">
      <inherit name="northdirection" />
    </exit>
  </object>
  <object name="room east">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="west" to="room">
      <inherit name="westdirection" />
    </exit>
  </object>
  <object name="room west">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="east" to="room">
      <inherit name="eastdirection" />
    </exit>
  </object>
  <object name="Dungeon Items">
    <inherit name="editor_room" />
    <object name="Floor">
      <inherit name="editor_object" />
      <useindividualverblist />
      <visible type="boolean">false</visible>
      <alias>Seabed</alias>
    </object>
    <object name="Chair">
      <inherit name="editor_object" />
      <useindividualverblist />
      <fishlist type="string"></fishlist>
      <alias>Shadow</alias>
      <catch type="script">
        msg ("You caught a "+this.alias)
        msg ("$"+this.price+ " have been added.")
        add = this.price
        player.money = player.money + add
        this.visible = false
      </catch>
    </object>
    <object name="Top Hedge Maze">
      <inherit name="editor_object" />
      <alias>↑ coral reef</alias>
    </object>
    <object name="Bottom Hedge Maze">
      <inherit name="editor_object" />
      <alias>↓ coral reef</alias>
    </object>
    <object name="Right Hedge Maze">
      <inherit name="editor_object" />
      <alias>→ coral reef</alias>
    </object>
    <object name="Left Hedge Maze">
      <inherit name="editor_object" />
      <alias>← coral reef</alias>
    </object>
    <object name="Exit">
      <inherit name="editor_object" />
      <info>Once you click it, it is game over, make sure to save beforehand if you still want to continue.</info>
      <useindividualverblist />
      <clickit type="script">
        msg ("Congratulations, you found the exit!")
        finish
      </clickit>
    </object>
  </object>
  <verb>
    <property>hidexycoordinates</property>
    <pattern>hide x y coordinates</pattern>
    <defaultexpression>"You can't hide x y coordinates " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>hideslimcorner</property>
    <pattern>hide slim corner</pattern>
    <defaultexpression>"You can't hide slim corner " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>clearscreen</property>
    <pattern>clear screen</pattern>
    <defaultexpression>"You can't clear screen " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>info</property>
    <pattern>info</pattern>
    <defaultexpression>"You can't info " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>exit</property>
    <pattern>exit</pattern>
    <defaultexpression>"You can't exit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>clickit</property>
    <pattern>click it</pattern>
    <defaultexpression>"You can't click it " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>catch</property>
    <pattern>catch</pattern>
    <defaultexpression>"You can't catch " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>unhideslimcorner</property>
    <pattern>unhide slim corner</pattern>
    <defaultexpression>"You can't unhide slim corner " + object.article + "."</defaultexpression>
  </verb>
  <function name="All Functions">
    if (game.hide x y=0) {
      msg ("X: "+game.x+" Y: "+game.y)
    }
    Enter Room
    Inventory Drop
    Hide Show Exits
    if (RandomChance(20)) {
      ClearScreen
    }
  </function>
  <function name="Enter Room">
    Hide Show Objects
    floorlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Floor)
    floorlist = FilterByAttribute (floorlist, "visible", true)
    if (ListCount (floorlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      thisfloor = CloneObjectAndMoveHere (Floor)
      thisfloor.x = game.x
      thisfloor.y = game.y
      Auto Generation
      Slim Corner
    }
  </function>
  <function name="Auto Generation"><![CDATA[
    if (RandomChance(10)) {
      rng = GetRandomInt(1,5)
      for (i, 1, rng, 1) {
        thischair = CloneObjectAndMoveHere (Chair)
        thischair.x = game.x
        thischair.y = game.y
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>2) {
        thistopmaze = CloneObjectAndMoveHere (Top Hedge Maze)
        thistopmaze.x = game.x
        thistopmaze.y = game.y
        thistopmaze2 = CloneObjectAndMoveHere (Bottom Hedge Maze)
        thistopmaze2.x = game.x
        thistopmaze2.y = game.y+1
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>1) {
        thisbottommaze = CloneObjectAndMoveHere (Bottom Hedge Maze)
        thisbottommaze.x = game.x
        thisbottommaze.y = game.y
        thisbottommaze2 = CloneObjectAndMoveHere (Top Hedge Maze)
        thisbottommaze2.x = game.x
        thisbottommaze2.y = game.y-1
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>4) {
        thisrightmaze = CloneObjectAndMoveHere (Right Hedge Maze)
        thisrightmaze.x = game.x
        thisrightmaze.y = game.y
        thisrightmaze2 = CloneObjectAndMoveHere (Left Hedge Maze)
        thisrightmaze2.x = game.x+1
        thisrightmaze2.y = game.y
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>3) {
        thisleftmaze = CloneObjectAndMoveHere (Left Hedge Maze)
        thisleftmaze.x = game.x
        thisleftmaze.y = game.y
        thisleftmaze2 = CloneObjectAndMoveHere (Right Hedge Maze)
        thisleftmaze2.x = game.x-1
        thisleftmaze2.y = game.y
        Hide Show Objects
      }
    }
    if (RandomChance(1)) {
      if (RandomChance(1)) {
        thisexit = CloneObjectAndMoveHere (Exit)
        thisexit.x = game.x
        thisexit.y = game.y
      }
    }
  ]]></function>
  <function name="Hide Show Exits">
    // Hide Top Maze
    mazetoplist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Top Hedge Maze)
    mazetoplist = FilterByAttribute (mazetoplist, "visible", true)
    if (ListCount (mazetoplist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomnorth)
    }
    else {
      MakeExitInvisible (roomnorth)
    }
    // Hide Bottom Maze
    mazebottomlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Bottom Hedge Maze)
    mazebottomlist = FilterByAttribute (mazebottomlist, "visible", true)
    if (ListCount (mazebottomlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomsouth)
    }
    else {
      MakeExitInvisible (roomsouth)
    }
    // Hide Right Maze
    mazerightlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Right Hedge Maze)
    mazerightlist = FilterByAttribute (mazerightlist, "visible", true)
    if (ListCount (mazerightlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomeast)
    }
    else {
      MakeExitInvisible (roomeast)
    }
    // Hide Left Maze
    mazeleftlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Left Hedge Maze)
    mazeleftlist = FilterByAttribute (mazeleftlist, "visible", true)
    if (ListCount (mazeleftlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomwest)
    }
    else {
      MakeExitInvisible (roomwest)
    }
  </function>
  <function name="Hide Show Objects">
    foreach (object, GetDirectChildren (room)) {
      if (HasInt (object, "x") and HasInt (object, "y") and not Contains (game.pov, object)) {
        object.visible = (object.x = game.x and object.y = game.y)
      }
    }
  </function>
  <function name="Inventory Drop">
    foreach (object, ScopeInventory()) {
      object.x = game.x
      object.y = game.y
    }
  </function>
  <function name="Slim Corner"><![CDATA[
    game.slim corner = game.slim corner+3
    if (game.slim corner>40) {
      game.slim corner = 0
    }
    if (game.hide slim corner=1) {
      msg ("slim corner: "+game.slim corner)
    }
  ]]></function>
  <timer name="fish timer1">
    <interval>1</interval>
    <enabled />
    <script>
      foreach (objectx, GetDirectChildren(game.pov.parent)) {
        if (HasAttribute(objectx, "fishlist")) {
          objectx.alias1 = PickOneString ("Silver;Golden;Coral;Pearl;Crystal;Emerald;Ruby;Sapphire;Diamond;Obsidian;Abyssal;Leviathan;Hydra;Kraken;Merman;Naga;Phoenix;Thunder;Stormy;Frostbite;Venomous;Spectral;Ancient;Mystic;Celestial;Phantom;Gilded;Enchanted;Glittering;Shadow;Luminous;Radiant;Thundering;Sea;Dreamy;Whispering;Starlight;Moonlit;Sunken;Pirate's;Mermaid's;Atlantis;Davy Jones';Neptune's;Poseidon's;Kraken's;Siren's;Enchanted;Coral;Sea Dragon's;Ghostly;Treasure;Pirate's;Mermaid's;Davy Jones';Neptune's;Poseidon's;Kraken's;Siren's;Enchanted;Coral;Sea Dragon's;Ghostly;Treasure;Abyssal;Leviathan's;Sunken;Coral;Pirate's;Mermaid's;Davy Jones';Neptune's;Poseidon's;Kraken's;Siren's;Enchanted;Coral;Sea Dragon's;Ghostly;Treasure;Sea;Pirate;Mermaid;Davy Jones';Neptune's;Poseidon's")
          objectx.alias2 = PickOneString ("Sardine;Grouper;Crab;Oyster;Shrimp;Eel;Ray;Squid;Dolphin;Octopus;Anglerfish;Lobster;Haddock;Kingfish;Marlin;Nautilus;Fish;Trout;Shark;Barracuda;Viperfish;Swordfish;Ammonite;Manta;Clownfish;Piranha;Guppy;Eel;Goby;Shark;Lionfish;Remora;Tuna;Serpent;Dugong;Whelk;Seahorse;Minnow;Treasure;Plunder;Mirror;Artifact;Locker;Necklace;Trident;Crown;Song;Pearl;Crown;Scale;Galleon;Trove;Abyss;Lair;Fish;Castle;Cove;Lagoon;Depths;Nook;Palace;Keep;Sanctuary;Cavern;Cave;Den;Graveyard;Hunter;Scoundrel;Captain;Queen;Curse;Champion;Protege;Slayer;Temptation;Enigma;Crusader;Rider;Guardian;Golem;Sorcerer;Parrot;Minstrel;Disciple;Navigator;Poseur;Keeper;Serenade;Entourage;Conqueror;Sorceress;Gaoler;Thief;Shaman;Pet;Mate;Doppelganger;Nemesis;Pupil")
          objectx.alias = objectx.alias1+ " " +objectx.alias2
          objectx.price = GetRandomInt(1,200)
          if (RandomChance(10)) {
            MakeObjectInvisible (objectx)
          }
        }
      }
    </script>
  </timer>
</asl>

I failed to implement some of the 6.11pm fish timer into this practice game

  1. Infinite maze do not have rooms, it uses pseudo rooms instead
  2. I tried to turn chair into fish spawn with alias ocean current, when player sees ocean current object, the fish timer turns fishes visible, however this code failed because the ocean current (Chair object) is cloned, and I am targeting the original Chair prototype and not the new cloned Chair with a different name
  3. If I can target the original Chair or uses alternative methods, I can directly spawn 10 fishes at start of game, turning them visible whenever ocean current (Cloned Chair object) is seen in a room

Update: Fish spawner has been added
This successfully implements most of 6.11pm mrangel fish timer logic into infinite maze,
yes, this means there are only 10 fishes, no matter how far you travel in this super big maze,
this means objects will not accumulate over time and create errors

Currently, this game still have very rare errors, I thought it was showhide fish function, but because the errors happens even when ocean current are not seen (Which makes fishes visible), makes me realize that it is still the fish timer's fault, because the fish timer runs irregardless of whether ocean current has appeared or not

To me, this is a small error, as it will will not accumulate objects over time and making the game laggier and laggier as I do intend to make big games with many rooms

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Infinite Maze Redo 1">
    <gameid>6b54aba7-6a1c-492f-bbcc-59999b7289ae</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
    <x type="int">0</x>
    <y type="int">0</y>
    <direction type="int">0</direction>
    <attr name="slim corner" type="int">0</attr>
    <attr name="hide x y" type="int">0</attr>
    <attr name="hide slim corner" type="int">0</attr>
    <gridmap type="boolean">false</gridmap>
    <showmoney />
    <activate type="int">0</activate>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <enter type="script">
      for (i, 1, 10, 1) {
        CloneObjectAndMove (Fish, game.pov.parent)
      }
    </enter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <exit name="roomnorth" alias="north" to="room north">
      <inherit name="northdirection" />
      <runscript />
      <script type="script">
        game.y = game.y+1
        game.direction = 1
        All Functions
      </script>
    </exit>
    <exit name="roomsouth" alias="south" to="room south">
      <inherit name="southdirection" />
      <runscript />
      <script type="script">
        game.y = game.y-1
        game.direction = 2
        All Functions
      </script>
    </exit>
    <exit name="roomeast" alias="east" to="room east">
      <inherit name="eastdirection" />
      <runscript />
      <script type="script">
        game.x = game.x+1
        game.direction = 3
        All Functions
      </script>
    </exit>
    <exit name="roomwest" alias="west" to="room west">
      <inherit name="westdirection" />
      <runscript />
      <script type="script">
        game.x = game.x-1
        game.direction = 4
        All Functions
      </script>
    </exit>
    <object name="Time Monster Pet">
      <inherit name="editor_object" />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <take />
      <look>Interesting hybrid of a machine and a living organism.</look>
      <hidexycoordinates type="script">
        if (game.hide x y=1) {
          game.hide x y = 0
          msg ("x y shown.")
        }
        else {
          game.hide x y = 1
          msg ("x y hidden.")
        }
      </hidexycoordinates>
      <clearscreen type="script">
        ClearScreen
      </clearscreen>
      <unhideslimcorner type="script">
        thischair = CloneObjectAndMoveHere (Chair)
        thischair.x = game.x
        thischair.y = game.y
      </unhideslimcorner>
    </object>
    <object name="mrangel">
      <inherit name="editor_object" />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
      <look>This game is made with codes from mrangel</look>
    </object>
    <object name="DarkLizerd">
      <inherit name="editor_object" />
      <usestandardverblist type="boolean">false</usestandardverblist>
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <displayverbs type="stringlist">
        <value>Take</value>
      </displayverbs>
      <take />
    </object>
    <object name="foxrain4">
      <inherit name="editor_object" />
      <visible />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <look>Errors: I am aware there could be errors, this is a coding practice ground for me, if you have any fixes, let me know directly</look>
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
    </object>
  </object>
  <object name="room north">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="south" to="room">
      <inherit name="southdirection" />
    </exit>
  </object>
  <object name="room south">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="north" to="room">
      <inherit name="northdirection" />
    </exit>
  </object>
  <object name="room east">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="west" to="room">
      <inherit name="westdirection" />
    </exit>
  </object>
  <object name="room west">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="east" to="room">
      <inherit name="eastdirection" />
    </exit>
  </object>
  <object name="Dungeon Items">
    <inherit name="editor_room" />
    <object name="Floor">
      <inherit name="editor_object" />
      <useindividualverblist />
      <visible type="boolean">false</visible>
      <alias>Seabed</alias>
    </object>
    <object name="Chair">
      <inherit name="editor_object" />
      <useindividualverblist />
      <alias>Ocean current</alias>
      <fishnumber type="int">0</fishnumber>
      <isafishspawner type="string"></isafishspawner>
    </object>
    <object name="Top Hedge Maze">
      <inherit name="editor_object" />
      <alias>↑ coral reef</alias>
    </object>
    <object name="Bottom Hedge Maze">
      <inherit name="editor_object" />
      <alias>↓ coral reef</alias>
    </object>
    <object name="Right Hedge Maze">
      <inherit name="editor_object" />
      <alias>→ coral reef</alias>
    </object>
    <object name="Left Hedge Maze">
      <inherit name="editor_object" />
      <alias>← coral reef</alias>
    </object>
    <object name="Exit">
      <inherit name="editor_object" />
      <info>Once you click it, it is game over, make sure to save beforehand if you still want to continue.</info>
      <useindividualverblist />
      <clickit type="script">
        msg ("Congratulations, you found the exit!")
        finish
      </clickit>
    </object>
    <object name="Fish">
      <inherit name="editor_object" />
      <catch type="script">
        msg ("You caught a "+this.alias)
        msg ("$"+this.price+ " have been added.")
        add = this.price
        player.money = player.money + add
        this.visible = false
      </catch>
      <isafish type="string"></isafish>
      <visible type="boolean">false</visible>
      <displayverbs type="stringlist" />
    </object>
  </object>
  <verb>
    <property>hidexycoordinates</property>
    <pattern>hide x y coordinates</pattern>
    <defaultexpression>"You can't hide x y coordinates " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>hideslimcorner</property>
    <pattern>hide slim corner</pattern>
    <defaultexpression>"You can't hide slim corner " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>clearscreen</property>
    <pattern>clear screen</pattern>
    <defaultexpression>"You can't clear screen " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>info</property>
    <pattern>info</pattern>
    <defaultexpression>"You can't info " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>exit</property>
    <pattern>exit</pattern>
    <defaultexpression>"You can't exit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>clickit</property>
    <pattern>click it</pattern>
    <defaultexpression>"You can't click it " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>catch</property>
    <pattern>catch</pattern>
    <defaultexpression>"You can't catch " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>unhideslimcorner</property>
    <pattern>unhide slim corner</pattern>
    <defaultexpression>"You can't unhide slim corner " + object.article + "."</defaultexpression>
  </verb>
  <function name="All Functions">
    if (game.hide x y=0) {
      msg ("X: "+game.x+" Y: "+game.y)
    }
    Enter Room
    Inventory Drop
    Hide Show Exits
    Hide Show Fishes
    if (RandomChance(20)) {
      ClearScreen
    }
  </function>
  <function name="Enter Room">
    Hide Show Objects
    floorlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Floor)
    floorlist = FilterByAttribute (floorlist, "visible", true)
    if (ListCount (floorlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      thisfloor = CloneObjectAndMoveHere (Floor)
      thisfloor.x = game.x
      thisfloor.y = game.y
      Auto Generation
      Slim Corner
    }
  </function>
  <function name="Auto Generation"><![CDATA[
    if (RandomChance(10)) {
      thischair = CloneObjectAndMoveHere (Chair)
      thischair.x = game.x
      thischair.y = game.y
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>2) {
        thistopmaze = CloneObjectAndMoveHere (Top Hedge Maze)
        thistopmaze.x = game.x
        thistopmaze.y = game.y
        thistopmaze2 = CloneObjectAndMoveHere (Bottom Hedge Maze)
        thistopmaze2.x = game.x
        thistopmaze2.y = game.y+1
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>1) {
        thisbottommaze = CloneObjectAndMoveHere (Bottom Hedge Maze)
        thisbottommaze.x = game.x
        thisbottommaze.y = game.y
        thisbottommaze2 = CloneObjectAndMoveHere (Top Hedge Maze)
        thisbottommaze2.x = game.x
        thisbottommaze2.y = game.y-1
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>4) {
        thisrightmaze = CloneObjectAndMoveHere (Right Hedge Maze)
        thisrightmaze.x = game.x
        thisrightmaze.y = game.y
        thisrightmaze2 = CloneObjectAndMoveHere (Left Hedge Maze)
        thisrightmaze2.x = game.x+1
        thisrightmaze2.y = game.y
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>3) {
        thisleftmaze = CloneObjectAndMoveHere (Left Hedge Maze)
        thisleftmaze.x = game.x
        thisleftmaze.y = game.y
        thisleftmaze2 = CloneObjectAndMoveHere (Right Hedge Maze)
        thisleftmaze2.x = game.x-1
        thisleftmaze2.y = game.y
        Hide Show Objects
      }
    }
    if (RandomChance(1)) {
      if (RandomChance(1)) {
        thisexit = CloneObjectAndMoveHere (Exit)
        thisexit.x = game.x
        thisexit.y = game.y
      }
    }
  ]]></function>
  <function name="Hide Show Exits">
    // Hide Top Maze
    mazetoplist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Top Hedge Maze)
    mazetoplist = FilterByAttribute (mazetoplist, "visible", true)
    if (ListCount (mazetoplist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomnorth)
    }
    else {
      MakeExitInvisible (roomnorth)
    }
    // Hide Bottom Maze
    mazebottomlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Bottom Hedge Maze)
    mazebottomlist = FilterByAttribute (mazebottomlist, "visible", true)
    if (ListCount (mazebottomlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomsouth)
    }
    else {
      MakeExitInvisible (roomsouth)
    }
    // Hide Right Maze
    mazerightlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Right Hedge Maze)
    mazerightlist = FilterByAttribute (mazerightlist, "visible", true)
    if (ListCount (mazerightlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomeast)
    }
    else {
      MakeExitInvisible (roomeast)
    }
    // Hide Left Maze
    mazeleftlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Left Hedge Maze)
    mazeleftlist = FilterByAttribute (mazeleftlist, "visible", true)
    if (ListCount (mazeleftlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomwest)
    }
    else {
      MakeExitInvisible (roomwest)
    }
  </function>
  <function name="Hide Show Objects">
    foreach (object, GetDirectChildren (room)) {
      if (HasInt (object, "x") and HasInt (object, "y") and not Contains (game.pov, object)) {
        object.visible = (object.x = game.x and object.y = game.y)
      }
    }
  </function>
  <function name="Inventory Drop">
    foreach (object, ScopeInventory()) {
      object.x = game.x
      object.y = game.y
    }
  </function>
  <function name="Slim Corner"><![CDATA[
    game.slim corner = game.slim corner+3
    if (game.slim corner>40) {
      game.slim corner = 0
    }
    if (game.hide slim corner=1) {
      msg ("slim corner: "+game.slim corner)
    }
  ]]></function>
  <function name="Hide Show Fishes"><![CDATA[
    game.activate = 0
    foreach (findchair, GetDirectChildren (game.pov.parent)) {
      if (findchair.alias="Ocean current") {
        if (findchair.visible=true) {
          game.activate = game.activate+1
        }
      }
    }
    if (game.activate>0) {
      rng = GetRandomInt(1,5)
      for (i, 1, 5, 1) {
        if (RandomChance(10)) {
          rng = rng+1
        }
      }
      foreach (showfishes, GetDirectChildren (game.pov.parent)) {
        if (HasAttribute(showfishes, "isafish")) {
          if (rng>0) {
            rng = rng-1
            showfishes.visible = true
          }
        }
      }
    }
    else {
      foreach (hidefishes, GetDirectChildren (game.pov.parent)) {
        if (HasAttribute(hidefishes, "isafish")) {
          hidefishes.visible = false
        }
      }
    }
  ]]></function>
  <timer name="fish timer1">
    <interval>1</interval>
    <enabled />
    <script>
      foreach (objectx, GetDirectChildren(game.pov.parent)) {
        if (HasAttribute(objectx, "isafish")) {
          objectx.alias1 = PickOneString ("Silver;Golden;Coral;Pearl;Crystal;Emerald;Ruby;Sapphire;Diamond;Obsidian;Abyssal;Leviathan;Hydra;Kraken;Merman;Naga;Phoenix;Thunder;Stormy;Frostbite;Venomous;Spectral;Ancient;Mystic;Celestial;Phantom;Gilded;Enchanted;Glittering;Shadow;Luminous;Radiant;Thundering;Sea;Dreamy;Whispering;Starlight;Moonlit;Sunken;Pirate's;Mermaid's;Atlantis;Davy Jones';Neptune's;Poseidon's;Kraken's;Siren's;Enchanted;Coral;Sea Dragon's;Ghostly;Treasure;Pirate's;Mermaid's;Davy Jones';Neptune's;Poseidon's;Kraken's;Siren's;Enchanted;Coral;Sea Dragon's;Ghostly;Treasure;Abyssal;Leviathan's;Sunken;Coral;Pirate's;Mermaid's;Davy Jones';Neptune's;Poseidon's;Kraken's;Siren's;Enchanted;Coral;Sea Dragon's;Ghostly;Treasure;Sea;Pirate;Mermaid;Davy Jones';Neptune's;Poseidon's")
          objectx.alias2 = PickOneString ("Sardine;Grouper;Crab;Oyster;Shrimp;Eel;Ray;Squid;Dolphin;Octopus;Anglerfish;Lobster;Haddock;Kingfish;Marlin;Nautilus;Fish;Trout;Shark;Barracuda;Viperfish;Swordfish;Ammonite;Manta;Clownfish;Piranha;Guppy;Eel;Goby;Shark;Lionfish;Remora;Tuna;Serpent;Dugong;Whelk;Seahorse;Minnow;Treasure;Plunder;Mirror;Artifact;Locker;Necklace;Trident;Crown;Song;Pearl;Crown;Scale;Galleon;Trove;Abyss;Lair;Fish;Castle;Cove;Lagoon;Depths;Nook;Palace;Keep;Sanctuary;Cavern;Cave;Den;Graveyard;Hunter;Scoundrel;Captain;Queen;Curse;Champion;Protege;Slayer;Temptation;Enigma;Crusader;Rider;Guardian;Golem;Sorcerer;Parrot;Minstrel;Disciple;Navigator;Poseur;Keeper;Serenade;Entourage;Conqueror;Sorceress;Gaoler;Thief;Shaman;Pet;Mate;Doppelganger;Nemesis;Pupil")
          objectx.alias = objectx.alias1+ " " +objectx.alias2
          objectx.price = GetRandomInt(1,200)
          if (RandomChance(10)) {
            MakeObjectInvisible (objectx)
          }
        }
      }
    </script>
  </timer>
</asl>

Someone asked for the latest version of v2 Infinite fishing maze (2021)

I have short term memory, so I dunno whats the difference, but here is is
Also, one issue I remember about this latest version of Infinite fishing maze is about the name generators
Well you see, if you have 100 first names x 100 second names to generate 10,000 scenery objects or fish objects

But it is a hassle to write, so yeah yeah, you get what I mean, I cheated, I used AI to write the 300 first names x 300 second names which leads to an unique issue, the scenery names and fishes names might not be interesting or makes sense, I had spent some time on teaching the AI, but this is pretty much what ended of it, the AI will keep spewing out same names, wrong names, adding numbers making it into a list, tell you another method which does not makes sense

So, if you want to edit this latest fishing maze, I would recommend you to manually change the scenery/fish name generators one word by one word or perhaps to challenge the AI again =D

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Infinite Maze Redo 1">
    <gameid>6b54aba7-6a1c-492f-bbcc-59999b7289ae</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
    <x type="int">0</x>
    <y type="int">0</y>
    <direction type="int">0</direction>
    <attr name="slim corner" type="int">0</attr>
    <attr name="hide x y" type="int">0</attr>
    <attr name="hide slim corner" type="int">0</attr>
    <gridmap type="boolean">false</gridmap>
    <showmoney />
    <activate type="int">0</activate>
    <mazesize type="int">0</mazesize>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <enter type="script">
      for (i, 1, 10, 1) {
        CloneObjectAndMove (Fish, game.pov.parent)
      }
    </enter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <exp type="int">0</exp>
      <object name="Level">
        <inherit name="editor_object" />
        <alias>Level: 1</alias>
      </object>
      <object name="Hard">
        <inherit name="editor_object" />
        <swap type="script"><![CDATA[
          this.slot = this.slot+1
          if (this.slot=4) {
            this.slot = 1
          }
          if (this.slot=1) {
            this.alias = "Hard"
            SetTimerInterval (fish timer1, 1)
            msg ("Fishes are harder to catch now<br/>EXP gained is nonupled (x9)")
          }
          if (this.slot=2) {
            this.alias = "Normal"
            SetTimerInterval (fish timer1, 2)
            msg ("Fishes are normal to catch now<br/>EXP gained is tripled")
          }
          if (this.slot=3) {
            this.alias = "Easy"
            SetTimerInterval (fish timer1, 3)
            msg ("Fishes are easy to catch now<br/>EXP gained is normal")
          }
        ]]></swap>
        <slot type="int">1</slot>
        <displayverbs type="stringlist" />
        <inventoryverbs type="stringlist" />
        <alias>Hard</alias>
      </object>
      <object name="EXP">
        <inherit name="editor_object" />
        <alias>EXP: 0</alias>
      </object>
      <object name="Skill">
        <inherit name="editor_object" />
        <displayverbs type="stringlist" />
        <inventoryverbs type="stringlist">
          <value>Look at</value>
        </inventoryverbs>
        <swap type="script">
          this.slot = this.slot+1
          if (this.slot=4) {
            this.slot = 1
          }
          if (this.slot=1) {
            this.alias = "Luck"
            msg ("Luck increases money gained from catching fishes")
          }
          if (this.slot=2) {
            this.alias = "Stealth"
            msg ("Stealth increases number of fishes/treasures appearing")
          }
          if (this.slot=3) {
            this.alias = "Charisma"
            msg ("Charisma decreases prices of shop items")
          }
        </swap>
        <slot type="int">1</slot>
        <alias>Luck</alias>
        <invest type="script"><![CDATA[
          if (this.alias="Luck") {
            if (Skill.skillpoint>Skill.usedskillpoint) {
              Skill.usedskillpoint = Skill.usedskillpoint+1
              Skill.luck = Skill.luck+1
            }
            else {
              msg ("Not enough")
            }
          }
          if (this.alias="Stealth") {
            if (Skill.skillpoint>Skill.usedskillpoint) {
              Skill.usedskillpoint = Skill.usedskillpoint+1
              Skill.stealth = Skill.stealth+1
            }
            else {
              msg ("Not enough")
            }
          }
          if (this.alias="Charisma") {
            if (Skill.skillpoint>Skill.usedskillpoint) {
              Skill.usedskillpoint = Skill.usedskillpoint+1
              Skill.charisma = Skill.charisma+1
            }
            else {
              msg ("Not enough")
            }
          }
        ]]></invest>
        <resetallskillpoints type="script">
          Skill.usedskillpoint = 0
          Skill.luck = 0
          Skill.stealth = 0
          Skill.charisma = 0
          msg ("Everything has been reseted")
        </resetallskillpoints>
        <skillpoint type="int">0</skillpoint>
        <usedskillpoint type="int">0</usedskillpoint>
        <look type="script">
          Skill.skillpoint = player.exp/100
          msg ("Total skill points: "+Skill.skillpoint)
          msg ("Used skill points: "+Skill.usedskillpoint)
          msg ("")
          msg ("Luck: "+Skill.luck)
          msg ("Stealth: "+Skill.stealth)
          msg ("Charisma: "+Skill.charisma)
        </look>
        <luck type="int">0</luck>
        <stealth type="int">0</stealth>
        <charisma type="int">0</charisma>
      </object>
    </object>
    <exit name="roomnorth" alias="north" to="room north">
      <inherit name="northdirection" />
      <runscript />
      <script type="script">
        game.y = game.y+1
        game.direction = 1
        All Functions
      </script>
    </exit>
    <exit name="roomsouth" alias="south" to="room south">
      <inherit name="southdirection" />
      <runscript />
      <script type="script">
        game.y = game.y-1
        game.direction = 2
        All Functions
      </script>
    </exit>
    <exit name="roomeast" alias="east" to="room east">
      <inherit name="eastdirection" />
      <runscript />
      <script type="script">
        game.x = game.x+1
        game.direction = 3
        All Functions
      </script>
    </exit>
    <exit name="roomwest" alias="west" to="room west">
      <inherit name="westdirection" />
      <runscript />
      <script type="script">
        game.x = game.x-1
        game.direction = 4
        All Functions
      </script>
    </exit>
    <object name="Time Monster Pet">
      <inherit name="editor_object" />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <take />
      <look>Interesting hybrid of a machine and a living organism.</look>
      <hidexycoordinates type="script">
        if (game.hide x y=1) {
          game.hide x y = 0
          msg ("x y shown.")
        }
        else {
          game.hide x y = 1
          msg ("x y hidden.")
        }
      </hidexycoordinates>
      <clearscreen type="script">
        ClearScreen
      </clearscreen>
      <unhideslimcorner type="script">
        thischair = CloneObjectAndMoveHere (Chair)
        thischair.x = game.x
        thischair.y = game.y
      </unhideslimcorner>
    </object>
    <object name="mrangel">
      <inherit name="editor_object" />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
      <look>This game is made with codes from mrangel</look>
    </object>
    <object name="DarkLizerd">
      <inherit name="editor_object" />
      <usestandardverblist type="boolean">false</usestandardverblist>
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <displayverbs type="stringlist">
        <value>Take</value>
      </displayverbs>
      <take />
    </object>
    <object name="foxrain4">
      <inherit name="editor_object" />
      <visible />
      <useindividualverblist type="boolean">false</useindividualverblist>
      <x type="int">0</x>
      <y type="int">0</y>
      <look>Errors: I am aware there could be errors, this is a coding practice ground for me, if you have any fixes, let me know directly</look>
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
    </object>
    <object name="fishy man">
      <inherit name="editor_object" />
      <take />
      <x type="int">0</x>
      <y type="int">0</y>
      <look type="script"><![CDATA[
        msg ("Maze size: "+game.mazesize)
        msg ("Update: v2.1<br/><br/>100% chances of meeting at least 5 fishes/treasures<br/>25% chances of meeting 6 fishes<br/>6.2% chances of meeting 7 fishes<br/>1.5% chances of meeting 8 fishes<br/>0.4% chances of meeting 9 fishes<br/>0.1% chances of meeting 10 fishes<br/><br/>100% chances of getting $1 to $100 from a fish/treasure<br/>50% chances of getting $15 more<br/>25% chances of getting $30 more<br/>12.5% chances of getting $45 more<br/>6.25% chances of getting $60 more<br/>3.125% chances of getting $75 more<br/>_____________________________<br/><br/>Update: v2.2<br/>There are 250 fish first names x 192 fish second names = 48 thousand fish possibilities<br/>There are 100 scenery first names x 100 scenery second names = 10 thousand scenery possibilities<br/>____________________________<br/><br/>Update:v2.3<br/>Easy, normal and hard settings which determines EXP gained from catching fishes<br/>There are 100 shop item first names x 75 shop item second names = 7.5 thousand shop item possibilities<br/>Shop items are available are starting point, no need to dig your way, lol<br/>____________________________<br/><br/>Update:v2.4<br/>Skill is added, we have luck, stealth and charisma<br/>They add minor bonuses and is more helpful for end-game players that have lots of skill points to spend on<br/>Every 100 exp gives you 1 skill point to be spent on<br/>____________________________<br/><br/>Update:v2.5<br/>Guide is here, the shop items at spawn are for you to strategize on how to explore the maze<br/>1. Drop them at no exit routes/ wrong pathways<br/>2. Drop along your longest exit pathway<br/>3. Drop them if there are ocean currents/fishes nearby<br/>____________________________<br/><br/>Update:v2.6<br/>Ocean current/ fish spawner despawns in 30 seconds and respawns in 300 seconds<br/>Shop items names have been updated to use original names rather than names from the fish name generator<br/>Fish names have increased from 100 x 100 to 250 x 192")
      ]]></look>
    </object>
  </object>
  <object name="room north">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="south" to="room">
      <inherit name="southdirection" />
    </exit>
  </object>
  <object name="room south">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="north" to="room">
      <inherit name="northdirection" />
    </exit>
  </object>
  <object name="room east">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="west" to="room">
      <inherit name="westdirection" />
    </exit>
  </object>
  <object name="room west">
    <inherit name="editor_room" />
    <isroom />
    <exit alias="east" to="room">
      <inherit name="eastdirection" />
    </exit>
  </object>
  <object name="Dungeon Items">
    <inherit name="editor_room" />
    <object name="Floor">
      <inherit name="editor_object" />
      <useindividualverblist />
      <visible type="boolean">false</visible>
      <alias>Seabed</alias>
    </object>
    <object name="Chair">
      <inherit name="editor_object" />
      <useindividualverblist />
      <alias>Ocean current</alias>
      <despawn type="boolean">false</despawn>
      <isafishspawner type="string"></isafishspawner>
      <respawn type="boolean">false</respawn>
    </object>
    <object name="Top Hedge Maze">
      <inherit name="editor_object" />
      <alias>↑ coral reef</alias>
    </object>
    <object name="Bottom Hedge Maze">
      <inherit name="editor_object" />
      <alias>↓ coral reef</alias>
    </object>
    <object name="Right Hedge Maze">
      <inherit name="editor_object" />
      <alias>→ coral reef</alias>
    </object>
    <object name="Left Hedge Maze">
      <inherit name="editor_object" />
      <alias>← coral reef</alias>
    </object>
    <object name="Exit">
      <inherit name="editor_object" />
      <info>Once you click it, it is game over, make sure to save beforehand if you still want to continue.</info>
      <useindividualverblist />
      <clickit type="script">
        msg ("Congratulations, you found the exit!")
        finish
      </clickit>
    </object>
    <object name="Fish">
      <inherit name="editor_object" />
      <isafish type="string"></isafish>
      <visible type="boolean">false</visible>
      <displayverbs type="stringlist" />
      <catch type="script">
        msg ("You caught a "+this.alias)
        add = this.price
        add = add+Skill.luck
        msg ("$"+add+ " have been added.")
        player.money = player.money + add
        this.visible = false
        if (Hard.alias="Hard") {
          player.exp = player.exp+9
          EXP.alias = "EXP: "+player.exp
        }
        if (Hard.alias="Normal") {
          player.exp = player.exp+3
          EXP.alias = "EXP: "+player.exp
        }
        if (Hard.alias="Easy") {
          player.exp = player.exp+1
          EXP.alias = "EXP: "+player.exp
        }
        Skill.skillpoint = player.exp/100
      </catch>
      <alias>Shadow</alias>
    </object>
    <object name="Scenery">
      <inherit name="editor_object" />
      <displayverbs type="stringlist" />
    </object>
    <object name="Shop item">
      <inherit name="editor_object" />
      <take type="script"><![CDATA[
        if (this.bought=true) {
          AddToInventory (this)
        }
        else {
          if (game.pov.money>this.price) {
            this.bought = true
            this.alias = this.alias1+ " " +this.alias2
            AddToInventory (this)
          }
          else {
            msg ("Not enough")
          }
        }
      ]]></take>
      <displayverbs type="stringlist">
        <value>Take</value>
      </displayverbs>
      <inventoryverbs type="stringlist">
        <value>Use</value>
        <value>Drop</value>
      </inventoryverbs>
      <feature_usegive />
      <use type="script">
        game.x = 0
        game.y = 0
        All Functions
        msg ("You teleported")
      </use>
      <x type="int">0</x>
      <y type="int">0</y>
      <bought type="boolean">false</bought>
    </object>
  </object>
  <verb>
    <property>hidexycoordinates</property>
    <pattern>hide x y coordinates</pattern>
    <defaultexpression>"You can't hide x y coordinates " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>hideslimcorner</property>
    <pattern>hide slim corner</pattern>
    <defaultexpression>"You can't hide slim corner " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>clearscreen</property>
    <pattern>clear screen</pattern>
    <defaultexpression>"You can't clear screen " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>info</property>
    <pattern>info</pattern>
    <defaultexpression>"You can't info " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>exit</property>
    <pattern>exit</pattern>
    <defaultexpression>"You can't exit " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>clickit</property>
    <pattern>click it</pattern>
    <defaultexpression>"You can't click it " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>catch</property>
    <pattern>catch</pattern>
    <defaultexpression>"You can't catch " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>unhideslimcorner</property>
    <pattern>unhide slim corner</pattern>
    <defaultexpression>"You can't unhide slim corner " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>swap</property>
    <pattern>swap</pattern>
    <defaultexpression>"You can't swap " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>invest</property>
    <pattern>invest</pattern>
    <defaultexpression>"You can't invest " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>resetallskillpoints</property>
    <pattern>reset all skill points</pattern>
    <defaultexpression>"You can't reset all skill points " + object.article + "."</defaultexpression>
  </verb>
  <function name="All Functions">
    if (game.hide x y=0) {
      msg ("X: "+game.x+" Y: "+game.y)
    }
    Enter Room
    Inventory Drop
    Hide Show Exits
    Hide Show Fishes
    Hide Show Shop Items
    if (RandomChance(20)) {
      ClearScreen
    }
  </function>
  <function name="Enter Room">
    Hide Show Objects
    floorlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Floor)
    floorlist = FilterByAttribute (floorlist, "visible", true)
    if (ListCount (floorlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      thisfloor = CloneObjectAndMoveHere (Floor)
      thisfloor.x = game.x
      thisfloor.y = game.y
      game.mazesize = game.mazesize+1
      Level.alias = "Level: "+game.mazesize
      Auto Generation
      Slim Corner
    }
  </function>
  <function name="Auto Generation"><![CDATA[
    if (RandomChance(10)) {
      thischair = CloneObjectAndMoveHere (Chair)
      thischair.x = game.x
      thischair.y = game.y
    }
    for (i, 1, 5, 1) {
      if (RandomChance(50)) {
        Scenery.alias1 = PickOneString ("Silent;Steamy;Swaying;Vibrant;Dark;Decaying;Waving;Bubbling;Deep;Frozen;Abyssal;Active;Twisting;Colorful;Hidden;Rusty;Floating;Molten;Endless;Submerged;Drifting;Crystal;Quiet;Boiling;Swirling;Luminous;Jagged;Forgotten;Floating;Shimmering;Ancient;Mysterious;Sinking;Glowing;Twinkling;Ancient;Lost;Sharp;Broken;Glistening;Deep;Echoing;Ghostly;Rusty;Gliding;Rumbling;Secret;Sunken;Crumbling;Whispering;Muddy;Hidden;Ancient;Treacherous;Quiet;Sandy;Forgotten;Lurking;Hidden;Shifting;Eerie;Broken;Haunting;Coral;Murky;Sunken;Gliding;Twisting;Whispering;Shimmering;Crystal;Treacherous;Glowing;Sunken;Shimmering;Twinkling;Hidden;Shadowy;Glistening;Crumbling;Deep;Ghostly;Rusty;Hidden;Gliding;Mysterious;Crumbling;Ancient;Eerie;Lurking;Whispering")
        Scenery.alias2 = PickOneString ("depths;mist;plants;colors;tunnels;remains;strands;lava;darkness;beauty;fauna;bubbles;branches;fish;caves;metal;leaves;rock;night;relics;seaweed;clear;shadows;water;currents;creatures;rocks;artifacts;debris;light;ruins;shadows;ship;jellyfish;stars;treasures;civilization;rocks;mast;scales;sea;chambers;remains;anchor;sharks;depths;passage;city;wreck;currents;bottom;caverns;artifacts;terrain;whispers;floor;shipwreck;shadows;treasure;sands;silence;hull;beauty;reef;waters;treasure;rays;vines;voices;scales;caverns;waters;algae;ruins;waters;lights;depths;figures;pearls;stones;shadows;figures;wreckage;world;creatures;creatures;rocks;statues;glow;predators;winds;coral;vessels;reflections;gems;sea;waters;depths;fish;tides")
        Scenery.alias = Scenery.alias1+ " " +Scenery.alias2+ " (0)"
        thisscenery = CloneObjectAndMoveHere (Scenery)
        thisscenery.x = game.x
        thisscenery.y = game.y
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>2) {
        thistopmaze = CloneObjectAndMoveHere (Top Hedge Maze)
        thistopmaze.x = game.x
        thistopmaze.y = game.y
        thistopmaze2 = CloneObjectAndMoveHere (Bottom Hedge Maze)
        thistopmaze2.x = game.x
        thistopmaze2.y = game.y+1
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>1) {
        thisbottommaze = CloneObjectAndMoveHere (Bottom Hedge Maze)
        thisbottommaze.x = game.x
        thisbottommaze.y = game.y
        thisbottommaze2 = CloneObjectAndMoveHere (Top Hedge Maze)
        thisbottommaze2.x = game.x
        thisbottommaze2.y = game.y-1
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>4) {
        thisrightmaze = CloneObjectAndMoveHere (Right Hedge Maze)
        thisrightmaze.x = game.x
        thisrightmaze.y = game.y
        thisrightmaze2 = CloneObjectAndMoveHere (Left Hedge Maze)
        thisrightmaze2.x = game.x+1
        thisrightmaze2.y = game.y
        Hide Show Objects
      }
    }
    if (RandomChance(20+game.slim corner)) {
      if ( game.direction<>3) {
        thisleftmaze = CloneObjectAndMoveHere (Left Hedge Maze)
        thisleftmaze.x = game.x
        thisleftmaze.y = game.y
        thisleftmaze2 = CloneObjectAndMoveHere (Right Hedge Maze)
        thisleftmaze2.x = game.x-1
        thisleftmaze2.y = game.y
        Hide Show Objects
      }
    }
    if (RandomChance(1)) {
      if (RandomChance(1)) {
        thisexit = CloneObjectAndMoveHere (Exit)
        thisexit.x = game.x
        thisexit.y = game.y
      }
    }
  ]]></function>
  <function name="Hide Show Exits">
    // Hide Top Maze
    mazetoplist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Top Hedge Maze)
    mazetoplist = FilterByAttribute (mazetoplist, "visible", true)
    if (ListCount (mazetoplist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomnorth)
    }
    else {
      MakeExitInvisible (roomnorth)
    }
    // Hide Bottom Maze
    mazebottomlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Bottom Hedge Maze)
    mazebottomlist = FilterByAttribute (mazebottomlist, "visible", true)
    if (ListCount (mazebottomlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomsouth)
    }
    else {
      MakeExitInvisible (roomsouth)
    }
    // Hide Right Maze
    mazerightlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Right Hedge Maze)
    mazerightlist = FilterByAttribute (mazerightlist, "visible", true)
    if (ListCount (mazerightlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomeast)
    }
    else {
      MakeExitInvisible (roomeast)
    }
    // Hide Left Maze
    mazeleftlist = FilterByAttribute (GetDirectChildren (game.pov.parent), "prototype", Left Hedge Maze)
    mazeleftlist = FilterByAttribute (mazeleftlist, "visible", true)
    if (ListCount (mazeleftlist) = 0) {
      // do whatever you wanted to do if there *isn't* a floor here
      MakeExitVisible (roomwest)
    }
    else {
      MakeExitInvisible (roomwest)
    }
  </function>
  <function name="Hide Show Objects">
    foreach (object, GetDirectChildren (room)) {
      if (HasInt (object, "x") and HasInt (object, "y") and not Contains (game.pov, object)) {
        object.visible = (object.x = game.x and object.y = game.y)
        // Hide ocean current when despawning
        if (HasAttribute(object, "despawn")) {
          if (object.despawn=true) {
            MakeObjectInvisible (object)
          }
        }
      }
    }
  </function>
  <function name="Inventory Drop">
    foreach (object, ScopeInventory()) {
      object.x = game.x
      object.y = game.y
    }
  </function>
  <function name="Slim Corner"><![CDATA[
    game.slim corner = game.slim corner+3
    if (game.slim corner>40) {
      game.slim corner = 0
    }
    if (game.hide slim corner=1) {
      msg ("slim corner: "+game.slim corner)
    }
  ]]></function>
  <function name="Hide Show Fishes"><![CDATA[
    game.activate = 0
    foreach (findchair, GetDirectChildren (game.pov.parent)) {
      if (findchair.alias="Ocean current") {
        if (findchair.visible=true) {
          game.activate = game.activate+1
          findchair.despawn = true
          despawn ocean current
        }
      }
    }
    if (game.activate>0) {
      rng = GetRandomInt(1,5)
      for (i, 1, 5, 1) {
        if (RandomChance(25+Skill.stealth)) {
          rng = rng+1
        }
      }
      foreach (showfishes, GetDirectChildren (game.pov.parent)) {
        if (HasAttribute(showfishes, "isafish")) {
          if (rng>0) {
            rng = rng-1
            showfishes.visible = true
          }
        }
      }
      EnableTimer (fish timer1)
    }
    else {
      foreach (hidefishes, GetDirectChildren (game.pov.parent)) {
        if (HasAttribute(hidefishes, "isafish")) {
          hidefishes.visible = false
        }
      }
      DisableTimer (fish timer1)
    }
  ]]></function>
  <function name="Hide Show Shop Items">
    if (game.x=0 and game.y=0) {
      // delete all current shop items
      foreach (deleteshopitem, GetDirectChildren (game.pov.parent)) {
        if (HasAttribute(deleteshopitem, "bought")) {
          if (deleteshopitem.bought = false) {
            deleteshopitem.parent = null
          }
        }
      }
      // Summon 4 new shop items
      for (i, 1, 4, 1) {
        Shop item.alias1 = PickOneString ("Sunken; Coral; Abyssal; Leviathan; Kelp; Crystal; Bioluminescent; Forgotten; Whispering; Mysterious; Gardens; Cathedral; Library; Graveyard; Canopy; Caverns; Lagoon; Shipwreck; Abyss; Trench; Blade; Staff; Tome; Scale; Cloak; Shard; Elixir; Rune; Skull; Orb; Key; Bell; Scroll; Shield; Hood; Gem; Potion; Compass; Watcher; Guardian; Sage; Lorekeeper; Warden; Caretaker; Curator; Illuminator; Navigator; Whisperer; Sentinel; Keeper; Archivist; Gatekeeper; Luminary; Seeker; Tactician; Custodian; Archivist; Lookout; Scholar; Wayfarer; Observer; Azure; Verdant; Deep; Colossal; Seaweed; Prismatic; Radiant; Ethereal; Enigmatic; Edenic; Majestic; Archival; Necrotic; Arboreal; Submerged; Wrecked; Chasmal; Bladed; Arcane; Grasping; Scaly; Enshrouded; Glacial; Vibrant; Elusive; Runic; Ossified; Ancient; Sonorous; Inscribed; Arcanist; Protector; Wayfinder; Whispers; Echoes; Steward; Observer; Wayfarer")
        Shop item.alias2 = PickOneString ("Sword; Staff; Grimoire; Cloak; Shard; Elixir; Rune; Skull; Orb; Key; Bell; Scroll; Shield; Hood; Gemstone; Potion; Compass; Whisper; Sentry; Garden; Cathedral; Tome; Graveyard; Canopy; Cavern; Lagoon; Shipwreck; Abyss; Trench; Guardian; Sage; Lorekeeper; Warden; Illuminator; Navigator; Sentinel; Forest; Boulder; Oaken; Ethereal; Mysterious; Hidden; Forgotten; Illuminated; Obsidian; Ancient; Eldritch; Celestial; Lunar; Solar; Cosmic; Astral; Elemental; Runed; Magical; Mystical; Guardian; Sentinel; Protector; Warden; Keeper; Watcher; Observer; Seeker; Wanderer; Pilgrim; Voyager; Traveler; Scholar; Sage; Oracle; Seer; Visionary; Dreamer; Sojourner; Nomad; Wayfarer; Pathfinder; Trailblazer; Pioneer; Discoverer; Adventurer; Explorer; Scout; Ranger; Tracker; Huntsman; Trapper")
        Shop item.price = GetRandomInt(200,2000-Skill.charisma)
        Shop item.alias = Shop item.alias1+ " " +Shop item.alias2+ " $"+Shop item.price
        CloneObjectAndMove (Shop item, room)
      }
    }
  </function>
  <function name="despawn ocean current">
    SetTimeout (30) {
      foreach (findcurrent, AllObjects()) {
        if (HasAttribute(findcurrent, "despawn")) {
          if (findcurrent.despawn=true) {
            findcurrent.respawn = true
            findcurrent.visible = false
          }
        }
      }
    }
    SetTimeout (300) {
      foreach (findcurrent, AllObjects()) {
        if (HasAttribute(findcurrent, "respawn")) {
          if (findcurrent.respawn=true) {
            findcurrent.despawn = false
            findcurrent.respawn = false
            findcurrent.visible = true
          }
        }
      }
    }
  </function>
  <timer name="fish timer1">
    <interval>1</interval>
    <enabled type="boolean">false</enabled>
    <script>
      foreach (objectx, GetDirectChildren(game.pov.parent)) {
        if (HasAttribute(objectx, "isafish")) {
          objectx.alias1 = PickOneString ("Gold; Silver; Coral; Pearl; Crystal; Emerald; Ruby; Sapphire; Diamond; Obsidian; Abyss; Leviathan; Hydra; Kraken; Merman; Naga; Phoenix; Thunder; Storm; Frost; Venom; Spectre; Ancient; Mystic; Celest; Phantom; Gild; Enchant; Glint; Shade; Glow; Radiance; Thunderous; Sea; Dream; Whisper; Starlight; Moonlight; Sunken; Pirate; Mermaid; Atlantis; Davy; Neptune; Poseidon; Siren; Dragon; Ghost; Treasure; Jaws; Eye; Song; Scale; Feather; Fin; Water; Snake; Whale; Turtle; Ray; Starfish; Seahorse; Trident; Chest; Booty; Shell; Crown; Harpoon; Net; Map; Mirror; Relic; Locker; Bounty; Wrath; Fortune; Riches; Plunder; Loot; Hoard; Prize; Gems; Jewels; Copper; Diamonds; Rubies; Sapphires; Pearls; Crystals; Artifacts; Relics; Antiques; Curios; Valuables; Possessions; Trove; Stash; Coffer; Safe; Vault; Strongbox; Cache; Trunk; Box; Sack; Pouch; Bag; Container; Vessel; Holder; Guardian; Protector; Sentinel; Warden; Custodian; Watcher; Steward; Caretaker; Curator; Overseer; Ranger; Master; Necklace; Heirloom; Reliquary; Ingot; Bullion; Goblet; Chalice; Plate; Diadem; Bracelet; Ring; Earring; Pendant; Amulet; Brooch; Bangle; Trinket; Keepsake; Token; Trophy; Antiquity; Vestige; Oddity; Curiosity; Rarity; Paragon; Essence; Stockpile; Arsenal; Repository; Reserve; Horde; Accumulation; Wealth; Prosperity; Opulence; Affluence; Spoils; Mariner; Voyager; Buccaneer; Corsair; Swashbuckler; Marauder; Pillager; Raider; Plunderer; Rogue; Bandit; Outlaw; Thief; Scoundrel; Brigand; Knave; Rascal; Pirate; Privateer; Sea Dog; Seafarer; Seaman; Sailor; Navigator; Explorer; Adventurer; Wanderer; Roamer; Nomad; Traveler; Wayfarer; Pilgrim; Quester; Treasure Hunter; Seeker; Discoverer; Finder; Scavenger; Collector; Gatherer; Hunter; Tracker; Scout; Observer; Watcher; Guardian; Sentinel; Warden; Custodian; Protector; Defender; Keeper; Caretaker; Steward; Curator; Overseer; Ranger; Apprentice; Novice; Acolyte; Disciple; Student; Scholar; Sage; Expert; Mentor; Teacher; Professor; Guru; Authority; Elder; Leader; Chieftain; Chief; Commander; Captain; Champion; Hero; Conqueror; Vanquisher; Victor; Winner; Legend; Myth; Legacy; Fate; Destiny; Prophecy; Omen; Fortune; Luck; Chance")
          objectx.alias2 = PickOneString ("Angelfish; Ammonite; Axolotl; Barracuda; Beluga; Beluga whale; Blue whale; Broad-snouted caiman; Carp; Catfish; Central African crocodile; Chalice; Chinese alligator; Clownfish; Crab; Crown; Cuvier's dwarf caiman; Cuttlefish; Dolphin; Dwarf crocodile; Dwarf caiman; Eel; Electric eel; Emeralds; Essence; Explorer; False gharial; Fish; Fortune; Fur seal; Galleon; Gharial; Goblet; Gold; Guardian; Hippopotamus; Horde; Humpback whale; Ingot; Jewels; Journey; Keeper; Kingfish; Killer whale; Lionfish; Manta ray; Marine otter; Mariner; Minnow; Moray eel; Mystic; Nautilus; Necklace; New Guinea crocodile; Nile crocodile; Nomad; Oddity; Opulence; Orinoco crocodile; Paragon; Penguin; Pendant; Philosopher; Philippine crocodile; Piranha; Plate; Polar bear; Poseur; Prosperity; Protector; Pufferfish; Quester; Raider; Raconteur; Rarity; Ray; Relic; Repository; Reserve; River dolphin; Rubies; Safe; Salmon; Sanctuary; Sapphires; Scavenger; Scoundrel; Sea lion; Sea otter; Sea turtle; Seahorse; Seeker; Sentinel; Serpent; Shrimp; Smooth-fronted caiman; Song; Spectacled caiman; Spoils; Stash; Stingray; Strongbox; Swashbuckler; Swordfish; Temple; Temptation; Tomistoma; Token; Topaz; Torque; Tourmaline; Trout; Trophy; Trout; Trunk; Tuna; Valuables; Vault; Viperfish; Voyager; Walrus; Wanderer; Warden; Watcher; Wayfarer; Wealth; Whelk; Amulet")
          objectx.alias = objectx.alias1+ " " +objectx.alias2
          objectx.price = GetRandomInt(1,100)
          for (i, 1, 5, 1) {
            if (RandomChance(50)) {
              objectx.price = objectx.price+15
            }
          }
          if (RandomChance(10)) {
            MakeObjectInvisible (objectx)
          }
        }
      }
    </script>
  </timer>
</asl>

Log in to post a reply.

Support

Forums