Enemies Movement

Shmabz
Hey, i am making a Slender game on text editor, and have made a 9x9 grid of "rooms" to simulate the forest and each landmark etc. The only problem is making slenderman, i have sussed out how to use timers to him, kill me and other stuff, but how do i get him to "move" towards me through and across all the rooms? Visible won't work with this. This is needed because if i move towards him i want the player to die sooner than if you walked away from his location. :D
Thanks for your help!

HegemonKhan
This is way too advanced programming for me, lol, but a few ideas of how it could be done:

make a script that checks the 'distance ('hops')' between your character's location (room) and 'slenderman's location (room), then you'd 'if-compare' if that distance is greater or lesser for each room that he could move to...

well, a 3x3 grid of rooms, wouldn't be too hard to do (while poor, you could give a numeral string for each room, using that to help in your if script coding)... but having a larger grid would require some advanced coding and algorithm..

a 'trajectory~path algorithm' as it is called in actual gaming.

try researching up on this online, as there should be info available on how to do this type of coding.

-----

a super simple thing to do is to just randomly move slenderman to different rooms (which is easy to code, I can do this), but this isn't what you want.

george
Yeah, HK is on the right track, you want path-finding. A common one is called A*. However practically speaking for your 9x9 grid you may be able to get away with a simpler approach, since the game 'knows' the grid perfectly, and aren't all the movement costs through rooms basically the same? For example, imagine this scenario, where slenderman is in 1,1 (row, column) and player is in 6, 4:


1 2 3 4 5 6 7 8 9
1 S
2
3
4
5
6 P
7
8
9


The game knows that player is 'southeast' of slenderman because the player's room coordinates are greater. So, just move slenderman by increasing its (row, column).

If the player is 'above' slenderman like so,


1 2 3 4 5 6 7 8 9
1
2
3 P
4
5
6 S
7
8
9


the game knows that the row of the player is less, but the column is greater. So increase slenderman's column number (from 4 to 5), and decrease the row (from 6 to 5) to move slenderman closer to the player.

Shmabz
You're all genius' :'D I'm REALLY new to coding though, i can do basic XML and I'm learning Python at the moment, but I'm still pretty novice :/ Could you guys (george and HK) maybe type up a little sample script i could start from or elaborate on? I know this is asking a lot of you guys and you have helped a lot, and i don't want it to look like you're coding the entire game for me because i can do the rest from this point on, but just maybe a code which will find the room values and store them? It would be a great help and WILL put you guys in the credits :3

HegemonKhan
I'm not really able to do such coding yet, but you can look at Jay's Map Generation coding (see the 'Libraries+Code' Board section on this site), or maybe others can help you with it. I don't want to comment beforehand, as I'd need to try to study Jay's coding first, so that my comment would be on the right track, at least. Hopefully, others can help you, but if not, let me know, and I'll try to study and understand Jay's maping coding, to then be able to try to help you the best that I can in understanding how Jay has set it up and done it.

you can give each room, two attributes:

rooms:

789
456
123

y,x:

3,1 ~ 3,2 ~ 3,3
2,1 ~ 2,2 ~ 2,3
1,1 ~ 1,2 ~ 1,3

room1.y_axis_integer = 1
room1.x_axis_integer = 1

room2.y_axis_integer = 1
room2.x_axis_integer = 2

room3.y_axis_integer = 1
room3.x_axis_integer = 3

room4.y_axis_integer = 2
room4.x_axis_integer = 1

room5.y_axis_integer = 2
room5.x_axis_integer = 2

room6.y_axis_integer = 2
room6.x_axis_integer = 3

room7.y_axis_integer = 3
room7.x_axis_integer = 1

room8.y_axis_integer = 3
room8.x_axis_integer = 2

room9.y_axis_integer = 3
room9.x_axis_integer = 3

then you can use the 'greater than (>)', 'lesser than (<)', 'greater than or equal to (>=)', or 'lesser than or equal to (<=)' to compare the two rooms' coordinates, within 'if' scripting, for how~where you move slenderman.

but look at Jay's coding, as I'm probably doing this very poorly (extra code work than needed or just simply wrongly too, lol)

-----------------

in a more general response, if you haven't already, I highly suggest that you go through and try to complete~do everything in the tutorial on here (err, the wiki section, it might be a different site, not sure, lol), just to get familiar with quest's code language, and its basic features, and in using its GUI~Editor mode too.

Quest's language is uber noobie-friendly, it's probably the easiest language to learn, just go through the tutorial, and for the coding, look at all the coding that is made public, a good starting code to work on understanding and creating is the "character creation" coding.

if you need help finding anything... let me know, I do have a few of the newest threads with all the "noobie links", but if you can't find those threads with these posts, I'll post the "noobie links" here too.

-------------

P.S.

nevermind, here's the "noobie" links for you:

some useful links for you:

01. http://quest5.net/wiki/Main_Page
02. http://quest5.net/wiki/Tutorial
03. http://quest5.net/wiki/How_to (guides)
04. http://quest5.net/wiki/Showing_a_menu
05. http://quest5.net/wiki/Character_Creation
06. http://quest5.net/wiki/Category:All_Fun ... t_Commands (page 1, range: A-S)
07. http://quest5.net/w/index.php?title=Cat ... t#mw-pages (page 2, range: S-Z)
08. viewforum.php?f=18 (more guides: libraries and code)
09. http://quest5.net/wiki/Object_element
10. http://quest5.net/wiki/Attribute_Types
11. http://quest5.net/wiki/Category:ASLX_Elements
12. http://quest5.net/wiki/ASLX_Elements

-----------------

the two most powerful scripts:

in GUI~Editor:

'Setting or Changing an Attribute (or a variable)' Script:

run as script -> add a script -> Variables -> Set a variable ->

Attribute:

Object.Attribute = Value_or_Expression

Variable:

Variable = Value_or_Expression

or, you can do so (well, making ~ setting up an attribute, anyways), via the specific object itself too:

(whatever) Object -> Attributes (tab) -> Attributes -> Add ->

Attribute Name: _______
Attribute Type: _______ (int = integer, double = float = floating point = decimal'ed number, boolean = flag, string, lists, dictionaries, script, object, etc)
Attribute Value: _______ (depends on the Attribute Type)

"if" Script:

run as script -> add a script -> Scripts -> "if..." -> (select whatever, [EXPRESSION] is the most powerful, letting you directly code in what script expression that you want, such as the 'set an attribute or variable' script.

---------------

In code:

Variable (can't be used~called upon, outside of its own scrip block, local, "non-save-load'able"):

Variable_name = Value_or_Expression

examples (built-in, such as when using the 'get input' or 'show menu' functions):

result = _______

examples (custom, self-made):

handled = false // or true
you_go_first = false // or true
count = 5
formula = x + 34
x = 10
y = x + 6

Attribute ("save-load'able", global, can be used~called upon from anywhere ~ so long as the Object still exists) syntax:

Object_name.Attribute_name = Value_or_Expression

examples:

game.turns = 0
player.turns = 0
player.strength = 50
game.pov.turns = 0
game.pov.strength = 50
HK.strength = 100
HK.favoritecolor = "black"
HK.favoritecolorslist = split ("black;red", ";")
orc.dead = false
orc.damage = 26.3
HK.strength = HK.strength + 900
HK.strength = HK.strength - 50
HK.strength = HK.strength * 3
HK.strength = HK.strength / 2
HK.damage = HK.weapon + HK.weapon * (HK.strength - orc.endurance) / 100
table.color = "brown"
table.material = "wood"
table.height = 4
table.items = split ("candles;utensils;plates;napkins;foods;drinks", ";")
orc.fight = (script block)
orc.handled = false // or true
orc.you_go_first = false // or true
game.count = 5
player.formula = x + 34
game.x = 10
player.y = x + 6
etc...

and the "if" script:

An example (combining the "if" script with an "setting an Attribute" script):

if (orc.dead = true) {
msg ("The orc is already dead, silly.")
} else if (orc.dead = false) {
msg ("The orc is still alive.")
}


-----------------

also, for a bit more advanced code scripts and coding concepts~logic (such as 'string comparison'):

Lists: stringlists, objectlists
Dictionaries: stringdictionaries, objectdictionaries, and scriptdictionaries

these are like your 'tables' or 'arrays'

String Lists:

stringlist_name = string1;string2;string3;etc
primary_colors = blue;yellow;red
days_of_week = sunday;monday;tuesday;wednesday;thursday;friday;saturdary

Dictionaries:

String Dictionaries (think conversion), for an example 'elementals' (spells, monsters, equipment, etc):

string_name = string_name // the conversion that occurs in scripting: StringDictionaryItem (Object.String_Dictionary, Value_as_a_"String")
fire = water // (fire ---> water)
water = fire // (water ---> fire)
earth = air // (earth ---> air)
air = earth // (air ---> earth)
light = dark // (light ---> dark)
dark = light // (dark ---> light)
holy = unholy // (holy ---> unholy)
unholy = holy // (unholy ---> holy)

monster.elemental = "fire"
spell.elemental = "water"

(common game elemental affinity concepts: 'strong' = damage is halved, 'weak' = damage is either doubled or x1.5, 'immune' = no damage, 'reflected' = damage is done back upon the caster, 'absorbed' = damage heals the target)

you cast a water spell on the fire monster (it's 'weak' to your water spell, thus we want to code it so that you'll do double the normal damage of the spell):

if (monster.elemental = StringDictionaryItem (global_data_object.opposing_elemental_string_dictionary, spell.elemental)) {
// if (monster:fire = opposing elemental of spell:water) {
// string dictionary's opposing elemental of water is 'spell:water -> fire'
// if ("fire" = "fire") {
-> monster.hp = monster.hp - spell.damage * 2
-> msg ("You do double the damage with your water spell against the fire monster.")
}

another example of using a string dictionary is:

month to season conversion

for example, if you make scripting that asks~gets the month, you can also return the correct season of~for that month, using a string dictionary.

(for northern hemisphere anyways, lol):

jan = winter, feb = winter, march = spring, april = spring, may = spring, june = summer, july = summer, aug = summer, sep = autumn, oct = autumn, nov = autumn, dec = winter

also, you can convert alpha strings to numbers and vice-versa:

a=1
...
z=26

and

1=a
....
26=z

// if (a), return~output: 1
// if (z), return~output: 26
// if (1), return~output: a
// if (26), return~output: z

january = 1
...
december = 12

and

1 = january
...
12 = december

// if (january), return~output: 1
// if (december), return~output: 12
// if (1), return~output: january
// if (12), return~output: december

and many more examples of uses for string dictionaries (ie: conversions)

-------

a script dictionary does the same thing, but it sets:

string_name = script

for example, you set up a topic selection code, and you choose 'dragon', it'll then output the script dictionary's script for the "dragon" string:

the wise owl Object's 'inquire about' (custom~self-made) Verb:

show menu ("What topic?", split ("dragon;sword;princess", ";"), false) {
// you choose: "dragon"
// for 'show menu' and 'get input' built-in functions, quest internally automaticallys sets the variable: result = your_choice
invoke (ScriptDictionaryItem (global_data_object.topic_string_dictionary, result)
// "dragon" -> msg ("The evil dragon kidnapped the princess.")
// outputs: The evil dragon kidnapped the princess.
}

and our "global_data_object" ('info~data storage object'):

<object name="global_data_object">
<inherit name="editor_object" />
<attr name="topic_string_dictionary">
// this is probably the wrong syntax~format, but I'm too lazy to look it up:
<item key="dragon">
msg ("The evil dragon kidnapped the princess.")
</item>
<item key="sword">
msg ("only the legendary dragon slayer sword can kill the evil dragon.")
</item>
<item key="princess">
msg ("if you rescue her, you'll become the new king, and have many kids with the beautiful princess, happily ever after.")
</item>
</attr>
</object>

george
Shmabz wrote:but just maybe a code which will find the room values and store them?


Well, I took HK's idea and got a little carried away I guess.


<!--Saved by Quest 5.4.4873.16527-->
<asl version="540">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="SlenderQUEST">
<gameid>b8c83e8c-3aa9-4646-905f-797fb4a8f96c</gameid>
<version>1.0</version>
<firstpublished>2014</firstpublished>
<start type="script">
grid_size_x = 9
grid_size_y = 9
//
msg ("Generating " + grid_size_x + "x" + grid_size_y + " grid of rooms...")
//
coords_list = NewList()
for (coord_y, 0, grid_size_y - 1) {
for (coord_x, 0, grid_size_x - 1) {
temp = NewList()
list add (temp, coord_x)
list add (temp, coord_y)
list add (coords_list, temp)
}
}
//
room_list = NewObjectList()
foreach (coords, coords_list) {
x = ListItem(coords, 0)
y = ListItem(coords, 1)
room_name = "Room" + x + y
create (room_name, "editor_room")
room_obj = GetObject(room_name)
room_obj.x = x
room_obj.y = y
room_obj.alias = "dark forest"
list add (room_list, room_obj)
}
//
dirs = NewStringDictionary()
dictionary add (dirs, "north", "0 -1")
dictionary add (dirs, "east", "1 0")
dictionary add (dirs, "south", "0 1")
dictionary add (dirs, "west", "-1 0")
//
foreach (room, room_list) {
foreach (dir, dirs) {
xy = Split(StringDictionaryItem(dirs, dir), " ")
dx = ToInt(StringListItem(xy, 0))
dy = ToInt(StringListItem(xy, 1))
target_x = room.x + dx
target_y = room.y + dy
target_room = "Room" + target_x + target_y
target_room_obj = GetObject(target_room)
if (not target_room_obj = null) {
create exit (dir, room, target_room_obj, dir + "direction")
}
}
}
//
MoveObject (player, Room00)
slenderman_starts_in = "Room" + GetRandomInt(0, grid_size_x - 1) + GetRandomInt(1, grid_size_y -1)
MoveObject (slenderman, GetObject(slenderman_starts_in))
</start>
<gridmap type="boolean">false</gridmap>
</game>
<object name="limbo">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="slenderman">
<inherit name="editor_object" />
<inherit name="male" />
</object>
</object>
<turnscript name="chase">
<enabled />
<script><![CDATA[
player_x = game.pov.parent.x
player_y = game.pov.parent.y
//
slenderman_x = slenderman.parent.x
slenderman_y = slenderman.parent.y
//
dx = player_x - slenderman_x
if (dx > 0) {
new_slenderman_x = slenderman_x + 1
}
else if (dx = 0) {
new_slenderman_x = slenderman_x
}
else {
new_slenderman_x = slenderman_x - 1
}
//
dy = player_y - slenderman_y
if (dy > 0) {
new_slenderman_y = slenderman_y + 1
}
else if (dy = 0) {
new_slenderman_y = slenderman_y
}
else {
new_slenderman_y = slenderman_y - 1
}
slenderman_moves_to = "Room" + new_slenderman_x + new_slenderman_y
MoveObject (slenderman, GetObject(slenderman_moves_to))
msg ("You are at " + game.pov.parent.x + " " + game.pov.parent.y)
msg ("And slenderman is at " + slenderman.parent.x + " " + slenderman.parent.y + ", watch out!")
if (slenderman.parent = game.pov.parent) {
msg ("slenderman catches you!")
finish
}
]]></script>
</turnscript>
</asl>


Are you familiar with the code view? It's on the toolbar in the GUi and looks like a piece of paper with writing on it. Click that and you can paste in everything above to get the whole game (or parts of it, but you have to be more careful that it'll work with code you already have).

There are two main parts to this, the start script which creates all the rooms, and the turnscript which moves slenderman to chase the player. It's not a very fair chase at the moment since slenderman homes in like the terminator :D. But you can mess with that as you like.

As you can see in the turnscript, I compare the player's coordinates to slenderman's (note that game.pov is a way of saying 'player'), and I use that to move slenderman toward the player.

Btw, the '//' is just a comment line, so Quest ignores it. I just use it to divide sections of the code.

Let me know if you have any questions/problems.

Shmabz
Okay, so would there be a way to apply JUST the Slenderman code to an already created game map with rooms named A1 - I1? Or should i rename my rooms to be stuff like 11 - 12 - 13 ----> 97 - 98 - 99 and would that work seeing as it uses generated integers that will match the room names? I have inserted landmarks in certain squares with pages as children of the landmarks, and i cannot customize the rooms generated as they are generated purely during the game and not into the GUI view, and don't really want to lose them. I can c/p my game code if you want but it's VERY long, cause i have descriptions for each room and all the exits have been made. This is absolutely beautiful though by the way, and has helped a ton!:D
Btw, what language does Quest use in the code view? It looks similar to Python but i have never seen it before o.0

------

EDIT: In short, is there a way to apply the movement turnscript to a list of already created rooms in the GUI? I don't care what i have to name and/or rename them as long as it is possible?
Is there a code for the turnscript to wait a certain number of turns before doing it again?

george
@Shmabz, yes there are a few ways. I named my rooms like that purely for convenience. If you give each room an x and y attribute (so I suppose depending on your layout your A1 might be A1.x = 0 and A1.y = 0 ?) you're most of the way there. Then perhaps create a dictionary (like I did with north, south, etc.) which uses a coordinate ("0 0") as the key and a room (A1) as the value. Then once you have the coordinate (notice the first part of the slenderman chase code doesn't use room names at all) you can check the dictionary to find the room.

http://quest5.net/wiki/Stringdictionary

If any of that is confusing let me know.

edit: Quest's scripting code is unique to Quest I think, though it uses concepts/syntax from other tools. As to running the turnscript periodically, yes that's possible. Have to run to work at the moment, perhaps someone else will explain.

HegemonKhan
you can use a 'turns' addition expression attribute within a Turnscript, and~or use a Timer. Both Timers and Turnscripts can be 'enabled' and 'disabled', and pertaining to a specific room or globally to the entire game (aka anywhere). As to a more advanced method, maybe George can help with that, some day, I'm going to learn to understand how to code what George just coded, lol.

Turnscripts and~or Timers, are like 'always executing functions' (within their setup of course), so they're very useful.

(this is very quick example below, so it's not the best coding... I can code a bit better than this, but it'd take longer)

<turnscript name="global_turnscript">
<enabled />
<script>
game.turns = game.turns + 1
</script>
</turnscript>

<object name="game">
// attributes~scripts
<attr name="turns" type="int">0</attr>
<attr name="changedturns" type="script">
if (game.turns = 5 or game.turns = 10 or // etc etc etc) {
move_slenderman_function
}
</attr>
<attr name="statusattributes" type="simplestringdictionary">turns =</attr>
// attributes~scripts
</object>

Shmabz
Okay, I'm in the process of messing with the code, ill keep you guys posted on any problems i run into if that's okay? Thanks so much :')

Shmabz
Okay, I've managed to make it so Slenderman only moves horizontally, making the game a lot easier, as well as limiting his movement to every few turns. I have also managed to figure out how to place things in random squares to randomly generate the environment, but i just have one question. How would i make it so no objects end up being in the same coordinate? Like is there a way to exclude certain squares from the random number generators once they have been taken? Also, is there a way to attach a description to some of the squares in the start script? Thank you by the way, I'm finally getting it :')

george
Way to get it done Shmabz :).

Here's a simple way to place one thing per square. Create a dictionary called occupiedRooms. The first time you place a thing, create a random coordinates where the thing will go (that's an actual room of course) and add it to the dictionary as the key, with the value as the room it represents. Now the next time you create random coordinates, you can check to see if the dictionary contains it already, and if it does, choose another coordinates.

http://quest5.net/wiki/DictionaryContains

If you already have a dictionary of coordinates -> rooms you use for another purpose, you could also check the individual room if a thing is already there. That'd be a few more lines of code though. You'd have to decide if you'd rather do that than have the extra data structure occupiedRooms.

A room's description is an attribute, see

http://quest5.net/wiki/Description

So you can set it like any other attribute.

jaynabonne
Just keep in mind that if the number of things you have is very close to the number of rooms you wish to occupy, then you could end up taking a long time to randomly find an unused room. The other way to go is to add all the rooms to a list, randomly select in turn and then remove each room from the list when it's selected so it won't be hit again. That way you'll always find a new room.

Shmabz
Thanks for the ideas and they definitely sounds like it could work!
@george: I have added in the descriptions and am in the process of customizing the descriptions for specific rooms such as adding in a pathway or two for the player to follow. Anyway, you suggested using a dictionary to index the rooms with stuff already in them? Well im gonna be honest, i have no idea how to do that :/ Could you maybe send me an example or something to help me along or start me off? I just have no idea on what the syntax is and how to call things back from dictionaries or use the "if" command to check up etc. Sorry :P
Thanks so much guys! This project is coming along great now and WILL include your names in the credits once finished :D

HegemonKhan
shmabz wrote:Anyway, you suggested using a dictionary to index the rooms with stuff already in them? Well im gonna be honest, i have no idea how to do that :/ Could you maybe send me an example or something to help me along or start me off? I just have no idea on what the syntax is and how to call things back from dictionaries or use the "if" command to check up etc. Sorry


you can study (or play with, if you're using v5.4 or if you know how to convert it to v5.5 also would work, lol) this 'explore and travel' coding of mine (not the best quality of coding, I'm still a noob at coding, but it's functional at least):

(it has all the dictionary+list stuff that you're implementing with George+Jay coding, for you to understand how lists and dictionaries work, how to count and remove~add stuff to lists, and etc)

<asl version="540">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Testing Game Stuff">
<gameid>eef801a1-4e6b-4b0a-bdbf-8f3ecfa8389c</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
<turns type="int">0</turns>
<statusattributes type="simplestringdictionary">turns=</statusattributes>
<start type="script">
msg ("Important Note:")
msg ("Type in: help")
</start>
</game>
<object name="homeland">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
</object>
<object name="grassland">
<inherit name="editor_room" />
</object>
<object name="plains">
<inherit name="editor_room" />
</object>
<object name="desert">
<inherit name="editor_room" />
</object>
<object name="tundra">
<inherit name="editor_room" />
</object>
<object name="swampland">
<inherit name="editor_room" />
</object>
<object name="mountains">
<inherit name="editor_room" />
</object>
<object name="forest">
<inherit name="editor_room" />
</object>
<object name="wasteland">
<inherit name="editor_room" />
</object>
<object name="coastland">
<inherit name="editor_room" />
</object>
<object name="hills">
<inherit name="editor_room" />
</object>
<command name="help_command">
<pattern>help</pattern>
<script>
help_function
</script>
</command>
<command name="explore_command">
<pattern>explore</pattern>
<script>
explore_function
</script>
</command>
<command name="travel_command">
<pattern>travel</pattern>
<script>
travel_function
</script>
</command>
<object name="data_object">
<inherit name="editor_object" />
<travel_string_list type="simplestringlist">homeland</travel_string_list>
<homeland_events_string_list type="simplestringlist">grassland_discovery;plains_discovery;desert_discovery;tundra_discovery;swampland_discovery;forest_discovery;mountains_discovery;hills_discovery;wasteland_discovery;coastland_discovery</homeland_events_string_list>
<homeland_events_script_dictionary type="scriptdictionary">
<item key="grassland_discovery">
list add (data_object.travel_string_list, "grassland")
msg ("You've discovered the grassland! Now, you can travel to the grassland and explore it!")
</item>
<item key="plains_discovery">
list add (data_object.travel_string_list, "plains")
msg ("You've discovered the plains! Now, you can travel to the plains and explore it!")
</item>
<item key="desert_discovery">
list add (data_object.travel_string_list, "desert")
msg ("You've discovered the desert! Now, you can travel to the desert and explore it!")
</item>
<item key="tundra_discovery">
list add (data_object.travel_string_list, "tundra")
msg ("You've discovered the tundra! Now, you can travel to the tundra and explore it!")
</item>
<item key="swampland_discovery">
list add (data_object.travel_string_list, "swampland")
msg ("You've discovered the swampland! Now, you can travel to the swampland and explore it!")
</item>
<item key="forest_discovery">
list add (data_object.travel_string_list, "forest")
msg ("You've discovered the forest! Now, you can travel to the forest and explore it!")
</item>
<item key="mountains_discovery">
list add (data_object.travel_string_list, "mountains")
msg ("You've discovered the mountains! Now, you can travel to the mountains and explore it!")
</item>
<item key="hills_discovery">
list add (data_object.travel_string_list, "hills")
msg ("You've discovered the hills! Now, you can travel to the hills and explore it!")
</item>
<item key="wasteland_discovery">
list add (data_object.travel_string_list, "wasteland")
msg ("You've discovered the wasteland! Now, you can travel to the wasteland and explore it!")
</item>
<item key="coastland_discovery">
list add (data_object.travel_string_list, "coastland")
msg ("You've discovered the coastland! Now, you can travel to the coastland and explore it!")
</item>
</homeland_events_script_dictionary>
</object>
<turnscript name="global_turnscript">
<enabled />
<script>
game.turns = game.turns + 1
</script>
</turnscript>
<function name="help_function">
msg ("Type 'explore' to explore your area.")
msg ("Type 'travel' to travel to different areas.")
</function>
<function name="explore_function"><![CDATA[
switch (game.pov.parent) {
case (homeland) {
result_1 = ListCount (data_object.homeland_events_string_list) - 1
if (result_1 >= 0) {
result_2 = StringListItem (data_object.homeland_events_string_list,GetRandomInt(0,result_1))
invoke (ScriptDictionaryItem (data_object.homeland_events_script_dictionary,result_2))
on ready {
foreach (item_x, split ("grassland_discovery;plains_discovery;desert_discovery;tundra_discovery;swampland_discovery;forest_discovery;mountains_discovery;hills_discovery;wasteland_discovery;coastland_discovery",";")) {
if (result_2 = item_x) {
list remove (data_object.homeland_events_string_list, result_2)
}
}
}
} else {
msg ("There seemingly is nothing left to explore in this area.")
}
}
}
]]></function>
<function name="travel_function">
show menu ("Where do you wish to travel?",data_object.travel_string_list,false) {
if (not game.pov.parent = GetObject (result)) {
game.pov.parent = GetObject (result)
} else {
msg ("You are already at this area.")
ask ("Try again?") {
if (result=true) {
travel_function
} else {
msg ("You realize that you need to discover a new area to travel to first, before you can travel to that place.")
}
}
}
}
</function>
</asl>

george
Shmabz, I like Jay's idea better of adding all the rooms to a list then selecting from that. How you would do that depends on whether you already have the rooms in a list.

If you have them in a list, you need a new copy of the list, so just newList = oldLIst.

If you don't have them in a list, you could do it by hand. But that sounds kind of tedious, so I think this would work:


myRoomList = NewObjectList()
foreach (obj, AllObjects()) {
if (DoesInherit(obj, "editor_room") = true) {
list add (myRoomList, obj)
}
}


As you can see, that code says, "for each object in the game see if it's a room, and if it is add it to my list of rooms". Note that this really only works at the start of the game for reasons I won't go into here.

Now to do the random placement of things, you'll work with this myRoomList. You want to select a random item from this list. You do that by counting the number of items in the list and choosing a random number no greater than that minus one. Then you select the item at that number position in the list.

To count a list, http://quest5.net/wiki/ListCount
To choose a random number, http://quest5.net/wiki/GetRandomInt

Why is the minus one important? Because when you check the positions of items in Quest lists (and really most lists in programming) you always start from 0. So, if a list has two items, the first item is at position 0, and the second item is at position 1 -- not position 1 and position 2 as you might intuitively think.

To select an item from an ObjectList, http://quest5.net/wiki/ObjectListItem

After you select this item, you want to remove it from the list. To do that, http://quest5.net/wiki/List_remove .

Then you just repeat the steps for every thing. Count the list, choose a random number, select, and remove.

HegemonKhan
quick explanation of something that often causes a lot of grief for noobs with quest's coding structure~design:

String: "belt"
Object: belt

if you want to reference an actual Object, do *NOT* surround its name with quotes
if you want to reference a string (mere text, NOT an Object in the game), then *DO* surround its name with quotes

any text that is quoted in code, tells the game engine, that it is 'Type: String'

also, note that numeral characters (-1, 0, 1,2,3,etc, and doubles~decimal characters too), are an Integer~Double, but also can be Strings too (as seen below under the "Strings" section).

the difference is again whether you use quotes or not:

Integer: 1
String: "1"

so make sure you're careful, as you'll get errors when you try to match up or use together, different Attribute Types, for examples:

"1" + 1 = ? -> (String + Integer) ... quest ... can't compute (nor can we humans, hehe)... ERROR!!!

you can change between (numeral) Strings and Integers though:

String: ToString (Object.Attribute_type_integer)
Integer: ToInt (Object.Attribute_type_string)

so (not in proper code syntax, only for conceptual example) ..

ToInt ("1") + 1 = ? -> quest... ah integer 1 + integer 1... that's easy.. it's integer: 2

ToString (1) + "1" = ? -> quest... ah string "1" + string "1"... that's easy... it's string: "11"

ToString (1) + "1" + "1" + "1" = ? -> quest... ah string "1" + string "1" + string "1" + string "1"... that's easy... it's string: "1111"

------------------------

Strings:

a collection of characters (but not all characters can be used, as they symbolize, are used for, other things in coding):

a
dead
1
1234
a1_43f_124dead_opqg6

special built-in Strings (these do *NOT* need quotes, even though 'true', 'false', and 'result' are used as 'Type: Strings'):

true, false, result, and (whatever else)

Lists (String Lists and Object Lists):

are broken ("split" function) apart strings, into choices that you can select:

string: redblueyellow
string list: (1) red, (2) blue, or (3) yellow

string -> "split" -> string list
string list -> "join" -> string

("join" is rarely used at least by a noob like me in coding, I don't even have any inkling of why~how~for what "join" is used for)

split ("string1{separator character}string2{separator character}string3{separator character}etc", "separator character")
split ("red;blue;yellow", ";")
split ("red+blue+yellow", "+")
split ("redHKblueHKyellow", "HK")

so to make a list (via quick writing):

Local Lists:

split ("red;blue;yellow", ";")
Variable = split ("red;blue;yellow", ";")

Global Lists:

Object.Attribute = split ("red;blue;yellow", ";")

examples (using "show menu"):

split ("red;blue;yellow", ";")
show menu ("What is your favorite primary color?", split ("red;blue;yellow", ";"), false) { scripting }

my_list = split ("red;blue;yellow", ";")
show menu ("What is your favorite primary color?", my_list, false) { scripting }

global_data_object.my_list = split ("red;blue;yellow", ";")
show menu ("What is your favorite primary color?", global_data_object.my_list, false) { scripting }

the other way to create lists (along with using "show menu" as an example):

Local List:

Variable = NewStringList ()
my_list = NewStringList ()
list add (my_list, "red")
list add (my_list, "blue")
list add (my_list, "yellow")
show menu ("What is your favorite primary color?", my_list, false) { scripting }

Global List:

Object.Attribute = NewStringList ()
global_data_object.my_list = NewStringList ()
list add (global_data_object.my_list, "red")
list add (global_data_object.my_list, "blue")
list add (global_data_list.my_list, "yellow")
show menu ("What is your favorite primary color?", global_data_list.my_list, false) { scripting }

Object Lists are the same, but they use actual Objects, not merely strings

----------------------------

Dictionaries (String Dictionaries, Object Dictionaries, and Script Dictionaries):

(dictionaries are quest's "tables" and~or "arrays")
(think conversion, along with using "algebraic substitution")

String Dictionaries: string = string // (string -> string)
Object Dictionaries: string = object // (string -> object)
Script Dictionaries: string = script // (string -> script)

conceptually only:

fire = water
fire -> water
if input (fire), then output~return (water)

water = fire
water -> fire
if input (water), then output~return (fire)

january = winter
january -> winter
if input (january), then output~return (winter)

1 = january
1 -> january
if input (1), then output~return (january)

january = 1
january -> 1
if input (january), then output~return (1)

actual syntax code (global usage) examples:

<object name="global_data_object">
-> <inherit name="editor_object" />
-> <attr name="opposite_elemental_string_dictionary" type="simplestringdictionary">fire=water;water=fire;air=earth;earth=fire</attr>
</object>

fire = water

Object.Attribute = StringDictionaryItem (Object.Attribute, Value)
// conceptually: Object.Attribute = output:StringDictionaryItem:conversion_function (Object.Attribute, input:fire)
global_data_object.opposite_elemental_string_dictionary = StringDictionaryItem (global_data_object.opposite_elemental_string_dictionary, "fire")
// conceptually: Object.Attribute = conversion_function (input:fire -> output:water)
// conceptually: Object.Attribute = output:water
// conceptually: Object.Attribute = water

// String dictionary: 1 = red; 2 = blue; 3 = yellow
get input {
-> // if I typed in "1")
-> result_2 = StringDictionaryItem (Object.Attribute, result)
-> msg (result_2)
-> // output: red
-> //
-> // if I typed in "2", output: blue
-> // if I typed in "3", output: yellow
}

the exact same thing takes place with Object dictionaries and Script dictionaries, for example of a script dictionary:

(I'm using a "msg" script, but you can use any script)

// Script dictionary: 1 = msg ("color is red"); 2 = msg ("color is blue"); 3 = msg ("color is yellow")
get input {
-> // if I typed in "1")
-> invoke (ScriptDictionaryItem (Object.Attribute, result))
-> // output: color is red
-> //
-> // if I typed in "2", output: color is blue
-> // if I typed in "3", output: color is yellow
}

------------

items in a list (such as my example of "red", "blue", or "yellow"), can be referenced~used~'gotten' by its count-ordering:

(1) red; (2) blue; or (3) yellow
but the list count ordering is:
0=red
1=blue
2=yellow

StringListItem (StringList, Value)

Variable = StringListItem (StringList, GetRandomInt (0,2))
// if 0 is randomly chosen: Variable = red
// if 1 is randomly chosen: Variable = blue
// if 2 is randomly chosen: Variable = yellow

Variable = StringListItem (StringList, GetRandomInt (0, ListCount (StringList) - 1) )
// Variable = StringListItem (StringList, GetRandomInt (0, 3 - 1) )
// Variable = StringListItem (StringList, GetRandomInt (0, 2) )
// if 0 is randomly chosen: Variable = red
// if 1 is randomly chosen: Variable = blue
// if 2 is randomly chosen: Variable = yellow
// NO ERROR

Variable = StringListItem (StringList, GetRandomInt (0, ListCount (StringList) ) )
// Variable = StringListItem (StringList, GetRandomInt (0, 3) )
// if 0 is randomly chosen: Variable = red
// if 1 is randomly chosen: Variable = blue
// if 2 is randomly chosen: Variable = yellow
// if 3 is randomly chosen: Variable = ... ??? = null ... ERROR!!!
// ERROR !!!!

-----------------

dictionary items can't be referenced~used~'gotten by a count-ordering, so you have to use strings (or Objects or Scripts ~ depends on the type of dictionary obviously):

String Dictionary: fire=water; water=fire; earth=air; air=earth

Variable = StringDictionaryItem (String Dictionary, "fire")
// Variable = "water"

Variable = StringDictionaryItem (String Dictionary, "water")
// Variable = "fire"

Variable = StringDictionaryItem (String Dictionary, "air")
// Variable = "earth"

Variable = StringDictionaryItem (String Dictionary, "earth")
// Variable = "air"

show menu ("what is your opposite elemental?", split ("fire;water;earth;air", ";"), false) {
-> msg (StringDictionaryItem (String Dictionary, result))
-> // if you selected "fire", outputs: water
-> // if you selected "water", outputs: fire
-> // if you selected "earth", outputs: air
-> // if you selected "air", outputs: earth

-----------------

and the big two parts of using both lists and dictionaries are...

the "foreach" function:

one example of how 'foreach' works, is by looking at Chase's Wearables Library in the Libraries+Code board section of this site

string comparison:

monster.elemental = "fire"
your_spell.elemental = "water"

String Dictionary: water=fire

conceptually:

if (monster.elemental = StringDictionaryItem (String Dictionary, your_spell.elemental)), then you do double damage as the fire monster is weak to your water spell

if ("fire" = StringDictionaryItem (String Dictionary, "water")), then you do double damage as the fire monster is weak to your water spell

if ("fire" = (water -> fire) ), then you do double damage as the fire monster is weak to your water spell

if ("fire" = "fire"), then you do double damage as the fire monster is weak to your water spell

---------

I'm getting tired, hopefully you can understand some of this attempt of mine at explaining this (more advanced coding and coding-logic) stuff.

let me know if anything confuses you, or if you need help, and I'll try to help you better and hopefully so that you can better understand this stuff... hehe.

---------

P.S.

see if you can use this post, to understand my previous post's 'expore~travel' coding

jaynabonne
Some notes:

If you have them in a list, you need a new copy of the list, so just newList = oldLIst.



Actually, no. :) That will just copy the list reference. It will be the same list referenced by two variables. One way to create a new list is to use ListCombine:

newList = ListCombine(NewObjectList(), oldList)


If you don't have them in a list, you could do it by hand. But that sounds kind of tedious, so I think this would work:

Code: Select allmyRoomList = NewObjectList()
foreach (obj, AllObjects()) {
if (DoesInherit(obj, "editor_room") = true) {
list add (myRoomList, obj)
}
}


Keep in mind that this will break if you ever publish your game, as all references to the "editor" types are stripped during the publishing process (so no objects will be in the above list in such a case). If you wished to go that route, you'd probably have to define your own room base type which will still be valid once published.

george
Oops, thanks Jay, I must have been confused reading something about copying objects on assignment.

jaynabonne
Ah, well that is true if you assign to an object attribute. It will make a copy of the list or dictionary in that case. But not in the general script variable case. :)

Shmabz
Okay, thanks so much for the help all you guys! I am following your instructions, and have run into a minor problem: The function ListCombine won't work :/ Here is my start script below, and as you can see i have used george's original code as a base. My new entry is just a trial and is located at the very last lines of the code. The error said that it could not function "room_list". I have put arrows next to the starting line in the block of code i have just typed up with the problem in, and the block containing the list i am using to combine.

      grid_size_x = 9
grid_size_y = 9
//
msg ("Generating environment...")
//
coords_list = NewList()
for (coord_y, 0, grid_size_y - 1) {
for (coord_x, 0, grid_size_x - 1) {
temp = NewList()
list add (temp, coord_x)
list add (temp, coord_y)
list add (coords_list, temp)
}
}
//
-----> room_list = NewObjectList()
foreach (coords, coords_list) {
x = ListItem(coords, 0)
y = ListItem(coords, 1)
room_name = "Room" + x + y
create (room_name, "editor_room")
room_obj = GetObject(room_name)
room_obj.x = x
room_obj.y = y
room_obj.alias = "Dark Forest"
room_obj.description = "Countless rows of tall trees extend in all direction with no immediate landmarks in sight. There is a strong feeling of isolation emmanating from the forest itself."
list add (room_list, room_obj)
}
//
dirs = NewStringDictionary()
dictionary add (dirs, "north", "0 -1")
dictionary add (dirs, "east", "1 0")
dictionary add (dirs, "south", "0 1")
dictionary add (dirs, "west", "-1 0")
//
foreach (room, room_list) {
foreach (dir, dirs) {
xy = Split(StringDictionaryItem(dirs, dir), " ")
dx = ToInt(StringListItem(xy, 0))
dy = ToInt(StringListItem(xy, 1))
target_x = room.x + dx
target_y = room.y + dy
target_room = "Room" + target_x + target_y
target_room_obj = GetObject(target_room)
if (not target_room_obj = null) {
create exit (dir, room, target_room_obj, dir + "direction")
}
}
}
//
Room00.description = "There appears to be a path leading to the south."
Room01.description = "There appears to be a path leading to the north and south."
Room02.description = "There appears to be a path leading to the north and east."
Room07.description = "There appears to be a path leading to the east."
//
Room12.description = "There appears to be a path leading to the east and west."
Room15.description = "There appears to be a path leading to the east and south."
Room16.description = "There appears to be a path leading to the north and south."
Room17.description = "There appears to be a path leading to the north, east and west."
//
Room21.description = "There appears to be a path leading to the east and south."
Room22.description = "There appears to be a path leading to the north, south and west."
Room23.description = "There appears to be a path leading to the north and south."
Room24.description = "There appears to be a path leading to the north and south."
Room25.description = "There appears to be a path leading to the north and west."
Room27.description = "There appears to be a path leading to the east and west."
//
Room31.description = "There appears to be a path leading to the east and west."
Room37.description = "There appears to be a path leading to the east and west."
//
Room41.description = "There appears to be a path leading to the east, south and west."
Room42.description = "There appears to be a path leading to the north and south."
Room43.description = "There appears to be a path leading to the north and south."
Room44.description = "There appears to be a path leading to the north and east."
Room47.description = "There appears to be a path leading to the east and west."
//
Room50.description = "There appears to be a path leading to the east and south."
Room51.description = "There appears to be a path leading to the north and west."
Room54.description = "There appears to be a path leading to the east and west."
Room57.description = "There appears to be a path leading to the east and west."
//
Room60.description = "There appears to be a path leading to the east and west."
Room64.description = "There appears to be a path leading to the east and west."
Room66.description = "There appears to be a path leading to the east and south."
Room67.description = "There appears to be a path leading to the north, south and west."
Room68.description = "There appears to be a path leading to the north."
//
Room70.description = "There appears to be a path leading to the south and west."
Room71.description = "There appears to be a path leading to the north and south."
Room72.description = "There appears to be a path leading to the north and south."
Room73.description = "There appears to be a path leading to the north and south."
Room74.description = "There appears to be a path leading to the north, east and west."
Room76.description = "There appears to be a path leading to the east and west."
//
Room84.description = "There appears to be a path leading to the south and west."
Room85.description = "There appears to be a path leading to the north and south."
Room86.description = "There appears to be a path leading to the north and west."
//
msg ("Building terrain...")
msg ("Adding movement...")
msg ("Finalising transitions...")
msg ("Inserting player...")
msg ("Inserting Slenderman...")
//
object_starts_in = "Room" + GetRandomInt(0, grid_size_x - 1) + GetRandomInt(1, grid_size_y - 1)
MoveObject (bigtree, GetObject(object_starts_in))
msg (object_starts_in)
object_starts_in = "Room" + GetRandomInt(0, grid_size_x - 1) + GetRandomInt(1, grid_size_y - 1)
MoveObject (slenderman, GetObject(object_starts_in))
//
MoveObject (player, Room44)


----> placementList = ListCombine(NewObjectList(), room_List)
listLength = ListCount (placementList)
index = GetRandomInt(0, listLength - 1)
placementRoom = ObjectListItem (placementList, index)
MoveObject (friend, GetObject(placementRoom))
msg (placementRoom)
list remove (placementList, placementRoom)

jaynabonne
One problem: instead of this:

placementList = ListCombine(NewObjectList(), room_List)

try this:

placementList = ListCombine(NewObjectList(), room_list)

Shmabz
You're a genius!! ^-^ Thank you so much it's working fine c:

Shmabz
OKay, ive managed to get pretty much the whole game working. I've managed to get the landmarks to be places randomly as well as the 8 pages to choose between 10 landmarks to be their parents, with none choosing the same parent. I have also remove the coordinate system with slenderman and got it so if he is 2 blocks away the player is issued a warning saying he is nearby, but not the exact coordinates. Now it's just fiddling with the scoring and end of the game, thanks so much everyone!! Btw, do you want me to put your display names from this website in the Author section, or are there any other names you want?:D

george
Nice work, as for me you can do the acknowledgements however you like, or not at all. I'm just here for the fun of it :).

Shmabz
Alright, one more thing ;) I have a background soundtrack and a sound effect for taking a page, however whenever the game plays the taking page sound effect the background music stops. Is there a way to keep it playing in the background even when other sounds are playing? Thanks :)

george
Not just with Quest. See this thread,

viewtopic.php?f=10&t=3075

I think the only option right now is to find a JS lib that works and integrate it with the Quest game. As far as I know no one has done this. I read in another thread that Jay tried with SoundJS and couldn't get it to work very well, but that was a while ago.

Shmabz
Hey, basically when i publish the game it just comes up with this error, and doesn't transfer any of the objects to any of the rooms, everything including the player stays in 'limbo'. It comes up with this....
Error running script: No element 'editor_room' of type 'ObjectType'
Any help guys? I know it's been a while xD

jaynabonne
A guess: you should never use the type "editor_room" (or editor_ANYTHING) in your scripts. Their purpose is to allow the editor to correctly identify things while you're editing, but when you publish, all the editor types are stripped out. So if you check if something is of type editor_room or try to create something of type editor_room in your code, it will fail once published.

Shmabz
So what should i use instead? Or can i just delete it?

Shmabz
So what should i use instead? Or can i just delete it?
Because i use things like this in the code: create (room_name, "editor_room")
Are there any alternatives?

jaynabonne
If you can show how you're using it, I can probably suggest an alternative.

If you're checking the type of something and you need to know it's a room, then you can just create your own base room type, which will remain when published. If you're doing some sort of object creation, you can just get rid of the editor_room type and let it use the default.

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums