среда, 1 июля 2009 г.

Это ВТОРОЙ Тетрис 1996 года, первый был на Паскале и потерялся; а есть ещё пятнашки из-за которых мной разбили окно

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <time.h>
#include <dos.h>

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

void interrupt far (*old_09)(__CPPARGS);

long DELAY=6L,
D=DELAY;
#define WAIT_LEVEL (long)(18.2*(float)200)

#define FIGURES 7
#define MY 20 // field
#define MX 14 // size
#define VALUE 50
#define OUT_X 3
#define OUT_Y 3
#define OUT_ATTR (BLACK<<4)|LIGHTGRAY
#define MS_HOLE ' '
#define MS_FIG 'Ы'
#define KEYS 25

char *sf_name="tetris.sav";
FILE *sf_;
unsigned long max_bonus=0;
int LEVEL=1;

char figures[FIGURES][3][3]={
{{0,1,0},{0,1,0},{0,1,0}},
{{0,0,1},{0,0,1},{0,1,1}},
// {{0,1,0},{0,1,0},{0,0,0}},
// {{0,1,0},{1,1,0},{0,0,0}},
{{1,1,0},{1,1,0},{0,0,0}},
{{1,0,1},{1,1,1},{0,0,0}},
{{0,1,0},{1,1,0},{1,0,0}},
{{0,1,0},{0,1,1},{0,0,1}},
{{0,1,0},{1,1,1},{0,0,0}},
};

typedef enum{LEFT=0,RIGHT=1,DOWN=2}r_direct;
typedef enum{NORM=0,EX=1}r_turn;
typedef struct{char it,at;}r_item;

r_item **desk;
int cx,cy,c_ind;
volatile int next_key=0;
//volatile char *keys;
//int next_key=0;
char *keys;
char b_error;
unsigned long bonus;
volatile unsigned far *head=(unsigned far*)0x41aL;
volatile unsigned far *tail=(unsigned far*)0x41cL;
volatile unsigned long far *timer=(unsigned long far*)0x46cL;
unsigned long previous,TIMER;

r_item **alloc_arr(int my,int mx){
int i=0;
r_item *buf,**p;

p=new r_item *[my];
buf=new r_item [my*mx];
for(;i<my;i++){p[i]=buf;buf+=mx;}
return p;
}

void free_arr(r_item **p){
delete[] p[0];
delete[] p;
}

int rnd_fig(){
int r= (int)(*timer % 10);
return (r >= FIGURES)? r-FIGURES : r ;
}

void writech(char x,char y,char c,char attr){
asm{
mov b_error,0
push es
push di
mov cl,x
mov ch,y

test cl,cl
jz err1
test ch,ch
jz err1

dec ch // decr lines for check

xor ax,ax
mov es,ax
cmp ch,byte ptr es:[0x484] // rows
ja err1
cmp cl,byte ptr es:[0x44a] // columns
ja err1

dec cl

xor ax,ax
mov al,ch
mul word ptr es:[0x44a] // columns

xor ch,ch
add ax,cx

xchg ax,di
shl di,1

mov ax,0xb800 // video segment
mov es,ax
mov al,c
mov ah,attr
cli
cld
stosw
sti
jmp ex1}
err1:
asm{
mov b_error,1}
ex1:
asm{
pop di
pop es}
}

void clr_kb(void){
*head=*tail;
next_key=0;
keys[next_key]=0;
}

void interrupt far new_09(__CPPARGS){
char scan,inp,ok,*occur;//,*_keys=keys;
int i,j;

disable();
scan=inportb(0x60);

inp=inportb(0x61);
inp|=0x80; outportb(0x61,inp);
inp&=0x7f; outportb(0x61,inp);

if((scan&0x80)==0){
if(next_key<KEYS)keys[next_key++]=scan;
//else{keys[next_key=0]=scan;++next_key;}
}
else
if((scan!=0xe0)&&(scan!=0xe1)){ //release code
do{
keys[next_key]=0;
occur=strchr(keys,(int)(scan&0x7f));
if(occur!=NULL){
memmove(occur,occur+1,(size_t)(next_key-(occur-keys)-1));
--next_key;
}
}while((occur!=NULL)&&next_key);
}
enable();
outportb(0x20/*port*/,0x20);
}

char read_key(void){
char scan=*keys;

if(next_key>1) memmove(keys,keys+1,next_key-1);
--next_key;
return scan;
}

void save(void){
if((bonus>max_bonus)&&((sf_=fopen(sf_name,"wb"))!=NULL)){
fwrite(&bonus,1,sizeof(bonus),sf_);
fclose(sf_);
max_bonus=bonus;
}
}

void inc_bonus(void){
char cnt=0;
int y,x,holes;
r_item **buf=alloc_arr(MY,MX);

y=MY-1;
while(y>0){
holes=0;
for(x=0;x<MX;x++)if(desk[y][x].it==0)holes++;
if(!holes){
cnt++;
memmove(buf[0],desk[0],MY*MX*sizeof(r_item));
memmove(desk[1],buf[0],y*MX*sizeof(r_item));
for(x=0;x<MX;x++){desk[0][x].at=OUT_ATTR;desk[0][x].it=0;}
y=MY;
}
y--;
}
bonus+=cnt*VALUE;
free_arr(buf);
}

void frame(int x1,int y1,int x2,int y2,char attr){
int i;

writech(x1,y1,218,attr);
writech(x2,y1,191,attr);
writech(x1,y2,192,attr);
writech(x2,y2,217,attr);
for(i=x1+1;i<x2;i++){writech(i,y1,196,attr);writech(i,y2,196,attr);}
for(i=y1+1;i<y2;i++){writech(x1,i,179,attr);writech(x2,i,179,attr);}
}

void draw_next(void){
int i,j,
dn_y=OUT_Y-1,dn_x=OUT_X+MX+5;

frame(dn_x,dn_y,dn_x+6,dn_y+6,(BLUE<<4)|DARKGRAY);
writech(dn_x,dn_y+6,'Г',(BLUE<<4)|DARKGRAY);
writech(dn_x+6,dn_y+6,'ґ',(BLUE<<4)|DARKGRAY);
for(i=0;i<3;i++)for(j=0;j<3;j++)
writech(dn_x+j+2,dn_y+i+2,(!figures[c_ind][i][j])?' ':MS_FIG,OUT_ATTR);
}

void draw(void){
int y,x;

for(y=0;y<MY;y++)
for(x=0;x<MX;x++){
writech(OUT_X+x,OUT_Y+y,
(char)((desk[y][x].it==0)?MS_HOLE:MS_FIG),desk[y][x].at);
}
gotoxy(OUT_X+MX+5,OUT_Y+7);cprintf("і%-6lu",bonus);
writech(OUT_X+MX+11,OUT_Y+7,'і',BLUE<<4|DARKGRAY);
gotoxy(OUT_X+MX+5,OUT_Y+8);cprintf("і%-6i",LEVEL);
writech(OUT_X+MX+11,OUT_Y+8,'і',BLUE<<4|DARKGRAY);
}

void finish(void){
char *msg="Enter for continue ...";

textattr((BLUE<<4)|YELLOW);gotoxy(1,25);cprintf("%s",msg);clreol();
do{
clr_kb();
while(!next_key);
}while(keys[0]!=0x1c);
save();
}

int init_next(void){
int y,x,attr;

inc_bonus();

attr=(random(8)<<4)|(random(13)+3);
if(attr>BLINK)attr-=BLINK;
cx=MX/2-1;cy=0;
for(y=0;y<3;y++)for(x=0;x<3;x++)if(figures[c_ind][y][x])
if(desk[cy+y][cx+x].it==2){finish();return 0;}
else{desk[cy+y][cx+x].it=1;desk[cy+y][cx+x].at=attr;}
c_ind=rnd_fig();
draw_next();
return 1;
}

void turn(r_turn how){
int y,x;
r_item **buf=alloc_arr(3,3);

for(y=cy;y<cy+3;y++)for(x=cx;x<cx+3;x++){
if(desk[y][x].it==2){free_arr(buf);return;}
buf[y-cy][x-cx]=desk[y][x];}
for(y=0;y<3;y++)for(x=0;x<3;x++)
if(how==NORM) desk[cy+x][cx+2-y]=buf[y][x];
else desk[cy+2-x][cx+y]=buf[y][x];
free_arr(buf);
}

int move(r_direct dir){
int y,x,chg_cur=0;
r_item **buf=alloc_arr(MY,MX);

memmove(buf[0],desk[0],MY*MX*sizeof(r_item));
switch(dir){
case LEFT:
for(y=cy;y<cy+3;y++)for(x=cx;x<cx+3;x++)if(desk[y][x].it==1){
if(x==cx){chg_cur=1;if(x-1<0)goto _EXIT;}
if(desk[y][x-1].it==2)goto _EXIT;
desk[y][x].it=0; desk[y][x-1].it=1;
desk[y][x-1].at=desk[y][x].at; desk[y][x].at=OUT_ATTR;
}break;
case RIGHT:
for(y=cy;y<cy+3;y++)for(x=cx+2;x>=cx;x--)if(desk[y][x].it==1){
if(x==cx+2){chg_cur=1;if(x+1==MX)goto _EXIT;}
if(desk[y][x+1].it==2)goto _EXIT;
desk[y][x].it=0; desk[y][x+1].it=1;
desk[y][x+1].at=desk[y][x].at; desk[y][x].at=OUT_ATTR;
}break;
case DOWN:
for(y=cy+2;y>=cy;y--)for(x=cx;x<cx+3;x++)if(desk[y][x].it==1){
if(y==cy+2){chg_cur=1;if(y+1==MY)goto _EXIT;}
if(desk[y+1][x].it==2)goto _EXIT;
desk[y][x].it=0; desk[y+1][x].it=1;
desk[y+1][x].at=desk[y][x].at; desk[y][x].at=OUT_ATTR;
}
}
if(chg_cur)
switch(dir){
case LEFT:cx--;break;
case RIGHT:cx++;break;
case DOWN:cy++;
}
free_arr(buf);return 1;
_EXIT:
memmove(desk[0],buf[0],MY*MX*sizeof(r_item));
free_arr(buf);return 0;
}

void make_ice(void){
int y=0,x;

for(;y<MY;y++)for(x=0;x<MX;x++)if(desk[y][x].it==1)desk[y][x].it=2;
}

void initialize(void){
int y,x;

textmode(C40);
textattr(OUT_ATTR);clrscr();
_AH=1; _CX=0x2000; geninterrupt(0x10);

desk=alloc_arr(MY,MX);
keys=new char[KEYS+1];

for(y=0;y<MY;y++)for(x=0;x<MX;x++){
desk[y][x].it=0; desk[y][x].at=OUT_ATTR;}

c_ind=rnd_fig();
bonus=0;
init_next();
frame(OUT_X-1,OUT_Y-1,OUT_X+MX,OUT_Y+MY,(GREEN<<4)|DARKGRAY);
textattr(BLUE<<4|DARKGRAY);
gotoxy(OUT_X+MX+5,OUT_Y+6);cprintf("і%-6lu",max_bonus);
writech(OUT_X+MX+11,OUT_Y+6,'і',BLUE<<4|DARKGRAY);
gotoxy(OUT_X+MX+5,OUT_Y+9);cprintf("АДДДДДЩ");
draw();
}

void run(void){
int cont=0,i,key,bottom_moves=0,is_bottom=0;
unsigned long dif,temp;

initialize();

DELAY=D;
LEVEL=1;
TIMER=*timer;

while(1){
if((*timer-TIMER>WAIT_LEVEL)&&(DELAY>2)){DELAY--;TIMER=*timer;LEVEL++;}
if(!cont)previous=*timer;
while((!next_key)&&(abs((int)(dif=*timer-previous))<DELAY));
if((!next_key)&&(is_bottom))bottom_moves=0;
temp=*timer;
if(dif<DELAY){
switch((int)read_key()){
case 0x48:turn(NORM);if(bottom_moves>0)bottom_moves--;break;
case 0x1c:turn(EX);if(bottom_moves>0)bottom_moves--;break;
case 0x39:case 0x50:
clr_kb();
if(bottom_moves>0)break;
while(move(DOWN)){
bonus+=VALUE/20;
draw();
i=0;
do{delay(1);i++;}while((!next_key)&&(i<18));
if(next_key){
switch((int)read_key()){
case 0x4b:move(LEFT);draw();clr_kb();break;
case 0x4d:move(RIGHT);draw();clr_kb();break;
}
clr_kb();
}
clr_kb();
}
bottom_moves=MX;
is_bottom=1;
previous=*timer-5;
clr_kb();
break;
case 0x4b:move(LEFT);if(bottom_moves>0)bottom_moves--;break;
case 0x4d:move(RIGHT);if(bottom_moves>0)bottom_moves--;break;
case 1:save();free_arr(desk);delete[] keys;return;
case 0x44/*F10*/:
save();
free_arr(desk);delete[] keys;
setvect(0x09,old_09);
textmode(C80);
exit(0);
}
cont=1;
}else cont=0;
if(!cont)
if((!move(DOWN))&&(!bottom_moves)){
make_ice();
if(!init_next()){
free_arr(desk);delete[] keys;
clr_kb();
return;
}
bottom_moves=0;
is_bottom=0;
clr_kb();
}
draw();
if(cont)previous+=(*timer-temp);
}
}

void main(void){
old_09=getvect(0x09);
setvect(0x09,new_09);

if((sf_=fopen(sf_name,"rb"))!=NULL)
{fread(&max_bonus,1,sizeof(max_bonus),sf_);fclose(sf_);}
while( 1 ) run();
}

Комментариев нет:

Отправить комментарий