⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bowl.c

📁 LTris a tetris clone for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************                          bowl.c  -  description                             -------------------    begin                : Tue Dec 25 2001    copyright            : (C) 2001 by Michael Speck    email                : kulkanie@gmx.net ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************/#include "ltris.h"#include "config.h"#include "tools.h"#include "shrapnells.h"#include "cpu.h"#include "bowl.h"extern Config config;extern Sdl sdl;extern SDL_Surface *offscreen;extern SDL_Surface *bkgnd;extern int keystate[SDLK_LAST];extern Bowl *bowls[BOWL_COUNT];extern int cpu_original_bowl[BOWL_WIDTH][BOWL_HEIGHT];extern Block_Mask *cpu_block;enum { FIGURE_COUNT = 21 };int figures[FIGURE_COUNT][BOWL_WIDTH][BOWL_HEIGHT];Block_Mask block_masks[BLOCK_COUNT];extern Bowl *bowls[BOWL_COUNT];extern int  *next_blocks, next_blocks_size;#define BOWL_DOWN_VEL_START    0.025#define BOWL_DOWN_VEL_END      0.32#define BOWL_DOWN_PERC_CHANGE  0.085/*====================================================================Locals====================================================================*//*====================================================================Get speed according to level of bowl.====================================================================*/void bowl_set_vert_block_vel( Bowl *bowl ){    int i;    /* ranges from BOWL_DOWN_VEL_START to BOWL_DOWN_VEL_END within twenty levels */    bowl->block_vert_vel = BOWL_DOWN_VEL_START;    for ( i = 0; i < bowl->level; i++ ) {//        printf( "Level %2i: %2.5f\n", i, bowl->block_vert_vel );        bowl->block_vert_vel += ( BOWL_DOWN_VEL_END - bowl->block_vert_vel ) * BOWL_DOWN_PERC_CHANGE;    }    /* set add action info */    if ( config.gametype == 2 ) {        bowl->dismantle_saves = 1;        /* 7 - 12 single tiles */        if ( bowl->level >= 7 && bowl->level <= 12 ) {            delay_set( &bowl->add_delay, 2000 + ( 12 - bowl->level ) * 500 );            bowl->add_lines = 0;            bowl->add_tiles = 1;        }        /* 13 - ... whole lines */        if ( bowl->level >= 13 ) {            if ( bowl->level <= 20 )                delay_set( &bowl->add_delay, 2000 + ( 20 - bowl->level ) * 500 );            else                delay_set( &bowl->add_delay, 2000 );            bowl->add_lines = 1;            bowl->add_tiles = 0;            bowl->add_line_holes = bowl->level - 12;            if ( bowl->add_line_holes > 6 )                bowl->add_line_holes = 6;        }    }}/*====================================================================Get position of helping shadow of block.====================================================================*/int bowl_block_pos_is_valid( Bowl *bowl, int x, int y ){    int i, j;    for ( i = 0; i < 4; i++ )        for ( j = 0; j < 4; j++ )            if ( block_masks[bowl->block.id].mask[bowl->block.rot_id][i][j] )                if ( x + i >= 0 && x + i < bowl->w ) {                    if ( y + j >= bowl->h ) return 0;                    if ( y + j >= 0 )                        if ( bowl->contents[x + i][y + j] != -1 )                            return 0;                }            return 1;}void bowl_compute_help_pos( Bowl *bowl ){    int j = bowl->block.y;    while ( bowl_block_pos_is_valid( bowl, bowl->block.x, j ) ) j++;    j--;    bowl->help_sx = bowl->block.x * bowl->block_size + bowl->sx;    bowl->help_sy = j * bowl->block_size + bowl->sy;}/*====================================================================Compute position of preview====================================================================*/void bowl_compute_preview_pos( Bowl *bowl ){    int i, j;    int x1, y1, x2, y2; /* corners of the tile */    if ( bowl->preview_center_sx == -1 )         return;    /* first tile */    x1 = y1 = -1;    for ( j = 0; j < 4; j++ ) {        for ( i = 0; i < 4; i++ ) {            if ( block_masks[bowl->next_block_id].mask[0][i][j] ) {                y1 = j;                break;            }        }        if ( y1 != -1 ) break;    }    for ( i = 0; i < 4; i++ ) {        for ( j = 0; j < 4; j++ ) {            if ( block_masks[bowl->next_block_id].mask[0][i][j] ) {                x1 = i;                break;            }        }        if ( x1 != -1 ) break;    }    /* last tile */    x2 = y2 = -1;    for ( j = 3; j >= 0; j-- ) {        for ( i = 3; i >= 0; i-- ) {            if ( block_masks[bowl->next_block_id].mask[0][i][j] ) {                y2 = j;                break;            }        }        if ( y2 != -1 ) break;    }    for ( i = 3; i >= 0; i-- ) {        for ( j = 3; j >= 0; j-- ) {            if ( block_masks[bowl->next_block_id].mask[0][i][j] ) {                x2 = i;                break;            }        }        if ( x2 != -1 ) break;    }    /* preview position */    bowl->preview_sx = bowl->preview_center_sx - ( x1 * bowl->block_size + ( ( ( x2 - x1 + 1 ) * bowl->block_size ) >> 1 ) );    bowl->preview_sy = bowl->preview_center_sy - ( y1 * bowl->block_size + ( ( ( y2 - y1 + 1 ) * bowl->block_size ) >> 1 ) );}/*====================================================================Compute computer target====================================================================*/void bowl_compute_cpu_dest( Bowl *bowl ){    int i, j;    CPU_Data cpu_data;    /* pass bowl contents to the cpu bowl */    if ( config.gametype == 0 ) /* demo is supposed to get the highest scores */        cpu_data.aggr = 0; /* so play defensive */    else        cpu_data.aggr = config.cpu_aggr; /* else use the wanted setting */    cpu_data.bowl_w = bowl->w;    cpu_data.bowl_h = bowl->h;    cpu_data.original_block = &block_masks[bowl->block.id];    cpu_data.original_preview = &block_masks[bowl->next_block_id];    for ( i = 0; i < bowl->w; i++ )        for ( j = 0; j < bowl->h; j++ )            cpu_data.original_bowl[i][j] = ( bowl->contents[i][j] != -1 );    /* get best destination */    cpu_analyze_data( &cpu_data );    bowl->cpu_dest_x = cpu_data.dest_x;    bowl->cpu_dest_rot = cpu_data.dest_rot;    bowl->cpu_dest_score = cpu_data.dest_score;}/*====================================================================Initate next block.====================================================================*/void bowl_create_next_block( Bowl *bowl ) {    int i, min, *new_next_blocks = 0;        bowl->block.id = bowl->next_block_id;    /* for experts: weight probability of next block against to      * helpfulness with a 50% chance. equal properties else. */    if ( config.expert && (rand()%2) ) {         int i, j, threshold, saveblockid;         struct { int block, score; } tmp, scores[BLOCK_COUNT];        saveblockid = bowl->block.id;        for (i=0; i<BLOCK_COUNT; i++ ) {            bowl->block.id = i;            bowl_compute_cpu_dest( bowl );            scores[i].block = i;            scores[i].score = bowl->cpu_dest_score;        }        /* Sort */        for ( i=0; i<BLOCK_COUNT-1; i++ ) {            for ( j=i+1; j<BLOCK_COUNT; j++ ) {                if ( scores[j].score < scores[i].score ) {                    tmp = scores[i];                    scores[i] = scores[j];                    scores[j] = tmp;                }            }        }        /* 50% chance of worst block, 25% next worse, etc.. */        j = rand();        threshold = RAND_MAX / 2;        for (i=0; i<BLOCK_COUNT-1; i++ ) {            if ( j > threshold ) break;            threshold /= 2;        }        bowl->next_block_id = scores[i].block;        bowl->block.id = saveblockid;    } else {        /* Even next-block probabilities */        if ( bowl->use_same_blocks )        {            bowl->next_block_id = next_blocks[bowl->next_blocks_pos++];            if ( bowl->next_blocks_pos == next_blocks_size )            {                /* resize block buffer and get new blocks */                min = next_blocks_size;                for ( i = 0; i < BOWL_COUNT; i++ )                    if ( bowls[i] && bowls[i]->next_blocks_pos < min )                        min = bowls[i]->next_blocks_pos;                for ( i = 0; i < BOWL_COUNT; i++ )                    if ( bowls[i] )                        bowls[i]->next_blocks_pos -= min;                new_next_blocks =                     calloc( next_blocks_size - min +                             NEXT_BLOCKS_CHUNK_SIZE,                            sizeof(int) );                memcpy( new_next_blocks, &next_blocks[min],                        sizeof(int) * (next_blocks_size - min) );                fill_int_array_rand( new_next_blocks,                                      next_blocks_size - min,                                     NEXT_BLOCKS_CHUNK_SIZE,                                     0, BLOCK_COUNT-1 );                free( next_blocks );                next_blocks = new_next_blocks;                next_blocks_size = next_blocks_size - min +                                   NEXT_BLOCKS_CHUNK_SIZE;            }        }        else        {            bowl->next_block_id = rand() % BLOCK_COUNT;             if ( bowl->next_block_id == bowl->block.id )                bowl->next_block_id = rand() % BLOCK_COUNT;        }    }    bowl->block.x = 3;    bowl->block.y = -3;    bowl->block.sx = bowl->sx + bowl->block_size * bowl->block.x;    bowl->block.sy = bowl->sy + bowl->block_size * bowl->block.y;    bowl->block.rot_id = 0;    bowl->block.sw = bowl->block.sh = 4 * bowl->block_size;    bowl->block.cur_x = bowl->block.x * bowl->block_size;    bowl->block.cur_y = bowl->block.y * bowl->block_size;    bowl->block.check_y = (int)bowl->block.cur_y;    bowl_compute_help_pos( bowl );    bowl_compute_preview_pos( bowl );    /* if CPU is in control get destination row & other stuff */    if ( !bowl->controls ) {        /* destination */        bowl_compute_cpu_dest( bowl );        /* set delay until cpu waits with dropping block */        delay_set( &bowl->cpu_delay, config.cpu_delay );        bowl->cpu_down = 0;        delay_set( &bowl->cpu_rot_delay, config.cpu_rot_delay );    }}/*====================================================================Set a tile contents and pixel contents.====================================================================*/inline void bowl_set_tile( Bowl *bowl, int x, int y, int tile_id ){    int i, j = y * bowl->block_size;    bowl->contents[x][y] = tile_id;    for ( i = 0; i < bowl->block_size; i++ )        bowl->pixel_contents[x][j + i] = tile_id;}/*====================================================================Reset bowl contents and add levels figure if wanted.====================================================================*/void bowl_reset_contents( Bowl *bowl ){    int i, j;    for ( i = 0; i < bowl->w; i++ )        for ( j = 0; j < bowl->h; j++ )            bowl_set_tile( bowl, i, j, -1 );    if ( bowl->use_figures && bowl->level < 20 /* don't have more figures */ )        for ( i = 0; i < bowl->w; i++ )            for ( j = 0; j < bowl->h; j++ )                bowl_set_tile( bowl, i, j, figures[bowl->level][i][j] );}/*====================================================================Check if the passed pixel position by rotation is a valid onefor bowl::block.NOTE: py is a pixel value and x is a bowl map value.The tolerance value moves the checked corners into the middleof the brick opening a small 'window' to move though it's blocked.Useful when config::block_by_block is disabled.====================================================================*/int bowl_validate_block_pos( Bowl *bowl, int x, int py, int rot, int tol ){    int i, j;    int tile_y = 0;    for ( j = 0; j < 4; j++ ) {        for ( i = 0; i < 4; i++ ) {            if ( block_masks[bowl->block.id].mask[rot][i][j] ) {                if ( x + i < 0 ) return 0;                if ( x + i >= bowl->w ) return 0;                if ( py + tile_y >= bowl->sh ) return 0;                /* if it doesn't fit the screen from above it's okay */                if ( py + tile_y < 0 ) continue;                /* bowl pixel contents */                if ( bowl->pixel_contents[i + x][py + tile_y + tol]!= -1 ) return 0;                if ( bowl->pixel_contents[i + x][py + tile_y + bowl->block_size - 1 - tol] != -1 ) return 0;                /* if the bowl bottom is hit it is a collision as well */                if ( py + tile_y + tol >= bowl->sh ) return 0;                if ( py + tile_y + bowl->block_size - 1 - tol >= bowl->sh ) return 0;            }        }        tile_y += bowl->block_size;    }    return 1;}/*====================================================================Draw block to offscreen.====================================================================*/void bowl_draw_block_to_offscreen( Bowl *bowl ){    int i, j;    int tile_x = 0, tile_y = 0;        if ( bowl->blind ) return;        bowl->block.sx = bowl->block.x * bowl->block_size + bowl->sx;    bowl->block.sy = bowl->block.y * bowl->block_size + bowl->sy;    for ( j = 0; j < 4; j++ ) {        for ( i = 0; i < 4; i++ ) {            if ( block_masks[bowl->block.id].mask[bowl->block.rot_id][i][j] ) {                DEST( offscreen, bowl->block.sx + tile_x, bowl->block.sy + tile_y, bowl->block_size, bowl->block_size );                SOURCE( bowl->blocks, bowl->block.id * bowl->block_size, 0 );                blit_surf();            }            tile_x += bowl->block_size;        }        tile_y += bowl->block_size;        tile_x = 0;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -