Text RPG Design Thread [1 new, on: Screenshot, working cmd]

Advanced game related topics
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

Sorry that I wasn't very clear.

This was more of an efficiency question. So what I was asking is, could I test all the slots at once, from one statement versus using an IF for each test, or using nested IF's.

Or is there really no speed difference?

Your example was what I was thinking of doing, I was just unsure if it would always work as expected and considering other ways I might write it.
User avatar
TomS
Enthusiast
Enthusiast
Posts: 342
Joined: Sun Mar 18, 2007 2:26 pm
Location: Munich, Germany

Re: Text RPG Design Thread

Post by TomS »

It actually seems that the one-liner is faster.
(I'm no ASM expert by all means). It's just fewer lines and the two-liner has an extra XOr. But I don't know why :P
But one or two extra asm-commands is nothing. You have to take a gazillion runs to actually note a difference...
So it's still: Whatever suits you best.

Code: Select all

; 
; a=1
  MOV    dword [v_a],1
; b=2
  MOV    dword [v_b],2
; If a = 1 
  MOV    ebx,dword [v_a]
  CMP    ebx,1
  JNE   _EndIf2
; If b = 2
  MOV    ebx,dword [v_b]
  CMP    ebx,2
  JNE   _EndIf4
; c=#True
  MOV    dword [v_c],1
; Endif
_EndIf4:
; Endif
_EndIf2:
; 

Code: Select all

; 
; a=1
  MOV    dword [v_a],1
; b=2
  MOV    dword [v_b],2
; If a = 1 And b = 2
  MOV    ebx,dword [v_a]
  CMP    ebx,1
  JNE    No0
  MOV    ebx,dword [v_b]
  CMP    ebx,2
  JNE    No0
Ok0:
  MOV    eax,1
  JMP    End0
No0:
  XOr    eax,eax
End0:
  And    eax,eax
  JE    _EndIf2
; c=#True
  MOV    dword [v_c],1
; Endif
_EndIf2:
; 
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

lol.. like I could read that :lol:

It's all good. I've learned a lot today and set some new design changes in motion, so all in all I've been very productive considering I haven't written any practical code yet! :mrgreen:

The last questions I will ask for today, are related to ideas for setting up my commands.

I don't really know how I should do it.. I could probably use an example first and foremost, on tokenizing my input line..
It will be coming from a PB String Gadget, that much is certain. I'm not sure how to setup a proper trigger to dump the input line into a variable though..

I do plan on putting a Hotkey in my GUI code so that when the user types something and presses the Enter key, I want it to capture whats in the String Gadget and put it into a variable called "Input$" or some such thing.

After that... does PB have a Tokenizer? Or will I need to manually Split the string by looking for space delimiters?

I'd like to be able to manipulate the Token and use it during calls to the Command that is picked out..

So if I type "wear necklace", that is simple enough to work with as the format of the Equip/Wear command would be <Equip (object)>. So I'd like to make sure I can pass "necklace" as the (object) and then I could do something fancy such as...

Get the GUID for the neckless and if possible reference it within the List() by its GUID (the GUID should be its List Element Name, so SelectElement() ??) then I can query any other info I need about it directly, and change info like the current owner, etc.. That should save me some cycles on list iteration I think?

I am hoping by doing the initial iteration and grabbing its GUID I could make testing for objects the player is holding much easier to do.. Because if you simply check for it to be held in one of the hands, how do you know which hand is holding the correct item to equip, etc? Without doing something more verbose I mean.. I think this might be a good idea to do.

-------

Lastly, I don't really know how I can/should setup more complex commands that perhaps take several tokens to complete?
I don't know how to programatically setup the syntax for such commands...

You know how some PB commands can take multiple arguments, and some of them optional? I want to know how to setup a Procedure to do THAT.. How does it distinguish between what is a required syntax and what is an optional value? I'm guessing optional values would have to be on the end of the syntax ? Can you skip a value at all if it isn't present? If so, how?

I hope you understand what I am asking :oops:
User avatar
TomS
Enthusiast
Enthusiast
Posts: 342
Joined: Sun Mar 18, 2007 2:26 pm
Location: Munich, Germany

Re: Text RPG Design Thread

Post by TomS »

Haha. Neither can I really. But I hope you see that there's very little difference between the two codes ;)
I'm not sure how to setup a proper trigger to dump the input line into a variable though..
I do plan on putting a Hotkey in my GUI code so that when the user types something and presses the Enter key, I want it to capture whats in the String Gadget and put it into a variable called "Input$" or some such thing.
That's exactly the way it needs to be done.
Wait for a trigger-event (either Hotkey, or button nearby) and simply store it in a variable, or in a list, so that you can use Cursor-Up to iterate through the list. I find that function extremely useful in the windows cmd.
Oh, there was a typo. Cursor-Up, search and correct typo, enter. Tadaaa.
Saves a lot of time when dealing with complex commands.
Just an idea for you ;)
GetGadgetText() is the function for that.

You can split the string by any delimiter you like (including Space, ofcourse). Use StringField()

For SelectElement() you'd have to know the exact position of the object in the list. So that's most of the time not an option (it defies the use of a linked list. If I wanted to get to entries by calling their position, I would use an array).

I'd do it like this:
Upon entering the room you create (or clear for every room but the first one (first one being the room you're starting after loading a save-file. Not necessarily the room you start the game in)) a list of all the objects in this room and the inventory of the player.

Then you find the command, you'll actually use.
Use a map for this.

Code: Select all

NewMap commands.s()
commands("wear") = "equip"
commands("equip") = "equip"

commands("attack") = "attack"
commands("fight") = "fight"
.

By simply calling commands( token_1 ), you know the player wants to equip an item.
Now you iterate through that list of objects in the room (it's a very small list of maybe max. 10 objects?)

Code: Select all

Foreach ObjectsInRoom()
    If ObjectsInRoom()\name = token_2
        ObjectsInRoom()\parent = playerUID ;
    Endif
Next
Alternatively you could do something like this. It's even better, but it only works with equip. If he want's to put something down/in a chest... you should simply change the parent.

Code: Select all

Foreach ObjectsInRoom()
    If ObjectsInRoom()\name = token_2
       Equip(ObjectsInRoom()\UID) ;
    Endif
Next
Where Equip looks like this:

Code: Select all

Procedure Equip(id.i)
	
	If slot_1 = 1
		If slot_2 = 1
			If slot_3 = 1
				ProcedureReturn #False ;No slot available: "You can't equip whatever, because you have no empty slots...."
			Else 
				slot_3 = id
			EndIf 
			ProcedureReturn #False ;No slot available: "You can't equip whatever, because you have no empty slots...."
		Else 
			slot_2 = id			
		EndIf 
		ProcedureReturn #False ;No slot available: "You can't equip whatever, because you have no empty slots...."
	Else 
		slot_1 = id 		
	EndIf 
	
	ProcedureReturn #True
	
EndProcedure 
You see I used 3 lines instead of only 1.
Because I wanted to know which of the slots is empty.
The necklace is placed in the first empty slot.
[X][X][ ] -> [X][X][O]
[ ][X][ ] -> [O][X] []
[X][ ][ ] -> [X][O][ ]
etc...

So at this time (Equip() returns #True) you delete the necklace from the List of Objects in the Room.
Upon leaving the room you iterate through the whole list of all Objects (you need to do that anyway to build the list for the next room) and you change the parent of the necklace from roomX to players_inventory.
I'm guessing optional values would have to be on the end of the syntax ? Can you skip a value at all if it isn't present? If so, how?

Code: Select all

Procedure test(mandatory1, mandatory2, optional1=0, optional2=99)
    Debug mandatory1
    Debug mandatory2
    Debug optional1
    Debug optional2
EndProcedure

test(1, 2)    
test(1, 1, 1, 1)
test(1, 1, 1)
test(1, 1, 0, 1)
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

Haha, I forgot Lists run off element numbers when selecting, you're right. I could just use a map in that case like you said.

A lot of what you outlined is how I was planning to design it, so good to know I am on a good track :)
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

Not really a question per say, but I'm just thinking out how I want to do several types of items..

I have a base Item Structure which contains definitions for the minimal set of values every Item in the Game should have and that need to be filled out. Then I start branching out, with Extended Structure Definitions, to cater more widely to various sub-types. I'm using this method because for one, it aids in keeping code clean and organized. I feel its sloppy and wasteful of resources to do things under one umbrella Structure, or even with only one or two Extended Structures, why allocate memory for fields you will not be using on particular items?

Take stackable consumables as an example.. I will have several kinds of Items that can be consumed, as well as stacked, or a combination of both.. I think it warrants separate Extended Structures to deal with this case, as while a stackable Item like a Monster Pelt may need to keep track of the quantity in the stack, that field is useless for an Item like a Healing Potion, or Herb where you only really have to track the number of drinks/bites left.. Now you might say I could use the Quantity field for both kinds of items but this is not the case! Potions and Herbs will not operate on a "1 item, 1 use" principal. Each individual Item will have a number of uses before it is destroyed, so I need to keep track of the "quantity" in a different manner. When combining Potions or Herbs, you add the number of uses together to create a single item with a high number of uses (up to a max number of allowed uses per single combined item).. The number of uses could also be a random value that is rolled at the time of item creation..

So if the max you could combine identical potions of the same type, was to 10 uses, you might be adding 10 individual potions with 1 use left, together to make 10.. or as few as 2 potions (7 & 3, or 5 & 5) etc.

Whereas something like Pelts are single items with no "uses" (you sell them for cash), but can be stacked into bundles of 25 or something like that.. Then you can simply combine up to 25 individual pelt items using the Qty field. Arrows could work on the same principle..

No sense making a structure that has both "Qty" & "Uses" fields when both won't be used; but I also feel like doing a single structure and using the same field in all, could easily lead to mishaps with math calculations etc if you get confused about which you are working with, and easily introduce bugs.

So.. I think when it comes to defining Structures and Extending them, I should worry more about organization and ease of use than worry about being "compact" and writing less code.

What say you?
User avatar
TomS
Enthusiast
Enthusiast
Posts: 342
Joined: Sun Mar 18, 2007 2:26 pm
Location: Munich, Germany

Re: Text RPG Design Thread

Post by TomS »

I know I'm preaching, what I don't do myself (and didn't in the last code I posted...), but I learned in OOP that you should never access a scalar (this would be a structurefield in PB) directly.

Pseudocode:

Code: Select all

Structure object_props
	id.i
	name.s
	qty_and_uses.i
EndStructure 

Procedure UseItem(item)
	If item\qty_and_uses > 0
		item\qty_and_uses - 1
		ProcedureReturn #True
	Else
		ProcedureReturn #False
	EndIf 
EndProcedure 

Procedure AddToStack(item, number)
	If item\qty_and_uses + number < 26
		item\qty_and_uses + number
		ProcedureReturn #True
	Else
		ProcedureReturn #False
	EndIf 
EndProcedure

UseItem(Potion)
AddToStack(Pelt, 3)
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

I understand what you're saying. I don't think I will be accessing them directly, but like you used in your example, I would have a Procedure (probably the direct command involved) that interacts with the fields.


For some reason I now have this idea brewing in my head.. to make a smaller game project, before I really set to work on this one.. lol
It would be a pretty simple game, either using the console and text, or some 2D graphics... It would be like a Mech Battle Arena or something, where you fight against the CPU in Turns/Rounds and you win Money which you use to upgrade your Mech... or something silly like that :?

I don't know why, it just popped into my head!
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

So I've been mulling over a certain problem for a while now.. I can't really figure out a logical way to handle one of the most important features I want to implement.

The Quest System!

The way I envision this thing working, its probably going to need to pull data from multiple sources, I'm not even sure how to store the more generalized data at this point..

I'd like it to be real-time of course, so I can have quest timers (you fail after so long) for some events. But I might also need to do a lot of stuff that relies on "triggers".. i.e Changing the environment of a certain room to enable a hidden exit, or to open a path to a new area. I'd like to be able to change the speech of some NPC's as well..

i.e if you're on a certain quest and they are meant to give helpful hints, make sure they only give them out if you indeed are actively on the quest.

I'm almost afraid I would have to hard code such things into the game, which bothers me as I am trying to keep the engine re-usable.. I don't know if I have the skill/ingenuity to implement even a basic type of scripting language to handle these things though..

Thoughts? Ideas?
User avatar
TomS
Enthusiast
Enthusiast
Posts: 342
Joined: Sun Mar 18, 2007 2:26 pm
Location: Munich, Germany

Re: Text RPG Design Thread

Post by TomS »

My first thought would be to use a parent-system just like with objects.
I'll elaborate, and then let's see if you find any flaws in my thinking (there are probably some things that are important to the gamer, that I don't realize, because I never played a text-rpg and other than Ocarina Of Time's Biggoron-sword, I never really had a quest).

So you have a list of quests. Each one with a UID once again.
The quest is divided in parts or steps. Each action that alters the environment (this would mainly be talk, take/give item or use switch) is a step.

So a simple quest may be:
Grandfather: Be a good grandson, and bring me some milk from the market. Be sure to ask your mother, who is also on the market, selling crops, to give you some money.

So the steps would be:
  1. Accept quest
  2. Talk to mother / Receive Money
  3. Talk to dairy farmer / Receive Milk
  4. Talk to grandfather / End quest (QuestID = 0) / Receive Award/Whatever
Every NPC has a list of lists of lists (inception :shock: ) with their text to say.


(questID=0, stepID, "Text to say") ;(If questID = 0 you are on no quest currently. NPC will say standard phrases)
Instead of string, there are lists that you either iterate through or choose a line of text randomly from.

Code: Select all

;The mother's text list looks like this.
(0, 0, "blabla - standardtext")
(0, 0, "blabla - another line of standard text. Every NPC will repeat the blabla after a while...")
;questID = 1. This is set upon accepting our grandfather's quest.
(1, 1, "You want money to buy grandfather some milk? Here you go. You're a good son and a good grandson, too")
;At this point we receive money and the current step is now (2)
(1, 2-3, "What are you still doing here? Go get grandfather some milk!")

;Now the farmer:

(0, 0, "blabla - We have fine milk here. Only 2$ (whatever)")
(0, 0, "blabla - another line of standard text. Every NPC will repeat the blabla after a while...")
;questID = 1. This is set upon accepting our grandfather's quest.
(1, 1, "You want Milk? Well, do you have money? No? Then I'm sorry. No milk for you....")
;Step 2 means, we have money.
(1, 2, "There you go. Some fresh fine milk for you. Be sure to come again when it's empty. We're here 24/7")

;Step is now 3
; Grandfather:

(1, 1-2, "Have you brought my milk? No? Go, go. Don't be lazy")
(1, 3, "Thanks for the milk. Here take this extraordinary item that may come in handy after 8 hours of nonstop gameplay....")

;The last step (4) is not necessary, because the quest is over at this point. 
;So step 4 is actually just part of a guide, or a checklist and has no meaning to the programm itself.

Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

I kind of get what you are saying here. Interesting recommending the List of lists of list of list of lis.... sorry.. Interesting ;) Given all the trouble we've gone through thus far to eliminate such lists.. However that doesn't mean it's a bad idea! :mrgreen:

I may be able to work with this.. although I'll probably modify it heavily along the way... Won't know until I get around to having to do it (if you haven't noticed I'm trying to get rough ideas on a broad range of subjects before I try building something and fail miserably).

Although I am still investigating the possibility of using some kind of scripting engine along the way.. Hell, if it were easy I'd love to integrate Python, but I'm pretty certain that would be an arduous task.


I came across a post on the forum from 2008, for BriskVM; Aside from the slightly rude reception it got, the gamers in the thread seemed to think it looked like a great tool, and it appears to be developed with bindings for PureBasic as well.. It makes integration look -really- easy vs doing something from scratch. I checked out the site and it costs 15 Euros (so about $20 USD I think) which seems like a pretty decent price for the Indie license..

I was wondering if we might have anything on the forums similar to this, like a User DLL or something where all the hard work has been done? :P Does anyone remember any projects like that?
User avatar
TomS
Enthusiast
Enthusiast
Posts: 342
Joined: Sun Mar 18, 2007 2:26 pm
Location: Munich, Germany

Re: Text RPG Design Thread

Post by TomS »

I don't see where WE did go trough trouble to avoid lists?
I was the one who recommended them.
You need to store the random talking of every NPC somewhere. Why not use the same storage for the talk in quests?
Whatever has an ID in this main list of blabla must be used as either a map or an array. I'd recommend array, because of the integer-key. Not because of speed issues, but because it's easier to simply iterate through the list by adding 1 to an internal counter.
So list doesn't necessarilly mean LinkedList. But you need a list if you don't want to load every single line of text from the database, when needed.
Upon accepting the quest you load every line that belongs to that quest and store in the list.
The rest is being taken care of by the "talking-engine" and the "inventory-engine".
The same lines of code that make NPCs talk to you and that organizes your giving/taking items.

Are you talking about an ready-made engine for (text-) rpgs or about some scripting engine.
If the latter, have a look at pbscript. It's a scripting engine based on the PB syntax.
Although I don't know if you can interact with your PB progamms or if it's just a standalone interpreter.

There's also some code that allows you to execute VBS scripts in your code.

As for a rpg engine there's nothing I would know of.
There was an open source project called "Lost Labyrinth". It was a 2D rpg. But like many advanced open source projects it would be hard to adapt, because it's probably not 100% clean code that is portable to your needs in 10 minutes.


But if you would write a neat engine like we've been planning for the last couple of pages, you could release it and maybe even charge some money for it ;)
All those abstract ideas here would be the perfect backbone for any rpg, if they stayed this abstract.
An abstract quest system with an abstract inventory system could be used for a 2D or a 3D RPG as well.
The only thing one needs to change is the structure of the rooms (obviously the output has to be graphical) and the movement of the player.
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

Basically I'd be looking for an already developed scripting language, that can be integrated in a rather trivial and easy manner.. (and include, some initialization calls etc) Which would allow me to interact with procedures I choose to expose to the scripting engine. Since it would be a bad idea to modify data directly, and all.

It would definitely make the engine very extensible, and could allow for things such as overwriting anything default I might otherwise hard-code into it, like a particular sub-system (combat mechanics, the quest system, stuff like that). Granted I can make most of that stuff modifiable but there would still end up being a default rigid structure, and I'd have to do some twisted coding to allow changes to things like math formulas etc, (since changing numbers in itself isn't really modifying anything but difficulty, where a combat system is concerned).

I have often thought about making such an engine, or series of Text RPG's for profit in this manner.. Even going so far as to include multiplayer support and the ability to run a server that could hold enough people to build a small community around, if people wanted.. But I am probably eons away from being able to produce something of that level of quality.


Although I'm not sure how many people would really want to buy something like that these days.. Even when I got into MUDs in the 90's when I was a teen, it was clear to me that Text games are a very niche product and hard to sell.

I've thought about just doing something for free and then having a donate button, more than anything... OF course I can't use paypal for reasons I don't want to go into, and all these other Internet Money sites look like shady operations when I dig into their background... I can't win :mrgreen:


and finally,
I don't see where WE did go trough trouble to avoid lists?
I was half joking in reference to all the lists I wanted to use in my structures, that you advised me against since there was a better way to do it ;)
User avatar
TomS
Enthusiast
Enthusiast
Posts: 342
Joined: Sun Mar 18, 2007 2:26 pm
Location: Munich, Germany

Re: Text RPG Design Thread

Post by TomS »

Yes, there's a difference between an object like a sword, and a text object.
The sword can be in room1 or in room99 or in a chest in room590 or in the inventory. It could be everywhere in the entire world that exists within your game.

The text "Go get grandpa some milk" on the other hand is spoken a very unique NPC in your game.
It's not like zombies running around would scream lines that normally a friendly NPC is supposed to say (except when your grandpa is zombiefied. But then it would be easier to create another NPC and delete the old one and viceversa, when you heal him).

So moving a sword from one list to another is messy and slow.

Code: Select all

ForEach list()
    If list()\id = ID
        AddElement(list_2())
        list_2()\id = ID
        list_2()\bla = list()\bla
        list_2()\blubb = list()\blubb
        ;and so on - Imagine adding another value to the structure in a later state of development...
    Endif
Next
It's easier to "move" it from one virtual container to another.

Code: Select all

ForEach list()
    If list()\id = ID
        list()\parent = NewParent
    Endif
Next
The text lines of the NPC don't need to be moved at all. They're static.
So loading every relevant line of text upon accepting a quest and then iterating through that small amount of objects is faster than a huge list of +10.000 lines of speech.
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Text RPG Design Thread

Post by Zach »

I understand that.. I think you are taking a light-hearted comment much too seriously :|
Post Reply