<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>libQGLViewer agora example</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <link href="../qglviewer.css" rel="stylesheet" type="text/css" /> <link rel="shortcut icon" href="../images/qglviewer.ico" type="image/x-icon" /> <link rel="icon" href="../images/qglviewer.icon.png" type="image/png" /> </head> <body> <table class="banner"> <tr> <td align="center"><a href="../index.html"><b>Home</b></a></td> <td align="center"><a href="../refManual/hierarchy.html"><b>Documentation</b></a></td> <td align="center"><a href="../download.html"><b>Download</b></a></td> <td align="center" class="qindexHL"><a href="index.html"><b>Screenshots</b></a></td> <td align="center"><a href="../developer.html"><b>Developer</b></a></td> </tr> </table> <h1>The agora example</h1> <center> <img src="../images/agora.jpg" width="300" height="200" alt="agora"/> </center> <p> Implementation of the game of <i>Agora</i>. </p> <p> <i>Agora</i> is a strategy game for two players. The code is rather complex and can be divided in two parts : a QGLViewer implementation for the viewer and an artificial intelligence that allows you to play against the computer. </p> <p> You should find the rules of the game on the web. Questions relative to the artificial intelligence implementation should be asked to <code>Jean-Guillaume dot Dumas at imag dot fr</code>. </p> <h2>agora.h</h2> <pre> <span class="com">// =================================================================== // </span><span class="com">// Time-stamp: <01 Jul 03 16:27:25 Jean-Guillaume.Dumas@imag.fr> </span><span class="com">// =================================================================== // </span><span class="dir">#ifndef __Agora_Plateau__ </span><span class="dir">#define __Agora_Plateau__ </span> <span class="dir">#include <iostream> </span><span class="dir">#include <vector> </span><span class="dir">#include </span><span class="dstr">"givtimer.h"</span><span class="dir"> </span> <span class="dir">#define SHORTCOULEURMASK 32768 </span> <span class="dir">#define WHITE false </span><span class="dir">#define BLACK true </span> <span class="dir">#define ADVANCEDRULES </span> <span class="dir">#include </span><span class="dstr">"agora_class.h"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_io.h"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_types.h"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_coup.h"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_container.h"</span><span class="dir"> </span> <span class="key">template</span><<span class="key">class </span>Ints> <span class="key">class </span>Agora : <span class="key">public </span>std::vector<Ints> { <span class="key">public</span>: <span class="key">typedef </span>Agora< Ints > Self_t; <span class="key">typedef </span>Ints Pile_t; <span class="key">typedef </span>std::vector<Pile_t> Plateau_t; <span class="key">typedef </span>std::vector< std::vector< Case_t > > Voisin_t; <span class="key">typedef </span>AgoraCoup Coup; <span class="key">typedef </span>AgoraContainer<<span class="num">256</span>, Coup> Possible_t; <span class="key">typedef </span>std::vector< Possible_t > Table_Possible_t; <span class="key">typedef </span>std::vector<Eval_t> Table_Eval_t; <span class="key">private</span>: Case_t _row, _size; Possible_t TopPM; Table_Possible_t _PM; Hauteur_t _bits; Size_t _bsize; Table_t _hauteurs, _uns, _pris, _altitude; Table_Eval_t _eval; Plateau_t _enleve, _ajoute_noir, _ajoute_blanc, _ajoute_prison; Voisin_t _voisins; <span class="key">public</span>: Agora(<span class="typ">int </span>n = <span class="num">6</span>) ; <span class="typ">void </span>reinit() ; <span class="com">// Tabulées </span> <span class="typ">bool </span>couleur(<span class="typ">const </span>Pile_t p) <span class="typ">const </span>; Hauteur_t taille( <span class="typ">const </span>Pile_t i ) <span class="typ">const</span>; Hauteur_t uns( <span class="typ">const </span>Pile_t i ) <span class="typ">const</span>; Hauteur_t pris( <span class="typ">const </span>Pile_t i ) <span class="typ">const</span>; Eval_t eval( <span class="typ">const </span>Pile_t i ) <span class="typ">const</span>; <span class="com">// Calculée </span> <span class="typ">bool </span>ArriveeRevolution( <span class="typ">const </span>Coup& c) <span class="typ">const</span>; <span class="typ">bool </span>DepartRevolution( <span class="typ">const </span>Coup& c) <span class="typ">const</span>; <span class="com">// Tabulées </span> Pile_t enleve( <span class="typ">const </span>Pile_t p ) <span class="typ">const</span>; Pile_t ajoute_noir( <span class="typ">const </span>Pile_t p ) <span class="typ">const </span>; Pile_t ajoute_blanc( <span class="typ">const </span>Pile_t p ) <span class="typ">const </span>; Pile_t ajoute_prison( <span class="typ">const </span>Pile_t p) <span class="typ">const </span>; <span class="com">// Initialisation </span> Pile_t init( <span class="typ">const </span>Case_t i, <span class="typ">const </span>Pile_t p ) ; <span class="com">// Jouer </span> <span class="typ">bool </span>jouer( <span class="typ">const </span>Coup& c ) ; <span class="typ">bool </span>jouer( <span class="typ">const </span>Case_t depart, <span class="typ">const </span>Case_t arrivee, <span class="typ">const bool </span>dessus ); <span class="typ">bool </span>jouer( <span class="typ">const </span>Case_t depart, Pile_t& ancien_d, <span class="typ">const </span>Case_t arrivee, Pile_t& ancien_a, <span class="typ">const bool </span>dessus ); <span class="typ">bool </span>jouer_dessus( <span class="typ">const </span>Case_t depart, Pile_t& ancien_d, <span class="typ">const </span>Case_t arrivee, Pile_t& ancien_a ) ; <span class="typ">bool </span>jouer_dessous( <span class="typ">const </span>Case_t depart, Pile_t& ancien_d, <span class="typ">const </span>Case_t arrivee, Pile_t& ancien_a ); <span class="typ">void </span>jouer( <span class="typ">const </span>Case_t depart, Pile_t& ancien_d, Pile_t& new_d, <span class="typ">const </span>Case_t arrivee, Pile_t& ancien_a, Pile_t& new_a, <span class="typ">const bool </span>dessus ); <span class="typ">void </span>jouer_dessus( <span class="typ">const </span>Case_t depart, Pile_t& ancien_d, Pile_t& new_d, <span class="typ">const </span>Case_t arrivee, Pile_t& ancien_a, Pile_t& new_a ) ; <span class="typ">void </span>jouer_dessous( <span class="typ">const </span>Case_t depart, Pile_t& ancien_d, Pile_t& new_d, <span class="typ">const </span>Case_t arrivee, Pile_t& ancien_a, Pile_t& new_a ); <span class="typ">void </span>remettre( <span class="typ">const </span>Case_t depart, <span class="typ">const </span>Pile_t ancien_d, <span class="typ">const </span>Case_t arrivee, <span class="typ">const </span>Pile_t ancien_a ) ; <span class="com">// Fonction d'évaluation </span> <span class="typ">double</span>& eval(<span class="typ">double</span>& e, <span class="typ">const </span>Pile_t p) <span class="typ">const</span>; <span class="typ">double</span>& uneval(<span class="typ">double</span>& e, <span class="typ">const </span>Pile_t p) <span class="typ">const</span>; <span class="typ">double</span>& eval(<span class="typ">double</span>& e, <span class="typ">const </span>Pile_t dep, <span class="typ">const </span>Pile_t ndep, <span class="typ">const </span>Pile_t arr, <span class="typ">const </span>Pile_t narr) <span class="typ">const </span>; <span class="typ">double </span>eval() <span class="typ">const </span>; <span class="com">// Meilleur coup </span> <span class="com">// Default : temps limité, mais si depth > 0 --> profondeur fixée </span> Coup& Suggest(Coup& bp, <span class="typ">bool </span>ordi_color, <span class="typ">double </span>temps_max, <span class="typ">int </span>depth = <span class="num">0</span>); <span class="com">// Coups possibles </span> <span class="typ">bool </span>gameIsOver() ; <span class="typ">bool </span>gameIsOver(<span class="typ">bool </span>color) ; Possible_t& CoupsVoisinsBlancs(Possible_t& Liste, <span class="typ">const </span>Case_t i) <span class="typ">const </span>; Possible_t& CoupsVoisinsNoirs(Possible_t& Liste, <span class="typ">const </span>Case_t i) <span class="typ">const </span>; Possible_t& CoupsVoisins(Possible_t& Liste, <span class="typ">const </span>Case_t i) <span class="typ">const </span>; Possible_t& CoupsPossibles(Possible_t& Liste, <span class="typ">const bool </span>c) <span class="typ">const </span>; <span class="key">private</span>: <span class="dir">#ifdef __ERRORS__ </span> <span class="typ">unsigned long long </span>_count; <span class="dir">#endif </span> <span class="com">// Construction </span> <span class="typ">void </span>voisin_g(<span class="typ">const </span>Case_t j, typename Voisin_t::value_type & loc) <span class="typ">const </span>; <span class="typ">void </span>voisin_d(<span class="typ">const </span>Case_t j, typename Voisin_t::value_type & loc) <span class="typ">const </span>; <span class="typ">void </span>voisin(<span class="typ">const </span>Case_t j, typename Voisin_t::value_type & loc) <span class="typ">const </span>; <span class="com">// Calculs initiaux pour tabulation </span> Pile_t& calcule_enleve(Pile_t & r, <span class="typ">const </span>Hauteur_t t, <span class="typ">const </span>Hauteur_t u, <span class="typ">const </span>Pile_t p) <span class="typ">const </span>; Pile_t& calcule_prison(Pile_t& a, <span class="typ">const </span>Hauteur_t t, <span class="typ">const </span>Hauteur_t u, <span class="typ">const </span>Pile_t p) <span class="typ">const </span>; Pile_t& calcule_ajoute(Pile_t & r_noir, Pile_t& r_blanc, <span class="typ">const </span>Hauteur_t t, <span class="typ">const </span>Hauteur_t u, <span class="typ">const </span>Pile_t p) <span class="typ">const </span>; Hauteur_t& calcule_hauteur(Hauteur_t& h, Hauteur_t& u, Hauteur_t& pris, <span class="typ">const </span>Pile_t p) <span class="typ">const </span>; Pile_t& calcule_revol(Pile_t& r, <span class="typ">const </span>Hauteur_t t, <span class="typ">const </span>Pile_t p) <span class="typ">const </span>; Eval_t& calcule_eval(Eval_t& ev, <span class="typ">const </span>Hauteur_t t, <span class="typ">const </span>Hauteur_t u, <span class="typ">const </span>Pile_t p) <span class="typ">const </span>; <span class="com">// Optimisations Branch and Cut </span> <span class="typ">double </span>ami_ab(<span class="typ">int </span>depth, <span class="typ">double </span>alpha, <span class="typ">double </span>beta, <span class="typ">bool </span>ordi_color); <span class="typ">double </span>ennemi_ab(<span class="typ">int </span>depth, <span class="typ">double </span>alpha, <span class="typ">double </span>beta, <span class="typ">bool </span>ordi_color) ; <span class="typ">double </span>ami_ab(<span class="typ">int </span>depth, <span class="typ">double </span>alpha, <span class="typ">double </span>beta, <span class="typ">bool </span>ordi_color, <span class="typ">double </span>currev, <span class="typ">const </span>Pile_t ad, <span class="typ">const </span>Pile_t nd, <span class="typ">const </span>Pile_t aa, <span class="typ">const </span>Pile_t na); <span class="typ">double </span>ennemi_ab(<span class="typ">int </span>depth, <span class="typ">double </span>alpha, <span class="typ">double </span>beta, <span class="typ">bool </span>ordi_color, <span class="typ">double </span>currev, <span class="typ">const </span>Pile_t ad, <span class="typ">const </span>Pile_t nd, <span class="typ">const </span>Pile_t aa, <span class="typ">const </span>Pile_t na) ; <span class="com">// Meilleur coup en temps limité </span> Coup& Iteratif(Coup& bp, <span class="typ">bool </span>ordi_color, <span class="typ">double </span>temps_max, <span class="typ">int </span>StartProf) ; <span class="com">// Meilleur coup à profondeur fixée </span> <span class="typ">double </span>BestPlay(Coup& bp, <span class="typ">bool </span>ordi_color, <span class="typ">int </span>depth); <span class="key">inline </span><span class="typ">double </span>MTDFdouble(<span class="typ">int </span>depth, <span class="typ">double </span>f, <span class="typ">bool </span>ordi_color) ; <span class="typ">double </span>OnebyOneBP(Coup& bp, <span class="typ">bool </span>ordi_color, <span class="typ">int </span>depth, <span class="typ">double </span>temps_max, Timer& global) ; <span class="com">// Possiblité de coup </span> <span class="com">// Pour l'instant isolé interdit </span> <span class="typ">bool </span>calcule_poss_dessus_noir(<span class="typ">const bool </span>c, <span class="typ">const </span>Hauteur_t t) <span class="typ">const </span>; <span class="typ">bool </span>calcule_poss_dessous_noir(<span class="typ">const bool </span>c, <span class="typ">const </span>Hauteur_t t) <span class="typ">const </span>; <span class="typ">bool </span>calcule_poss_dessus_blanc(<span class="typ">const bool </span>c, <span class="typ">const </span>Hauteur_t t) <span class="typ">const </span>; <span class="typ">bool </span>calcule_poss_dessous_blanc(<span class="typ">const bool </span>c, <span class="typ">const </span>Hauteur_t t) <span class="typ">const </span>; Hauteur_t calcule_poss_blancs(Possible_t& Liste, <span class="typ">const </span>Case_t depart, <span class="typ">const </span>Hauteur_t hdepalt, <span class="typ">const </span>Case_t arrivee) <span class="typ">const </span>; Hauteur_t calcule_poss_noirs(Possible_t& Liste, <span class="typ">const </span>Case_t depart, <span class="typ">const </span>Hauteur_t hdepalt, <span class="typ">const </span>Case_t arrivee) <span class="typ">const </span>; <span class="com">// Entrées/Sorties </span> <span class="key">friend </span>std::ostream& <span class="key">operator</span><< <>(std::ostream& out, <span class="typ">const </span>Agora& p) ; <span class="key">friend </span>std::ostream& affiche <>(std::ostream& out, <span class="typ">const </span>Agora& p) ; <span class="key">friend </span>std::ostream& details <>(std::ostream& out, <span class="typ">const </span>Agora& p) ; <span class="key">friend </span>std::istream& <span class="key">operator</span>>> <>(std::istream& in, Agora& p) ; }; <span class="dir">#include </span><span class="dstr">"agora_init.inl"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_io.inl"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_jouer.inl"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_evaluation.inl"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_alphabeta.inl"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora_coupspossibles.inl"</span><span class="dir"> </span><span class="dir">#endif</span></pre> <h2>agoraViewer.h</h2> <pre> <span class="dir">#include </span><span class="dstr">"QGLViewer/qglviewer.h"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agora.h"</span><span class="dir"> </span> <span class="key">typedef </span>Agora<<span class="typ">unsigned short</span>> Agora_t; <span class="key">typedef </span>Agora_t::Pile_t Pile; <span class="key">typedef </span>Agora_t::Coup Play; <span class="key">typedef </span>Case_t Position; <span class="key">typedef </span>Agora_t::Possible_t Possibles; <span class="key">class </span>AgoraViewer : <span class="key">public </span>QGLViewer { Q_OBJECT <span class="key">public</span>: AgoraViewer(QWidget* parent=NULL, <span class="typ">const char</span>* name=<span class="num">0</span>); <span class="key">public </span>slots: <span class="com">// F i l e m e n u </span> <span class="typ">void </span>load(); <span class="typ">void </span>save(); <span class="typ">void </span>saveAs(); <span class="typ">void </span>print() { std::cout << <span class="str">"Print not yet implemented"</span> << std::endl; } <span class="com">// G a m e m e n u </span> <span class="typ">void </span>undo(); <span class="typ">void </span>redo(); <span class="typ">void </span>startNewGame() { initGame(); updateGL(); } <span class="typ">void </span>suggestPlay() { play_ = agora.Suggest(play_, blackPlay_, gameLevel_.computerMaxReflexionTime_, gameLevel_.computerMaxDepth_); play(); } <span class="typ">void </span>togglePlayAgainstComputer(<span class="typ">bool </span>on); <span class="typ">void </span>levelIsEasy() { gameLevel_.computerMaxDepth_ = <span class="num">3</span>; } <span class="typ">void </span>levelIsAverage() { gameLevel_.computerMaxReflexionTime_ = <span class="num">1.5</span>; gameLevel_.computerMaxDepth_ = <span class="num">0</span>; } <span class="typ">void </span>levelIsDifficult() { gameLevel_.computerMaxReflexionTime_ = <span class="num">8.0</span>; gameLevel_.computerMaxDepth_ = <span class="num">0</span>; } <span class="typ">void </span>toggleComputerIsBlack(<span class="typ">bool </span>black) { computerIsBlack_ = black; } <span class="com">// D i s p l a y m e n u </span> <span class="typ">void </span>toggleAnimation(<span class="typ">bool </span>on) { animatePlays_ = on; } <span class="typ">void </span>toggleLight(<span class="typ">bool </span>on) { <span class="key">if </span>(on) glEnable(GL_LIGHT1); <span class="key">else </span>glDisable(GL_LIGHT1); updateGL(); } <span class="typ">void </span>toggleTexture(<span class="typ">bool </span>on) { textures_ = on; updateGL(); } <span class="typ">void </span>toggleShowPossible(<span class="typ">bool </span>on) { displayPossibleDestination_ = on; updateGL(); } <span class="com">// H e l p m e n u </span> <span class="typ">void </span>help(); <span class="typ">void </span>about(); <span class="key">protected </span>: <span class="typ">void </span>draw(); <span class="typ">void </span>mouseDoubleClickEvent(QMouseEvent *) {}; <span class="typ">void </span>keyPressEvent(QKeyEvent *) {}; <span class="typ">void </span>select(<span class="typ">const </span>QMouseEvent*); <span class="typ">void </span>init(); <span class="typ">void </span>play(); <span class="key">private </span>slots: <span class="typ">void </span>simplePlay(); <span class="key">private </span>: <span class="com">// D r a w i n g f u n c t i o n s </span> <span class="typ">void </span>drawAgora() <span class="typ">const</span>; <span class="typ">void </span>drawAllPieces(<span class="typ">bool </span>select = <span class="key">false</span>) <span class="typ">const</span>; <span class="typ">void </span>drawPiece() <span class="typ">const</span>; <span class="typ">void </span>highlightSelectedPiece() <span class="typ">const</span>; <span class="typ">void </span>drawPossibleDestinations(<span class="typ">bool </span>select = <span class="key">false</span>) <span class="typ">const</span>; <span class="com">// D r a w i n g u t i l s </span> <span class="typ">void </span>drawBorder(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">bool </span>out=<span class="key">true</span>, <span class="typ">float </span>heightMin=<span class="num">0.0</span>) <span class="typ">const</span>; <span class="typ">void </span>drawBorderLines(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">bool </span>out=<span class="key">true</span>, <span class="typ">float </span>heightMin=<span class="num">0.0</span>) <span class="typ">const</span>; <span class="typ">void </span>drawFace(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">bool </span>up) <span class="typ">const</span>; <span class="typ">void </span>drawRing(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">float </span>thickness=<span class="num">1.0</span>) <span class="typ">const</span>; <span class="typ">void </span>drawSeparatingBars(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">float </span>thickness=<span class="num">1.0</span>) <span class="typ">const</span>; <span class="typ">void </span>drawLeveLines(<span class="typ">float </span>width, <span class="typ">float </span>height) <span class="typ">const</span>; <span class="com">// I n i t i a l i z a t i o n </span> <span class="typ">void </span>initSpotLight(); <span class="typ">void </span>initCamera(); <span class="typ">void </span>initViewer(); <span class="typ">void </span>initGame(); <span class="com">// G a m e i n t e r f a c e </span> <span class="typ">void </span>reactToSelection(<span class="typ">int </span>selected, <span class="typ">bool </span>onTop); <span class="typ">void </span>updatePiecePositions(); <span class="typ">int </span>higherPieceOnPosition(Position pos) <span class="typ">const</span>; <span class="typ">void </span>animatePlay(); <span class="typ">void </span>deselect(); <span class="com">// Size of one Agora position is 1.0, entire board is hence 6.0 x 6.0. </span> <span class="typ">static const float </span>pieceSize = <span class="num">29.0 </span>/ <span class="num">38.0</span>; <span class="typ">static const float </span>pieceHeight = <span class="num">5.0 </span>/ <span class="num">38.0</span>; qglviewer::Vec normal[<span class="num">5</span>]; Agora_t agora; Play play_; <span class="typ">bool </span>blackPlay_; <span class="typ">bool </span>computerIsBlack_; <span class="key">struct </span>AgoraLevel { <span class="typ">float </span>computerMaxReflexionTime_; <span class="typ">int </span>computerMaxDepth_; } gameLevel_; <span class="typ">int </span>selectedPiece_; <span class="typ">bool </span>playerIsComputer_; <span class="typ">bool </span>gameIsOver_; <span class="com">// D i s p l a y F l a g s </span> <span class="typ">bool </span>displayPossibleDestination_; <span class="typ">bool </span>animatePlays_; <span class="typ">bool </span>textures_; <span class="key">struct </span>Piece { Position square; <span class="typ">bool </span>isBlack; qglviewer::Frame frame; <span class="typ">float </span>scale; <span class="typ">int </span>level; }; Piece piece_[<span class="num">16</span>]; qglviewer::Vec casePosition[<span class="num">36</span>]; Possibles possibleDest_; qglviewer::KeyFrameInterpolator kfi_[<span class="num">16</span>]; QString fileName; <span class="key">struct </span>Undo { Undo() {}; Undo(<span class="typ">const </span>Play& play, <span class="typ">const </span>Agora_t& agora); Position pos1, pos2; Pile before1, before2; Pile after1, after2; }; std::vector<Undo> history_; <span class="typ">void </span>updateUndoHistory(<span class="typ">bool </span>before); <span class="typ">unsigned int </span>undoIndex_, maxUndoIndex_; };</pre> <h2>agoraWindow.ui.h</h2> <pre> <span class="com">/**************************************************************************** ** ui.h extension file, included from the uic-generated form implementation. ** ** If you wish to add, delete or rename slots use Qt Designer which will ** update this file, preserving your code. Create an init() slot in place of ** a constructor, and a destroy() slot in place of a destructor. *****************************************************************************/</span> </pre> <h2>agora_class.h</h2> <pre> <span class="com">// =================================================================== // </span><span class="com">// Time-stamp: <19 Jun 03 15:53:22 Jean-Guillaume.Dumas@imag.fr> </span><span class="com">// =================================================================== // </span><span class="dir">#ifndef __Agora_Class__ </span><span class="dir">#define __Agora_Class__ </span> <span class="key">template</span><<span class="key">class </span>Ints = <span class="typ">unsigned short</span>> <span class="key">class </span>Agora ; <span class="dir">#endif</span></pre> <h2>agora_container.h</h2> <pre> <span class="com">// =================================================================== // </span><span class="com">// Time-stamp: <23 Jun 03 10:42:45 Jean-Guillaume.Dumas@imag.fr> </span><span class="com">// =================================================================== // </span><span class="dir">#ifndef __Agora_Container__ </span><span class="dir">#define __Agora_Container__ </span> <span class="com">// #include <vector> </span><span class="com">// typedef std::vector AgoraContainer; </span> <span class="dir">#include <iostream> </span> <span class="key">template</span><<span class="typ">int </span>POSS_SIZE, typename Elem> <span class="key">struct </span>AgoraContainer { <span class="key">private</span>: <span class="key">typedef </span>AgoraContainer<POSS_SIZE, Elem> Self_t; Elem _container[ POSS_SIZE ]; Elem * _finish; <span class="key">public</span>: <span class="key">typedef </span>Elem* iterator; <span class="key">typedef </span><span class="typ">const </span>Elem* const_iterator; AgoraContainer() : _finish(_container) { } AgoraContainer(<span class="typ">int </span>s) : _finish(_container+s) { } Case_t size() <span class="typ">const </span>{ <span class="key">return </span>Case_t(_finish - _container); } <span class="typ">void </span>clear() { _finish = _container; } <span class="typ">void </span>resize(<span class="typ">int </span>s) { _finish = _container + s; } iterator begin() { <span class="key">return </span>_container; } iterator end() { <span class="key">return </span>_finish; } const_iterator begin() <span class="typ">const </span>{ <span class="key">return </span>const_iterator(_container); } const_iterator end() <span class="typ">const </span>{ <span class="key">return </span>const_iterator(_finish); } <span class="typ">void </span>push_back(<span class="typ">const </span>Elem& c) { *_finish = c; ++_finish; } }; <span class="dir">#endif</span></pre> <h2>agora_coup.h</h2> <pre> <span class="com">// =================================================================== // </span><span class="com">// Time-stamp: <20 Jun 03 18:45:45 Jean-Guillaume.Dumas@imag.fr> </span><span class="com">// =================================================================== // </span><span class="dir">#ifndef __Agora_Coup__ </span><span class="dir">#define __Agora_Coup__ </span><span class="dir">#include </span><span class="dstr">"agora_types.h"</span><span class="dir"> </span><span class="dir">#include <iostream> </span> <span class="key">struct </span>AgoraCoup { AgoraCoup() {} AgoraCoup(Case_t d, Case_t a, <span class="typ">bool </span>b) : _depart(d), _arrivee(a), _dessus(b) {} Case_t depart() <span class="typ">const </span>{ <span class="key">return </span>_depart; } Case_t arrivee() <span class="typ">const </span>{ <span class="key">return </span>_arrivee; } <span class="typ">bool </span>dessus() <span class="typ">const </span>{ <span class="key">return </span>_dessus; } <span class="typ">void </span>copy( <span class="typ">const </span>AgoraCoup& c) { _depart = c._depart; _arrivee = c._arrivee; _dessus = c._dessus; } <span class="typ">bool </span><span class="key">operator</span>==( <span class="typ">const </span>AgoraCoup& c) { <span class="key">return </span>( (_depart == c._depart) && (_arrivee == c._arrivee) && (_dessus == c._dessus) ); } <span class="key">friend </span>std::ostream& <span class="key">operator</span><< (std::ostream& out, <span class="typ">const </span>AgoraCoup& c) { <span class="key">return </span>out << (Size_t)(c._depart) << (c._dessus?<span class="str">"/"</span>:<span class="str">"</span><span class="esc">\\</span><span class="str">"</span>) << (Size_t)(c._arrivee); } <span class="key">friend </span>std::istream& <span class="key">operator</span>>> (std::istream& in, AgoraCoup& c) { <span class="typ">char </span>s; Size_t d, a; in >> d >> s >> a; c._depart = (Case_t)d; c._arrivee = (Case_t)a; <span class="key">if </span>(s == <span class="str">'/'</span>) c._dessus = <span class="num">1</span>; <span class="key">else </span>c._dessus = <span class="num">0</span>; <span class="key">return </span>in; } <span class="key">private</span>: Case_t _depart, _arrivee; <span class="typ">bool </span>_dessus; }; <span class="dir">#endif</span></pre> <h2>agora_io.h</h2> <pre> <span class="com">// =================================================================== // </span><span class="com">// Time-stamp: <24 Jun 03 14:51:09 Jean-Guillaume.Dumas@imag.fr> </span><span class="com">// =================================================================== // </span><span class="dir">#ifndef __Agora_IO_H__ </span><span class="dir">#define __Agora_IO_H__ </span> <span class="dir">#include </span><span class="dstr">"agora_class.h"</span><span class="dir"> </span> <span class="key">template</span><<span class="key">class </span>Ints> std::ostream& <span class="key">operator</span><< (std::ostream& out, <span class="typ">const </span>Agora<Ints>& p) ; <span class="key">template</span><<span class="key">class </span>Ints> std::ostream& details (std::ostream& out, <span class="typ">const </span>Agora<Ints>& p) ; <span class="key">template</span><<span class="key">class </span>Ints> std::ostream& affiche (std::ostream& out, <span class="typ">const </span>Agora<Ints>& p) ; <span class="key">template</span><<span class="key">class </span>Ints> std::istream& <span class="key">operator</span>>> (std::istream& in, Agora<Ints>& p) ; <span class="dir">#endif</span></pre> <h2>agora_types.h</h2> <pre> <span class="com">// =================================================================== // </span><span class="com">// Time-stamp: <30 Jun 03 18:50:44 Jean-Guillaume.Dumas@imag.fr> </span><span class="com">// =================================================================== // </span><span class="dir">#ifndef __Agora_Types__ </span><span class="dir">#define __Agora_Types__ </span> <span class="dir">#include <vector> </span><span class="key">typedef </span><span class="typ">short </span>Eval_t; <span class="key">typedef </span><span class="typ">unsigned short </span>Hauteur_t; <span class="key">typedef </span><span class="typ">unsigned long </span>Size_t; <span class="key">typedef </span><span class="typ">unsigned short </span>Case_t; <span class="key">typedef </span>std::vector<Hauteur_t> Table_t; <span class="dir">#endif</span></pre> <h2>container_stream.h</h2> <pre> <span class="com">// =================================================================== // </span><span class="com">// Time-stamp: <20 Jun 03 18:42:27 Jean-Guillaume.Dumas@imag.fr> </span><span class="com">// =================================================================== // </span><span class="dir">#ifndef __CONTAINER_STREAM__ </span><span class="dir">#define __CONTAINER_STREAM__ </span> <span class="dir">#include <iostream> </span><span class="key">template</span><<span class="key">class </span>T, <span class="key">template </span><<span class="key">class </span>T> <span class="key">class </span>Container > std::ostream& <span class="key">operator</span><< (std::ostream& o, <span class="typ">const </span>Container<T>& v) { o << <span class="str">"["</span>; typename Container<T>::const_iterator vi = v.begin(); <span class="key">for</span>( ; vi != v.end(); ++vi) o << *vi << <span class="str">" "</span>; <span class="key">return </span>o << <span class="str">"]"</span>; } <span class="key">template</span><<span class="typ">int </span>I, <span class="key">class </span>T, <span class="key">template </span><<span class="typ">int </span>I, <span class="key">class </span>T> <span class="key">class </span>Container > std::ostream& <span class="key">operator</span><< (std::ostream& o, <span class="typ">const </span>Container<I,T>& v) { o << <span class="str">"["</span>; typename Container<I,T>::const_iterator vi = v.begin(); <span class="key">for</span>( ; vi != v.end(); ++vi) o << *vi << <span class="str">" "</span>; <span class="key">return </span>o << <span class="str">"]"</span>; } <span class="dir">#endif</span></pre> <h2>givtimer.h</h2> <pre> <span class="dir">#ifndef _TIMER_H_ </span><span class="dir">#define _TIMER_H_ </span><span class="com">// ========================================================================== </span><span class="com">// $Source: /local/cvs/Agora/givtimer.h,v $ </span><span class="com">// Copyright(c)'94-97 by Givaro Team </span><span class="com">// see the copyright file. </span><span class="com">// Authors: T. Gautier </span><span class="com">// $Id: givtimer.h,v 1.1.1.1 2003/06/20 13:03:43 jgdumas Exp $ </span><span class="com">// ========================================================================== </span><span class="com">// Description: </span> <span class="dir">#include <iostream> </span> <span class="com">// class RealTimer; class SysTimer; class UserTimer; </span> <span class="key">class </span>BaseTimer { <span class="key">public</span>: <span class="key">enum </span>{ MSPSEC = <span class="num">1000000 </span><span class="com">// microsecond per second </span>}; <span class="com">// -- Clear timer : </span> <span class="key">inline </span><span class="typ">void </span>clear() { _t = <span class="num">0</span>; } <span class="com">// -- total amount of second spent </span> <span class="key">inline </span><span class="typ">double </span>time() <span class="typ">const </span>{ <span class="key">return </span>_t; } <span class="com">// -- Return a value to initialize random generator </span><span class="typ">static long </span>seed(); <span class="com">// -- basic methods: </span> std::ostream& print( std::ostream& ) <span class="typ">const</span>; <span class="com">// -- Some arithmetic operators to compute cumulative time : </span> BaseTimer& <span class="key">operator </span>= (<span class="typ">const </span>BaseTimer & T) ; <span class="typ">const </span>BaseTimer <span class="key">operator </span>- (<span class="typ">const </span>BaseTimer & T) <span class="typ">const</span>; <span class="typ">const </span>BaseTimer <span class="key">operator </span>- () ; <span class="typ">const </span>BaseTimer <span class="key">operator </span>+ (<span class="typ">const </span>BaseTimer & T) <span class="typ">const</span>; <span class="typ">const </span>BaseTimer <span class="key">operator </span>+= (<span class="typ">const </span>BaseTimer & T) { <span class="key">return </span>*<span class="key">this </span>= *<span class="key">this </span>+ T; }; <span class="typ">const </span>BaseTimer <span class="key">operator </span>-= (<span class="typ">const </span>BaseTimer & T) { <span class="key">return </span>*<span class="key">this </span>= *<span class="key">this </span>- T; }; <span class="key">public</span>: <span class="typ">double </span>_t; <span class="com">// time </span>}; <span class="key">inline </span>std::ostream& <span class="key">operator</span><< (std::ostream& o, <span class="typ">const </span>BaseTimer& BT) { <span class="key">return </span>BT.print(o);} <span class="key">class </span>RealTimer : <span class="key">public </span>BaseTimer { <span class="key">public</span>: <span class="key">inline </span>RealTimer( <span class="typ">const </span>BaseTimer& BT ): BaseTimer(BT) {}; <span class="key">inline </span>RealTimer( ){}; <span class="typ">void </span>start(); <span class="typ">void </span>stop(); }; <span class="key">class </span>UserTimer : <span class="key">public </span>BaseTimer { <span class="key">public</span>: <span class="key">inline </span>UserTimer( <span class="typ">const </span>BaseTimer& BT ): BaseTimer(BT) {}; <span class="key">inline </span>UserTimer( ) {}; <span class="typ">void </span>start(); <span class="typ">void </span>stop(); }; <span class="key">class </span>SysTimer : <span class="key">public </span>BaseTimer { <span class="key">public</span>: <span class="key">inline </span>SysTimer( <span class="typ">const </span>BaseTimer& BT ): BaseTimer(BT) {}; <span class="key">inline </span>SysTimer( ) {}; <span class="typ">void </span>start(); <span class="typ">void </span>stop(); }; <span class="key">class </span>Timer { <span class="key">public </span>: <span class="com">// Clear timer : </span> <span class="typ">void </span>clear(); <span class="com">// Start timer </span> <span class="typ">void </span>start(); <span class="com">// Stop timer </span> <span class="typ">void </span>stop(); <span class="com">// total amount of second spent in user mode </span> <span class="typ">double </span>usertime() <span class="typ">const </span>{ <span class="key">return </span>ut.time(); } <span class="com">// total amount of second spent in system mode </span> <span class="typ">double </span>systime () <span class="typ">const </span>{ <span class="key">return </span>st.time(); } <span class="com">// real total amount of second spent. </span> <span class="typ">double </span>realtime () <span class="typ">const </span>{ <span class="key">return </span>rt.time(); } <span class="com">// retourne une petite graine </span> <span class="com">// long seed() const { return RealTimer::seed(); } </span> <span class="com">// Some arithmetic operators to compute cumulative time : </span> Timer& <span class="key">operator </span>= (<span class="typ">const </span>Timer & T) ; <span class="typ">const </span>Timer <span class="key">operator </span>- (<span class="typ">const </span>Timer & T) <span class="typ">const</span>; <span class="typ">const </span>Timer <span class="key">operator </span>- () ; <span class="typ">const </span>Timer <span class="key">operator </span>+ (<span class="typ">const </span>Timer & T) <span class="typ">const</span>; <span class="typ">const </span>Timer <span class="key">operator </span>+= (<span class="typ">const </span>Timer & T) { <span class="key">return </span>*<span class="key">this </span>= *<span class="key">this </span>+ T; }; <span class="typ">const </span>Timer <span class="key">operator </span>-= (<span class="typ">const </span>Timer & T) { <span class="key">return </span>*<span class="key">this </span>= *<span class="key">this </span>- T; }; <span class="com">// -- methods : </span> std::ostream& print( std::ostream& ) <span class="typ">const</span>; <span class="key">public</span>: RealTimer rt; UserTimer ut; SysTimer st; }; <span class="com">// inline std::ostream& operator<<( std::ostream& o, const Timer& T) </span><span class="com">// { return T.print(o);} </span> <span class="key">inline </span>std::ostream& <span class="key">operator</span><<( std::ostream& o, <span class="typ">const </span>Timer& T) { <span class="key">return </span>o << T.realtime() << <span class="str">"s ("</span> << T.usertime() << <span class="str">" cpu)"</span>; } <span class="dir">#endif</span></pre> <h2>agoraViewer.cpp</h2> <pre> <span class="dir">#include </span><span class="dstr">"agoraViewer.h"</span><span class="dir"> </span><span class="dir">#include </span><span class="dstr">"agoraWindow.h"</span><span class="dir"> </span><span class="dir">#include <fstream> </span><span class="dir">#include <math.h> </span><span class="dir">#include <qmessagebox.h> </span><span class="dir">#include <qimage.h> </span><span class="dir">#include <qfile.h> </span><span class="dir">#include <qfileinfo.h> </span><span class="dir">#include <qfiledialog.h> </span><span class="dir">#include <qaction.h> </span> <span class="key">using namespace </span>std; <span class="key">using namespace </span>qglviewer; AgoraViewer::AgoraViewer(QWidget* parent, <span class="typ">const char</span>* name) : QGLViewer(parent, name), computerIsBlack_(<span class="key">true</span>), selectedPiece_(<span class="num">-1</span>), playerIsComputer_(<span class="key">true</span>), displayPossibleDestination_(<span class="key">true</span>), animatePlays_(<span class="key">true</span>), textures_(<span class="key">true</span>), fileName(<span class="str">"savedGame.ago"</span>), undoIndex_(<span class="num">0</span>), maxUndoIndex_(<span class="num">0</span>) { <span class="com">// Stored once and for all </span> normal[<span class="num">0</span>] = Vec(<span class="num">-1.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>); normal[<span class="num">1</span>] = Vec( <span class="num">0.0</span>, <span class="num">1.0</span>, <span class="num">0.0</span>); normal[<span class="num">2</span>] = Vec( <span class="num">1.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>); normal[<span class="num">3</span>] = Vec( <span class="num">0.0</span>, <span class="num">-1.0</span>, <span class="num">0.0</span>); normal[<span class="num">4</span>] = normal[<span class="num">0</span>]; levelIsEasy(); <span class="com">// Prevent too many updateGL when several KFI are runned together. Only kfi_[0] updatesGL. </span> <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">1</span>; i<<span class="num">16</span>; ++i) QObject::disconnect(&kfi_[i], SIGNAL(interpolated()), <span class="key">this</span>, SLOT(updateGL())); QObject::connect(&kfi_[<span class="num">0</span>], SIGNAL(finished()), <span class="key">this</span>, SLOT(simplePlay())); } <span class="com">// I n i t i a l i z a t i o n f u n c t i o n s // </span> <span class="typ">void </span>AgoraViewer::init() { initViewer(); initSpotLight(); initCamera(); initGame(); setMouseBinding(Qt::RightButton, CAMERA, ManipulatedFrame::ROTATE); setMouseBinding(Qt::LeftButton, SELECT); } <span class="typ">void </span>AgoraViewer::initSpotLight() { glMatrixMode(GL_MODELVIEW); glEnable(GL_LIGHT1); glLoadIdentity(); <span class="com">// Light default parameters </span> <span class="typ">const </span>GLfloat light_ambient[<span class="num">4</span>] = {<span class="num">2.0</span>, <span class="num">2.0</span>, <span class="num">2.0</span>, <span class="num">1.0</span>}; <span class="typ">const </span>GLfloat light_specular[<span class="num">4</span>] = {<span class="num">2.0</span>, <span class="num">2.0</span>, <span class="num">2.0</span>, <span class="num">1.0</span>}; <span class="typ">const </span>GLfloat light_diffuse[<span class="num">4</span>] = {<span class="num">2.0</span>, <span class="num">2.0</span>, <span class="num">2.0</span>, <span class="num">1.0</span>}; glLightf( GL_LIGHT1, GL_SPOT_EXPONENT, <span class="num">2.0</span>); glLightf( GL_LIGHT1, GL_SPOT_CUTOFF, <span class="num">60.0</span>); glLightf( GL_LIGHT1, GL_CONSTANT_ATTENUATION, <span class="num">0.1</span>); glLightf( GL_LIGHT1, GL_LINEAR_ATTENUATION, <span class="num">0.3</span>); glLightf( GL_LIGHT1, GL_QUADRATIC_ATTENUATION, <span class="num">0.3</span>); glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); } <span class="key">class </span>BoardConstraint : <span class="key">public </span>Constraint { <span class="key">public</span>: <span class="key">virtual </span><span class="typ">void </span>constrainRotation(Quaternion& q, Frame * <span class="typ">const </span>fr) { <span class="typ">const </span>Vec up = fr->transformOf(Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>)); Vec axis = q.axis(); <span class="typ">float </span>angle = <span class="num">2.0</span>*acos(q[<span class="num">3</span>]); <span class="key">if </span>(fabs(axis*up) > fabs(axis.x)) axis.projectOnAxis(up); <span class="key">else </span>{ angle = (axis.x > <span class="num">0.0</span>) ? angle : -angle; axis.setValue(fabs(axis.x), <span class="num">0.0</span>, <span class="num">0.0</span>); <span class="typ">const float </span>currentAngle = asin(fr->inverseTransformOf(Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">-1.0</span>)).z); <span class="key">if </span>(currentAngle + angle > <span class="num">-0.2</span>) angle = <span class="num">-0.2 </span>- currentAngle; <span class="com">// Not too low </span> <span class="key">if </span>(currentAngle + angle < -M_PI/<span class="num">2.0</span>) angle = -M_PI/<span class="num">2.0 </span>- currentAngle; <span class="com">// Do not pass on the other side </span> } q = Quaternion(axis, angle); } }; <span class="typ">void </span>AgoraViewer::initCamera() { camera()->setUpVector(Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>)); camera()->setPosition(Vec(<span class="num">-6.0</span>, <span class="num">-6.0</span>, <span class="num">4.0</span>)); camera()->lookAt(sceneCenter()); setSceneRadius(<span class="num">3.5</span>); showEntireScene(); <span class="com">// Limit camera rotation motion </span> camera()->frame()->setConstraint(<span class="key">new </span>BoardConstraint()); } <span class="typ">void </span>AgoraViewer::initGame() { agora.reinit(); updatePiecePositions(); blackPlay_ = <span class="key">false</span>; gameIsOver_ = <span class="key">false</span>; } <span class="typ">void </span>AgoraViewer::initViewer() { <span class="typ">int </span>count = <span class="num">0</span>; <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">6</span>; ++i) <span class="key">for </span>(<span class="typ">int </span>j=<span class="num">0</span>; j<<span class="num">6</span>; ++j) { <span class="typ">float </span>height; <span class="key">if </span>((i==<span class="num">0</span>) || (j==<span class="num">0</span>) || (i==<span class="num">5</span>) || (j==<span class="num">5</span>)) height = <span class="num">6.0 </span>* pieceHeight; <span class="key">else if </span>((i==<span class="num">1</span>) || (j==<span class="num">1</span>) || (i==<span class="num">4</span>) || (j==<span class="num">4</span>)) height = <span class="num">3.0 </span>* pieceHeight; <span class="key">else </span>height = pieceHeight; casePosition[count++] = Vec(i-2.<span class="num">5</span>, j-2.<span class="num">5</span>, height); } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); <span class="com">// Enable GL textures </span> glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glEnable( GL_TEXTURE_2D ); <span class="com">// Nice texture coordinate interpolation </span> glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); <span class="typ">const </span>QString texFileName(<span class="str">"wood.png"</span>); QImage img(texFileName); <span class="key">if </span>(img.isNull()) { cerr << <span class="str">"Unable to load wood texture from "</span> << texFileName << endl; exit(<span class="num">1</span>); } <span class="com">// 1E-3 needed. Just try with width=128 and see ! </span> <span class="key">if </span>( ( img.width() != <span class="num">1</span><<(<span class="typ">int</span>)(<span class="num">1</span>+log(img.width() <span class="num">-1</span>+<span class="num">1</span>E-3) / log(<span class="num">2.0</span>)) ) || ( img.height() != <span class="num">1</span><<(<span class="typ">int</span>)(<span class="num">1</span>+log(img.height()<span class="num">-1</span>+<span class="num">1</span>E-3) / log(<span class="num">2.0</span>))) ) { cerr << <span class="str">"Texture dimensions are not powers of 2 in "</span> << texFileName << endl; exit(<span class="num">1</span>); } QImage glImg = QGLWidget::convertToGLFormat(img); <span class="com">// flipped 32bit RGBA </span> <span class="com">// Bind the img texture... </span> glTexImage2D(GL_TEXTURE_2D, <span class="num">0</span>, <span class="num">4</span>, glImg.width(), glImg.height(), <span class="num">0</span>, GL_RGBA, GL_UNSIGNED_BYTE, glImg.bits()); } <span class="com">// D r a w i n g f u n c t i o n s // </span> <span class="typ">void </span>AgoraViewer::draw() { glColor3f(<span class="num">0.7</span>, <span class="num">0.7</span>, <span class="num">0.7</span>); glDisable(GL_LIGHTING); <span class="key">if </span>(blackPlay_) drawText(<span class="num">20</span>, <span class="num">20</span>, <span class="str">"Blacks play"</span>); <span class="key">else </span>drawText(<span class="num">20</span>, <span class="num">20</span>, <span class="str">"Whites play"</span>); glEnable(GL_LIGHTING); drawAgora(); drawAllPieces(); <span class="key">if </span>(selectedPiece_ >= <span class="num">0</span>) { highlightSelectedPiece(); <span class="key">if </span>(displayPossibleDestination_) drawPossibleDestinations(); } } <span class="typ">void </span>AgoraViewer::drawAgora() <span class="typ">const </span>{ <span class="typ">static const </span>GLfloat pos[<span class="num">4</span>] = {<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">3.0</span>, <span class="num">1.0</span>}; <span class="typ">const </span>GLfloat spot_dir[<span class="num">3</span>] = {<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">-1.0</span>}; glLightfv(GL_LIGHT1, GL_POSITION, pos); glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_dir); glColor3f(<span class="num">0.5</span>, <span class="num">0.5</span>, <span class="num">0.5</span>); <span class="key">if </span>(textures_) glEnable(GL_TEXTURE_2D); <span class="key">else </span>glDisable(GL_TEXTURE_2D); drawBorder(<span class="num">6.0</span>, <span class="num">6.0 </span>* pieceHeight); drawBorder(<span class="num">4.0</span>, <span class="num">6.0 </span>* pieceHeight, <span class="key">false</span>, <span class="num">3.0 </span>* pieceHeight); drawBorder(<span class="num">2.0</span>, <span class="num">3.0 </span>* pieceHeight, <span class="key">false</span>, pieceHeight); drawRing(<span class="num">6.0</span>, <span class="num">6.0 </span>* pieceHeight); drawRing(<span class="num">4.0</span>, <span class="num">3.0 </span>* pieceHeight); drawRing(<span class="num">2.0</span>, pieceHeight); drawFace(<span class="num">6.0</span>, <span class="num">0.0</span>, <span class="key">false</span>); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glLineWidth(<span class="num">3.0</span>); glColor3f(<span class="num">0.4</span>, <span class="num">0.4</span>, <span class="num">0.4</span>); drawBorderLines(<span class="num">6.0</span>, <span class="num">6.0 </span>* pieceHeight); drawBorderLines(<span class="num">4.0</span>, <span class="num">6.0 </span>* pieceHeight, <span class="key">false</span>, <span class="num">3.0 </span>* pieceHeight); drawBorderLines(<span class="num">2.0</span>, <span class="num">3.0 </span>* pieceHeight, <span class="key">false</span>, pieceHeight); drawLeveLines(<span class="num">4.0</span>, <span class="num">5.0 </span>* pieceHeight); drawLeveLines(<span class="num">4.0</span>, <span class="num">4.0 </span>* pieceHeight); drawLeveLines(<span class="num">2.0</span>, <span class="num">2.0 </span>* pieceHeight); glLineWidth(<span class="num">4.0</span>); glColor3f(<span class="num">0.1</span>, <span class="num">0.1</span>, <span class="num">0.1</span>); drawSeparatingBars(<span class="num">6.0</span>, <span class="num">6.0 </span>* pieceHeight); drawSeparatingBars(<span class="num">4.0</span>, <span class="num">3.0 </span>* pieceHeight); drawSeparatingBars(<span class="num">2.0</span>, pieceHeight); glEnable(GL_LIGHTING); } <span class="typ">void </span>AgoraViewer::drawPiece() <span class="typ">const </span>{ drawBorder(pieceSize, pieceHeight); drawFace(pieceSize, pieceHeight, <span class="key">true</span>); drawFace(pieceSize, <span class="num">0.0</span>, <span class="key">false</span>); glLineWidth(<span class="num">2.0</span>); glDisable(GL_LIGHTING); glColor3f(<span class="num">0.4</span>, <span class="num">0.4</span>, <span class="num">0.4</span>); drawBorderLines(pieceSize, pieceHeight); glEnable(GL_LIGHTING); } <span class="typ">void </span>AgoraViewer::highlightSelectedPiece() <span class="typ">const </span>{ glEnable(GL_BLEND); <span class="typ">const float </span>s = <span class="num">1.1 </span>* piece_[selectedPiece_].scale; glColor4f(<span class="num">0.3</span>, <span class="num">0.9</span>, <span class="num">0.3</span>, <span class="num">0.3</span>); glPushMatrix(); glMultMatrixd(piece_[selectedPiece_].frame.matrix()); glScalef(s, s, s); drawPiece(); glPopMatrix(); glDisable(GL_BLEND); } <span class="typ">void </span>AgoraViewer::drawAllPieces(<span class="typ">bool </span>select) <span class="typ">const </span>{ <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">16</span>; ++i) { glPushMatrix(); glMultMatrixd(piece_[i].frame.matrix()); glScalef(piece_[i].scale, piece_[i].scale, <span class="num">1.0</span>); <span class="key">if </span>(piece_[i].isBlack) glColor3f(<span class="num">0.2</span>, <span class="num">0.2</span>, <span class="num">0.2</span>); <span class="key">else </span>glColor3f(<span class="num">0.9</span>, <span class="num">0.9</span>, <span class="num">0.9</span>); <span class="key">if </span>(select) glPushName(i); drawPiece(); <span class="key">if </span>(select) glPopName(); glPopMatrix(); } } <span class="typ">void </span>AgoraViewer::drawPossibleDestinations(<span class="typ">bool </span>select) <span class="typ">const </span>{ glEnable(GL_BLEND); glColor4f(<span class="num">0.3</span>, <span class="num">0.3</span>, <span class="num">0.9</span>, <span class="num">0.5</span>); <span class="key">for </span>(Possibles::const_iterator it=possibleDest_.begin(), end=possibleDest_.end(); it != end; ++it) { <span class="typ">const int </span>dest = (*it).arrivee(); glPushMatrix(); glTranslatef(casePosition[dest].x, casePosition[dest].y, casePosition[dest].z + <span class="num">0.01</span>); <span class="key">if </span>(select) glPushName(dest); drawFace(<span class="num">0.9</span>, <span class="num">0.0</span>, <span class="key">true</span>); <span class="key">if </span>(select) <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">16</span>; ++i) <span class="key">if </span>(piece_[i].square == dest) { glPushMatrix(); glTranslatef(<span class="num">0.0</span>, <span class="num">0.0</span>, piece_[i].level * pieceHeight); drawPiece(); glPopMatrix(); } <span class="key">if </span>(select) glPopName(); glPopMatrix(); } glDisable(GL_BLEND); } <span class="typ">void </span>AgoraViewer::drawBorder(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">bool </span>out, <span class="typ">float </span>heightMin) <span class="typ">const </span>{ <span class="typ">const </span>Vec up(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>); <span class="typ">const float </span>coef = sqrt(<span class="num">2.0</span>) / <span class="num">2.0</span>; <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">4</span>; ++i) { <span class="key">if </span>(out) glNormal3fv(normal[i].address()); <span class="key">else </span>glNormal3fv((-normal[i]).address()); glBegin(GL_QUADS); glTexCoord2f(-width*coef, heightMin); glVertex3fv((width/<span class="num">2.0</span>*(normal[i] - normal[i+<span class="num">1</span>]) + heightMin*up).address()); glTexCoord2f(width*coef, heightMin); glVertex3fv((width/<span class="num">2.0</span>*(normal[i] + normal[i+<span class="num">1</span>]) + heightMin*up).address()); glTexCoord2f(width*coef, height); glVertex3fv((width/<span class="num">2.0</span>*(normal[i] + normal[i+<span class="num">1</span>]) + height*up).address()); glTexCoord2f(-width*coef,height); glVertex3fv((width/<span class="num">2.0</span>*(normal[i] - normal[i+<span class="num">1</span>]) + height*up).address()); glEnd(); } } <span class="typ">void </span>AgoraViewer::drawBorderLines(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">bool </span>out, <span class="typ">float </span>heightMin) <span class="typ">const </span>{ <span class="typ">const </span>Vec up(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>); <span class="com">// Avoid aliassing on inside agora </span> <span class="key">if </span>(!out) { heightMin += <span class="num">0.01</span>; width -= <span class="num">0.01</span>; } <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">4</span>; ++i) { glBegin(GL_LINE_LOOP); glVertex3fv((width/<span class="num">2.0</span>*(normal[i] - normal[i+<span class="num">1</span>]) + heightMin*up).address()); glVertex3fv((width/<span class="num">2.0</span>*(normal[i] + normal[i+<span class="num">1</span>]) + heightMin*up).address()); glVertex3fv((width/<span class="num">2.0</span>*(normal[i] + normal[i+<span class="num">1</span>]) + height*up).address()); glVertex3fv((width/<span class="num">2.0</span>*(normal[i] - normal[i+<span class="num">1</span>]) + height*up).address()); glEnd(); } } <span class="typ">void </span>AgoraViewer::drawRing(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">float </span>thickness) <span class="typ">const </span>{ <span class="typ">const </span>Vec up(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>); <span class="typ">const float </span>dist1 = width/<span class="num">2.0</span>; <span class="typ">const float </span>dist2 = width/<span class="num">2.0</span>-thickness; glNormal3fv(up.address()); <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">4</span>; ++i) { <span class="typ">const </span>Vec dir1 = normal[i] - normal[i+<span class="num">1</span>]; <span class="typ">const </span>Vec dir2 = normal[i] + normal[i+<span class="num">1</span>]; glBegin(GL_QUADS); glTexCoord2f(dist1*dir1.x, dist1*dir1.y); glVertex3fv((dist1*dir1 + height*up).address()); glTexCoord2f(dist1*dir2.x, dist1*dir2.y); glVertex3fv((dist1*dir2 + height*up).address()); glTexCoord2f(dist2*dir2.x, dist2*dir2.y); glVertex3fv((dist2*dir2 + height*up).address()); glTexCoord2f(dist2*dir1.x, dist2*dir1.y); glVertex3fv((dist2*dir1 + height*up).address()); glEnd(); } } <span class="typ">void </span>AgoraViewer::drawSeparatingBars(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">float </span>thickness) <span class="typ">const </span>{ <span class="typ">const </span>Vec up(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>); height += <span class="num">0.01</span>; <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">4</span>; ++i) { <span class="key">for </span>(<span class="typ">int </span>j=<span class="num">1</span>; j<width-0.<span class="num">9</span>; ++j) { glBegin(GL_LINES); glVertex3fv((width/<span class="num">2.0</span>*normal[i] + (j*thickness-width/<span class="num">2.0</span>)*normal[i+<span class="num">1</span>] + height*up).address()); glVertex3fv(((width/<span class="num">2.0</span>-thickness)*normal[i] + (j-width/<span class="num">2.0</span>)*normal[i+<span class="num">1</span>] + height*up).address()); glEnd(); } } } <span class="typ">void </span>AgoraViewer::drawLeveLines(<span class="typ">float </span>width, <span class="typ">float </span>height) <span class="typ">const </span>{ <span class="typ">const </span>Vec up(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>); width -= <span class="num">0.01</span>; glBegin(GL_LINE_LOOP); <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">4</span>; ++i) glVertex3fv((width/<span class="num">2.0</span>*(normal[i] + normal[i+<span class="num">1</span>]) + height*up).address()); glEnd(); } <span class="typ">void </span>AgoraViewer::drawFace(<span class="typ">float </span>width, <span class="typ">float </span>height, <span class="typ">bool </span>up) <span class="typ">const </span>{ <span class="key">if </span>(up) glNormal3f(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>); <span class="key">else </span>glNormal3f(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">-1.0</span>); glBegin(GL_QUADS); glVertex3f(-width/<span class="num">2.0</span>, -width/<span class="num">2.0</span>, height); glVertex3f(-width/<span class="num">2.0</span>, width/<span class="num">2.0</span>, height); glVertex3f( width/<span class="num">2.0</span>, width/<span class="num">2.0</span>, height); glVertex3f( width/<span class="num">2.0</span>, -width/<span class="num">2.0</span>, height); glEnd(); } <span class="typ">void </span>AgoraViewer::animatePlay() { <span class="typ">float </span>start = <span class="num">0.0</span>; <span class="typ">float </span>end = <span class="num">0.8</span>; <span class="typ">int </span>hpops = higherPieceOnPosition(play_.depart()); <span class="typ">int </span>hpope = higherPieceOnPosition(play_.arrivee()); <span class="key">if </span>(hpops < <span class="num">0</span>) cerr << <span class="str">"Internal error"</span> << endl; <span class="typ">int </span>nbKfi = <span class="num">0</span>; <span class="key">if </span>(play_.dessus()) { <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">16</span>; ++i) <span class="key">if </span>((piece_[i].square == play_.arrivee()) && (piece_[i].isBlack != piece_[hpops].isBlack) && (piece_[hpops].isBlack != piece_[hpope].isBlack)) { <span class="com">// piece_[i].isBlack = piece_[hpops].isBlack; </span> nbKfi++; kfi_[nbKfi].deletePath(); kfi_[nbKfi].setFrame(&piece_[i].frame); kfi_[nbKfi].addKeyFrame(piece_[i].frame, <span class="num">0.0</span>); Frame midFrame(piece_[i].frame.position()+Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">4</span>*pieceHeight*(piece_[i].level+<span class="num">2</span>)), Quaternion(Vec(<span class="num">1.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>), <span class="num">2.0</span>)); kfi_[nbKfi].addKeyFrame(midFrame, <span class="num">0.3</span>); Frame endFrame(piece_[i].frame.position()+Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, pieceHeight), Quaternion(Vec(<span class="num">1.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>), M_PI)); kfi_[nbKfi].addKeyFrame(endFrame, <span class="num">0.6</span>); start = <span class="num">0.6</span>; } } <span class="key">else </span>{ <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">16</span>; ++i) <span class="key">if </span>(piece_[i].square == play_.arrivee()) { nbKfi++; kfi_[nbKfi].deletePath(); kfi_[nbKfi].setFrame(&piece_[i].frame); kfi_[nbKfi].addKeyFrame(piece_[i].frame, <span class="num">0.0</span>); Frame midFrame, endFrame; <span class="key">if </span>((agora.ArriveeRevolution(play_)) && (piece_[i].isBlack != piece_[hpops].isBlack)) { midFrame = Frame(piece_[i].frame.position()+Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">3.0</span>*pieceHeight*(piece_[i].level+<span class="num">2</span>)), Quaternion(Vec(<span class="num">1.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>), <span class="num">2.0</span>)); endFrame = Frame(piece_[i].frame.position()+Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">2.0</span>*pieceHeight), Quaternion(Vec(<span class="num">1.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>), M_PI)); <span class="com">// piece_[i].isBlack = piece_[hpops].isBlack; </span> } <span class="key">else </span>{ midFrame.setPosition(piece_[i].frame.position()+Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">3.0</span>*pieceHeight*(piece_[i].level+<span class="num">2</span>))); endFrame.setPosition(piece_[i].frame.position()+Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, pieceHeight)); } kfi_[nbKfi].addKeyFrame(midFrame, <span class="num">0.4</span>); kfi_[nbKfi].addKeyFrame(endFrame, <span class="num">1.0</span>); end = <span class="num">1.0</span>; } } <span class="com">// Revolution on starting case </span> <span class="key">if </span>(agora.DepartRevolution(play_)) <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">16</span>; ++i) <span class="key">if </span>((piece_[i].square == play_.depart()) && (i!=hpops) && (piece_[i].isBlack == piece_[hpops].isBlack)) { nbKfi++; kfi_[nbKfi].deletePath(); kfi_[nbKfi].setFrame(&piece_[i].frame); kfi_[nbKfi].addKeyFrame(piece_[i].frame, <span class="num">0.0</span>); kfi_[nbKfi].addKeyFrame(piece_[i].frame, <span class="num">0.6</span>); Frame midFrame(piece_[i].frame.position()+Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">3.0</span>*pieceHeight*(piece_[i].level+<span class="num">2</span>)), Quaternion(Vec(<span class="num">1.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>), <span class="num">2.0</span>)); Frame endFrame(piece_[i].frame.position()+Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, pieceHeight), Quaternion(Vec(<span class="num">1.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>), M_PI)); <span class="com">// piece_[i].isBlack = !piece_[hpops].isBlack; </span> kfi_[nbKfi].addKeyFrame(midFrame, <span class="num">0.9</span>); kfi_[nbKfi].addKeyFrame(endFrame, <span class="num">1.5</span>); end = <span class="num">1.5</span>; } <span class="com">// Selected piece </span> kfi_[<span class="num">0</span>].deletePath(); kfi_[<span class="num">0</span>].setFrame(&piece_[hpops].frame); Frame arrival; <span class="key">if </span>((hpope >= <span class="num">0</span>) && (play_.dessus())) arrival.setPosition(piece_[hpope].frame.position() + Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, pieceHeight)); <span class="key">else </span>arrival.setPosition(casePosition[play_.arrivee()]); Vec mid(<span class="num">0.5 </span>* (piece_[hpops].frame.position() + arrival.position())); mid.z = max(piece_[hpops].frame.position().z, arrival.position().z) + <span class="num">2.0 </span>* pieceHeight; <span class="typ">const </span>Frame intermediate(mid, Quaternion()); kfi_[<span class="num">0</span>].addKeyFrame(piece_[higherPieceOnPosition(play_.depart())].frame, <span class="num">0.0</span>); kfi_[<span class="num">0</span>].addKeyFrame(piece_[higherPieceOnPosition(play_.depart())].frame, start); kfi_[<span class="num">0</span>].addKeyFrame(intermediate, start+<span class="num">0.3</span>); kfi_[<span class="num">0</span>].addKeyFrame(arrival, start+<span class="num">0.8</span>); kfi_[<span class="num">0</span>].addKeyFrame(arrival, start+end); <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">1</span>; i<=nbKfi; ++i) kfi_[i].startInterpolation(); kfi_[<span class="num">0</span>].startInterpolation(); } <span class="typ">int </span>AgoraViewer::higherPieceOnPosition(Position pos) <span class="typ">const </span>{ <span class="typ">float </span>levelMax = <span class="num">-1.0</span>; <span class="typ">int </span>res = <span class="num">-1</span>; <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">16</span>; ++i) <span class="key">if </span>((piece_[i].square == pos) && (piece_[i].level > levelMax)) { res = i; levelMax = piece_[i].level; } <span class="key">return </span>res; } <span class="com">// G a m e I n t e r f a c e // </span> <span class="typ">void </span>AgoraViewer::play() { <span class="key">if </span>(animatePlays_) animatePlay(); <span class="key">else </span>simplePlay(); } <span class="typ">void </span>AgoraViewer::deselect() { selectedPiece_ = <span class="num">-1</span>; possibleDest_.clear(); } <span class="typ">void </span>AgoraViewer::simplePlay() { deselect(); updateUndoHistory(<span class="key">true</span>); agora.jouer(play_); updateUndoHistory(<span class="key">false</span>); updatePiecePositions(); blackPlay_ = !blackPlay_; updateGL(); gameIsOver_ = agora.gameIsOver(); <span class="key">if </span>(gameIsOver_) { <span class="key">if </span>(agora.gameIsOver(BLACK)) QMessageBox::information(<span class="key">this</span>, <span class="str">"Whites won !"</span>, <span class="str">"The whites won !"</span>); <span class="key">else </span>QMessageBox::information(<span class="key">this</span>, <span class="str">"Blacks won !"</span>, <span class="str">"The blacks won !"</span>); } <span class="key">else if </span>((playerIsComputer_) && (computerIsBlack_==blackPlay_)) { play_ = agora.Suggest(play_, blackPlay_, gameLevel_.computerMaxReflexionTime_, gameLevel_.computerMaxDepth_); play(); } } <span class="typ">void </span>AgoraViewer::reactToSelection(<span class="typ">int </span>selected, <span class="typ">bool </span>onTop) { <span class="key">if </span>(selectedPiece_ >= <span class="num">0</span>) { <span class="key">if </span>(selected >= <span class="num">0</span>) { <span class="typ">bool </span>playOnTopIsValid = <span class="key">false</span>; <span class="typ">bool </span>playPrisonnerIsValid = <span class="key">false</span>; Play playOnTop, playPrisonner; <span class="key">for </span>(Possibles::const_iterator it=possibleDest_.begin(), end=possibleDest_.end(); it != end; ++it) <span class="key">if </span>(((*it).depart() == piece_[selectedPiece_].square) && ((<span class="typ">int</span>)((*it).arrivee()) == selected)) <span class="key">if </span>((*it).dessus()) { playOnTopIsValid = <span class="key">true</span>; playOnTop = (*it); } <span class="key">else </span>{ playPrisonnerIsValid = <span class="key">true</span>; playPrisonner = (*it); } <span class="key">if </span>(playOnTopIsValid) <span class="key">if </span>(playPrisonnerIsValid) play_ = (onTop) ? playOnTop : playPrisonner; <span class="key">else </span>play_ = playOnTop; <span class="key">else if </span>(playPrisonnerIsValid) play_ = playPrisonner; <span class="key">else </span>cerr << <span class="str">"Internal error : invalid play in reactToSelection."</span> << endl; play(); } <span class="key">else </span>deselect(); } <span class="key">else </span><span class="com">// New piece selection. Color must correspond to current player </span> <span class="key">if </span>((selected >= <span class="num">0</span>) && (piece_[selected].isBlack == blackPlay_)) { <span class="com">// Search for the piece at highest level on this heap </span> selectedPiece_ = higherPieceOnPosition(piece_[selected].square); agora.CoupsVoisins( possibleDest_, piece_[selectedPiece_].square ); } } <span class="typ">void </span>AgoraViewer::select(<span class="typ">const </span>QMouseEvent* e) { <span class="key">if </span>(gameIsOver_) <span class="key">return</span>; <span class="com">// Make openGL context current </span> makeCurrent(); <span class="typ">const int </span>SENSITIVITY = <span class="num">4</span>; <span class="typ">const int </span>NB_HITS_MAX = <span class="num">50</span>; <span class="com">// Prepare the selection mode </span> <span class="typ">static </span>GLuint hits[NB_HITS_MAX]; glSelectBuffer(NB_HITS_MAX, hits); glRenderMode(GL_SELECT); glInitNames(); <span class="com">// Loads the matrices </span> glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLint viewport[<span class="num">4</span>]; glGetIntegerv(GL_VIEWPORT,viewport); gluPickMatrix(<span class="key">static_cast</span><GLdouble>(e->x()), <span class="key">static_cast</span><GLdouble>(viewport[<span class="num">3</span>] - e->y()), SENSITIVITY, SENSITIVITY, viewport); <span class="com">// loadProjectionMatrix() first resets the GL_PROJECTION matrix with a glLoadIdentity. </span> <span class="com">// Give false as a parameter in order to prevent this and to combine the matrices. </span> camera()->loadProjectionMatrix(<span class="key">false</span>); camera()->loadModelViewMatrix(); <span class="com">// Render scene with objects ids </span> <span class="key">if </span>(selectedPiece_ >= <span class="num">0</span>) drawPossibleDestinations(<span class="key">true</span>); <span class="key">else </span>drawAllPieces(<span class="key">true</span>); glFlush(); <span class="com">// Get the results </span> GLint nb_hits = glRenderMode(GL_RENDER); <span class="com">// Interpret results </span> <span class="typ">unsigned int </span>zMin = UINT_MAX; <span class="typ">int </span>id = <span class="num">-1</span>; <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<nb_hits; ++i) <span class="key">if </span>(hits[i*<span class="num">4</span>+<span class="num">1</span>] < zMin) { zMin = hits[i*<span class="num">4</span>+<span class="num">1</span>]; id = hits[i*<span class="num">4</span>+<span class="num">3</span>]; } reactToSelection(id, e->state() == Qt::NoButton); } <span class="typ">void </span>AgoraViewer::updatePiecePositions() { <span class="typ">int </span>nb = <span class="num">0</span>; <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">36</span>; ++i) { Pile p = agora[i]; <span class="typ">bool </span>topIsBlack = agora.couleur(p); <span class="key">for </span>(<span class="typ">int </span>j=<span class="num">0</span>; j<agora.taille(p); ++j) { <span class="key">if </span>(j == agora.uns(p)) topIsBlack = !topIsBlack; piece_[nb].square = i; piece_[nb].isBlack = topIsBlack; piece_[nb].level = agora.taille(p)<span class="num">-1</span>-j; piece_[nb].frame.setPosition(casePosition[i] + Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, pieceHeight * piece_[nb].level)); piece_[nb].frame.setOrientation(Quaternion()); piece_[nb].scale = <span class="num">1.0 </span>- <span class="num">0.1</span>*(agora.taille(p)-j-1)/(<span class="typ">float</span>)agora.taille(p); nb++; } } <span class="key">if </span>(nb > <span class="num">16</span>) cerr << <span class="str">"More than 16 pieces in the Agora !!!"</span> << endl; } <span class="com">// F i l e m e n u f u n c t i o n s </span><span class="typ">void </span>AgoraViewer::load() { fileName = QFileDialog::getOpenFileName(<span class="str">""</span>, <span class="str">"Agora files (*.ago);;All files (*)"</span>, <span class="key">this</span>); <span class="com">// In case of Cancel </span> <span class="key">if </span>(fileName.isEmpty()) <span class="key">return</span>; std::ifstream f(fileName.latin1()); f >> agora; f >> undoIndex_ >> maxUndoIndex_; history_.clear(); <span class="key">for </span>(<span class="typ">unsigned int </span>i=<span class="num">0</span>; i<maxUndoIndex_; ++i) { Undo u; f >> u.pos1 >> u.pos2 >> u.before1 >> u.before2 >> u.after1 >> u.after2; history_.push_back(u); } f.close(); blackPlay_ = undoIndex_%<span class="num">2 </span>== <span class="num">1</span>; updatePiecePositions(); deselect(); } <span class="typ">void </span>AgoraViewer::save() { std::ofstream f(fileName.latin1()); f << agora; <span class="com">// save undo history </span> f << undoIndex_ << <span class="str">" "</span> << maxUndoIndex_ << endl; <span class="key">for </span>(std::vector<Undo>::iterator it=history_.begin(), end=history_.end(); it != end; ++it) f << (*it).pos1 << <span class="str">" "</span> << (*it).pos2 << <span class="str">" "</span> << (*it).before1 << <span class="str">" "</span> << (*it).before2 << <span class="str">" "</span> << (*it).after1 << <span class="str">" "</span> << (*it).after2 << endl; f.close(); } <span class="typ">void </span>AgoraViewer::saveAs() { fileName = QFileDialog::getSaveFileName(<span class="str">""</span>, <span class="str">"Agora files (*.ago);;All files (*)"</span>, <span class="key">this</span>, fileName.latin1()); QFileInfo fi(fileName); <span class="key">if </span>(fi.extension().isEmpty()) { fileName += <span class="str">".ago"</span>; fi.setFile(fileName); } <span class="key">if </span>(fi.exists()) <span class="key">if </span>(QMessageBox::warning(<span class="key">this </span>,<span class="str">"Existing file"</span>, <span class="str">"File "</span>+fi.fileName()+<span class="str">" already exists.</span><span class="esc">\n</span><span class="str">Save anyway ?"</span>, QMessageBox::Yes, QMessageBox::Cancel) == QMessageBox::Cancel) <span class="key">return</span>; <span class="key">if </span>(!fi.isWritable()) <span class="com">// CHECK THIS </span> { QMessageBox::warning(<span class="key">this </span>,<span class="str">"Cannot save"</span>, <span class="str">"File "</span>+fi.fileName()+<span class="str">" is not writeable."</span>); <span class="key">return</span>; } save(); } <span class="com">// U n d o a n d R e do </span>AgoraViewer::Undo::Undo(<span class="typ">const </span>Play& play, <span class="typ">const </span>Agora_t& agora) { pos1 = play.depart(); pos2 = play.arrivee(); before1 = agora[pos1]; before2 = agora[pos2]; } <span class="typ">void </span>AgoraViewer::updateUndoHistory(<span class="typ">bool </span>before) { <span class="key">if </span>(before) { <span class="key">if </span>(undoIndex_ < history_.size()) history_[undoIndex_] = Undo(play_, agora); <span class="key">else </span>history_.push_back(Undo(play_, agora)); } <span class="key">else </span>{ history_[undoIndex_].after1 = agora[play_.depart()]; history_[undoIndex_].after2 = agora[play_.arrivee()]; undoIndex_++; maxUndoIndex_ = undoIndex_; } } <span class="typ">void </span>AgoraViewer::undo() { <span class="key">if </span>(undoIndex_ > <span class="num">0</span>) undoIndex_--; <span class="key">else return</span>; agora.remettre(history_[undoIndex_].pos1, history_[undoIndex_].before1, history_[undoIndex_].pos2, history_[undoIndex_].before2); updatePiecePositions(); blackPlay_ = !blackPlay_; updateGL(); } <span class="typ">void </span>AgoraViewer::redo() { <span class="key">if </span>(undoIndex_ >= maxUndoIndex_) { QMessageBox::warning(<span class="key">this</span>, <span class="str">"No more redo"</span>, <span class="str">"No more redo is possible"</span>); <span class="key">return</span>; } agora.remettre(history_[undoIndex_].pos1, history_[undoIndex_].after1, history_[undoIndex_].pos2, history_[undoIndex_].after2); undoIndex_++; updatePiecePositions(); blackPlay_ = !blackPlay_; updateGL(); } <span class="typ">void </span>AgoraViewer::help() { QMessageBox::information(<span class="key">this</span>, <span class="str">" A g o r a"</span>, <span class="str">"Rules of Agora</span><span class="esc">\n</span><span class="str">Not yet available, please browse the web."</span>); } <span class="typ">void </span>AgoraViewer::about() { QMessageBox::about(<span class="key">this</span>, <span class="str">" A g o r a"</span>, <span class="str">"A g o r a</span><span class="esc">\n</span><span class="str">Created by Gilles Debunne and Jean-Guillaume Dumas</span><span class="esc">\n</span><span class="str">Version 1.0 - June 2003"</span>); } <span class="typ">void </span>AgoraViewer::togglePlayAgainstComputer(<span class="typ">bool </span>on) { playerIsComputer_ = on; <span class="com">// Disable menu items </span> AgoraWindow* window = <span class="key">dynamic_cast</span><AgoraWindow*>(parent()->parent()); <span class="key">if </span>(!window) { qWarning(<span class="str">"Unable to disable menu items"</span>); <span class="key">return</span>; } window->levelActionGroup->setEnabled(on); window->computerBlackAction->setEnabled(on); }</pre> <h2>main.cpp</h2> <pre> <span class="dir">#include <qapplication.h> </span><span class="dir">#include </span><span class="dstr">"agoraWindow.h"</span><span class="dir"> </span> <span class="typ">int </span>main(<span class="typ">int </span>argc, <span class="typ">char </span>* argv[]) { <span class="com">// Read command lines arguments. </span> QApplication application(argc,argv); AgoraWindow aw; aw.show(); application.setMainWidget(&aw); <span class="com">// Run main loop. </span> <span class="key">return </span>application.exec(); } </pre> <p> <a href="index.html">Go back</a> to the examples main page </p> <p> <a href="http://validator.w3.org/check/referer"><img src="../images/xhtml.png" alt="Valid XHTML 1.0!" height="31" width="88" border="0"/></a> <a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="../images/css.png" width="88" height="31" alt="Valid CSS!" border="0"/></a> <i>Last modified on Thursday, February 5, 2004.</i> </p> </body> </html>