CSCI 1320 - Assignment #7


We continue the trend of playing with arrays (they are very handy things afterall). In this case you might also be playing with strings a fair bit, depending on what option you actually pick to work on.

As a side note, be sure to save the code from all the programs you do. It is quite possible that later in the semester other assignments will include things that overlap with them and your code will be reusable.

Map Traversal :

This is the first installment for you building your own text adventure. Your program will read in from a map file that you will write by hand and let the user run around in that map by using commands like "north" to move from one room to another. The map file will have a fairly simple format right now and you will create your own map file using vi. Make sure when you submit this program you turn in both the .c file and the map file so I can walk through your map.

The format of the map file should be something like the following:

room_number room_name
long line of room description
number_of_links
direction1 destination1
direction2 destination2
...

This is repeated over an over. Each room should have a unique room number and it should start at 0. The reason is that you will be putting all the room information into arrays. I'm providing a sample map file below, but you don't have to stick perfectly to that format if you don't want to. You might deviate if you are thinking about other options you will add in later. Odds are good you will be refactoring your code later anyway to add support for things like structures once we cover them.

The interface for your program is quite simple. When you run the program it should read in the map file and keep all the map information stored in various arrays (they might be dynamic). You will start the user in room 0 and print the description of that room and the different directions they can go as well as where they lead to, then follow that with a prompt. You could just use ">" as the prompt to start with. It might get more complex later on when you have real game functionality. So when the user starts the game it might look something like this if you read in the sample map file.

Halsell 228
You are standing in a room full of computers and comfy chairs with a giant air conditioning unit hanging from the ceiling. While the surroundings are serine enough, you can't help feeling a certain amount of dread. This isn't just a fear that the air conditioning unit is going to fall either. Something in you tells you that this room is regularly used for strange rituals involving torture. You can only wonder what happens here and why there isn't blood all over the place. Your uneasyness makes you want to leave quickly.
The hallway is east.
>

The user must type in either a direction to move or "quit". If anything else is entered you should print an appropriate error message.

Sample map file

Graphics Problem:

For this problem you will be bringing together components of the last two graphics assignments to make something a bit different. You are going to use parts of your raster drawing program to help "render" a scene in 3-D. You are going to use a very simple rendering model to do it so that things aren't too complex. A real rendering model would have things look smaller as they move away, that is a perspective view. You aren't going to do that. You'll assume that your lines of sight are parallel which makes things a lot easier.

What you will build is something a lot like assignment #4, but now the image will be in 3-D instead of 2-D and you will have some lighting from assignment #5. In this assignment there are two things that you can add to what you are drawing, triangles and light sources. You should be able to handle at least 3 lights and 20 triangles, but you can write your code to handle more than that if you want. When you start the program, you won't have any of either. You will have functions that read lights and triangles from a file as well as a function to write such a file. Your code will also have the simplePrint and printRaster functions you wrote before. The first one will still print to screen just so you can see roughly what it looks like. The second though should write out to file. The user should be prompted for a file name. Make sure your print raster prints a first line with the width and height that you use on it. I left that out of my earlier sample output. I'll be providing you a way that you can view those images in color if you want to. So the functions in your program are the following

  1. Add light
  2. Add triangle
  3. Read geometry file
  4. Write geometry file
  5. Simple print
  6. Print raster to file
  7. Quit

The lights and triangles will have x, y, and z coorodinates. x and y will be just like they were in the earlier program. z will be distance from the viewer. When you draw a triangle (you get to figure out how to do this), you will ignore the z component for where it is on screen. That will only matter for determining the lighting on it. When the user adds a triangle, that should be drawn on the raster with the current lights. When a light is added all the triangles will need to be redrawn so that they use all the lights. Each triangle and light should also have a color specified for it. To determine the color to draw each triangle, you will add up the colors it would be for each light. To determine that, you will use what you did for assignment #4 to get the intensity of the light. One alteration you should make here is that using the pixels distances for the 1/r^2 decrease in intensity causes things to be very dark so instead, take the distance you find and divide it by WIDTH to get a more appropriately scaled value. If we say that value is frac, then the color from that light will be a rgb where each component is determined as follows. r_drawn=frac*r_tri*r_light/255. The reason you divide at the end is because the components aren't between 0 and 1, but between 0 and 255 so to get a value in that same range you multiple the two and divide by 255.

The only geometric shape you are drawing for this is a triangle. Of course, any polygon can be built out of triangles. Drawing triangles isn't a simple task though. My hint to you is that you should figure out where you would draw lines between the points, then for each row in the raster, fill all the pixels between those. Then you only have to worry about the math for drawing a straight line.

The option to read in a geometry file should ask for a file name, clear your current geometry, then read in a file that has new lights and triangles. The format of the file has lines that start with an 'L' for a light or a 'T' for a triangle. You can read a string for that and just examine the first character. Following that will be either 3 numbers for a light or 9 numbers for a triangle. After this is called, the raster needs to be cleared and all the new triangles should be drawn. Note that the reading function will have to check for feof to know when it is done. Writing a geometry file should ask for a file name then write the above format to it.

If you want to do this option and you didn't do the graphics options on earlier assignments, let me know and I can e-mail you code for those.

To view your rasters graphically download this file to the directory you are doing your assignment in. To use it you will need to have a recent version of java installed. The ones on the mab machines should work well. At the command prompt, type "java -cp RasterViewer.jar RasterViewer RGB raster.txt". The raster .txt can be replaced with whatever file name you are using for your output file.

input : output : orginal format geometry file : geometry file : raster file

Baby Mathematica:

For this problem you will use your equation parser from assignment #6 to build a little program that can be used to do some simple function evaluation. You will then give it the ability to output text files that are plots of your functions and can be plotted up using gnuplot. You should also give it the ability to read files that have functions defined in them.

You can define 3 functions: f, g, and h. They are all functions of a single variable x. They are definied in terms of numbers, x, and the other functions. You only have to have the four basic operators (+, -, *, /), but you can add extra ones if you want extra credit. If you do this, there needs to be a big comment at the top of the code telling me what you did so I can try it and give you the extra credit.

Options:

This program won't use a numeric menu. Instead, it will be more command line like, similar to what we wrote in class for the text editor. You can read in a string for the command and check the first character to see what they picked. Use the strings shown above after each option. See the sample input file for an idea of how this would work.

The define option lets the user define a function. The format for that should look something like this "define f=x*x" or "def g=f(x-1)+2". After the keyword (beginning with 'd') you have the function letter ('f', 'g', or 'h'), followed by an equals sign and the string for the function. I recommend that you store the functions in an array of 3 strings.

The evaluate option allows the user to evalutate one of the functions at a particular value. So they could type in something like "evaluate f(4)" or "eval h(5+3)". To get this to work, you will add a bit to your parse function from assignment #6. Earlier it needed three arguments, a string for the equation and two ints for start and end. You will need to add two more arguments to that. The first is a double for the value of x. The second is a 2D array of chars that holds the three strings defining f, g, and h. You need that because the functions can call other functions. The second example in this paragraph and the second one in the define paragraph might scare you a bit, but don't let them. Instead think about the power of your parse function and how you can use that to make evaluating those expressions easier.

In addition to adding the two extra arguments to parse, you will also add some extra possible cases in the function. Where you earlier just called atof, now you will need to check for 3 possibilities and all can be easily distinguished by the value of str[start] (or whatever name you use for the string argument. If it is an 'x' then you need to return the value that was passed in for x. If it begins with an f, g, or h, you need to parse the argument and then use that as the x value for a call to parse on the proper function definition string.

The view option just prints out the formulas that have been entered in case you forget them.

The read and write options are fairly straight forward. You need to write some code that will read in definitions for your three functions from a file or write out to it. In both cases, the use needs to specify a file name. For example "read forms.txt" or "w cooleqs.txt". You can choose your own format for this as long as it works for reading and writing when you don't have all of them defined. Consider that using something close to what I have asked you to do for define might be helpful because you could call a single function for define and for the read function.

The last option is to plot. You aren't going to write the graphics code, but you will write a file that has x and y values in it so that it can be plotted with gnuplot. See the description of the physics problem in assignment #4 for information on that. For this to work, they need to specify which function, a minimum x, a maximum x, and a file name. Your code should evaluate the function at 100 evenly spaced points between the min and max and write 100 lines where each has the x value followed by the y value on it. For example, they might give the command "plot f(x) 2.3 6.7 funcPlot.txt".

If you choose this option you might want to look at the strcmp and strcpy functions in string.h using the man pages or your text. You can certainly write those functions yourself, but calling those will make your code shorter.

Just as a side note, I think this might be the most exciting problem of all the ones I've given so far this year (for me). It can really show you the power of a simple recursive algorithm and once it is done, you will have written a program that is far more powerful than what most people in a PAD1 class would even dream of doing. That doesn't mean it is harder though, just more powerful.

If you want to do this option and you didn't do the symbolic algebra options on assignment #5, let me know and I can e-mail you code for it, mainly the parse function.

input file : output file : function file : plot file : plot2 file

Biology/Chemistry Problem:

In this problem you will model diffusion of particles and how that can lead to crystal growth. For this assignment you will implement a "raster" like what was done in the graphics option for assignment #4. However, for this one you can use just a simple raster of characters if you just want to print out text images of the crystals. If you want to use my raster viewer (which is described in the graphics option of this assignment) then using the raster style from assignment #4 can help, but you don't need the full color functionality unless you want to make your pictures prettier. You will also be using the random number generator in C to help with modeling diffusion which appears to be a random process on a macroscopic scale. The random number generator in C is rand() which you can get more info on with the man pages.

The menu for this application should look like this:

  1. Clear Raster
  2. Clear Sources
  3. Add Source
  4. Add Seed
  5. Free Particles
  6. Print Sources and Raster to Screen
  7. Print Raster to File
  8. Save Sources
  9. Load Sources
  10. Exit

The data you will store in this program has two basic parts, a raster which is a 2-D array of ints and configuration data that keeps the number and locations of your sources. A source is just an x,y position in the raster and you should be able to support up to 10 of them. For this "simulation", you will start a "particle" at one of the sources and let it drift around until it comes in contact with another particle. This might sound complex, but it isn't. Say you have one source at 5,5. You start your "particle" there just by keeping track of 5,5 in two varialbes. Then you pick a random number between 0 and 3 (rand()%4) and depending on what that number is you try to offset your particle either up, down, left, or right. If we got a move to the right our particle would now be at 5,6. The procedure is repeated until the move would put the particle in the location of another particle. At the beginning the only particles out there are seeds which you have placed. If a particle tries to move onto something, it attaches there and is put on the raster. If a particle ever tries to move out of the raster bounds, simply don't move it and pick another random number.

The clear raster option sets all the values in the raster (your 2-D array of ints) to zero.

The clear sources option sets the number of sources to 0.

When the user selects "Add Source" you should ask them for an x,y location and put that in your source array(s) then increment the number of sources by one.

When they select "Add Seed" you should ask them for an x,y and put a non-zero value in your array at that location. This is effectively a particle that things can stick to.

When they do "Free Particles", you will ask them how many particles to free. Then you will repeat the following procedure that many times. First pick a source at random from the sources you have. If they haven't made a source yet, give them an error message and go back to the menu. Then start a particle at the source location and let it do a random walk as described above until it attaches to a non-zero value in the raster/array.

If the user selects option 6 you should print out the sources to screen, then print out a simple representation of your raster to screen. Print a blank (' ') for each zero entry and an 'X' for each non-zero entry. Separate the lines of the raster with newlines. See the sample output for more information on this.

When they select item 7 you should ask them for a file name to save to, then "print" the raster in a manner like what is described in assignment #5: graphics option so that it can be viewed with the raster viewer. The difference being that if you don't want to make it pretty you don't have to. Your file should start with two ints on one line. These give the size of you raster. After that is 6 characters per pixel in the raster. To make things simple, you can print 0 if the raster value was 0 and 10 if it was not. This just gives you black and white, but you will be able to see what you get.

If they select 8 you should ask for a file name and write to that file the information on your sources. The easiest format is probably the number of sources followed by x and y for each one.

If they select 9 you should ask for a file name and read in whatever format you wrote from that file.

For extra credit you can have your new particles color coded by the point from which they were released. This will allow you to visualize where the particles end up. You could also color code them by "when" they were released so the color coding changes as you move away from the seed. This means printing something a bit more complex for the pixel values, but you still don't have to pack and unpack colors like in assignment #4 unless you want to.

input : output : raster file 1 : raster file 2 : source file