/
clans/
include/CVS/
manual/CVS/
races/CVS/
system/CVS/
text/
text/CVS/
todo/
todo/CVS/
units/CVS/
procedure do_bash(ch:GCharacter;param:string);
var chance:integer;
    vict:GCharacter;
begin
  if (ch.learned[gsn_bash] = 0) then
    begin
    ch.sendBuffer('You don''t know how to bash!'#13#10);
    exit;
    end;

  if (length(param) = 0) and (ch.position <> POS_FIGHTING) then
    begin
    act(AT_REPORT,'Bash whom?',false,ch,nil,nil,TO_CHAR);
    exit;
    end;

  if (ch.position = POS_BASHED) then
    begin
    ch.sendBuffer('You are bashed and cannot move!'#13#10);
    exit;
    end;

  if (ch.bash_timer > -2) then
    begin
    act(AT_REPORT,'You are still too off-balance from that last bash.',false,ch,nil,nil,TO_CHAR);
    exit;
    end;

  if (ch.bashing > -2) then
    begin
    act(AT_REPORT,'You cannot bash this soon after a bash!',false,ch,nil,nil,TO_CHAR);
    exit;
    end;

  vict := ch.room.findChar(ch, param);

  if (vict = nil) then
   if (ch.position = POS_FIGHTING) and (ch.fighting <> nil) then
    vict := ch.fighting;

  if (vict = nil) then
    ch.sendBuffer('They aren''t here.'#13#10)
  else
  if not in_melee(ch,vict) then
    begin
    act(AT_REPORT,'You aren''t on the front lines of that battle!',false,ch,nil,nil,TO_CHAR);
    exit;
    end
  else
  if (vict = ch) then
    begin
    ch.sendBuffer('You try to bash yourself and fall to the ground!'#13#10);
    act(AT_REPORT,'$n looks silly as $e tries to bash $mself.',false,ch,nil,nil,TO_ROOM);
    end
  else
  if (vict.IS_NPC) and (IS_SET(vict.act_flags, ACT_SPIRIT) or IS_SET(vict.act_flags,ACT_NOBASH)) then
    ch.sendBuffer('You can''t bash that kind of creature!'#13#10)
  else
   with ch do
    begin
    if fighting=nil then
      begin
      if IS_SET(ch.room.flags,ROOM_SAFE) then
        begin
        ch.sendBuffer('A strange force prevents you from attacking.'#13#10);
        exit;
        end
      else
        begin
        fighting:=vict;

        if (not ch.IS_NPC) then
          player^.fightxp:=0;
        end;
      end;
    chance:=ch.learned[gsn_bash];
    if (vict.bash_timer>0) then
      act(AT_REPORT,'$N is already bashed to the ground!',false,ch,nil,vict,TO_CHAR)
    else
    if (vict.bash_timer>-2) then
      act(AT_REPORT,'$N is still alert from the last bash.',false,ch,nil,vict,TO_CHAR)
    else
    if number_percent<=chance then
      begin
      improve_skill(ch,gsn_bash);
      vict.position:=POS_BASHED;
      position:=POS_FIGHTING;
      vict.bash_timer:=6;
      bashing:=6;
      if vict.fighting=nil then
        vict.fighting:=ch;
      act(AT_GREEN,'Your powerful bash sends $N sprawling to the ground!',false,ch,nil,vict,TO_CHAR);
      act(AT_GREEN,'$n sends $N sprawling to the ground with a powerful bash!',false,ch,nil,vict,TO_ROOM);
      end
    else
      begin
      ch.setWait(8);

      act(AT_REPORT,'You miss the bash and almost fall over!',false,ch,nil,nil,TO_CHAR);
      act(AT_REPORT,'$n misses a bash at $N and almost falls over!',false,ch,nil,vict,TO_ROOM);
      position:=POS_FIGHTING;
      vict.position:=POS_FIGHTING;
      if vict.fighting=nil then
        vict.fighting:=ch;
      end;
    end;
end;

procedure do_kick(ch:GCharacter;param:string);
var dam,chance:integer;
    vict:GCharacter;
begin
  if (ch.learned[gsn_kick] = 0) then
    begin
    ch.sendBuffer('You don''t know how to kick!'#13#10);
    exit;
    end;

  if (length(param)=0) and (ch.position<>POS_FIGHTING) then
    begin
    act(AT_REPORT,'Kick whom?',false,ch,nil,nil,TO_CHAR);
    exit;
    end;

  if (ch.position = POS_BASHED) then
    begin
    ch.sendBuffer('You are bashed and cannot move!'#13#10);
    exit;
    end;

  if (ch.bash_timer > -2) then
    begin
    act(AT_REPORT,'You are still too off-balance from that last bash.',false,ch,nil,nil,TO_CHAR);
    exit;
    end;

  if (ch.bashing > -2) then
    begin
    act(AT_REPORT,'You cannot kick this soon after a bash!',false,ch,nil,nil,TO_CHAR);
    exit;
    end;

  vict := ch.room.findChar(ch, param);

  if (vict = nil) then
   if (ch.position=POS_FIGHTING) and (ch.fighting<>nil) then
    vict:=ch.fighting;

  if (vict = nil) then
    act(AT_REPORT,'They aren''t here.',false,ch,nil,nil,TO_CHAR)
  else
  if not in_melee(ch,vict) then
    begin
    act(AT_REPORT,'You cannot reach $N!',false,ch,nil,vict,TO_CHAR);
    exit;
    end
  else
  if (vict = ch) then
    ch.sendBuffer('Painfully, you force your knee to bend in a way it isn''t supposed to.'#13#10)
  else
   with ch do
    begin
    if point.mv<12 then
      begin
      ch.sendBuffer('You don''t have enough energy to kick.'#13#10);
      exit;
      end;

    if (vict.CHAR_DIED) then
      exit;

    if fighting=nil then
      begin
      if IS_SET(ch.room.flags,ROOM_SAFE) then
        begin
        ch.sendBuffer('A strange force prevents you from attacking.'#13#10);
        exit;
        end
      else
        begin
        fighting:=vict;

        if (not ch.IS_NPC) then
          player^.fightxp:=0;
        end;
      end;

    ch.setWait(8);

    chance:=ch.learned[gsn_kick];
    if (vict.IS_NPC) and (IS_SET(vict.act_flags,ACT_SPIRIT)) then
      begin
      ch.sendBuffer('You swing your leg and kick high, but it goes right through your victim!'#13#10);

      if vict.fighting=nil then
        vict.fighting:=ch;

      position:=POS_FIGHTING;
      vict.position:=POS_FIGHTING;
      end
    else
    if number_percent<=chance then
      begin
      improve_skill(ch,gsn_kick);
      dam:=urange(1,rolldice(4,18),level div 6)*3;
      inc(dam,ch.point.apb);
      dam:=(dam*ch.ability.str) div 50;
      damage(ch,ch.fighting,dam,gsn_kick);
      end
    else
      damage(ch,ch.fighting,0,gsn_kick);
    end;
end;

procedure do_fly(ch:GCharacter;param:string);
begin
  if (ch.IS_FLYING) then
    ch.stopFlying
  else
    ch.startFlying;
end;

procedure do_sneak(ch:GCharacter;param:string);
begin
  if IS_SET(ch.aff_flags,AFF_SNEAK) then
    begin
    ch.sendBuffer('You no longer sneak.'#13#10);
    REMOVE_BIT(ch.aff_flags,AFF_SNEAK);
    end
  else
    begin
    ch.sendBuffer('You attempt to move silently.'#13#10);
    SET_BIT(ch.aff_flags,AFF_SNEAK);
    end;
end;

procedure do_spells(ch:GCharacter;param:string);
var a:integer;
begin
  with ch do
    begin
    act(AT_REPORT,'Spells learned:'#13#10,false,ch,nil,nil,TO_CHAR);
    for a:=0 to MAX_SKILLS-1 do
     if learned[a]>0 then
      with skill_table[a] do
       if skill_type=SKILL_SPELL then
        act(AT_REPORT,pad_integer(min_mana,2)+'Ma    '+name+' ('+inttostr(learned[a])+'%)',false,ch,nil,nil,TO_CHAR);
    end;
end;

procedure do_skills(ch:GCharacter;param:string);
var a:integer;
begin
  with ch do
    begin
    act(AT_REPORT,'Skills learned:'#13#10,false,ch,nil,nil,TO_CHAR);
    for a:=0 to MAX_SKILLS-1 do
     if learned[a]>0 then
      with skill_table[a] do
       if skill_type<>SKILL_SPELL then
        act(AT_REPORT,'        '+name+' ('+inttostr(learned[a])+'%)',false,ch,nil,nil,TO_CHAR);
    end;
end;

procedure do_learn(ch:GCharacter;param:string);
var sn:integer;
    node : GListNode;
    vict,learn:GCharacter;
begin
  learn := nil;
  node := ch.room.chars.head;

  while (node <> nil) do
    begin
    vict := node.element;

    if (vict.IS_NPC) and (vict.IS_LEARNER) then
      begin
      learn := vict;
      break;
      end;

    node := node.next;
    end;

  if (learn=nil) then
    begin
    ch.sendBuffer('You cannot learn anything here!'#13#10);
    exit;
    end
  else
  if (length(param)=0) then
    begin
    ch.sendBuffer('Skills you can learn here:'#13#10#13#10);

    for sn := 0 to MAX_SKILLS - 1 do
      begin
      if (vict.learned[sn] > 0) and (ch.learned[sn] = 0) then
        act(AT_REPORT, '  (Level $B$4' + pad_integer_front(skill_table[sn].min_lvl, 3) + '$A$7) ' + skill_table[sn].name, false, ch, nil, nil, TO_CHAR);
      end;
    end
  else
    begin
    sn := findSkill(param);

    if (sn = -1) or (vict.learned[sn] = 0) then
      act(AT_REPORT, '$N doesn''t teach this skill.',false,ch,nil,vict,TO_CHAR)
    else
      begin
      if (ch.learned[sn] = 0) then
        begin
        if (skill_table[sn].min_lvl > ch.level) then
          ch.sendBuffer('You have not yet reached the appropiate level.'#13#10)
        else
          begin
          node := skill_table[sn].prereqs.head;
          while (node <> nil) do
            begin
            if (ch.learned[GSkill(node.element).sn] < 50) then
              begin
              ch.sendBuffer('You need to have sufficient knowledge of ' + GSkill(node.element).name + ' first.'#13#10);
              exit;
              end;

            node := node.next;
            end;

          act(AT_REPORT,'You learn '+cap(skill_table[sn].name)+'.',false,ch,nil,nil,TO_CHAR);
          ch.learned[sn]:=20;
          end;
        end
      else
        act(AT_REPORT,'You have already learned that skill.',false,ch,nil,nil,TO_CHAR);
      end;
    end;
end;

procedure do_unlearn(ch:GCharacter;param:string);
var
   sn : integer;
begin
  if (length(param) = 0) then
    begin
    ch.sendBuffer('UNLEARN <skill or spell to unlearn>'#13#10#13#10);
    ch.sendBuffer('This is irreversible, and you won''t get any practice sessions back.'#13#10);
    exit;
    end;

  sn := findSkill(param);

  if (sn = -1) or (ch.learned[sn] = 0) then
    act(AT_REPORT, 'You haven''t learned this skill.',false,ch,nil,nil,TO_CHAR)
  else
    begin
    ch.learned[sn] := 0;
    act(AT_REPORT, 'You have unlearned ' + skill_table[sn].name + '.', false, ch, nil, nil, TO_CHAR);
    end;
end;

procedure do_practice(ch:GCharacter;param:string);
var sn:integer;
    vict,learn:GCharacter;
    node : GListNode;
begin
  learn := nil;
  node := ch.room.chars.head;

  while (node <> nil) do
    begin
    vict := node.element;

    if (vict.IS_NPC) and (vict.IS_LEARNER) then
      begin
      learn := vict;
      break;
      end;

    node := node.next;
    end;

  if (learn=nil) then
    begin
    ch.sendBuffer('You cannot practice anything here!'#13#10);
    exit;
    end
  else
  if (length(param)=0) then
    begin
    ch.sendBuffer('Skills you can practice here:'#13#10#13#10);

    for sn := 0 to MAX_SKILLS - 1 do
      begin
      if (vict.learned[sn] > 0) then
        act(AT_REPORT, '  (Level $B$4' + pad_integer_front(skill_table[sn].min_lvl, 3) + '$A$7) ' + skill_table[sn].name, false, ch, nil, nil, TO_CHAR);
      end;
    end
  else
    begin
    sn := findSkillPlayer(ch,param);

    if (sn <> -1) then
      begin
      if (vict.learned[sn] = 0) then
        act(AT_REPORT, '$N doesn''t teach this skill.', false, ch, nil, vict, TO_CHAR)
      else
      if ch.learned[sn]<50 then
        begin
        inc(ch.learned[sn],8);
        if (ch.learned[sn]>50) then
          begin
          ch.learned[sn]:=50;
          act(AT_REPORT,'You now know enough about '+cap(skill_table[sn].name)+'.',false,ch,nil,nil,TO_CHAR);
          end
        else
          act(AT_REPORT,'You practice '+cap(skill_table[sn].name)+'.',false,ch,nil,nil,TO_CHAR);
        end
      else
        act(AT_REPORT,'You have practiced this skill enough.',false,ch,nil,nil,TO_CHAR);
      end
    else
      act(AT_REPORT,'You have not learned this skill!',false,ch,nil,nil,TO_CHAR);
    end;
end;

procedure search_timer(ch,victim:GCharacter;sn:integer);
var pexit : GExit;
    node : GListNode;
begin
  ch.position := POS_STANDING;
  
  if skill_success(ch,sn) then
    begin
    { check for hidden exits first }
    node := ch.room.exits.head;

    while (node <> nil) do
      begin
      pexit := node.element;

      if (IS_SET(pexit.flags, EX_SECRET)) and (IS_SET(pexit.flags, EX_ISDOOR)) then
        begin
        if (length(pexit.keywords^) > 0) then
          act(AT_REPORT,'You uncover a $d!',false,ch,nil,pexit,TO_CHAR)
        else
          act(AT_REPORT,'You uncover a secret passage '+headings[pexit.direction]+'!',false,ch,nil,nil,TO_CHAR);

        REMOVE_BIT(pexit.flags, EX_SECRET);
        exit;
        end;

      node := node.next;
      end;

    ch.sendBuffer('You look around, but find nothing.'#13#10);
    end
  else
    ch.sendBuffer('You look around, but find nothing.'#13#10);
end;

procedure do_search(ch:GCharacter;param:string);
begin
  ch.sendBuffer('You start searching...'#13#10);

  act(AT_REPORT,'$n looks around, searching for something...',false,ch,nil,nil,TO_ROOM);

  ch.position := POS_SEARCHING;

  registerTimer(TIMER_SEARCH, search_timer, 6, ch, nil, gsn_searching);
end;

procedure backstab_timer(ch,victim:GCharacter;sn:integer);
var roll,to_hit:integer;
    dam:integer;
    wield : GObject;
begin
  if (victim.CHAR_DIED) or (victim.room <> ch.room) or (not ch.CAN_SEE(victim)) then
    begin
    ch.sendBuffer('They are not here.'#13#10);
    ch.position:=POS_STANDING;
    exit;
    end;

  wield := ch.getWield(ITEM_WEAPON);

  to_hit:=ch.point.hitroll + 10;             { +10 bonus because of backstab }

  inc(to_hit,victim.point.ac);
  inc(to_hit,(ch.learned[sn]-50) div 5);
  roll:=rolldice(1,100);
  
  if (roll<=to_hit) and (wield<>nil) then
    begin
    dam:=URange(1,rolldice(wield.value[2],wield.value[3])*(2+ch.level div 15),350);
    act(AT_REPORT,'Your weapon finds its point in $N''s back, causing $S body to spasm.',false,ch,nil,victim,TO_CHAR);
    act(AT_REPORT,'Before you know what happens, $n places $s weapon in your back!',false,ch,nil,victim,TO_VICT);
    act(AT_REPORT,'$n sneaks up behind $N''s back and places $s weapon into $S''s back.',false,ch,nil,victim,TO_NOTVICT);
    if (dam<=25) then
      begin
      act(AT_REPORT,'$N grimaces in pain as your blade pierces $S flesh.',false,ch,nil,victim,TO_CHAR);
      act(AT_REPORT,'You grimace in pain as $n''s blade pierces your flesh.',false,ch,nil,victim,TO_VICT);
      act(AT_REPORT,'$N grimaces in pain as $n''s blade pierces $S flesh.',false,ch,nil,victim,TO_NOTVICT);
      end
    else
    if (dam<=50) then
      begin
      act(AT_REPORT,'$N winces in agony as you stab $M in the back.',false,ch,nil,victim,TO_CHAR);
      act(AT_REPORT,'You wince in agony as $n stabs you in the back.',false,ch,nil,victim,TO_VICT);
      act(AT_REPORT,'$N winces in agony as $n stabs $M in the back.',false,ch,nil,victim,TO_NOTVICT);
      end
    else
    if (dam<=75) then
      begin
      act(AT_REPORT,'As you find a lung and pierce hard, $N cries out in pain!',false,ch,nil,victim,TO_CHAR);
      act(AT_REPORT,'You cry out in pain as $n pierces your lung!',false,ch,nil,victim,TO_VICT);
      act(AT_REPORT,'$N cries out in pain as $n pierces $S lung!',false,ch,nil,victim,TO_NOTVICT);
      end
    else
    if (dam<=100) then
      begin
      act(AT_REPORT,'$N spasms in terrible pain as you plunge your blade into $M.',false,ch,nil,victim,TO_CHAR);
      act(AT_REPORT,'You feel a terrible pain as $n plunges $s blade into you!',false,ch,nil,victim,TO_VICT);
      act(AT_REPORT,'$N spasms in terrible pain as $n plunges $s blade into $M.',false,ch,nil,victim,TO_NOTVICT);
      end
    else
    if (dam<=150) then
      begin
      act(AT_REPORT,'Blood runs over your hands as you forcefully stab $N!',false,ch,nil,victim,TO_CHAR);
      act(AT_REPORT,'You bleed hard as you are forcefully stabbed by $n!',false,ch,nil,victim,TO_VICT);
      act(AT_REPORT,'Blood runs over $n''s hands as $e forcefully stabs $N!',false,ch,nil,victim,TO_NOTVICT);
      end
    else
    if (dam<=200) then
      begin
      act(AT_REPORT,'As you pierce $N''s back, you twist your weapon multiple times!',false,ch,nil,victim,TO_CHAR);
      act(AT_REPORT,'$n pierces your back and twists $s blade multiple times!',false,ch,nil,victim,TO_VICT);
      act(AT_REPORT,'$n pierces $N''s back and twists $s blade multiple times!',false,ch,nil,victim,TO_NOTVICT);
      end
    else
    if (dam<=350) then
      begin
      act(AT_REPORT,'You find a mark in $N''s spine and thrust your blade through!',false,ch,nil,victim,TO_CHAR);
      act(AT_REPORT,'$n targets your spine and thrusts $s blade through!',false,ch,nil,victim,TO_VICT);
      act(AT_REPORT,'$n finds a mark in $N''s spine and thrusts $s blade through!',false,ch,nil,victim,TO_NOTVICT);
      end;
    damage(ch,victim,dam,sn);
    victim.fighting:=ch;
    end
  else
    begin
    act(AT_REPORT,'As you attempt to sneak behind $N''s back, you are uncovered!',false,ch,nil,victim,TO_CHAR);
    act(AT_REPORT,'$n failed to backstab $N!', false,ch,nil,victim,TO_ROOM);
    damage(ch,victim,0,sn);
    victim.fighting:=ch;
    end;
end;

procedure do_backstab(ch:GCharacter;param:string);
var victim:GCharacter;
    wield:GObject;
begin
  if (ch.learned[gsn_backstab] = 0) then
    begin
    ch.sendBuffer('You don''t know how to backstab!'#13#10);
    exit;
    end;

  if (length(param)=0) then
    begin
    ch.sendBuffer('Backstab whom?'#13#10);
    exit;
    end;

  if (ch.position=POS_FIGHTING) then
    begin
    ch.sendBuffer('You cannot backstab while fighting!'#13#10);
    exit;
    end;

  victim := ch.room.findChar(ch, param);

  if (victim=nil) then
    begin
    ch.sendBuffer('They are not here.'#13#10);
    exit;
    end
  else
  if (victim=ch) then
    begin
    ch.sendBuffer('How would you sneak upon yourself?'#13#10);
    exit;
    end;

  wield := ch.getWield(ITEM_WEAPON);

  if (wield=nil) or not (wield.value[4] in [FG_PIERCE,FG_STAB]) then
    begin
    ch.sendBuffer('You must wield a piercing or stabbing weapon.'#13#10);
    exit;
    end;

  ch.sendBuffer('You move stealthily, attempting to get behind your target...'#13#10);
  registerTimer(TIMER_BACKSTAB, backstab_timer, 8, ch, victim, gsn_backstab);
  ch.position:=POS_BACKSTAB;
end;

procedure circle_timer(ch,victim:GCharacter;sn:integer);
begin
  if (victim.CHAR_DIED) or (victim.room<>ch.room) then
    begin
    ch.sendBuffer('They are not here.'#13#10);
    ch.position:=POS_STANDING;
    exit;
    end;
  ch.position:=POS_FIGHTING;
  if (number_percent<=ch.learned[sn]) then
    begin
    act(AT_REPORT,'You succeed in circling your opponent and find yourself behind $M.',false,ch,nil,victim,TO_CHAR);
    backstab_timer(ch,victim,gsn_backstab);
    end
  else
    act(AT_REPORT,'You failed to circle.',false,ch,nil,nil,TO_CHAR);
end;

procedure do_circle(ch:GCharacter;param:string);
var
   wield : GObject;
begin
  if (ch.learned[gsn_circle] = 0) then
    begin
    ch.sendBuffer('You don''t know how to circle!'#13#10);
    exit;
    end;

  if (ch.position<>POS_FIGHTING) then
    begin
    ch.sendBuffer('You are not fighting!'#13#10);
    exit;
    end;

  if (ch.fighting.fighting=ch) then
    begin
    ch.sendBuffer('You are on the frontline and can not circle!'#13#10);
    exit;
    end;

  wield := ch.getWield(ITEM_WEAPON);

  if (wield=nil) or not (wield.value[4] in [FG_PIERCE,FG_STAB]) then
    begin
    ch.sendBuffer('You must wield a piercing or stabbing weapon.'#13#10);
    exit;
    end;

  act(AT_REPORT,'You attempt to circle behind your target...',false,ch,nil,nil,TO_CHAR);
  registerTimer(TIMER_CIRCLE, circle_timer, 10, ch, ch.fighting, gsn_circle);
  ch.position:=POS_CIRCLE;
end;

procedure do_rescue(ch:GCharacter;param:string);
var victim:GCharacter;
begin
  if (ch.learned[gsn_rescue] = 0) then
    begin
    ch.sendBuffer('You don''t know how to rescue!'#13#10);
    exit;
    end;

  if (length(param) = 0) then
    begin
    ch.sendBuffer('Rescue whom?'#13#10);
    exit;
    end;

  if (ch.position=POS_FIGHTING) and (ch.fighting.fighting=ch) then
    begin
    ch.sendBuffer('You are on the frontline and can not rescue!'#13#10);
    exit;
    end;

  victim := ch.room.findChar(ch, param);

  if (victim = nil) then
    begin
    ch.sendBuffer('That is not here!'#13#10);
    exit;
    end;

  if (number_percent <= ch.learned[gsn_rescue]) then
    begin
    act(AT_REPORT,'You rescue $N!',false,ch,nil,victim,TO_CHAR);
    act(AT_REPORT,'$N rescues you!',false,victim,nil,ch,TO_VICT);
    act(AT_REPORT,'$N rescues $n!',false,victim,nil,ch,TO_NOTVICT);

    if (ch.position <> POS_FIGHTING) then
      begin
      ch.fighting := victim.fighting;
      ch.position := POS_FIGHTING;
      end;

    ch.fighting.fighting := ch;
    victim.fighting := nil;
    victim.position := POS_STANDING;
    end
  else
    begin
    act(AT_REPORT,'Your rescue attempt failed.',false,ch,nil,nil,TO_CHAR);

    ch.setWait(3);
    end;
end;

procedure track_timer(ch,victim:GCharacter;sn:integer);
var
   node : GListNode;
   track : GTrack;
begin
  if (not skill_success(ch, gsn_track)) then
    begin
    ch.sendBuffer('You can''t seem to find any tracks.'#13#10);
    exit;
    end;

  node := ch.room.tracks.head;
  track := nil;

  while (node <> nil) do
    begin
    if (GTrack(node.element).who = ch.tracking) and ((track = nil) or (track.life < GTrack(node.element).life)) then
      track := node.element;

    node := node.next;
    end;

  if (track = nil) then
    begin
    if (victim = nil) then
      begin
      ch.sendBuffer('The tracks seem to end here.'#13#10);
      ch.tracking := '';
      end
    else
      ch.sendBuffer('You can''t seem to find any tracks.'#13#10)
    end
  else
    begin
    ch.sendBuffer('You see some tracks heading ' + headings[track.direction] + '!'#13#10);
    end;
end;

procedure do_track(ch : GCharacter; param : string);
var
   vict : GCharacter;
begin
  vict := nil;
  
  if (ch.learned[gsn_track] = 0) then
    begin
    ch.sendBuffer('You don''t know how to track!'#13#10);
    exit;
    end;

  if (length(param) = 0) then
    begin
    if (ch.tracking = '') then
      begin
      ch.sendBuffer('Track whom?'#13#10);
      exit;
      end;
    end
  else
    begin
    vict := findCharWorld(ch, param);

    if (vict = ch) then
      begin
      ch.sendBuffer('You stop looking for tracks.'#13#10);
      ch.tracking := '';
      exit;
      end;
    end;

  act(AT_REPORT,'You begin to look for tracks...',false,ch,nil,nil,TO_CHAR);

  if (vict <> nil) then
    ch.tracking := vict.name^;

  registerTimer(TIMER_TRACK, track_timer, 4, ch, vict, gsn_track);
end;