;; =================================== ;; Progetto di Informatica e Didattica ;; a.a. 2006-2007 ;; Alessandro Cosentino ;; =================================== breed [mines mine] breed [turtlesc turtlec] globals [cwin matrix colors] patches-own [visited flagged] ;; Genera una tartaruga in ognuna delle caselle che circondano la mina to parto if (ycor < max-pycor) [ if (xcor < max-pxcor) [ figlia 1 1 ] figlia 0 1 if (xcor > min-pxcor) [figlia -1 1 ] ] if (ycor > min-pycor) [ if (xcor < max-pxcor) [ figlia 1 -1 ] figlia 0 -1 if (xcor > min-pxcor) [ figlia -1 -1 ] ] if (xcor < max-pxcor) [ figlia 1 0 ] if (xcor > min-pxcor) [ figlia -1 0] end to figlia [xp yp] if ((count mines-at xp yp) = 0) [hatch-turtlesc 1 [setxy ((xcor-of myself) + xp) ((ycor-of myself) + yp)]] end ;; imposta la forma delle tartarughe in base a quante ce ne sono nella stessa cella: ;; la forma corrisponde al numerale corrispondente to numerini let num count turtlesc-here set shape "shape-" + num set color item (num - 1) colors end to setup ht set heading 0 set color white set colors [yellow violet sky red lime cyan magenta green] without-interruption [ setxy (first (first matrix)) (last (first matrix)) set matrix but-first matrix ] end ;; E' la procedura che avvia il gioco: crea le mine, ne avvia le procedure di setup ;; e gestisce gli eventi di terminazione del gioco, stampando il risultato. to newgame clear-all output-print "PRONTI..." create-mines minesNum set cwin (world-height * world-width - count mines) ;; Crea una lista i cui elementi sono tutte le caselle del mondo. ;; La lista viene mescolata in maniera casuale per distribiure ;; le mine su caselle diverse. set matrix [] let x 0 let y 0 repeat world-width [ set y 0 repeat world-height [ set matrix lput (list (x + min-pxcor) (y + min-pycor)) matrix set y (y + 1) ] set x (x + 1) ] set matrix shuffle matrix ask turtles [setup] ask patches [set visited false set flagged false] ask mines [parto] ask turtlesc [numerini] output-print "VIA!" reset-timer loop [ let mxcor max-pxcor + 1 let mycor max-pycor + 1 if mouse-down? [ set mxcor (round mouse-xcor) set mycor (round mouse-ycor) ] let mousevent "" if (mxcor != max-pxcor + 1) [ set mousevent (gestisci_mouse mxcor mycor) ] display ifelse (mousevent = "lose") [ output-print "HAI PERSO :( in " + timer + " sec" ask turtles-at mxcor mycor [set shape "cross" stampcolor red] ask mines [st] display stop ] [ if (mousevent = "win") [ output-print "HAI VINTO :) in " + timer + " sec" stop ] ] ] file-close-all end ;; La seguente procedura colora la patch sotto la tartaruga ;; del colore passato come parametro to stampcolor [colorp] set pcolor-of patch-here colorp end ;; Gestisce gli eventi generati dal mouse e restituisce una stringa: ;; - "lose" se e' stata colpita una mina ;; - "continue" altrimenti to-report gestisci_mouse [mxcor mycor] ifelse (Bandiera? = "OFF") [ ifelse ((count mines-at mxcor mycor) > 0) [report "lose"] [(apri mxcor mycor) if vittoria? [report "win"]] report "continue" ] [ plant_flag mxcor mycor report "continue" ] end ;; Pianta la bandiera nella patch nella posizione (x, y) ;; e colora quest'ultima di arancione. to plant_flag [x y] if (not visited-of (patch-at x y)) [ ifelse (Bandiera? = "pianta") [ if ((count patches with [flagged = true]) < minesNum) [ask patch-at x y [set flagged true set pcolor orange]] ] [ if (Bandiera? = "spianta") [ ask patch-at x y [set flagged false set pcolor black] ] ] ] end ;; Restituisce true se la partita e' finita to-report vittoria? report (cwin <= 0) end to apri [mxcor mycor] if (not visited-of (patch-at mxcor mycor)) [ set cwin (cwin - 1) ask patch-at mxcor mycor [set pcolor gray set visited true] ifelse ((count turtlesc-at mxcor mycor) > 0) [ask turtles-at mxcor mycor [st]] [ if (mycor < max-pycor) [ if (mxcor < max-pxcor) [apri (mxcor + 1) (mycor + 1)] apri mxcor (mycor + 1) if (mxcor > min-pxcor) [apri (mxcor - 1) (mycor + 1)]] if (mycor > min-pycor) [ if (mxcor < max-pxcor) [apri (mxcor + 1) (mycor - 1)] apri mxcor (mycor - 1) if (mxcor > min-pxcor) [apri (mxcor - 1) (mycor - 1)]] if (mxcor < max-pxcor) [apri (mxcor + 1) mycor] if (mxcor > min-pxcor) [apri (mxcor - 1) mycor] ] ] end @#$#@#$#@ GRAPHICS-WINDOW 276 14 646 405 4 4 40.0 1 20 1 1 1 0 0 0 1 -4 4 -4 4 CC-WINDOW 5 419 655 514 Command Center 0 SLIDER 42 203 223 236 minesNum minesNum 10 40 10 1 1 mine BUTTON 73 327 184 360 Nuovo Gioco newgame NIL 1 T OBSERVER NIL NIL OUTPUT 15 13 255 188 CHOOSER 42 250 149 295 Bandiera? Bandiera? "OFF" "pianta" "spianta" 0 MONITOR 157 247 223 296 Bandiere minesNum - (count patches with [flagged = true]) 0 1 @#$#@#$#@ LA STORIA ----------- Campo minato (in ingl. Minesweeper) e' un gioco, celebre nella sua versione Microsoft (Campo fiorito nelle versioni piu' recenti di Windows), inventato da Robert Donner e Curt Johnson nel 1981. In realta' e' un discendente del famoso Cube, gioco creato nel 1973 per PDP-11. Nelle versioni piu' recenti di Windows, il titolo e' stato rinominato in Prato Fiorito. SCOPO DEL GIOCO ------------ L'obiettivo del gioco e' scoprire tutto il territorio senza far esplodere le mine nel minor tempo possibile. COME SI GIOCA ------------- Ogni quadrato viene scoperto clickando su di esso se il flag Bandiera e' impostato ad . Se quest'ultimo e' sull'opzione il giocatore puo' segnare ogni quadrato in cui crede che sia presente una mina con una bandiera. Impostazioni come il numero di mine o le dimensioni del territorio possono essere cambiate solo prima dell'inizio della partita. Non si garantisce alcun comportamento corretto del programma nel caso esse siano modificate a partita in corso. IMPLEMENTAZIONE ------------- Il codice che da' vita al gioco puo' essere suddiviso in due sezioni principali: la prima e' una fase di setup in cui viene preparato il quadro, la seconda prevede invece l'interazione con il giocatore. Nella fase di setup viene creato un numero di tartarughe di razza "mine" (da qui in poi chiamate solo mine) pari al valore indicato dallo slider. Ad ognuna di esse viene richiesto di disporsi in una posizione casuale sul campo. Per garantire che in ogni casella ci sia al massimo una mina viene costruita una lista che contiene, in modo casuale, tutte le posizioni possibili del campo. Le mine accedono alla lista estrapolando il primo elemento in alcune istruzioni racchiuse in un blocco | without-interruption Questo comando crea un lock sulla struttura dati, poiche' l'agente che esegue comandi nel blocco non puo' essere "interrotto" da altri agenti, i quali nel frattempo sono "sospesi". Una volta che le mine si sono disposte in campo, ognuna di esse genera un figlio (tartarughe di razza "turtlec") per ogni casella circostante. Appena il "parto" e' completato si chiede alle turtlec di assumere una forma ed un colore corrispondente al numero di tartarughe che convivono sulla stessa patch. A questo punto il setup, che avviene ovviamente a tartarughe "nascoste", e' completato. Inizia quindi il ciclo che gestisce gli eventi generati dal giocatore con il mouse. Supponiamo a questo punto che il flag Bandiera sia impostato ad . Ad ogni click, la procedura gestisci-mouse controlla innanzitutto se a quelle coordinate corrisponde una mina: in tal caso dichiara la partita conclusa. Se invece, nella casella corrispondente non ci sono mine, si "apre" il campo (mostrando le tartarughe sottostanti) fino alla frontiera, ovvero fino a trovare caselle in cui ci sono solo tartarughe di razza "turtlec". Quando queste vengono mostrate, il giocatore puo' vedere il numerino corrispondente alla casella. L'esplorazione del territorio scoperto viene gestito dalla semplice procedura ricorsiva | apri [mxcor mycor] Per gestire la terminazione, viene mantenuta una variabile (cwin) che e' decrementata ogni volta che viene scoperta una parte di campo. Se cwin diviene uguale a 0 la partita viene dichirata vinta. Il valore del timer visualizzato sul pannello di output indica la durata della partita. STARLOGO O NETLOGO? ----------- Dopo una prima implementazione in StarLogo, il porting in NetLogo e' stato necessario per rendere piu' reattiva l'interazione con l'utente e per l'esistenza di un comando di "lock" sulle strutture dati (vedi sez. Implementazione). RIFERIMENTI ---------------------- http://it.wikipedia.org/wiki/Campo_minato http://www.planet-minesweeper.com/ @#$#@#$#@ default true 0 Polygon -7500403 true true 150 5 40 250 150 205 260 250 link true 0 Line -7500403 true 150 0 150 300 link direction true 0 Line -7500403 true 150 150 30 225 Line -7500403 true 150 150 270 225 cross true 0 Line -7500403 true 45 45 255 255 Line -7500403 true 45 255 255 45 shape-1 false 0 Rectangle -7500403 true true 165 60 180 240 Polygon -7500403 true true 165 60 120 120 135 135 shape-2 false 5 Line -7500403 false 90 105 105 75 Line -7500403 false 105 75 150 60 Line -7500403 false 150 60 195 75 Line -7500403 false 195 75 210 105 Line -7500403 false 210 105 90 225 Line -7500403 false 90 225 210 225 Line -10899396 true 210 225 90 225 Line -10899396 true 90 105 105 75 Line -10899396 true 210 105 90 225 Line -10899396 true 105 75 150 60 Line -10899396 true 150 60 195 75 Line -10899396 true 195 75 210 105 Rectangle -10899396 true true 90 225 210 240 Polygon -10899396 true true 210 105 210 120 105 225 90 225 Polygon -10899396 true true 90 105 105 105 120 75 180 75 195 120 210 105 195 75 150 60 105 75 shape-3 false 0 Polygon -7500403 true true 93 60 105 53 127 48 169 48 193 58 214 82 215 121 206 140 186 147 206 161 216 173 217 212 206 233 170 249 115 249 83 236 85 210 118 229 166 228 187 220 198 205 198 179 193 168 177 155 149 155 148 137 177 137 191 130 199 118 197 90 182 71 164 63 128 65 94 80 shape-4 false 0 Rectangle -7500403 true true 165 60 180 240 Rectangle -7500403 true true 75 180 210 195 Polygon -7500403 true true 165 60 75 180 90 180 165 75 165 60 shape-5 false 0 Rectangle -7500403 true true 103 60 193 75 Rectangle -7500403 true true 103 75 118 135 Polygon -7500403 true true 102 122 101 166 122 149 147 143 172 145 189 154 202 168 208 189 209 213 203 234 189 247 166 255 134 257 101 239 100 264 131 273 174 274 206 256 220 234 224 216 224 178 217 158 199 137 178 128 148 125 118 135 Rectangle -7500403 true true 178 60 216 75 shape-6 false 0 Polygon -7500403 true true 212 69 193 56 174 52 152 52 123 55 100 90 91 136 92 187 104 213 132 239 180 239 209 211 212 180 211 150 202 132 178 121 133 121 116 138 119 104 135 70 150 64 187 65 211 86 Circle -16777216 true false 117 137 80 Polygon -7500403 true true 211 151 218 182 209 210 shape-7 false 0 Polygon -7500403 true true 90 60 90 90 195 75 105 240 135 240 225 60 shape-8 true 0 Circle -7500403 false true 120 75 60 Circle -7500403 false true 96 141 108 @#$#@#$#@ NetLogo 3.1.3 @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ @#$#@#$#@