File: statemachine-rogue.html

package info (click to toggle)
qt4-x11 4%3A4.8.2%2Bdfsg-11
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 701,696 kB
  • sloc: cpp: 2,686,179; ansic: 375,485; python: 25,859; sh: 19,349; xml: 17,091; perl: 14,765; yacc: 5,383; asm: 5,038; makefile: 1,259; lex: 555; ruby: 526; objc: 347; cs: 112; pascal: 112; php: 54; sed: 34
file content (228 lines) | stat: -rw-r--r-- 24,884 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- rogue.qdoc -->
  <title>Qt 4.8: Rogue Example</title>
  <link rel="stylesheet" type="text/css" href="style/offline.css" />
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="content"> 
    <a href="index.html" class="qtref"><span>Qt Reference Documentation</span></a>
  </div>
  <div class="breadcrumb toolblock">
    <ul>
      <li class="first"><a href="index.html">Home</a></li>
      <!--  Breadcrumbs go here -->
<li><a href="all-examples.html">Examples</a></li>
<li>Rogue Example</li>
    </ul>
  </div>
</div>
<div class="content mainContent">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#window-class-definition">Window Class Definition</a></li>
<li class="level1"><a href="#window-class-implementation">Window Class Implementation</a></li>
<li class="level1"><a href="#the-movementtransition-class">The MovementTransition Class</a></li>
<li class="level1"><a href="#the-roguelike-tradition">The Roguelike Tradition</a></li>
</ul>
</div>
<h1 class="title">Rogue Example</h1>
<span class="subtitle"></span>
<!-- $$$statemachine/rogue-description -->
<div class="descr"> <a name="details"></a>
<p>Files:</p>
<ul>
<li><a href="statemachine-rogue-movementtransition-h.html">statemachine/rogue/movementtransition.h</a></li>
<li><a href="statemachine-rogue-window-cpp.html">statemachine/rogue/window.cpp</a></li>
<li><a href="statemachine-rogue-window-h.html">statemachine/rogue/window.h</a></li>
<li><a href="statemachine-rogue-main-cpp.html">statemachine/rogue/main.cpp</a></li>
<li><a href="statemachine-rogue-rogue-pro.html">statemachine/rogue/rogue.pro</a></li>
</ul>
<p>The Rogue example shows how to use the Qt state machine for event handling.<p class="centerAlign"><img src="images/rogue-example.png" alt="" /></p><p>This example implements a simple text based game. Do you see the <tt>@</tt> in the screenshot? That's you, the rogue. The <tt>#</tt> characters are walls, and the dots represent floor. In a real game, other ASCII characters would represent all kinds of objects and creatures, for instance, ancient dragons (<tt>D</tt>s) or food rations (<tt>%</tt>s). But let's not get carried away. In this game, the rogue is simply running around in an empty room.</p>
<p>The rogue is moved with the keypad (2, 4, 8, 6). That aside, we have implemented a <tt>quit</tt> command that triggers if the player types <tt>q</tt>. The player is then asked if he/she really wants to quit.</p>
<p>Most games have commands that need more than one key press (we think of consecutive presses, i.e&#x2e;, not of several keys being pressed at the same time). In this game, only the <tt>quit</tt> command falls under this category, but for the sake of argument, let's imagine a fully-fledged game with a rich set of commands. If we were to implement these by catching key events in <a href="qwidget.html#keyPressEvent">keyPressEvent()</a>, we would have to keep a lot of class member variables to track the sequence of keys already typed (or find some other way of deducing the current state of a command). This can easily lead to spaghetti, which is--as we all well know, I'm sure--unpleasant. With a state machine, on the other hand, separate states can wait for a single key press, and that makes our lives a lot simpler.</p>
<p>The example consists of two classes:</p>
<ul>
<li><tt>Window</tt> draws the text display of the game and sets up the state machine. The window also has a status bar above the area in which the rouge moves.</li>
<li><tt>MovementTransition</tt> is a transition that carries out a single move of the rogue.</li>
</ul>
<p>Before we embark on a code walkthrough, it is necessary to take a closer look at the design of the machine. Here is a state chart that shows what we want to achieve:</p>
<p class="centerAlign"><img src="images/rogue-statechart.png" alt="" /></p><p>The input state waits for a key press to start a new command. When receiving a key it recognizes, it transitions to one of the two commands of the game; though, as we will see, movement is handled by the transition itself. The quit state waits for the player to answer yes or no (by typing <tt>y</tt> or <tt>n</tt>) when asked whether he/she really wants to quit the game.</p>
<p>The chart demonstrates how we use one state to wait for a single key press. The press received may trigger one of the transitions connected to the state.</p>
<a name="window-class-definition"></a>
<h2>Window Class Definition</h2>
<p>The <tt>Window</tt> class is a widget that draws the text display of the game. It also sets up the state machine, i.e&#x2e;, creates and connects the states in the machine. It is the key events from this widget that are used by the machine.</p>
<pre class="cpp"> <span class="keyword">class</span> Window : <span class="keyword">public</span> <span class="type"><a href="qwidget.html">QWidget</a></span>
 {
     Q_OBJECT
     Q_PROPERTY(<span class="type"><a href="qstring.html">QString</a></span> status READ status WRITE setStatus)

 <span class="keyword">public</span>:
     <span class="keyword">enum</span> Direction { Up<span class="operator">,</span> Down<span class="operator">,</span> Left<span class="operator">,</span> Right };

     Window();

     <span class="type">void</span> movePlayer(Direction direction);
     <span class="type">void</span> setStatus(<span class="keyword">const</span> <span class="type"><a href="qstring.html">QString</a></span> <span class="operator">&amp;</span>status);
     <span class="type"><a href="qstring.html">QString</a></span> status() <span class="keyword">const</span>;

     <span class="type"><a href="qsize.html">QSize</a></span> sizeHint() <span class="keyword">const</span>;

 <span class="keyword">protected</span>:
     <span class="type">void</span> paintEvent(<span class="type"><a href="qpaintevent.html">QPaintEvent</a></span> <span class="operator">*</span>event);</pre>
<p><tt>Direction</tt> specifies the direction in which the rogue is to move. We use this in <tt>movePlayer()</tt>, which moves the rogue and repaints the window. The game has a status line above the area in which the rogue moves. The <tt>status</tt> property contains the text of this line. We use a property because the <a href="qstate.html">QState</a> class allows setting any Qt <a href="properties.html#qt-s-property-system">property</a> when entered. More on this later.</p>
<pre class="cpp"> <span class="keyword">private</span>:
     <span class="type">void</span> buildMachine();
     <span class="type">void</span> setupMap();

     <span class="type"><a href="qchar.html">QChar</a></span> map<span class="operator">[</span>WIDTH<span class="operator">]</span><span class="operator">[</span>HEIGHT<span class="operator">]</span>;
     <span class="type">int</span> pX<span class="operator">,</span> pY;

     <span class="type"><a href="qstatemachine.html">QStateMachine</a></span> <span class="operator">*</span>machine;
     <span class="type"><a href="qstring.html">QString</a></span> myStatus;
 };</pre>
<p>The <tt>map</tt> is an array with the characters that are currently displayed. We set up the array in <tt>setupMap()</tt>, and update it when the rogue is moved. <tt>pX</tt> and <tt>pY</tt> is the current position of the rogue. <tt>WIDTH</tt> and <tt>HEIGHT</tt> are macros specifying the dimensions of the map.</p>
<p>The <tt>paintEvent()</tt> function is left out of this walkthrough. We also do not discuss other code that does not concern the state machine (the <tt>setupMap()</tt>, <tt>status()</tt>, <tt>setStatus()</tt>, <tt>movePlayer()</tt>, and <tt>sizeHint()</tt> functions). If you wish to take a look at the code, click on the link for the <tt>window.cpp</tt> file at the top of this page.</p>
<a name="window-class-implementation"></a>
<h2>Window Class Implementation</h2>
<p>Here is the constructor of <tt>Window</tt>:</p>
<pre class="cpp"> Window<span class="operator">::</span>Window()
 {
     pX <span class="operator">=</span> <span class="number">5</span>;
     pY <span class="operator">=</span> <span class="number">5</span>;
     ...
     setupMap();
     buildMachine();
 }</pre>
<p>The player starts off at position (5, 5). We then set up the map and statemachine. Let's proceed with the <tt>buildMachine()</tt> function:</p>
<pre class="cpp"> <span class="type">void</span> Window<span class="operator">::</span>buildMachine()
 {
     machine <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qstatemachine.html">QStateMachine</a></span>;

     <span class="type"><a href="qstate.html">QState</a></span> <span class="operator">*</span>inputState <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qstate.html">QState</a></span>(machine);
     inputState<span class="operator">-</span><span class="operator">&gt;</span>assignProperty(<span class="keyword">this</span><span class="operator">,</span> <span class="string">&quot;status&quot;</span><span class="operator">,</span> <span class="string">&quot;Move the rogue with 2, 4, 6, and 8&quot;</span>);

     MovementTransition <span class="operator">*</span>transition <span class="operator">=</span> <span class="keyword">new</span> MovementTransition(<span class="keyword">this</span>);
     inputState<span class="operator">-</span><span class="operator">&gt;</span>addTransition(transition);</pre>
<p>We enter <tt>inputState</tt> when the machine is started and from the <tt>quitState</tt> if the user wants to continue playing. We then set the status to a helpful reminder of how to play the game.</p>
<p>First, the <tt>Movement</tt> transition is added to the input state. This will enable the rogue to be moved with the keypad. Notice that we don't set a target state for the movement transition. This will cause the transition to be triggered (and the <a href="qabstracttransition.html#onTransition">onTransition()</a> function to be invoked), but the machine will not leave the <tt>inputState</tt>. If we had set <tt>inputState</tt> as the target state, we would first have left and then entered the <tt>inputState</tt> again.</p>
<pre class="cpp">     <span class="type"><a href="qstate.html">QState</a></span> <span class="operator">*</span>quitState <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qstate.html">QState</a></span>(machine);
     quitState<span class="operator">-</span><span class="operator">&gt;</span>assignProperty(<span class="keyword">this</span><span class="operator">,</span> <span class="string">&quot;status&quot;</span><span class="operator">,</span> <span class="string">&quot;Really quit(y/n)?&quot;</span>);

     <span class="type"><a href="qkeyeventtransition.html">QKeyEventTransition</a></span> <span class="operator">*</span>yesTransition <span class="operator">=</span> <span class="keyword">new</span>
         <span class="type"><a href="qkeyeventtransition.html">QKeyEventTransition</a></span>(<span class="keyword">this</span><span class="operator">,</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>KeyPress<span class="operator">,</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Y);
     yesTransition<span class="operator">-</span><span class="operator">&gt;</span>setTargetState(<span class="keyword">new</span> <span class="type"><a href="qfinalstate.html">QFinalState</a></span>(machine));
     quitState<span class="operator">-</span><span class="operator">&gt;</span>addTransition(yesTransition);

     <span class="type"><a href="qkeyeventtransition.html">QKeyEventTransition</a></span> <span class="operator">*</span>noTransition <span class="operator">=</span>
         <span class="keyword">new</span> <span class="type"><a href="qkeyeventtransition.html">QKeyEventTransition</a></span>(<span class="keyword">this</span><span class="operator">,</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>KeyPress<span class="operator">,</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_N);
     noTransition<span class="operator">-</span><span class="operator">&gt;</span>setTargetState(inputState);
     quitState<span class="operator">-</span><span class="operator">&gt;</span>addTransition(noTransition);</pre>
<p>When we enter <tt>quitState</tt>, we update the status bar of the window.</p>
<p><tt>QKeyEventTransition</tt> is a utility class that removes the hassle of implementing transitions for <a href="qkeyevent.html">QKeyEvent</a>s. We simply need to specify the key on which the transition should trigger and the target state of the transition.</p>
<pre class="cpp">     <span class="type"><a href="qkeyeventtransition.html">QKeyEventTransition</a></span> <span class="operator">*</span>quitTransition <span class="operator">=</span>
         <span class="keyword">new</span> <span class="type"><a href="qkeyeventtransition.html">QKeyEventTransition</a></span>(<span class="keyword">this</span><span class="operator">,</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>KeyPress<span class="operator">,</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Q);
     quitTransition<span class="operator">-</span><span class="operator">&gt;</span>setTargetState(quitState);
     inputState<span class="operator">-</span><span class="operator">&gt;</span>addTransition(quitTransition);</pre>
<p>The transition from <tt>inputState</tt> allows triggering the quit state when the player types <tt>q</tt>.</p>
<pre class="cpp">     machine<span class="operator">-</span><span class="operator">&gt;</span>setInitialState(inputState);

     connect(machine<span class="operator">,</span> SIGNAL(finished())<span class="operator">,</span> qApp<span class="operator">,</span> SLOT(quit()));

     machine<span class="operator">-</span><span class="operator">&gt;</span>start();
 }</pre>
<p>The machine is set up, so it's time to start it.</p>
<a name="the-movementtransition-class"></a>
<h2>The MovementTransition Class</h2>
<p><tt>MovementTransition</tt> is triggered when the player request the rogue to be moved (by typing 2, 4, 6, or 8) when the machine is in the <tt>inputState</tt>.</p>
<pre class="cpp"> <span class="keyword">class</span> MovementTransition : <span class="keyword">public</span> <span class="type"><a href="qeventtransition.html">QEventTransition</a></span>
 {
     Q_OBJECT

 <span class="keyword">public</span>:
     MovementTransition(Window <span class="operator">*</span>window) :
         <span class="type"><a href="qeventtransition.html">QEventTransition</a></span>(window<span class="operator">,</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>KeyPress) {
         <span class="keyword">this</span><span class="operator">-</span><span class="operator">&gt;</span>window <span class="operator">=</span> window;
     }</pre>
<p>In the constructor, we tell <a href="qeventtransition.html">QEventTransition</a> to only send <a href="qevent.html#Type-enum">KeyPress</a> events to the <a href="qabstracttransition.html#eventTest">eventTest()</a> function:</p>
<pre class="cpp"> <span class="keyword">protected</span>:
     <span class="type">bool</span> eventTest(<span class="type"><a href="qevent.html">QEvent</a></span> <span class="operator">*</span>event) {
         <span class="keyword">if</span> (event<span class="operator">-</span><span class="operator">&gt;</span>type() <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>StateMachineWrapped <span class="operator">&amp;</span><span class="operator">&amp;</span>
             <span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="type"><a href="qstatemachine.html">QStateMachine</a></span><span class="operator">::</span>WrappedEvent <span class="operator">*</span><span class="operator">&gt;</span>(event)<span class="operator">-</span><span class="operator">&gt;</span>event()<span class="operator">-</span><span class="operator">&gt;</span>type() <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qevent.html">QEvent</a></span><span class="operator">::</span>KeyPress) {
             <span class="type"><a href="qevent.html">QEvent</a></span> <span class="operator">*</span>wrappedEvent <span class="operator">=</span> <span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="type"><a href="qstatemachine.html">QStateMachine</a></span><span class="operator">::</span>WrappedEvent <span class="operator">*</span><span class="operator">&gt;</span>(event)<span class="operator">-</span><span class="operator">&gt;</span>event();

             <span class="type"><a href="qkeyevent.html">QKeyEvent</a></span> <span class="operator">*</span>keyEvent <span class="operator">=</span> <span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="type"><a href="qkeyevent.html">QKeyEvent</a></span> <span class="operator">*</span><span class="operator">&gt;</span>(wrappedEvent);
             <span class="type">int</span> key <span class="operator">=</span> keyEvent<span class="operator">-</span><span class="operator">&gt;</span>key();

             <span class="keyword">return</span> key <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_2 <span class="operator">|</span><span class="operator">|</span> key <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_8 <span class="operator">|</span><span class="operator">|</span> key <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_6 <span class="operator">|</span><span class="operator">|</span>
                    key <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_4 <span class="operator">|</span><span class="operator">|</span> key <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Down <span class="operator">|</span><span class="operator">|</span> key <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Up <span class="operator">|</span><span class="operator">|</span>
                    key <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Right <span class="operator">|</span><span class="operator">|</span> key <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Left;
         }
         <span class="keyword">return</span> <span class="keyword">false</span>;
     }</pre>
<p>The KeyPress events come wrapped in <a href="qstatemachine-wrappedevent.html">QStateMachine::WrappedEvent</a>s. <tt>event</tt> must be confirmed to be a wrapped event because Qt uses other events internally. After that, it is simply a matter of checking which key has been pressed.</p>
<p>Let's move on to the <tt>onTransition()</tt> function:</p>
<pre class="cpp">     <span class="type">void</span> onTransition(<span class="type"><a href="qevent.html">QEvent</a></span> <span class="operator">*</span>event) {
         <span class="type"><a href="qkeyevent.html">QKeyEvent</a></span> <span class="operator">*</span>keyEvent <span class="operator">=</span> <span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="type"><a href="qkeyevent.html">QKeyEvent</a></span> <span class="operator">*</span><span class="operator">&gt;</span>(
             <span class="keyword">static_cast</span><span class="operator">&lt;</span><span class="type"><a href="qstatemachine.html">QStateMachine</a></span><span class="operator">::</span>WrappedEvent <span class="operator">*</span><span class="operator">&gt;</span>(event)<span class="operator">-</span><span class="operator">&gt;</span>event());

         <span class="type">int</span> key <span class="operator">=</span> keyEvent<span class="operator">-</span><span class="operator">&gt;</span>key();
         <span class="keyword">switch</span> (key) {
             <span class="keyword">case</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Left:
             <span class="keyword">case</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_4:
                 window<span class="operator">-</span><span class="operator">&gt;</span>movePlayer(Window<span class="operator">::</span>Left);
                 <span class="keyword">break</span>;
             <span class="keyword">case</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Up:
             <span class="keyword">case</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_8:
                 window<span class="operator">-</span><span class="operator">&gt;</span>movePlayer(Window<span class="operator">::</span>Up);
                 <span class="keyword">break</span>;
             <span class="keyword">case</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Right:
             <span class="keyword">case</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_6:
                 window<span class="operator">-</span><span class="operator">&gt;</span>movePlayer(Window<span class="operator">::</span>Right);
                 <span class="keyword">break</span>;
             <span class="keyword">case</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_Down:
             <span class="keyword">case</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>Key_2:
                 window<span class="operator">-</span><span class="operator">&gt;</span>movePlayer(Window<span class="operator">::</span>Down);
                 <span class="keyword">break</span>;
             <span class="keyword">default</span>:
                 ;
         }
     }</pre>
<p>When <tt>onTransition()</tt> is invoked, we know that we have a <a href="qevent.html#Type-enum">KeyPress</a> event with 2, 4, 6, or 8, and can ask <tt>Window</tt> to move the player.</p>
<a name="the-roguelike-tradition"></a>
<h2>The Roguelike Tradition</h2>
<p>You might have been wondering why the game features a rogue. Well, these kinds of text based dungeon exploration games date back to a game called, yes, &quot;Rogue&quot;. Although outflanked by the technology of modern 3D computer games, roguelikes have a solid community of hard-core, devoted followers.</p>
<p>Playing these games can be surprisingly addictive (despite the lack of graphics). Angband, the perhaps most well-known rougelike, is found here: <a href="http://rephial.org/">http://rephial.org/</a>.</p>
</div>
<!-- @@@statemachine/rogue -->
  <div class="ft">
    <span></span>
  </div>
</div> 
<div class="footer">
    <p>
      <acronym title="Copyright">&copy;</acronym> 2012 Nokia Corporation and/or its
      subsidiaries. Documentation contributions included herein are the copyrights of
      their respective owners.</p>
    <br />
    <p>
      The documentation provided herein is licensed under the terms of the
      <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation
      License version 1.3</a> as published by the Free Software Foundation.</p>
    <p>
      Documentation sources may be obtained from <a href="http://www.qt-project.org">
      www.qt-project.org</a>.</p>
    <br />
    <p>
      Nokia, Qt and their respective logos are trademarks of Nokia Corporation 
      in Finland and/or other countries worldwide. All other trademarks are property
      of their respective owners. <a title="Privacy Policy"
      href="http://en.gitorious.org/privacy_policy/">Privacy Policy</a></p>
</div>
</body>
</html>