Step countingNow, we're going to develop a more sophisticated map. There are three important characteristics: 
 Create Steps.txt and include it in the driver: #Steps.txt The base mapFirst, we'll create a first draft of this map; just empty fields, walls, doors and named coordinates - you should already know them: /* Prototypes */
prototypen:
// Ordinary door
t_d =	Teleporter("Images/Teleporter.png", "Images/Bricks.png")
// Lockable door
t_l =	Tuer("Images/Teleporter.png", "Images/Bricks.png", "Images/Bricks.png")
/* The map */
karten:
steps = 5 10
w	w	w	t_l(j, finish_steps)=steps_door	w
w	e	e	e=steps_finish	w
w	e	e	e	w
w	e	e	e=finish_steps	w
w	e=t_guarded	e	e	w
w	e	w	w	w
w	e	e	e	w
w	e	e	e	w
w	e=steps_shift	e	e	w
w	t_d(shift_steps)	w	w	w
This one should work, you can try; the coordinate finish_steps is just temporarly assigned to that field on this map, as the final map currently does not exist. Step counterTo implement the step counting, we'll use WissenSchaf(f)t? internal event system. This can't be done with DialogSkript, so we need to write our component in Java. net.daniel_kraft.wissenSchafft.welten.Demo.StepCounter is a module, meaning that it just wants to be loaded together with the game, and isn't a more concrete object, like an avatar or a prototype. Here's that class' source, but how to write components in Java or how to use the event system is beyond the scope of this document: package net.daniel_kraft.wissenSchafft.welten.Demo;
import net.daniel_kraft.wissenSchafft.basis.*;
import net.daniel_kraft.wissenSchafft.events.*;
import net.daniel_kraft.wissenSchafft.parser.*;
import net.daniel_kraft.wissenSchafft.standard.Sperrbar;
import java.io.*;
/**
 * A WissenSchaf(f)t? module, which counts the steps the Avatar takes (on a
 * specific map) and alternatively opens and closes a door every second step.
 */
public class StepCounter implements Modul, Erzeugbar, FeldListener
{
 // Number of steps; -1 means we aren't counting at the moment (wrong map).
 private int    count;
 
 // Lock / unlock this one
 private Sperrbar      door;
 // No work for constructor, initialization isn't done here.
 public StepCounter()
 {}
 
 // Generate it, we expect no arguments
 public void erzeugen(String[] args) throws FalscheArgumenteExc
 {
  if(args.length!=0)
   throw new FalscheArgumenteExc("Erwartet: StepCounter()");
 }
 // Here we are to initialize everything.
 public void init(Welt w) throws UndefiniertExc
 {
  count=0;
  
  // Register event listeners
  w.getKarten().getKarte("steps").addListener(this);
  
  // Get door
  door=(Sperrbar)(w.getKarten().getKoordinate("steps_door").getFeld().getSpeziell());
 }
 
 // Flip the state.
 public void flip()
 {
  ++count;
  door.setBetretbar(count%2==0);
 }
 public void zerstoeren()
 {}
 // Load & save the current count
 public void speichern(OutputStream aOut) throws IOException
 {
  DataOutputStream out=(aOut instanceof DataOutputStream ?
   (DataOutputStream)aOut : new DataOutputStream(aOut));
  out.writeInt(count);
 }
 public void laden(InputStream aIn) throws IOException
 {
  DataInputStream in=(aIn instanceof DataInputStream ?
   (DataInputStream)aIn : new DataInputStream(aIn));
  count=in.readInt();
 }
 
 public void feldAngesprochen(FeldEvent evt)
 {}
 public void feldVerlassen(FeldEvent evt)
 {}
 public void feldBetreten(FeldEvent evt)
 {
  flip();
 }
}
What this module does: As soon as loaded into the world it registers an event listener to be notified whenever a field on the step-counting-map is entered. Everytime this happens, it inverts the door state. To make this work, you have to compile the module, and load it into WissenSchaf(f)t?; this is done somewhere in the world: /* Load our step counter */ module: stepCounter = net.daniel_kraft.wissenSchafft.welten.Demo.StepCounter The new version of our map should work, and the door state should be flipped every step. GuardingFinally, we need the guard. A guard is a person, who watches several fields; whenever the player wants to enter one of those, the guard is notified and it determines, whether the user is allowed to or not. In the latter case, the avatar is sent back to where it came from. We'll implement our guard in DialogSkript, and now we need a new prototype: // Guard who waits for you and who's able to alter the door cycle.
t_g =	DialogWaechter("Images/SmileyN.png", "Images/SmileyE.png",
                       "Images/SmileyS.png", "Images/SmileyW.png", "Images/Empty.png")
Here, as usual, the parameters specify the images for any of the four main directions, and an optional background. Including it into the map we get: karten:
steps = 5 10
w	w	w	t_l(j, finish_steps)=steps_door	w
w	e	e	e=steps_finish	w
w	e	e	e	w
w	e	e	e=finish_steps	w
w	e=t_guarded	t_g(W, <t_gname>, <t_gscript>, t_guarded)	e	w
w	e	w	w	w
w	e	e	e	w
w	e	e	e	w
w	e=steps_shift	e	e	w
w	t_d(shift_steps)	w	w	w
The first three parameters are identical to those of DialogPerson (initial viewing direction, name and script), then one or more coordinate names are to follow (which indicate the fields to guard). Of coure, we need the two strings: strings: t_gname = Guard t_gscript = @"Scripts/Guard.ds" Yet just the script is missing. Create Scripts/Guard.ds: /* Some imports for convenience */
import net.daniel_kraft.wissenSchafft.basis;
import net.daniel_kraft.wissenSchafft.welten.Demo;
import java.util;
/* Variables */
// Actual number he's asking.
var Int number;
// Correct answer: The smallest prime larger than number
var Int answer;
// Link to API
var Objekt@Welt w;
// Our random number generator
var Objekt@Random rand;
/* Methods */
// Is that number prime?
Boolean isPrime(Int num)
{
 var Int t;
 for(set t=2; t*t<=num; set t=t+1;)
  if(num%t==0) return false;
 return true;
}
// Choose a number and calculate the correct answer
void chooseNumber()
{
 // Choose a random number
 set number=rand:nextInt(11122000?Java@int)?Int+1;
 // Calculate the correct answer
 for(set answer=number+1; !isPrime(answer); set answer=answer+1;);
}
// Initialization, here we get our API reference.
void init(Objekt@Welt aW)
{
 set w=aW;
 set rand=new Random();
 chooseNumber();
}
// Check if the player knows about primes and is willing to guess...
Boolean check()
{
 var Int ans;
 // Output our question
 out w:getUserIStrListe():getString('steps_task'), number;
 // Ask for answer
 in ans;
 // Check.
 if(ans!=answer)
 {
  out w:getUserIStrListe():getString('steps_wrong');
  return false;
 }
 // OK, also invert the door state.
 chooseNumber();
 out w:getUserIStrListe():getString('steps_ok');
 w:getModul("stepCounter")?Objekt@StepCounter:flip();
 return true;
}
The highlighted function is the one which determines if the user is allowed to enter the guarded field. Whenever the user answers correctly, the step counter is flipped. We need new strings in the language file Lang/en.txt: /* ***************************************************************** */ // Step counting map with guard steps_task = "The smallest prime number above " steps_wrong = "Wrong." steps_ok = "OK, you can pass." Just try it out, and happy guessing! If you don't like it, you may insert a line to output the correct solution right after the question... Incorrecting itTo finish this map, we have to remove the wrongly given coordinate name, incorrecting our world (as long as you don't advance to the next chapter): karten:
steps = 5 10
w	w	w	t_l(j, finish_steps)=steps_door	w
w	e	e	e=steps_finish	w
w	e	e	e	w
w	e	e	e	w
w	e=t_guarded	t_g(W, <t_gname>, <t_gscript>, t_guarded)	e	w
w	e	w	w	w
w	e	e	e	w
w	e	e	e	w
w	e=steps_shift	e	e	w
w	t_d(shift_steps)	w	w	w
 |