/* 
 * death.c
 */
#include "copyright.h"

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/time.h>
#include "defs.h"
#include "struct.h"
#include "data.h"

extern jmp_buf env;

death()
{
    SIGNAL(SIGALRM, SIG_IGN);

    me->p_status = POUTFIT;             /* Stop the ghost buster */

#ifdef SB_TRANSWARP
    me->p_flags &= ~PFTWARP;
#endif


    switch(me->p_whydead) {
    case KTORP:
    case KTORP2:
    case KPLASMA:
    case KPHASER:
    case KPLANET:
    case KSHIP:
    case KSHIP2:
    case KGENOCIDE:
    case KGHOST:
    case KPROVIDENCE:
    case KPLASMA2:
    case TOURNEND:
    case TOURNSTART:
	break;
    case KQUIT:
    case KDAEMON:
    case KWINNER:
    case KOVER:
	case KBADBIN:
	mustexit = 1;
	break;
    default:
	ERROR(1,("BUG in server: ?? reason for death: %d\n",me->p_whydead));
	printf("BUG in server: ?? reason for death: %d\n",me->p_whydead);
	mustexit = 1;
	break;
    }

    me->p_flags &= ~(PFWAR|PFREFITTING);


    /* First we check for promotions: */
    if (me->p_stats.st_rank < NUMRANKS-1) {
        float ratingTotals;

        ratingTotals=planetRating(me) + bombingRating(me) + offenseRating(me);
        /* The person is promoted if they have enough hours and their ratings
         * are high enough, or if it is clear that they could sit around and
         * do nothing for the amount of time required, and still make the rank.
         * (i.e. their 'DI' rating is about rank.hours * rank.ratings ad they
         *  have insufficient time yet).
         */
        if (defenseRating(me) >= ranks[mystats->st_rank + 1].defense &&
            ((mystats->st_tticks/36000.0 >= ranks[mystats->st_rank + 1].hours/hourratio &&
             ratingTotals >= ranks[mystats->st_rank + 1].ratings) ||
            (mystats->st_tticks/36000.0 < ranks[mystats->st_rank + 1].hours/hourratio &&
             ratingTotals*(mystats->st_tticks/36000.0) >=
             ranks[mystats->st_rank+1].hours/hourratio*ranks[mystats->st_rank+1].ratings))
) {
            mystats->st_rank ++;
        } else if 
	    /* We also promote if they belong in their current rank, but have
	     * twice enough DI for the next rank.
	     */
	    ((defenseRating(me) >= ranks[mystats->st_rank].defense &&
	      ratingTotals >= ranks[mystats->st_rank].ratings) && 
	     ratingTotals*(mystats->st_tticks/36000.0) >= 
	     ranks[mystats->st_rank+1].hours/hourratio*ranks[mystats->st_rank+1].ratings*2) {
	    mystats->st_rank ++;
	} else if 
	    /* We also promote if they belong down a rank, but have four
	     * times the DI for the next rank.
	     */
	    (mystats->st_rank > 0 &&
	     (defenseRating(me) >= ranks[mystats->st_rank-1].defense &&
	      ratingTotals >= ranks[mystats->st_rank-1].ratings) &&
	     ratingTotals*(mystats->st_tticks/36000.0) >=
	     ranks[mystats->st_rank+1].hours/hourratio*ranks[mystats->st_rank+1].ratings*4) {
	    mystats->st_rank++;
        } else if ( (mystats->st_rank) >=4 ) {
            /* We also promote if they belong down a rank, but have eight
             * times the DI for the next rank, and at least the rank of 
             * Captain.
             */
	    if ((mystats->st_rank-2 > 0 &&
              (defenseRating(me) >= ranks[mystats->st_rank-2].defense &&
               ratingTotals >= ranks[mystats->st_rank-2].ratings) &&
	       ratingTotals*(mystats->st_tticks/36000.0) >=
	       ranks[mystats->st_rank+1].hours / 
	       hourratio*ranks[mystats->st_rank+1].ratings*8)) {
		mystats->st_rank++;
            }
        }
    }
    updateClient();
    /* Give them one more update now... */
    savestats();
    longjmp(env, 0);
}
