how to load level data from txt file? please help!

BlitzMax Forums/BlitzMax Beginners Area/how to load level data from txt file? please help!

Caton(Posted 2015) [#1]
how do I read\write this text file?

level.txt
=====================
Level Data
{
musictrack = 1
volume=0.5
sound = "sound.wav"
data = 1, -1, -1, -1, -1
}
====================


xlsior(Posted 2015) [#2]
FWIW, it may be easiest to get one of the ready-made XML reader/writers... Check the code archives on the forum.


Caton(Posted 2015) [#3]
I want to read\write this text file in blitzmax I don't want to use xml.


Henri(Posted 2015) [#4]
Hi,

there are multiple of ways to load text file, but easiest would probably be 'LoadText("Your_text_file.txt")'. This loads your file into a string which leaves it up to you to parse the data.
Afterwards string data can be saved using 'SaveText(your_string, "your_file.txt")'

-Henri


Brucey(Posted 2015) [#5]
As Henri says, if you use your own custom format, you'll need to build your own parser for it too.

You could process the text line by line, and depending on its content, process each line as appropriate.

You can split strings using the Split() method.
You can use Find() to find interesting characters.
There's also StartsWith() for interesting things at the beginning of strings.

With some small tweaks you text format could be JSON ( http://www.json.org/ ).
In which case there are some parsing modules/code available already.


Fielder(Posted 2015) [#6]
topic for "beginners area" i think, there is an active forum moderator?


Midimaster(Posted 2015) [#7]
You have to open a text file, separate the lines, analyse the left side of the text. At the end to have to asign the right side values to the corresponding variables.

Your text loos a little bit like "INI"-files, where you find a lot of samples in this forum.

typical INI:
[Level Data]
musictrack=1
volume=0.5
sound="sound.wav"
' comments are allowed
data1=1
data2=-1
data3=-1
data4=-1
data5=-1
[Player Data]
X=5
....


here I helped somebody with nearly the same question:

http://www.blitzbasic.com/Community/posts.php?topic=96726#1120401


Caton(Posted 2015) [#8]
level.txt
=====================
Level Data
{
musictrack = 1
volume=0.5
sound = "sound.wav"
data = 1, -1, -1, -1, -1
}
====================
could you help read this text file?
it's not a ini file.
it you could help I would be very thankful.


Brucey(Posted 2015) [#9]
You want someone to write the code for you?


Derron(Posted 2015) [#10]
But he would be very thankful...


- Load each line
- if line.trim() ="{" then OpenBracket :+1
- elseif line.trim() = "}" then OpenBracket :-1
- elseif OpenBracket > 0 then parts:string[] = line.Split("=")
- - command = parts[0].trim()
- - payload = "" (if parts.length < 2) or parts[1].trim()


bye
Ron


Caton(Posted 2015) [#11]
will this work in blitzmax?
I don't see read file.
and "--" isn't part of blitzmax.
how would this work in blitzmax?


Xerra(Posted 2015) [#12]
Just copy/pasted this code for loading and saving a high score table in an old game I wrote. It's pretty primitive but it should give an idea about how to open/close files and read in lines.

Function LoadScores()
		' ** Load the high scores file **
		Local S:TStream = OpenFile(File_HighScores)
		If Not S ' If high score data file not present then create defaults.
			Initialise()
		Else
			For T = 0 To 4
				HighName[T] = ReadLine(s)
				HighScore[T] = Int(ReadLine(s))
			Next
			CloseFile S
		End If
	End Function
	
	Function SaveScores()
		' ** Save the high scores file **
		Local S:TStream = WriteFile(File_HighScores)
		If Not S
			' ** Error Saving File - just exit for now **
		Else
			For T = 0 To 4
				WriteLine (S, HighName[T])
				WriteLine (S, HighScore[T])
			Next
			CloseFile S
		EndIf
	End Function




Brucey(Posted 2015) [#13]
will this work in blitzmax?

Not as is. You'll need to put some effort in yourself to fill in the rest, but it gives you an idea of the things you might do to parse the text.

How are you getting on with the rest of your game?


Midimaster(Posted 2015) [#14]
Is the text file yours? Or do you use it from a third party? How long is it in the end? Is there a need to keep it exactly in this way?

I ask, because i contains a lot of "problems", which will cause a longer code. So if you can, I would suggest to build the TXT-file in an other way (more systematic). f.e. As an INI-file.

The problems are:
1. comment lines like the first line without a comment sign
Level Data

better...
'Level Data

Or is this a headline? Block-Definition?


2. lines with "=", but sometimes without SPACEs, sometime with SPACEs
musictrack = 1
volume=0.5

better...
musictrack=1
volume=0.5




3. lines with more than one data

data = 1, -1, -1, -1, -1

better...
data1=1
data2=-1
data3=-1
data4=-1
data5=-1


Please tell us a little bit more about the TXT-file and why it has to be like this? Tell us, why a INI file would not be better.


Derron(Posted 2015) [#15]
@lines with more data

an
- parts = line.split("=")
- blockname = parts[0].trim()
- blockparts = parts[1].split(",")
- for blockpart = EachIn blockparts
- - add value blockpart.trim()
is easier to write and understand than
- parts = line.split("=")
- blockname = parts[0].trim()
- somehow split away numbers from variable names
- add value parts[1].trim() to the identified structure

So if something is already grouped, there is no need to remove that information from the file format.


@spaces
As long as spaces at the begin or end of the rhs-value, trim() is your friend.


@No working code
As brucey stated: I do not give you working code examples as this whole thing is more an excercise for you. If you want others to write code for you, you might also post the bounty you are paying for doing so.

And the most disturbing thing is: you wrote that in the programmers section, not the beginners section - so this implies you should already have an basic knowledge of doing things.
This then means, that after we gave you some basic ideas how to do things, this is up to you to make something out of it.


bye
Ron


dw817(Posted 2015) [#16]
If I understand this correctly, you just want to read the text file in ?
I can do that.
That's the only way I can really learn myself is by other people posting an example.

Here is how I would read it in and display it for test purposes.

Strict
Global fp:TStream,a$,b$,c$,q$=Chr$(34)
Global mt$ ' Music Track
Global vo$ ' Volume
Global so$ ' Sound
Global da$ ' Data
fp=ReadStream("level.txt")
While Eof(fp)=0
  a$=ReadLine(fp)
  a$=Replace$(a$," = ","=")
  a$=Replace$(a$,q$,"")
  b$=Left$(a$,Instr(a$,"=")-1)
  c$=Mid$(a$,Instr(a$,"=")+1,999)
  If b$="musictrack"
    mt$=c$
  ElseIf b$="volume"
    vo$=c$
  ElseIf b$="sound"
    so$=c$
  ElseIf b$="data"
    da$=c$
  EndIf
Wend
CloseStream(fp)
Print "Music Track: "+mt$
Print "Volume: "+vo$
Print "Sound: "+so$
Print "Data: "+da$



Endive(Posted 2015) [#17]
What I would do there would be to terminate each line with #, split on that, then load the string into a map. I would also look into run-length encoding if it is a tilemap game.


Brucey(Posted 2015) [#18]
terminate each line with #, split on that

Why not split each line by the end-of-line character instead, since it's already there?
And if you are using ReadLine your lines are already split...


Endive(Posted 2015) [#19]
I said what I would do if it were me :)_

A lot of my habits come from awk and sed and that's the way I do things there. Good point on readline.


dw817(Posted 2015) [#20]
Oh, BTW, some of you may be wondering why I use openstream() instead of openfile().

I have found you cannot use INCBIN with openfile() and readfile(), so - I use openstream() and readstream() which does.

The difference ? According to the documentation, readfile() will attempt to cache the contents of the file to ensure streams such as http: based url's are seekable.

Not so important when you aren't dealing with HTTP content.


grable(Posted 2015) [#21]
Do you need to parse that exact file, or any file following that format?

A bit late perhaps, but i was bored so i whipped up a parser for it.
Its a bit looser with placement of braces than specified though, and it ignores most whitespace. But should otherwise be compatible.




Bobysait(Posted 2015) [#22]
Seriously, Caton clearly doesn't know how to read/write a single line of code, there is no way giving him some code could help him, you're just keeping him stuck on the basis he should have learnt before trying to read a line from a file.

Caton : You have only two ways to go
- If you want it to be done fast, use a library ready for the job where all the commands are easy to understand.
- If you want to do it by yourself : learn the basis of blitzmax programming before asking for people to do it for you.

ATM, as xlsior said, an XML library is probably the best way to get what you want if you don't want to involve yourself in programming, because its syntax is easy, and it's a standard file format for text-based structurs -> You'll find a lot of documentations on the topic.

for exemple, your level file would look-like something like this
<Level>
   <musictrack = '1' />
   <volume='0.5' />
   <sound = 'sound.wav' />
   <data = '1, -1, -1, -1, -1' />
</Level>

This can be easily read in blitzmax using an xml library which is in the <code archive> section.


Else, if you really want to do it by yourself, start reading the blitzmax doc, read step by step tutorials and of use the search button on the forum !
For exemple, this topic is redundant with so many that you can get all the data you need just by searching the forum.

Programming is not that hard, and it's really greatfull, but you can't take shortcuts or you'll just head straight for disaster.

ps : Sometimes, people here are too smart to let you deal with your problems, they offer too many code too easily, and it's not always the best thing they should do. You should not rely on the fact they will be always here to give the code you need, you really have to try to do it by yourself, so, be patient, and learn.


ps2 : anyway, instead of posting "I've got a problem-solve it for me" topics, you could start explaining why you are here.
If it's not to learn blitzmax, say it, users here diserves to know who they are giving codes to. If you're here to learn, maybe you could post using politeness formulas "hi/hello", "thanks" ... you know what I mean.

ps3 : To blitzbasic members :
Do you really want this place to look like this ?
People come and ask for something "I need this !" and you give it to him ?
I hope not ... I know there is a lot of people who want to show all what they learnt and are ready to sacrifice their spirit for the purpose, but damned ... Keep a little bit of dignity ! We all deserve a little bit more of respect, don't you think ?

ps4 : happy christmass


Brucey(Posted 2015) [#23]
Nice post bobysait ;-)


dw817(Posted 2015) [#24]
Well now bobysait and Brucey, I post code because I'm following the Golden Rule. Treat others as you would like them to treat you.

I would dearly LOVE it if people gave me more source examples to experiment with rather than just sit and try to explain the complex intricate details where I can't understand it at all.

Learn by example I say. I started out that way, and I suspect source code examples will help some others too for things they can't figure out.

Were it not for CASABER I would never have perfect MIDI in BlitzMAX for the engine that I'm working on today.

Were it not for TomToad I would still be reading raw keystrokes in BlitzMAX.

Were it not for Gustavo I would not have understood MCI at all as he posted me many working examples years ago for GFA.

Were it not for Russell Hayward I would not have understood have to 'lock' pixels on the screen using screen swapping code examples he gave me for GFA.

I can go on if you like. Nearly everything I have learned is by code example. Even my perfect maze making program is originated from a 300-line piece of code written in 1967 by David H. Ahl for line printers.

https://en.wikipedia.org/wiki/David_H._Ahl



He even included cute illustrations such as these with his source code examples.

Today I understand how it works and I can write it myself - but not if I didn't originally have the example code to look at and figure out for myself.


Bobysait(Posted 2015) [#25]
dw817 :
I can understand your point, I also learnt a lot from exemples, but, as I suppose you did too, I've mostly learnt from the docs first and from small pieces of documented code, because you neither can't start from nothing nor everything, you have to learn one step at a time, you can't start from scratch by making a MMORPG without a single clue on how to add two values.

And, you know, giving a code (at least without a comment) is just like explaining matrix to a child who only knows additions. You will just end with
"Why [...] ?"
"[...] It's because of the matrix composed with vectors"
"Ok, but what is a vector ?"
You can't assume a guy who doesn't know how to read a line from a file will try to understand your code ... you can just assume he'll go for the "copy-paste-tell me now how to code [...]" method.
To resume, thoose codes are just snippet, not ways to learn.

To argue, (I know it will look-like a free agressive statement, but he's almost everything I think a bad programmer is) just look at Guy Fawkes. He spent monthes/years asking for codes that members gave him again and again ...
Now after some years, he post a network sample : the main part of the code is a copy-pasted from the code archive, and the remaining is just very simple code ... you kow what ? he asked on the same topic "Enjoy, but can you fix the camera and post your result" ... no need to say it's freaking simple for someone who spent at least 2 or 3 years coding with blitz3d and at the same time, I really think blitzbasic members made programmers like him just by giving them what they ask just without commenting anything and without letting him do it by himself.

You want to help ? give some pieces of commented code but don't give the full code. Just "the way to do it"
The guy behind the screen will probably know how to use it and in the end will have it working by himself, or ... he just will give up because he's maybe just not wanting to program.


dw817(Posted 2015) [#26]
I can comment my code, Bobysait, but I think it's pretty straight-forward, especially what I wrote above. You should know the rudiments of programming:

Print / Input
Goto / Gosub / Call (function)
While / Wend
If / Elseif / Endif
For / Step / Next
Global, Local

The advanced string commands I am using are MID$, Left$, Instr$, and Replace$.

File commands I am using are ReadStream, Eof, and ReadLine, and CloseStream.

And you can always press F1 to get help on any of these commands.

LEFT$(string,number) returns characters to the leftmost position of a string.

MID$(string,position,length) returns characters from inside a string and a number of them across.

(string)=Replace$(string,originalstring, replacestring) will let you replace any string with another and save the results in a new or same string.

tstream=ReadStream(filename) will open a text file for reading.

EOF(tstream) determines if you have reached the end of that open text file.

ReadLine(tstream,string) reads in a single text line from the open text file.

CloseStream(tstream) neatly closes the file so it is not open later.


The thing is, by source example, even if you don't understand a command, you KNOW what the command name =IS= through the examples.

There were many times I was starting out in BlitzMAX that I had the programming knowledge I needed to do exactly what I wanted =BUT= I did NOT know what the command or function names were for the new language.

Reading and understanding working example code written by others takes care of that problem.


Bobysait(Posted 2015) [#27]
I'm just going and quote something you maybe missed on this topic ...


will this work in blitzmax?
I don't see read file.
and "--" isn't part of blitzmax.
how would this work in blitzmax?



... you really think Caton is ready for your code ?
He doesn't see the difference between blitzmax code and "pseudo-code"

For now, if you have a bit of time, just have a look at this
- one month ago : this topic
- 3 weeks ago : problem to read a file http://www.blitzbasic.com/Community/posts.php?topic=105405
- 3 weeks ago (again) : problem to read a string http://www.blitzbasic.com/Community/posts.php?topic=105417
- 2 monthes ago : problem using ... seekfile with loadimage ... http://www.blitzbasic.com/Community/posts.php?topic=105104

Does he looks like someone who knows what he is doing for you ?

Well ... now, to be true, I can't spend more time explaining why you shouldn't, it's up to you to continue or not the way you do, I have nothing against that. I just hope you understand sometimes it's really useless, and worse, probably counter-productive, for him, and for you.

So, I give up.


dw817(Posted 2015) [#28]
The thing is Bobysait, it's not a private message going back and forth. Any source code submitted can and WILL help not just Caton but other readers as well.

I find myself looking at posts of questions I already know the answers to because I know and have often found and been delighted to see new and unique ways of solving them - by reading source code submissions from other people answering the question.

If Caton is having problems, some of the source code must sink in.

Sometimes I see myself asking questions I know the answer too in hopes of seeing more efficient ways of producing results. I just made a post on this recently found HERE: http://www.blitzbasic.com/Community/posts.php?topic=105548

If Caton doesn't understand, other people will. Caton's questions are good ones and I was very much like him when I first started to learn BlitzMAX.

I'm glad for the time and patience people took with me to teach me how to code in it, and I know for a good fact there is still a LOT of commands and functions in it I have yet to understand.

Caton is not the only one involved in seeing new answers, please consider.


Bobysait(Posted 2015) [#29]
Ok, nevermind, you're true, I'm wrong.

I won't force anybody to use a well known learning technique that is more productive than giving code to someone who can't understand it just because others can, it's not my forum, it's even not my topic, and as long as it's not the way you want it to be, it's not my business too.

Yeah, as I said, I gave up.


Brucey(Posted 2015) [#30]
Bobysait, you'd be better investing all this useful energy in something more constructive ;-)

I happen to agree with your point of view. Handing people (specifically to those who obviously have no idea how to program in general, and appear, over the course of many questions in different posts on the forums here to be unable to understand most of the code and concepts presented to them anyway) large swathes of code isn't going to help them learn to write their own.

If Caton is having problems, some of the source code must sink in.

Your optimism should be applauded. Yet, I do fear thy nature... it is too full of the milk of human kindness...

Caton's questions are good ones

You may think so on first inspection. Perhaps a browse through all his previous questions would shed more light.


dw817(Posted 2015) [#31]
Well without deep delving, has Caton written or submitted complete code in the past ? If he has, then CLEARLY he understands some degree of programming.

I started out coding Fire When Ready Gridley:
http://willus.com/trs80/?-a+1+-p+126050+-f+1

It was an absolute NIGHTMARE for me. It was bad enough I could barely type on the keyboard, let alone type all those weird symbols and the repeats of SET and RESET over and over again.

It took me 4 good tries to write the code the proper way and then I sat for several hours to both run it and look it over.

Then I started fiddling with it. Changing a few values and laughed at what I saw. Perhaps I wasn't programming yet but I was making CHANGES to an existing program and I could SEE the changes.

After a few more weeks of this and coding from the book, I sat down to write my first program.

It was a little adventure game, it used arrays, and an EMPTY room was actually a wall. It used text graphics only and had rooms with monsters to fight and treasure to find. I was 8-years old at the time.

- - ? # -
M - # ? -
# - * - T
# M - ? -
- ? T - -
You are in room 13 9
This room is empty.
Life 17 Power 14


It called upon every single programming resource within me to write, but write it I did. I saved it for future experimentation and then I went on to write other games, several of which were sold by the age of 10. I learned entirely by example code.

Dad bought magazines and books that had examples written in them. He knew I wasn't interested in any programming books - not until many years later - but even then only to finalize in my head what the actual commands represented.

I suspect very strongly if someone just sat down to try and explain to me all the commands for the programming language and it was my first few days with it, it would not have sank in as deeply as handing me existing and working code to play and experiment with.

That is my belief. It may not match others, but it definitely works and has been working for me.


Caton(Posted March) [#32]
How do I make a script parser to read this?
I would like to know how to parse my own custom format text format.
I know how to use mid and left and right and other strings.
I used a plain text file but I would like to use my own parse text format.
I'm going to write code by myself, but how would detect each class and using commet
classes are like simple AI script commands
and all values some value = something is like a command argument.
Appscript:app.txt
Class Window */Setup App Window Settings
{
Title = "Game Title"
Version = 1,0,0
Height = 800
Width = 600
Depth = 32
Mode = 2
}



Derron(Posted March) [#33]
Read char by char and process it.

processing means:
- if char is "*" and next char is (available and) "/" start comment
- if comment started and newline or "/" with next (available) being "*" end comment
- if comment is started, ignore read chars
- if bracket open then do something different than without (one looks for "class", the other one will read properties)
- if bracket is open, then read in the chars to a string until you reach newline (alternatively split into individual lines before processing "char by char")
- each line contains a command / definition / ...
- when reading properties:
- - search for the first "=" in the line
- - extract the left handed part and then the right handed one
- - trim both strings
- - left handed string is property name
- - right handed one the value

imho a ""-encapsulation of strings is not needed in a "one property per line" code (except you extend for right hand printed functions with string-params)

depending on the property you read you will have to process the value (eg. split "," to get RGB or so)


As you stated to know how to use mid, left, ... the above principle should explain enough on how to handle these things.

All in al it is just reading in the strings and splitting it into the pieces you want: property name + value. If you really need "if then else" it will be way more complicated. I assume the archives / forums here already contain simple script parsers.


bye
Ron


cps(Posted March) [#34]
Assuming you want to start by getting data in and out of a text file, the following may help. (Better examples exist in the code archives)
MyFile is a TStream object Declared as: Local MyFile:TStream
Dat is a string with the folder/directory name IE "C:/Docs" Declared as: Local Dat$
TX1 is an integer variable Declared as: Local Tx1%
Chart[x] is an array of strings Declared as: Local Chart$[67]
Pays.dat is a text file 67 lines long located in the directory set by Dat, with a string on each line.

The following will read the strings from the file into the array Chart[x], what you do with them is up to you. No error trapping is provided (in case file does not exist) for ease of digestion.

MyFile=ReadFile(Dat+"/PAYS.DAT")
For Tx1=0 To 66
Chart[Tx1]=ReadLine(MyFile)
Next
CloseStream MyFile

The following writes the strings in the array Chart[x] to the file PAYS2.DAT In the directory specified by the string Dat

MyFile=WriteFile(Dat+"/PAYS2.DAT")
For Tx1=0 To 66
WriteLine(MyFile,Chart[Tx1])
Next
CloseStream MyFile

While I can't argue with the sentiments expressed in this thread, we all started somewhere and I can only do my thing thanks to the people on this forum who have pushed me in the right direction.
Also the documentation is a bit sparse plus the search function is no longer with us making looking for applicable examples a little tough.
Hope you go on to master the beasty that is Blitz Max, It really is worth the effort. Have fun cps


Caton(Posted March) [#35]
Could use some help.

class ID = "Window" (
height = 800
width = 600
depth = 32
mode = 2
data = 1, -1, -1, -1, -1
)





col(Posted March) [#36]
What you are trying to achieve is called 'parsing'. There are an almost infinite number of ways to do what you require. You can keep it straight forward and easy by using what BlitzMax provides for string manipulation, you can learn that strings can be accessed as arrays of characters, you can write a mini parser or even a full blown parser, the choice is yours. The choices are almost endless as to how to go about writing the code for any of these. I mean whole technical papers and books have been written just about text parsers.

Anyway, to get the data into some code as you request then something simple ( but error prone as there is no error checking for incorrect data etc ) like the following will get the job done.

Strict

Local file:TStream = ReadFile("script.txt")

While Not Eof(file)
	Local line:String = ReadLine(file)
	Local parts:String[] = line.split("=")

	Select parts[0].toLower()
	Case "class id "
		Local firstQuote:Int = parts[1].Find("~q") + 1 ' + 1 to skip the " character
		Local lastQuote:Int = parts[1].FindLast("~q")
		Local classId:String = parts[1][firstQuote..lastQuote]
		Print "Class ID: " + classId
		
	Case "height "
		Print "Height: " + parts[1]

	Case "width "
		Print "Width: " + parts[1]

	Case "depth "
		Print "Depth: " + parts[1]

	Case "mode "
		Print "mode: " + parts[1]

	Case "data "
		Print "data: " + parts[1]
		' now use parts[1].split(",") to get the parts of the data
	
	Case ")"
		' last line of data - ignore or use to signal end of the this piece of data

	Default	
		Print "Unnknown entry"
	EndSelect
Wend



TomToad(Posted March) [#37]
I would parse the data much like col has done, with one exception. I would change line 9 to read Select parts[0].Trim().ToLower() and my case statements would ;eave off the trailing space Case "class id" .. Case "width" .. Case "height".. etc... This way you can type
height = 800
Width=600
     deptH     =     32

and all lines will still be read correctly.


Hardcoal(Posted April) [#38]
if anyone interested you can use my database read write engine.