I am about to write a text based adventure game in Prolog, therefore i have tons of writeline statements. I was wondering if i could slow down the output processing of my text. So imagine the following scenario:
I have a Textblock A that gets printed and i want a 2 sec delay afterwards.
So Textblock B gets printed 2 sec later, without the :- sign in Prolog.
My first idea was to write a loop that compares the current time with currenttime + 2 s but i cant get rid of the :- sign.
Unfortunately; I am a newbie in Prolog and Ii don't have any clue about the thread handling.
That statement might be useful but it doesn't work at all:
delayText([H|T]) :-
put_char(H),
flush_output,
sleep(0.1),
delayText(T).
delayText([]).
Neither flush output nor sleep seem to work.
I'm using ProDT in Eclipse.
Thanks in advance,
Chris.
I'm not sure as to how you want to realise the writing for your game, but sleep/1 as used in the example code in your question can be used together with a simple write like so:
delayText([]).
delayText([H|T]) :-
write(H),
sleep(1), % Time in seconds
delayText(T).
Related
I have stumbled upon a piece of code that I can't quite understand. It looks like this:
% spawn process which waits for a message and prints it
Pid = spawn(fun() ->
receive
X -> io:fwrite("I received: ~p~n", [X])
end
end),
% send a message to the new process
Pid ! {message, "Hello"}.
In the last line, is "message" an atom that is defined in the module? I can't really understand that part.
My attempt at understanding it would be this: we save things in tuples where the first element is descriptive of the content. For example: {celsius, 55}. What is less clear is that the atom message is not defined in the module. Do you have to define it? No declaration is necessary so I guess you don't have to define the atom before using it. Am I correct?
Thanks for the help!
The code is from here.
Correct- you just use atoms at will. They're not "defined" anywhere.
Basically, You understood right. You can use everything atom you want, they are not defined anywhere. Except some reserved words in Erlang:
receive, case, if, throw, catch, else...
Atoms can be used at will, Every unique atom will be entered into an atom table. The atom table is never garbage collected. The default max atom count for an ERTS instance is 1048576. This limit can be increased by using +t option on startup.
more information regarding limits. For diagnostic purpose you can use erlang:memory(atom) - elrang:memory(atom_used) calls, to ensure you haven't exhausted the available atoms. If the atoms are exhausted it leads to immediate termination of the ERTS without warning.
I am running my code on SWI Prolog and Windows 7. In my code, I call another application using 'win_exec()' (I tried using the method 'shell()', but it won't work.), and at the end produces its output in a text file. However sometimes it runs for times like 30 minutes. Now my prolog code uses this output text file, to further parse it and process it.
This is the code I use to call the other application and then use its output file:
main(Value,X) :- win_exec('C:\\myfolder\\external_app.bat C:\\myfolder\\outputfile.txt', normal),
open('C:\\myfolder\\outputfile.txt', read, Mf),
read_file(Mf, X), % PROCEDURE TO READ FILE CONTENTS
close(Mf),
statistics(cputime, Value). % CALCULATE HOW LONG IT TOOK
However, since the file has not been outputted by that another application, it gives the error:
ERROR: open/4: source_sink `C:\myfolder\outputfile.txt' does not exist (No such file or directory)
So, as a workaround, I try to catch the error, handle it by comparing with 'existence_error' and then recursively call the open procedure, until it finally succeeds i.e. the other application has completed its processing and the output file is produced. This is my workaround code for this:
main(Value,X) :- win_exec('C:\\myfolder\\external_app.bat C:\\myfolder\\outputfile.txt', normal),
open_output(X), % PROCEDURE FOR FILE EXCEPTION HANDLING
statistics(cputime,Value).
open_output(X) :- catch((open('C:\\myfolder\\outputfile.txt', read, Mf), read_file(Mf,X), close(Mf)),
error(Err,Context),
open_output_aux(Err,X)). % AUX PROCEDURE TO RECOVER
% Write some code here
% open_output_aux code matches the error code with 'existence_error';
% if true, calls open_aux_wait procedure; else throw the error.
open_aux_wait(Z):- catch((open('C:\\myfolder\\outputfile.txt', read, Mf), read_file(Mf,Z), close(Mf)),
error(Err,Context),
open_aux_wait(Z)).
However this seems to be very inefficient of way doing this. I wanted to know if there's any better way to do this, like in java, you could simply call wait() while handling file exception. In the documentation, there's a method 'wait_for_input\3' but it says 'wait_for_input()' cannot be used for File Streams in Windows. I tried using it, but it gives error.
Any help or guidelines is greatly appreciated.
You have several options to solve this:
You can totally reconsider the way that these processes communicate. For example, SWI-Prolog ships with very powerful HTTP libraries, and you can set up the communication between the two processes to work over HTTP, using a client/server architecture. In this case, you avoid the busy waiting that currently uses many CPU cycles unnecessarily.
A much more trivial solution is to simply insert a call of the built-in sleep/1 predicate to put the process to sleep before trying to open the file again. Use for example sleep(1) to put the process to sleep for 1 second.
Use for example process_wait/2 to wait until the called process has finished and generated the file.
From what you are describing, it looks like (2) will do, (3) is slightly more elegant, and (1) may be good to know in general, for more difficult cases.
So for our computer science class, we had to write a program that randomly generates cards, i decided to do mine in batch, because im a massive noob XD
I was confident that i could do it as im quite experienced with it. Even though batch isn't by any means a good 'language' if your going to call it that. I was able to fix most of the problems by myself with some hard work. I am however, still having some issues i don't know how to resolve.
My biggest issues i don't know how to fix are...
Text not being displayed properly.
Numbers (i use for the base of the AI and card generation) sometimes not being defined properly in variables.
The point system just refuses to work not matter what i do.
It sometimes randomly just flat out decides to crash on me if i skip a 'TIMEOUT' or a 'PAUSE'.
Some 'IF' statements not being executed properly even though there exactly the same as the other ones.
I'm sorry if this question is too broad, but i really didn't know quite how to summarize it.
Here is a link to my card game: http://pastebin.com/t2S3yWk5
Here is our question:
1) Create a program that will generate two random numbers - one that maps to a suit (hearts,diamonds, clubs or spades) and one that maps to a card (Ace, 2, 3, ..... Jack, Queen, King)
*Mine is slightly different, it generates two different suits based on two random numbers.*
2) Create a program that will generate a random card and then ask the user to go Higher,Lower or Quit. If the player chooses Higher the next card must be of a higher value or theplayer is out. Likewise for Lower.
3)Extending the previous program, the user will select a trump suit at the start of the game. If the card is a trump suit card then the game continues regardless of the card’s value. The program will keep score and will save the score to a highscore file. The user will also be able to display the current highscore file.
I would like to try and do this stuff (listed above) myself. I just need help trying to fix my existing program.
I hope that if your reading this you could give me some advise or provide solutions to some of my problems. Thanks in advance! :3
Good news; nothing is super wrong with your code, it's just a bunch of little things that seem like a lot. Some off-by-one errors and a missing variable that I can only assume got replicated from copying and pasting.
Text not being displayed properly
I assume this is the "Access denied" errors that your code produces instead of the AI's comments. This is due to the fact that > and < are used for output redirection, so the emoticons you are adding are trying to create a file in a place you don't have access to. Either get rid of them (recommended) or use ^ to escape them (^>:)).
Numbers (I use for the base of the AI and card generation) sometimes not being defined properly in variables
%random% %% 5 results in one of the numbers in the set 0, 1, 2, 3, 4. You currently do not have an if statement for what should happen if 0 is randomly selected. Add an if statement or have the code go back to the top of the section if a 0 is selected.
The point system just refuses to work no matter what I do
You're going to kick yourself...
Your set statements are missing the assignment portion. SET /A %p1p% + 2 should be SET /A p1p=%p1p% + 2 and so forth (or set /a p1p+=2 if you think that looks better).
If sometimes randomly just flat out decides to crash on me if I skip a 'TIMEOUT' or 'PAUSE'
I couldn't replicate that, but the code seemed to work fine when I removed those statements.
Some 'IF' statements not being executed properly even though they're exactly the same as the other ones
Your comment indicated lines 119-132, which include the if statements that assign points. See above for why those aren't working.
Some other recommendations for your code
Your variable names should be more descriptive. For example, ctog doesn't tell me anything about what that variable should be; I can look at the code to see what it does, but without any context, that could be doing anything.
You should add the /i flag to the if statements that check which card you put down so that C1 and c1 get treated the same. On a related note, you should add a check for when the player enters something other than C1 or C2. You can even use a choice command like you did earlier.
:pvic is missing an exit command, so you automatically play again if you win. Combined with the fact that you only check if lt is equal to 2, not greater than or equal to 2, there's no way to stop playing if you win. Also on the subject of end game conditions, there's no if statement for if you tie the computer.
cp1 and num1 are effectively the same variable, there's no reason to have both (same with cp2/num2, ap1/num3, and ap2/num4).
You need some kind of goto at the end of :pc1 so that :pc2 doesn't automatically run after :pc1 finishes.
I'm writing an interpreter for a game. User enters its move to the interpreter and program executes that move.
Now I want to implement a time limit for each decision. Player shouldn't be able to think more than 30 seconds to write a move and press enter.
call_with_time_limit seemed relevant but it doesnt work properly as such:
call_with_time_limit( 30, read(X) ), Problem, write(Problem).
In this case, it waits for input, and when input is entered, timer starts afterwards. But I want the timer to start at the beginning.
How can I do it?
If you are interested in I/O related timeouts please consider wait_for_input/3 or set_stream/2. The built-in you found, call_with_time_limit/2 is not a simple and reliable interface.
Edit: I just see that you use read/1 for input. Please read in above documentation how to avoid blocking in read/1. It is not clear to me why you need this, but a user might simply enter Return, thereby circumventing the initial timeout. read/1 would now read that '\n' but then would wait for further input - without a timeout, while the user lavishly skims Wikipedia for the answer... might even ask the question on SO...
Your approach seems sensible: from the SWI-Prolog docs: 'Blocking I/O can be handled using the timeout option of read_term/3. '.
That's not really informative: changing timeout on user leads to some bug (I'll test more and will report to SWI_prolog mailing list if appropriate), even under catch/3.
The following seems to work
...,
current_input(I),
wait_for_input([I], A, 30),
...
If not input given (shorter time to test here...)
?- current_input(I), wait_for_input([I],A,5).
I = <stream>(0x7fa75bb31880),
A = [].
EDIT: the variable A will keep the list will contain the list of streams with ready input: I just reported the case where the user doesn't input anything before the timeout occurs. To get the actual input, using your supplied code:
tql :-
current_player(I),
writef('Its %d. players turn: ', [I]),
flush_output,
current_input(Input),
wait_for_input([Input], [Input], 5),
read(Input, Move),
writeln(Move).
current_player(1).
HTH
suppose that no bytecode is generated for a program, like in Ruby, Perl, or PHP, in this case, is line 1 below re-interpreted every time the execution reach line 1 again?
while ($indexArrayMoviesData < $countArrayMoviesData + $countNewlyAddedMoviesData) {
# do something
}
that is, if the loop runs 100,000 times, then that line will be re-interpreted 100,000 times?
and if so, the bytecode creation helps not only the initial start up of he program, but also during the execution? (because code doesn't need to be re-interpreted again)
Typically, it'll be converted into byte code and that byte code will then be executed.
But in the case of PHP for example, the byte code is regenerated on every request/page view. Unless you install a byte code (or opcode as it's called often in the case of PHP) cache, such as XCache, APC or EAccelerator.
For recent languages, including perl, the code is precompiled before being executed. So most of the analysis work is performed only once.
This is not the case for shells, which interpret every line each time they execute them.
If the interpreter is sensible it would hopefully check if $countArrayMoviesData or $countNewlyAddedMoviesData were altered during the loop and if they weren't then the sum could be calculated and kept.
If the values are updated within the loop then in all likelihood even the bytecode would require an addition operation to take place, not making it any more efficient.
Very, very few interpreters will do this. An example is the ages-old, no longer used Hypertalk interpreter for Hypercard where you could actually rewrite the text of your code programatically (it's just a string!)
Even interpreters that don't produce byte code will parse your code first, as it's hard to do that line by line and much easier to do it all at once. So a really simple interpreter will basically have a tree, with a node for the "where" loop with two children: one "less than" expression for the conditional, and one block for the body of the loop.
The answer to your question, as all consultants know, is "it depends."
You're right, in some interpreted languages, that line may be reinterpreted each time. I suspect most shells handle it roughly this way.
The original versions of Basic also did it this way.
Most current interpreters will at least tokenize the language, so that the text doesn't need to be re-scanned each time. That is, a BASIC-ish program like
00010 LET A=42
00020 DO WHILE A > 0
00025 LET A = A - 1
00030 ENDDO
would convert it at the least to small tokens for the keywords, and addresses for the variable, something like
LET $0003, 42
LABEL 00020
LETEST A, 0
IFTRUEGOTO 00030
SUB $0005, $0003, 1
GOTO 00020
LABEL 00030
where each word in upper case in the translation is a single integer internally. That way, there's a single lexical analysis pass to translate it, followed by the interpreter being able to just interpret the token values.
Of course, once you go that far, you find yourself thinking "gee, why not use real opcodes?"