Example: basic knowledge tracking — КиберПедия 

История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...

Поперечные профили набережных и береговой полосы: На городских территориях берегоукрепление проектируют с учетом технических и экономических требований, но особое значение придают эстетическим...

Example: basic knowledge tracking

2021-11-25 16
Example: basic knowledge tracking 0.00 из 5.00 0 оценок
Заказать работу

The simplest use of a multi-valued list is for tracking "game flags" tidily.

LIST Facts = (Fogg_is_fairly_odd), first_name_phileas, (Fogg_is_English)

 

{Facts? Fogg_is_fairly_odd:I smiled politely.|I frowned. Was he a lunatic?}

'{Facts? first_name_phileas:Phileas|Monsieur}, really!' I cried.

In particular, it allows us to test for multiple game flags in a single line.

{ Facts? (Fogg_is_English, Fogg_is_fairly_odd): 

   <> 'I know Englishmen are strange, but this is *incredible*!'

}

Example: a doctor's surgery

We're overdue a fuller example, so here's one.

LIST DoctorsInSurgery = (Adams), Bernard, Cartwright, (Denver), Eamonn

 

-> waiting_room

 

=== function whos_in_today()

   In the surgery today are {DoctorsInSurgery}.

       

=== function doctorEnters(who)

   { DoctorsInSurgery!? who:

          ~ DoctorsInSurgery += who

          Dr {who} arrives in a fluster.

   }

 

=== function doctorLeaves(who)

   { DoctorsInSurgery? who:

          ~ DoctorsInSurgery -= who

          Dr {who} leaves for lunch.

   }

 

=== waiting_room

   {whos_in_today()}

   *  [Time passes...]

          {doctorLeaves(Adams)} {doctorEnters(Cartwright)} {doctorEnters(Eamonn)}

          {whos_in_today()}

This produces:

In the surgery today are Adams, Denver.

 

> Time passes...

 

Dr Adams leaves for lunch. Dr Cartwright arrives in a fluster. Dr Eamonn arrives in a fluster.

 

In the surgery today are Cartwright, Denver, Eamonn.

Advanced: nicer list printing

The basic list print is not especially attractive for use in-game. The following is better:

=== function listWithCommas(list, if_empty)

{LIST_COUNT(list):

- 2:

     {LIST_MIN(list)} and {listWithCommas(list - LIST_MIN(list), if_empty)}

- 1:

     {list}

- 0:

                  {if_empty}        

- else:

    {LIST_MIN(list)}, {listWithCommas(list - LIST_MIN(list), if_empty)}

}

 

LIST favouriteDinosaurs = (stegosaurs), brachiosaur, (anklyosaurus), (pleiosaur)

 

My favourite dinosaurs are {listWithCommas(favouriteDinosaurs, "all extinct")}.

It's probably also useful to have an is/are function to hand:

=== function isAre(list)

   {LIST_COUNT(list) == 1:is|are}

       

My favourite dinosaurs {isAre(favouriteDinosaurs)} {listWithCommas(favouriteDinosaurs, "all extinct")}.

And to be pendantic:

My favourite dinosaur{LIST_COUNT(favouriteDinosaurs)!= 1:s} {isAre(favouriteDinosaurs)} {listWithCommas(favouriteDinosaurs, "all extinct")}.

Lists don't need to have multiple entries

Lists don't have to contain multiple values. If you want to use a list as a state-machine, the examples above will all work - set values using =, ++ and --; test them using ==, <, <=, > and >=. These will all work as expected.

The "full" list

Note that LIST_COUNT, LIST_MIN and LIST_MAX are refering to who's in/out of the list, not the full set of possible doctors. We can access that using

LIST_ALL(element of list)

or

LIST_ALL(list containing elements of a list)

 

{LIST_ALL(DoctorsInSurgery)} // Adams, Bernard, Cartwright, Denver, Eamonn

{LIST_COUNT(LIST_ALL(DoctorsInSurgery))} // "5"

{LIST_MIN(LIST_ALL(Eamonn))}                    // "Adams"

Note that printing a list using {...} produces a bare-bones representation of the list; the values as words, delimited by commas.

Advanced: "refreshing" a list's type

If you really need to, you can make an empty list that knows what type of list it is.

LIST ValueList = first_value, second_value, third_value

VAR myList = ()

 

~ myList = ValueList()

You'll then be able to do:

{ LIST_ALL(myList) }

Advanced: a portion of the "full" list

You can also retrieve just a "slice" of the full list, using the LIST_RANGE function.

LIST_RANGE(list_name, min_value, max_value)

Example: Tower of Hanoi

To demonstrate a few of these ideas, here's a functional Tower of Hanoi example, written so no one else has to write it.

LIST Discs = one, two, three, four, five, six, seven

VAR post1 = ()

VAR post2 = ()

VAR post3 = ()

 

~ post1 = LIST_ALL(Discs)

 

-> gameloop

 

=== function can_move(from_list, to_list) ===

{

- LIST_COUNT(from_list) == 0:

   // no discs to move

   ~ return false

- LIST_COUNT(to_list) > 0 && LIST_MIN(from_list) > LIST_MIN(to_list):

   // the moving disc is bigger than the smallest of the discs on the new tower

   ~ return false

- else: 

 // nothing stands in your way!

   ~ return true

       

}

 

=== function move_ring(ref from, ref to) ===

~ temp whichRingToMove = LIST_MIN(from)

~ from -= whichRingToMove

~ to += whichRingToMove

 

== function getListForTower(towerNum)

{ towerNum:

   - 1: ~ return post1

   - 2: ~ return post2

   - 3: ~ return post3

 }

 

=== function name(postNum)

the {postToPlace(postNum)} temple

   

=== function Name(postNum)

The {postToPlace(postNum)} temple

 

=== function postToPlace(postNum)

{ postNum:

   - 1: first

   - 2: second

   - 3: third

}

 

=== function describe_pillar(listNum) ==

~ temp list = getListForTower(listNum)

{

- LIST_COUNT(list) == 0:

   {Name(listNum)} is empty.

- LIST_COUNT(list) == 1:

   The {list} ring lies on {name(listNum)}.

- else:

   On {name(listNum)}, are the discs numbered {list}.

}

   

 

=== gameloop

Staring down from the heavens you see your followers finishing construction of the last of the great temples, ready to begin the work.

- (top)

+ (describe) {true || TURNS_SINCE(-> describe) >= 2 ||!describe} [ Regard the temples]

   You regard each of the temples in turn. On each is stacked the rings of stone. {describe_pillar(1)} {describe_pillar(2)} {describe_pillar(3)}

<- move_post(1, 2, post1, post2)  

<- move_post(2, 1, post2, post1) 

<- move_post(1, 3, post1, post3) 

<- move_post(3, 1, post3, post1) 

<- move_post(3, 2, post3, post2) 

<- move_post(2, 3, post2, post3) 

-> DONE

   

= move_post(from_post_num, to_post_num, ref from_post_list, ref to_post_list)

+ { can_move(from_post_list, to_post_list) }

   [ Move a ring from {name(from_post_num)} to {name(to_post_num)} ]

   { move_ring(from_post_list, to_post_list) }

   { stopping:

   - The priests far below construct a great harness, and after many years of work, the great stone ring is lifted up into the air, and swung over to the next of the temples.

       The ropes are slashed, and in the blink of an eye it falls once more.

   - Your next decree is met with a great feast and many sacrifices. After the funeary smoke has cleared, work to shift the great stone ring begins in earnest. A generation grows and falls, and the ring falls into its ordained place.

   - {cycle:

       - Years pass as the ring is slowly moved.

       - The priests below fight a war over what colour robes to wear, but while they fall and die, the work is still completed.

       }

   }

-> top

Advanced List Operations

The above section covers basic comparisons. There are a few more powerful features as well, but - as anyone familiar with mathematical sets will know - things begin to get a bit fiddly. So this section comes with an 'advanced' warning.

A lot of the features in this section won't be necessary for most games.

Comparing lists

We can compare lists less than exactly using >, <, >= and <=. Be warned! The definitions we use are not exactly standard fare. They are based on comparing the numerical value of the elements in the lists being tested.

"Distinctly bigger than"

LIST_A > LIST_B means "the smallest value in A is bigger than the largest values in B": in other words, if put on a number line, the entirety of A is to the right of the entirety of B. < does the same in reverse.

"Definitely never smaller than"

LIST_A >= LIST_B means - take a deep breath now - "the smallest value in A is at least the smallest value in B, and the largest value in A is at least the largest value in B". That is, if drawn on a number line, the entirety of A is either above B or overlaps with it, but B does not extend higher than A.

Note that LIST_A > LIST_B implies LIST_A!= LIST_B, and LIST_A >= LIST_B allows LIST_A == LIST_B but precludes LIST_A < LIST_B, as you might hope.

Health warning!

LIST_A >= LIST_B is not the same as LIST_A > LIST_B or LIST_A == LIST_B.

The moral is, don't use these unless you have a clear picture in your mind.

Inverting lists

A list can be "inverted", which is the equivalent of going through the accommodation in/out name-board and flipping every switch to the opposite of what it was before.

LIST GuardsOnDuty = (Smith), (Jones), Carter, Braithwaite

 

=== function changingOfTheGuard

   ~ GuardsOnDuty = LIST_INVERT(GuardsOnDuty)

Note that LIST_INVERT on an empty list will return a null value, if the game doesn't have enough context to know what invert. If you need to handle that case, it's safest to do it by hand:

=== function changingOfTheGuard

   {!GuardsOnDuty: // "is GuardsOnDuty empty right now?"

          ~ GuardsOnDuty = LIST_ALL(Smith)

   - else:

          ~ GuardsOnDuty = LIST_INVERT(GuardsOnDuty)

   }

Footnote

The syntax for inversion was originally ~ list but we changed it because otherwise the line

~ list = ~ list

was not only functional, but actually caused list to invert itself, which seemed excessively perverse.

Intersecting lists

The has or? operator is, somewhat more formally, the "are you a subset of me" operator, ⊇, which includes the sets being equal, but which doesn't include if the larger set doesn't entirely contain the smaller set.

To test for "some overlap" between lists, we use the overlap operator, ^, to get the intersection.

LIST CoreValues = strength, courage, compassion, greed, nepotism, self_belief, delusions_of_godhood

VAR desiredValues = (strength, courage, compassion, self_belief)

VAR actualValues = (greed, nepotism, self_belief, delusions_of_godhood)

 

{desiredValues ^ actualValues} // prints "self_belief" 

The result is a new list, so you can test it:

{desiredValues ^ actualValues: The new president has at least one desirable quality.}

 

{LIST_COUNT(desiredValues ^ actualValues) == 1: Correction, the new president has only one desirable quality. {desiredValues ^ actualValues == self_belief: It's the scary one.}}

Multi-list Lists

So far, all of our examples have included one large simplification, again - that the values in a list variable have to all be from the same list family. But they don't.

This allows us to use lists - which have so far played the role of state-machines and flag-trackers - to also act as general properties, which is useful for world modelling.

This is our inception moment. The results are powerful, but also more like "real code" than anything that's come before.

Lists to track objects

For instance, we might define:

LIST Characters = Alfred, Batman, Robin

LIST Props = champagne_glass, newspaper

 

VAR BallroomContents = (Alfred, Batman, newspaper)

VAR HallwayContents = (Robin, champagne_glass)

We could then describe the contents of any room by testing its state:

=== function describe_room(roomState)

   { roomState? Alfred: Alfred is here, standing quietly in a corner. } { roomState? Batman: Batman's presence dominates all. } { roomState? Robin: Robin is all but forgotten. }

   <> { roomState? champagne_glass: A champagne glass lies discarded on the floor. } { roomState? newspaper: On one table, a headline blares out WHO IS THE BATMAN? AND *WHO* IS HIS BARELY-REMEMBERED ASSISTANT? }

So then:

{ describe_room(BallroomContents) }

produces:

Alfred is here, standing quietly in a corner. Batman's presence dominates all.

 

On one table, a headline blares out WHO IS THE BATMAN? AND *WHO* IS HIS BARELY-REMEMBERED ASSISTANT?

While:

{ describe_room(HallwayContents) }

gives:

Robin is all but forgotten.

 

A champagne glass lies discarded on the floor.

And we could have options based on combinations of things:

*  { currentRoomState? (Batman, Alfred) } [Talk to Alfred and Batman]

   'Say, do you two know each other?'


Поделиться с друзьями:

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...

Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...

Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.054 с.