1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
# -*- tcl -*-
package require Tk
package require cache::async
package require struct::set
namespace eval ::city {
proc block {n} { variable part ; return [expr {$n * $part}] }
variable tessel 64
variable part [expr {$tessel/8}]
variable cstart [block 2]
variable cend [block 6]
variable rstart [block 3]
variable rend [block 5]
variable parcel [image create photo -height $part -width $part]
$parcel put black -to 0 0 $part $part
variable tilecache [cache::async tc ::city::Gen]
variable lego {}
variable neigh ; array set neigh {} ; # name,dir -> list(name)
variable map ; array set map {} ; # name -> (type flags)
variable grid ; array set grid {} ; # at -> name
}
proc ::city::tile {} {
variable tessel
return $tessel
}
proc ::city::grid {__ at donecmd} {
Tile get [Randomize $at] [list ::city::ToGrid $at $donecmd --]
return
}
proc ::city::ToGrid {at donecmd -- what key args} {
# Route the cache result retrieved by name to the grid cell the
# original request came from.
#puts "\tToGrid ($at) '$donecmd' $what ($key) <$args>"
if {[catch {
uplevel #0 [eval [linsert $args 0 linsert $donecmd end $what $at]]
}]} { puts $::errorInfo }
}
proc ::city::Randomize {at} {
variable grid
set p [Possibilities $at]
if {[llength $p] == 1} {
set res [lindex $p 0]
} else {
set res [lindex $p [Rand [llength $p]]]
}
#puts "($at) = $p"
set grid($at) $res
return $res
}
proc ::city::Rand {n} {
# 0...n-1
# (0,1) -> (0,n)
expr {int(rand()*$n)}
}
proc ::city::Possibilities {at} {
variable lego
variable grid
foreach {y x} $at break
set l [list [expr {$x - 1}] $y]
set r [list [expr {$x + 1}] $y]
set u [list $x [expr {$y - 1}]]
set d [list $x [expr {$y - 1}]]
set allowed $lego
Cut $l r allowed
Cut $r l allowed
Cut $u d allowed
Cut $d u allowed
return $allowed
}
proc ::city::Cut {at dir v} {
variable grid
variable neigh
upvar 1 $v allowed
foreach {y x} $at break
if {![info exists grid($at)]} return
set allowed [struct::set intersect $allowed $neigh($grid($at),$dir)]
return
}
proc ::city::Tile {__ name donecmd} {
variable tilecache
#puts "__ $name ($donecmd)"
$tilecache get $name $donecmd
return
}
proc ::city::Gen {__ name donecmd} {
variable tessel
variable cstart
variable cend
variable rstart
variable rend
variable parcel
variable map
#puts "\tGENERATE $name ($donecmd)"
foreach {olx orx oux odx ilx irx iux idx cx} $map($name) break
set tile [image create photo -height $tessel -width $tessel]
$tile put white -to 0 0 $tessel $tessel
#puts ([join $map($name) {)(}])|$olx|$orx|$oux|$odx|$ilx|$irx|$iux|$idx|$cx|
if {$cx} { $tile copy $parcel -to $rstart $rstart $rend $rend } ; # center
if {$olx} { $tile copy $parcel -to 0 $rstart $cstart $rend } ; # ou left
if {$orx} { $tile copy $parcel -to $cend $rstart $tessel $rend } ; # ou right
if {$oux} { $tile copy $parcel -to $rstart 0 $rend $cstart } ; # ou up
if {$odx} { $tile copy $parcel -to $rstart $cend $rend $tessel } ; # ou down
if {$ilx} { $tile copy $parcel -to $cstart $rstart $rstart $rend } ; # in left
if {$irx} { $tile copy $parcel -to $rend $rstart $cend $rend } ; # in right
if {$iux} { $tile copy $parcel -to $rstart $cstart $rend $rstart } ; # in up
if {$idx} { $tile copy $parcel -to $rstart $cend $rend $cend } ; # in down
if 0 {
set label $olx$orx$oux$odx/$ilx$irx$iux$idx/$cx
#set label [string range $name 0 3]/[string range $name 4 7]/[string index $name 8]
label .l$name -image $tile -bd 2 -relief sunken
pack .l$name -side left
tooltip::tooltip .l$name $label
}
#puts "run ([linsert $donecmd end set $name $tile])"
uplevel #0 [linsert $donecmd end set $name $tile]
return
}
proc ::city::Name {olx orx oux odx ilx irx iux idx cx} {
#set name "$olx$orx$oux$odx$ilx$irx$iux$idx$cx"
set name ""
if {$cx} { append name c } ; # center
if {$olx} { append name l } ; # left
if {$ilx} { append name - } ; # left
if {$orx} { append name r } ; # right
if {$irx} { append name _ } ; # right
if {$oux} { append name u } ; # up
if {$iux} { append name = } ; # up
if {$odx} { append name d } ; # down
if {$idx} { append name % } ; # down
if {$name eq ""} { set name empty }
#puts $name\ ...
return $name
}
proc ::city::Init {} {
variable lego
variable neigh
variable map
foreach olx {0 1} {
foreach orx {0 1} {
foreach oux {0 1} {
foreach odx {0 1} {
foreach ilx {0 1} {
foreach irx {0 1} {
foreach iux {0 1} {
foreach idx {0 1} {
foreach cx {0 1} {
# inner not allowed without center
if {!$cx && $ilx} continue
if {!$cx && $irx} continue
if {!$cx && $iux} continue
if {!$cx && $idx} continue
#if {!$olx && $ilx} continue
#if {!$orx && $irx} continue
#if {!$oux && $iux} continue
#if {!$odx && $idx} continue
set n [Name $olx $orx $oux $odx $ilx $irx $iux $idx $cx]
set map($n) [list $olx $orx $oux $odx $ilx $irx $iux $idx $cx]
lappend bins(l$olx) $n
lappend bins(r$orx) $n
lappend bins(u$oux) $n
lappend bins(d$odx) $n
lappend lego $n
}
}
}
}
}
}
}
}
}
#puts /[llength $lego]
# Now compute which tiles can be neighbours of what others, for
# all four sides.
foreach t $bins(d0) { foreach n $bins(u0) { lappend neigh($t,d) $n } }
foreach t $bins(d1) { foreach n $bins(u1) { lappend neigh($t,d) $n } }
foreach t $bins(l0) { foreach n $bins(r0) { lappend neigh($t,l) $n } }
foreach t $bins(l1) { foreach n $bins(r1) { lappend neigh($t,l) $n } }
foreach t $bins(u0) { foreach n $bins(d0) { lappend neigh($t,u) $n } }
foreach t $bins(u1) { foreach n $bins(d1) { lappend neigh($t,u) $n } }
foreach t $bins(r0) { foreach n $bins(l0) { lappend neigh($t,r) $n } }
foreach t $bins(r1) { foreach n $bins(l1) { lappend neigh($t,r) $n } }
foreach k [array names neigh] { set neigh($k) [lsort -unique $neigh($k)] }
return
}
::city::Init
#exit
|