home *** CD-ROM | disk | FTP | other *** search
/ GameStar Special 2004 August / GSSH0804.iso / Rollenspiele / SwordOfFargoal / fargoal20030731b.exe / fargoal / src / player.c < prev    next >
C/C++ Source or Header  |  2003-07-31  |  29KB  |  1,305 lines

  1. #include "map.h"
  2. #include "char.h"
  3. #include "game.h"
  4.  
  5. static char const *attacks[] = {
  6.     "Chop!",
  7.     "Clang!",
  8.     "Ouch!",
  9.     "Thud",
  10.     "Clink!",
  11.     "Shriek!",
  12.     "Slash!",
  13.     "Ugh!",
  14.     "Claw!",
  15.     "Crunch!",
  16.     "Gnarl!",
  17.     "Growl!",
  18.     "Shred!",
  19.     "Thump!"
  20. };
  21.  
  22.  
  23. static int pass_key=FALSE;
  24.  
  25. /* C64: (Healing equation?)
  26.  
  27.     4 poke198,0:gd=0:p1=0:l1=0:b1=0:r1=50:s=20-l:gosub208:pokev3,0:ifs<1thens=1
  28.  
  29.    62 ifht<0then114
  30.    63 sp=sp+1:ifht<thandsp>ht/th*r1thenht=ht+1:print"(home)         ":sp=0
  31. */
  32.  
  33. static void player_health_add(int id, int health)
  34. {
  35.     list[id].hit+=health;
  36.  
  37.     if(list[id].hit>list[id].maxhit)
  38.         list[id].hit=list[id].maxhit;
  39.  
  40.     update_stats ();
  41. }
  42.  
  43.  
  44. static void
  45. healing (int id)
  46. {
  47.     int rate, multiplier;
  48.     if (list[id].fighting || list[id].hit < 0 || paused)
  49.         return;
  50.     
  51.     list[id].healing_time++;
  52.     
  53.     multiplier = map_get_spot (list[id].x, list[id].y) == SPOT_TEMPLE ? 1 : 0;
  54.     multiplier += list[id].amulets_of_healing;
  55.     multiplier = 1 << (list[id].spells[SPELL_REGENERATION].active + multiplier);
  56.     rate = 10 * FPS * list[id].hit / (list[id].maxhit * multiplier);
  57.  
  58.     if (list[id].hit < list[id].maxhit && list[id].healing_time > rate)
  59.     {
  60.         list[id].healing_time = 0;
  61.         player_health_add(id, 1);
  62.     }
  63. }
  64.  
  65.  
  66. /* C64: healing potion
  67.    60 hp=hp-1:x=int(20*rnd(1)+3*l):ht=ht+x:ifht>ththenht=th
  68.    61 gosub113:print"(home)healing potion taken!":gosub182:goto40
  69.  
  70. */
  71. static int drink_potion(int id)
  72. {
  73.     if (list[id].potions && list[id].hit < list[id].maxhit)
  74.     {
  75.         list[id].potions--;
  76.         player_health_add(id, rnd(0, 19)+3*list[id].current_level);
  77.  
  78.         message (FPS * 2, potion, "Healing potion taken!");
  79.         return TRUE;
  80.     }
  81.  
  82.     return FALSE;
  83. }
  84.  
  85. static void try_lose_map(int id)
  86. {
  87.     int r = rnd (1, 4);
  88.     (void) id;
  89.  
  90.     if (r == 1)
  91.     {
  92.         message (FPS * 2, NULL, "Lost your map!");
  93.         map_hide_completely ();
  94.     }
  95. }
  96.  
  97. static void
  98. monster_step_back (int e)
  99. {
  100.     /* Step back in overlapping mode */
  101.     int dx[] = {-1, -1,  0,  1, 1, 1,  0, -1};
  102.     int dy[] = { 0, -1, -1, -1, 0, 1,  1,  1};
  103.     static int d[] = {0, 1, 2, 3, 4, 5, 6, 7};
  104.     int remaining = 8;
  105.     /* Restore overlapped player. */
  106.     map_put_char (list[e].x, list[e].y, 1);
  107.     while (remaining)
  108.     {
  109.         int r = rnd (0, remaining - 1);
  110.         int rd = d[r];
  111.         int x = list[e].x + dx[rd];
  112.         int y = list[e].y + dy[rd];
  113.         if (map_get_spot (x, y) != SPOT_WALL && !map_get_char (x, y))
  114.         {
  115.             list[e].x += dx[rd];
  116.             list[e].y += dy[rd];
  117.             break;
  118.         }
  119.         remaining--;
  120.         d[r] = d[remaining];
  121.         d[remaining] = rd;
  122.     }
  123.     map_put_char (list[e].x, list[e].y, e);
  124. }
  125.  
  126. void
  127. cancel_fighting (int id)
  128. {
  129.     if (list[id].fighting)
  130.     {
  131.         int e = list[id].fighting;
  132.         /* Weak monsters bring less XP! */
  133.         list[e].maxhit = list[e].hit;
  134.         
  135.         list[e].fighting = 0;
  136.         list[e].attacked = 0;
  137.         list[id].fighting = 0;
  138.         list[id].attacked = 0;
  139.         list[id].spells[SPELL_SHIELD].active = 0;    
  140.  
  141.         if (!extensions_overlapfight)
  142.             map_put_char (list[e].x, list[e].y, e);        
  143.     }
  144. }
  145.  
  146. void
  147. player_won (int id)
  148. {
  149.     int e = list[id].fighting;
  150.     // 298 s1=0:e=e+(s%+h1)*l:bs=bs+int(5*rnd(1)+1):mk=mk+1:k=32
  151.     // 299 m%=0:gosub113:print"(home)you vanquished "x$:gosub112
  152.     // or
  153.     // 346 v1=0:s1=0:pokeo,a:e=e+(s%+h1)*l:bs=bs+int(5*rnd(1)+1):mk=mk+1
  154.     // 347 print"(home)you have slain "x$:gosub300:w%=1:gosub175
  155.  
  156.     list[id].exp += (list[e].dex + list[e].maxhit)*list[id].current_level;
  157.     //rnd (m_bs / p_bs, 3 * m_bs / p_bs)
  158.     if (extensions_balance)
  159.     {
  160.         list[id].dex+=rnd(((float)list[e].dex/list[id].dex), 
  161.         4*((float)list[e].dex/list[id].dex))+1;
  162.     }
  163.     else
  164.     {
  165.          list[id].dex+=rnd(1, 5);
  166.     }
  167.      
  168.     list[id].slain_foes[0]++;
  169.     list[id].slain_foes[list[e].type]++;
  170.     
  171.     if (list[id].attacked)
  172.     {
  173.         message (FPS * 2, victory, "You vanquished %s %s!",
  174.             char_prefixes[list[e].type][list[e].subtype],
  175.             char_names[list[e].type]);
  176.     }
  177.     else
  178.     {
  179.         message (FPS * 2, victory, "You have slain %s %s!",
  180.             char_prefixes[list[e].type][list[e].subtype],
  181.             char_names[list[e].type]);
  182.     }
  183.     
  184.     if (list[e].gold)
  185.     {
  186.     //  350 gosub113:print"(home)found your"g(v)"gold!!":t=t+g(v):goto274
  187.         list[id].gold += list[e].gold;
  188.         if(extensions_monsteraction)
  189.         {
  190.             message (FPS / 2, NULL, "Found %i gold!!", list[e].gold);
  191.         }
  192.         else
  193.         {
  194.             message (FPS / 2, NULL, "Found your %i gold!!", list[e].gold);
  195.         }
  196.     }
  197.     
  198.     {
  199.         int s;
  200.         int got_stuff = 0;
  201.         for (s = 0; s < 6; s++)
  202.         {
  203.             if (list[e].spells[s].amount)
  204.             {
  205.                 got_stuff = 1;
  206.                 list[id].spells[s].amount += list[e].spells[s].amount;
  207.             }
  208.         }
  209.         if (got_stuff)
  210.             message (FPS / 2, NULL, "Found your spells!!");
  211.     }
  212.     
  213.     if (list[e].exp)
  214.     {
  215.         list[id].exp += list[e].exp;
  216.         message (FPS / 2, NULL, "Regained your experience!!");
  217.     }
  218.     
  219.     monster_die (e);
  220.     cancel_fighting (id);
  221.     
  222.     if (!extensions_overlapfight)
  223.         map_put_char (list[id].x, list[id].y, id);
  224. }
  225.  
  226.  
  227. static void fight_action(int e)
  228. {
  229.     int random_sound = rnd (0, 6);
  230.     if (list[e].type >= CHAR_DIREWOLF)
  231.     {
  232.         message_ex(FPS * 1.25, creature[random_sound], 0, 50, 0, "%s",
  233.             attacks[7 + random_sound]);
  234.     }
  235.     else
  236.     {
  237.         message_ex(FPS * 1.25, human[random_sound], 0, 50, 0, "%s",
  238.             attacks[random_sound]);
  239.     }
  240. }
  241.  
  242.  
  243. static void
  244. player_fight (int id)
  245. {
  246.     int e = list[id].fighting;
  247.     int my_attack, monster_attack;
  248.     int max_damage;
  249.     float skill_ratio;
  250.     
  251.     update_stats ();
  252.     
  253.     /* Assassin is visible during fight. */
  254.     if (list[e].type == CHAR_ASSASSIN)
  255.     {
  256.         list[e].spells[SPELL_INVISIBILITY].active = 0;
  257.         /* Redraw */
  258.         map_put_char (list[e].x, list[e].y, e);
  259.     }
  260.     
  261.     if (!list[e].dex)
  262.     {
  263.         // 307 print"(home)the mage takes your magic spells!!":iv=0:rg=0:tp=0:sh=0:fa=0:lg=0:goto309
  264.         // 308 print"(home)the demon drains your experience level!!":e=int(e/2):ifel>1thenel=el-1
  265.         if (list[e].type >= CHAR_DIREWOLF)
  266.         {
  267.             message (FPS, NULL, "The demon drains your experience level!!");
  268.             list[e].exp = list[id].exp / 2;
  269.             list[id].exp -= list[e].exp;
  270.         
  271.             if(!extensions_monsteraction)
  272.                 if (list[id].lev > 1)
  273.                     list[id].lev--;
  274.         
  275.             list[e].trapped = 1;
  276.             list[e].dex++;
  277.         }
  278.         else
  279.         {
  280.             int s;
  281.             message (FPS, NULL, "The mage takes your magic spells!!");
  282.             for (s = 0; s < 6; s++)
  283.             {
  284.                 list[e].spells[s].amount = list[id].spells[s].amount;
  285.                 list[id].spells[s].amount = 0;
  286.             }
  287.             list[e].trapped = 1;
  288.             list[e].dex++;
  289.         }
  290.                 
  291.         //  309 m%=0:gosub112:gosub300:return
  292.         if (extensions_monsteraction)
  293.         {
  294.             monster_teleport (e);
  295.             if (!extensions_overlapfight)
  296.                 map_put_char (list[id].x, list[id].y, id);
  297.         }
  298.         else
  299.             monster_die (e);
  300.         
  301.         cancel_fighting (id);
  302.         return;
  303.     }
  304.     
  305.     // C64: 286 x2=s%/bs:h1=h%
  306.     skill_ratio=(float)list[id].dex/(list[e].dex);
  307.     //290 h%=h%-int(1/x2*4*l*rnd(1)+1+pl):ifh%<0then298
  308.     max_damage = (float)(skill_ratio) * 4 * list[id].current_level;
  309.     my_attack = rnd (1, max_damage) + list[id].weapon;
  310.  
  311.     // C64: 288 ht=ht-int(x2*4*l*rnd(1)+1)
  312.     skill_ratio=(float)list[e].dex/(list[id].dex);
  313.     max_damage = (float)skill_ratio * 4 * list[id].current_level;
  314.     monster_attack = rnd (1, max_damage);
  315.     
  316.     /* We are merely defending ourselves. */
  317.     if (list[id].attacked)
  318.     {        
  319.         // 286 x2=s%/bs:h1=h%
  320.         // 287 ifs1=1then289
  321.         // 288 ht=ht-int(x2*4*l*rnd(1)+1)
  322.         if (!list[id].spells[SPELL_SHIELD].active)
  323.         {
  324.             player_health_add(id, -monster_attack);
  325.             add_hit (list[id].x, list[id].y, -monster_attack);
  326.         }
  327.  
  328.         fight_action(e);
  329.         
  330.         // 289 ifd=1andt>0orsf=1thenifx2<.5orx2>1orc=42then294
  331.         if (list[e].type < CHAR_DIREWOLF && (list[id].gold || list[id].sword))
  332.         {
  333.             if (list[e].dex > list[id].dex || list[e].dex * 2 < list[id].dex ||
  334.                 list[e].type == CHAR_ROGUE)
  335.             {
  336.                 // 294 gosub113:ifsf=1thensf=0:print"(home)the sword is stolen!!":gosub112:goto296
  337.                 // 295 d=-1:p=a:print"(home)your gold is stolen!!":gosub112:g(j)=t:t=0:goto386
  338.                 
  339.                 if (list[id].sword)
  340.                 {
  341.                     list[e].sword = list[id].sword;
  342.                     list[id].sword = 0;
  343.                     message (FPS * 2, NULL, "The sword is stolen!!");
  344.                     list[e].trapped = 1;
  345.                     if (list[id].current_level == swordlev)
  346.                     {
  347.                         map_put_spot (19, 12, SPOT_SWORD);
  348.                     }
  349.                 }
  350.                 else
  351.                 {
  352.                     message (FPS * 2, NULL, "Your gold is stolen!!");
  353.                     list[e].gold = list[id].gold;
  354.                     list[id].gold = 0;
  355.                     list[e].trapped = 1;
  356.                 }
  357.                 
  358.                 if (!extensions_overlapfight)
  359.                     monster_step_back (e);
  360.                 
  361.                 cancel_fighting (id);
  362.             }
  363.         }
  364.         
  365.         if (list[id].fighting)
  366.         {    
  367.             // 290 h%=h%-int(1/x2*4*l*rnd(1)+1+pl):ifh%<0then298
  368.             list[e].hit -= my_attack;
  369.             add_hit (list[e].x, list[e].y, my_attack);
  370.  
  371.             if (list[e].hit < 0)
  372.                 player_won (id);
  373.             //  291 ifht<-5thengosub113:print"(home)slain by "x$:goto426
  374.             else if (list[id].hit < -5)
  375.             {
  376.                 player_die (id);
  377.                 
  378.                 message (FPS, slain, "Slain by %s %s",
  379.                     char_prefixes[list[e].type][list[e].subtype],
  380.                     char_names[list[e].type]);
  381.  
  382.                 cancel_fighting(id);
  383.             }    
  384.         }
  385.     }
  386.     else /* We are attacking. */
  387.     {
  388.         // 340 h%=h%-int(1/x*4*l*rnd(1)+1+pl):ifh%<0then346
  389.         list[e].hit -= my_attack;
  390.         if (list[e].dex)
  391.         {
  392.             add_hit (list[e].x, list[e].y, my_attack);
  393.         }
  394.  
  395.         if (list[e].hit < 0)
  396.         {
  397.             player_won (id);
  398.         }
  399.         else
  400.         {
  401.         // 341 ifs1=1then344
  402.         // 342 ht=ht-int(x*4*l*rnd(1)+1)
  403.         // 343 ifht<-5thenprint"(home)(rvon) (rvof) thou art slain!":goto426
  404.         
  405.             fight_action(e);
  406.  
  407.             if (!list[id].spells[SPELL_SHIELD].active)
  408.             {
  409.                 player_health_add(id, -monster_attack);
  410.                 add_hit (list[id].x, list[id].y, -monster_attack);
  411.                 
  412.                 if (list[id].hit < -5)
  413.                 {
  414.                     player_die (id);
  415.                     message (FPS, slain, "Thou art slain!");
  416.                     cancel_fighting (id);
  417.                 }
  418.             }
  419.         }            
  420.     }
  421. }
  422.  
  423. void
  424. player_roll (int *health, int *skill)
  425. {
  426.     int i;
  427.     /*
  428.     - Hah! I new it! Initial roll for the player's stats (3d6):
  429.  
  430.             443 fori=1to3:ht=ht+int(6*rnd(1)+1):bs=bs+int(6*rnd(1)+1):next
  431.             444 sr=1:th=ht:ep=200:k=32:hp=1:tp=1:t1=100:ql=int(5*rnd(1)+15)
  432.     - Quest Level is assigned in 'ql' above
  433.     */
  434.     *health = 0;
  435.     *skill = 0;
  436.     for (i = 0; i < 3; i++)
  437.     {
  438.         *health += rnd (1, 6);
  439.         *skill += rnd (1, 6);
  440.     }
  441. }
  442.  
  443. int
  444. player_create (int x, int y, int health, int skill)
  445. {
  446.     int id = char_create (x, y);
  447.  
  448.     list[id].type = CHAR_HERO;
  449.     list[id].hit = health;
  450.     list[id].dex = skill;
  451.     list[id].maxhit = list[id].hit;
  452.     list[id].next = 200;
  453.     list[id].potions = 1;
  454.     list[id].spells[SPELL_TELEPORT].amount = 1;
  455.     
  456.     return id;
  457. }
  458.  
  459. static void
  460. player_treasure (int id)
  461. {
  462.     //  227 r=int(9*rnd(1)+1):onrgoto236,243,228,245,247,247,247,247,247
  463.     int w = rnd (1, 9);
  464.     int x = list[id].x;
  465.     int y = list[id].y;
  466.     
  467.     map_put_spot (x, y, SPOT_FLOOR);
  468.     
  469.     switch (w)
  470.     {
  471.         case 1:
  472.             // 236 p1=0:pokev3,peek(v3)and254:print"(home)pit!!...you fell!"
  473.             // 237 h1=int(10*rnd(1)+l):k=61:pokem,k:pokeo,k:cl=1:gosub148:goto262
  474.             // 238 p$="down":p1=1:p2=k:k=62:pt=int(4*rnd(1)+2)
  475.             // 239 z=pt*p1:l=l+z:pokeo,p2:gosub113:print"(home)climbing the pit...";
  476.             message (FPS, pit, "Pit!!... You fell!");
  477.             map_put_spot (x, y, SPOT_PIT);
  478.             map_put_info(x, y, rnd(2, 5));
  479.             list[id].trapped = SPOT_PIT;
  480.             break;
  481.         case 2:
  482.             //  243 pokev3,peek(v3)and254:print"(home)ceiling trap!"
  483.             //  244 h1=int(10*rnd(1)+l):k=59:pokem,k:pokeo,k:gosub156:cl=1:goto262
  484.             message (FPS, pit, "Ceiling trap!");
  485.             map_put_spot (x, y, SPOT_CEILING);
  486.             list[id].trapped = SPOT_CEILING;
  487.             break;
  488.         case 3:
  489.             //  228 print"(home)explosion!!":pokes5,10:pokes6,42:pokes3,1:pokeso,12:pokes5+7,10:pokes6+7,42
  490.             message (FPS, boom, "Explosion!!");
  491.     
  492.             if (list[id].spells[SPELL_SHIELD].active)
  493.             {
  494.                 //  234 s1=0:print"(home)shielded from blast!":gosub112
  495.                 list[id].spells[SPELL_SHIELD].active--;
  496.                 message (FPS, NULL, "Shielded from blast!");
  497.             }
  498.             else
  499.             {
  500.                 // C64: 233 next:ifs1=0thenht=ht-int(15*rnd(1)+l):cl=1:goto235
  501.                 int h = rnd (0, 14)+list[1].current_level;
  502.     
  503.                 player_health_add(id, -h);
  504.                 add_hit (list[id].x, list[id].y, -h);
  505.                 try_lose_map(id);
  506.             }
  507.             break;
  508.         case 4:
  509.             //  245 print"(home)teleport...":k=32:pokem,k:pokeo,k:gosub144:o=n-d%:pokeo,a:pokeo+cm,1
  510.             message (FPS, teleport, "Teleport...");
  511.             char_teleport (id);
  512.             try_lose_map(id);
  513.             break;
  514.         case 5:
  515.         case 6:
  516.         case 7:
  517.         case 8:
  518.         case 9:
  519.         {
  520.             //  247 w%=2:gosub175:e=e+int(50*rnd(1)+l):k=32:pokem,k:x=int(15*rnd(1)+1)
  521.             //  248 onxgoto250,251,250,249,251,252,257,253,254,255,259,252,257,258,260
  522.             list[id].exp += rnd (0, 49) + list[id].current_level;
  523.             w = rnd (1, 15);
  524.             switch (w)
  525.             {
  526.                 case 1:
  527.                 case 2:
  528.                     //  250 print"(home)healing potion!!":hp=hp+1:goto274
  529.                     message (FPS, item, "Healing potion!!");
  530.                     list[id].potions++;
  531.                     break;
  532.                 case 3:
  533.                 case 4:
  534.                     //  251 print"(home)magic sack!!":bg=bg+1:t1=t1+100:goto274
  535.                     message (FPS, item, "Magic sack!!");
  536.                     list[id].sacks++;
  537.                     break;
  538.                 case 5:
  539.                     /* Played some more, and still spent time in the temple
  540.                        healing in level 8. So now you can get amulets, at most
  541.                        one after every 8 levels, and only a 1:2 chance instead
  542.                        of a regeneration spell. The effect is just like a
  543.                        permanent regeneration spell. */
  544.                     if (extensions_balance &&
  545.                         list[id].current_level > 8 * (1 + list[id].amulets_of_healing) &&
  546.                         !rnd (0, 2))
  547.                     {
  548.                         message (FPS, item, "Amulet of Healing!!");
  549.                         list[id].amulets_of_healing++;
  550.                     }
  551.                     else
  552.                     {
  553.                         //  249 print"(home)regeneration spell!!":rg=rg+1:goto274
  554.                         message (FPS, item, "Regeneration spell!!");
  555.                         list[id].spells[SPELL_REGENERATION].amount++;
  556.                     }
  557.                     break;
  558.                 case 6:
  559.                 case 7:
  560.                     //  252 print"(home)shield spell!!":sh=sh+1:goto274
  561.                     message (FPS, item, "Shield spell!!");
  562.                     list[id].spells[SPELL_SHIELD].amount++;
  563.                     break;
  564.                 case 8:
  565.                 case 9:
  566.                     //  257 print"(home)teleport spell!!":tp=tp+1:goto274
  567.                     message (FPS, item, "Teleport spell!!");
  568.                     list[id].spells[SPELL_TELEPORT].amount++;
  569.                     break;
  570.                 case 10:
  571.                     /* Since I added a healing amulet, thought could as well
  572.                        add a light amulet. This is very unlikely to obtain right
  573.                        now though (one per 15 levels, and 25% chance instead of
  574.                        a spell. The effect is a permanent light spell. */
  575.                     if (extensions_balance &&
  576.                         list[id].current_level > 15 * (1 + list[id].amulets_of_light) &&
  577.                         !rnd (0, 3))
  578.                     {
  579.                         message (FPS, item, "Amulet of Light!!");
  580.                         list[id].amulets_of_light++;
  581.                     }
  582.                     else
  583.                     {
  584.                         //   253 print"(home)light spell!!":lg=lg+1:goto274
  585.                         message (FPS, item, "Light spell!!");
  586.                         list[id].spells[SPELL_LIGHT].amount++;
  587.                     }
  588.                     break;
  589.                 case 11:
  590.                     //  254 print"(home)enchanted weapon!!":pl=pl+1:bs=bs+int(10*rnd(1)+5):goto274
  591.                     message (FPS, item, "Enchanted weapon!!");
  592.                     list[id].weapon++;
  593.                     list[id].dex+=rnd(0, 9)+5;
  594.                     break;
  595.                 case 12:
  596.                     //  255 x=int(8*rnd(1)+l+3):print"(home)map to"x"th level!!"
  597.                     //  256 tm=tm+1:t%(tm)=x:goto274
  598.                     {
  599.                         int m = list[id].current_level + rnd (3, 10);
  600.                         
  601.                         if(m==list[id].current_level)
  602.                         {
  603.                             message(FPS, item, "Treasure Map!!");
  604.                             map_seen (20, 12, 20);
  605.                         }
  606.                         else
  607.                         {
  608.                             message (FPS, item, "Map to %ith level!!!", m);
  609.                             list[id].map |= (1 << m);
  610.                         }
  611.                         break;
  612.                     }
  613.                 case 13:
  614.                     //  259 print"(home)invisibility spell!!":iv=iv+1:goto274
  615.                     message (FPS, item, "Invisibility spell!!");
  616.                     list[id].spells[SPELL_INVISIBILITY].amount++;
  617.                     break;
  618.                 case 14:
  619.                     //  258 print"(home)drift spell!!":fa=fa+1:goto274
  620.                     message (FPS, item, "Drift spell!!");
  621.                     list[id].spells[SPELL_DRIFT].amount++;
  622.                     break;
  623.                 case 15:
  624.                     //   260 print"(home)beacon!!":be=be+1:goto274
  625.                     message (FPS, item, "Beacon!!");
  626.                     list[id].beacons++;
  627.                     break;        
  628.             }
  629.             break;
  630.         }
  631.     }
  632. }
  633.  
  634.  
  635. static void climb_pit(int id)
  636. {
  637.     int x = list[id].x;
  638.     int y = list[id].y;
  639.  
  640.     int downsteps = map_get_info (x, y);
  641.  
  642.     /* C64:
  643.     238 p$="down":p1=1:p2=k:k=62:pt=int(4*rnd(1)+2)
  644.     239 z=pt*p1:l=l+z:pokeo,p2:gosub113:print"(home)climbing the pit...";
  645.     240 pokev3,peek(v3)and254:w1=int(2*rnd(1)+1):gosub171:y=int(2*rnd(1))
  646.     241 ify=1thenprint"you fell!":h1=int(10*rnd(1)+3*pt+l):gosub148:goto261
  647.     */
  648.  
  649.     list[id].current_level += downsteps;
  650.     message (FPS, climb, "Climbing the pit...");
  651.     if (!rnd (0, 1))
  652.     {
  653.         list[id].trapped = SPOT_PIT;
  654.         message (0, pit, NULL);
  655.     }
  656.     map_enter (SPOT_ROPE, downsteps);
  657. }
  658.  
  659.  
  660. static void
  661. player_action (int id)
  662. {
  663.     int x = list[id].x;
  664.     int y = list[id].y;
  665.     int spot;
  666.     
  667.     /*
  668.         During fighting, try to teleport away. 
  669.         302 iftp>0then305
  670.         303 ifsh>0ands1=0thensh=sh-1:s1=1:gosub113:print"(home)thy shield is in         
  671.         - This is only if attacked
  672.         - Shield will be used if there's no teleport
  673.     */
  674.     if (list[id].attacked)
  675.     {
  676.         if(!spell_cast (id, SPELL_TELEPORT))
  677.         {
  678.             if(!spell_cast(id, SPELL_SHIELD))
  679.             {
  680.                 play_sample (ding, 250, 128, 1000, 0);
  681.                 return;
  682.             }
  683.         }
  684.         else
  685.         {
  686.             // So that we can't cast both spells by accident
  687.             list[id].attacked=0;
  688.         }
  689.         
  690.         return;
  691.     }
  692.  
  693.     if (list[id].trapped==SPOT_PIT)
  694.     {
  695.         if(!spell_cast (id, SPELL_DRIFT))
  696.             play_sample (ding, 250, 128, 1000, 0);
  697.         return;
  698.     }
  699.     else if (list[id].trapped==SPOT_CEILING)
  700.     {
  701.         if(!spell_cast (id, SPELL_TELEPORT))
  702.             play_sample (ding, 250, 128, 1000, 0);
  703.         return;
  704.     }
  705.  
  706.     spot=map_get_spot (x, y);
  707.     
  708.     if(paused)
  709.     {
  710.         if(spot==SPOT_FLOOR)
  711.         {
  712.             play_sample (ding, 250, 128, 1000, 0);
  713.             pass_key=TRUE;
  714.         }
  715.         return;
  716.     }
  717.  
  718.     switch (spot)
  719.     {
  720.         default:
  721.             play_sample (ding, 250, 128, 1000, 0);
  722.             pass_key=TRUE;
  723.             break;
  724.  
  725.         case SPOT_DOWN:
  726.  
  727.             list[id].current_level++;
  728.             message (FPS, down, "You go down the stairs.");
  729.             map_enter (SPOT_UP, 1);
  730.             break;
  731.         case SPOT_UP:
  732.             if (list[id].current_level == 1)
  733.             {
  734.                 if (swordrun && list[id].sword)
  735.                 {
  736.                     // 111 print"(clr)(down)(down)(down)(down)(down)(down)(down)(down)(down)(down)        your quest is complete!!":gosub201:goto412
  737.                     message (FPS * 4, intro, "Your quest is complete!!");
  738.                     won = 1;
  739.                 }
  740.                 else
  741.                 {
  742.                     message (FPS, NULL, "Not without the Sword of Fargoal!");
  743.                 }
  744.             }
  745.             else
  746.             {
  747.                 list[id].current_level--;
  748.                 message (FPS, up, "You go up the stairs.");
  749.                 map_enter (SPOT_DOWN, 1);
  750.             }
  751.             break;
  752.         case SPOT_ROPE:
  753.         {
  754.             int upsteps = map_get_info (x, y);
  755.  
  756.             list[id].current_level -= upsteps;
  757.             message (FPS, climb, "Climbing the rope...");
  758.             map_enter (SPOT_PIT, upsteps);
  759.             break;
  760.         }
  761.         case SPOT_PIT:
  762.         {
  763.             climb_pit(id);
  764.             break;
  765.         }
  766.         case SPOT_BEACON:
  767.             //   92 ifk=44thenpokeo,k:k=38:o=b3:pokeo,a:pokeo+cm,1:gosub108:gosub146:gosub113:goto117
  768.             message (FPS, teleport, NULL);
  769.             char_transfer_to (id, temple_x, temple_y);
  770.             break;
  771.     
  772.         case SPOT_TREASURE:
  773.             player_treasure (id);
  774.             break;
  775.     }
  776. }
  777.  
  778. static void
  779. player_in_trap (int id)
  780. {
  781.     int x = list[id].x;
  782.     int y = list[id].y;
  783.     int s = map_get_spot (x, y);
  784.     if (s == SPOT_PIT || s == SPOT_ROPE)
  785.     {
  786.         if (!list[id].spells[SPELL_DRIFT].active)
  787.         {
  788.             int h;
  789.  
  790.             if (s == SPOT_PIT)
  791.             {
  792.                 //  237 h1=int(10*rnd(1)+l):k=61:pokem,k:pokeo,k:cl=1:gosub148:goto262
  793.                 h = rnd(0, 9)+list[id].current_level;
  794.                 message (FPS, human[0], NULL);
  795.             }
  796.             else
  797.             {
  798.                 //  241 ify=1thenprint"you fell!":h1=int(10*rnd(1)+3*pt+l):gosub148:goto261
  799.                 int upsteps = map_get_info (x, y);
  800.                 h = rnd (0, 9) + 3 * upsteps + list[id].current_level;
  801.                 message (FPS, human[0], "You fell!");
  802.             }
  803.  
  804.             player_health_add(id, -h);
  805.             add_hit (list[id].x, list[id].y, -h);
  806.         }
  807.         else
  808.         {
  809.             list[id].spells[SPELL_DRIFT].active--;
  810.             message (FPS, NULL, "like a feather...");
  811.         }
  812.     }
  813.     /* Crushing ceiling. */
  814.     if (s == SPOT_CEILING)
  815.     {
  816.         if (!list[id].spells[SPELL_TELEPORT].active)
  817.         {
  818.             /* C64:
  819.                 244 h1=int(10*rnd(1)+l):k=59:pokem,k:pokeo,k:
  820.                     gosub156:cl=1:goto262
  821.             */
  822.  
  823.             int h = rnd (0, 9)+list[id].current_level;
  824.  
  825.             message (FPS, crunch, NULL);
  826.             player_health_add(id, -h);
  827.             add_hit (list[id].x, list[id].y, -h);
  828.  
  829.             try_lose_map(id);
  830.         }
  831.         else
  832.         {
  833.             list[id].spells[SPELL_TELEPORT].active--;
  834.             char_teleport (1);
  835.             message (FPS, NULL, "Teleport to safety!");
  836.         }
  837.     }
  838. }
  839.  
  840. void
  841. player_try_levelup (int id)
  842. {
  843.     /* C64: Level up
  844.        119 ep=ep*2:el=el+1:th=th+int(15*rnd(1)+5):bs=bs+int(10*rnd(1)+1)
  845.        - Implemented
  846.      */
  847.     if (list[id].exp >= list[id].next)
  848.     {
  849.         float percentage = (float)list[id].hit / (float)list[id].maxhit;
  850.         list[id].lev++;
  851.         list[id].maxhit += rnd (1, 15)+4;
  852.         list[id].dex += rnd (1, 10);
  853.         if (extensions_balance)
  854.             list[id].hit = percentage * list[id].maxhit + 0.5;
  855.         
  856.         list[id].next *= 2;
  857.         message (FPS, levelup, "Gained a level!");
  858.         //printf ("maxhit = %i skill = %i\n", list[id].maxhit, list[id].dex);
  859.     }
  860. }
  861.  
  862. void
  863. player_die (int id)
  864. {
  865.     (void) id;
  866.     gameover = 1;
  867.     spiral_map = MAP_W * MAP_H / 2;
  868. }
  869.  
  870. void
  871. player_process (int id)
  872. {
  873.     int x = list[id].x;
  874.     int y = list[id].y;
  875.     int i;
  876.  
  877.     /* Keyboard state. */
  878.     int dir_x = 0;
  879.     int dir_y = 0;
  880.  
  881. #if defined(_DEBUG) || defined(DEBUGMODE)
  882.  
  883.     if (key[KEY_0])
  884.     {
  885.         player_health_add(id, -list[id].hit);;
  886.     }
  887.  
  888.     if (key[KEY_1])
  889.     {
  890.         list[id].spells[SPELL_SHIELD].amount=1;
  891.         list[id].spells[SPELL_TELEPORT].amount=1;
  892.         list[id].spells[SPELL_DRIFT].amount=1;
  893.         list[id].spells[SPELL_LIGHT].amount=1;
  894.         list[id].spells[SPELL_REGENERATION].amount=1;
  895.         list[id].spells[SPELL_INVISIBILITY].amount=1;
  896.         list[id].beacons++;
  897.         list[id].potions++;
  898.         list[id].gold+=50;
  899.         list[id].dex=400;
  900.         list[id].maxhit++;
  901.         list[id].hit=list[id].maxhit;
  902.         update_stats();
  903.     }
  904.     
  905.     if (key[KEY_2])
  906.     {
  907.         list[id].current_level=20;
  908.         list[id].hit=list[id].maxhit;
  909.         update_stats();
  910.     }
  911.     
  912.     if (key[KEY_3])
  913.     {
  914.         map_seen (20, 12, 20);
  915.     }
  916.     
  917.     if (key[KEY_4])
  918.     {
  919.         list[id].sword = 1;
  920.         swordrun = SWORD_TIME;
  921.     }
  922.     
  923.     if (key[KEY_5])
  924.     {
  925.         list[id].amulets_of_healing = 1;
  926.         list[id].amulets_of_light = 1;
  927.         update_stats();
  928.     }
  929.     
  930.     if (key[KEY_6])
  931.     {
  932.         list[id].amulets_of_healing = 0;
  933.         list[id].amulets_of_light = 0;
  934.         update_stats();
  935.     }
  936.  
  937. #endif
  938.  
  939.  
  940.     if (check_key_ex(KEY_LEFT, TRUE))
  941.     {
  942.         dir_x = -1;
  943.     }
  944.     if (check_key_ex(KEY_RIGHT, TRUE))
  945.     {
  946.         dir_x = 1;
  947.     }
  948.     if (check_key_ex(KEY_UP, TRUE))
  949.     {
  950.         dir_y = -1;
  951.     }
  952.     if (check_key_ex(KEY_DOWN, TRUE))
  953.     {
  954.         dir_y = 1;
  955.     }
  956.  
  957.     /* Check spell keys. */
  958.     for (i = 0; i < 6; i++)
  959.     {
  960.         static int spellkeys[] = { KEY_I, KEY_R, KEY_T, KEY_S, KEY_L, KEY_D };
  961.  
  962.         if (check_key (spellkeys[i]))
  963.         {
  964.             if (!spell_cast (id, i))
  965.                 play_sample (ding, 250, 128, 1000, 0);
  966.         }
  967.     }
  968.  
  969.     if (check_key (KEY_B))
  970.     {
  971.         //  54 ifa$="+"andbe>0andb1=0thenbe=be-1:b1=1:k=44:b2=o:pokeo+d%,k:gosub113:print"(home)thy beacon is placed!":gosub150:goto40
  972.         if (list[id].beacons && list[id].beaconx == 0 && list[id].beacony == 0)
  973.         {
  974.             if (map_get_spot (x, y) == SPOT_FLOOR)
  975.             {
  976.                 map_put_spot (x, y, SPOT_BEACON);
  977.                 list[id].spells[SPELL_INVISIBILITY].active++;
  978.                 list[id].beacons--;
  979.                 list[id].beaconx = x;
  980.                 list[id].beacony = y;
  981.                 message (FPS, beacon, "Thy beacon is placed!");
  982.             }
  983.             else
  984.             {
  985.                 message (FPS, ding, "Cannot place beacon here");
  986.             }
  987.         }
  988.         else
  989.             play_sample (ding, 250, 128, 1000, 0);
  990.     }
  991.  
  992.     if (check_key (KEY_H))
  993.     {
  994.         if (!drink_potion(id))
  995.         {
  996.             play_sample (ding, 250, 128, 1000, 0);
  997.         }
  998.  
  999.     }
  1000.  
  1001.     if (check_key (KEY_LCONTROL) || check_key (KEY_RCONTROL) || 
  1002.         check_key (KEY_SPACE) || check_key (KEY_ENTER))
  1003.     {
  1004.         player_action (id);
  1005.     }
  1006.     
  1007.     if (check_key (KEY_O))
  1008.     {
  1009.         //  121 gosub113:ifl1=1thenl1=2:print"(home)light off":gosub112:goto42
  1010.           //  122 l1=1:gosub211:print"(home)light on":gosub112:goto42
  1011.         if (list[id].spells[SPELL_LIGHT].active)
  1012.         {
  1013.             list[id].spells[SPELL_LIGHT].active = -list[id].spells[SPELL_LIGHT].active;
  1014.             if (list[id].spells[SPELL_LIGHT].active > 0)
  1015.                 message (FPS, NULL, "Light on");
  1016.             if (list[id].spells[SPELL_LIGHT].active < 0)
  1017.                 message (FPS, NULL, "Light off");
  1018.         }
  1019.         else
  1020.             play_sample (ding, 250, 128, 1000, 0);
  1021.     }
  1022.     
  1023.     if (check_key (KEY_G))
  1024.     {
  1025.         //  124 ifgd>9ork<>32then41
  1026.         //  125 gd=gd+1:k=60:pokeo+d%,k:g%(gd)=t:l%(gd)=o:gosub113
  1027.         //  126 print"(home)hiding"t"gold pieces":t=0:gosub112:goto42
  1028.         if (list[id].gold)
  1029.         {
  1030.             if (map_get_spot (x, y) == SPOT_FLOOR)
  1031.             {
  1032.                 message (FPS, NULL, "Hiding %i gold pieces", list[id].gold);
  1033.                 map_put_spot (x, y, SPOT_STASH);
  1034.                 map_put_info (x, y, list[id].gold);
  1035.                 list[id].gold = 0;
  1036.             }
  1037.             else
  1038.             {
  1039.                 message (FPS, ding, "Cannot bury gold here");
  1040.             }
  1041.         }
  1042.         else
  1043.             play_sample (ding, 250, 128, 1000, 0);
  1044.     }
  1045.  
  1046.     healing (id);
  1047.  
  1048.     /* Game is currently paused. */
  1049.     if (paused)
  1050.     {
  1051.         paused--;
  1052.         char_move (id, 0, 0);
  1053.  
  1054.         if (paused == 0)
  1055.         {
  1056.             if (list[id].trapped)
  1057.             {
  1058.                 player_in_trap(id);
  1059.                 list[id].trapped = 0;
  1060.             }
  1061.         }
  1062.     }
  1063.     else                        /* Not paused. */
  1064.     {
  1065.         if (!extensions_nomonsterpause)
  1066.         {
  1067.             if(!global_steps)
  1068.             {
  1069.                 dir_x = dir_y = 0;
  1070.             }
  1071.         }
  1072.         
  1073.         // See if player is trying to escape, and was not attacked
  1074.         if (!list[id].attacked)
  1075.         {
  1076.             char_move (id, dir_x, dir_y);
  1077.         }
  1078.         
  1079.         if (!paused && !list[id].step)
  1080.         {
  1081.             // 114 ifhp>0then60
  1082.               // 115 gosub113:print"(home)(rvon) (rvof) you died!!":goto426
  1083.  
  1084.             /* Teleport spell? */
  1085.             if (list[id].spells[SPELL_TELEPORT].active)
  1086.             {
  1087.                 char_teleport (id);
  1088.                 cancel_fighting (id);
  1089.                 list[id].spells[SPELL_TELEPORT].active--;
  1090.             }
  1091.  
  1092.             /* Dead? */
  1093.             if (list[id].hit < 0)
  1094.             {
  1095.                 if (!drink_potion(id))
  1096.                 {
  1097.                     player_die (id);
  1098.                     message (FPS, slain, "You died!!");
  1099.                     return;
  1100.                 }
  1101.             }
  1102.  
  1103.             if (list[id].fighting)
  1104.                 player_fight (id);
  1105.         }
  1106.  
  1107.         player_try_levelup (id);
  1108.     }
  1109. }
  1110.  
  1111.  
  1112. void
  1113. player_leave (int id)
  1114. {
  1115.     int x = list[id].x;
  1116.     int y = list[id].y;
  1117.         
  1118.     switch (map_get_spot (x, y))
  1119.     {
  1120.         default:
  1121.             break;
  1122.         case SPOT_BEACON:
  1123.           list[id].spells[SPELL_INVISIBILITY].active--;
  1124.           update_stats();
  1125.         break;
  1126.     }
  1127. }
  1128.  
  1129. void
  1130. player_change_position (int id)
  1131. {
  1132.     int x = list[id].x;
  1133.     int y = list[id].y;
  1134.     int r = 1 + list[id].spells[SPELL_LIGHT].active + list[id].amulets_of_light;
  1135.     int spot;
  1136.  
  1137.     if (r < 1)
  1138.         r = 1;
  1139.  
  1140.     map_seen (x, y, r);
  1141.  
  1142.     play_sample (step, 250, 128, 1000, 0);
  1143.  
  1144.     if (extensions_nomonsterpause && global_steps)
  1145.     {
  1146.         global_steps--;
  1147.         stepcount = (extensions_speed ? FPS : FPS*2);
  1148.     }
  1149.  
  1150.     spot=map_get_spot (x, y);
  1151.  
  1152.     // TODO: if Pass key, clear key and return
  1153.     if(pass_key&&spot!=SPOT_FLOOR&&spot!=SPOT_VOID)
  1154.     {
  1155.         pass_key=FALSE;
  1156.         return;
  1157.     }
  1158.  
  1159.     switch (spot)
  1160.     {
  1161.         default:
  1162.             break;
  1163.         
  1164.         case SPOT_TREASURE:
  1165.             if(!extensions_controls)
  1166.                 player_treasure (id);
  1167.             break;
  1168.  
  1169.         case SPOT_DOWN:
  1170.             message (FPS / 2, down, "Stairs going down");
  1171.             break;
  1172.         case SPOT_UP:
  1173.             message (FPS / 2, up, "Stairs going up");
  1174.             break;
  1175.  
  1176.         case SPOT_PIT:
  1177.             if(extensions_controls)
  1178.                 message (FPS / 2, NULL, "Pit!");
  1179.             else
  1180.                 climb_pit(id);
  1181.             break;
  1182.  
  1183.         case SPOT_ROPE:
  1184.             message (FPS / 2, NULL, "Climbable pit above!");
  1185.             break;
  1186.         case SPOT_CEILING:
  1187.             message (FPS / 2, NULL, "hole in the ceiling!");
  1188.             break;
  1189.         case SPOT_BEACON:
  1190.             message (FPS * 2, beacon, "Swirling mists surround you!");
  1191.             /* Get invisible on beacon. */
  1192.             list[id].spells[SPELL_INVISIBILITY].active++;
  1193.             break;
  1194.         case SPOT_SWORD:
  1195.             //   94 gosub113:print"(home)the sword of fargoal!!":gosub201:sf=1:k=32:pokem,k:ift2=0thene=e*2:t2=ti
  1196.                //   95 goto274
  1197.             list[id].sword++;
  1198.             if (swordrun == 0)
  1199.             {
  1200.                 list[id].exp *= 2;
  1201.                 swordrun = SWORD_TIME;
  1202.             }
  1203.             message (FPS * 4, intro, "The Sword of Fargoal!!");
  1204.             map_put_spot (x, y, SPOT_FLOOR);
  1205.             break;
  1206.         case SPOT_GOLD:
  1207.         {
  1208.             // 216 y=int(20*rnd(1)+10*l):print"(home)treasure: "y"gp's":gosub165:ift+y>t1then218
  1209.             // 217 t=t+y:k=32:pokem,k:goto40
  1210.             // 218 ifgd>9then40
  1211.             // 219 gd=gd+1:k=60:pokem,k:g%(gd)=t+y-t1:l%(gd)=o:ift=t1then221
  1212.             // 220 t=t1:print"(home)can't carry more gold":goto274
  1213.             // 221 print"(home)hiding the gold      ":goto274
  1214.             int max = 100 + list[id].sacks * 100;
  1215.             int g = 10 * list[id].current_level + rnd (0, 19);
  1216.             
  1217.             //if(extensions_controls && max <= list[id].gold)
  1218.             //    break;
  1219.             
  1220.             message (FPS, gold, "Treasure: %i GP's", g);
  1221.  
  1222.             if (list[id].gold + g <= max)
  1223.             {
  1224.                 map_put_spot (x, y, SPOT_FLOOR);
  1225.                 list[id].gold += g;
  1226.             }
  1227.             else
  1228.             {
  1229.                 map_put_spot (x, y, SPOT_STASH);
  1230.                 map_put_info (x, y, list[id].gold + g - max);
  1231.                 if (list[id].gold < max)
  1232.                 {
  1233.                     list[id].gold= max;
  1234.                     message (FPS/2, NULL, "Can't carry more gold");
  1235.                 }
  1236.                 else
  1237.                 {
  1238.                     message (FPS/2, NULL, "Hiding the gold");
  1239.                 }
  1240.             }
  1241.             break;
  1242.         }
  1243.         case SPOT_STASH:
  1244.         {
  1245.             //  222 print"(home)hidden treasure!!":gosub165:forj=1togd:ifo=l%(j)thenv=j:j=gd
  1246.               //  223 next
  1247.             //  224 z=g%(v):ift+z>t1then226
  1248.             //  225 t=t+z:k=32:pokem,k:goto40
  1249.             //  226 g%(v)=t+z-t1:t=t1:gosub113:print"(home)gold too heavy":goto274
  1250.             int max = 100 + list[id].sacks * 100;
  1251.             int g = map_get_info (x, y);
  1252.  
  1253.             if(max<=list[id].gold)
  1254.                 break;
  1255.  
  1256.             message (FPS / 2, gold, "Hidden Treasure!!");
  1257.  
  1258.             if (list[id].gold + g <= max)
  1259.             {
  1260.                 list[id].gold += g;
  1261.                 map_put_spot (x, y, SPOT_FLOOR);
  1262.             }
  1263.             else
  1264.             {
  1265.                 map_put_info (x, y, list[id].gold + g - max);
  1266.                 list[id].gold= max;
  1267.                 message (FPS/2, NULL, "Gold too heavy");
  1268.             }
  1269.             break;
  1270.         }
  1271.         case SPOT_TEMPLE:
  1272.             if (list[id].gold)
  1273.             {
  1274.                 message (FPS, sacrifice, "Sacrifice of gold!");
  1275.                 list[id].exp += list[id].gold;
  1276.                 if (extensions_balance)
  1277.                 {
  1278.                     {
  1279.                         list[id].sacrificed_gold+=list[id].gold;
  1280.                         if(list[id].sacrificed_gold>=TEMPLE_GOLD &&
  1281.                             list[id].hit<list[id].maxhit)
  1282.                         {
  1283.                             list[id].sacrificed_gold-=TEMPLE_GOLD;
  1284.                             player_health_add(id, list[id].maxhit);
  1285.                             message (FPS, item, "You are blessed!");
  1286.                         }
  1287.                         
  1288.                         /*
  1289.                             PP: I wonder if we should still add faster temple
  1290.                             healing, perhaps with regeneration... so that 
  1291.                             regen + temple is quite fast
  1292.                         */
  1293.  
  1294.                     }
  1295.                 }
  1296.                 list[id].gold = 0;
  1297.             }
  1298.             else
  1299.             {
  1300.                 message (FPS/2, NULL, "Temple!");
  1301.             }
  1302.             break;
  1303.     }
  1304. }
  1305.