Author Topic: A room counter  (Read 7974 times)

0 Members and 1 Guest are viewing this topic.

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
A room counter
« on: June 04, 2013, 11:12:44 pm »
Suppose you want to give a player a challenge to explore the entire zone, and tell the player how many rooms he or she has yet to find. This is not easy to script, because a zone with 100 rooms might necessitate 100 (different) flags on the player.

It is possible to make a script (using the following outline shown) to reduce the worst case scenario of the number of flags to {Number of rooms /2} by considering the vnums in binary. However, it might be possible to reduce this number further - unfortunately I don't know what (other) commands I can use in scripting.

Therefore, here is a test case by considering vnums in base 10. While this is inefficient (it's not in base 2), the outline of the code is relatively easier to follow.

I would also like to know whether it's possible to create for loops in scripts - then the following code can be further compacted.

I have resorted to a hack - putting this as a room enter trigger, so this necessitates that *every* room have this trigger. Ideally, I'd like to have this trigger on an object in the player's inventory - so that if the player moves, then the object will trigger, and tally the number of rooms.

If anyone has any suggestions for improvements, or any shortcuts which I have overlooked, do post here, so everyone can benefit :)

Code: [Select]
*Code works like this:
*Every 10vnums are grouped together, from 00-09, 10-19, 20-29, .., 90-99
*Flags are labelled africanexplored0, africanexplored1, .. africanexplored99
*But if you have a group of 10, say africanexplored0, .. africanexplored9
*then you'll get the flag africanexploredtens0 (the tens0 denotes the tens
*position as 0). So here, the worst case scenario is the player gets 9 of each
*group, and has 90 extra flags. The 91st flag would mean the player completes
*one group of 10, and hence reduce the number of flags from 90 to 81.
*Of course, we can group 2 vnums together, to reduce the worst case scenarion
*to 50. I think this can be even reduced further, but I'm not sure what
*commands I'm able to use.

*For the code below, you can see I've only been using "if" statements, as
*I'm not sure if for loops, etc exists.

if %actor.is_pc%
if !%actor.varexists(africanexploredall)%
*The flag africanexploredall means you've been to all the rooms
*So suppose you haven't
eval NUM %actor.room.vnum%
eval ABSNUM %NUM% -33700
                *We want the last two digits of the vnum - we're assuming the zone has 100 rooms, and given zone 337
eval TENS %ABSNUM%/10
                *We want the digit in the 10s place
eval TENSVAR africanexploredtens%TENS%
                *Create the variable which corresponds to the 10sdigit
eval ABSNUMVAR africanexplored%ABSNUM%
                *Create the variable which corresponds to the last two digits of the vnum
%echo% My room number is %NUM%
%echo% My tens is %TENS%
%echo% I belong to %TENSVAR%
%echo% and %ABSNUMVAR%
%echo% My absolute number is %ABSNUM%
*TENS will be from 00-09
if  !%actor.varexists(%TENSVAR%)% && !%actor.varexists(%ABSNUMVAR%)%
%echo% I haven't been in this room yet%
set %ABSNUMVAR% 1
remote %ABSNUMVAR% %actor.id%
                                *Put your room counter here and make it increase by 1
endif
*check per 10 rooms
                        *A for loop would be nice here (needless to say, for binary case
                        *it's somewhat easier as we can look at %NUM%/2, %NUM%+1/2
                        *etc)
eval T1 %TENS% * 10
eval T1VAR africanexplored%T1%
eval T2 %T1% + 1
eval T2VAR africanexplored%T2%
eval T3 %T1% + 2
eval T3VAR africanexplored%T3%
eval T4 %T1% + 3
eval T4VAR africanexplored%T4%
eval T5 %T1% + 4
eval T5VAR africanexplored%T5%
eval T6 %T1% + 5
eval T6VAR africanexplored%T6%
eval T7 %T1% + 6
eval T7VAR africanexplored%T7%
eval T8 %T1% + 7
eval T8VAR africanexplored%T8%
eval T9 %T1% + 8
eval T9VAR africanexplored%T9%
eval T10 %T1% + 9
eval T10VAR africanexplored%T10%
%echo% My 10 variables are
%echo% %T1VAR%
%echo% %T2VAR%
%echo% %T3VAR%
%echo% %T4VAR%
%echo% %T5VAR%
%echo% %T6VAR%
%echo% %T7VAR%
%echo% %T8VAR%
%echo% %T9VAR%
%echo% %T10VAR%
if %actor.varexists(%T1VAR%)% && %actor.varexists(%T2VAR%)% && %actor.varexists(%T3VAR%)% && %actor.varexists(%T4VAR%)% && %actor.varexists(%T5VAR%)% && %actor.varexists(%T6VAR%)% && %actor.varexists(%T7VAR%)% && %actor.varexists(%T8VAR%)% && %actor.varexists(%T9VAR%)% && %actor.varexists(%T10VAR%)%
%echo% I've been in a set of 10 rooms
%echo% so I'm adding %TENSVAR% to me
%echo% Check to see I have this
set %TENSVAR% 1
remote %TENSVAR% %actor.id%
rdelete %T1VAR% %actor.id%
rdelete %T2VAR% %actor.id%
rdelete %T3VAR% %actor.id%
rdelete %T4VAR% %actor.id%
rdelete %T5VAR% %actor.id%
rdelete %T6VAR% %actor.id%
rdelete %T7VAR% %actor.id%
rdelete %T8VAR% %actor.id%
rdelete %T9VAR% %actor.id%
rdelete %T10VAR% %actor.id%
endif
*check all rooms
if %actor.varexists(africanexploredtens0)% && %actor.varexists(africanexploredtens1)% && %actor.varexists(africanexploredtens2)% && %actor.varexists(africanexploredtens3)% && %actor.varexists(africanexploredtens4)% && %actor.varexists(africanexploredtens5)% && %actor.varexists(africanexploredtens6)% && %actor.varexists(africanexploredtens7)% && %actor.varexists(africanexploredtens8)% && %actor.varexists(africanexploredtens9)%
%echo% If I am triggered, I have explored everywhere
%echo% Check to see if I have the complete flag!
set africanexploredall 1
remote africanexploredall %actor.id%
rdelete africanexploredtens0 %actor.id%
rdelete africanexploredtens1 %actor.id%
rdelete africanexploredtens2 %actor.id%
rdelete africanexploredtens3 %actor.id%
rdelete africanexploredtens4 %actor.id%
rdelete africanexploredtens5 %actor.id%
rdelete africanexploredtens6 %actor.id%
rdelete africanexploredtens7 %actor.id%
rdelete africanexploredtens8 %actor.id%
rdelete africanexploredtens9 %actor.id%
endif
endif
endif

Now, it just suffices to put a counter whenever the player enters a new room to increase the rooms explored by 1! Tada!
« Last Edit: June 04, 2013, 11:44:52 pm by erwin »

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Re: A room counter
« Reply #1 on: June 06, 2013, 12:59:43 am »
I can bring this down to 2-3 flags in worst case scenario, as opposed to 50 flags - I have the outline of the script (hint - it uses the charat function), so I'll do it in the weekend. Here's a short exercise for all of you.

Q1: What is the maximum string length a flag can hold? [5 marks]
Q2: Suppose a zone has seven rooms. Using the string 1100011, we can say that the first 2 rooms have been explored, the next three rooms have not, and the last two have. With this idea, write code to improve the previous script for the worse case scenario of flags [20 marks]
« Last Edit: June 06, 2013, 01:16:01 am by erwin »

Offline Jaros

  • Full Member
  • ***
  • Posts: 234
    • View Profile
    • Email
Re: A room counter
« Reply #2 on: June 06, 2013, 06:13:04 am »
loops:
while %var%
  < blah >
done

eval flag 0000000...000  * 110 digits.  I don't know what the max length of a flag is but i suspect it is more than 110.

eval tens %self.room.vnum.charat(4)%
eval tens_check 100 + %tens%
eval ones %self.room.vnum.charat(5)%
eval ones_check %tens% * 10 + %ones%
if %flag.charat(%tens_check%)% == 0 && %flag.charat(%ones_check%)% == 0
  %echo% this room is new to me
  eval i 1
  eval newflag
  while %i% < 101
    if %i% == %ones_check%
      eval digit 1
    else
      eval digit %flag.charat(%i)%
    end
    eval newflag %newflag%%digit%
    eval i %i% + 1
  done
  eval flag %newflag%
end

plus another loop in there to check if all the ones in the relevant 10-digit bracket == 1 and if so set the tens place (100 + tens) to 1.

are you doing something like that?
« Last Edit: June 06, 2013, 07:03:12 am by Jaros »

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Re: A room counter
« Reply #3 on: June 06, 2013, 08:39:21 am »
My script would be just putting the flag

0000..0000000

on the player.

When the relevant room, say k is entered, we'll check if the kth position is a 0 or a 1.

If it is a 0, we change it to a 1. Update counter by 1.

This is the problem I have. How do we change the kth position of a flag? eg, suppose I have the flag value 123, and I want to change it to 143. Apart from adding 20 to it, how do I change the 2 to a 4?

Furthermore, expressions like 10^2 isn't recognized - the output will be 10^2 instead of 100, so even a workaround by adding would be a pain.[/i]

If the kth position is a 1, check if the flag is 111..1111.

If it is 111....111, we give player a new flag - explored, and delete the messy 111...111 flag.

I'll look through the above script later when I'm at the office.
« Last Edit: June 06, 2013, 09:08:26 am by erwin »

Offline Jaros

  • Full Member
  • ***
  • Posts: 234
    • View Profile
    • Email
Re: A room counter
« Reply #4 on: June 06, 2013, 08:36:29 pm »
The while loop in that script above builds a new flag the same as the old one updated at k.  I'm pretty sure something like that could be made to work.  You could use another loop if k == 1 to check the digits from tens*10 to tens*10+9.  If they all == 1, build a new flag updated at tens_check position.

Not ideal having to loop through ~100 characters every time you want to update the flag but I'm not sure how else you could do it.  I don't think there's a way to change a character at an index?  Does anyone know if there is?
« Last Edit: June 06, 2013, 08:48:25 pm by Jaros »

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Re: A room counter
« Reply #5 on: June 06, 2013, 11:48:59 pm »
I think Now says he'll put the command in soon.

I also have another question.

Suppose the player has a flag called africanexploredtens4

You would normally call this by %actor.africanexploredtens4%.

However, suppose the player is in room 12345. Using the code

Code: [Select]
set num %actor.room.vnum%
eval tens %num.charat(4)%
set tensvar africanexploredtens%tens%

we will have tensvar to be africanexploredtens4.

However, how would I then modify this flag? The following syntaxes:

Code: [Select]
%actor.tensvar%
%actor.%tensvar%%
%actor.%tensvar%
%%actor.tensvar%%

doesn't work for me, because the system interprets it as a flag called tensvar, instead of africanexploredtens4.

Anyone have any ideas?

Offline Jaros

  • Full Member
  • ***
  • Posts: 234
    • View Profile
    • Email
Re: A room counter
« Reply #6 on: June 07, 2013, 12:58:55 am »
not sure what you're after.  if you remote tensvar %actor.id% then %actor.tensvar% will point to 'africanexploredtens4' and %actor.tensvar.charat(20)% will point to 4.  If there was a way of changing character at index you could modify it easily, otherwise you can loop through appending characters onto a new flag, with a modified char at 20.

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Re: A room counter
« Reply #7 on: June 07, 2013, 08:52:50 am »
Well, my idea is, suppose you had 10 flags on you, africanexploredtens0, africanexploredtens1, ..., africanexploredtens9.

africanexploredtens4 is currently set at 0011011001

The idea is, once you step into a room (eg, room vnum 12345), we have set tens %num.charat(4)%, and I'm hoping to link this to the flag africanexploredtens4, so we check whether the 5th position is a 0 or 1.

Hence I have set tensvar africanexploredtens%tens%.

What I'm hoping is that %actor.tensvar% (or some sort of variant) will give me the flag 0011011001, so I can check whether the respective position is 0 or 1.
« Last Edit: June 07, 2013, 08:56:43 am by erwin »

Offline Jaros

  • Full Member
  • ***
  • Posts: 234
    • View Profile
    • Email
Re: A room counter
« Reply #8 on: June 07, 2013, 09:07:48 am »
If you're using binary flags why do you need africanexploredtens0...africanexploredtens9?  Why not just use one long flag?

ie. %africa.charat(4*10+5)% instead of %africanexploredtens4.charat(5)%

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Re: A room counter
« Reply #9 on: June 07, 2013, 02:30:51 pm »
I've been told that a long string is not as efficient because DG doesn't store strings very well.

Not to mention, without a replace character command, looping through a 100 character string isn't very efficient. Neither are doing operations on the string since then the string would be a 100 digit number...