home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 May / Amiga_Games_Extra_CD_5-96.bin / spiele / publicdomain / amsrc / combat / monsters.m < prev   
Text File  |  1996-02-19  |  15KB  |  515 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1996 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * monsters.m - define some monster classes and monsters.
  9.  */
  10.  
  11. private tp_monsters CreateTable().
  12. use tp_monsters
  13.  
  14. /* a move routine for a simple random moving monster */
  15.  
  16. /*
  17.  * RandomMove - used for dumb monsters which just wander around.
  18.  */
  19.  
  20. define t_monsters proc public RandomMove()void:
  21.     thing theMonster;
  22.     int n;
  23.     action a;
  24.  
  25.     theMonster := Me();
  26.     if MonsterStillMoving(theMonster, nil) then
  27.     a := theMonster@p_mSpecialAction;
  28.     if a ~= nil then
  29.         if not call(a, bool)() then
  30.         /* something special - give it a new lease on life */
  31.         theMonster@p_mMovesUntilVanish := RANDOM_MONSTER_LIFE + 1;
  32.         MonsterReschedule(theMonster);
  33.         fi;
  34.     else
  35.         DoMonsterMove(theMonster);
  36.         MonsterReschedule(theMonster);
  37.     fi;
  38.     fi;
  39. corp;
  40.  
  41. /* set up monsters which will pick up and use stuff */
  42.  
  43. define t_monsters proc public MonsterPickUp()void:
  44.     list thing lt;
  45.     int count, i, carryCount, n;
  46.     thing here, theMonster, th, old;
  47.  
  48.     theMonster := Me();
  49.     here := Here();
  50.     lt := here@p_rContents;
  51.     count := Count(lt);
  52.     carryCount := Count(theMonster@p_pCarrying);
  53.     i := 0;
  54.     while i < count and carryCount < MAX_CARRY do
  55.     th := lt[i];
  56.     if not th@p_oInvisible and not th@p_oNotGettable then
  57.         if DoGet(here, theMonster, th) ~= continue then
  58.         /* something wrong - quit trying to get things */
  59.         i := count;
  60.         else
  61.         count := count - 1;
  62.         carryCount := carryCount + 1;
  63.         n := th@p_oArmourProt;
  64.         old := theMonster@p_pArmour;
  65.         if old = nil and n ~= 0 or
  66.             old ~= nil and n < old@p_oArmourProt
  67.         then
  68.             SetIt(th);
  69.             ignore call(th@p_oWearChecker, status)();
  70.             /* make him live forever */
  71.             theMonster@p_mMovesUntilVanish := FOREVER_LIFE;
  72.         else
  73.             n := th@p_oShieldProt;
  74.             old := theMonster@p_pShield;
  75.             if old = nil and n ~= 0 or
  76.             old ~= nil and n < old@p_oShieldProt
  77.             then
  78.             SetIt(th);
  79.             ignore call(th@p_oUseChecker, status)();
  80.             theMonster@p_mMovesUntilVanish := FOREVER_LIFE;
  81.             else
  82.             n := th@p_oDamage;
  83.             old := theMonster@p_pWeapon;
  84.             if old = nil and n ~= 0 or
  85.                 old ~= nil and n > old@p_oDamage
  86.             then
  87.                 SetIt(th);
  88.                 ignore call(th@p_oWieldChecker, status)();
  89.                 theMonster@p_mMovesUntilVanish := FOREVER_LIFE;
  90.             fi;
  91.             fi;
  92.         fi;
  93.         fi;
  94.     else
  95.         i := i + 1;
  96.     fi;
  97.     od;
  98. corp;
  99.  
  100. /* set up trackers */
  101.  
  102. define t_monsters p_mTrackerPath CreateIntListProp().
  103. define t_monsters p_pTrackerList CreateThingListProp().
  104.  
  105. /*
  106.  * TrackerDieNotify - called when a player with trackers dies. Return 'true'
  107.  *    to indicate that we want to be removed from the notify list.
  108.  */
  109.  
  110. define t_monsters proc TrackerDieNotify(thing thePlayer)bool:
  111.     list thing trackers;
  112.     int count;
  113.     list int path;
  114.  
  115.     trackers := thePlayer@p_pTrackerList;
  116.     count := Count(trackers);
  117.     while count ~= 0 do
  118.     count := count - 1;
  119.     trackers[count] -- p_mTrackerPath;
  120.     RemTail(trackers);
  121.     od;
  122.     true
  123. corp
  124.  
  125. /*
  126.  * TrackerChecker - a player leave checker that records the direction on all
  127.  *    following trackers
  128.  */
  129.  
  130. define t_monsters proc TrackerChecker(int dir)status:
  131.     list thing lt;
  132.     int count, n, dirCount;
  133.     thing thePlayer, theTracker;
  134.     list int li;
  135.  
  136.     thePlayer := Me();
  137.     lt := thePlayer@p_pTrackerList;
  138.     if lt = nil then
  139.     DelPlayerLeaveChecker(thePlayer, TrackerChecker);
  140.     DelElement(thePlayer@p_pDieNotifyList, TrackerDieNotify);
  141.     else
  142.     count := Count(lt);
  143.     if count ~= 0 then
  144.         n := 0;
  145.         while n ~= count do
  146.         theTracker := lt[n];
  147.         if theTracker@p_mExpired then
  148.             DelElement(lt, theTracker);
  149.             DestroyMachine(theTracker);
  150.             count := count - 1;
  151.         else
  152.             li := theTracker@p_mTrackerPath;
  153.             if li = nil then
  154.             li := CreateIntList();
  155.             theTracker@p_mTrackerPath := li;
  156.             dirCount := 0;
  157.             else
  158.             dirCount := Count(li);
  159.             fi;
  160.             if dirCount ~= 0 and li[dirCount - 1] = DirBack(dir) then
  161.             /* two directions cancel out */
  162.             RemTail(li);
  163.             else
  164.             AddTail(li, dir);
  165.             fi;
  166.             n := n + 1;
  167.         fi;
  168.         od;
  169.     fi;
  170.     if count = 0 then
  171.         thePlayer -- p_pTrackerList;
  172.         DelPlayerLeaveChecker(thePlayer, TrackerChecker);
  173.         DelElement(thePlayer@p_pDieNotifyList, TrackerDieNotify);
  174.     fi;
  175.     fi;
  176.     continue
  177. corp;
  178.  
  179. /*
  180.  * TrackerDie - a die action for trackers, as called by MonsterStillMoving
  181.  */
  182.  
  183. define t_monsters proc TrackerDie(thing theTracker)void:
  184.     list thing lt;
  185.     thing theTarget;
  186.  
  187.     theTarget := theTracker@p_pCurrentTarget;
  188.     if theTarget ~= nil then
  189.     lt := theTarget@p_pTrackerList;
  190.     if lt ~= nil and FindElement(lt, theTracker) ~= -1 then
  191.         DelElement(lt, theTracker);
  192.         if Count(lt) = 0 then
  193.         theTarget -- p_pTrackerList;
  194.         DelPlayerLeaveChecker(theTarget, TrackerChecker);
  195.         DelElement(theTarget@p_pDieNotifyList, TrackerDieNotify);
  196.         fi;
  197.     fi;
  198.     fi;
  199. corp;
  200.  
  201. /*
  202.  * TrackerKill - routine to do extra stuff when a tracker is killed.
  203.  *    NOTE: this should be attached to each model of a tracker.
  204.  */
  205.  
  206. define t_monsters proc TrackerKill(thing thePlayer, theMonster)bool:
  207.     int hitsLeft;
  208.  
  209.     hitsLeft := theMonster@p_pHitNow;
  210.     TrackerDie(theMonster);
  211.     KillMonster(theMonster);
  212.     DestroyMachine(theMonster);
  213.     AddExperience(thePlayer, hitsLeft);
  214.     false
  215. corp;
  216.  
  217. /*
  218.  * TrackerInit - extra init stuff for a tracker.
  219.  */
  220.  
  221. define t_monsters proc TrackerInit()void:
  222.     thing theMonster, thePlayer;
  223.     list thing trackers;
  224.  
  225.     theMonster := Me();
  226.     if theMonster@p_mKillAction = nil then
  227.     /* should be on the model, but if not... */
  228.     theMonster@p_mKillAction := TrackerKill;
  229.     fi;
  230.     MonsterInit();
  231.     thePlayer := theMonster@p_pCurrentTarget;
  232.     trackers := thePlayer@p_pTrackerList;
  233.     if trackers = nil then
  234.     trackers := CreateThingList();
  235.     thePlayer@p_pTrackerList := trackers;
  236.     AddPlayerLeaveChecker(thePlayer, TrackerChecker, false);
  237.     AddTail(thePlayer@p_pDieNotifyList, TrackerDieNotify);
  238.     fi;
  239.     AddTail(trackers, theMonster);
  240. corp;
  241.  
  242. /*
  243.  * TrackerMove - a tracker moves a single step, hopefully on the path
  244.  *    following the target.
  245.  */
  246.  
  247. define t_monsters proc TrackerMove()void:
  248.     thing theMonster, theTarget, here;
  249.     list int li;
  250.     int dir, count;
  251.     bool followed;
  252.  
  253.     theMonster := Me();
  254.     here := Here();
  255.     li := theMonster@p_mTrackerPath;
  256.     if li = nil then
  257.     count := 0;
  258.     else
  259.     count := Count(li);
  260.     fi;
  261.     theTarget := theMonster@p_pCurrentTarget;
  262.     if AgentLocation(theTarget) = here then
  263.     ignore MonsterHitPlayer(theMonster, theTarget, here);
  264.     theMonster@p_mTrackerPath := CreateIntList();
  265.     MonsterReschedule(theMonster);
  266.     else
  267.     followed := false;
  268.     if count ~= 0 then
  269.         dir := li[0];
  270.         RemHead(li);
  271.         if MonsterMove(theMonster, dir) then
  272.         followed := true;
  273.         else
  274.         /* rats! can't follow */
  275.         theMonster -- p_mTrackerPath;
  276.         fi;
  277.     fi;
  278.     if not followed then
  279.         /* where did he go, where did he go? */
  280.         if not MonsterMove(theMonster, Random(12)) then
  281.         if MonsterStillMoving(theMonster, TrackerDie) then
  282.             MonsterAction(theMonster);
  283.             MonsterReschedule(theMonster);
  284.         fi;
  285.         else
  286.         MonsterReschedule(theMonster);
  287.         fi;
  288.     else
  289.         MonsterReschedule(theMonster);
  290.     fi;
  291.     fi;
  292. corp;
  293.  
  294. /* define some "standard" monsters.
  295.    Note: numerics: hitpoints, speed, protection, accuracy, damage, gold */
  296.  
  297. define t_monsters m_rat CreateMonsterModel("rat",
  298.     "The rat is of average size, and, like most rats, is quite filthy.",
  299.     MonsterInit, RandomMove,
  300.     2, 6, 9, 5, 2, 0).
  301. AddModelAction(m_rat, "runs around").
  302. AddModelAction(m_rat, "chitters").
  303. AddModelAction(m_rat, "squeals").
  304. m_rat@p_Image := "Characters/rat".
  305.  
  306. define t_monsters m_snake CreateMonsterModel("snake",
  307.     "The snake isn't poisonous, but bites pretty well. It has no "
  308.     "distinguishing markings.",
  309.     MonsterInit, RandomMove,
  310.     4, 8, 9, 5, 2, 0).
  311. AddModelAction(m_snake, "slithers around").
  312. AddModelAction(m_snake, "hisses").
  313. AddModelAction(m_snake, "coils and uncoils").
  314. m_snake@p_Image := "Characters/snake".
  315.  
  316. define t_monsters m_dog CreateMonsterModel("dog;wild", "",
  317.     MonsterInit, RandomMove,
  318.     6, 5, 9, 5, 3, 0).
  319. m_dog@p_mBlocker := true.
  320. AddModelAction(m_dog, "runs around").
  321. AddModelAction(m_dog, "barks").
  322. AddModelAction(m_dog, "growls").
  323. AddModelAction(m_dog, "snarls").
  324. m_dog@p_Image := "Characters/dog".
  325.  
  326. define t_monsters m_gremlin CreateMonsterModel("gremlin;nasty",
  327.     "The gremlin, like all of its kind, is quite dirty. It also comes "
  328.     "equipped with sharp teeth and claws.",
  329.     MonsterInit, RandomMove,
  330.     5, 5, 9, 5, 3, 15).
  331. AddModelAction(m_gremlin, "runs in circles around you").
  332. AddModelAction(m_gremlin, "shrieks loudly").
  333. AddModelAction(m_gremlin, "curses").
  334. AddModelAction(m_gremlin, "picks its nose").
  335. AddModelAction(m_gremlin, "thumbs its nose").
  336. AddModelAction(m_gremlin, "spits at you").
  337. m_gremlin@p_Image := "Characters/gremlin".
  338.  
  339. /* and now some bigger stuff for forests, etc. */
  340.  
  341. define t_monsters m_wolf CreateMonsterModel("wolf", "",
  342.     MonsterInit, RandomMove,
  343.     10, 5, 9, 7, 6, 0).
  344. m_wolf@p_mBlocker := true.
  345. AddModelAction(m_wolf, "runs around").
  346. AddModelAction(m_wolf, "snarls").
  347. AddModelAction(m_wolf, "howls").
  348. m_wolf@p_Image := "Characters/wolf".
  349.  
  350. define t_monsters m_troll CreateMonsterModel("troll", "",
  351.     MonsterInit, RandomMove,
  352.     13, 4, 8, 6, 6, 40).
  353. m_troll@p_mBlocker := true.
  354. AddModelAction(m_troll, "lumbers around").
  355. AddModelAction(m_troll, "bellows").
  356. AddModelAction(m_troll, "raises its fists and roars").
  357. m_troll@p_Image := "Characters/troll".
  358.  
  359. define t_monsters m_blackBear CreateMonsterModel("bear;black", "",
  360.     MonsterInit, RandomMove,
  361.     15, 5, 8, 6, 6, 0).
  362. m_blackBear@p_mBlocker := true.
  363. AddModelAction(m_blackBear, "lumbers around").
  364. AddModelAction(m_blackBear, "roars").
  365. AddModelAction(m_blackBear, "stands upright and waves its paws").
  366. m_blackBear@p_Image := "Characters/blackBear".
  367.  
  368. define t_monsters m_deer CreateMonsterModel("deer;mule", "",
  369.     MonsterInit, RandomMove,
  370.     8, 7, 9, 0, 0, 0).
  371. AddModelAction(m_deer, "leaps around").
  372. AddModelAction(m_deer, "screams silently").
  373. AddModelAction(m_deer, "snorts").
  374. define tp_monsters proc deerArrivalCheck(thing theDeer, theArrival)void:
  375.  
  376.     if IsAncestor(theArrival, m_wolf) or IsAncestor(theArrival, m_troll) then
  377.     RunAway(theDeer);
  378.     fi;
  379. corp;
  380. m_deer@p_mArriveAction := deerArrivalCheck.
  381. define tp_monsters proc deerCreationCheck(thing theDeer, theNew)void:
  382.  
  383.     if IsAncestor(theNew, m_wolf) or IsAncestor(theNew, m_troll) then
  384.     RunAway(theDeer);
  385.     fi;
  386. corp;
  387. m_deer@p_mCreateAction := deerCreationCheck.
  388. define tp_monsters proc deerArrivedCheck()void:
  389.     thing here;
  390.  
  391.     here := Here();
  392.     if FindAgentAsDescendant(here, m_wolf) ~= nil or
  393.     FindAgentAsDescendant(here, m_troll) ~= nil
  394.     then
  395.     ignore RunAwaySoon();
  396.     fi;
  397. corp;
  398. m_deer@p_mArrivedAction := deerArrivedCheck.
  399. m_deer@p_Image := "Characters/deer".
  400.  
  401. define t_monsters m_moose CreateMonsterModel("moose", "",
  402.     MonsterInit, RandomMove,
  403.     18, 4, 7, 6, 4, 0).
  404. m_moose@p_mBlocker := true.
  405. AddModelAction(m_moose, "wades around").
  406. AddModelAction(m_moose, "snorts").
  407. AddModelAction(m_moose, "bellows").
  408. m_moose@p_Image := "Characters/moose".
  409.  
  410. /* larger stuff for the sewers */
  411.  
  412. define t_monsters m_largeRat CreateMonsterModel("rat;large",
  413.     "The rat is of above average size and is quite filthy.",
  414.     MonsterInit, RandomMove,
  415.     4, 6, 9, 5, 4, 0).
  416. AddModelAction(m_largeRat, "runs around").
  417. AddModelAction(m_largeRat, "chitters loudly").
  418. AddModelAction(m_largeRat, "squeals loudly").
  419. m_largeRat@p_Image := "Characters/largeRat".
  420.  
  421. define t_monsters m_largeSnake CreateMonsterModel("snake;large",
  422.     "The snake isn't poisonous, but bites pretty well. It has pretty "
  423.     "red and yellow stripes running down its length.",
  424.     MonsterInit, RandomMove,
  425.     8, 8, 9, 5, 4, 0).
  426. AddModelAction(m_largeSnake, "slithers around").
  427. AddModelAction(m_largeSnake, "hisses").
  428. AddModelAction(m_largeSnake, "coils and uncoils").
  429. m_largeSnake@p_Image := "Characters/largeSnake".
  430.  
  431. define t_monsters m_goblin CreateMonsterModel("goblin",
  432.     "The goblin is a small, humanoid creature with pale skin, large eyes, "
  433.     "protruding ears, and sharp teeth. It walks in a perpetual crouch but "
  434.     "is nonetheless quite fast on its feet.",
  435.     MonsterInit, RandomMove,
  436.     10, 8, 9, 6, 5, 30).
  437. m_goblin@p_mBlocker := true.
  438. AddModelAction(m_goblin, "slouches around").
  439. AddModelAction(m_goblin, "gibbers").
  440. AddModelAction(m_goblin, "drools").
  441. AddModelAction(m_goblin, "howls").
  442. m_goblin@p_mAfterMoveAction := MonsterPickUp.
  443. m_goblin@p_Image := "Characters/goblin".
  444.  
  445. define t_monsters m_hugeRat CreateMonsterModel("rat;huge",
  446.     "The rat is quite large, but not totally filthy.",
  447.     MonsterInit, RandomMove,
  448.     8, 6, 10, 5, 8, 0).
  449. m_hugeRat@p_mBlocker := true.
  450. AddModelAction(m_hugeRat, "runs around").
  451. AddModelAction(m_hugeRat, "chitters loudly").
  452. AddModelAction(m_hugeRat, "squeals loudly").
  453. m_hugeRat@p_Image := "Characters/hugeRat".
  454.  
  455. define t_monsters m_hugeSnake CreateMonsterModel("snake;huge",
  456.     "The snake isn't poisonous, but bites pretty well. It has a very striking "
  457.     "checkerboard pattern.",
  458.     MonsterInit, RandomMove,
  459.     16, 8, 10, 5, 8, 0).
  460. m_hugeSnake@p_mBlocker := true.
  461. AddModelAction(m_hugeSnake, "slithers around").
  462. AddModelAction(m_hugeSnake, "hisses").
  463. AddModelAction(m_hugeSnake, "coils and uncoils").
  464. m_hugeSnake@p_Image := "Characters/hugeSnake".
  465.  
  466. define t_monsters m_fighterGoblin CreateMonsterModel("goblin;fighter",
  467.     "The goblin is a small, humanoid creature with pale skin, large eyes, "
  468.     "protruding ears, and sharp teeth. It walks in a perpetual crouch but "
  469.     "is nonetheless quite fast on its feet.",
  470.     MonsterInit, RandomMove,
  471.     20, 8, 10, 6, 10, 50).
  472. m_fighterGoblin@p_mBlocker := true.
  473. AddModelAction(m_fighterGoblin, "slouches around").
  474. AddModelAction(m_fighterGoblin, "gibbers").
  475. AddModelAction(m_fighterGoblin, "drools").
  476. AddModelAction(m_fighterGoblin, "howls").
  477. m_fighterGoblin@p_mAfterMoveAction := MonsterPickUp.
  478. m_fighterGoblin@p_Image := "Characters/fighterGoblin".
  479.  
  480. define t_monsters m_hugeSpider CreateMonsterModel("spider;huge",
  481.     "The spider's body is almost as large as yours, and it's long legs give "
  482.     "it good mobility and a long reach.",
  483.     MonsterInit, RandomMove,
  484.     16, 12, 15, 8, 12, 0).
  485. m_hugeSpider@p_mBlocker := true.
  486. AddModelAction(m_hugeSpider, "dances around").
  487. AddModelAction(m_hugeSpider, "clashes its fangs").
  488. AddModelAction(m_hugeSpider, "drips saliva").
  489. AddModelAction(m_hugeSpider, "waves its front legs menacingly").
  490. m_hugeSpider@p_Image := "Characters/hugeSpider".
  491.  
  492. define t_monsters m_trackerSpider CreateMonsterModel("spider;tracker",
  493.     "The spider's body is almost as large as yours, and it's long legs give "
  494.     "it good mobility and a long reach.",
  495.     TrackerInit, TrackerMove,
  496.     16, 12, 15, 8, 12, 0).
  497. m_trackerSpider@p_mBlocker := true.
  498. m_trackerSpider@p_mKillAction := TrackerKill.
  499. AddModelAction(m_trackerSpider, "dances around").
  500. AddModelAction(m_trackerSpider, "clashes its fangs").
  501. AddModelAction(m_trackerSpider, "drips saliva").
  502. AddModelAction(m_trackerSpider, "waves its front legs menacingly").
  503. m_trackerSpider@p_Image := "Characters/trackerSpider".
  504.  
  505. define t_monsters m_largeTroll CreateMonsterModel("troll;large", "",
  506.     MonsterInit, RandomMove,
  507.     26, 4, 7, 6, 12, 80).
  508. m_troll@p_mBlocker := true.
  509. AddModelAction(m_troll, "lumbers around").
  510. AddModelAction(m_troll, "bellows").
  511. AddModelAction(m_troll, "raises its fists and roars").
  512. m_troll@p_Image := "Characters/troll".
  513.  
  514. unuse tp_monsters
  515.