home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #7 / amigamamagazinepolishissue1998.iso / rozrywka / rpg / amigamud / src / combat / fight.m < prev    next >
Text File  |  1997-06-19  |  51KB  |  1,917 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1997 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * fight.m - add player stats, fighting, etc. to the starter dungeon.
  9.  */
  10.  
  11. private tp_fight CreateTable()$
  12. use tp_fight
  13.  
  14. /*
  15.  * NOTE: there is a direct dependency on r_arrivals, to send killed
  16.  *    players there.
  17.  */
  18.  
  19. define t_fight STEPS_PER_REGAINED_HIT_POINT    25$
  20. define t_fight BLUTOS_AFTER_DYING        25$
  21. define t_fight RANDOM_MONSTER_LIFE        100$
  22. define t_fight FOREVER_LIFE            -1$
  23. define t_fight STANDARD_STRENGTH        5$
  24. define t_fight STANDARD_ACCURACY        5$
  25. define t_fight STANDARD_DAMAGE            5$
  26. define t_fight STANDARD_SPEED            5$
  27.  
  28. /* first, the new player properties. Note: these are all the effective values,
  29.    which may include modifications from armour, weapons, spells, etc. */
  30.  
  31. define t_fight p_pInited CreateBoolProp()$    /* player has been set up */
  32. define t_fight p_pFightTerse CreateBoolProp()$
  33. define t_fight p_pFightSuperTerse CreateBoolProp()$
  34. define t_fight p_pHitMax CreateIntProp()$    /* max hit points */
  35. define t_fight p_pHitNow CreateIntProp()$    /* current hit points */
  36. define t_fight p_pHitCount CreateIntProp()$    /* part count for healing */
  37. define t_fight p_pExperience CreateIntProp()$    /* experience */
  38. define t_fight p_pLevel CreateIntProp()$    /* current level */
  39. define t_fight p_pStrength CreateIntProp()$    /* strength */
  40. define t_fight p_pSpeed CreateIntProp()$    /* speed/dexterity */
  41. define t_fight p_pProtection CreateIntProp()$    /* current armour class */
  42. define t_fight p_pWeapon CreateThingProp()$    /* current weapon */
  43. define t_fight p_pShield CreateThingProp()$    /* current shield */
  44. define t_fight p_pArmour CreateThingProp()$    /* current armour */
  45. define t_fight p_pCurrentTarget CreateThingProp()$    /* current opponent */
  46. define t_fight p_pDieNotifyList CreateActionListProp()$
  47. define t_fight p_pNewMonster CreateThingProp()$ /* temp during creation */
  48. define t_fight p_pWieldChecker CreateActionProp()$     /* allow player check */
  49. define t_fight p_pTrackerList CreateThingListProp()$    /* list of trackers */
  50.  
  51. /* monster-only properties */
  52.  
  53. define t_fight p_mActions CreateStringProp()$    /* single string of actions */
  54. define t_fight p_mActionIndexes CreateIntListProp()$    /* indices of them */
  55. define t_fight p_mMovesUntilVanish CreateIntProp()$    /* when it leaves */
  56. define t_fight p_mSound CreateStringProp()$        /* name of sample */
  57. define t_fight p_mInitAction CreateActionProp()$    /* startup action */
  58. define t_fight p_mMoveAction CreateActionProp()$    /* step action */
  59. define t_fight p_mAfterMoveAction CreateActionProp()$    /* on enter new room */
  60. define t_fight p_mFightAction CreateActionProp()$    /* fight action */
  61. define t_fight p_mSpecialAction CreateActionProp()$    /* action to do */
  62. define t_fight p_mKillAction CreateActionProp()$    /* action on kill */
  63. define t_fight p_mCreateAction CreateActionProp()$    /* something new */
  64. define t_fight p_mArriveAction CreateActionProp()$    /* something comes */
  65. define t_fight p_mArrivedAction CreateActionProp()$    /* check new loc */
  66. define t_fight p_mExpired CreateBoolProp()$        /* it has "died" */
  67. define t_fight p_mBlocker CreateBoolProp()$        /* it can block */
  68. define t_fight p_mHunting CreateBoolProp()$        /* look for target */
  69. define t_fight p_mTrackerPath CreateIntListProp()$    /* path to target */
  70.  
  71. /* properties for weapons/shield/armour */
  72.  
  73. define t_fight p_oHitBonus CreateIntProp()$    /* hitpoints bonus */
  74. define t_fight p_oStrBonus CreateIntProp()$    /* strength bonus */
  75. define t_fight p_oSpeedBonus CreateIntProp()$    /* speed bonus */
  76. define t_fight p_oArmourProt CreateIntProp()$    /* armour protection bonus */
  77. define t_fight p_oShieldProt CreateIntProp()$    /* shield protection bonus */
  78. define t_fight p_oAccuracy CreateIntProp()$    /* base accuracy level */
  79. define t_fight p_oDamage CreateIntProp()$    /* base damage level */
  80. define t_fight p_oHealing CreateIntProp()$    /* strength of heal */
  81. define t_fight p_oWieldChecker CreateActionProp()$    /* when wield a weapon */
  82.  
  83. /* properties on rooms */
  84.  
  85. define t_fight p_rNoGenerateMonsters CreateBoolProp()$/* no new baddies */
  86. define t_fight p_rMonsterList CreateThingListProp()$  /* what might turn up */
  87. define t_fight p_rMonsterChance CreateIntListProp()$    /* diff per person */
  88. define t_fight p_rMonsterTotal CreateIntProp()$ /* total of the chances */
  89. define t_fight p_rKillAction CreateActionProp()$      /* when monster killed */
  90.  
  91. /* this is an ancestor of all generic monsters */
  92.  
  93. define t_fight GenericMonster CreateThing(nil)$
  94.  
  95. /*
  96.  * fighterDesc - return additional description for a fighter.
  97.  */
  98.  
  99. define tp_fight proc fighterDesc()string:
  100.     thing it, weapon, shield, armour;
  101.     string name, s, shieldName, armourName;
  102.  
  103.     it := It();
  104.     s := "";
  105.     name := Capitalize(CharacterNameS(it));
  106.     weapon := it@p_pWeapon;
  107.     shield := it@p_pShield;
  108.     if shield ~= nil then
  109.     shieldName := FormatName(shield@p_oName);
  110.     fi;
  111.     armour := it@p_pArmour;
  112.     if armour ~= nil then
  113.     armourName := FormatName(armour@p_oName);
  114.     fi;
  115.     if weapon = nil then
  116.     if shield = nil then
  117.         if armour ~= nil then
  118.         s := name + " is wearing " + armourName;
  119.         fi;
  120.     else
  121.         s := name + AAn(" is using", shieldName);
  122.         if armour ~= nil then
  123.         s := s + " and wearing " + armourName;
  124.         fi;
  125.     fi;
  126.     else
  127.     s := name + AAn(" is wielding", FormatName(weapon@p_oName));
  128.     if shield = nil then
  129.         if armour ~= nil then
  130.         s := s + " and wearing " + armourName;
  131.         fi;
  132.     else
  133.         if armour ~= nil then
  134.         s := s + AAn(", using", shieldName);
  135.         s := s + " and wearing " + armourName;
  136.         else
  137.         s := s + AAn(" and using", shieldName);
  138.         fi;
  139.     fi;
  140.     fi;
  141.     if s ~= "" then
  142.     s := " " + s + ".";
  143.     fi;
  144.     s
  145. corp;
  146.  
  147. /*
  148.  * AddFighterDesc - add the description about weapons, etc. to the list
  149.  *    of extra descriptions on the passed character, if it is not
  150.  *    already there.
  151.  */
  152.  
  153. define t_fight proc AddFighterDesc(thing theCharacter)void:
  154.     list action la;
  155.  
  156.     la := theCharacter@p_pDescMore;
  157.     if la = nil then
  158.     la := CreateActionList();
  159.     theCharacter@p_pDescMore := la;
  160.     fi;
  161.     if FindElement(la, fighterDesc) = -1 then
  162.     AddTail(la, fighterDesc);
  163.     fi;
  164. corp;
  165.  
  166. /*
  167.  * useItem - start using the given item.
  168.  */
  169.  
  170. define tp_fight proc useItem(thing th)void:
  171.     thing me;
  172.     list action la;
  173.  
  174.     me := Me();
  175.     me@p_pHitMax := me@p_pHitMax + th@p_oHitBonus;
  176.     me@p_pStrength := me@p_pStrength + th@p_oStrBonus;
  177.     me@p_pSpeed := me@p_pSpeed + th@p_oSpeedBonus;
  178.     me@p_pProtection := me@p_pProtection + th@p_oArmourProt + th@p_oShieldProt;
  179.     AddFighterDesc(me);
  180. corp;
  181.  
  182. /*
  183.  * unUseItem - stop using the given item.
  184.  */
  185.  
  186. define tp_fight proc unUseItem(thing th, theCharacter)void:
  187.  
  188.     theCharacter@p_pHitMax := theCharacter@p_pHitMax - th@p_oHitBonus;
  189.     theCharacter@p_pStrength := theCharacter@p_pStrength - th@p_oStrBonus;
  190.     theCharacter@p_pSpeed := theCharacter@p_pSpeed - th@p_oSpeedBonus;
  191.     theCharacter@p_pProtection := theCharacter@p_pProtection -
  192.     th@p_oArmourProt - th@p_oShieldProt;
  193. corp;
  194.  
  195. /* the wear/use/wield routines for armour/shields/weapons */
  196.  
  197. define tp_fight proc armourDrop(thing th)status:
  198.     thing theCharacter;
  199.  
  200.     theCharacter := th@p_oCarryer;
  201.     if theCharacter ~= nil then
  202.     unUseItem(th, theCharacter);
  203.     theCharacter -- p_pArmour;
  204.     th -- p_oUnGetChecker;
  205.     fi;
  206.     continue
  207. corp;
  208.  
  209. define tp_fight proc shieldDrop(thing th)status:
  210.     thing theCharacter;
  211.  
  212.     theCharacter := th@p_oCarryer;
  213.     if theCharacter ~= nil then
  214.     unUseItem(th, theCharacter);
  215.     theCharacter -- p_pShield;
  216.     th -- p_oUnGetChecker;
  217.     fi;
  218.     continue
  219. corp;
  220.  
  221. define tp_fight proc weaponDrop(thing th)status:
  222.     thing theCharacter;
  223.  
  224.     theCharacter := th@p_oCarryer;
  225.     if theCharacter ~= nil then
  226.     unUseItem(th, theCharacter);
  227.     theCharacter -- p_pWeapon;
  228.     th -- p_oUnGetChecker;
  229.     fi;
  230.     continue
  231. corp;
  232.  
  233. define tp_fight proc armourWear()status:
  234.     thing th, me, oldArmour;
  235.     string aName;
  236.  
  237.     th := It();
  238.     me := Me();
  239.     if me@p_pWeapon = th then
  240.     ignore weaponDrop(th);
  241.     fi;
  242.     if me@p_pShield = th then
  243.     ignore shieldDrop(th);
  244.     fi;
  245.     oldArmour := me@p_pArmour;
  246.     if oldArmour ~= nil then
  247.     unUseItem(oldArmour, me);
  248.     oldArmour -- p_oUnGetChecker;
  249.     fi;
  250.     useItem(th);
  251.     th@p_oUnGetChecker := armourDrop;
  252.     me@p_pArmour := th;
  253.     aName := FormatName(th@p_oName);
  254.     OPrint(Capitalize(CharacterNameS(me)) + AAn(" dons", aName) + ".\n");
  255.     Print("You are now wearing the " + aName + ".\n");
  256.     succeed
  257. corp;
  258.  
  259. define tp_fight proc shieldUse()status:
  260.     thing th, me, oldShield;
  261.     string sName;
  262.  
  263.     th := It();
  264.     me := Me();
  265.     if me@p_pWeapon = th then
  266.     ignore weaponDrop(th);
  267.     fi;
  268.     if me@p_pArmour = th then
  269.     ignore armourDrop(th);
  270.     fi;
  271.     oldShield := me@p_pShield;
  272.     if oldShield ~= nil then
  273.     unUseItem(oldShield, me);
  274.     oldShield -- p_oUnGetChecker;
  275.     fi;
  276.     useItem(th);
  277.     th@p_oUnGetChecker := shieldDrop;
  278.     me@p_pShield := th;
  279.     sName := FormatName(th@p_oName);
  280.     OPrint(Capitalize(CharacterNameS(me)) + AAn(" readies", sName) + ".\n");
  281.     Print("You are now using the " + sName + ".\n");
  282.     succeed
  283. corp;
  284.  
  285. define tp_fight proc weaponWield()status:
  286.     thing th, me, oldWeapon;
  287.     string wName;
  288.  
  289.     th := It();
  290.     me := Me();
  291.     if me@p_pShield = th then
  292.     ignore shieldDrop(th);
  293.     fi;
  294.     if me@p_pArmour = th then
  295.     ignore armourDrop(th);
  296.     fi;
  297.     oldWeapon := me@p_pWeapon;
  298.     if oldWeapon ~= nil then
  299.     unUseItem(oldWeapon, me);
  300.     oldWeapon -- p_oUnGetChecker;
  301.     fi;
  302.     useItem(th);
  303.     th@p_oUnGetChecker := weaponDrop;
  304.     me@p_pWeapon := th;
  305.     wName := FormatName(th@p_oName);
  306.     OPrint(Capitalize(CharacterNameS(me)) + AAn(" wields", wName) + ".\n");
  307.     Print("You are now wielding the " + wName + ".\n");
  308.     succeed
  309. corp;
  310.  
  311. /*
  312.  * SetupWeapon - set up a model object as a weapon.
  313.  */
  314.  
  315. define t_fight proc public SetupWeapon(thing theModel; int hitBonus, strBonus,
  316.     speedBonus, armourProt, shieldProt, accuracy, damage)void:
  317.  
  318.     if hitBonus ~= 0 then
  319.     theModel@p_oHitBonus := hitBonus;
  320.     fi;
  321.     if strBonus ~= 0 then
  322.     theModel@p_oStrBonus := strBonus;
  323.     fi;
  324.     if speedBonus ~= 0 then
  325.     theModel@p_oSpeedBonus := speedBonus;
  326.     fi;
  327.     if armourProt ~= 0 then
  328.     theModel@p_oArmourProt := armourProt;
  329.     theModel@p_oWearChecker := armourWear;
  330.     fi;
  331.     if shieldProt ~= 0 then
  332.     theModel@p_oShieldProt := shieldProt;
  333.     theModel@p_oUseChecker := shieldUse;
  334.     fi;
  335.     if accuracy ~= 0 then
  336.     theModel@p_oAccuracy := accuracy;
  337.     fi;
  338.     if damage ~= 0 then
  339.     theModel@p_oDamage := damage;
  340.     theModel@p_oWieldChecker := weaponWield;
  341.     fi;
  342. corp;
  343.  
  344. /*
  345.  * WeaponSell - companion routine - set up what is for sale.
  346.  */
  347.  
  348. define t_fight proc public WeaponSell(thing room; string name, desc;
  349.     int price, hitBonus, strBonus, speedBonus,
  350.         armourProt, shieldProt, accuracy, damage
  351.     )thing:
  352.     thing theModel;
  353.  
  354.     theModel := AddForSale(room, name, desc, price, nil);
  355.     SetupWeapon(theModel, hitBonus, strBonus, speedBonus, armourProt,
  356.         shieldProt, accuracy, damage);
  357.     theModel
  358. corp;
  359.  
  360. define tp_fight proc healBuy()status:
  361.     thing th, me;
  362.     int n, hits, delta;
  363.  
  364.     th := It();
  365.     me := Me();
  366.     n := th@p_oHealing;
  367.     n := n / 2 + Random(n / 2);
  368.     hits := me@p_pHitNow;
  369.     delta := me@p_pHitMax - hits;
  370.     if delta = 0 then
  371.     Print("You didn't need healing. Oh well - easy come, easy go!\n");
  372.     else
  373.     if n > delta then
  374.         n := delta;
  375.     fi;
  376.     me@p_pHitNow := hits + n;
  377.     if n = 1 then
  378.         Print("You are healed for one point.\n");
  379.     else
  380.         Print("You are healed for " + IntToString(n) + " points.\n");
  381.     fi;
  382.     fi;
  383.     if not me@p_pHidden then
  384.     OPrint(Capitalize(CharacterNameG(me)) + " makes a purchase.\n");
  385.     fi;
  386.     /* Tell 'StoreBuy' to destroy the copy, do not add it to our inventory,
  387.        and print no messages, but charge us for it. */
  388.     succeed
  389. corp;
  390.  
  391. /*
  392.  * HealSell - set up a healing "object".
  393.  */
  394.  
  395. define t_fight proc public HealSell(thing room; string name;
  396.     int cost, healing)void:
  397.     thing theModel;
  398.  
  399.     theModel := AddForSale(room, name, "", cost, healBuy);
  400.     theModel@p_oHealing := healing;
  401. corp;
  402.  
  403. /*
  404.  * showStats - show the statistics of the given thing (monster or player)
  405.  */
  406.  
  407. define tp_fight proc showStats(thing theCharacter; bool forceLong)void:
  408.     string name;
  409.     int ac;
  410.     thing th;
  411.  
  412.     name := FormatName(theCharacter@p_pName);
  413.     Print(name);
  414.     Print(": Hit: ");
  415.     IPrint(theCharacter@p_pHitNow);
  416.     Print("/");
  417.     IPrint(theCharacter@p_pHitMax);
  418.     Print(" Exp: ");
  419.     IPrint(theCharacter@p_pExperience);
  420.     Print(" Lvl: ");
  421.     IPrint(theCharacter@p_pLevel);
  422.     Print(" Str: ");
  423.     IPrint(theCharacter@p_pStrength);
  424.     Print(" Spd: ");
  425.     IPrint(theCharacter@p_pSpeed);
  426.     Print(" AC: ");
  427.     ac := theCharacter@p_pProtection;
  428.     if ac > 0 then
  429.     Print("+");
  430.     fi;
  431.     IPrint(ac);
  432.     Print(" Bl: ");
  433.     IPrint(theCharacter@p_pMoney);
  434.     Print("\n");
  435.     if forceLong or not theCharacter@p_pFightTerse or theCharacter ~= Me() then
  436.     th := theCharacter@p_pWeapon;
  437.     if th ~= nil then
  438.         Print("Weapon: ");
  439.         Print(FormatName(th@p_oName));
  440.         Print("\n");
  441.     fi;
  442.     th := theCharacter@p_pShield;
  443.     if th ~= nil then
  444.         Print("Shield: ");
  445.         Print(FormatName(th@p_oName));
  446.         Print("\n");
  447.     fi;
  448.     th := theCharacter@p_pArmour;
  449.     if th ~= nil then
  450.         Print("Armour: ");
  451.         Print(FormatName(th@p_oName));
  452.         Print("\n");
  453.     fi;
  454.     fi;
  455. corp;
  456.  
  457. /**************************************************************************\
  458. *                                       *
  459. *    Code, etc. for monsters                        *
  460. *                                       *
  461. \**************************************************************************/
  462.  
  463. /* NOTE: each monster points at the player it is currently attacking, which
  464.    is usually the player which caused it to come into being, but can be
  465.    another, if that other attacked the monster. Players point at the monster
  466.    they most recently created or attacked, but those pointers are subject
  467.    to testing before they are used, since the monsters can leave. */
  468.  
  469. /* set up monsters which will pick up and use stuff */
  470.  
  471. define tp_fight proc MonsterUse(thing theMonster, item)void:
  472.     int n;
  473.     thing old;
  474.  
  475.     n := item@p_oArmourProt;
  476.     old := theMonster@p_pArmour;
  477.     if old = nil and n ~= 0 or old ~= nil and n < old@p_oArmourProt then
  478.     SetIt(item);
  479.     ignore call(item@p_oWearChecker, status)();
  480.     /* make him live forever */
  481.     theMonster@p_mMovesUntilVanish := FOREVER_LIFE;
  482.     else
  483.     n := item@p_oShieldProt;
  484.     old := theMonster@p_pShield;
  485.     if old = nil and n ~= 0 or old ~= nil and n < old@p_oShieldProt then
  486.         SetIt(item);
  487.         ignore call(item@p_oUseChecker, status)();
  488.         theMonster@p_mMovesUntilVanish := FOREVER_LIFE;
  489.     else
  490.         n := item@p_oDamage;
  491.         old := theMonster@p_pWeapon;
  492.         if old = nil and n ~= 0 or old ~= nil and n > old@p_oDamage then
  493.         SetIt(item);
  494.         ignore call(item@p_oWieldChecker, status)();
  495.         theMonster@p_mMovesUntilVanish := FOREVER_LIFE;
  496.         fi;
  497.     fi;
  498.     fi;
  499. corp;
  500.  
  501. define tp_fight proc MonsterPickUp()void:
  502.     list thing lt;
  503.     int count, i, carryCount;
  504.     thing here, theMonster, th;
  505.  
  506.     theMonster := Me();
  507.     here := Here();
  508.     lt := here@p_rContents;
  509.     count := Count(lt);
  510.     carryCount := Count(theMonster@p_pCarrying);
  511.     i := 0;
  512.     while i < count and carryCount < MAX_CARRY do
  513.     th := lt[i];
  514.     if not th@p_oInvisible and not th@p_oNotGettable then
  515.         if DoGet(here, theMonster, th) ~= fail then
  516.         count := count - 1;
  517.         carryCount := carryCount + 1;
  518.         MonsterUse(theMonster, th);
  519.         else
  520.         /* something wrong - quit trying to get things */
  521.         i := count;
  522.         fi;
  523.     else
  524.         i := i + 1;
  525.     fi;
  526.     od;
  527. corp;
  528.  
  529. define tp_fight proc MonsterGivePost()status:
  530.  
  531.     MonsterUse(Me(), It());
  532.     continue
  533. corp;
  534.  
  535. define tp_fight proc doPickup()status:
  536.     MonsterPickUp();
  537.     continue
  538. corp;
  539.  
  540. define tp_fight proc monsterGivePre()status:
  541.     SPrint(TrueMe(), "You can't give things to " +
  542.        CharacterNameS(Me()) + ".\n");
  543.     fail
  544. corp;
  545.  
  546. define tp_fight proc smartGivePre()status:
  547.     continue
  548. corp;
  549.  
  550. /*
  551.  * MakeMonsterSmart - call this routine on a monster model to make that
  552.  *    monster "smart" in that it will pick up and use weapons, armour
  553.  *    and shields.
  554.  */
  555.  
  556. define t_fight proc MakeMonsterSmart(thing monster)void:
  557.  
  558.     monster@p_mAfterMoveAction := MonsterPickUp;
  559.     monster@p_pGivePre := smartGivePre;     /* override any from parent */
  560.     monster@p_pGivePost := MonsterGivePost;
  561. corp;
  562.  
  563. /* the fighting code */
  564.  
  565. /*
  566.  * AddExperience - do all needed on an experience gain or loss.
  567.  */
  568.  
  569. define t_fight proc public AddExperience(thing thePlayer; int n)void:
  570.     int level, value;
  571.  
  572.     n := n + thePlayer@p_pExperience;
  573.     thePlayer@p_pExperience := n;
  574.     level := 0;
  575.     value := 10;
  576.     while value <= n do
  577.     value := value * 10;
  578.     level := level + 1;
  579.     od;
  580.     value := thePlayer@p_pLevel;
  581.     if level ~= value then
  582.     thePlayer@p_pLevel := level;
  583.     if level > value then
  584.         SPrint(thePlayer, "You have gained a level!\n");
  585.         if Random(2) = 0 then
  586.         SPrint(thePlayer, "You gain speed.\n");
  587.         thePlayer@p_pSpeed := thePlayer@p_pSpeed + 1;
  588.         else
  589.         SPrint(thePlayer, "You gain strength.\n");
  590.         thePlayer@p_pStrength := thePlayer@p_pStrength + 1;
  591.         fi;
  592.         thePlayer@p_pHitMax := thePlayer@p_pHitMax + 8 + Random(5);
  593.     else
  594.         SPrint(thePlayer, "You have lost a level!\n");
  595.         if thePlayer@p_pSpeed > thePlayer@p_pStrength or
  596.         thePlayer@p_pSpeed = thePlayer@p_pStrength and Random(2) = 0
  597.         then
  598.         SPrint(thePlayer, "You lose speed.\n");
  599.         thePlayer@p_pSpeed := thePlayer@p_pSpeed - 1;
  600.         else
  601.         SPrint(thePlayer, "You lose strength.\n");
  602.         thePlayer@p_pStrength := thePlayer@p_pStrength - 1;
  603.         fi;
  604.         n := thePlayer@p_pHitMax - 8 - Random(5);
  605.         if n < 10 then
  606.         n := 10;
  607.         fi;
  608.         thePlayer@p_pHitMax := n;
  609.     fi;
  610.     fi;
  611. corp;
  612.  
  613. /*
  614.  * FindLoot - the player finds loot from a kill.
  615.  */
  616.  
  617. define t_fight proc public FindLoot(int amount)void:
  618.     thing theCharacter;
  619.  
  620.     if amount = 0 then
  621.     amount := 1;
  622.     fi;
  623.     if amount = 1 then
  624.     Print("You found one bluto of loot.\n");
  625.     else
  626.     Print("You found ");
  627.     IPrint(amount);
  628.     Print(" blutos of loot.\n");
  629.     fi;
  630.     theCharacter := Me();
  631.     theCharacter@p_pMoney := theCharacter@p_pMoney + amount;
  632. corp;
  633.  
  634. /*
  635.  * part of KillPlayer.
  636.  */
  637.  
  638. define tp_fight proc showAndLook()status:
  639.  
  640.     ShowIcon();
  641.     ignore ShowRoomToMe(true);
  642.     continue
  643. corp;
  644.  
  645. /*
  646.  * KillPlayer - general routine for killing a player. Send him back to the
  647.  *    arrivals room with no belongings and 25 blutos.
  648.  *    NOTE: if a player tells Packrat to go into the proving grounds, she
  649.  *    will be set up to fight, just as if she were a player. Then, if
  650.  *    someone kills her, this routine will be called by her!
  651.  */
  652.  
  653. define t_fight proc public KillPlayer(thing theVictim, theKiller)void:
  654.     list action la;
  655.     list thing lt;
  656.     int count, i;
  657.     action a;
  658.     thing here, item, killerLoc;
  659.     string victimName;
  660.  
  661.     la := theVictim@p_pDieNotifyList;
  662.     count := Count(la);
  663.     i := 0;
  664.     while i ~= count do
  665.     a := la[i];
  666.     if call(a, bool)(theVictim) then
  667.         DelElement(la, a);
  668.         count := count - 1;
  669.     else
  670.         i := i + 1;
  671.     fi;
  672.     od;
  673.     here := AgentLocation(theVictim);
  674.     lt := theVictim@p_pCarrying;
  675.     count := Count(lt);
  676.     i := 0;
  677.     while i < count do
  678.     item := lt[i];
  679.     if DoDrop(here, theVictim, item) = continue then
  680.         count := count - 1;
  681.     else
  682.         i := i + 1;
  683.     fi;
  684.     od;
  685.  
  686.     /* this makes for a non-obvious cheat, but I want it disabled anyway */
  687.     victimName := CharacterNameG(theVictim);
  688.     if victimName ~= "Packrat" then
  689.     theVictim@p_pMoney := BLUTOS_AFTER_DYING;
  690.     fi;
  691.     theVictim@p_pHitNow := 10;
  692.     theVictim@p_pExperience := theVictim@p_pExperience / 2;
  693.     AddExperience(theVictim, 0);
  694.  
  695.     if theVictim@p_pHidden then
  696.     theVictim@p_pHidden := false;
  697.     ABPrint(here, theVictim, theVictim,
  698.         "Something fades into view. It is the corpse of " + victimName +
  699.         "!\n");
  700.     fi;
  701.     ABPrint(here, theVictim, theVictim,
  702.     "The corpse just fades away, but you catch a glimpse from the corner "
  703.     "of your eye of a pale cloud floating off.\n");
  704.     ignore ForceAction(theVictim, DoUnShowIcon);
  705.     SetAgentLocation(theVictim, r_arrivals);
  706.     SPrint(theVictim,
  707. "You feel an abrupt tearing of the local continuum as your essence "
  708. "departs from your ravaged body. Looking down, you see your corpse fade "
  709. "away to nothing, leaving little sign of your recent presence. A feeling "
  710. "of lightness pervades your being, and you begin to float away from the "
  711. "scene. The floating quickens and the world becomes a blur of motion. Soon "
  712. "you can again make out your surroundings.\n");
  713.     ABPrint(r_arrivals, theVictim, theVictim, "From the corner of your eye "
  714.     "you see a pale cloud float into view, which then solidifies into " +
  715.     victimName + ".\n");
  716.     ignore ForceAction(theVictim, showAndLook);
  717.  
  718.     /* did the killer kill off the only light source? */
  719.     if theKiller ~= theVictim and not LightAt(here) then
  720.     /* it may have gotten dark there */
  721.     killerLoc := AgentLocation(theKiller);
  722.     if killerLoc ~= here or not HasLight(theKiller) then
  723.         ForEachAgent(here, UnShowRoomFromAgent);
  724.         if killerLoc = here then
  725.         if theKiller = Me() then
  726.             UnShowRoomFromMe();
  727.         else
  728.             UnShowRoomFromAgent(theKiller);
  729.         fi;
  730.         fi;
  731.     fi;
  732.     fi;
  733. corp;
  734.  
  735. /*
  736.  * AttackHits - whether or not an attack will hit.
  737.  */
  738.  
  739. define t_fight proc public AttackHits(thing attacker; bool isPlayer)bool:
  740.     thing weapon;
  741.     int n;
  742.  
  743.     weapon := attacker@p_pWeapon;
  744.     if weapon ~= nil then
  745.     n := weapon@p_oAccuracy;
  746.     else
  747.     if isPlayer then
  748.         n := STANDARD_ACCURACY;
  749.     else
  750.         n := attacker@p_oAccuracy;
  751.     fi;
  752.     fi;
  753.     if isPlayer then
  754.     /* weaponless level 0 character has one chance in 4 of hitting */
  755.     /* weaponless level 1 - 4 character has one chance in 3 of hitting */
  756.     /* weaponless level 5 - 10 character has one chance in 2 of hitting */
  757.     /* weaponless level 11 and up character always hits */
  758.     n := n + attacker@p_pLevel;
  759.     fi;
  760.     n := n * 3 + attacker@p_pSpeed - STANDARD_SPEED;
  761.     if n ~= 0 then
  762.     n := Random(60 / n);
  763.     else
  764.     n := 1;
  765.     fi;
  766.     n = 0
  767. corp;
  768.  
  769. /*
  770.  * AttackPoints - the strength of an attack.
  771.  */
  772.  
  773. define t_fight proc public AttackPoints(thing attacker; bool aIsPlayer;
  774.                     thing target; bool tIsPlayer)int:
  775.     thing weapon;
  776.     int n;
  777.  
  778.     weapon := attacker@p_pWeapon;
  779.     if weapon ~= nil then
  780.     n := weapon@p_oDamage;
  781.     else
  782.     if aIsPlayer then
  783.         n := STANDARD_DAMAGE;
  784.     else
  785.         n := attacker@p_oDamage;
  786.     fi;
  787.     fi;
  788.     if aIsPlayer then
  789.     n := n + attacker@p_pStrength;
  790.     fi;
  791.     n := n * 2;
  792.     n := (n / 2 + Random(n / 2 + 3)) / 4;
  793.     /* Modify by target armour class */
  794.     n := n + target@p_pProtection - 9;
  795.     /* and for excessive target player strength */
  796.     if tIsPlayer then
  797.     n := n - (target@p_pStrength - STANDARD_STRENGTH) / 5;
  798.     fi;
  799.     n
  800. corp;
  801.  
  802. /*
  803.  * MonsterHitPlayer - have the monster hit the player.
  804.  *    Note: this can be executed by the player or by the monster!
  805.  *    Return 'true' if the player is still alive.
  806.  */
  807.  
  808. define t_fight proc public MonsterHitPlayer(
  809.     thing theMonster, thePlayer, where)bool:
  810.     string monsterName, playerName;
  811.     int n, hits;
  812.     bool alive;
  813.  
  814.     if thePlayer@p_pCurrentTarget = nil then
  815.     thePlayer@p_pCurrentTarget := theMonster;
  816.     fi; 
  817.     alive := true;
  818.     if theMonster@p_oAccuracy ~= 0 and Here()@p_rMonsterList ~= nil then
  819.     /* Special case - if accuracy = 0, the monster never attacks.
  820.        Also, don't let monsters attack in a non-combat area, since
  821.        the player can't hit back! */
  822.     monsterName := Capitalize(CharacterNameG(theMonster));
  823.     playerName := CharacterNameG(thePlayer);
  824.     if thePlayer@p_pHidden then
  825.         ABPrint(where, thePlayer, thePlayer,
  826.         monsterName + " attacks something.\n");
  827.     else
  828.         ABPrint(where, thePlayer, thePlayer,
  829.         monsterName + " attacks " + playerName + ".\n");
  830.     fi;
  831.     /* first, does the attack hit? */
  832.     if AttackHits(theMonster, false) then
  833.         /* A hit. Get basic damage done by monster */
  834.         n := AttackPoints(theMonster, false, thePlayer, true);
  835.         if n > 0 then
  836.         hits := thePlayer@p_pHitNow;
  837.         hits := hits - n;
  838.         SPrint(thePlayer, monsterName + " hits for " +
  839.             if n = 1 then
  840.             "one point"
  841.             else
  842.             IntToString(n) + " points"
  843.             fi +
  844.             ". [" + IntToString(hits) + "/" +
  845.             IntToString(thePlayer@p_pHitMax) + "]\n");
  846.         if hits <= 0 then
  847.             SPrint(thePlayer, "You are killed!\n");
  848.             if not thePlayer@p_pHidden then
  849.             ABPrint(where, thePlayer, thePlayer,
  850.                 monsterName + " kills " + playerName + "!\n");
  851.             fi;
  852.             AddExperience(theMonster, thePlayer@p_pHitNow);
  853.             theMonster@p_pMoney :=
  854.             theMonster@p_pMoney + thePlayer@p_pMoney;
  855.             KillPlayer(thePlayer, theMonster);
  856.             if theMonster@p_mAfterMoveAction = MonsterPickUp then
  857.             ignore ForceAction(theMonster, doPickup);
  858.             fi;
  859.             alive := false;
  860.         else
  861.             thePlayer@p_pHitNow := hits;
  862.             AddExperience(theMonster, n);
  863.         fi;
  864.         else
  865.         if not thePlayer@p_pFightSuperTerse then
  866.             SPrint(thePlayer,
  867.             monsterName + " hits but does no damage.\n");
  868.         fi;
  869.         fi;
  870.     else
  871.         if not thePlayer@p_pFightTerse then
  872.         SPrint(thePlayer, monsterName + " attacks but misses.\n");
  873.         fi;
  874.     fi;
  875.     fi;
  876.     alive
  877. corp;
  878.  
  879. /*
  880.  * KillMonster - normal stuff for killing a monster.
  881.  */
  882.  
  883. define t_fight proc KillMonster(thing theMonster)void:
  884.     string monsterName;
  885.     thing theKiller, other, here;
  886.     list thing lt;
  887.     int i;
  888.  
  889.     theKiller := Me();
  890.     monsterName := CharacterNameS(theMonster);
  891.     Print(Capitalize(monsterName) + " is killed!\n");
  892.     if theKiller@p_pHidden then
  893.     OPrint(Capitalize(monsterName) + " is killed!\n");
  894.     else
  895.     OPrint(Capitalize(CharacterNameS(theKiller)) + " kills " +
  896.         monsterName +"!\n");
  897.     fi;
  898.     theKiller -- p_pCurrentTarget;
  899.     other := theMonster@p_pCurrentTarget;
  900.     if other ~= nil and other ~= theKiller then
  901.     if other@p_pCurrentTarget = theMonster then
  902.         other -- p_pCurrentTarget;
  903.     fi;
  904.     fi;
  905.     lt := theMonster@p_pCarrying;
  906.     if lt ~= nil then
  907.     here := Here();
  908.     i := Count(lt);
  909.     while i ~= 0 do
  910.         i := i - 1;
  911.         ignore DoDrop(here, theMonster, lt[i]);
  912.     od;
  913.     fi;
  914.     if theMonster ~= theKiller then
  915.     i := theMonster@p_pMoney;
  916.     if i ~= 0 then
  917.         FindLoot((i + 1) / 2 + Random((i + 1) / 2));
  918.     fi;
  919.     fi;
  920.     ignore ForceAction(theMonster, DoUnShowIcon);
  921. corp;
  922.  
  923. /*
  924.  * PlayerHitMonster - the player is attacking the monster.
  925.  *    Return 'true' if the monster is still alive.
  926.  *    Note: this is only ever executed by the player.
  927.  */
  928.  
  929. define t_fight proc public PlayerHitMonster(thing thePlayer, theMonster)bool:
  930.     thing target, weapon, here, theModel;
  931.     string monsterName;
  932.     int n, hits;
  933.     list thing lt;
  934.     bool alive;
  935.     action a;
  936.  
  937.     alive := true;
  938.     if theMonster@p_mMovesUntilVanish ~= FOREVER_LIFE then
  939.     theMonster@p_mMovesUntilVanish := RANDOM_MONSTER_LIFE;
  940.     fi;
  941.     thePlayer@p_pCurrentTarget := theMonster;
  942.     target := theMonster@p_pCurrentTarget;
  943.     if target ~= thePlayer then
  944.     if target ~= nil then
  945.         /* Remove reference to monster */
  946.         target -- p_pCurrentTarget;
  947.     fi;
  948.     /* If multiple people are bashing on a monster, it randomly
  949.        targets one of them. Trackers do not switch if they have a
  950.        partial path, however. */
  951.     if target = nil or Random(2) = 0 and target@p_mTrackerPath = nil then
  952.         theMonster@p_pCurrentTarget := thePlayer;
  953.     fi;
  954.     fi;
  955.     weapon := thePlayer@p_pWeapon;
  956.     monsterName := CharacterNameG(theMonster);
  957.     if thePlayer@p_pHidden then
  958.     OPrint(Capitalize(monsterName) + " is attacked.\n");
  959.     else
  960.     OPrint(Capitalize(CharacterNameG(thePlayer)) + " attacks " +
  961.         monsterName + ".\n");
  962.     fi;
  963.  
  964.     /* first, does the attack hit? */
  965.     if AttackHits(thePlayer, true) then
  966.     /* A hit! How much damage? */
  967.     n := AttackPoints(thePlayer, true, theMonster, false);
  968.     if n > 0 then
  969.         Print("You hit for " + IntToString(n) +
  970.         if n = 1 then " point.\n" else " points.\n" fi);
  971.         hits := theMonster@p_pHitNow;
  972.         if n >= hits then
  973.         /* it is killed */
  974.         theModel := Parent(theMonster);
  975.         a := theMonster@p_mKillAction;
  976.         if a ~= nil then
  977.             alive := call(a, bool)(thePlayer, theMonster);
  978.         else
  979.             alive := false;
  980.             KillMonster(theMonster);
  981.             DestroyMachine(theMonster);
  982.             AddExperience(thePlayer, hits);
  983.         fi;
  984.         a := Here()@p_rKillAction;
  985.         if a ~= nil then
  986.             call(a, void)(thePlayer, theModel);
  987.         fi;
  988.         else
  989.         theMonster@p_pHitNow := hits - n;
  990.         AddExperience(thePlayer, n);
  991.         fi;
  992.     else
  993.         if not thePlayer@p_pFightSuperTerse then
  994.         Print("You hit " + monsterName + " but do no damage.\n");
  995.         fi;
  996.     fi;
  997.     else
  998.     if not thePlayer@p_pFightTerse then
  999.         Print("You attack " + monsterName + " but miss.\n");
  1000.     fi;
  1001.     fi;
  1002.     alive
  1003. corp;
  1004.  
  1005. /*
  1006.  * PlayerHitPlayer - the current player is attacking the given player.
  1007.  */
  1008.  
  1009. define t_fight proc public PlayerHitPlayer(thing theTarget)void:
  1010.     thing here, theAttacker, weapon;
  1011.     string attackerName, targetName, points;
  1012.     int n, hits;
  1013.  
  1014.     here := Here();
  1015.     theAttacker := Me();
  1016.     attackerName := Capitalize(CharacterNameS(theAttacker));
  1017.     targetName := theTarget@p_pName;
  1018.     if theTarget@p_pInited then
  1019.     if not theAttacker@p_pHidden and not theTarget@p_pHidden then
  1020.         ABPrint(here, theTarget, theAttacker,
  1021.         attackerName + " attacks " + targetName + ".\n");
  1022.     fi;
  1023.     weapon := theAttacker@p_pWeapon;
  1024.  
  1025.     /* first, does the attack hit? */
  1026.     if AttackHits(theAttacker, true) then
  1027.         /* A hit! How much damage? */
  1028.         n := AttackPoints(theAttacker, true, theTarget, true);
  1029.         if n > 0 then
  1030.         hits := theTarget@p_pHitNow;
  1031.         SPrint(theTarget, attackerName +
  1032.             " attacks you and hits for " +
  1033.             if n = 1 then
  1034.             "one point"
  1035.             else
  1036.             IntToString(n) + " points"
  1037.             fi + ". [" + IntToString(hits - n) + "/" +
  1038.             IntToString(hits) + "]\n");
  1039.         Print("You hit for " + if n = 1 then "one point" else
  1040.             IntToString(n) + " points" fi + ".\n");
  1041.         if n >= hits then
  1042.             /* target is killed */
  1043.             n := hits;
  1044.             if not theAttacker@p_pHidden and not theTarget@p_pHidden
  1045.             then
  1046.             ABPrint(here, theTarget, theAttacker,
  1047.                 attackerName + " kills " + targetName + "!\n");
  1048.             fi;
  1049.             SPrint(theTarget, attackerName + " has killed you!\n");
  1050.             Print(Capitalize(targetName) + " is killed!\n");
  1051.             if theTarget@p_pMoney ~= 0 then
  1052.             FindLoot(theTarget@p_pMoney);
  1053.             fi;
  1054.             KillPlayer(theTarget, theAttacker);
  1055.         else
  1056.             theTarget@p_pHitNow := hits - n;
  1057.         fi;
  1058.         AddExperience(theAttacker, n);
  1059.         else
  1060.         if not theTarget@p_pFightSuperTerse then
  1061.             SPrint(theTarget, attackerName +
  1062.             " attacks you and hits, but does no damage.\n");
  1063.         fi;
  1064.         if not theAttacker@p_pFightSuperTerse then
  1065.             Print("You hit " + targetName + " but do no damage.\n");
  1066.         fi;
  1067.         fi;
  1068.     else
  1069.         if not theTarget@p_pFightTerse then
  1070.         SPrint(theTarget, attackerName + " attacks you but misses.\n");
  1071.         fi;
  1072.         if not theAttacker@p_pFightTerse then
  1073.         Print("You attack " + targetName + " but miss.\n");
  1074.         fi;
  1075.     fi;
  1076.     else
  1077.     Print(Capitalize(targetName) + " is not set up for fighting.\n");
  1078.     fi;
  1079. corp;
  1080.  
  1081. /*
  1082.  * InitMonsterModels - clear a room for a new opponent set.
  1083.  */
  1084.  
  1085. define t_fight proc public InitMonsterModels(thing room; int initTotal)void:
  1086.  
  1087.     room@p_rMonsterList := CreateThingList();
  1088.     room@p_rMonsterChance := CreateIntList();
  1089.     room@p_rMonsterTotal := initTotal;
  1090. corp;
  1091.  
  1092. /*
  1093.  * AddPossibleMonster - add a monster to a room's opponent list.
  1094.  */
  1095.  
  1096. define t_fight proc public AddPossibleMonster(thing room, theMonster;
  1097.     int likelihood)void:
  1098.  
  1099.     AddTail(room@p_rMonsterList, theMonster);
  1100.     AddTail(room@p_rMonsterChance, likelihood);
  1101.     room@p_rMonsterTotal := room@p_rMonsterTotal + likelihood;
  1102. corp;
  1103.  
  1104. define t_fight proc public MonsterMove(thing theMonster; int dir)bool:
  1105.     false
  1106. corp;
  1107.  
  1108. /*
  1109.  * doRunAway - part of RunAwaySoon, and hence of RunAway.
  1110.  */
  1111.  
  1112. define tp_fight proc doRunAway()void:
  1113.     int dir;
  1114.  
  1115.     dir := Random(12);
  1116.     if not MonsterMove(Me(), dir) then
  1117.     /* failed to move - try again real soon */
  1118.     After(1.0, doRunAway);
  1119.     fi;
  1120. corp;
  1121.  
  1122. /*
  1123.  * RunAwaySoon - the current monster panics and tries hard to leave this
  1124.  *    location. This routine returns a 'status', so that it can be called
  1125.  *    via 'ForceAction'.
  1126.  */
  1127.  
  1128. define t_fight proc public RunAwaySoon()status:
  1129.  
  1130.     OPrint(Capitalize(CharacterNameG(Me())) + " panics!\n");
  1131.     After(0.0, doRunAway);
  1132.     continue
  1133. corp;
  1134.  
  1135. /*
  1136.  * RunAway - something has happened to cause a monster to want to run away.
  1137.  *    Arrange for it to try to do so. This routine is not normally called
  1138.  *    by the monster that wants to run away, so we use ForceAction and
  1139.  *    After to make it work out right.
  1140.  */
  1141.  
  1142. define t_fight proc public RunAway(thing theCoward)void:
  1143.  
  1144.     ignore ForceAction(theCoward, RunAwaySoon);
  1145. corp;
  1146.  
  1147. /*
  1148.  * MonsterAction - a monster does one of its random "actions".
  1149.  */
  1150.  
  1151. define t_fight proc public MonsterAction(thing theMonster)void:
  1152.     list int li;
  1153.     string monsterName, s;
  1154.     int pos, n;
  1155.  
  1156.     if LightAt(Here()) then
  1157.     li := theMonster@p_mActionIndexes;
  1158.     monsterName := Capitalize(CharacterNameG(theMonster));
  1159.     if li = nil then
  1160.         OPrint(monsterName + " runs around.\n");
  1161.     else
  1162.         s := theMonster@p_mActions;
  1163.         n := Random(Count(li));
  1164.         if n = 0 then
  1165.         pos := 0;
  1166.         else
  1167.         pos := li[n - 1];
  1168.         fi;
  1169.         n := li[n];
  1170.         s := SubString(s, pos, n - pos);
  1171.         OPrint(monsterName + " " + s + ".\n");
  1172.     fi;
  1173.     else
  1174.     OPrint("You hear a noise.\n");
  1175.     fi;
  1176. corp;
  1177.  
  1178. /*
  1179.  * checkMonsterArrival - a monster has moved somewhere - inform each other
  1180.  *    monster that cares.
  1181.  */
  1182.  
  1183. define tp_fight proc checkMonsterArrival(thing theTarget)void:
  1184.     action a;
  1185.  
  1186.     a := theTarget@p_mArriveAction;
  1187.     if a ~= nil then
  1188.     call(a, void)(theTarget, Me());
  1189.     fi;
  1190. corp;
  1191.  
  1192. /*
  1193.  * PickNewTarget - the monster has no target here. Randomly pick one.
  1194.  */
  1195.  
  1196. define tp_fight proc huntTarget(thing theTarget)void:
  1197.     thing me;
  1198.  
  1199.     me := Me();
  1200.     if me@p_mHunting and theTarget@p_pStandard then
  1201.     me -- p_mHunting;
  1202.     me@p_pCurrentTarget := theTarget;
  1203.     ignore MonsterHitPlayer(me, theTarget, Here());
  1204.     fi;
  1205. corp;
  1206.  
  1207. define t_fight proc public PickNewTarget()void:
  1208.  
  1209.     Me()@p_mHunting := true;
  1210.     ForEachAgent(Here(), huntTarget);
  1211. corp;
  1212.  
  1213. /*
  1214.  * MonsterMove - try to move in given direction and fight attacker.
  1215.  */
  1216.  
  1217. replace MonsterMove(thing theMonster; int dir)bool:
  1218.     thing theTarget, here;
  1219.     action a;
  1220.  
  1221.     if TryToMove(dir) then
  1222.     MachineMove(dir);
  1223.     a := theMonster@p_mArrivedAction;
  1224.     if a ~= nil then
  1225.         call(a, void)();
  1226.     fi;
  1227.     here := Here();
  1228.     ForEachAgent(here, checkMonsterArrival);
  1229.     theTarget := theMonster@p_pCurrentTarget;
  1230.     /* if our current target is here - attack! */
  1231.     if theTarget ~= nil and AgentLocation(theTarget) = here then
  1232.         if LightAt(here) then
  1233.         ignore MonsterHitPlayer(theMonster, theTarget, here);
  1234.         else
  1235.         OPrint("You hear a noise.\n");
  1236.         fi;
  1237.     elif Random(5) = 0 then
  1238.         PickNewTarget();
  1239.     fi;
  1240.     true
  1241.     else
  1242.     false
  1243.     fi
  1244. corp;
  1245.  
  1246. define t_fight MONSTER_SOUND_ID NextSoundEffectId()$
  1247. define t_fight SoundThing CreateThing(nil)$
  1248. define t_fight p_tCurrentSound CreateStringProp()$
  1249.  
  1250. /*
  1251.  * monsterSoundOnce - play the sound for a client.
  1252.  */
  1253.  
  1254. define tp_fight proc monsterSoundOnce(thing client)void:
  1255.     if SOn(client) then
  1256.     SPlaySound(client, SoundThing@p_tCurrentSound, 1, MONSTER_SOUND_ID);
  1257.     fi;
  1258. corp;
  1259.  
  1260. /*
  1261.  * playMonsterSound - play the sound associated with a monster.
  1262.  */
  1263.  
  1264. define t_fight proc PlayMonsterSound(thing theMonster, me)void:
  1265.     string sound;
  1266.  
  1267.     sound := theMonster@p_mSound;
  1268.     if sound ~= "" then
  1269.     SoundThing@p_tCurrentSound := sound;
  1270.     ForEachAgent(Here(), monsterSoundOnce);
  1271.     if me ~= nil then
  1272.         monsterSoundOnce(me);
  1273.     fi;
  1274.     SoundThing -- p_tCurrentSound;
  1275.     fi;
  1276. corp;
  1277.  
  1278. /*
  1279.  * DoMonsterMove - attack target, move in random direction or do "action"
  1280.  */
  1281.  
  1282. define t_fight proc public DoMonsterMove(thing theMonster)void:
  1283.     thing theTarget, here;
  1284.     action a;
  1285.  
  1286.     here := Here();
  1287.     if Random(3) = 0 then
  1288.     theTarget := theMonster@p_pCurrentTarget;
  1289.     if theTarget ~= nil and AgentLocation(theTarget) = here then
  1290.         PlayMonsterSound(theMonster, nil);
  1291.         if LightAt(here) then
  1292.         ignore MonsterHitPlayer(theMonster, theTarget, here);
  1293.         else
  1294.         OPrint("You hear a noise.\n");
  1295.         fi;
  1296.     elif Random(5) = 0 then
  1297.         PickNewTarget();
  1298.     fi;
  1299.     else
  1300.     if MonsterMove(theMonster, Random(12)) then
  1301.         a := theMonster@p_mAfterMoveAction;
  1302.         if a ~= nil then
  1303.         call(a, void)();
  1304.         fi;
  1305.     else
  1306.         PlayMonsterSound(theMonster, nil);
  1307.         MonsterAction(theMonster);
  1308.     fi;
  1309.     fi;
  1310. corp;
  1311.  
  1312. /*
  1313.  * MonsterStillMoving - see if monster leaves, and if so, nuke it.
  1314.  */
  1315.  
  1316. define t_fight proc public MonsterStillMoving(thing theMonster;
  1317.     action dieAction)bool:
  1318.     thing obj, theTarget;
  1319.     int n, count;
  1320.     list thing lt;
  1321.  
  1322.     n := theMonster@p_mMovesUntilVanish;
  1323.     if n = FOREVER_LIFE then
  1324.     true
  1325.     elif n <= 0 then
  1326.     theMonster@p_mExpired := true;
  1327.     if dieAction ~= nil then
  1328.         call(dieAction, void)(theMonster);
  1329.     fi;
  1330.     if LightAt(Here()) then
  1331.         OPrint(Capitalize(CharacterNameG(theMonster)) + " leaves.\n");
  1332.         ForEachAgent(Here(), UnShowIconOnce);
  1333.     fi;
  1334.     theTarget := theMonster@p_pCurrentTarget;
  1335.     if theTarget ~= nil then
  1336.         if theTarget@p_pCurrentTarget = theMonster then
  1337.         theTarget -- p_pCurrentTarget;
  1338.         fi;
  1339.     fi;
  1340.     lt := theMonster@p_pCarrying;
  1341.     if lt ~= nil then
  1342.         count := Count(lt);
  1343.         while count ~= 0 do
  1344.         count := count - 1;
  1345.         obj := lt[count];
  1346.         ZapObject(obj);
  1347.         DelElement(lt, obj);
  1348.         od;
  1349.     fi;
  1350.     /* After this point, the monster has no properties */
  1351.     DestroyMachine(theMonster);
  1352.     /* At this point, the monster does not exist, so this routine must
  1353.        do nothing but exit. In particular, OPrint is a no-no. */
  1354.     /* NOTE: because of a possible reference from a player who attacked
  1355.        the monster and therefore has a reference to its thing as that
  1356.        player's p_pCurrentTarget, the thing, although emptied out,
  1357.        will not go away until all such players delete their reference. */
  1358.     false
  1359.     else
  1360.     theMonster@p_mMovesUntilVanish := n - 1;
  1361.     true
  1362.     fi
  1363. corp;
  1364.  
  1365. /*
  1366.  * MonsterReschedule - setup to do his step again.
  1367.  */
  1368.  
  1369. define t_fight proc public MonsterReschedule(thing theMonster)void:
  1370.     thing me;
  1371.     int i;
  1372.  
  1373.     me := Me();
  1374.     i := me@p_pHitCount;
  1375.     i := i + 1;
  1376.     if i = STEPS_PER_REGAINED_HIT_POINT then
  1377.     i := me@p_pHitNow;
  1378.     if i < me@p_pHitMax then
  1379.         me@p_pHitNow := i + 1;
  1380.     fi;
  1381.     i := 0;
  1382.     fi;
  1383.     me@p_pHitCount := i;
  1384.     i := theMonster@p_pSpeed;
  1385.     if i = 0 then
  1386.     i := 100;
  1387.     else
  1388.     i := 100 / i;
  1389.     fi;
  1390.     After(IntToFixed(Random(i) + 1), theMonster@p_mMoveAction);
  1391. corp;
  1392.  
  1393. /*
  1394.  * DummyMonsterInit - init routine that just does the Reschedule.
  1395.  */
  1396.  
  1397. define t_fight proc public DummyMonsterInit()void:
  1398.  
  1399.     MonsterReschedule(Me());
  1400. corp;
  1401.  
  1402. /*
  1403.  * MonsterInit - initialization of a random moving monster.
  1404.  */
  1405.  
  1406. define t_fight proc public MonsterInit()void:
  1407.     thing theMonster;
  1408.  
  1409.     theMonster := Me();
  1410.     ignore SetMachineActive(theMonster, theMonster@p_mMoveAction);
  1411.     if LightAt(Here()) then
  1412.     OPrint(Capitalize(CharacterNameG(theMonster)) + " has appeared.\n");
  1413.     ForEachAgent(Here(), ShowIconOnce);
  1414.     fi;
  1415.     MonsterReschedule(theMonster);
  1416. corp;
  1417.  
  1418. /*
  1419.  * MonsterNoNo - standard monster response to many actions.
  1420.  */
  1421.  
  1422. define t_fight proc public MonsterNoNo()status:
  1423.  
  1424.     Print("You don't want to do that!\n");
  1425.     fail
  1426. corp;
  1427.  
  1428. GenericMonster@p_pName := "MONSTER;GENERIC"$
  1429. GenericMonster@p_oTouchChecker := MonsterNoNo$
  1430. GenericMonster@p_oSmellChecker := MonsterNoNo$
  1431. GenericMonster@p_oPushChecker := MonsterNoNo$
  1432. GenericMonster@p_oPullChecker := MonsterNoNo$
  1433. GenericMonster@p_oTurnChecker := MonsterNoNo$
  1434. GenericMonster@p_oLiftChecker := MonsterNoNo$
  1435. GenericMonster@p_oLowerChecker := MonsterNoNo$
  1436. GenericMonster@p_oEatChecker := MonsterNoNo$
  1437. GenericMonster@p_pGivePre := monsterGivePre$
  1438. SetThingStatus(GenericMonster, ts_readonly)$
  1439.  
  1440. /*
  1441.  * CreateMonsterModel - create a new model monster.
  1442.  */
  1443.  
  1444. define t_fight proc public CreateMonsterModel(string name, desc;
  1445.     action initAction, moveAction;
  1446.     int hits, speed, protection, accuracy, damage, money)thing:
  1447.     thing theModel;
  1448.  
  1449.     theModel := CreateThing(GenericMonster);
  1450.     SetThingStatus(theModel, ts_readonly);
  1451.     theModel@p_pName := name;
  1452.     if desc ~= "" then
  1453.     theModel@p_pDesc := desc;
  1454.     else
  1455.     theModel@p_pDesc := "This is an ordinary " + FormatName(name) + ".";
  1456.     fi;
  1457.     if initAction ~= nil then
  1458.     theModel@p_mInitAction := initAction;
  1459.     fi;
  1460.     theModel@p_mMoveAction := moveAction;
  1461.     theModel@p_pHitMax := hits;
  1462.     theModel@p_pSpeed := speed;
  1463.     theModel@p_pProtection := protection;
  1464.     theModel@p_oAccuracy := accuracy;
  1465.     theModel@p_oDamage := damage;
  1466.     if money ~= 0 then
  1467.     theModel@p_pMoney := money;
  1468.     fi;
  1469.     /* Note that we put this extra description on the model, rather than
  1470.        on the individual monsters. This saves time and space, but can mess
  1471.        up if some code ends up wanting to add description stuff to
  1472.        monsters created this way. */
  1473.     AddFighterDesc(theModel);
  1474.     theModel
  1475. corp;
  1476.  
  1477. /*
  1478.  * AddModelAction - add a 'moves around' action to a model monster.
  1479.  *    Note: keep in mind that these messages are seen by both the player
  1480.  *    involved and by any bystanders. (So don't use 'you'!).
  1481.  */
  1482.  
  1483. define t_fight proc public AddModelAction(thing theModel; string a)void:
  1484.     list int li;
  1485.     int len;
  1486.  
  1487.     li := theModel@p_mActionIndexes;
  1488.     if li = nil then
  1489.     li := CreateIntList();
  1490.     theModel@p_mActionIndexes := li;
  1491.     theModel@p_mActions := a;
  1492.     else
  1493.     a := theModel@p_mActions + a;
  1494.     theModel@p_mActions := a;
  1495.     fi;
  1496.     AddTail(li, Length(a));
  1497. corp;
  1498.  
  1499. /*
  1500.  * checkMonsterCreation - a new monster has arrived. Tell all who care.
  1501.  */
  1502.  
  1503. define tp_fight proc checkMonsterCreation(thing theOther)void:
  1504.     action a;
  1505.  
  1506.     a := theOther@p_mCreateAction;
  1507.     if a ~= nil then
  1508.     call(a, void)(theOther, Me()@p_pNewMonster);
  1509.     fi;
  1510. corp;
  1511.  
  1512. /*
  1513.  * CreateMonster - create a new monster with random hitpoints.
  1514.  *    Note: this routine assumes it is called by a player.
  1515.  */
  1516.  
  1517. define t_fight proc public CreateMonster(thing theCreator,theModel,where)thing:
  1518.     thing theMonster, me;
  1519.     int hits;
  1520.  
  1521.     me := Me();
  1522.     theMonster := CreateThing(theModel);
  1523.     SetupMachine(theMonster);
  1524.     hits := theModel@p_pHitMax;
  1525.     hits := hits / 2 + Random(hits / 2) + 1;
  1526.     theMonster@p_pHitMax := hits;
  1527.     theMonster@p_pHitNow := hits;
  1528.     theMonster@p_pHitCount := 0;
  1529.     theMonster@p_mMovesUntilVanish := RANDOM_MONSTER_LIFE;
  1530.     theMonster@p_pCurrentTarget := theCreator;
  1531.     theMonster@p_mExpired := false;
  1532.     CreateMachine(theModel@p_pName, theMonster, where, theModel@p_mInitAction);
  1533.     theCreator@p_pCurrentTarget := theMonster;
  1534.     me@p_pNewMonster := theMonster;
  1535.     ForEachAgent(where, checkMonsterCreation);
  1536.     me -- p_pNewMonster;
  1537.     PlayMonsterSound(theModel, me);
  1538.     theMonster
  1539. corp;
  1540.  
  1541. /*
  1542.  * CreateSpecificMonster - create a copy of a model monster.
  1543.  */
  1544.  
  1545. define t_fight proc public CreateSpecificMonster(
  1546.     thing theCreator, theModel, where)thing:
  1547.     thing theMonster, me;
  1548.  
  1549.     me := Me();
  1550.     theMonster := CreateThing(theModel);
  1551.     SetupMachine(theMonster);
  1552.     theMonster@p_pHitNow := theModel@p_pHitMax;
  1553.     theMonster@p_pHitCount := 0;
  1554.     theMonster@p_mMovesUntilVanish := RANDOM_MONSTER_LIFE;
  1555.     theMonster@p_pCurrentTarget := theCreator;
  1556.     CreateMachine(theModel@p_pName, theMonster, where, theModel@p_mInitAction);
  1557.     theCreator@p_pCurrentTarget := theMonster;
  1558.     me@p_pNewMonster := theMonster;
  1559.     ForEachAgent(where, checkMonsterCreation);
  1560.     me -- p_pNewMonster;
  1561.     PlayMonsterSound(theModel, me);
  1562.     theMonster
  1563. corp;
  1564.  
  1565. /*
  1566.  * PickNewMonster - pick a new monster for the player to fight.
  1567.  *    Return the thing of the generated monster, if any.
  1568.  */
  1569.  
  1570. define t_fight proc public PickNewMonster(thing theCreator, where)thing:
  1571.     list thing lt;
  1572.     list int li;
  1573.     int choice, count;
  1574.  
  1575.     lt := where@p_rMonsterList;
  1576.     if lt ~= nil then
  1577.     li := where@p_rMonsterChance;
  1578.     choice := Random(where@p_rMonsterTotal);
  1579.     count := Count(li);
  1580.     while count ~= 0 and choice >= li[count - 1] do
  1581.         choice := choice - li[count - 1];
  1582.         count := count - 1;
  1583.     od;
  1584.     if count ~= 0 then
  1585.         CreateMonster(theCreator, lt[count - 1], where)
  1586.     else
  1587.         nil
  1588.     fi
  1589.     else
  1590.     nil
  1591.     fi
  1592. corp;
  1593.  
  1594. /* a 'checker' for healing and generating random monsters */
  1595.  
  1596. define tp_fight proc monsterEnterCheck()status:
  1597.     thing me, theMonster;
  1598.     int i;
  1599.  
  1600.     me := Me();
  1601.     i := me@p_pHitCount;
  1602.     i := i + 1;
  1603.     if i = STEPS_PER_REGAINED_HIT_POINT then
  1604.     i := me@p_pHitNow;
  1605.     if i < me@p_pHitMax then
  1606.         me@p_pHitNow := i + 1;
  1607.     fi;
  1608.     i := 0;
  1609.     fi;
  1610.     me@p_pHitCount := i;
  1611.     theMonster := me@p_pCurrentTarget;
  1612.     if theMonster = nil and not Here()@p_rNoGenerateMonsters then
  1613.     theMonster := PickNewMonster(me, Here());
  1614.     fi;
  1615.     continue
  1616. corp;
  1617.  
  1618. /* a 'checker' to let monsters try to hit fleeing players */
  1619.  
  1620. define tp_fight proc monsterLeaveCheck(int dir)status:
  1621.     thing me, theMonster, here;
  1622.     int n;
  1623.     status result;
  1624.  
  1625.     result := continue;
  1626.     me := Me();
  1627.     theMonster := me@p_pCurrentTarget;
  1628.     if theMonster ~= nil then
  1629.     here := Here();
  1630.     if AgentLocation(theMonster) = here then
  1631.         /* the monster I was fighting is still here with me */
  1632.         n := Random(3);
  1633.         if n = 0 and theMonster@p_mBlocker then
  1634.         if LightAt(here) then
  1635.             Print(Capitalize(CharacterNameG(theMonster)) +
  1636.             " blocks you.\n");
  1637.         else
  1638.             Print("Something blocks you.\n");
  1639.         fi;
  1640.         result := fail;
  1641.         else
  1642.         if n = 1 and LightAt(here) then
  1643.             if not MonsterHitPlayer(theMonster, me, here) then
  1644.             /* player has died - fail the move */
  1645.             result := fail;
  1646.             fi;
  1647.         fi;
  1648.         me -- p_pCurrentTarget;
  1649.         fi;
  1650.     else
  1651.         me -- p_pCurrentTarget;
  1652.     fi;
  1653.     fi;
  1654.     result
  1655. corp;
  1656.  
  1657. /*
  1658.  * StandardAttack - standard code for player attack something.
  1659.  */
  1660.  
  1661. define t_fight proc public StandardAttack(
  1662.     thing thePlayer, theTarget, where)void:
  1663.     int mSpeed;
  1664.  
  1665.     if theTarget@p_pStandard then
  1666.     /* a monster set up like a player, e.g. Packrat after being forced
  1667.        into the proving grounds */
  1668.     if theTarget@p_pInited then
  1669.         PlayerHitPlayer(theTarget);
  1670.     else
  1671.         Print(Capitalize(CharacterNameS(theTarget)) +
  1672.           " is not set up for fighting.\n");
  1673.     fi;
  1674.     else
  1675.     mSpeed := theTarget@p_pSpeed;
  1676.     if Random(thePlayer@p_pSpeed + mSpeed) < mSpeed then
  1677.         /* monster hits first */
  1678.         if MonsterHitPlayer(theTarget, thePlayer, where) then
  1679.         ignore PlayerHitMonster(thePlayer, theTarget);
  1680.         fi;
  1681.     else
  1682.         /* player hits first */
  1683.         if PlayerHitMonster(thePlayer, theTarget) then
  1684.         ignore MonsterHitPlayer(theTarget, thePlayer, where);
  1685.         fi;
  1686.     fi;
  1687.     fi;
  1688. corp;
  1689.  
  1690. /*
  1691.  * InitFighter - set up a player for fighting. Can be called repeatedly,
  1692.  *    since it checks for duplicates.
  1693.  */
  1694.  
  1695. define t_fight proc public InitFighter(thing fighter)void:
  1696.  
  1697.     if not fighter@p_pInited then
  1698.     fighter@p_pInited := true;
  1699.     fighter@p_pHitMax := 10;
  1700.     fighter@p_pHitNow := 10;
  1701.     fighter@p_pHitCount := 0;
  1702.     fighter@p_pExperience := 0;
  1703.     fighter@p_pStrength := STANDARD_STRENGTH;
  1704.     fighter@p_pSpeed := STANDARD_SPEED;
  1705.     fighter@p_pProtection := 9;    /* armour class +9 */
  1706.     fighter@p_pLevel := 0;
  1707.     fighter@p_pDieNotifyList := CreateActionList();
  1708.     AddPlayerEnterChecker(fighter, monsterEnterCheck, false);
  1709.     AddPlayerLeaveChecker(fighter, monsterLeaveCheck, false);
  1710.     SPrint(fighter, "\nCombat initialized!\n\n");
  1711.     fi;
  1712. corp;
  1713.  
  1714. /*
  1715.  * LeaveFighting - utility to call when leaving a fighting area. It returns
  1716.  *    'fail' for monsters, to keep them in, 'succeed' for players. Is
  1717.  *    suitable for a regular move checker.
  1718.  */
  1719.  
  1720. define t_fight proc public LeaveFighting()status:
  1721.     thing fighter;
  1722.  
  1723.     fighter := Me();
  1724.     if fighter@p_pInited then
  1725.     /* a player or someone like Packrat */
  1726.     continue
  1727.     else
  1728.     /* must be a monster - don't let them out */
  1729.     fail
  1730.     fi
  1731. corp;
  1732.  
  1733. /*
  1734.  * HealingBuy - routine to buy healing at a healer.
  1735.  */
  1736.  
  1737. define t_fight proc public HealingBuy(string what)bool:
  1738.     thing me;
  1739.  
  1740.     me := Me();
  1741.     if me@p_pHitNow >= me@p_pHitMax then
  1742.     Print("The proprietor looks at you for a moment, and then frowns "
  1743.         "in puzzlement and says: 'But you are in perfect health!'\n");
  1744.     false
  1745.     else
  1746.     StoreBuy(what)
  1747.     fi
  1748. corp;
  1749.  
  1750. /************************\
  1751. *             *
  1752. * The new commands added *
  1753. *             *
  1754. \************************/
  1755.  
  1756. define tp_fight proc v_status(string who)bool:
  1757.     thing me;
  1758.  
  1759.     me := Me();
  1760.     if who == "full" then
  1761.     if me@p_pInited then
  1762.         showStats(me, true);
  1763.         true
  1764.     else
  1765.         Print("There is no combat status to show you.\n");
  1766.         false
  1767.     fi
  1768.     elif who ~= "" and IsWizard() then
  1769.     me := FindAgent(who);
  1770.     if me ~= nil then
  1771.         showStats(me, true);
  1772.         true
  1773.     else
  1774.         Print("There is no " + who + " here.\n");
  1775.         false
  1776.     fi
  1777.     else
  1778.     if me@p_pInited then
  1779.         showStats(me, false);
  1780.         true
  1781.     else
  1782.         Print("There is no combat status to show you.\n");
  1783.         false
  1784.     fi
  1785.     fi
  1786. corp;
  1787.  
  1788. define tp_fight proc v_wield(string what)bool:
  1789.     VerbCarry("wield", nil, p_oWieldChecker, p_pWieldChecker,
  1790.           "You cannot wield", what)
  1791. corp;
  1792.  
  1793. /*
  1794.  * v_hit - the basic attacking verb.
  1795.  */
  1796.  
  1797. define tp_fight proc v_hit(string what)bool:
  1798.     thing me, theTarget, here;
  1799.     action a;
  1800.  
  1801.     me := Me();
  1802.     here := Here();
  1803.     if not me@p_pInited then
  1804.     Print("You are not yet set up for fighting.\n");
  1805.     false
  1806.     elif not CanSee(here, me) then
  1807.     Print("You can't see to fight.\n");
  1808.     false
  1809.     elif here@p_rMonsterList = nil then
  1810.     Print("This is a non-combat area.\n");
  1811.     false
  1812.     elif what = "" then
  1813.     Print("You flail around at nothing in particular.\n");
  1814.     if not me@p_pHidden then
  1815.         OPrint(Capitalize(CharacterNameG(me)) + " flails around.\n");
  1816.     fi;
  1817.     true
  1818.     else
  1819.     theTarget := FindAgent(what);
  1820.     if theTarget = nil then
  1821.         if FindName(here@p_rContents, p_oName, what) ~= fail or
  1822.         FindName(me@p_pCarrying, p_oName, what) ~= fail or
  1823.         MatchName(here@p_rScenery, what) ~= -1
  1824.         then
  1825.         Print("You can only attack players or monsters.\n");
  1826.         else
  1827.         Print(IsAre("There", "no", FormatName(what), "here.\n"));
  1828.         fi;
  1829.         false
  1830.     else
  1831.         if ThingCharacter(theTarget) ~= nil then
  1832.         if theTarget = me then
  1833.             Print("Masochism is not implemented.\n");
  1834.         else
  1835.             /* attacking another player */
  1836.             PlayerHitPlayer(theTarget);
  1837.         fi;
  1838.         else
  1839.         /* attacking a monster */
  1840.         a := theTarget@p_mFightAction;
  1841.         if a ~= nil then
  1842.             call(a, void)(theTarget);
  1843.         else
  1844.             StandardAttack(me, theTarget, here);
  1845.         fi;
  1846.         fi;
  1847.         true
  1848.     fi
  1849.     fi
  1850. corp;
  1851.  
  1852. /*
  1853.  * verbs to allow briefer output during combat.
  1854.  */
  1855.  
  1856. define tp_fight proc v_fightterse()bool:
  1857.     thing me;
  1858.  
  1859.     me := Me();
  1860.     if me@p_pFightTerse and not me@p_pFightSuperTerse then
  1861.     Print("You are already in fightterse mode.\n");
  1862.     false
  1863.     else
  1864.     me -- p_pFightSuperTerse;
  1865.     me@p_pFightTerse := true;
  1866.     Print("fightterse mode set.\n");
  1867.     true
  1868.     fi
  1869. corp;
  1870.  
  1871. define tp_fight proc v_fightsuperterse()bool:
  1872.     thing me;
  1873.  
  1874.     me := Me();
  1875.     if me@p_pFightSuperTerse then
  1876.     Print("You are already in fightsuperterse mode.\n");
  1877.     false
  1878.     else
  1879.     me@p_pFightTerse := true;
  1880.     me@p_pFightSuperTerse := true;
  1881.     Print("fightsuperterse mode set.\n");
  1882.     true
  1883.     fi
  1884. corp;
  1885.  
  1886. define tp_fight proc v_fightverbose()bool:
  1887.     thing me;
  1888.  
  1889.     me := Me();
  1890.     if not me@p_pFightTerse then
  1891.     Print("You are already in fightverbose mode.\n");
  1892.     false
  1893.     else
  1894.     me -- p_pFightTerse;
  1895.     me -- p_pFightSuperTerse;
  1896.     Print("fightverbose mode set.\n");
  1897.     true
  1898.     fi
  1899. corp;
  1900.  
  1901. Verb1(G, "status", 0, v_status)$
  1902. Synonym(G, "status", "st")$
  1903. Verb1(G, "wield", 0, v_wield)$
  1904. Verb1(G, "hit", 0, v_hit)$
  1905. Synonym(G, "hit", "fight")$
  1906. Synonym(G, "hit", "attack")$
  1907. Synonym(G, "hit", "kill")$
  1908. Synonym(G, "hit", "h")$
  1909. Synonym(G, "hit", "k")$
  1910. Verb0(G, "fightterse", 0, v_fightterse)$
  1911. Synonym(G, "fightterse", "fightbrief")$
  1912. Verb0(G, "fightsuperterse", 0, v_fightsuperterse)$
  1913. Synonym(G, "fightsuperterse", "fightsuperbrief")$
  1914. Verb0(G, "fightverbose", 0, v_fightverbose)$
  1915.  
  1916. unuse tp_fight
  1917.