TASVideos

Tool-assisted game movies
When human skills are just not enough

Fractal Fusion / Source

Table of contents [expand all] [collapse all]


Bisqwit: For now, I am opposed against mechanically changing all quotes [1]. I have noticed that some machine translators, such as Excite, cannot cope with the typographically proper quotes. Thus I try to avoid inserting them in contexts that I think I would like to be understood through machine translation too ― that being the important pages such as MovieRules.
This is one of the reasons why I actually try to avoid quotes altogether, by replacing it's with it is, for example.
Notice that the <q> tag (that comes from the «« »» markup) does not suffer from this limitation.
[1]: Actually, against all mechanical changes, such as timeattack→TAS or nesvideos→tasvideos…

This program was motivated out of a desire to program something that transfers input by specifying only the target frame where to start to overwrite and the source frame from where to transfer.

It is currently experimental, and it looks bad, but it works (with VBM files). It does not work with anything but VBM files. Back-up your movie files if you use something like this.

P.S. The downloaded ROM came with the misspelling "Tommorow". I didn't spell it wrong; I just didn't bother to fix it. :)

P.P.S. The filenames listed are only examples. Use whatever fits the situation.

vbmfuse.cc:

#include <stdio.h>

long rlong(FILE *f);

int main()
{
    FILE *f, *g; //source; target
    unsigned long d, frame;
    int y;
    
    if(!(f=fopen("zzzz.vbm","rb")))
    {
      printf("No source");
      goto qq2;
    }

    if(!(g=fopen("1626 - Tom Clancy's Splinter Cell - Pandora Tommorow (U)(Chameleon).vbm","rb+")))
    {
      printf("No target");
      goto qq1;
    }
    
    fseek(f,0x3C,0);
    d=rlong(f);
    
    printf("Target frame:");
    scanf("%d", &frame);
    fseek(g,0x3C,0);
    d=rlong(g);
    
    printf("Source frame:");
    scanf("%d", &frame);
    fseek(f,0x3C,0);
    d=rlong(f);
    
    fseek(g,d+frame*2,0);
    fseek(f,d+frame*2,0);

    while(1)
    {
            y=fgetc(f);
            if(feof(f)) break;
            fputc(y,g);
    }
    
    fseek(g,0xE,0);
    fputc(0x10, g);
    
qq:
    fclose(g);
qq1:
    fclose(f);
qq2:
    return(0);
}

long rlong(FILE *f)
{
     unsigned long d=0;
     
     d+=fgetc(f);
     d+=fgetc(f)*256;
     d+=fgetc(f)*256*256;
     d+=fgetc(f)*256*256*256;
     
     return(d);
}

Inappropriately named quotes2.cc, this program changes code or code-like text to adapt to this wiki. It does this by indenting each line by one space, breaking some double-brackets, and doubling [ and ].

Don't use this program and then try to %%SRC_EMBED it. %%SRC_EMBED function operates differently from the wiki.

quotes2.cc:

#include <stdio.h>
#include <string.h>

int main (int argc, char *argv[])
{
    FILE *fp, *fq;
    char fn[100];
    char c[15]="_COPY.txt";
    char x,y;
    
    if(argc<2)
               return 1;

    
    strncpy(fn,argv[1],80);

    
    printf("%s", fn);
    
    if(!(fp = fopen(fn,"rb")))
           return 1;

    strncat(fn,c,12);

    if(!(fq = fopen(fn,"wb")))
    {
           fclose(fq);
           return 1;
    }
    
    y=0;
    
    while(1)
    {
        x=y;
        y=fgetc(fp);
        if(feof(fp))
                    break;
        
        if(y=='\n')
        {
                   fputc(y,fq);
                   fputc(' ',fq);
        }
        
        else if(( x=='{' || x=='(' || x=='}' || x==')' ) && y==x)
        {
                    fputc('\'',fq);     fputc('\'',fq);
                    fputc('\'',fq);     fputc('\'',fq);
                    fputc(y,fq);
        }
        
        else if(( y=='[' || y==']'))
        {
             fputc(y,fq); fputc(y,fq);
        }
        
        else
        {
            fputc(y,fq);
        }
    }
    
    
    fclose(fq);
    fclose(fp);
    
    return 0;   
}

This program puts random numbers for each byte into a file. I used this for my Mega Man X submission and one of my avatars.

garbagegenerator.cc:

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

int main()
{
    srand(unsigned(time(0)));
    FILE *fp;
    int i,j;
    long k;
    
    if(!(fp=fopen("wxyz","wb")))
       return 1;
    
    printf("How many bytes of garbage do you want?");
    scanf("%d",&k);
    for(i=1;i<=k;i++)
              fputc(rand()%256,fp); 
    fclose(fp);
    return(0);
}

This program simulates the slot machine in Space Quest 1 EGA. All probabilities were discovered by decompilation of SQ1 using AGI Studio. The resulting ratio of successes to trials appears to confirm the value given by the slot machine solver program (0.00666, 1 in 150). If bz is set to 40 and the success point at 250, the ratio drops to about 0.0062 (1 in 160).

sq1slotmachine2.cc:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LIMIT 1000000

int main()
{
    long i,success=0, skulls=0;
    int bz, c, bet;
    srand(unsigned(time(0)));

    for(i=1;i<=LIMIT;i++)
    {
        bz=42;
        while(1)
        {
        c=rand()%100+1;
        bet=3;

        if (c<=2) {skulls++; bz=0;}
        else if (c<=70) bz-=bet;
        else if (c<=77) bz+=2*bet;
        else if (c<=81) bz+=4*bet;
        else if (c<=83) bz+=9*bet;
        else if (c<=84) bz+=19*bet;

        if (bz<=0) break;
        if (bz>=249) {success++; break;}
        }
    }

    printf("%d %f %d",success, ((float)success)/LIMIT, skulls);
    getchar();
    return(0);
}

This program implements a Markov matrix representation for the slot machine in Space Quest 1 EGA. All probabilities were discovered by decompilation of SQ1 using AGI Studio. Repeatedly squaring this matrix 50 times (way too much, 15 is sufficient) brings the matrix to a limit (single-precision floating point). Note that there are two absorbing states: 0 (lose) and 83 (win). All other states represent buckazoids (currency in SQ1) divided by 3.

Starting from 42 buckazoids, the probability of making it to 249 buckazoids is about 0.006656957131849 (1 in 150.218783175827).

The theory behind the matrix representation is that there is a base matrix which represents 1-step (2^0-step) probability from one state to another. Every time the matrix is squared, it doubles the number of steps from n-step probability to 2*n-step probability. Squaring the base matrix 50 times results in a 2^50-step probability matrix. For most matrices, the probability values reach a limit.

Read the resulting output file with word-wrap off. The row numbers are prior states and the column numbers are final states. Only the final states 0 and 83 should have positive numbers.

sq1slotmachine.cc

#include <stdio.h>

void initarray();
int min(int a, int b);
void squarearray();
void printarray();

FILE *fp;
double m[84][84];

int main()
{
    int x;
    if(!(fp=fopen("wxyz2.txt","w")))
       return 1;

    initarray();
    for(x=1;x<=50;x++)
        squarearray();
    printarray();

    return(0);
}

void printarray()
{
     //header
     int i,j;
     fprintf(fp,"\t");
     for(i=0;i<=83;i++)
        fprintf(fp,"%d\t",i);
     fprintf(fp,"\n");

     //rest
     for(i=0;i<=83;i++)
     {
        fprintf(fp, "%d\t",i);
        for(j=0;j<=83;j++)
            fprintf(fp, "%.5f\t",m[i][j]);
        fprintf(fp, "\n");
     }
}

void initarray()
{
     int i,j;
     for(i=0;i<=83;i++)
        for(j=0;j<=83;j++)
           m[i][j]=0;

     m[0][0]=1; //lose
     m[83][83]=1; //win
     for(i=1;i<83;i++)
     {
        m[i][0]+=0.02; //skulls
        m[i][i-1]+=0.68; //nothing
        m[i][i]+=0.16; //1 cherry
        m[i][min(83,i+2)]+=0.07; //2 cherries
        m[i][min(83,i+4)]+=0.04; //3 cherries
        m[i][min(83,i+9)]+=0.02; //eyes
        m[i][min(83,i+19)]+=0.01; //diamonds
     }
}

void squarearray()
{
     int i,j,k;
     double n[84][84];
     double sum;
     for(i=0;i<=83;i++)
        for(j=0;j<=83;j++)
        {
           sum=0;
           for(k=0;k<=83;k++)
               sum+=m[i][k]*m[k][j];
           n[i][j]=sum;
        }

     for(i=0;i<=83;i++)
        for(j=0;j<=83;j++)
           m[i][j]=n[i][j];
}

int min(int a, int b)
{
    return ((a<b)?a:b);
}

This program calculates a score for an .smv based on left-right-left wobbling.

Left-right-left scores 1 point. Right-left-right scores 1 point. (Left+right)=right

#include <stdio.h>
#include <string.h>

long rlong(FILE *f);

int main (int argc, char *argv[])
{
    FILE *fp;
    char fn[200];
    unsigned int x,y,z;
    long score=0, offset;
    
    if(argc<2)
    {
              printf("sdikuthw");
              getchar();
              return 1;
    }

    
    strncpy(fn,argv[1],180);
    if((fp = fopen(fn,"rb"))==NULL)
    {
           printf("%s",fn);
           getchar();
           return 1;
    }
           
    fseek(fp,0x1C,0); 
    
    offset=rlong(fp);
        
    fseek(fp,offset,0);
    
        x=fgetc(fp);
    x=256*x+fgetc(fp);
        y=fgetc(fp);
    y=256*y+fgetc(fp);
        z=fgetc(fp);
    z=256*z+fgetc(fp);

    while(1)
    {
            if ( ( ((x&3)==1)&&((y&3)==2)&&((z&3)==1) ) || ( ((x&3)==2)&&((y&3)==1)&&((z&3)==2) ) )
               score++;
            if ( ( ((x&3)==3)&&((y&3)==2)&&((z&3)==3) ) || ( ((x&3)==2)&&((y&3)==3)&&((z&3)==2) ) )
               score++; //leftright
            x=y;
            y=z;
            z=fgetc(fp);
            z=256*z+fgetc(fp);
            if(feof(fp))
             break;
    }
            
    printf("%d",score);
    
    getchar();
    return(0);
}

long rlong(FILE *f)
{
     unsigned long d=0;
     
     d+=fgetc(f);
     d+=fgetc(f)*256;
     d+=fgetc(f)*256*256;
     d+=fgetc(f)*256*256*256;
     
     return(d);
}
     

This program generates a colorful 80x80 .bmp.

rainbow.cc:

#include <stdio.h>
#include <math.h>
#include <string.h>

long hue(int angle, float r);
float arg(float x, float y);
float rad(float x, float y);

int main()
{
    FILE *f;
    int x,y;
    float zarg, zrad;
    long h;
    unsigned char red,blue,green;
    char header[]={0x42,0x4d,0x0a,0xb7,0x02,0,0,0,0,0,
    0x36,0,0,0,0x28,0,0,0,0x50,0,0,0,0x50,0,0,0,
    0x01,0,0x18,0,0,0,0,0,0xd4,0xb6,0x02,
    0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0};
    
    if(!(f=fopen("rainbow.bmp","wb")))
    {
      printf("fail");
      getchar();
      return(1);
    }
    
    fwrite(header,1,54,f);
    
    for(x=1;x<=80;x++)
    {
    for(y=1;y<=80;y++)
    {
       zarg=arg((float)(x-40),(float)(y-40));
       zrad=rad((float)(x-40),(float)(y-40));
       h=hue((int)(((float)240/360)*zarg),zrad/40);
       red=h%256;
       h/=256;
       green=h%256;
       h/=256;
       blue=h%256;
       fputc(blue,f);
       fputc(green,f);
       fputc(red,f);
       
    }
    }
    
    /*
    float s;
    s=arg(1,1);
    printf("%f\n",s);
    
    printf("%X",hue(111));
    */
    
    fclose(f);
    getchar();
    
    
    return(0);
    
}


float rad(float x, float y)
{
      return(sqrt(x*x+y*y));
}

float arg(float x, float y)
{
      float c;
      if(x==0 && y==0) return(0);
      c=(180/3.141592654)*acos(x/sqrt(x*x+y*y));
      if(y>=0) return(c); else return(360-c);
}

long hue(int angle, float r)
{
     unsigned char red=0, blue=0, green=0;
     unsigned long s;
     if(angle>=0 && angle<40) //r g^ b
     {
                 red=255;
                 green=(char)(((float)255/40)*angle);
                 blue=0;
     }
     
     if(angle>=40 && angle<80) //rv g b
     {
                 red=(char)(((float)255/40)*(80-angle));
                 green=255;
                 blue=0;
     }
     
     if(angle>=80 && angle<120) //r g b^
     {
                 red=0;
                 green=255;
                 blue=(char)(((float)255/40)*(angle-80));
     }
     
     if(angle>=120 && angle<160) //r gv b
     {
                 red=0;
                 green=(char)(((float)255/40)*(160-angle));
                 blue=255;
     }
     
     if(angle>=160 && angle<200) //r^ g b
     {
                 red=(char)(((float)255/40)*(angle-160));
                 green=0;
                 blue=255;
     }
     
     if(angle>=200 && angle<240) //r g bv
     {
                 red=255;
                 green=0;
                 blue=(char)(((float)255/40)*(240-angle));
     }
     
     if(r>=0 && r<1)
     {
             blue=(char)(blue*r);
             green=(char)(green*r);
             red=(char)(red*r);
     }
     
     if(r>=1 && r<2)
     {
             blue=(char)(255-(255-blue)*(2-r));
             green=(char)(255-(255-green)*(2-r));
             red=(char)(255-(255-red)*(2-r));
     }
             
     
     
     s=blue;
     s=s*256+green;
     s=s*256+red;
     
     return(s);
     
}

Bisqwit: May I humbly suggest the following refactoring for that code:

#include <complex>
#include <cstdio>

/* hsv_to_rgb:
 *  Converts from HSV (hue, saturation, value) colorspace
 *  to RGB values (red, green, blue).
 */
template<typename IntType>
static void hsv_to_bgr
    (double h, double s, double v,
     IntType bgr[3])
{
    v *= 255.0;

    if (s == 0.0)
        bgr[0] = bgr[1] = bgr[2] = IntType(v);
    else
    {
        while (h < 0)h += 360;
        h = fmod(h, 360.0) / 60.0;
        int i = (int)h;
        double frac = h - i;
        double p = v - v * s, qt = v * s * frac;
        
        bgr[ (10-i)%6/2 ] = IntType(v); // max  
        bgr[  (7-i)%6/2 ] = IntType(p); // min
        bgr[    (i+1)%3 ] = IntType(
            (i&1) ? v - qt    // max downto min
                  : p + qt ); // min   upto max
    }
}

int main()
{
    static const char fn[] = "rainbow.tga";
    const int Xdim = 80, Ydim = 80;
    
    std::FILE* fp = fopen(fn, "wb");
    if(!fp) { perror(fn); return -1; }
    
    static const unsigned char tgaBuf[] = {
        0,0,2, 0,0, 0,0, 0, 0,0, 0,0,
        Xdim&255, Xdim>>8,
        Ydim&255, Ydim>>8,
        24,32};
    
    std::fwrite(tgaBuf, 1, sizeof(tgaBuf), fp);
    
    for(int y=0; y<Ydim; ++y)
        for(int x=0; x<Xdim; ++x)
        {
            std::complex<double> c ( 1.0-y*2.0/Ydim, x*2.0/Xdim-1.0 );
            /* Using complex numbers here because it hides the trigonometric
             * calculations (angle, distance) rather nicely.
             * Note: Y axis is reversed because Tga file origin is in lower left corner.
             */
            double h = std::arg(c) * 180.0 / 3.141592653; /* Radians to degrees */
            double v = std::abs(c);
            double s = 1.0;
            if(v > 1.0)
            {
                s = std::max(0.0, s - (v-1.0) / 0.414); // vary saturation for corners (optional)
                v = 1.0; // clamp brightness to maximum
            }
            
            unsigned char bgr[3] /* blue, green, red */;
            hsv_to_bgr(h, s, v, bgr);

            std::fwrite(bgr, 1, 3, fp);
        }
    std::fclose(fp);
}


Combined RSS Feed
FractalFusion/Source last edited by Ilari on 2011-06-26 16:39:39
Page info and history | Latest diff | List referrers | View Source