home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /***************************************************************************
- *
- * BZ - Multiplayer tank game -- solo module.
- *
- * $Id: bzsolo.c,v 1.3 1993/08/11 19:46:29 adele Exp $
- *
- * Chris Fouts - Silicon Graphics, Inc.
- * April, 1992
- **************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <string.h>
- #include <bstring.h>
- #include <sys/time.h>
- #include <sys/param.h>
- #include <X11/Intrinsic.h>
- #include <gl/gl.h>
- #include "bz.h"
- #include "bzobjs.h"
- #include "bzsolo.h"
- #include "bzbase.h"
- #include "bzcollide.h"
- #include "bzsound.h"
- #include "framerate.h"
-
- #define MISLRMIN 20.0f
- #define MISSILE_STRIKE 1
- #define VAPORIZE 2
- #define FRIENDLY_FIRE 3
-
- #define REMINDER_DELAY 180.0f
-
- static struct BzEnemy {
- unsigned avoiding ;
- unsigned lead_me ;
- unsigned flip ;
- unsigned can_wait ;
- unsigned turning ;
- int enemy_loading ;
- int mine_status ;
- float mine_x ;
- float mine_y ;
- float target_angle ;
- float turning_l ;
- float turning_r ;
- float dist ;
- struct timeval msl_launch ;
- struct timeval msl_explode ;
- struct timeval death_time ;
- struct timeval wait_time ;
- } robot[MAX_ENEMY+1] ;
-
-
- static int max_wait = 200 ;
- static float zig_zag_angle = 0 ;
- extern float vx[] ;
- extern float vy[] ;
- extern float msl_vx[] ;
- extern float msl_vy[] ;
- extern float last_msl_x[] ;
- extern float last_msl_y[] ;
- static float fire_ang = 30.0f ;
- static unsigned tanks_per_level ;
- static unsigned super_tank_prob ;
- static unsigned runner_tank_prob ;
- static unsigned new_man_score ;
- static unsigned new_man_score_inc ;
-
- extern unsigned int number_players ;
- extern struct BzMember player[] ;
- extern float obst_x[] ;
- extern float obst_y[] ;
- extern struct timeval current_time ;
- extern float rm_vel ;
- extern float d_time ;
- extern Boolean need_to_show_score ;
- extern Boolean need_to_show_lives ;
- extern unsigned int lives ;
- extern unsigned int practice_level ;
- extern float vx[] ;
- extern float vy[] ;
- extern float vmax[] ;
- extern float t_factor ;
- extern long loading_missile ;
- extern unsigned int level ;
- extern Boolean need_to_show_players ;
- extern Boolean need_to_show_level ;
- extern GL_Object tank_logo[] ;
- extern int tank_logo_side[] ;
- extern char player_name[] ;
- extern struct timeval missile_launch_time ;
- extern struct timeval missile_explode_time ;
- extern struct timeval time_of_death ;
- extern struct timeval hit_time ;
- extern Boolean kids_mode ;
-
-
-
- static struct timeval pause_begin ;
- static struct timeval pause_end ;
- static long reminders ;
-
- static long logo_count = 0 ;
- static GL_Object *robot_logo = NULL ;
- static int *robot_logo_side = NULL ;
-
- /* BEGIN PROTOTYPES -S bzsolo.c */
- static int aimed_at_enemy( unsigned int enemy ) ;
- static void avoid_missile( unsigned int enemy, float v, float dxm,
- float dym, float ang, float dang, float dist,
- float *l, float *r ) ;
- static void bury_enemy( unsigned int enemy ) ;
- static void check_enemy_hit( unsigned int enemy ) ;
- static int clear_shot( unsigned int enemy ) ;
- static void do_top_10( void ) ;
- static void enemy_fire( unsigned int enemy ) ;
- static void enemy_mine( unsigned int enemy ) ;
- static void enemy_move( unsigned int enemy ) ;
- static void explode_enemy( unsigned int enemy, int kill_type ) ;
- static char *get_topscore_file( void ) ;
- static void inc_level( void ) ;
- static void list_top_10( void ) ;
- static int load_top_10_stuff( FILE *f, char names[][NAMELEN],
- unsigned int topscore[], int max_scores ) ;
- static GL_Object next_logo( int *logo_side ) ;
- static char *next_name( int i, char *names[] ) ;
- static char *next_regular_name( void ) ;
- static char *next_runner_name( void ) ;
- static char *next_super_name( void ) ;
- static void place_enemy( int i ) ;
- static void prowl( unsigned int enemy, float dang, unsigned seen,
- float dist, float *l, float *r ) ;
- static void robot_logo_init( void ) ;
- /* END PROTOTYPES -S bzsolo.c */
-
-
-
- /*------------------------------------------------------------------------------
- * Do all stuff for solo mode.
- *----------------------------------------------------------------------------*/
- void do_enemy_stuff( void )
- {
- int i ;
- int side ;
- unsigned int hit_tank ;
- unsigned int obst ;
- long status ;
-
- for( i = ENEMY ; i < number_players ; i++ ) {
-
- if( IS_ALIVE( player[i] ) ) {
-
- enemy_move( i ) ;
-
- player[i].x += vx[i] * d_time ;
- player[i].y += vy[i] * d_time ;
-
- switch( check_tank_collision( i, &obst ) ) {
- case 1 :
- move_after_hit( i, player[obst].x, player[obst].y,
- vx[i], vy[i] ) ;
- break ;
-
- case 2 :
- move_after_hit( i, obst_x[obst], obst_y[obst],
- vx[i], vy[i] ) ;
- break ;
-
- default :
- case 0 :
- break ;
- }
-
- robot[i].dist = hypotn( player[SELF].x - player[i].x,
- player[SELF].y - player[i].y ) ;
-
- if( robot[i].enemy_loading ) {
- status = RM_DURATN - elapsed_sec_tenths( &(robot[i].msl_launch),
- ¤t_time ) ;
- if( status <= 0 ) {
- robot[i].enemy_loading = 0 ;
- }
- else {
- robot[i].enemy_loading = status ;
- }
- }
-
- /*
- * Mine support.
- */
- if( IS_ALIVE( player[SELF] ) ) {
- enemy_mine( i ) ;
- }
- }
- else {
- status = MAX_DEAD_STATUS -
- elapsed_sec_tenths( &(robot[i].death_time), ¤t_time ) ;
- if( status < MIN_DEAD_STATUS + 20 ) {
- player[i].status = -1 ;
- }
- else {
- player[i].status = status ;
- }
- }
-
- if( player[i].msl_status > 0 ) {
- status = RM_DURATN -
- elapsed_sec_tenths( &(robot[i].msl_launch), ¤t_time ) ;
- if( status > 0 ) {
- player[i].msl_status = status ;
- last_msl_x[i] = player[i].msl_x ;
- last_msl_y[i] = player[i].msl_y ;
- player[i].msl_x += msl_vx[i] * d_time ;
- player[i].msl_y += msl_vy[i] * d_time ;
- switch( check_missile_hit( i, &hit_tank, &side ) ) {
-
- case 1 :
- status = -1 ;
- player[i].msl_x = player[hit_tank].x ;
- player[i].msl_y = player[hit_tank].y ;
- msl_vx[i] = msl_vy[i] = 0.f ;
- player[i].hit_type = HIT_BY_MISSILE ;
- if( hit_tank == SELF ) {
- blow_up_self( i ) ;
- }
- else {
- explode_enemy( hit_tank, FRIENDLY_FIRE ) ;
- post_new_message( 0, 0, "%s killed %s.",
- player[i].name, ( i == hit_tank ) ?
- "self" : player[hit_tank].name ) ;
- }
- break ;
-
- case 2 :
- player[i].msl_x -= msl_vx[i] * d_time ;
- player[i].msl_y -= msl_vy[i] * d_time ;
- switch( side ) {
- case MIN_X_SIDE :
- case MAX_X_SIDE :
- msl_vx[i] = -msl_vx[i] ;
- break ;
- case MIN_Y_SIDE :
- case MAX_Y_SIDE :
- msl_vy[i] = -msl_vy[i] ;
- break ;
- }
- player[i].msl_head = getangle( msl_vy[i], msl_vx[i] ) ;
- break ;
-
- default :
- if( player[i].msl_x < -FIELD_SIZE ) {
- player[i].msl_x = -FIELD_SIZE ;
- status = -1 ;
- }
- if( player[i].msl_x > FIELD_SIZE ) {
- player[i].msl_x = FIELD_SIZE ;
- status = -1 ;
- }
- if( player[i].msl_y < -FIELD_SIZE ) {
- player[i].msl_y = -FIELD_SIZE ;
- status = -1 ;
- }
- if( player[i].msl_y > FIELD_SIZE ) {
- player[i].msl_y = FIELD_SIZE ;
- status = -1 ;
- }
- break ;
-
- }
- }
- if( status <= 0 ) {
- player[i].msl_status = -MEXPL_DURATION ;
- copy_time( &(robot[i].msl_explode), ¤t_time ) ;
- explosion_sfx( player[i].msl_x - player[SELF].x,
- player[i].msl_y - player[SELF].y,
- player[SELF].head ) ;
- }
- }
- else if( player[i].msl_status < 0 ) {
- status = -MEXPL_DURATION +
- elapsed_sec_tenths( &(robot[i].msl_explode),
- ¤t_time ) ;
- if( status >= 0 ) {
- player[i].msl_status = 0 ;
- }
- else {
- player[i].msl_status = status ;
- }
- }
-
- check_enemy_hit( i ) ;
- }
-
- /*
- * Clean up after any dead players.
- */
- for( i = number_players - 1 ; i > SELF ; i-- ) {
- if( player[i].status == -1 ) {
- bury_enemy( i ) ;
- }
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Enemy mine support.
- *----------------------------------------------------------------------------*/
- static void enemy_mine(
- unsigned int enemy
- )
- {
- float dx ;
- float dy ;
- float d2 ;
-
- /*
- * If mine has been dropped, check to explode it.
- */
- if( robot[enemy].mine_status ) {
- dx = player[SELF].x - robot[enemy].mine_x ;
- dy = player[SELF].y - robot[enemy].mine_y ;
- d2 = dx * dx + dy * dy ;
- /*
- * Detonate mine if tank is within range.
- */
- if( d2 < DET_MINE_RADIUS * DET_MINE_RADIUS ) {
- player[enemy].hit_type = HIT_BY_MINE ;
- robot[enemy].mine_status = 0 ;
- blow_up_self( enemy ) ;
- }
- /*
- * Detonate mine if SELF is much farther from mine than from enemy.
- */
- else if( d2 > 2.0f * robot[enemy].dist * robot[enemy].dist ) {
- robot[enemy].mine_status = 0 ;
- }
- }
- /*
- * Check to drop a mine.
- */
- else if( !kids_mode ) {
- if( robot[enemy].dist < 175.0f ) {
- robot[enemy].mine_x = player[enemy].x ;
- robot[enemy].mine_y = player[enemy].y ;
- robot[enemy].mine_status = 1 ;
- }
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Check if the enemy was hit by SELF.
- *----------------------------------------------------------------------------*/
- static void check_enemy_hit(
- unsigned int enemy
- )
- {
- int kill_em = 0 ;
-
- if( IS_ALIVE( player[enemy] ) && player[SELF].hit_by_id == enemy ) {
- post_new_message( 0, 0, "Killed %s.", player[enemy].name ) ;
- player[SELF].hit_by_id = 0 ;
- kill_em = MISSILE_STRIKE ;
- if( player[SELF].hit_type == HIT_BY_MINE ) {
- explosion_sfx( player[enemy].x - player[SELF].x,
- player[enemy].y - player[SELF].y,
- player[SELF].head ) ;
- }
- }
-
- if( player[enemy].x < -FIELD_SIZE ) {
- player[enemy].x = -FIELD_SIZE ;
- kill_em = VAPORIZE ;
- }
- if( player[enemy].x > FIELD_SIZE ) {
- player[enemy].x = FIELD_SIZE ;
- kill_em = VAPORIZE ;
- }
- if( player[enemy].y < -FIELD_SIZE ) {
- player[enemy].y = -FIELD_SIZE ;
- kill_em = VAPORIZE ;
- }
- if( player[enemy].y > FIELD_SIZE ) {
- player[enemy].y = FIELD_SIZE ;
- kill_em = VAPORIZE ;
- }
-
- if( kill_em ) {
- explode_enemy( enemy, kill_em ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Explode the enemy.
- *----------------------------------------------------------------------------*/
- static void explode_enemy(
- unsigned int enemy,
- int kill_type
- )
- {
- float dx ;
- float dy ;
-
- /*
- * Kill due to missile strike (explosion sfx will come from missile).
- */
- if( kill_type == MISSILE_STRIKE ) {
- if( kids_mode ) {
- switch( player[enemy].tank_type ) {
- case 0 :
- player[SELF].score += 10 ;
- break ;
- case 1 :
- player[SELF].score += 15 ;
- break ;
- case 3 :
- player[SELF].score += 20 ;
- break ;
- }
- }
- else {
- switch( player[enemy].tank_type ) {
- case 0 :
- player[SELF].score += 50 ;
- break ;
- case 1 :
- player[SELF].score += 75 ;
- break ;
- case 3 :
- player[SELF].score += 100 ;
- break ;
- }
- }
- if( player[SELF].score >= new_man_score ) {
- new_man_score += new_man_score_inc ;
- lives++ ;
- need_to_show_lives = TRUE ;
- post_new_message( 0, 0, "Extra life awarded. Next life at "
- "%d points.", new_man_score ) ;
- sfx( SFX_FLAG_WON ) ;
- }
- }
- /*
- * Explode due to hitting boundary (no score).
- */
- else {
- explosion_sfx( player[enemy].msl_x - player[SELF].x,
- player[enemy].msl_y - player[SELF].y,
- player[SELF].head ) ;
- if( kill_type == VAPORIZE ) {
- post_new_message( 0, 0, "%s was vaporized.",
- player[enemy].name ) ;
- }
- }
-
- /*
- * Detonate mine if it was out there.
- */
- if( robot[enemy].mine_status ) {
- dx = player[SELF].x - robot[enemy].mine_x ;
- dy = player[SELF].y - robot[enemy].mine_y ;
- /*
- * Detonate mine if tank is within range.
- */
- if( dx * dx + dy * dy < DET_MINE_RADIUS * DET_MINE_RADIUS ) {
- player[enemy].hit_type = HIT_BY_MINE ;
- blow_up_self( enemy ) ;
- }
- robot[enemy].mine_status = 0 ;
- }
-
- need_to_show_score = TRUE ;
- vx[enemy] = vy[enemy] = 0.f ;
- player[enemy].status = MAX_DEAD_STATUS ;
- copy_time( &(robot[enemy].death_time), ¤t_time ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Initialize stuff for solo version.
- *----------------------------------------------------------------------------*/
- void solo_init( void )
- {
- int i ;
-
- robot_logo_init() ;
-
- inc_level() ;
-
- if( kids_mode ) {
- new_man_score_inc = 250 ;
- }
- else {
- new_man_score_inc = 1000 ;
- }
- new_man_score = new_man_score_inc ;
-
- post_new_message( 0, 0, " " ) ;
- if( practice_level ) {
- post_new_message( 0, 0, "Practice level %u.", practice_level ) ;
- }
- else {
- list_top_10() ;
- }
- post_new_message( 0, 0, " " ) ;
- post_new_message( 0, 0, "Extra life at %d points.", new_man_score ) ;
-
- for( i = ENEMY ; i < number_players ; i++ ) {
- place_enemy( i ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Determine the enemy tank's movement.
- *----------------------------------------------------------------------------*/
- static void enemy_move(
- unsigned int enemy
- )
- {
- float dist ;
- float dx ;
- float dy ;
- float dxm ;
- float dym ;
- float t ;
- float t_lead ;
- float ang ;
- float ga ;
- float dang ;
- float seen_angle ;
- float r ;
- float l ;
- int shoot ;
- long status ;
- unsigned seen ;
-
- dxm = player[enemy].x - player[SELF].msl_x ;
- dym = player[enemy].y - player[SELF].msl_y ;
- dx = player[SELF].x - player[enemy].x ;
- dy = player[SELF].y - player[enemy].y ;
- dist = robot[enemy].dist ;
- t = dist / rm_vel ;
- seen_angle = getangle( dy, dx ) ;
- /*
- * ang is the angle of SELF in enemy's field of vision.
- */
- ang = fmodf( 720.0f + seen_angle - player[enemy].head, 360.0f ) ;
- /*
- * seen_angle is the angle of enemy in self's field of vision.
- */
- seen_angle = fmodf( 720.0f - seen_angle + player[SELF].head, 360.0f ) ;
- /*
- * seen = 1 if in self's field of vision.
- */
- seen = ( seen_angle > 165.0f && seen_angle < 195.0f ) ;
-
- /*
- * dang is delta angle to turn to be able to fire at SELF.
- */
- if( player[enemy].tank_type > 0 ) {
- /*
- * if not normal tank, find angle for firing allowing
- * for lead.
- */
- t_lead = (float)( robot[enemy].lead_me ) * t / 3.f ;
- ga = getangle( dy+t_lead*vy[SELF], dx+t_lead*vx[SELF] ) ;
- dang = fmodf( 720.0f + ga - player[enemy].head, 360.0f ) ;
- }
- else {
- /*
- * if not super tank, find angle for firing based on
- * where SELF is now.
- */
- dang = ang ;
- }
-
- /*
- * determine if missile headed at tank
- */
- if( player[SELF].msl_status && aimed_at_enemy( enemy ) ) {
- /*
- * missile is headed at tank
- */
- avoid_missile( enemy, rm_vel, dxm, dym, ang, dang, dist,
- &l, &r ) ;
- }
- else {
- /*
- * missile not headed at tank
- */
- prowl( enemy, dang, seen, dist, &l, &r ) ;
- }
-
- turn_and_go( l, r, &(player[enemy].head), &vx[enemy],
- &vy[enemy]) ;
-
- if( !kids_mode && seen_angle > ( 180.0f - fire_ang ) &&
- seen_angle < ( 180.0f + fire_ang ) ) {
- if( ( shoot = clear_shot( enemy ) ) == 1 ) {
- robot[enemy].can_wait = max_wait ;
- copy_time( &(robot[enemy].wait_time), ¤t_time ) ;
- }
- }
- else {
- if( robot[enemy].can_wait > 0 ) {
- status = max_wait - elapsed_sec_tenths( &(robot[enemy].wait_time),
- ¤t_time ) ;
- if( status <= 0 ) {
- robot[enemy].can_wait = 0 ;
- }
- else {
- robot[enemy].can_wait = status ;
- }
- }
- if( robot[enemy].can_wait ) {
- shoot = 0 ;
- }
- else {
- shoot = clear_shot( enemy ) ;
- }
- }
- if( IS_ALIVE( player[enemy] ) && IS_ALIVE( player[SELF] )
- && shoot && robot[enemy].enemy_loading == 0 &&
- ( dang < 1.1f || dang > 358.9f ) ) {
- enemy_fire( enemy ) ;
- robot[enemy].lead_me = rand() % 4 ;
- }
- }
-
-
-
-
- /*------------------------------------------------------------------------------
- * Avoid missile.
- *----------------------------------------------------------------------------*/
- static void avoid_missile(
- unsigned int enemy,
- float v, /* Velocity of missile. */
- float dxm, /* Delta's of enemy - missile positions. */
- float dym,
- float ang, /* Angle of SELF from enemy's heading. */
- float dang, /* Delta angle to firing heading. */
- float dist, /* Distance to SELF. */
- float *l,
- float *r
- )
- {
- float t ;
- float t0 ;
- float dot ;
- float vm ;
- float d ; /* Distance to missile. */
- float max_turn ; /* Maximum turning angle before impact. */
- float ue ;
- float ve ;
- float numer ;
- float denom ;
-
- d = hypotn( dxm, dym ) ;
-
- robot[enemy].avoiding = 1 ;
- vm = vmax[player[enemy].tank_type] ;
- /*
- * Time 'til impact.
- */
- t = d / v ;
-
- dot = dxm * SINE( player[enemy].head ) +
- dym * COSINE( player[enemy].head ) ;
- /*
- * v is the velocity perpendicular to the missile path
- *
- * v^2 = vm^2 * ( 1 - |heading . dist| / dist )
- */
- v = sqrtf( 1.0f - ( fabsf( dot ) / d ) ) * vm ;
-
- ue = vm * SINE( player[enemy].head ) ;
- ve = vm * COSINE( player[enemy].head ) ;
- denom = ue * msl_vy[SELF] - ve * msl_vx[SELF] ;
- numer = msl_vx[SELF] * dym - msl_vy[SELF] * dxm ;
-
- /*
- * Only interested in sign of numer/denom.
- */
- t0 = ( ( numer < 0.0f ) ? -1.0f : 1.0f ) *
- ( ( denom < 0.0f ) ? -1.0f : 1.0f ) ;
-
- /*
- * If don't need to turn, simply go forward or backward.
- */
- if( v*t > MISLRMIN ) {
- robot[enemy].turning = 0 ;
- if( t0 < 0.f ) {
- *l = vm ;
- *r = vm ;
- }
- else {
- *l = -vm ;
- *r = -vm ;
- }
- }
-
- /*
- * have to try to turn to avoid missile
- */
- else {
- if( robot[enemy].turning < 5 ) {
- if( !robot[enemy].turning )
- robot[enemy].flip = 0 ;
- robot[enemy].turning += 1 ;
- /*
- * check to kamikaze
- */
- max_turn = t_factor * 2.f * vmax[player[enemy].tank_type] * t ;
-
- if( dist < 180.f && 0.1f * robot[enemy].enemy_loading < t &&
- ( dang < max_turn || dang > 360.0f - max_turn ) ) {
- if( dang > 1.0f && dang < 180.0f ) {
- robot[enemy].turning_l = vm ;
- robot[enemy].turning_r = -vm ;
- }
- else if( dang >= 180.0f && dang < 359.0f ) {
- robot[enemy].turning_l = -vm ;
- robot[enemy].turning_r = vm ;
- }
- else {
- robot[enemy].turning_l = robot[enemy].turning_r = -vm ;
- }
- }
- /*
- * SELF on left side.
- */
- else if( ang > 180.0f ) {
- if( t0 < 0.f ) {
- robot[enemy].turning_r = 0.f ;
- robot[enemy].turning_l = vm ;
- }
- else {
- robot[enemy].turning_r = -vm ;
- robot[enemy].turning_l = 0.f ;
- }
- }
- /*
- * SELF on right side.
- */
- else {
- if( t0 < 0.f ) {
- robot[enemy].turning_r = vm ;
- robot[enemy].turning_l = 0.f ;
- }
- else {
- robot[enemy].turning_r = 0.f ;
- robot[enemy].turning_l = vm ;
- }
- }
- }
- *l = robot[enemy].turning_l ;
- *r = robot[enemy].turning_r ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Prowl (controls movement when not in danger of being hit).
- *----------------------------------------------------------------------------*/
- static void prowl(
- unsigned int enemy,
- float dang,
- unsigned seen,
- float dist,
- float *l,
- float *r
- )
- {
- float t_a ;
- unsigned retreat ;
- unsigned fire_order ;
- float vm ;
-
- robot[enemy].turning = 0 ;
-
- if( !seen || ( robot[enemy].enemy_loading <= loading_missile ) )
- retreat = 0 ;
- else
- retreat = 1 ;
-
- vm = vmax[player[enemy].tank_type] ;
-
- switch( player[enemy].tank_type ) {
- case 0 :
- /*
- * if not tank not at target angle, turn either right or left
- */
- if( dang > 1.0f && dang < 180.0f ) {
- *l = vm ;
- *r = -vm ;
- }
- else if( dang >= 180.0f && dang < 359.0f ) {
- *l = -vm ;
- *r = vm ;
- }
- else {
- /*
- * already facing tank, either approach or retreat
- */
- if( !retreat ) {
- if( dist > 100.f )
- *l = *r = vm ;
- else
- *l = *r = 0.f ;
- }
- else {
- if( dist < ( kids_mode ) ? 300.f : 800.f )
- *l = *r = -vm ;
- else
- *l = *r = 0.f ;
- }
- }
- break ;
- case 1 :
- case 3 :
- if( robot[enemy].enemy_loading < loading_missile )
- fire_order = 2 ;
- else if( robot[enemy].enemy_loading > loading_missile )
- fire_order = 1 ;
- else
- fire_order = 0 ;
-
- if( robot[enemy].flip == 0 ) {
- robot[enemy].flip = 1 ;
- robot[enemy].target_angle =
- fmodf( 720.0f - robot[enemy].target_angle, 360.0f ) ;
- }
- t_a = ( dist > 150.f && fire_order != 2 && seen ) ?
- robot[enemy].target_angle : 0 ;
- dang = fmodf( 720.0f + dang + t_a, 360.0f ) ;
-
- if( dang < 1.0f || dang > 359.0f ) {
- /*
- * facing tank directly
- */
- robot[enemy].avoiding = robot[enemy].flip = 0 ;
- if( dist > 500.f )
- *l = *r = vm ;
- else if( dist < 130.f )
- *l = *r = -vm ;
- else if( dist < 150.f )
- *l = *r = 0.f ;
- else
- *l = *r = ( fire_order != 1 ) ? vm : 0.f ;
- }
- else if( dang < 50.0f || dang > 310.0f ) {
- /*
- * tank in viewscreen
- */
- if( dist > 150.f ) {
- if( dang > 180.0f ) {
- *r = vm ;
- *l = ( robot[enemy].avoiding ) ? -vm : 0.f ;
- }
- else {
- *r = ( robot[enemy].avoiding ) ? -vm : 0.f ;
- *l = vm ;
- }
- }
- else {
- if( dang > 180.0f )
- *l = -( *r = vm ) ;
- else
- *r = -( *l = vm ) ;
- }
- }
- else {
- /*
- * tank not in viewscreen
- */
- if( dang > 180.0f )
- *l = -( *r = vm ) ;
- else
- *r = -( *l = vm ) ;
- }
- break ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Increment the playing level.
- *----------------------------------------------------------------------------*/
- static void inc_level( void )
- {
- if( practice_level == 0 )
- level++ ;
-
- number_players = ( ( ( level - 1 ) / 3 ) + 2 ) ;
- if( number_players > MAX_ENEMY + 1 ) {
- number_players = MAX_ENEMY + 1 ;
- }
-
- need_to_show_level = TRUE ;
- need_to_show_players = TRUE ;
-
- tanks_per_level = 1 + ( 3 * ( level + 1 ) ) / 4 ;
-
- if( kids_mode ) {
- max_wait = 600 - (level - 1) * 100 ;
- if( max_wait < 50 )
- max_wait = 50 ;
- }
- else {
- max_wait = 150 - (level - 1) * 25 ;
- if( max_wait < 20 )
- max_wait = 20 ;
- }
-
- zig_zag_angle = ( level - 1 ) * 3.0f ;
- if( zig_zag_angle > 30.0f )
- zig_zag_angle = 30.0f ;
-
- if( kids_mode ) {
- fire_ang = ( level - 1 ) * 2.0f + 30.0f ;
- }
- else {
- fire_ang = ( level - 1 ) * 5.0f + 30.0f ;
- }
- if( fire_ang > 180.0f )
- fire_ang = 180.0f ;
-
- if( level < 5 ) {
- super_tank_prob = ( level - 1 ) * 20 ;
- runner_tank_prob = 0 ;
- }
- else {
- super_tank_prob = 60 + ( level - 4 ) * 10 ;
- runner_tank_prob = ( level - 5 ) * 20 ;
- }
- if( super_tank_prob > 100 ) {
- super_tank_prob = 100 ;
- }
- if( runner_tank_prob > 100 ) {
- runner_tank_prob = 100 ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Cause enemy tanks to fire.
- *----------------------------------------------------------------------------*/
- static void enemy_fire(
- unsigned int enemy
- )
- {
- robot[enemy].enemy_loading = player[enemy].msl_status = RM_DURATN ;
-
- player[enemy].msl_head = player[enemy].head ;
-
- turn_and_go( rm_vel, rm_vel, &(player[enemy].msl_head),
- &msl_vx[enemy], &msl_vy[enemy] ) ;
-
- last_msl_x[enemy] = player[enemy].msl_x =
- player[enemy].x + 0.25f * msl_vx[enemy] ;
- last_msl_y[enemy] = player[enemy].msl_y =
- player[enemy].y + 0.25f * msl_vy[enemy] ;
-
- copy_time( &(robot[enemy].msl_launch), ¤t_time ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Place enemy tanks on the field.
- *----------------------------------------------------------------------------*/
- static void place_enemy(
- int i
- )
- {
- int j ;
- int k ;
- float r ;
- float ang ;
- int rand_val ;
-
- do{
- j = 0 ;
- r = 100.f + (float)( rand() & 0x1ff ) ;
- ang = (float)( rand() % 360 ) ;
- player[i].x = player[SELF].x + r * COSINE(ang) ;
- player[i].y = player[SELF].y + r * SINE(ang) ;
- r = 0.9f * FIELD_SIZE ;
- if( player[i].x < -r ) player[i].x = -r ;
- if( player[i].y < -r ) player[i].y = -r ;
- if( player[i].x > r ) player[i].x = r ;
- if( player[i].y > r ) player[i].y = r ;
- for( k = 0 ; k < TOTALOBSTS ; k++ ) {
- if( square( player[i].x - obst_x[k], player[i].y - obst_y[k] )
- < 1600.f) {
- j = 1 ;
- }
- }
- for( k = ENEMY ; k < number_players ; k++ ) {
- if( k != i &&
- square( player[i].x - player[k].x, player[i].y - player[k].y )
- < 1600.f) {
- j = 1 ;
- }
- }
- } while( j != 0 );
- player[i].id = i ;
- player[i].head = ( float )( rand() % 3600 ) / 10.f ;
- player[i].status = ALIVE_STATUS ;
- player[i].team = ( ( level - 1 ) % N_TEAMS ) ;
- player[i].msl_status = 0 ;
- robot[i].mine_status = 0 ;
-
- rand_val = rand() % 100 ;
-
- if( rand_val < runner_tank_prob ) {
- player[i].tank_type = 3 ;
- strcpy( player[i].name, next_runner_name() ) ;
- }
- else if( rand_val < super_tank_prob ) {
- player[i].tank_type = 1 ;
- strcpy( player[i].name, next_super_name() ) ;
- }
- else {
- player[i].tank_type = 0 ;
- strcpy( player[i].name, next_regular_name() ) ;
- }
-
- robot[i].enemy_loading = RM_DURATN / 2 ;
- set_time( &(robot[i].msl_launch), ¤t_time, 0,
- robot[i].enemy_loading * 100000 ) ;
- robot[i].can_wait = max_wait ;
- copy_time( &(robot[i].wait_time), ¤t_time ) ;
- robot[i].lead_me = (rand() % 4 ) ;
- robot[i].flip = 20 ;
- robot[i].target_angle = zig_zag_angle ;
-
- if( logo_count > 0 ) {
- tank_logo[i] = next_logo( &(tank_logo_side[i]) ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Clean up when enemy tank is destroyed.
- *----------------------------------------------------------------------------*/
- static void bury_enemy(
- unsigned int enemy
- )
- {
- unsigned int i ;
-
- if( practice_level == 0 ) {
- tanks_per_level--;
- }
-
- /*
- * All tanks on this level destroyed. Go to a new level.
- */
- if( !tanks_per_level ) {
- inc_level() ;
- for( i = ENEMY ; i < number_players ; i++ ) {
- place_enemy(i) ;
- robot[i].flip = 20 ;
- }
- }
- /*
- * No more tanks to appear on this level (nearing the end).
- */
- else if( tanks_per_level < number_players-1 ) {
- if( number_players > 2 ) {
- if( enemy < number_players-1 ) {
- copy_player( enemy, &(player[number_players-1]) ) ;
- player[enemy].id = enemy ;
- vx[enemy] = vx[number_players-1] ;
- vy[enemy] = vy[number_players-1] ;
- msl_vx[enemy] = msl_vx[number_players-1] ;
- msl_vy[enemy] = msl_vy[number_players-1] ;
- tank_logo[enemy] = tank_logo[number_players-1] ;
- tank_logo_side[enemy] = tank_logo_side[number_players-1] ;
- bcopy( &(robot[number_players-1]), &(robot[enemy]),
- sizeof( robot[enemy] ) ) ;
- }
- player[number_players-1].status = MIN_DEAD_STATUS ;
- player[number_players-1].msl_status = 0 ;
- }
- else {
- place_enemy(enemy) ;
- }
- number_players-- ;
- reset_viewing_order() ;
- need_to_show_players = TRUE;
- }
- /*
- * Have more tanks to appear.
- */
- else if( enemy < number_players ) {
- place_enemy(enemy) ;
- }
- else {
- player[enemy].status = -1 ;
- }
- }
-
-
-
- char *top_file = "bz.top" ;
- #define MAX_SCORES 10
-
-
-
- /*------------------------------------------------------------------------------
- * Return the name of the topscore file.
- *----------------------------------------------------------------------------*/
- static char *get_topscore_file( void )
- {
- char *t_dir ;
- char *filename ;
- unsigned i ;
- unsigned j ;
-
- if( ( t_dir = getenv( "BZ_SCORE_DIR" ) ) == NULL &&
- ( t_dir = getenv( "BZ_DIR" ) ) == NULL ) {
- t_dir = DATA_DIR ;
- }
-
- i = strlen( t_dir ) ;
- j = 0 ;
- if( i > 0 && t_dir[i-1] != '/' ) {
- j = 1 ;
- }
-
- i += strlen( top_file ) + 1 ;
-
- if( ( filename = malloc( i + j ) ) == NULL ) {
- return( NULL ) ;
- }
-
- if( j ) {
- sprintf( filename, "%s/%s", t_dir, top_file ) ;
- }
- else {
- sprintf( filename, "%s%s", t_dir, top_file ) ;
- }
-
- return( filename ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Load scores and names from top 10 file.
- *----------------------------------------------------------------------------*/
- static int load_top_10_stuff(
- FILE *f,
- char names[][NAMELEN],
- unsigned int topscore[],
- int max_scores
- )
- {
- unsigned i ;
- unsigned n ;
- char *c ;
- char line[256] ;
-
- for( i = 0 ; i < max_scores ; i++ ) {
- if( fgets( line, sizeof( line ), f ) == NULL ) {
- topscore[i] = 0 ;
- names[i][0] = '\0' ;
- return( i ) ;
- }
- else {
- if( ( c = strrchr( line, ' ' ) ) == NULL ) {
- topscore[i] = 0 ;
- names[i][0] = '\0' ;
- return( -i ) ;
- }
- else {
- topscore[i] = atoi( c ) ;
- while( *c == ' ' && c != line ) {
- *(c--) = '\0' ;
- }
- strncpy( names[i], line, NAMELEN ) ;
- }
- }
- }
- return( i ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Update the top scores.
- *----------------------------------------------------------------------------*/
- static void do_top_10( void )
- {
- FILE *f ;
- unsigned i ;
- unsigned j ;
- unsigned n ;
- char *filename ;
- char names[MAX_SCORES+1][NAMELEN] ;
- unsigned topscore[MAX_SCORES] ;
-
- if( ( filename = get_topscore_file() ) == NULL ) {
- perror( "do_top_10" ) ;
- return ;
- }
-
- strcpy( names[MAX_SCORES], player_name ) ;
-
- if( ( f = fopen( filename, "r" ) ) != NULL ) {
- if( ( i = load_top_10_stuff( f, names, topscore, MAX_SCORES ) ) < 0 ) {
- printf( "top score file, %s, trashed\n", filename ) ;
- i = -i ;
- }
- }
- else {
- i = 0 ;
- fprintf( stderr, "Can't read top scores file %s\n\n", filename ) ;
- }
-
- fclose( f ) ;
- n = i ;
- for( i = 0 ; i < n && topscore[i] >= player[SELF].score ; )
- i++ ;
-
- if( !player[SELF].score || practice_level ) {
- i = j = MAX_SCORES + 1 ;
- }
- if( i < MAX_SCORES ) {
- if( n > MAX_SCORES - 1 )
- n = MAX_SCORES - 1 ;
- for( j = n ; j > i ; j-- ) {
- topscore[j] = topscore[j-1];
- strcpy( names[j], names[j-1] ) ;
- }
- n = ( n < MAX_SCORES ) ? n+1 : MAX_SCORES ;
- strcpy( names[i], names[MAX_SCORES] ) ;
- topscore[i] = player[SELF].score ;
- j = i ;
- if( ( f = fopen( filename, "w" ) ) != NULL ) {
- for( i = 0 ; i < n ; i++) {
- fprintf( f, "%s %u\n", names[i], topscore[i] ) ;
- }
- fclose(f);
- }
- else {
- fprintf( stderr, "Unable to open %s\n", filename ) ;
- }
- }
- else {
- j = MAX_SCORES + 1 ;
- }
-
- printf( "\n\t TOP SCORES\n" ) ;
- for( i = 0 ; i < n ; i++ ) {
- printf( " %2d %-12s %6u %c\n", (i+1), names[i], topscore[i],
- ( ( i == j ) ? '<' : ' ' ) ) ;
- }
- if( j >= n ) {
- if( practice_level ) {
- printf( "\n Your score: %6u (at practice level %u)\n",
- player[SELF].score, practice_level ) ;
- }
- else {
- printf( "\n Your score: %6u\n", player[SELF].score ) ;
- }
- }
- printf( "\n\n" ) ;
-
- free( filename ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * List the top scores to the message window.
- *----------------------------------------------------------------------------*/
- static void list_top_10( void )
- {
- FILE *f ;
- unsigned i ;
- unsigned n ;
- char names[MAX_SCORES+1][NAMELEN] ;
- char *filename ;
- unsigned topscore[MAX_SCORES] ;
-
- if( ( filename = get_topscore_file() ) == NULL ) {
- perror( "list_top_10" ) ;
- return ;
- }
-
- if( ( f = fopen( filename, "r" ) ) != NULL ) {
- if( ( n = load_top_10_stuff( f, names, topscore, MAX_SCORES ) ) < 0 ) {
- n = -n ;
- }
- for( i = 0 ; i < n ; i++ ) {
- if( i == 0 ) {
- post_new_message( 0, 0, " TOP SCORES" ) ;
- }
- post_new_message( 0, 0, "%2d %-12s %6u", i+1, names[i],
- topscore[i] ) ;
- }
- fclose( f ) ;
- }
-
- free( filename ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Determine if missile is on line with enemy tank.
- *----------------------------------------------------------------------------*/
- static int aimed_at_enemy(
- unsigned int enemy
- )
- {
- float self[2][2] ;
- float obstacle[4][2] ;
-
- locate_tank_corner_points( enemy, obstacle ) ;
- self[0][0] = player[SELF].msl_x ;
- self[0][1] = player[SELF].msl_y ;
- self[1][0] = player[SELF].msl_x + RM_DURATN * msl_vx[SELF] ;
- self[1][1] = player[SELF].msl_y + RM_DURATN * msl_vy[SELF] ;
-
- return( check_line_to_rect( self, obstacle, 0 ) ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Decrement life count.
- *----------------------------------------------------------------------------*/
- void adjust_lives( void )
- {
- if( practice_level == 0 && --lives < 1 ) {
- do_top_10() ;
- end_program( 0 ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Check to see if an enemy tank has a clear shot at self.
- *----------------------------------------------------------------------------*/
- static int clear_shot(
- unsigned int enemy
- )
- {
- int obst ;
- float path[2][2] ;
- float obstacle[4][2] ;
-
- path[0][0] = player[enemy].x ;
- path[0][1] = player[enemy].y ;
- path[1][0] = player[SELF].x ;
- path[1][1] = player[SELF].y ;
-
- for( obst = CONES ; obst < CUBES ; obst++ ) {
- locate_obstacle_corner_points( obst, obstacle, CONE_COLLISION_INSET ) ;
- if( check_line_to_rect( path, obstacle, 0 ) )
- return( 0 ) ;
- }
-
- for( obst = CUBES ; obst < TOTALOBSTS ; obst++ ) {
- locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
- if( check_line_to_rect( path, obstacle, 0 ) )
- return( 0 ) ;
- }
-
- for( obst = ENEMY ; obst < number_players ; obst++ ) {
- if( obst != enemy ) {
- locate_tank_corner_points( obst, obstacle ) ;
- if( check_line_to_rect( path, obstacle, 0 ) )
- return( 0 ) ;
- }
- }
-
- return( 1 ) ;
- }
-
-
-
- static char *regular_names[] = {
- "Joe", "Fred", "Mary", "Elmer",
- "John", "Chuck", "Gary", "Wally",
- "Eddie", "Tim", "Baxter", "Bob",
- "Betty", "Poindexter", "Sue", "Winona"
- } ;
-
- static char *super_names[] = {
- "Nitro", "Butch", "Spike", "Animal",
- "Booger", "Slash", "Deadeye", "Bullet",
- } ;
-
- static char *runner_names[] = {
- "Blaze", "Speedy", "Lightning", "Smoke",
- "Streaker", "Flash", "Quicksilver", "Blur",
- } ;
-
-
- /*------------------------------------------------------------------------------
- * Unique random name retrieval kernel.
- *----------------------------------------------------------------------------*/
- static char *next_name(
- int i,
- char *names[]
- )
- {
- int n ;
- char *tmp ;
-
- n = rand() % i ;
-
- tmp = names[i-1] ;
- names[i-1] = names[n] ;
- names[n] = tmp ;
-
- return( names[i-1] ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Return the name of the next regular tank.
- *----------------------------------------------------------------------------*/
- static char *next_regular_name( void )
- {
- static int i = -1 ;
-
- if( i < 1 ) {
- i = sizeof( regular_names ) / sizeof( regular_names[0] ) ;
- }
-
- return( next_name( i--, regular_names ) ) ;
- }
-
-
- /*------------------------------------------------------------------------------
- * Return the name of the next super tank.
- *----------------------------------------------------------------------------*/
- static char *next_super_name( void )
- {
- static int i = -1 ;
-
- if( i < 1 ) {
- i = sizeof( super_names ) / sizeof( super_names[0] ) ;
- }
-
- return( next_name( i--, super_names ) ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Return the name of the next runner tank.
- *----------------------------------------------------------------------------*/
- static char *next_runner_name( void )
- {
- static int i = -1 ;
-
- if( i < 1 ) {
- i = sizeof( runner_names ) / sizeof( runner_names[0] ) ;
- }
-
- return( next_name( i--, runner_names ) ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Start pause.
- *----------------------------------------------------------------------------*/
- void start_pause( void )
- {
- start_time( &pause_begin ) ;
- reminders = 1 ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * End pause (update all times).
- *----------------------------------------------------------------------------*/
- void end_pause( void )
- {
- int i ;
- long secs ;
- long usecs ;
-
- (void) end_time( &pause_begin, &pause_end ) ;
-
- secs = pause_end.tv_sec - pause_begin.tv_sec ;
- usecs = pause_end.tv_usec - pause_begin.tv_usec ;
-
- for( i = ENEMY ; i < number_players ; i++ ) {
- add_to_time( &(robot[i].msl_launch), secs, usecs ) ;
- add_to_time( &(robot[i].msl_explode), secs, usecs ) ;
- add_to_time( &(robot[i].death_time), secs, usecs ) ;
- add_to_time( &(robot[i].wait_time), secs, usecs ) ;
- }
-
- add_to_time( &missile_launch_time, secs, usecs ) ;
- add_to_time( &missile_explode_time, secs, usecs ) ;
- add_to_time( &time_of_death, secs, usecs ) ;
- add_to_time( &hit_time, secs, usecs ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Check pause (see if a specified amount of time has passed).
- *----------------------------------------------------------------------------*/
- int check_pause( void )
- {
- float et ;
-
- et = end_time( &pause_begin, NULL ) ;
-
- if( et > reminders * REMINDER_DELAY ) {
- reminders++ ;
- return( 1 ) ;
- }
-
- return( 0 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Initialize robot logos.
- *----------------------------------------------------------------------------*/
- static void robot_logo_init( void )
- {
- int i ;
- FILE *f ;
- char *c ;
- char logo_file[MAXPATHLEN] ;
- unsigned char logo_buf[LOGO_SIZE] ;
- char *cmd ;
-
- if( ( c = getenv( "BZ_LOGO_DIR" ) ) == NULL &&
- ( c = getenv( "BZ_DIR" ) ) == NULL ) {
- c = DATA_DIR ;
- }
-
- i = strlen( c ) + 23 ;
- if( ( cmd = malloc( i ) ) == NULL ) {
- perror( "robot_logo_init" ) ;
- free( cmd ) ;
- return ;
- }
-
- sprintf( cmd, "/bin/ls %s/*.bzl | wc -l", c ) ;
-
- if( ( f = popen( cmd, "r" ) ) == NULL ) {
- logo_count = 0 ;
- free( cmd ) ;
- return ;
- }
- fscanf( f, "%d", &logo_count ) ;
- pclose( f ) ;
- if( logo_count <= 0 ) {
- free( cmd ) ;
- return ;
- }
-
- if( ( c = strrchr( cmd, '|' ) ) != NULL ) {
- *c = '\0' ;
- }
-
- if( ( f = popen( cmd, "r" ) ) == NULL ) {
- logo_count = 0 ;
- free( cmd ) ;
- return ;
- }
-
- free( cmd ) ;
-
- robot_logo = (GL_Object *)malloc( logo_count * sizeof(GL_Object) ) ;
- robot_logo_side = (int *)malloc( logo_count * sizeof(int) ) ;
- if( robot_logo == NULL || robot_logo_side == NULL ) {
- fprintf( stderr, "trying to allocate space for %ld logos...\n",
- logo_count ) ;
- perror( "robot_logo_init" ) ;
- pclose( f ) ;
- if( robot_logo != NULL )
- free( robot_logo ) ;
- if( robot_logo_side != NULL )
- free( robot_logo_side ) ;
- return ;
- }
-
- for( i = 0 ; i < logo_count ; i++ ) {
- if( fgets( logo_file, MAXPATHLEN, f ) == NULL ) {
- break ;
- }
- /*
- * Remove trailing line feed if present.
- */
- if( ( c = strrchr( logo_file, '\n' ) ) != NULL ) {
- *c = '\0' ;
- }
-
- if( ( robot_logo[i] = read_logo( logo_file, logo_buf, LOGO_SIZE, 1,
- &(robot_logo_side[i]) ) ) == 0 ) {
- break ;
- }
- }
-
- logo_count = i ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Unique random logo retrieval routine.
- *----------------------------------------------------------------------------*/
- static GL_Object next_logo(
- int *logo_side
- )
- {
- int n ;
- GL_Object logo_tmp ;
- int logo_side_tmp ;
- static int i = -1 ;
-
- if( i < 1 ) {
- i = logo_count ;
- }
-
- n = rand() % i ;
-
- logo_tmp = robot_logo[i-1] ;
- robot_logo[i-1] = robot_logo[n] ;
- robot_logo[n] = logo_tmp ;
-
- logo_side_tmp = robot_logo_side[i-1] ;
- robot_logo_side[i-1] = robot_logo_side[n] ;
- robot_logo_side[n] = logo_side_tmp ;
-
- *logo_side = robot_logo_side[i-1] ;
-
- return( robot_logo[--i] ) ;
- }
-