Adding sequential numbers when printing out an non-numbered string list

Forgewright
25 Apr 2020, 01:57
ViewObjectScreen
request (Show, "Command")
msg ("<center>------------------------------------------")
msg ("<center><small><em><br>Please type in the box below to enter the information if you want to add to your journal notes. Then press ENTER.")
msg ("<center><small><em><br>Or just press 'ENTER' to close the journal")
JS.eval ("$(function () {var a=runCommand;runCommand=function(){sendCommand($(\"#txtCommand\").val());runCommand=a;};});")
get input {
  game.answer = result
  if (result = "") {
    HandleSingleCommand ("Back to the action!")
  }
  Ask ("Is this what you want to add to the journal?<br>" + result) {
    if (result) {
      list add (player.playeraddjournal, game.answer)
      HandleSingleCommand ("journal")
      msg ("<br><center>You have written in your journal.")
      game.nojournal = True
    }
    else if (result = false) {
      HandleSingleCommand ("journal")
    }
  }
}

As you can see the player is making the notes to be added to a list called player.playeraddjournal. I am saving thier response/result as game.answer. I could code list add (player.playeraddjournal, game.answer) as list add (player.playeraddjournal, ("1. " + game.answer ) (I would think thats wrong, but you get my drift.) It would only work on one entry to the list as they would all have a one in front of them.

Is this enough information to figure it out? Oh, gods of the Quest forum.

Oh, My next step is creating a command that will remove an entry in the journal notes, However, I think I do do that part with what I learned from adding them. So I will move on to that for now.

Thanks and the check is in the mail...


Dcoder
25 Apr 2020, 03:15

So when you want to print out the journal, how 'bout something like this:

foreach (item, player.playeraddjournal) {
  bullet = ToString(IndexOf(player.playeraddjournal, item) + 1)
  msg (bullet + ". " + item)
}

Forgewright
25 Apr 2020, 03:59

Dcoder, I pasted it in and it worked like a charm. 👍


mrangel
25 Apr 2020, 09:35

Your solution will get confused if the player enters the same line twice; and is O(N²) in all cases.
Should be:

for (number, 1, ListCount(player.playeraddjournal)) {
  msg (number + ". " + ListItem (player.playeraddjournal, number-1))
}

or

bullet = 1
foreach (item, player.playeraddjournal) {
  msg (ToString(bullet) + ". " + item)
  bullet = bullet + 1
}

Or slightly more efficient, you could do:

msg ("<ol><li>" + Join (player.playeraddjournal, "</li><li>") + "</li></ol>")

(<ol> = Ordered List. Automatically adds numbers; can be configured to use Roman numerals, Chinese numbers, or letters if you prefer)


Forgewright
25 Apr 2020, 13:37

Yep, that works too.


Forgewright
25 Apr 2020, 18:20

How do I remove an item from game.playeraddjounal by using its position?
This is the 'remove a note from journal' command script:

request (Show, "Command")
msg ("<center>------------------------------------------")
msg ("<center><small><em><br>Enter the number of the note you want to remove from journal.")
msg ("<center><small><em><br>Or just press 'ENTER' to close the journal")
msg ("<ol><li>" + Join (player.playeraddjournal, "</li><li>") + "</li></ol>")
JS.eval ("$(function () {var a=runCommand;runCommand=function(){sendCommand($(\"#txtCommand\").val());runCommand=a;};});")
get input {  
  n = result + 1
  game.answer = n
  if (result = "") {
    HandleSingleCommand ("Back to the action!")
  }
  else if (not IsInt (result)) {
    msg ("Please enter a number between 1 and " + n + ".")
  }
  else {
    Ask ("Is this the note you want to remove from the journal?<br>" + result) {
      n = game.answer
      if (result) {
        list remove (player.playeraddjournal, n)
        HandleSingleCommand ("journal")
        msg ("<br><center>You have removed a note in your journal.")
        game.nojournal = True
      }
      else if (result = false) {
        HandleSingleCommand ("remove a note from journal")
      }
    }
  }
} 

I added 1 to the result to get the right string position but it is not removing anything


mrangel
25 Apr 2020, 19:13

Oddly, you need to remove items by value. So it would be something like:

list remove (player.playeraddjournal, ListItem (player.playeraddjournal, n))

The main problem with doing it this way is that if the player enters the same line twice, it will remove the first one, and not the one they asked for. If you want that to work correctly, you would do:

for (i, 1, ListCount(player.playeraddjournal)) {
  value = ListItem (player.playeraddjournal, 0)
  list remove (player.playeraddjournal, value)
  if (not i = n) {
    list add (player.playeraddjournal, value)
  }
}

(this loops over the whole list, taking values off the beginning and putting them back at the end; and skips the "put it back at the end" step for the number the player entered. Note that in this case, the number n should be the number the player typed; you don't need to subtract 1 from it like you do with the previous version)


Also, you've got a few logic errors in that code.
Think about what would happen in the following situations:

List has 10 items; player enters "2":

  • n = result + 1 ⇒ result is the string "2", so n is the string "21"
  • Ask(… ⇒ Asks "Is this the note you want to remove from the journal? 2"
  • Assuming the player says yes…
    • Game attempts to remove item 21 from the list. In the case of the loop I posted above, nothing happens because there's no such item. Using the other method, it gives an error.

List has 10 items; player enters "12":

  • n = result + 1 ⇒ result is the string "12", so n is the string "121"
  • Ask(… ⇒ Asks "Is this the note you want to remove from the journal? 12"
  • Assuming the player says yes…
    • Game attempts to remove item 121 from the list. In the case of the loop I posted above, nothing happens because there's no such item. Using the other method, it gives an error.

List has 10 items; player enters "-5":

  • n = result + 1 ⇒ result is the string "-5", so n is the string "-51"
  • Ask(… ⇒ Asks "Is this the note you want to remove from the journal? -5"
  • Assuming the player says yes…
    • Game attempts to remove item -51 from the list. In the case of the loop I posted above, nothing happens because there's no such item. Using the other method, it gives an error.

List has 10 items; player enters "fish":

  • n = result + 1 ⇒ result is the string "fish", so n is the string "fish1"
  • else if (not IsInt (result)) { ⇒ "fish" isn't an int, so:
    • msg ("… ⇒ Outputs the message "Please enter a number between 1 and fish1."

To handle all situations properly, I think you'd want:

get input {
  if (result = "") {
    HandleSingleCommand ("Back to the action!")
  }
  else {
    if (IsInt (result)) {
      game.answer = ToInt (result)
    }
    else {
      game.answer = 0
    }
    if (game.answer <1 or game.answer > ListCount (player.playeraddjournal)) {
      msg ("Please enter a number between 1 and " + ListCount (player.playeraddjournal)+".")
    }
    else {
      Ask ("Is this the note you want to remove from the journal?<br>" + game.answer) {
        if (result) {
          n = game.answer
          for (i, 1, ListCount(player.playeraddjournal)) {
            value = ListItem (player.playeraddjournal, 0)
            list remove (player.playeraddjournal, value)
            if (not i = n) {
              list add (player.playeraddjournal, value)
            }
          }
          HandleSingleCommand ("journal")
          msg ("<br><center>You have removed a note in your journal.")
          game.nojournal = True
        }
        else if (result = false) {
          HandleSingleCommand ("remove a note from journal")
        }
      }
    }
  }
}

Forgewright
25 Apr 2020, 21:43

Good stuff! However, the lines :

if (game.answer <1 or game.answer > ListCount (game.playeraddjournal)) {
     msg ("Please enter a number between 1 and " + ListCount (game.playeraddjournal)+".")
   }

Gives the error:
Error running script: Error evaluating expression 'game.answer < 1 or game.answer > ListCount (game.playeraddjournal)': ListCount function expected list parameter but was passed 'null'


mrangel
25 Apr 2020, 21:50

Sorry, careless mistake. I put game.playeraddjournal instead of player.playeraddjournal.


Forgewright
25 Apr 2020, 23:01

Ha! I can't believe I didn't see that...


Forgewright
25 Apr 2020, 23:10

That works great.

Why does the last entry into the command box remain in the box when I return to the game after a Clear Screen and ShowRoomDecription. Or if I use any of the other commands in the journal that bring up the command box. Do I need to clear it somehow?


mrangel
26 Apr 2020, 10:48

Why does the last entry into the command box remain in the box when I return to the game after a Clear Screen and ShowRoomDecription. Or if I use any of the other commands in the journal that bring up the command box. Do I need to clear it somehow?

Sorry, my bad. The runCommand function checks if there's anything in the command box, send that to sendCommand if there is, and then clears the box. So the function to allow blank input should be:

JS.eval ("$(function () {var a=runCommand;runCommand=function(){sendCommand($(\"#txtCommand\").val());$(\"#txtCommand\").val(\"\");runCommand=a;};});")

(sets the contents of the command bar to ""


Forgewright
26 Apr 2020, 16:47

That was it!