View Single Post
Old 09-06-2006, 04:10 AM   #6
guesst
Abandonia Homie
 
guesst's Avatar

 
Join Date: May 2005
Location: Aurora, United States
Posts: 606
Default

<div class='quotetop'>QUOTE(Eagg @ Jun 9 2006, 12:03 AM) [snapback]235363[/snapback]</div>
Quote:
Interesting how compact source code can be, even though I have a different view about what "minimal" source code is.
What I would like to know is how long it would take you to complete such a transformation on code that you have not seen before?
[/b]
Me? It would depend on the complexity of the code, I suppose. I'm not about to boast about my mad hackor skills. Minimilizing the code consists of using single character variables for starts, clearing out excessive spaces and line feeds, and then fiddling with the actual way that the code does what it does, identifying and trimming non-necessary code (like the sort of "good coding" practice like freeing memory and the like that the OS usually handles if you don't) and occasionally restructuring whole parts around a new paradgm that may involve just plain rewriting whole segments, which is the hard part, especally if you're not intimitely aquainted with what the code does and how it does it. In the end, the scaled down version may bear resemblance to the original verison in execution time only.

Which is a perfect segway into the next program.
Robot Escape
The instructions are in the game, so just read down a few lines to see them:
Code:
/* Robot Escape 
 * by Joseph Larson 2005
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

#define W 77
#define H 21
#define MAX_LOC**W * H
#define SQ(a) (a) * (a)

typedef struct {int loc, type;} STUFF;

STUFF **p;
int numobj;
char msg[W], icons[4] = {' ', '#', 'O', '+'};

void intro (void) {
**printf ("Robot Escape\n------------\n"
**"You are being chased by robots. Fortunately you have two advantages. First,\n"
**"your pursures aren't very smart. Second, you have a teleport-a-matic at\n"
**"your command should you need it.\n\n"
**"The robots will take the most direct route to you, even if it means running\n"
**"into another robot. When two robots crash they make a debris heap that you\n"
**"can crash other robots into. When all robots are destroyed you win and go\n"
**"on to the next level. Try to make it to level 10!\n\n"
**"If you have to use your teleport-a-matic remember that it might teleport\n"
**"you into your enemies, so use it sparingly.\n\n"
**"You move using the number keys. (Be sure num-lock is on) Use the 5 key if\n"
**"you don't want to move for a turn. Use the 0 key to turn on your\n"
**"teleport-a-matic. And if you don't need to move for the rest of the level\n"
**"type a period ('.') for your move. Otherwise 8 is up, 2 is down, 4 is left\n"
**"and 6 is right and the corner keys are diagonal.\n\n"
**"\nGood luck! Press any the ENTER key start.\n\n");
**getchar ();
}

int setup (int lv) {
**int n, numleft;

**numobj = numleft = 3 + lv * 4;
**p = malloc ((numobj + 1) * sizeof (STUFF *));
**n = rand () % numleft;
**while (numleft >= 0) {
****p[numleft] = malloc (sizeof (STUFF));
****p[numleft]->loc = (numleft - numobj) ? 
******numleft * (MAX_LOC / numobj) + rand() % (MAX_LOC / numobj) : MAX_LOC + W;
****p[numleft]->type = (n != numleft--) + 2;
**}
**return n;
}

void takedown (void) {
**int n;

**for (n = 0; n < numobj; n++) free (p[n]);
**free (p);
}

int draw_floor (int l) {
**int c, d, n, s = 1; 
**STUFF *temp;

**putchar ('\n'); puts (msg);
**putchar ('-'); for (c = W; c; c--) putchar ('-');
**for (d = 0; d <= numobj; d++) {
****for (n = numobj; d < numobj && n > d; n--)
******if (p[n]->loc < p[n - 1]->loc) {
********temp = p[n]; p[n] = p[n - 1]; p[n - 1] = temp;
******}
****if (d) {
******if (p[d]->loc == p[d - 1]->loc) {p[d]->type = p[d - 1]->type = 1;}
******else do {
********if (!(c % W)) printf ("|\n|");
********putchar (icons[(p[d - 1]->loc == c) ? p[d - 1]->type : 0]);
******} while (++c < p[d]->loc && c < MAX_LOC);
******if (p[d - 1]->type == 3) s = 0;
****}
**}
**printf ("|\n|"); for (c = W; c; c--) putchar ('-'); printf ("-\n");
**sprintf (msg, "Level %d", l);
**return s;
}

void gorobo (STUFF *pl) {
**int n;

**for (n = 0; n < numobj; n++) if (p[n]->type == 3) {
****if ((p[n]->loc % W) > (pl->loc % W)) p[n]->loc -= 1;
**else if ((p[n]->loc % W) < (pl->loc % W)) p[n]->loc += 1;
****if ((p[n]->loc / W) > (pl->loc / W)) p[n]->loc -= W;
**else if ((p[n]->loc / W) < (pl->loc / W)) p[n]->loc += W;
**}
}

int main (int argc, char *argv[]) {
**int n, m, w, level, d[9];
**char in;
**STUFF *pl;

**srand (time (NULL));
**intro ();
**for (n = 0; n < 9; n++) d[n] = W * (1 - n / 3) + (n % 3 - 1);
**level = (--argc) ? (atoi (argv[1]) - 1) : 0;
**sprintf (msg, "Game Start!");
**do {
****pl = p[setup (++level)]; m = 1;
****draw_floor (level);
****do {
******printf ("Move : ");
******if (m) {
********do in = getche (); while (iscntrl (in));
********if (in == '.') m = 0;
********else if (!(in - '0')) {
**********gorobo (pl); pl->loc = rand () % MAX_LOC;
**********sprintf (msg, "Stunned... Press ENTER"); draw_floor (level); 
**********getche ();
**********gorobo (pl);
********} else if (in > '0' && in <= '9') {
**********n = pl->loc + d[in - '1'];
**********if (SQ((n % W) - (pl->loc % W)) < 2 && n < MAX_LOC && n >= 0)
************pl->loc = n;
**********else sprintf (msg, "You were stopped by the wall.");
**********gorobo(pl);
********} else sprintf (msg, "Invalad entry.");
******} else gorobo(pl);
******w = draw_floor (level);
****} while (!w && pl->type == 2);
****if ((w = pl->type) == 2) sprintf (msg, "level %d complete! ", level);
****takedown ();
**} while (w == 2 && level < 10);
**if (w == 2) printf ("You Win!");
**else printf ("You were captured by the robots at level %d\n", level);
**exit (0);
}
And gameplay looks like this:
Code:
Stunned... Press ENTER
------------------------------------------------------------------------------|
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|************************************************************ +************** |
|**************************************************************************** |
|**************************+**************************************************|
|**************************************************************************** |
|********************************+********************************************|
|**************************************************** +**O********************|
|**************************************************************************** |
|**************************************************************************** |
|********************************************** +**************************** |
|**************************************************************************** |
|**************************************************************************** |
|**********************+******** #**** +********************+**************** |
|------------------------------------------------------------------------------
This code is pretty dynamic. You can change the height and width of the screen. You can change the effect of teleportation. (I experimented with atleast 3 different variations on that one.) A clever programmer could even add more evil robot types.

I wanted to see how small I could get it. My goal was 1K, less than 1024 characters. After much work I got it. But oh the sacrifices that had to be made:
Code:
#define q(a)(a)*(a)
#define f(u,v) if((p[n]->l u 79)v(l->l u 79))p[n]->l
typedef struct{int l,t;}z;z*p[99];int y;k(){int a=0,b,c=0,d=0;z*e;for(;a<=y;a++
){for(b=y;a<y&&b>a;b--)if(p[b]->l<p[b-1]->l){e=p[b];p[b]=p[b-1];p[b-1]=e;}if(a)
{if(p[a]->l==p[a-1]->l)p[a]->t=p[a-1]->t=3;else do{if(!(c%79))puts("");putchar(
" O+#"[(p[a-1]->l==c)?p[a-1]->t:0]);}while(++c<p[a]->l&&c<=1817);d+=(p[a-1]->t
==2);}}return d;}main(){int n=0,m,w,e=0,d[9],i;z*l;srand(time(0));for(;n<99;n++
){if(n<9)d[n]=79*(1-n/3)+(n%3-1);p[n]=malloc(sizeof(z));p[n]->l=1976;}do{y=m=7+
++e*4;n=rand()%m;w=1817;while(m-->0){p[m]->l=w-=rand()%(w/(m+1))+1;p[m]->t=(n!=
m)+1;}l=p[n];printf("\nLevel %d",e);m=k();do{if(m){do i=getche ();while(iscntrl
(i));if(i=='.')m=0;else if(!(i-'0'))l->l=rand()%1817;else if(i>'0'&&i<='9'){n=l
->l + d[i-'1'];if(q((n%79)-(l->l%79))<2&&n<1817&&n>=0)l->l=n;}}for(n=0;n<y;n++)
if(p[n]->t==2){f(%,>)-=1;else f(%,<)+=1;f(/,>)-=79;else f(/,<)+=79;}w=k();}
while(w&&l->t==1);}while(!w);if(w)printf("Ended on %d\n",e);}
In crunching robot escape to fit in less than 1k certain features had to be fudged. Robotescape1k does not free the memory it allocates, not much of a problem to most modern systems. Robotescape1k also makes no attempt at type checking. If you input an invalid keystroke, or run into a boundary for that matter, the program makes no attempt to tell you so, you simply lose a turn as though you pressed '5'. It also doesn't draw the borders, so you have to be careful at the edges.

In the 1k version there is technically no winning condition, so you can play until you are overwhelmed by sheer numbers. But Robotescape1k has a fixed max number of enemies on screen which, by the way, is 98 enemies and you makes 99. I was so crammed for space that adding one more digit to that number would have put me over. You exceed the maximum if you make it to level 24, which will consequenly crash the game. This however is an highly difficult thing to do, so consider the game beaten if you make it that far.

The 1k restriction also introduced a bug concerning the conditions of winning a level where it checks to see if all the robots are dead before checking if you are. In other words, if the last robot(s) kill themselves upon you, you still win and move on to the next level. Ah well, such is the price of this sort of pursuit. However, it can be a strange sort of satisfying to win by kamikaze / jihad / whatever.

.:EDIT:. CRA...UD. I wrote this ages ago and just noticed in the last line that "if(w)" can be removed, saving me 5 characters meaning I could take the game up to 9999999 on screen characters, more than the screen can handle, erradicating the level 24 cap. Meh, screw it. I never survived past level 16 myself anyways.
guesst is offline                         Send a private message to guesst
Reply With Quote