Sunday, November 30, 2014

0007 - Prolog Adventure Game

I hate the Prolog language. Just going to get that out there to start this.

Anyway, I've finally finished the assignment given to my class a few weeks ago: take a text-based adventure/maze game that is written in Prolog, and modify the code so that different configurations can be used in the game. Also, this rewrite should include the capability of having a list of commands passed to the game for an "autopilot" type of deal.

Simple, right? No, because I hate Prolog because it is stupid and sucks and I'll probably play with it later and find out I secretly like it.

Anyway, I decided to add a few of the more interesting bits of code on here in case anyone ever wants to see it:

The "go" and "fileManager" clauses. The first "go" clause simply opens up the configuration file (a comma-delimited plaintext file), reads it into the List labeled "Data," and passes Data to the fileManager clause. The fileManager clause opens up a new stream for writing the results of the game, creates an atom whose value is set to the next file name, and calls the next go clause. This go clause reads in the commands from the file, then runs through them iteratively for each configuration. Once all of that ends, everything kicks back to fileManager, which sends the next file.

go :-
  csv_read_file('/home/jonathan/Desktop/Prolog/configurations.txt',Data),
  fileManager(Data).
 
fileManager(Data) :-
  open('/home/jonathan/Desktop/Prolog/commands_v1Results.txt',write,Stream1),
  File1='/home/jonathan/Desktop/Prolog/commands_v1',
  go(Data,Stream1,0,0,File1),
  open('/home/jonathan/Desktop/Prolog/commands_v2Results.txt',write,Stream2),
  File2='/home/jonathan/Desktop/Prolog/commands_v2',
  go(Data,Stream2,0,0,File2),
  open('/home/jonathan/Desktop/Prolog/commands_v3Results.txt',write,Stream3),
  File3='/home/jonathan/Desktop/Prolog/commands_v3',
  go(Data,Stream3,0,0,File3),
  open('/home/jonathan/Desktop/Prolog/commands_v4Results.txt',write,Stream4),
  File4='/home/jonathan/Desktop/Prolog/commands_v4',
  go(Data,Stream4,0,0,File4),
  open('/home/jonathan/Desktop/Prolog/commands_v5Results.txt',write,Stream5),
  File5='/home/jonathan/Desktop/Prolog/commands_v5',
  go(Data,Stream5,0,0,File5).
   
go([],_,_,_,_).

go([row(X,Y)|Data],Stream,M,S,File) :-
  retractall(at(_,_)), % clean up from previous runs
  area(X,Loc1),
  area(Y,Loc2),
  assert(at(you,valley)),
  assert(at(ogre,Loc1)),
  assert(at(treasure,Loc2)),
  open(File, read, Str),
  read_commands(Str, Commands),
  close(Str),
  report,
  S1 is S+1,
  main(Commands,Data,Stream,M,S1,File).
 
read_commands(Stream, []) :-
  at_end_of_stream(Stream).
   
read_commands(Stream, [X|L]) :-
  \+ at_end_of_stream(Stream),
  read(Stream, X),
  read_commands(Stream, L).


That's really the trickiest part of the code. Every other change mainly had to deal with writing to the Stream rather than the console (which may not have actually been a requirement for the assignment...).

Enjoy!

Monday, November 3, 2014

0006 - Sure, it's simple, but I like it

This semester, I'm in COMP 4040 (Programming Languages). The big assignments in this class are all pretty much the same thing: take a text-based adventure game originally written in Prolog (nifty language, but I don't care for writing in it), and translate it to other languages that we are learning about.

Well, the C++ translation was due last night at 11:59 pm. I finally gave up on trying to optimize it and turned in what I had at about 11:50, but that didn't sit well with me. Before I go down that road, I do want to fill you in on a few things about me that you may or may not already know:
1. I am a serial optimizer. I may write a quick and dirty piece of code to get a job done, but I can never let sleeping dogs lie: I have to eventually come back and clean it up, making it run faster, smoother, more error-free.
2. I'm finally learning C++. I tried picking it up when I was 12, but it was hard to find info, I had no idea what a compiler was, and the code looked scary, so I deemed it Too Hard and maintained that stance until this past summer. As such, I'm excited that I'm able to write some C++ now, and am finding it very fun.

So, since I am a serial optimizer, I'm just now learning C++, and I find C++ to be fun, I couldn't let the code I turned in last night just stay as it was. As such, I spent about 5-6 hours today trying to figure out ways to make it better.
The version I turned in last night could run from start to finish (automated tasks ftw!) in an average of .135 seconds. Since the other students I talked to had their running in just over 1.0 seconds, I originally felt pretty good about that. However, I knew there were a few things I could change to speed mine up, so I started tinkering...and tinkering...and tinkering. After trimming .01 seconds off of the run time (down to .125s), I decided that, surely, the code could be better optimized, and that I should be able to get the run time down to under 0.1 seconds.

Long story short, after another 5 hours of tinkering, I managed to get the run time down to an average of .057 seconds (less than half of the time when I started). Why am I so excited about this? Because I set an uncertain goal in a still largely unknown language, and accomplished what I set out to do. Also, because my friend Nathan said I was crazy and might have said that I couldn't pull it off (I don't listen well, so I just put words in people's mouths). So, if someone's interested in checking out what I did, leave a comment asking for the code (or ask me in person), and I'll send you the whole kit and caboodle (code, configuration files, etc.). After all, 345 lines is too much to have to read in this poorly formatted blog.