tRevamped fighting code; the protagonist is penalised (cops may intervene and attack, probability of successful flight is halved) - vaccinewars - be a doctor and try to vaccinate the world
 (HTM) git clone git://src.adamsgaard.dk/vaccinewars
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 43ce87336da1f84fc60b983b800e7590003cd8f0
 (DIR) parent 93331be9af913e2a14cdf0c878fef43c2cd549af
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Thu,  5 Apr 2001 01:13:05 +0000
       
       Revamped fighting code; the protagonist is penalised (cops may intervene
       and attack, probability of successful flight is halved)
       
       
       Diffstat:
         M TODO                                |       2 +-
         M src/dopewars.c                      |      11 ++---------
         M src/dopewars.h                      |      12 +++++++-----
         M src/message.c                       |       6 +++---
         M src/serverside.c                    |     159 +++++++++++++++++++++----------
         M src/serverside.h                    |       2 --
       
       6 files changed, 120 insertions(+), 72 deletions(-)
       ---
 (DIR) diff --git a/TODO b/TODO
       t@@ -1,4 +1,4 @@
       -- Tidy up display of high scores in GUI client
       +DONE - Tidy up display of high scores in GUI client
        - Revamp player-player fighting; use same system for fighting the cops and
          for fighting other players (perhaps the cops can intervene in fights);
          add SWAT teams, soldiers, etc. as dealers get more and more guns
 (DIR) diff --git a/src/dopewars.c b/src/dopewars.c
       t@@ -545,7 +545,7 @@ GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First) {
           NewPlayer->Bank=0;
           NewPlayer->Bitches.Carried=8;
           NewPlayer->CopIndex=0;
       -   NewPlayer->Health=MaxHealth(NewPlayer,NewPlayer->Bitches.Carried);
       +   NewPlayer->Health=100;
           NewPlayer->CoatSize=100;
           NewPlayer->Flags=0;
           NewPlayer->ReadBuf.Data=NewPlayer->WriteBuf.Data=NULL;
       t@@ -554,6 +554,7 @@ GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First) {
           InitAbilities(NewPlayer);
           if (Server) NewPlayer->fd=fd;
           NewPlayer->FightArray=NULL;
       +   NewPlayer->Attacking=NULL;
           return g_slist_append(First,(gpointer)NewPlayer);
        }
        
       t@@ -602,14 +603,6 @@ void CopyPlayer(Player *Dest,Player *Src) {
           Dest->Flags=Src->Flags;
        }
        
       -int MaxHealth(Player *Play,int NumBitches) {
       -   if (IsCop(Play))
       -      return (Cop[Play->CopIndex-1].Health+
       -              NumBitches*Cop[Play->CopIndex-1].DeputyHealth);
       -   else
       -      return (80+NumBitches*20);
       -}
       -
        gboolean IsCop(Player *Play) {
           return (Play->CopIndex>0);
        }
 (DIR) diff --git a/src/dopewars.h b/src/dopewars.h
       t@@ -70,6 +70,8 @@ typedef long price_t;
        typedef long long price_t;
        #endif
        
       +/* "Abilities" are protocol extensions, which are negotiated between the
       +   client and server at connect-time. */
        #define A_PLAYERID      0    /* Use numeric IDs rather than player names
                                        in network messages */
        #define A_DRUGVALUE     1    /* Server keeps track of purchase price of drugs */
       t@@ -77,9 +79,9 @@ typedef long long price_t;
        #define A_TSTRING       3    /* We understand the %Txx (tstring) notation */
        #define A_NUM           4
        typedef struct ABILITIES {
       -   gboolean Local[A_NUM];
       -   gboolean Remote[A_NUM];
       -   gboolean Shared[A_NUM];
       +   gboolean Local[A_NUM];   /* Abilities that we have */
       +   gboolean Remote[A_NUM];  /* Those that the other end of the connection has */
       +   gboolean Shared[A_NUM];  /* Abilites shared by us and the remote host */
        } Abilities;
        
        struct NAMES {
       t@@ -292,7 +294,8 @@ struct PLAYER_T {
           Player *OnBehalfOf;
           ConnBuf ReadBuf,WriteBuf;
           Abilities Abil;
       -   GPtrArray *FightArray;
       +   GPtrArray *FightArray; /* If non-NULL, a list of players in a fight */
       +   Player *Attacking;     /* The player that this player is attacking */
           gint CopIndex;  /* if >0,  then this player is a cop, described
                                      by Cop[CopIndex-1]
                              if ==0, this is a normal player that has killed no cops
       t@@ -347,7 +350,6 @@ int CountPlayers(GSList *First);
        GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First);
        void UpdatePlayer(Player *Play);
        void CopyPlayer(Player *Dest,Player *Src);
       -int MaxHealth(Player *Play,int NumBitches);
        void ClearInventory(Inventory *Guns,Inventory *Drugs);
        int IsCarryingRandom(Player *Play,int amount);
        void ChangeSpaceForInventory(Inventory *Guns,Inventory *Drugs,
 (DIR) diff --git a/src/message.c b/src/message.c
       t@@ -1170,13 +1170,13 @@ void FormatFightMessage(Player *To,GString *text,Player *Attacker,
                           ArmPercent<80 ? _("heavily armed")         :
                                           _("armed to the teeth");
                 if (DefendName[0]) {
       -            if (IsCop(Defender)) {
       +            if (IsCop(Defender) && !AttackName[0]) {
                       if (Bitches==0) {
       -                  dpg_string_sprintfa(text,_("%s, %s, is chasing you, man!"),
       +                  dpg_string_sprintfa(text,_("%s - %s - is chasing you, man!"),
                                              DefendName,Armament);
                       } else {
                          dpg_string_sprintfa(text,
       -                              _("%s and %d %tde, %s, are chasing you, man!"),
       +                              _("%s and %d %tde - %s - are chasing you, man!"),
                                              DefendName,Bitches,BitchesName,Armament);
                       }
                    } else {
 (DIR) diff --git a/src/serverside.c b/src/serverside.c
       t@@ -1187,6 +1187,10 @@ void CopsAttackPlayer(Player *Play) {
           gint CopIndex,NumDeputy,GunIndex;
        
           CopIndex=1-Play->CopIndex;
       +   if (CopIndex<0) {
       +      g_warning(_("Cops cannot attack other cops!"));
       +      return;
       +   }
           if (CopIndex > NumCop) CopIndex=NumCop;
           Cops=g_new(Player,1);
           FirstServer=AddPlayer(0,Cops,FirstServer);
       t@@ -1200,7 +1204,7 @@ void CopsAttackPlayer(Player *Play) {
           GunIndex=Cop[CopIndex-1].GunIndex;
           if (GunIndex>=NumGun) GunIndex=NumGun-1;
           Cops->Guns[GunIndex].Carried=NumDeputy+1;
       -   Cops->Health=MaxHealth(Cops,NumDeputy);
       +   Cops->Health=100;
        
           Play->EventNum++;
           AttackPlayer(Cops,Play);
       t@@ -1217,41 +1221,37 @@ void AttackPlayer(Player *Play,Player *Attacked) {
        
           if (Play->FightArray && Attacked->FightArray) {
              if (Play->FightArray==Attacked->FightArray) {
       -         g_warning("Players are already in a fight!");
       +         g_warning(_("Players are already in a fight!"));
              } else {
       -         g_warning("Players are already in separate fights!");
       +         g_warning(_("Players are already in separate fights!"));
              }
              return;
           }
        
       -   if (Play->FightArray) {
       -      FightArray=Play->FightArray;
       -      AddPlayerToFight(Attacked,FightArray,Play,TRUE);
       -   } else if (Attacked->FightArray) {
       -      FightArray=Attacked->FightArray;
       -      AddPlayerToFight(Play,FightArray,Attacked,TRUE);
       +   if (!Play->FightArray && !Attacked->FightArray) {
       +      FightArray = g_ptr_array_new();
           } else {
       -      FightArray=g_ptr_array_new();
       -      AddPlayerToFight(Attacked,FightArray,Play,TRUE);
       -      AddPlayerToFight(Play,FightArray,Attacked,FALSE);
       +      FightArray = Play->FightArray ? Play->FightArray : Attacked->FightArray;
       +   }
       +
       +   if (!Play->FightArray) {
       +      Play->ResyncNum=Play->EventNum;
       +      g_ptr_array_add(FightArray,Play);
       +   }
       +   if (!Attacked->FightArray) {
       +      Attacked->ResyncNum=Attacked->EventNum;
       +      g_ptr_array_add(FightArray,Attacked);
           }
       +   Play->FightArray=Attacked->FightArray=FightArray;
       +   Play->EventNum=Attacked->EventNum=E_FIGHT;
       +
       +   Play->Attacking = Attacked;
       +
       +   SendFightMessage(Attacked,Play,0,F_ARRIVED,FALSE,TRUE,NULL);
           
           Fire(Play);
        }
        
       -void AddPlayerToFight(Player *NewPlay,GPtrArray *Fight,Player *Other,
       -                      gboolean Inform) {
       -/* Adds the player "NewPlay" to the fight "Fight", and informs any      */
       -/* players already in the fight of the new player's arrival, if         */
       -/* "Inform" is TRUE. "Other" is a player already in the fight.          */
       -   NewPlay->FightArray=Fight;
       -   NewPlay->ResyncNum=NewPlay->EventNum;
       -   NewPlay->EventNum=E_FIGHT;
       -
       -   g_ptr_array_add(Fight,NewPlay);
       -   if (Inform) SendFightMessage(NewPlay,Other,0,F_ARRIVED,FALSE,TRUE,NULL);
       -}
       -
        gboolean IsOpponent(Player *Play,Player *Other) {
        /* Returns TRUE if player "Other" is not allied with player "Play"  */
           return TRUE;
       t@@ -1273,10 +1273,9 @@ void HandleDamage(Player *Defend,Player *Attack,int Damage,
              AddInventory(Drugs,Defend->Drugs,NumDrug);
              Defend->Health=0;
           } else if (Defend->Bitches.Carried>0 &&
       -              Defend->Health-Damage <=
       -              MaxHealth(Defend,Defend->Bitches.Carried-1)) {
       +              Defend->Health<=Damage) {
              LoseBitch(Defend,Guns,Drugs);
       -      Defend->Health=MaxHealth(Defend,Defend->Bitches.Carried);
       +      Defend->Health=100;
              *BitchesKilled=1;
           } else {
              Defend->Health-=Damage;
       t@@ -1352,7 +1351,11 @@ void RunFromCombat(Player *Play) {
        
           if (!Play || !Play->FightArray) return;
        
       -   EscapeProb=50;
       +   EscapeProb=60;
       +
       +/* Penalise players that are attacking others */
       +   if (Play->Attacking) EscapeProb/=2;
       +
           RandNum=brandom(0,100);
        
           if (RandNum<EscapeProb) {
       t@@ -1366,7 +1369,7 @@ void RunFromCombat(Player *Play) {
              WithdrawFromCombat(Play);
              Play->EventNum=Play->ResyncNum; SendEvent(Play);
           } else {
       -      SendFightMessage(Play,NULL,0,F_MSG,FALSE,FALSE,"You can't get away!");
       +      SendFightMessage(Play,NULL,0,F_MSG,FALSE,FALSE,_("You can't get away!"));
              AllowNextShooter(Play);
              DoReturnFire(Play);
           }
       t@@ -1400,10 +1403,56 @@ void CheckForKilledPlayers(Player *Play) {
           g_ptr_array_free(KilledPlayers,FALSE);
        }
        
       +static void CheckCopsIntervene(Player *Play) {
       +/* If "Play" is attacking someone, and no cops are currently present, */
       +/* then have the cops intervene (with a probability dependent on the  */
       +/* current location's PolicePresence)                                 */
       +   gint ArrayInd;
       +   Player *Defend;
       +
       +   if (!Play || !Play->FightArray) return; /* Sanity check */
       +
       +   if (!Play->Attacking) return; /* Cops don't attack "innocent victims" ;) */
       +
       +   if (brandom(0,100) > Location[(int)Play->IsAt].PolicePresence) {
       +      return; /* The cops shouldn't _always_ attack (unless P.P. == 100) */
       +   }
       +
       +   for (ArrayInd=0;Play->FightArray && ArrayInd<Play->FightArray->len;
       +        ArrayInd++) {
       +      Defend=(Player *)g_ptr_array_index(Play->FightArray,ArrayInd);
       +      if (IsCop(Defend)) return;  /* We don't want _more_ cops! */
       +   }
       +
       +   /* OK - let 'em have it... */
       +   CopsAttackPlayer(Play);
       +}
       +
       +static Player *GetFireTarget(Player *Play) {
       +/* Returns a suitable player (or cop) for "Play" to fire at. If "Play" */
       +/* is attacking a designated target already, return that, otherwise    */
       +/* return the first valid opponent in the player's FightArray.         */
       +   Player *Defend;
       +   gint ArrayInd;
       +
       +   if (Play->Attacking && g_slist_find(FirstServer,(gpointer)Play->Attacking)) {
       +      return Play->Attacking;
       +   } else {
       +      Play->Attacking=NULL;
       +      for (ArrayInd=0;ArrayInd<Play->FightArray->len;ArrayInd++) {
       +         Defend=(Player *)g_ptr_array_index(Play->FightArray,ArrayInd);
       +         if (Defend && Defend!=Play && IsOpponent(Play,Defend)) {
       +            return Defend;
       +         }
       +      }
       +   }
       +   return NULL;
       +}
       +
        void Fire(Player *Play) {
       -/* Fires all weapons of player "Play" at all opponents, and resets  */
       -/* the fight timeout (the reload time)                              */
       -   int Damage,ArrayInd,i,j;
       +/* Fires all weapons of player "Play" at an opponent, and resets  */
       +/* the fight timeout (the reload time)                            */
       +   int Damage,i,j;
           int AttackRating,DefendRating;
           int BitchesKilled;
           gboolean Loot;
       t@@ -1416,29 +1465,28 @@ void Fire(Player *Play) {
           AllowNextShooter(Play);
           if (FightTimeout) SetFightTimeout(Play);
        
       -   for (ArrayInd=0;ArrayInd<Play->FightArray->len;ArrayInd++) {
       -      Defend=(Player *)g_ptr_array_index(Play->FightArray,ArrayInd);
       -
       -      if (Defend && Defend!=Play && IsOpponent(Play,Defend)) {
       -         Damage=0; BitchesKilled=0; Loot=FALSE;
       -         if (TotalGunsCarried(Play)>0) {
       -            GetFightRatings(Play,Defend,&AttackRating,&DefendRating);
       -            if (brandom(0,AttackRating)>brandom(0,DefendRating)) {
       -               FightPoint=F_HIT;
       -               for (i=0;i<NumGun;i++) for (j=0;j<Play->Guns[i].Carried;j++) {
       -                  Damage+=brandom(0,Gun[i].Damage);
       -               }
       -               if (Damage==0) Damage=1;
       -               HandleDamage(Defend,Play,Damage,&BitchesKilled,&Loot);
       -            } else FightPoint=F_MISS;
       -         } else FightPoint=F_STAND;
       -         SendFightMessage(Play,Defend,BitchesKilled,FightPoint,Loot,TRUE,NULL);
       -      }
       +   Defend = GetFireTarget(Play);
       +   if (Defend) {
       +      Damage=0; BitchesKilled=0; Loot=FALSE;
       +      if (TotalGunsCarried(Play)>0) {
       +         GetFightRatings(Play,Defend,&AttackRating,&DefendRating);
       +         if (brandom(0,AttackRating)>brandom(0,DefendRating)) {
       +            FightPoint=F_HIT;
       +            for (i=0;i<NumGun;i++) for (j=0;j<Play->Guns[i].Carried;j++) {
       +               Damage+=brandom(0,Gun[i].Damage);
       +            }
       +            if (Damage==0) Damage=1;
       +            HandleDamage(Defend,Play,Damage,&BitchesKilled,&Loot);
       +         } else FightPoint=F_MISS;
       +      } else FightPoint=F_STAND;
       +      SendFightMessage(Play,Defend,BitchesKilled,FightPoint,Loot,TRUE,NULL);
           }
           CheckForKilledPlayers(Play);
        
        /* Careful, as we might have killed Player "Play" */
           if (g_slist_find(FirstServer,(gpointer)Play)) DoReturnFire(Play);
       +
       +   if (g_slist_find(FirstServer,(gpointer)Play)) CheckCopsIntervene(Play);
        }
        
        gboolean CanPlayerFire(Player *Play) {
       t@@ -1501,6 +1549,7 @@ void WithdrawFromCombat(Player *Play) {
           int i,j;
           gboolean FightDone;
           Player *Attack,*Defend;
       +   GSList *list;
        
           if (!Play->FightArray) return;
        
       t@@ -1516,6 +1565,11 @@ void WithdrawFromCombat(Player *Play) {
              if (!FightDone) break;
           }
        
       +   for (list=FirstServer;list;list=g_slist_next(list)) {
       +      Attack=(Player *)list->data;
       +      if (Attack->Attacking==Play) Attack->Attacking=NULL;
       +   }
       +
           SendFightLeave(Play,FightDone);
           g_ptr_array_remove(Play->FightArray,(gpointer)Play);
        
       t@@ -1535,6 +1589,7 @@ void WithdrawFromCombat(Player *Play) {
              g_ptr_array_free(Play->FightArray,TRUE);
           }
           Play->FightArray=NULL;
       +   Play->Attacking=NULL;
        }
        
        int RandomOffer(Player *To) {
       t@@ -1818,7 +1873,7 @@ void HandleAnswer(Player *From,Player *To,char *answer) {
              case E_DOCTOR:
                 if (From->Cash >= From->DocPrice) {
                    From->Cash -= From->DocPrice;
       -            From->Health=MaxHealth(From,From->Bitches.Carried);
       +            From->Health=100;
                    SendPlayerData(From);
                 }
        /*       FinishFightWithHardass(From,NULL);*/
 (DIR) diff --git a/src/serverside.h b/src/serverside.h
       t@@ -69,8 +69,6 @@ gboolean CheckHighScoreFile();
        int HighScoreRead(struct HISCORE *MultiScore,struct HISCORE *AntiqueScore);
        void CopsAttackPlayer(Player *Play);
        void AttackPlayer(Player *Play,Player *Attacked);
       -void AddPlayerToFight(Player *NewPlay,GPtrArray *Fight,Player *Other,
       -                      gboolean Inform);
        gboolean IsOpponent(Player *Play,Player *Other);
        void Fire(Player *Play);
        void WithdrawFromCombat(Player *Play);