/* * ttyvaders Textmode shoot'em up * Copyright (c) 2002 Sam Hocevar * All Rights Reserved * * $Id: tunnel.c,v 1.8 2002/12/23 12:47:36 sam Exp $ * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include #include "common.h" /* Init tunnel */ tunnel * create_tunnel( game *g, int w, int h ) { int i; tunnel *t = malloc(sizeof(tunnel)); t->left = malloc(h*sizeof(int)); t->right = malloc(h*sizeof(int)); t->w = w; t->h = h; if( t->w >= g->w ) { for( i = 0; i < g->h; i++ ) { t->left[i] = -10; t->right[i] = g->w + 10; } } else { t->left[0] = (g->w - w) / 2; t->right[0] = (g->w + w) / 2; /* Yeah, sub-efficient, but less code to do :-) */ for( i = 0; i < g->h; i++ ) { update_tunnel( g, t ); } } return t; } void free_tunnel( tunnel *t ) { free( t->left ); free( t->right ); free( t ); } void draw_tunnel( game *g, tunnel *t ) { int i, j; char c; gfx_color( GREEN ); /* Left border */ for( i = 0; i < g->h ; i++ ) { if( t->left[i] <= -10 ) { continue; } if( i + 1 == g->h || t->left[i] > t->left[i+1] ) { c = ( i == 0 || t->left[i] > t->left[i-1] ) ? '>' : '/'; } else { c = ( i == 0 || t->left[i] > t->left[i-1] ) ? '\\' : '<'; } gfx_goto( t->left[i] + 1, i ); gfx_putchar( c ); if( i + 1 < g->h ) { for( j = 1; j < t->left[i+1] - t->left[i]; j++ ) { gfx_goto( t->left[i] + j + 1, i ); gfx_putchar( '_' ); } } } /* Right border */ for( i = 0; i < g->h ; i++ ) { if( t->right[i] >= g->w + 10 ) { continue; } if( i + 1 == g->h || t->right[i] > t->right[i+1] ) { c = ( i == 0 || t->right[i] > t->right[i-1] ) ? '>' : '/'; } else { c = ( i == 0 || t->right[i] > t->right[i-1] ) ? '\\' : '<'; } if( i + 1 < g->h ) { for( j = 1; j < t->right[i] - t->right[i+1]; j++ ) { gfx_goto( t->right[i+1] + j - 1, i ); gfx_putchar( '_' ); } } gfx_goto( t->right[i] - 1, i ); gfx_putchar( c ); } gfx_color( RED ); /* Left concrete */ for( i = 0; i < g->h ; i++ ) { for( j = 0 ; j <= t->left[i]; j++ ) { gfx_goto( j, i ); gfx_putchar( '#' ); } } /* Right concrete */ for( i = 0; i < g->h ; i++ ) { for( j = t->right[i] ; j < g->w ; j++ ) { gfx_goto( j, i ); gfx_putchar( '#' ); } } } void update_tunnel( game *g, tunnel *t ) { static int const delta[] = { -3, -2, -1, 1, 2, 3 }; int i,j,k; /* Slide tunnel one block vertically */ for( i = t->h - 1; i--; ) { t->left[i+1] = t->left[i]; t->right[i+1] = t->right[i]; } /* Generate new values */ i = delta[GET_RAND(0,6)]; j = delta[GET_RAND(0,6)]; /* Check in which direction we need to alter tunnel */ if( t->right[1] - t->left[1] < t->w ) { /* Not wide enough, make sure i <= j */ if( i > j ) { k = j; j = i; i = k; } } else if( t->right[1] - t->left[1] - 2 > t->w ) { /* Too wide, make sure i >= j */ if( i < j ) { k = j; j = i; i = k; } } else { /* No need to mess with i and j: width is OK */ } /* If width doesn't exceed game size, update coords */ if( t->w <= g->w || t->right[1] - t->left[1] < t->w ) { t->left[0] = t->left[1] + i; t->right[0] = t->right[1] + j; } else { t->left[0] = -10; t->right[0] = g->w + 10; } if( t->w > g->w ) { if( t->left[0] < 0 && t->right[0] < g->w - 2 ) { t->left[0] = t->left[1] + 1; } if( t->left[0] > 1 && t->right[0] > g->w - 1 ) { t->right[0] = t->right[1] - 1; } } else { if( t->left[0] < 0 ) { t->left[0] = t->left[1] + 1; } if( t->right[0] > g->w - 1 ) { t->right[0] = t->right[1] - 1; } } }