Visual maze map that updates as you move

All about the past, current and future webteases and the art of webteasing in general.
---
Post Reply
notSafeForDev
Explorer
Explorer
Posts: 33
Joined: Sun Sep 06, 2020 12:39 pm

Visual maze map that updates as you move

Post by notSafeForDev »

I got inspired to create this after playing Girls Naughty School, by MaidKun. Which is a tease where you navigate a procedurally generated maze. Which made me think, wouldn't it be neat if you could see a mini-map that updates as you move around the maze?

https://milovana.com/webteases/showteas ... 08b16dc746

It's just a proof of concept, but I tried writing the code in such a way that you wouldn't need to modify too much of it.

The following code is used to design the maze:

Code: Select all

width: 4,
height: 4,
map: [
    " ", "-", " ", "L", " ", "-", " ",
    "X", "X", "|", "X", "|", "X", "X",
    " ", "-", " ", "-", " ", "X", " ",
    "|", "X", "|", "X", "X", "X", "|",
    " ", "-", " ", "X", " ", "-", " ",
    "X", "X", "|", "X", "|", "X", "|",
    "X", "X", " ", "-", " ", "X", " ",
]
" ": Room
"-", "|": Door
"L": Locked door
"X": Wall

Each room is placed on a grid, with a wall or door between each of them.

If a page is created with the name "roomX1Y2", it will automatically be opened when reaching the room 1 step right, 2 steps down. So you don't need to modify the code in order to add pages for rooms.

Here's the code:

Code: Select all

{
  "pages": {
    "start": [
      {
        "say": {
          "label": "<p>This is a test for a visual maze that you can navigate.</p>"
        }
      },
      {
        "goto": {
          "target": "map"
        }
      }
    ],
    "map": [
      {
        "say": {
          "label": "<p><eval>showMapRow(0)</eval></p><p><eval>showMapRow(1)</eval></p><p><eval>showMapRow(2)</eval></p><p><eval>showMapRow(3)</eval></p><p><eval>showMapRow(4)</eval></p>"
        }
      },
      {
        "choice": {
          "options": [
            {
              "label": "<",
              "commands": [
                {
                  "eval": {
                    "script": "goInDirection(-1, 0);"
                  }
                }
              ],
              "visible": "$canGoInDirection(-1, 0);"
            },
            {
              "label": "^",
              "commands": [
                {
                  "eval": {
                    "script": "goInDirection(0, -1)"
                  }
                }
              ],
              "visible": "$canGoInDirection(0, -1);"
            },
            {
              "label": "v",
              "commands": [
                {
                  "eval": {
                    "script": "goInDirection(0, 1);"
                  }
                }
              ],
              "visible": "$canGoInDirection(0, 1);"
            },
            {
              "label": ">",
              "commands": [
                {
                  "eval": {
                    "script": "goInDirection(1, 0);"
                  }
                }
              ],
              "visible": "$canGoInDirection(1, 0);"
            }
          ]
        }
      },
      {
        "goto": {
          "target": "map"
        }
      }
    ],
    "roomX3Y0": [
      {
        "say": {
          "label": "<p>You have entered the room in the top right corner!</p><p>You will only get this encounter this first time.</p>"
        }
      },
      {
        "goto": {
          "target": "map"
        }
      }
    ],
    "roomX3Y3": [
      {
        "say": {
          "label": "<p>You have entered the room in the bottom right corner!</p><p>You will only get this encounter this first time.</p>"
        }
      },
      {
        "goto": {
          "target": "map"
        }
      }
    ],
    "mapBeforeEncounter": [
      {
        "say": {
          "label": "<p><eval>showMapRow(0)</eval></p><p><eval>showMapRow(1)</eval></p><p><eval>showMapRow(2)</eval></p><p><eval>showMapRow(3)</eval></p><p><eval>showMapRow(4)</eval></p>"
        }
      },
      {
        "timer": {
          "duration": "0.75s",
          "style": "hidden"
        }
      },
      {
        "goto": {
          "target": "$targetPageId"
        }
      }
    ],
    "roomX1Y1": [
      {
        "say": {
          "label": "<p>You have entered a random encounter!</p><p>It triggers randomly when entering this room.</p>"
        }
      },
      {
        "goto": {
          "target": "map"
        }
      }
    ]
  },
  "init": "var targetPageId = \"\";\r\n\r\nvar position = {\r\n  x: 0,\r\n  y: 0,\r\n}\r\n\r\nvar inventory = {\r\n  keys: 1,\r\n}\r\n\r\nvar maze = {\r\n  width: 4,\r\n  height: 4,\r\n  viewDistance: 1, // See comment before showMapRow declaration\r\n  map: [\r\n    \" \", \"-\", \" \", \"L\", \" \", \"-\", \" \",\r\n    \"X\", \"X\", \"|\", \"X\", \"|\", \"X\", \"X\",\r\n    \" \", \"-\", \" \", \"-\", \" \", \"X\", \" \",\r\n    \"|\", \"X\", \"|\", \"X\", \"X\", \"X\", \"|\",\r\n    \" \", \"-\", \" \", \"X\", \" \", \"-\", \" \",\r\n    \"X\", \"X\", \"|\", \"X\", \"|\", \"X\", \"|\",\r\n    \"X\", \"X\", \" \", \"-\", \" \", \"X\", \" \",\r\n  ],\r\n  rooms: [[{\r\n    x: -1,\r\n    y: -1,\r\n    isAvailable: false,\r\n    timesEntered: 0,\r\n    doorUp: {isAvailable: false, isLocked: false, x: -1, y: -1},\r\n    doorRight: {isAvailable: false, isLocked: false, x: -1, y: -1},\r\n    doorDown: {isAvailable: false, isLocked: false, x: -1, y: -1},\r\n    doorLeft: {isAvailable: false, isLocked: false, x: -1, y: -1},\r\n  }]],\r\n}\r\n\r\nvar tiles = {\r\n  obscured: \" ░░ \",\r\n  visible: \" ██ \",\r\n  lockedDoor: \" ╫╫ \",\r\n  horizontalDoor: \" ══ \",\r\n  verticalDoor: \" ║║ \",\r\n  unknown: \" ▒▒ \",\r\n  unknown2: \" ?_? \",\r\n}\r\n\r\ninitializeMaze();\r\n\r\nfunction roomEncounter(room) {\r\n  if (room.x === 1 && room.y === 1) {\r\n    if (Math.random() >= 0.33) {\r\n      return;\r\n    }\r\n  } else if (room.timesEntered > 1) {\r\n    return;\r\n  }\r\n\r\n  targetPageId = \"roomX\" + position.x + \"Y\" + position.y;\r\n  pages.goto(\"mapBeforeEncounter\");\r\n}\r\n\r\nfunction drawRoom(room) {\r\n  if (room.isAvailable === true) {\r\n    return tiles.obscured;\r\n  }\r\n  if (room.timesEntered === 0) {\r\n    return tiles.obscured;\r\n  }\r\n  return tiles.visible;\r\n}\r\n\r\nfunction drawDoor(room, door) {\r\n  if (door.isAvailable === false) {\r\n    return tiles.obscured;\r\n  }\r\n  if (room.timesEntered === 0 && getRoom(door.x, door.y).timesEntered === 0) {\r\n    return tiles.obscured;\r\n  }\r\n  if (door.isLocked === true) {\r\n    return tiles.lockedDoor;\r\n  }\r\n  if (room.x !== door.x) {\r\n    return tiles.horizontalDoor;\r\n  }\r\n  return tiles.verticalDoor;\r\n}\r\n\r\nfunction canGoInDirection(x, y) {\r\n  var door = getDoor(position.x, position.y, x, y);\r\n  return door.isAvailable === true && door.isLocked === false;\r\n}\r\n\r\nfunction goInDirection(x, y) {\r\n  position.x += x;\r\n  position.y += y;\r\n  maze.rooms[position.x][position.y].timesEntered++;\r\n\r\n  if (hasPage(\"roomX\" + position.x + \"Y\" + position.y) === true) {\r\n    roomEncounter(maze.rooms[position.x][position.y]);\r\n  }\r\n}\r\n\r\nfunction initializeMaze() {\r\n  var charactersPerRow = (maze.width * 2 - 1);\r\n  \r\n  maze.rooms = [];\r\n\r\n  for (var x = 0; x < maze.width; x++) {\r\n    maze.rooms.push([]);\r\n  }\r\n\r\n  for (var y = 0; y < maze.height; y++) {\r\n    for (var x = 0; x < maze.width; x++) {\r\n      var index = 0;\r\n      index += x * 2;\r\n      index += y * charactersPerRow * 2;\r\n\r\n      var characterAtPosition = maze.map[index];\r\n      var characterDoorUp = \"X\";\r\n      var characterDoorRight = \"X\";\r\n      var characterDoorDown = \"X\";\r\n      var characterDoorLeft = \"X\";\r\n\r\n      if (y > 0) {\r\n        characterDoorUp = maze.map[index - charactersPerRow];\r\n      }\r\n      if (x < maze.width - 1) {\r\n        characterDoorRight = maze.map[index + 1];\r\n      }\r\n      if (y < maze.height - 1) {\r\n        characterDoorDown = maze.map[index + charactersPerRow];\r\n      }\r\n      if (x > 0) {\r\n        characterDoorLeft = maze.map[index - 1];\r\n      }\r\n      \r\n      maze.rooms[x].push({\r\n        isAvailable: characterAtPosition === \"X\",\r\n        timesEntered: 0,\r\n        x: x,\r\n        y: y,\r\n        doorUp: {\r\n          isAvailable: characterDoorUp !== \"X\",\r\n          isLocked: characterDoorUp === \"L\",\r\n          x: x, y: y - 1\r\n        },\r\n        doorRight: {\r\n          isAvailable: characterDoorRight !== \"X\",\r\n          isLocked: characterDoorRight === \"L\",\r\n          x: x + 1, y: y\r\n        },\r\n        doorDown: {\r\n          isAvailable: characterDoorDown !== \"X\",\r\n          isLocked: characterDoorDown === \"L\",\r\n          x: x, y: y + 1\r\n        },\r\n        doorLeft: {\r\n          isAvailable: characterDoorLeft !== \"X\",\r\n          isLocked: characterDoorLeft === \"L\",\r\n          x: x - 1, y: y\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  maze.rooms[position.x][position.y].timesEntered = 1;\r\n}\r\n\r\nfunction getRoom(x, y) {\r\n  if (x < 0 || x >= maze.width || y < 0 || y >= maze.height) {\r\n    return {\r\n      x: -1,\r\n      y: -1,\r\n      isAvailable: false,\r\n      timesEntered: 0,\r\n      doorUp: {isAvailable: false, isLocked: false, x: -1, y: -1},\r\n      doorRight: {isAvailable: false, isLocked: false, x: -1, y: -1},\r\n      doorDown: {isAvailable: false, isLocked: false, x: -1, y: -1},\r\n      doorLeft: {isAvailable: false, isLocked: false, x: -1, y: -1},\r\n    }\r\n  }\r\n  return maze.rooms[x][y];\r\n}\r\n\r\nfunction getDoor(roomX, roomY, directionX, directionY) {\r\n  var room = getRoom(roomX, roomY);\r\n  if (directionX === 0 && directionY === -1) {\r\n    return room.doorUp;\r\n  }\r\n  if (directionX === 1 && directionY === 0) {\r\n    return room.doorRight;\r\n  }\r\n  if (directionX === 0 && directionY === 1) {\r\n    return room.doorDown;\r\n  }\r\n  if (directionX === -1 && directionY === 0) {\r\n    return room.doorLeft;\r\n  }\r\n}\r\n\r\n// Should be called with rows: 0 - 4, for viewDistance 1\r\n// rows: 0 - 8 for viewDistance 2\r\n// rows: 0 - 12 for viewDistance 3\r\n// etc...\r\nfunction showMapRow(row) {\r\n  var message = \"\";\r\n  var fromX = position.x - maze.viewDistance;\r\n  var toX = position.x + maze.viewDistance;\r\n  var y = position.y - maze.viewDistance + Math.floor(row / 2);\r\n  var hasRoomsOnRow = row % 2 === 0;\r\n\r\n  for (var x = fromX; x <= toX; x++) {\r\n    var isLastRoom = x === toX;\r\n    var room = getRoom(x, y);\r\n\r\n    if (hasRoomsOnRow === true) {\r\n      message += drawRoom(room);\r\n      if (isLastRoom === false) {\r\n        message += drawDoor(room, room.doorRight);\r\n      }\r\n    } else {\r\n      message += drawDoor(room, room.doorDown);\r\n      if (isLastRoom === false) {\r\n        message += tiles.obscured;\r\n      }\r\n    }\r\n  }\r\n\r\n  return message;\r\n}\r\n\r\n// Credits to fapnip for the solution\r\nfunction hasPage(pageId) {\r\n    var originalState = pages.isEnabled(pageId);\r\n    pages.disable(pageId);\r\n    // Missing pages will always return true\r\n    var doesExist = pages.isEnabled(pageId) === false;\r\n    if (doesExist === true && originalState === true) {\r\n      pages.enable(pageId);\r\n    }\r\n    return doesExist;\r\n}",
  "modules": {
    "notification": {}
  },
  "files": {},
  "galleries": {},
  "editor": {
    "recentImages": []
  }
}
I don't plan on creating a tease with this myself, so please let me know if you would be interested in using it!
Last edited by notSafeForDev on Mon Nov 02, 2020 3:22 am, edited 1 time in total.
Roblsforbobls
Explorer At Heart
Explorer At Heart
Posts: 272
Joined: Tue May 21, 2019 2:27 am
Gender: Male
Sexual Orientation: Asexual
I am a: Switch

Re: Visual maze map that updates as you move

Post by Roblsforbobls »

Wow that's amazing! It took me a few seconds to understand how to read the map during the demonstration; the doors you've coded look like rooms, so it looks like you skip a room every time the map advances. Is there any way to change that? Also, is there any way to make the map multi-colored?

Again, amazing work! :D
notSafeForDev
Explorer
Explorer
Posts: 33
Joined: Sun Sep 06, 2020 12:39 pm

Re: Visual maze map that updates as you move

Post by notSafeForDev »

Roblsforbobls wrote: Mon Nov 02, 2020 2:19 am Wow that's amazing! It took me a few seconds to understand how to read the map during the demonstration; the doors you've coded look like rooms, so it looks like you skip a room every time the map advances. Is there any way to change that? Also, is there any way to make the map multi-colored?

Again, amazing work! :D
Thanks! That's a valid point, so I have changed it to use different characters for doors.

I'm using ascii characters from here: https://en.wikipedia.org/wiki/Box-drawing_character as many characters has the same width.

Original code:

Code: Select all

var tiles = {
  obscured: " ░░ ",
  visible: " ██ ",
  lockedDoor: " ╫╫ ",
  unknown: " ▒▒ ",
  unknown2: " ?_? ",
}

function drawDoor(room, door) {
  if (door.isAvailable === false) {
    return tiles.obscured;
  }
  if (room.timesEntered === 0 && getRoom(door.x, door.y).timesEntered === 0) {
    return tiles.obscured;
  }
  if (door.isLocked === true) {
    return tiles.lockedDoor;
  }
  return tiles.visible;
}
Updated code:

Code: Select all

var tiles = {
  obscured: " ░░ ",
  visible: " ██ ",
  lockedDoor: " ╫╫ ",
  horizontalDoor: " ══ ",
  verticalDoor: " ║║ ",
  unknown: " ▒▒ ",
  unknown2: " ?_? ",
}

function drawDoor(room, door) {
  if (door.isAvailable === false) {
    return tiles.obscured;
  }
  if (room.timesEntered === 0 && getRoom(door.x, door.y).timesEntered === 0) {
    return tiles.obscured;
  }
  if (door.isLocked === true) {
    return tiles.lockedDoor;
  }
  if (room.x !== door.x) {
    return tiles.horizontalDoor;
  }
  return tiles.verticalDoor;
}
As for multicolored, I'll have to look into how to change the color of text.
Roblsforbobls
Explorer At Heart
Explorer At Heart
Posts: 272
Joined: Tue May 21, 2019 2:27 am
Gender: Male
Sexual Orientation: Asexual
I am a: Switch

Re: Visual maze map that updates as you move

Post by Roblsforbobls »

notSafeForDev wrote: Mon Nov 02, 2020 3:20 am Thanks! That's a valid point, so I have changed it to use different characters for doors.
Now that looks a lot more clear! :yes:
May I ask why "║║" is the vertical door instead of "║"? I think a single bar would further improve consistency and readability
notSafeForDev
Explorer
Explorer
Posts: 33
Joined: Sun Sep 06, 2020 12:39 pm

Re: Visual maze map that updates as you move

Post by notSafeForDev »

Roblsforbobls wrote: Wed Nov 04, 2020 3:02 am Now that looks a lot more clear! :yes:
May I ask why "║║" is the vertical door instead of "║"? I think a single bar would further improve consistency and readability
A single "║" isn't wide enough, which would make the grid misaligned:

██ ══ ██ ██ ██
██ ██ ║ ██ ██
██ ██ ██ ██ ██
██ ██ ██ ██ ██
██ ██ ██ ██ ██

Normally I could add more spaces to make it look more aligned, but EOS actually removes any extra spaces from displayed text.

I have changed to " -║- " as it takes the right amount of width.
Roblsforbobls
Explorer At Heart
Explorer At Heart
Posts: 272
Joined: Tue May 21, 2019 2:27 am
Gender: Male
Sexual Orientation: Asexual
I am a: Switch

Re: Visual maze map that updates as you move

Post by Roblsforbobls »

notSafeForDev wrote: Thu Nov 05, 2020 6:33 pm
Roblsforbobls wrote: Wed Nov 04, 2020 3:02 am Now that looks a lot more clear! :yes:
May I ask why "║║" is the vertical door instead of "║"? I think a single bar would further improve consistency and readability
A single "║" isn't wide enough, which would make the grid misaligned:

██ ══ ██ ██ ██
██ ██ ║ ██ ██
██ ██ ██ ██ ██
██ ██ ██ ██ ██
██ ██ ██ ██ ██

Normally I could add more spaces to make it look more aligned, but EOS actually removes any extra spaces from displayed text.

I have changed to " -║- " as it takes the right amount of width.
notSafeForDev wrote: Thu Nov 05, 2020 6:33 pm I have changed to " -║- " as it takes the right amount of width.
" ║ " seems to be the right amount of width as well!

I have tried to make the map appear as a notification with mixed luck. I have been using spaces to create the illusion of a line break and to make the grid, but the map inevitably gets misaligned after navigating a couple rooms. Is there anything else we can try, or do you know of a way to make a real line break in a notification title?
Here's my attempt:
https://milovana.com/webteases/showteas ... f48ddf061a
desertfox
Explorer At Heart
Explorer At Heart
Posts: 365
Joined: Mon Dec 03, 2012 7:26 pm
Gender: Male
Sexual Orientation: Straight
I am a: None of the above

Re: Visual maze map that updates as you move

Post by desertfox »

You may want to download my maze tease I had started a while back and use or look at some of the code. Granted it's in guideme but I think it's the same as the tease viewer. But it's basically got a random maze generator, map view, all done.

Random Mazes

I took a generic maze generator and changed it slightly so it would bust down a few walls here or there. It also takes pictures from a directory that can be any 'theme' you want. So if you get in a a room with just north and east exits, it'll take the ne.jpg out of the directory and show it. So you only need to really cover a few exit types and you've got a picture for each. If you get picture sets you can have separate themes. In the tease I didn't get to writing more, but I had hedge maze, mansion, and open fields themes ready to go.

The map is just a 2d array of rooms with the exits marked, so the navigation page just shows a button for the available exits. The map view will just go through the array and display rooms you've visited. I also have some rooms marked with event triggers so when you walk into them you'll find say the exit or a specific place.

Anyway feel free to just rip the map display page or any other bit of code in there if you like!
Lamei
Explorer
Explorer
Posts: 99
Joined: Wed Jan 30, 2019 8:23 pm

Re: Visual maze map that updates as you move

Post by Lamei »

Nice idea. I've been doing some work on Mazes over the last 18 months also. There is a way to add spaces to text that is stored as a variable or an array in EOS. Every time you need a space use '\xa0'.

Eg.

var Maze = ['\xa0Test1','Test2','Test3\xa0\xa0']

This will make EOS display 1 space at the start of Test1 and display 2 spaces at the end of Test 3.
Post Reply