Script Library: 1213 scripts
 

reversi.r

REBOL [ Title: "Reversi" Date: 27-Mar-2006 Version: 2.3.0 File: %reversi.r Author: "Vincent Ecuyer" Purpose: "Reversi / Othello" Usage: { ===English Classic Reversi / Othello game. It's a two players board game, where the objective is to cover the board with the greatest number of pieces of your chosen color. The first four pieces must be placed at the center of the plate, then the normal game begins. At each turn, each player puts a two faced piece on the board - all adjacent opponent pieces between the new one and the ones on the board are reversed to match the player color: right after the start: after more turns: (two diagonals (one horizontal line reversed) and one vertical lines reversed) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X . . . . . . . X . . . . . . . . . . . . . . . . . . . . . . . X v X . . . . . X O X . . . . . O X v . . > . . . O O O . . . . X X X X . . > . . X O O O . . . . . X O . . . > . . . X O . . . . . X X X X O . > . . O X O X O . . . . . . . . . . . . . . . . . . O O O O O X . . O O O O O X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . If it doesn't reverse opponent pieces, you can't place a piece on the board - you must skip your turn. The game ends when the board is fully covered, or when both players can't puts pieces on the plate anymore. This script allows you to play against another player or a basic AI . If the game starts in french, change the first code line from language: 'francais to language: 'english . ===Français Le jeu Reversi, aussi appelé Othello. C'est un jeu de plateau pour deux joueurs, où l'objectif est de couvrir le plateau avec le plus grand nombre de pièces de votre couleur. Les quatre premières pièces doivent être placées sur les cases du centre du plateau, puis la partie normale commence. Dans un tour, chaque joueur place une pièce à deux faces sur le plateau - toutes les pièces adjacentes de l'adversaire situées entre la nouvelle pièce et les pièces déjà placées sont retournées pour présenter la couleur du joueur: juste après le début: plus tard dans la partie: (deux (une ligne horizontale retournée)diagonales et une colonne retournées) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X . . . . . . . X . . . . . . . . . . . . . . . . . . . . . . . X v X . . . . . X O X . . . . . O X v . . > . . . O O O . . . . X X X X . . > . . X O O O . . . . . X O . . . > . . . X O . . . . . X X X X O . > . . O X O X O . . . . . . . . . . . . . . . . . . O O O O O X . . O O O O O X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ....... ........ Vous devez retourner des pions de l'adversaire à chaque coup - si c'est impossible vous passez votre tour. La partie se termine lorsque le plateau est recouvert où lorsque aucun joueur ne peut placer de pion. Ce script vous permet de jouer contre un autre joueur où contre une AI basique. Pour jouer en français, changez la première ligne de code de language: 'english en language: 'francais . } Library: [ level: 'advanced platform: 'all type: 'game domain: [gui vid game] tested-under: [ view 1.3.2.3.1 on [Win2K] view 1.2.1.1.1 on [AmigaOS30] view 1.2.1.3.1 on [Win2K] ] support: none license: 'gpl see-also: none ] History: [ 1.0.0 26-7-2001 "Première version jouable" 2.0.0 15-5-2002 "Première version publique. Refonte du moteur et ajout du niveau de difficulté" 2.1.0 2-2-2004 "Nettoyage du code pour View 1.3 et amélioration du redimensionnement." 2.2.0 28-1-2005 "Plus de libertés pour le redimensionnement." 2.3.0 27-3-2006 "Refonte de l'interface." ] ] ; ===Localisation ; choix de la langue/language selection (actuellement, 'francais ou 'english) language: 'english ; textes de l'application locale-strings: [ francais [ doc [ usage { Le jeu commence en mode deux joueurs. Le premier bouton indique le mode de jeu actuel, et permet de le modifier. Le second règle le niveau de difficulté: - minimum : un des trois meilleurs coups trouvés est joué - moyen : un des deux meilleurs coups trouvés est joué - maximum : le meilleur coup trouvé est joué } usage-title "Utilisation" usage-close "(cliquez sur la fenêtre pour la fermer)" ] mode [ human-human "2 joueurs" computer-white "Ordinateur joue blancs" computer-black "Ordinateur joue noirs" ] level [ min "Minimum" med "Moyen" max "Maximum" ] button [ skip "Passer le tour" end "Fin de la partie" ] score [ draw "Egalité" white "Joueur blanc gagnant" black "Joueur noir gagnant" ] ] english [ doc [ usage { The game starts in two players mode. The leftmost button shows the current mode, and allows to change it. The second button controls difficulty: - minimum : one of the three best moves is played - medium : one of the two best moves is played - maximum : the best move is played } usage-title "Usage" usage-close "(click on this window to close it)" ] mode [ human-human "2 Players" computer-white "Computer plays light" computer-black "Computer plays dark" ] level [ min "Minimum" med "Medium" max "Maximum" ] button [ skip "Skip turn" end "End game" ] score [ draw "Draw game" white "Light Wins" black "Dark Wins" ] ] ] ; fonction de localisation locale: func [ "Sélectionne la chaîne dans la langue courante." 'name [word! path!] "Nom de la chaîne" /local r ][ r: locale-strings/:language foreach i :name [r: r/:i] ] ; ===Aspect visuel ; motif de fond du plateau ; (ici, le motif %wood1.pat de GIMP, avec l'effet [colorize 170.100.70]) fond.png: load 64#{ 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 /p0+lCkKJWo8AAAAASUVORK5CYII=} ; apparence des jetons (en réalité, des cases) jeton-effects: [ noir [ gradient 1x1 127.127.127 0.0.0 oval 255.255.255 key 255.255.255 ] blanc [ gradient 1x1 255.255.255 128.128.128 oval 255.255.255 key 255.255.255 ] vide none ] ; ===Déclaration des styles de l'application reversi-style: stylize [ ; interface button: button gold font [colors: [0.0.0 255.0.0] shadow: none] effect [] edge [size: 1x1 color: 0.0.0] choice: choice gold white font [colors: [0.0.0 255.0.0] shadow: none] effect [] edge [size: 1x1 color: 0.0.0] ; jetons noirs et blancs jeton: box 74x74 with [ ; 'noir, 'blanc ou 'vide data: 'vide ; coordonnées sur le plateau en cases coords: none ; listes des cases adjacentes (pour simplifier les calculs) gauche: droite: haut: bas: none haut-gauche: haut-droite: bas-gauche: bas-droite: none ; déclarations dans layout words: [ noir [ new/data: 'noir new/effect: jeton-effects/noir next args ] blanc [ new/data: 'blanc new/effect: jeton-effects/blanc next args ] vide [ new/data: 'vide new/effect: jeton-effects/vide next args ] ] ] ; clic gauche [ ; si le coup est valide if essaie-coup face [ ; case modifiée face/data: face/parent-face/joueur face/effect: select jeton-effects face/data face/parent-face/joueur: select [blanc noir blanc] face/data ; affichage pour le joueur suivant fenetre/color: select [blanc 255.255.255 noir 0.0.0] plateau/joueur show [fenetre face] ; pour suivre le déroulement de la partie coups: coups + 1 ; plateau plein => fin if coups = 64 [do-face fin 'down return] ; si coup joué par la machine if plateau/joueur = ordinateur [ ; attente avant de jouer, pour voir le coup wait 0.5 use [case][ ; jouer le meilleur coup, sinon passer le tour either case: meilleur-coup plateau/joueur [do-face case 'down][ do-face passer 'down if not meilleur-coup plateau/joueur [do-face fin 'down] ] ] ] ] ] ; apparence du plateau de jeu (taille: 8x8 cases + bordure) grille: box fond.png 602x602 with [ joueur: 'blanc effect: [tile grid 75x75 0x0 34.20.14 2] data: array/initial [8 8] 'vide ] ] ; ===Fonctions d'accès aux tableaux simulés ; primitives d'accès x-pos: func [ "Primitive de conversion linéaire -> table." table [any-block!] "Série" width [integer!] "Largeur de la table" ][ (-1 + index? table) // width + 1 ] y-pos: func [ "Primitive de conversion linéaire -> table." table [any-block!] "Série" width [integer!] "Largeur de la table" ][ 1 + to-integer (-1 + index? table) / width ] ; copies à partir d'un point gauche: func [ "Copie tous les éléments à gauche de la case." table [any-block!] "Série" size [pair!] "Dimensions de la table" /local y ][ if 1 >= x-pos table size/x [return copy []] y: y-pos table size/x head reverse copy/part skip head table y - 1 * size/x table ] droite: func [ "Copie tous les éléments à droite de la case." table [any-block!] "Série" size [pair!] "Dimensions de la table" /local y ][ if size/x <= x-pos table size/x [return copy []] y: y-pos table size/x copy/part next table skip head table y * size/x ] haut: func [ "Copie tous les éléments en haut de la case." table [any-block!] "Série" size [pair!] "Dimensions de la table" /local y block b-size sk ][ if 1 >= y: y-pos table size/x [return copy []] block: make block! b-size: y - 1 table: skip table sk: (- size/x) loop b-size [append block table/1 table: skip table sk] block ] bas: func [ "Copie tous les éléments en bas de la case." table [any-block!] "Série" size [pair!] "Dimensions de la table" /local y block b-size sk ][ if size/y <= y: y-pos table size/x [return copy []] block: make block! b-size: size/y - y table: skip table sk: size/x loop b-size [append block table/1 table: skip table sk] block ] haut-gauche: func [ "Copie tous les éléments en haut à gauche de la case." table [any-block!] "Série" size [pair!] "Dimensions de la table" /local x y block b-size sk ][ if 1 >= x: x-pos table size/x [return copy []] if 1 >= y: y-pos table size/x [return copy []] block: make block! b-size: min x - 1 y - 1 table: skip table sk: (-1 - size/x) loop b-size [append block table/1 table: skip table sk] block ] haut-droite: func [ "Copie tous les éléments en haut à droite de la case." table [any-block!] "Série" size [pair!] "Dimensions de la table" /local x y block b-size sk ][ if size/x <= x: x-pos table size/x [return copy []] if 1 >= y: y-pos table size/x [return copy []] block: make block! b-size: min size/x - x y - 1 table: skip table sk: (1 - size/x) loop b-size [append block table/1 table: skip table sk] block ] bas-gauche: func [ "Copie tous les éléments en bas à gauche de la case." table [any-block!] "Série" size [pair!] "Dimensions de la table" /local x y block b-size sk ][ if 1 >= x: x-pos table size/x [return copy []] if size/y <= y: y-pos table size/x [return copy []] block: make block! b-size: min x - 1 size/y - y table: skip table sk: (size/x - 1) loop b-size [append block table/1 table: skip table sk] block ] bas-droite: func [ "Copie tous les éléments en bas à droite de la case." table [any-block!] "Série" size [pair!] "Dimensions de la table" /local x y block b-size sk ][ if size/x <= x: x-pos table size/x [return copy []] if size/y <= y: y-pos table size/x [return copy []] block: make block! b-size: min size/x - x size/y - y table: skip table sk: (size/x + 1) loop b-size [append block table/1 table: skip table sk] block ] ; ===Initialisations de la partie coups-depart: func [ "Cases autorisées en début de partie" /local p ][ p: plateau/pane p/28/effect: p/29/effect: p/36/effect: p/37/effect: [merge tint 60] ] ; Pas de coup joué coups: 0 ; Mode 2 joueurs ordinateur: none ; ===Déclaration et initialisation de la fenêtre fenetre: layout [ ; Styles prédéfinis plus haut styles reversi-style ; 'blanc commence backcolor white across ; Sélection de l'adversaire mode: choice 178 locale mode/human-human locale mode/computer-white locale mode/computer-black [ if all [ ; si en mode 1 joueur... ordinateur: select reduce [1 none 2 'blanc 3 'noir] index? find mode/texts mode/text ; ...et tour de l'ordinateur plateau/joueur = ordinateur ][ ; Coup de la machine use [case][ ; attente avant de jouer, pour voir le coup wait 0.5 ; jouer le meilleur coup, sinon passer le tour either case: meilleur-coup plateau/joueur [do-face case 'down][ do-face passer 'down if not meilleur-coup plateau/joueur [do-face fin 'down] ] ] ] ] ; Sélection du niveau de difficulté en mode 1 joueur niveau: choice locale level/min locale level/med locale level/max ; Passer le tour passer: button locale button/skip 136 [ plateau/joueur: select [blanc noir blanc] plateau/joueur fenetre/color: select [blanc 255.255.255 noir 0.0.0] plateau/joueur show fenetre ; Coup de la machine si en mode 1 joueur if plateau/joueur = ordinateur [ use [case][ ; attente avant de jouer, pour voir le coup wait 0.5 ; jouer le meilleur coup, sinon passer le tour either case: meilleur-coup plateau/joueur [do-face case 'down][ do-face passer 'down if not meilleur-coup plateau/joueur [do-face fin 'down] ] ] ] ] ; Terminer la partie et donner le résultat fin: button locale button/end 136 [ use [total-blanc total-noir][ ; calcul des totaux total-blanc: total-noir: 0 foreach p plateau/pane [ if p/data = 'blanc [total-blanc: total-blanc + 1] if p/data = 'noir [total-noir: total-noir + 1] ] ; égalité either total-blanc = total-noir [ inform layout [ backdrop effect [gradient 1x0 255.255.255 0.0.0] banner green locale score/draw font [shadow: 1x1] feel none ] ][ ; blanc gagnant either total-blanc > total-noir [ inform layout [ backcolor white banner red locale score/white font [shadow: 1x1] feel none ] ][ ; noir gagnant inform layout [ backcolor black banner locale score/black font [shadow: 1x1] feel none ] ] ] ; réinitialisation du plateau et des drapeaux foreach p plateau/pane [p/data: 'vide p/effect: none] coups: 0 plateau/joueur: 'blanc ordinateur: none mode/text: first find mode/texts locale mode/human-human fenetre/color: white ; positions de départ coups-depart show [fenetre mode] show plateau/pane ] ] ; aide du jeu aide: button "?" 20 [ inform layout [ backcolor rebolor banner locale doc/usage-title text as-is locale doc/usage text locale doc/usage-close ] ] return ; plateau de jeu plateau: grille with [ ; initialisation par des cases vides pane: get in (layout append copy [ styles reversi-style origin 1x1 space 1x1 across ] head insert/dup copy [] append insert/dup copy [] [jeton vide] 8 'return 8) 'pane init: [ ; déclaration des références entre les cases use [x y p][ x: y: 1 p: pane forall p [ p/1/coords: to-pair reduce [x y] p/1/gauche: gauche p 8x8 p/1/droite: droite p 8x8 p/1/haut: haut p 8x8 p/1/bas: bas p 8x8 p/1/haut-gauche: haut-gauche p 8x8 p/1/haut-droite: haut-droite p 8x8 p/1/bas-gauche: bas-gauche p 8x8 p/1/bas-droite: bas-droite p 8x8 x: x + 1 if x = 9 [x: 1 y: y + 1] ] pane: head pane ] ] ] ] ; ===Moteur logique du jeu ; validité d'un coup essaie-coup: func [ "Vérifie si un coup est valide." face "Case jouée" /local f-l c ok b ][ ; place occupée -> faux if 'vide <> face/data [return false] ; coups d'introduction, seulement au centre if coups < 4 [ use [p][ p: face/parent-face/pane return either any [p/28 = face p/29 = face p/36 = face p/37 = face][true][false] ] ] ; cherche la présence voisine de jetons de l'adversaire suivis d'un jeton de même couleur ok: false c: face/parent-face/joueur foreach f-l [gauche droite haut bas haut-gauche haut-droite bas-gauche bas-droite][ if all [face/:f-l/1 face/:f-l/1/data <> c][ b: false foreach f face/:f-l [ if any ['vide = f/data b: c = f/data][break] ] if b [ok: true foreach f face/:f-l [ if c = f/data [break] f/data: c f/effect: select jeton-effects f/data show f ]] ] ] ok ] ; Table de décision du joueur machine ; tactique: 1) prendre les coins du plateau ; 2) ne pas laisser l'adversaire les prendre ; 3) contrôler les bords ; 4) retourner un maximum de jetons valeurs: [ [ 36 (either ordinateur = plateau/pane/1/data [24][-18]) 5.5 5.5 5.5 5.5 (either ordinateur = plateau/pane/8/data [24][-18]) 36 ][ (either ordinateur = plateau/pane/1/data [24][-18]) (either ordinateur = plateau/pane/1/data [2][-29]) -11 -11 -11 -11 (either ordinateur = plateau/pane/8/data [2][-29]) (either ordinateur = plateau/pane/8/data [24][-18]) ][ 5.5 -11 1 1 1 1 -11 5.5 ][ 5.5 -11 1 1 1 1 -11 5.5 ][ 5.5 -11 1 1 1 1 -11 5.5 ][ 5.5 -11 1 1 1 1 -11 5.5 ][ (either ordinateur = plateau/pane/57/data [24][-18]) (either ordinateur = plateau/pane/57/data [2][-29]) -11 -11 -11 -11 (either ordinateur = plateau/pane/64/data [2][-29]) (either ordinateur = plateau/pane/64/data [24][-18]) ][ 36 (either ordinateur = plateau/pane/57/data [24][-18]) 5.5 5.5 5.5 5.5 (either ordinateur = plateau/pane/64/data [24][-18]) 36 ] ] ; intérêt/risque actuel de prendre une case valeur-case: func [ "Valeur actuelle d'une case" offset "Position sur le plateau" /local x y ][ x: offset/x y: offset/y do valeurs/:y/:x ] ; Détermination du meilleur coup pour le joueur actuel, à l'aide de la table de valeurs meilleur-coup: func [ "Recherche du meilleur coup" joueur "Joueur en cours" /local liste-coups p valeur b ][ ; liste des coups possibles liste-coups: copy [] ; en début de partie, une des case du centre if coups < 4 [ p: plateau/pane foreach case random [28 29 36 37] [ if 'vide = p/:case/data [return p/:case] ] ] ; construit la liste des coups possibles accompagnés de leur pondération foreach p plateau/pane [ if 'vide = p/data [ foreach f-l [ gauche droite haut bas haut-gauche haut-droite bas-gauche bas-droite ][ valeur: valeur-case p/coords if all [p/:f-l/1 p/:f-l/1/data <> joueur][ b: false foreach f p/:f-l [ if any ['vide = f/data b: joueur = f/data][break] valeur: valeur + valeur-case f/coords ] if b [repend liste-coups [valeur p]] ] ] ] ] ; pas de coup possible either empty? liste-coups [ none ][ ; tri avec les meilleurs coups en premier sort/reverse/skip liste-coups 2 ; suivant le niveau, on prend un des 3 meilleurs/des 2 meilleurs/le meilleur either 6 <= length? liste-coups [ pick liste-coups 2 * random select reduce [ locale level/min 3 locale level/med 2 locale level/max 1 ] first niveau/data ][ second liste-coups ] ] ] ; ===Redimensionnement de la fenêtre ; référence de base last-size: base-size: fenetre/size ; sauvegarde des dimensions et des positions de départ base-sizes: copy [] foreach face [mode niveau passer fin aide plateau][ face: get face repend base-sizes [face face/size face/offset] append base-sizes either face/font [face/font/size][none] ] ; sauvegarde des coordonnées des cases jetons-offsets: copy [] foreach jeton plateau/pane [repend jetons-offsets [jeton jeton/offset]] ; adaptation de la fenêtre à l'écran actuel fenetre/size: fenetre/size * (system/view/screen-face/size/y / 768) ; fonction de redimensionnement, lancée la 1ère fois avant l'affichage do resize-all: insert-event-func [ if event/type = 'resize [ use [delta-x delta-y facteur taille][ ;facteur de redimensionnement delta-x: abs fenetre/size/x - last-size/x delta-y: abs fenetre/size/y - last-size/y facteur: either delta-x > delta-y [ fenetre/size/x / base-size/x ][ fenetre/size/y / base-size/y ] if facteur < 0.014 [return event] ;redimensionnement des contrôles foreach [face size offset font] base-sizes [ face/size: size * facteur face/offset: offset * facteur if font [face/font/size: to-integer font * facteur] ] ;redimensionnement des cases et des jetons taille: 74x74 * facteur foreach [jeton offset] jetons-offsets [ jeton/size: taille jeton/offset: offset * facteur ] ;redimensionnement de la grille taille: 75x75 * facteur plateau/size: plateau/size / taille * taille + 2x2 change find plateau/effect pair! taille last-size: fenetre/size if (abs delta-x - delta-y) > 2 [ fenetre/size: base-size * facteur ] show fenetre ] ] event ] fenetre context [type: 'resize] ; ===Lancement du jeu ; initialisation du générateur aléatoire random/seed now ; cases de départ coups-depart ; affichage fenêtre principale view/options fenetre 'resize ; ===Fin quit
halt ;; to terminate script if DO'ne from webpage
Notes