######################################################################## # SimCity.tcl, by Don Hopkins. # Copyright (C) 2002 by Electronic Arts. # This file defines the user interface of SimCity. # Modify at your own risk! ######################################################################## ######################################################################## # Libraries ######################################################################## set errorInfo {} set auto_noexec 1 source $tk_library/wish.tcl ######################################################################## # Globals ######################################################################## set UniqueID 0 set State uninitialized set CityName "SimCity" set GameLevel 0 set SimHome [pwd] set CityLibDir $SimHome/cities set CityDir $CityLibDir set OldBudget 0 set BudgetRoadFund 0 set BudgetFireFund 0 set BudgetPoliceFund 0 set BudgetTaxRate 0 set DemandRes 0 set DemandCom 0 set DemandInd 0 set Priority 3 set Time 3 set AutoGoto 1 set AutoBudget 1 set Disasters 1 set AutoBulldoze 1 set Sound 1 set DoAnimation 1 set DoMessages 1 set DoNotices 1 set ShapePies 1 set SoundServers {} set AudioChannels {mode edit fancy warning intercom} set BudgetTimeout 30 set BudgetTimer 0 set BudgetTimerActive 0 set BudgetsVisible 0 set EvaluationsVisible 0 set Scenario -1 set Chatting 0 #set ChatServer "www.LushCreations.com" set ChatServer "localhost" set ChatSocket 6667 set ChatConnection {} set NickName "nickname" set UserName "username" set ServerName "servername" set RealName "realname" set ChannelName "#SimCity" set HomeDir "" set ResourceDir "" set HostName "" set LocalHostName "[exec hostname]" set SaveCityWin "" set MapHistory {} set MapHistoryNum -1 set HelpLoaded 0 set QueryX 0 set QueryY 0 set FreeVotes 0 set ShowingPicture 300 set MaxLines 500 set ShrinkLines 250 set ShowingParms {} set VoteNames {UseThisMap Ask Zone} set VotesForUseThisMap {} set VotesForAsk {} set VotesForZone {} set VotesForBudget {} set CurrentDate {} set WebServer {} set WebSocket 9993 set HeadWindows {} set EditorWindows {} set MapWindows {} set GraphWindows {} set BudgetWindows {} set EvaluationWindows {} set ScenarioWindows {} set FileWindows {} set AskWindows {} set PlayerWindows {} set NoticeWindows {} set HelpWindows {} set FrobWindows {} set HeadPanelWidth 360 set HeadPanelHeight 200 set MapPanelWidth 360 set MapPanelHeight 330 set NoticePanelWidth 360 set NoticePanelHeight 250 set ScenarioPanelWidth 415 set ScenarioPanelWidth 420 set ScenarioPanelHeight 440 set SubWindows { {editor EditorWindows} {map MapWindows} {graph GraphWindows} {budget BudgetWindows} {evaluation EvaluationWindows} {scenario ScenarioWindows} {file FileWindows} {ask AskWindows} {player PlayerWindows} {notice NoticeWindows} {help HelpWindows} {frob FrobWindows} {head HeadWindows} } set FontInfo_Adobe { {Big { {-Adobe-Helvetica-Bold-R-Normal-*-140-100-100-*} {-Adobe-Helvetica-Bold-R-Normal-*-180-75-75-*} }} {Large { {-Adobe-Helvetica-Bold-R-Normal-*-100-100-100-*} {-Adobe-Helvetica-Bold-R-Normal-*-140-75-75-*} }} {Medium { {-Adobe-Helvetica-Bold-R-Normal-*-90-100-100-*} {-Adobe-Helvetica-Bold-R-Normal-*-120-75-75-*} }} {Small { {-Adobe-Helvetica-Bold-R-Normal-*-80-100-100-*} {-Adobe-Helvetica-Bold-R-Normal-*-100-75-75-*} }} {Narrow { {-Adobe-Helvetica-Medium-R-Normal-*-80-100-100-*} {-Adobe-Helvetica-Medium-R-Normal-*-100-75-75-*} }} {Tiny { {-Adobe-Helvetica-Bold-R-Normal-*-80-100-100-*} {-Adobe-Helvetica-Bold-R-Normal-*-80-75-75-*} }} {Text { {-Adobe-Helvetica-Medium-R-Normal-*-100-100-100-*} {-Adobe-Helvetica-Medium-R-Normal-*-140-75-75-*} }} {Message { {-Adobe-Helvetica-Bold-R-Normal-*-100-100-100-*} {-Adobe-Helvetica-Bold-R-Normal-*-140-75-75-*} }} {Alert { {-Adobe-Helvetica-Bold-O-Normal-*-100-100-100-*} {-Adobe-Helvetica-Bold-O-Normal-*-140-75-75-*} }} } # Hacked for OLPC set FontInfo { {Big { {fixed} {fixed} }} {Large { {fixed} {fixed} }} {Medium { {fixed} {fixed} }} {Small { {fixed} {fixed} }} {Narrow { {fixed} {fixed} }} {Tiny { {fixed} {fixed} }} {Text { {fixed} {fixed} }} {Message { {fixed} {fixed} }} {Alert { {fixed} {fixed} }} } set MapTitles { {SimCity Overall Map} {Residential Zone Map} {Commercial Zone Map} {Industrial Zone Map} {Power Grid Map} {Transportation Map} {Population Density Map} {Rate of Growth Map} {Traffic Density Map} {Pollution Desity Map} {Crime Rate Map} {Land Value Map} {Fire Coverage Map} {Police Coverage Map} {Dynamic Filter Map} } set EditorPallets { leftframe.tools.palletres leftframe.tools.palletcom leftframe.tools.palletind leftframe.tools.palletfire leftframe.tools.palletquery leftframe.tools.palletpolice leftframe.tools.palletwire leftframe.tools.palletbulldozer leftframe.tools.palletrail leftframe.tools.palletroad leftframe.tools.palletchalk leftframe.tools.palleteraser leftframe.tools.palletstadium leftframe.tools.palletpark leftframe.tools.palletseaport leftframe.tools.palletcoal leftframe.tools.palletnuclear leftframe.tools.palletairport } set EditorPalletImages { res com ind fire qry pol wire dozr rail road chlk ersr stad park seap coal nuc airp } set EditorPalletSounds { Res Com Ind Fire Query Police Wire Bulldozer Rail Road Chalk Eraser Stadium Park Seaport Coal Nuclear Airport } set GraphPallets { leftframe.left.res leftframe.left.com leftframe.left.ind leftframe.right.money leftframe.right.crime leftframe.right.pollution } set GraphPalletImages { res com ind mony crim poll } set GraphYearPallets { leftframe.year.year10 leftframe.year.year120 } set GraphYearPalletImages { 10 120 } set ToolInfo { { {a} {Residential Zone} {$100}} { {a} {Commercial Zone} {$100}} { {an} {Industrial Zone} {$100}} { {a} {Fire Station} {$500}} { {a} {Query} {free}} { {a} {Police Station} {$500}} { {a} {Wire} {$5}} { {a} {Bulldozer} {$1}} { {a} {Rail} {$20}} { {a} {Road} {$10}} { {a} {Chalk} {free}} { {an} {Eraser} {free}} { {a} {Stadium} {$5,000}} { {a} {Park} {$20}} { {a} {Seaport} {$3,000}} { {a} {Coal Power Plant} {$3,000}} { {a} {Nuclear Power Plant} {$5,000}} { {an} {Airport} {$10,000}} { {a} {Network} {$1,000}} } set DynamicDataNames { {Population Density} {Rate of Growth} {Traffic Density} {Pollution Density} {Crime Rate} {Land Value} {Police Coverage} {Fire Coverage} } ######################################################################## # Initialization ######################################################################## wm title . {SimCity Root} if {"[sim Platform]" == "msdos"} { sim DoAnimation 0 set DoAnimation 0 set ShapePies 0 } else { sim DoAnimation 1 set DoAnimation 1 set ShapePies 1 } sprite explosion 7 sprite tornado 6 sprite airplane 3 sprite helicopter 2 sprite monster 5 sprite ship 4 sprite bus 8 sprite train 1 sim ResetDynamic ######################################################################## # Messages ######################################################################## proc Message {id color title msg {props {}}} { global Messages set Messages($id) [list $color $title $msg $props] } Message 1 #7f7fff {DULLSVILLE, USA 1900} \ {Things haven't changed much around here in the last hundred years or so and the residents are beginning to get bored. They think Dullsville could be the next great city with the right leader. It is your job to attract new growth and development, turning Dullsville into a Metropolis within 30 years.} Message 2 #7f7fff {SAN FRANCISCO, CA. 1906} \ {Damage from the earthquake was minor compared to that of the ensuing fires, which took days to control. 1500 people died. Controlling the fires should be your initial concern. Then clear the rubble and start rebuilding. You have 5 years.} Message 3 #7f7fff {HAMBURG, GERMANY 1944} \ {Allied fire-bombing of German cities in WWII caused tremendous damage and loss of life. People living in the inner cities were at greatest risk. You must control the firestorms during the bombing and then rebuild the city after the war. You have 5 years.} Message 4 #7f7fff {BERN, SWITZERLAND 1965} \ {The roads here are becoming more congested every day, and the residents are upset. They demand that you do something about it. Some have suggested a mass transit system as the answer, but this would require major rezoning in the downtown area. You have 10 years.} Message 5 #7f7fff {TOKYO, JAPAN 1957} \ {A large reptilian creature has been spotted heading for Tokyo bay. It seems to be attracted to the heavy levels of industrial pollution there. Try to control the fires, then rebuild the industrial center. You have 5 years.} Message 6 #7f7fff {DETROIT, MI. 1972} \ {By 1970, competition from overseas and other economic factors pushed the once "automobile capital of the world" into recession. Plummeting land values and unemployment then increased crime in the inner-city to chronic levels. You have 10 years to reduce crime and rebuild the industrial base of the city.} Message 7 #7f7fff {BOSTON, MA. 2010} \ {A major meltdown is about to occur at one of the new downtown nuclear reactors. The area in the vicinity of the reactor will be severly contaminated by radiation, forcing you to restructure the city around it. You have 5 years to get the situation under control.} Message 8 #7f7fff {RIO DE JANEIRO, BRAZIL 2047} \ {In the mid-21st century, the greenhouse effect raised global temperatures 6 degrees F. Polar icecaps melted and raised sea levels worldwide. Coastal areas were devastated by flood and erosion. You have 10 years to turn this swamp back into a city again.} Message 9 #ffa500 {Query Zone Status} \ { Zone: %s Density: %s Value: %s Crime: %s Pollution: %s Growth: %s} \ {{view {PanView $v $QueryX $QueryY}}} Message 10 #ff4f4f {POLLUTION ALERT!} \ {Pollution in your city has exceeded the maximum allowable amounts established by the SimCity Pollution Agency. You are running the risk of grave ecological consequences. Either clean up your act or open a gas mask concession at city hall.} \ {{view {PanView $v [sim PolMaxX] [sim PolMaxY]}}} Message 11 #ff4f4f {CRIME ALERT!} \ {Crime in your city is our of hand. Angry mobs are looting and vandalizing the central city. The president will send in the national guard soon if you cannot control the problem.} \ {{view {PanView $v [sim CrimeMaxX] [sim CrimeMaxY]}}} Message 12 #ff4f4f {TRAFFIC WARNING!} \ {Traffic in this city is horrible. The city gridlock is expanding. The commuters are getting militant. Either build more roads and rails or get a bulletproof limo.} \ {{view {PanView $v [sim TrafMaxX] [sim TrafMaxY]}}} Message 20 #ff4f4f {FIRE REPORTED!} \ "A fire has been reported!" \ {{view {PanView $v [sim CrashX] [sim CrashY]}}} Message 21 #ff4f4f {MONSTER ATTACK!} \ "A large reptilian creature has been spotted in the water. It seems to be attracted to areas of high pollution. There is a trail of destruction wherever it goes. \ All you can do is wait till he leaves, then rebuild from the rubble." \ {{view {FollowView $v monster}}} # XXX: write more text Message 22 #ff4f4f {TORNADO ALERT!} \ {A tornado has been reported! There's nothing you can do to stop it, so you'd better prepare to clean up after the disaster!} \ {{view {FollowView $v tornado}}} # XXX: write more text Message 23 #ff4f4f {EARTHQUAKE!} \ {A major earthquake has occurred! Put out the fires as quickly as possible, before they spread, then reconnect the power grid and rebuild the city.} \ {{view {PanView $v [sim CenterX] [sim CenterY]}}} # XXX: write more text Message 24 #ff4f4f {PLANE CRASH!} \ {A plane has crashed!} \ {{view {PanView $v [sim CrashX] [sim CrashY]}}} # XXX: write more text Message 25 #ff4f4f {SHIPWRECK!} \ {A ship has wrecked!} \ {{view {PanView $v [sim CrashX] [sim CrashY]}}} # XXX: write more text Message 26 #ff4f4f {TRAIN CRASH!} \ {A train has crashed!} \ {{view {PanView $v [sim CrashX] [sim CrashY]}}} # XXX: write more text Message 27 #ff4f4f {HELICOPTER CRASH!} \ {A helicopter has crashed!} \ {{view {PanView $v [sim CrashX] [sim CrashY]}}} Message 30 #ff4f4f {FIREBOMBING REPORTED!} \ {Firebombs are falling!!} \ {{view {PanView $v [sim CrashX] [sim CrashY]}}} Message 35 #7fff7f {TOWN} \ {Congratulations, your village has grown to town status. You now have 2,000 citizens.} \ {{view {PanView $v [sim CenterX] [sim CenterY]}}} Message 36 #7fff7f {CITY} \ {Your town has grown into a full sized city, with a current population of 10,000. Keep up the good work!} \ {{view {PanView $v [sim CenterX] [sim CenterY]}}} Message 37 #7fff7f {CAPITAL} \ {Your city has become a capital. The current population here is 50,000. Your political future looks bright.} \ {{view {PanView $v [sim CenterX] [sim CenterY]}}} Message 38 #7fff7f {METROPOLIS} \ {Your capital city has now achieved the status of metropolis. The current population is 100,000. With your management skills, you should seriously consider running for governor.} \ {{view {PanView $v [sim CenterX] [sim CenterY]}}} Message 39 #7fff7f {MEGALOPOLIS} \ {Congratulation, you have reached the highest category of urban development, the megalopolis. If you manage to reach this level, give us a call at Maxis or send us a copy of your city. We might do something interesting with it.} \ {{view {PanView $v [sim CenterX] [sim CenterY]}}} Message 40 #7fff7f {MEGALINIUM} \ {Congratulation, you have reached the end of time! Because of the toroidal nature of the the SimCity Space/Time Continuom, your city has wrapped back in time to 1900!} \ {{view {PanView $v [sim CenterX] [sim CenterY]}}} # XXX: write more text Message 41 #ff4f4f {HEAVY TRAFFIC!} \ {Sky Watch One reporting heavy traffic!} \ {{view {FollowView $v helicopter}}} # XXX: write more text Message 42 #ff4f4f {FLOODING REPORTED!} \ {Flooding has been been reported along the water's edge!} \ {{view {PanView $v [sim FloodX] [sim FloodY]}}} Message 43 #ff4f4f {NUCLEAR MELTDOWN!} \ {A nuclear meltdown has occured at your power plant. You are advised to avoid the area until the radioactive isotopes decay. Many generations will confront this problem before it goes away, so don't hold your breath.} \ {{view {PanView $v [sim MeltX] [sim MeltY]}}} Message 44 #ff4f4f {RIOTS!} \ {The citizens are rioting in the streets, setting cars and houses on fire, and bombing government buildings and businesses! All media coverage is blacked out, while the fascist pigs beat the poor citizens into submission.} Message 46 #ff4f4f {NO SOUND SERVER!} \ {There is no sound server running on your X11 display "%s". You won't hear any noise unless you run a sound server, and turn the sound back on in the "Options" menu.} Message 48 #7f7fff {Start a New City} \ {Build your very own city from the ground up, starting with this map of uninhabited land.} Message 49 #7f7fff {Restore a Saved City} \ {This city was saved in the file named: %s} Message 100 #7fff7f {YOU'RE A WINNER!} \ {Your mayorial skill and city planning expertise have earned you the KEY TO THE CITY. Local residents will erect monuments to your glory and name their first-born children after you. Why not run for governor?} \ {{middle {@images/key2city.xpm}}} Message 200 #ff4f4f {IMPEACHMENT NOTICE!} \ {The entire population of this city has finally had enough of your inept planning and incompetant management. An angry mob -- led by your mother -- has been spotted in the vicinity of city hall. You should seriously consider taking an extended vacation -- NOW. (Or read the manual and try again.)} Message 300 #ffd700 {About SimCity} \ "Multi Player SimCity Version [sim Version] Copyright (C) 2007 by Electronic Arts. Multi Player User Interface Designed and Created by Don Hopkins. Ported to Linux, Optimized and Adapted for OLPC by Don Hopkins. Based on the Original SimCity Concept and Design by Will Wright, Maxis Software, Electronic Arts." \ {{left {@images/maxis.xpm}} {middle {@images/simcityl.xpm}} {right {@images/maxis.xpm}}} ######################################################################## # Options ######################################################################## option add *CheckButton.relief flat option add *Dialog.cursor top_left_arrow option add *Entry.relief sunken option add *Frame.borderWidth 0 option add *Listbox.relief sunken option add *Scrollbar.relief sunken option add *RadioButton.anchor w option add *RadioButton.relief flat option add *background #b0b0b0 option add *foreground #000000 option add *activeBackground #d0d0d0 option add *activeForeground #000000 option add *disabledForeground "" option add *selectBackground #d0d0d0 option add *selectForeground #000000 #option add *selector #ffff80 option add *selector #bf0000 option add *Scrollbar.Background #b0b0b0 option add *Scrollbar.Foreground #d0d0d0 option add *Interval.Background #b0b0b0 option add *Interval.Foreground #000000 option add *Interval.activeForeground #d0d0d0 option add *Interval.sliderForeground #b0b0b0 option add *Scale.activeForeground #d0d0d0 option add *Scale.sliderForeground #b0b0b0 option add *PieMenu.activeBackground #b0b0b0 option add Mwm*SimCity.clientDecoration -maximize ######################################################################## # Global Bindings ######################################################################## bind all {HandleHelp %W %x %y %X %Y} bind all {HandleHelp %W %x %y %X %Y} bind all {HandleHelp %W %x %y %X %Y} bind all {HandleHelp %W %x %y %X %Y} ######################################################################## # Utilities ######################################################################## proc echo {args} { puts stdout $args flush stdout } proc Unique {} { global UniqueID set id $UniqueID incr UniqueID return $id } proc tkerror {err} { global errorInfo puts stderr "$errorInfo" } proc ident {i} { return "$i" } proc NoFunction {args} {} proc LinkWindow {fromname to} { global WindowLinks set WindowLinks($fromname) $to } proc WindowLink {fromname} { global WindowLinks set to "" catch {set to $WindowLinks($fromname)} return $to } proc DeleteWindow {sym name win} { set head [WindowLink $win.head] LinkWindow $head.$sym {} global $name set wins [eval ident "\$$name"] set i [lsearch $wins $win] if {$i != -1} { set $name [lreplace $wins $i $i] } destroy $win } proc Font {win name} { global FontInfo FontCache HeadWindows set scr [winfo screen $win] set font "" catch { set font $FontCache($scr,$name) } if {"$font" == ""} { set label "" catch { set label $FontCache($scr) } if {"$label" == ""} { foreach head $HeadWindows { if {"[winfo screen $head]" == "$scr"} { set label $head.fontlabel label $label -text "X11 Sucks" -font fixed set FontCache($scr) $label } } } set fonts [keylget FontInfo $name] foreach font $fonts { if {[catch "$label config -font $font"] == 0} { break } else { set font "" } } if {"$font" == ""} { #set font 8x16 # OLCP default font set font 6x13 } set FontCache($scr,$name) $font } return $font } proc Color {win color mono} { if {[winfo screendepth $win] == 1} { return $mono } else { return $color } } ######################################################################## # Window Definition Functions ######################################################################## proc MakeWindow.head {{display ":0"}} { global ResourceDir source $ResourceDir/whead.tcl return $win } proc MakeWindow.editor {head {display ":0"}} { global ResourceDir source $ResourceDir/weditor.tcl return $win } proc MakeWindow.map {head {display ":0"}} { global ResourceDir source $ResourceDir/wmap.tcl return $win } proc MakeWindow.graph {head {display ":0"}} { global ResourceDir source $ResourceDir/wgraph.tcl return $win } proc MakeWindow.budget {head {display ":0"}} { global ResourceDir source $ResourceDir/wbudget.tcl return $win } proc MakeWindow.evaluation {head {display ":0"}} { global ResourceDir source $ResourceDir/weval.tcl return $win } proc MakeWindow.scenario {head {display ":0"}} { global ResourceDir source $ResourceDir/wscen.tcl return $win } proc MakeWindow.file {head {display ":0"}} { global ResourceDir source $ResourceDir/wfile.tcl return $win } proc MakeWindow.ask {head {display ":0"}} { global ResourceDir source $ResourceDir/wask.tcl return $win } proc MakeWindow.player {head {display ":0"}} { global ResourceDir source $ResourceDir/wplayer.tcl return $win } proc MakeWindow.notice {head {display ":0"}} { global ResourceDir source $ResourceDir/wnotice.tcl return $win } proc MakeWindow.help {head {display ":0"}} { global ResourceDir source $ResourceDir/whelp.tcl return $win } proc MakeWindow.frob {head {display ":0"}} { global ResourceDir source $ResourceDir/wfrob.tcl return $win } ######################################################################## # Sound Support ######################################################################## proc UIInitializeSound {} { } proc UIShutDownSound {} { } proc UIDoSoundOn {win cmd} { global Sound SoundServers if {$Sound} { set win [WindowLink [winfo toplevel $win].head] if {[lsearch $SoundServers $win] != -1} { set cmd "send -quick -server $win Sound sound $cmd" if {[catch $cmd]} { # XXX: Lost a sound server... LostSoundServer $win } } } } proc UIDoSound {cmd} { global Sound SoundServers if {$Sound} { foreach win $SoundServers { set foo "send -quick -server $win Sound $cmd" if {[catch $foo]} { # XXX: Lost a sound server... LostSoundServer $win } } } } proc KillSoundServers {} { global SoundServers foreach win $SoundServers { set foo "send -quick -server $win Sound KillSoundServer" catch $foo } set SoundServers {} } proc UISetChannelVolume {win chan vol} { UIDoSoundOn $win "channel $chan -volume $vol" } proc UIMakeSoundOn {win chan sound {opts ""}} { UIDoSoundOn $win "play $sound -replay -channel $chan $opts" } proc UIStartSoundOn {win chan sound {opts ""}} { UIDoSoundOn $win "play $sound -replay -channel $chan -repeat 100 $opts" } proc UIStopSoundOn {win chan sound {opts ""}} { UIDoSoundOn $win "stop $sound" } proc UIMakeSound {chan sound {opts ""}} { UIDoSound "sound play $sound -replay -channel $chan $opts" } proc UIStartSound {chan sound {opts ""}} { UIDoSound "sound play $sound -channel $chan -repeat 100 $opts" } proc UIStopSound {chan sound {opts ""}} { UIDoSound "sound stop $sound" } proc SetupSoundServer {win} { AddSoundServer $win } proc AddSoundServer {win} { global SoundServers set i [lsearch $SoundServers $win] if {$i < 0} { set SoundServers [linsert $SoundServers 0 $win] } } proc LostSoundServer {win} { DeleteSoundServer $win # UIShowPictureOn [WindowLink $win.head] 46 [winfo screen $win] } proc DeleteSoundServer {win} { global SoundServers set i [lsearch $SoundServers $win] if {$i >= 0} { set SoundServers [lreplace $SoundServers $i $i] } } proc UISoundOff {} { } proc MonsterSpeed {} { return [expr "[sim Rand 40] + 70"] } proc ExplosionPitch {} { return [expr "[sim Rand 20] + 90"] } proc HonkPitch {} { return [expr "[sim Rand 20] + 90"] } ######################################################################## # Global Window Handlers proc WithdrawAll {} { WithdrawHeads WithdrawEditors WithdrawMaps WithdrawGraphs WithdrawBudgets WithdrawEvaluations WithdrawScenarios WithdrawFiles WithdrawAsks WithdrawPlayers WithdrawNotices WithdrawHelps WithdrawFrobs } proc ShowInitial {} { ShowHeads ShowEditors ShowMaps EnableMaps } ######################################################################## # Head Window Handlers proc PrepHead {head} { global State InitHeadMenus $head case $State { uninitialized { } scenario { ShowHeadOf $head ShowScenarioOf $head ShowMapOf $head DisableMaps ReShowPictureOn $head sim UpdateEditors sim UpdateMaps } play { ShowHeadOf $head ShowEditorOf $head ShowMapOf $head EnableMaps ReShowPictureOn $head InitHead $head InitHeadMenus $head } } } proc ShowHeadOf {head} { wm deiconify $head } proc ShowHeads {} { global HeadWindows foreach win $HeadWindows { ShowHeadOf $win } } proc WithdrawHeads {} { global HeadWindows foreach win $HeadWindows { wm withdraw $win } } proc DeleteHeadWindow {head} { UIQuit $head } proc InitHeads {} { global HeadWindows foreach win $HeadWindows { InitHead $win } } proc InitHead {win} { set w [WindowLink $win.text] $w configure -state normal $w delete 0.0 end $w insert end "\n" $w configure -state disabled set w [WindowLink $win.entry] $w delete 0 end global ${w}.value set ${w}.value "" sim UpdateHeads UIUpdateRunning } proc InitAllHeadMenus {} { global HeadWindows foreach win $HeadWindows { InitHeadMenus $win } } proc InitHeadMenus {win} { global State set m0 [WindowLink $win.m0] set m1 [WindowLink $win.m1] set m2 [WindowLink $win.m2] set m3 [WindowLink $win.m3] set m4 [WindowLink $win.m4] set m5 [WindowLink $win.m5] set b0 [WindowLink $win.b0] set b1 [WindowLink $win.b1] set b2 [WindowLink $win.b2] set b3 [WindowLink $win.b3] set b4 [WindowLink $win.b4] set b5 [WindowLink $win.b5] case $State { uninitialized { } scenario { $m0 unpost $m1 unpost $m2 unpost $m3 unpost $m4 unpost $m5 unpost $m0 disable 1 $m0 disable 2 $m0 disable 4 $b0 config -state normal # $b1 config -state disabled $b2 config -state disabled $b3 config -state disabled # $b4 config -state disabled $b5 config -state disabled } play { $m0 enable 1 $m0 enable 2 $m0 enable 4 $b0 config -state normal # $b1 config -state normal $b2 config -state normal $b3 config -state normal # $b4 config -state normal $b5 config -state normal } } } proc UIDisaster {win cmd action} { AskQuestion [Color $win #ff0000 #ffffff] "Cause a Disaster" \ "Oh no! Do you really want to $action" \ "{No way!} Disaster.No {WithdrawAsks}" \ "" \ "{I guess so.} Disaster.Yes {WithdrawAsks ; $cmd}" } proc CrushHead {head} { global SubWindows VoteNames foreach foo $VoteNames { global VotesFor$foo set votes [eval ident \$VotesFor$foo] set i [lsearch $votes $head] if {$i != -1} { set VotesFor$foo [lreplace $votes $i $i] } } foreach foo $SubWindows { set sym [lindex $foo 0] set name [lindex $foo 1] global $name set wins [eval ident "\$$name"] foreach win $wins { if {[WindowLink $win.head] == $head} { DeleteWindow $sym $name $win } } } } proc ChatDown {win} { tk_butDown $win } proc ChatUp {win} { tk_butUp $win global Chatting if {$Chatting} { CloseChat } else { OpenChat } } proc OpenChat {} { global Chatting global ChatServer global ChatSocket global ChatConnection DoSendMessage "Opening Connection to Chat Server $ChatServer socket $ChatSocket ..." status set ChatConnection {} catch { set ChatConnection [connect $ChatServer $ChatSocket] } if {$ChatConnection == {}} then { DoSendMessage "Sorry, I could not open a connection to chat server $ChatServer socket $ChatSocket." status set Chatting 0 } else { filehandler $ChatConnection r "ReceiveChat" set Chatting 1 } global NickName global UserName global HostName global ServerName global RealName global ChannelName catch { puts $ChatConnection "USER $UserName $HostName $ServerName $RealName\r\n" nonewline puts $ChatConnection "NICK $NickName\r\n" nonewline puts $ChatConnection "JOIN $ChannelName\r\n" nonewline flush $ChatConnection } } proc ReceiveChat {mode f} { # DoSendMessage "ReceiveChat: MODE $mode F $f" set msg "" gets $f msg if {[string first {:} $msg]} { set msg ": $msg" } set from [lindex $msg 0] set cmd [string tolower [lindex $msg 1]] set handled 0 if {($cmd == "privmsg") || ($cmd == "notice")} then { set handled 1 set chan [lindex $msg 2] set i [expr "[string length $from] + 1 + [string length $cmd] + 1 + [string length $chan] + 2"] set j [expr "[string length $msg] - 2"] set line [string range $msg $i $j] set chan [string range $chan 1 [string length $chan]] set from [string range $from 1 [expr "[string length $from] - 1"]] set from [split $from {!}] set from [lindex $from 0] DoSendMessage "$from> $line" } if {$handled == 0} { set msg [string range $msg \ [expr "[string length $from] + 1"] \ [expr "[string length $msg] - 2"]] DoSendMessage $msg } } proc SendChatMessage {msg win} { global ChatConnection ChannelName NickName if {"$msg" == ""} { return } if {[string range $msg 0 0] == "/"} { set cmd [string range $msg 1 [string length $msg]] DoSendMessage "$NickName> \[$cmd\]" set cmd "$cmd\r\n" } else { set cmd "PRIVMSG $ChannelName :$msg\r\n" DoSendMessage "$NickName> $msg" } set result 1 catch { puts $ChatConnection $cmd nonewline flush $ChatConnection set result 0 } if {$result} { DoSendMessage "IRC Broke the connection" CloseChat } } proc CloseChat {} { global Chatting global ChatServer global ChatSocket global ChatConnection DoSendMessage "Closing Connection to Chat Server." status catch { puts $ChatConnection "QUIT\r\n" nonewline flush $ChatConnection $ChatConnection close } set ChatConnection {} set Chatting 0 } proc DoEnterMessage {win var} { global Chatting global $var set msg [eval ident "\$\{$var\}"] if {$Chatting} then { SendChatMessage $msg $win } else { DoSendMessage $msg } $win delete 0 end } proc DoEvalMessage {win var} { global $var set command [eval ident "\$\{$var\}"] $win delete 0 end DoSendMessage "Evaluating TCL: $command" catch {uplevel #0 $command} result DoSendMessage "Result: $result" } proc DoSendMessage {msg {tag message}} { global HeadWindows foreach win $HeadWindows { appendWithTag [WindowLink $win.text] $tag "$msg" } } proc UISetMessage {msg {tag status}} { global DoMessages EditorWindows HeadWindows if {$DoMessages == 0} { return } foreach win $EditorWindows { [WindowLink $win.message] configure -text "$msg" } foreach win $HeadWindows { appendWithTag [WindowLink $win.text] $tag "$msg" } } proc appendWithTag {w tag text} { global MaxLines global ShrinkLines set start [$w index end] $w configure -state normal if {$start > $MaxLines} then { $w delete 0.0 $ShrinkLines.0 set start [$w index end] } $w insert end "${text}\n" $w tag add $tag $start {end - 1 char} $w configure -state disabled $w yview -pickplace {end - 1 char} } ######################################################################## # Budget Window Handlers proc ShowBudgetOf {head} { set win [WindowLink $head.budget] if {$win == {}} { set win [MakeWindow.budget $head [winfo screen $head]] } wm deiconify $win wm raise $win update idletasks sim UpdateBudget } proc ShowBudgets {} { global HeadWindows foreach win $HeadWindows { ShowBudgetOf $win } } proc WithdrawBudgets {} { global BudgetWindows BudgetsVisible foreach win $BudgetWindows { wm withdraw $win } StopBudgetTimer set BudgetsVisible 0 } proc BudgetContinue {{win ""}} { global OldBudget BudgetRoadFund BudgetFireFund BudgetPoliceFund BudgetTaxRate set OldBudget 0 if {([sim RoadFund] != $BudgetRoadFund) || ([sim FireFund] != $BudgetFireFund) || ([sim PoliceFund] != $BudgetPoliceFund) || ([sim TaxRate] != $BudgetTaxRate)} { UISetMessage "The budget was changed." } else { UISetMessage "The budget wasn't changed." } WithdrawBudgets sim Resume MakeRunningSound } proc BudgetReset {{win ""}} { global OldBudget BudgetRoadFund BudgetFireFund BudgetPoliceFund BudgetTaxRate if {([sim RoadFund] != $BudgetRoadFund) || ([sim FireFund] != $BudgetFireFund) || ([sim PoliceFund] != $BudgetPoliceFund) || ([sim TaxRate] != $BudgetTaxRate)} { UISetMessage "The budget was reset." if {[sim Players] > 1} { UIMakeSound edit Sorry } } else { UISetMessage "The budget was reset." } sim RoadFund $BudgetRoadFund sim FireFund $BudgetFireFund sim PoliceFund $BudgetPoliceFund sim TaxRate $BudgetTaxRate set OldBudget 0 ChangeBudget } proc BudgetCancel {{win ""}} { BudgetReset WithdrawBudgets sim Resume MakeRunningSound } proc SetTaxRate {rate} { sim TaxRate $rate } proc BudgetSetTaxRate {rate} { SetTaxRate $rate ChangeBudget } proc BudgetSetRoadFund {percent} { sim RoadFund $percent ChangeBudget } proc BudgetSetFireFund {percent} { sim FireFund $percent ChangeBudget } proc BudgetSetPoliceFund {percent} { sim PoliceFund $percent ChangeBudget } proc BudgetVisible {w v} { global BudgetsVisible global [set var $w.visible] set $var $v if ($v) { set BudgetsVisible [expr "$BudgetsVisible + 1"] } else { set BudgetsVisible [expr "$BudgetsVisible - 1"] } } proc UIShowBudgetAndWait {} { global OldBudget BudgetRoadFund BudgetFireFund BudgetPoliceFund BudgetTaxRate if {$OldBudget == 0} { set BudgetRoadFund [sim RoadFund] set BudgetFireFund [sim FireFund] set BudgetPoliceFund [sim PoliceFund] set BudgetTaxRate [sim TaxRate] set OldBudget 1 } ShowBudgets UISetMessage "Pausing to set the budget ..." sim Pause MakeRunningSound StartBudgetTimer InitVotesForBudget } proc ToggleBudgetTimer {} { global BudgetTimerActive if {$BudgetTimerActive} { StopBudgetTimer } else { StartBudgetTimer } } proc StopBudgetTimer {} { global BudgetTimerActive set BudgetTimerActive 0 UpdateBudgetTimer } proc StartBudgetTimer {} { global BudgetTimerActive BudgetTimer BudgetTimeout set me [Unique] set BudgetTimerActive $me set BudgetTimer $BudgetTimeout UpdateBudgetTimer after 1000 TickBudgetTimer $me } proc RestartBudgetTimer {} { global BudgetTimerActive if {$BudgetTimerActive} { StopBudgetTimer StartBudgetTimer } } proc UpdateBudgetTimer {} { global BudgetWindows BudgetTimerActive BudgetTimer if {$BudgetTimerActive} { set text [format "Auto Cancel in %d seconds ..." $BudgetTimer] } else { set text [format "Auto Cancel"] } foreach win $BudgetWindows { set t [WindowLink $win.timer] $t config -text "$text" } } proc TickBudgetTimer {me} { global BudgetTimerActive BudgetTimer BudgetTimeout if {$BudgetTimerActive == $me} { incr BudgetTimer -1 if {$BudgetTimer < 0} { StopBudgetTimer UpdateBudgetTimer FireBudgetTimer } else { UpdateBudgetTimer after 1000 TickBudgetTimer $me } } } proc FireBudgetTimer {} { BudgetCancel } proc funds {n} { sim Funds $n } proc UISetBudget {cashflow previous current collected taxrate} { global BudgetWindows BudgetsVisible if {$BudgetsVisible} { foreach win $BudgetWindows { global [set var $win.visible] set visible [eval ident "\$\{$var\}"] if {$visible} { set w [WindowLink $win.cashflow] set old [lindex [$w configure -text] 4] if {$old != $cashflow} { $w configure -text $cashflow } set w [WindowLink $win.previous] set old [lindex [$w configure -text] 4] if {$old != $previous} { $w configure -text $previous } set w [WindowLink $win.current] set old [lindex [$w configure -text] 4] if {$old != $current} { $w configure -text $current } set w [WindowLink $win.collected] set old [lindex [$w configure -text] 4] if {$old != $collected} { $w configure -text $collected } set w [WindowLink $win.taxrate] set old [$w get] if {$old != $taxrate} { $w set $taxrate } set w [WindowLink $win.taxlabel] set old [lindex [$w configure -text] 4] set new "$taxrate%" if {$old != $new} { $w configure -text $new } } } } global HeadWindows foreach win $HeadWindows { set w [WindowLink $win.taxrate] set old [$w get] if {$old != $taxrate} { $w set $taxrate } set w [WindowLink $win.taxlabel] set old [lindex [$w configure -text] 4] set new "Tax Rate: $taxrate%" if {$old != $new} { $w configure -text $new } } } proc UISetBudgetValues {roadgot roadwant roadpercent policegot policewant policepercent firegot firewant firepercent} { global BudgetWindows BudgetsVisible if {$BudgetsVisible == 0} { return; } foreach win $BudgetWindows { global [set var $win.visible] set visible [eval ident "\$\{$var\}"] if {$visible} { set w [WindowLink $win.fire].request set old [lindex [$w configure -text] 4] set new "$firepercent% of $firewant = $firegot" if {$old != $new} { $w configure -text $new } set w [WindowLink $win.fire].fund set old [$w get] if {$old != $firepercent} { $w set $firepercent } set w [WindowLink $win.police].request set old [lindex [$w configure -text] 4] set new "$policepercent% of $policewant = $policegot" if {$old != $new} { $w configure -text $new } set w [WindowLink $win.police].fund set old [$w get] if {$old != $policepercent} { $w set $policepercent } set w [WindowLink $win.road].request set old [lindex [$w configure -text] 4] set new "$roadpercent% of $roadwant = $roadgot" if {$old != $new} { $w configure -text $new } set w [WindowLink $win.road].fund set old [$w get] if {$old != $roadpercent} { $w set $roadpercent } } } } proc ChangeBudget {} { global VotesForBudget if {"$VotesForBudget" != ""} { InitVotesForBudget } RestartBudgetTimer } proc InitVotesForBudget {} { global VotesForBudget BudgetWindows set VotesForBudget {} foreach win $BudgetWindows { [WindowLink $win.vote] config -relief raised } UpdateVotesForBudget } proc UpdateVotesForBudget {} { global BudgetWindows UpdateVotesFor Budget $BudgetWindows } ######################################################################## # Evaluation Window Handlers proc ShowEvaluationOf {head} { set win [WindowLink $head.evaluation] if {$win == {}} { set win [MakeWindow.evaluation $head [winfo screen $head]] } #wm raise $win #wm deiconify $win set parent [WindowLink $win.parent] #pack append [WindowLink $head.col2]\ # $parent {top frame nw fill} pack append $parent\ $win {top frame nw fillx} update idletasks sim UpdateEvaluation } proc WithdrawEvaluations {} { global EvaluationWindows EvaluationsVisible foreach win $EvaluationWindows { #wm withdraw $win #set parent [WindowLink $win.parent] #pack unpack $parent pack unpack $win } set EvaluationsVisible 0 } proc EvaluationVisible {w v} { global EvaluationsVisible global [set var $w.visible] set $var $v if ($v) { set EvaluationsVisible [expr "$EvaluationsVisible + 1"] } else { set EvaluationsVisible [expr "$EvaluationsVisible - 1"] } } proc UISetEvaluation {changed score ps0 ps1 ps2 ps3 pv0 pv1 pv2 pv3 pop delta assessed cityclass citylevel goodyes goodno title} { global EvaluationWindows EvaluationsVisible CurrentDate set class [string tolower $cityclass] UISetMessage "$CurrentDate: Score $score, $class population $pop." if {$EvaluationsVisible} { foreach win $EvaluationWindows { global [set var $win.visible] set visible [eval ident "\$\{$var\}"] if {$visible} { # TODO: set evaluation window and icon title #wm title $win "$title" #wm iconname $win "$title" set w [WindowLink $win.goodjob] set old [lindex [$w configure -text] 4] set new "$goodyes\n$goodno" if {$old != $new} { $w configure -text $new } set w [WindowLink $win.problemnames] set old [lindex [$w configure -text] 4] set new "$ps0\n$ps1\n$ps2\n$ps3" if {$old != $new} { $w configure -text $new } set w [WindowLink $win.problempercents] set old [lindex [$w configure -text] 4] set new "$pv0\n$pv1\n$pv2\n$pv3" if {$old != $new} { $w configure -text $new } set w [WindowLink $win.stats] set old [lindex [$w configure -text] 4] set new "$pop\n$delta\n\n$assessed\n$cityclass\n$citylevel" if {$old != $new} { $w configure -text $new } set w [WindowLink $win.score] set old [lindex [$w configure -text] 4] set new "$score\n$changed" if {$old != $new} { $w configure -text $new } } } } } ######################################################################## # File Window Handlers proc ShowFileOf {head} { set win [WindowLink $head.file] if {$win == {}} { set win [MakeWindow.file $head [winfo screen $head]] } wm deiconify $win wm raise $win return $win } proc ShowFiles {} { global HeadWindows foreach win $HeadWindows { ShowFileOf $win } } proc WithdrawFiles {} { global FileWindows foreach win $FileWindows { wm withdraw $win } } proc DoFileDialog {win Message Path Pattern FileName ActionOk ActionCancel} { ShowFileDialog $win "$Path" "$Pattern" $win.message1 configure -text "$Message" $win.path.path delete 0 end $win.path.path insert 0 $Path $win.file.file delete 0 end $win.file.file insert 0 "$FileName" $win.frame1.ok config -command " $ActionOk \[$win.file.file get\] \[$win.path.path get\] wm withdraw $win" $win.frame1.rescan config -command " ShowFileDialog $win \[$win.path.path get\] $Pattern" $win.frame1.cancel config -command " $ActionCancel wm withdraw $win" bind $win.files.files "" "\ FileSelectDouble $win %W %y $Pattern \" $ActionOk \[$win.file.file get\] \[$win.path.path get\]\"" bind $win.path.path " ShowFileDialog $win \[$win.path.path get\] $Pattern $win.file.file cursor 0 focus $win.file.file" bind $win.file.file "\ $ActionOk \[$win.file.file get\] \[$win.path.path get] wm withdraw $win" } proc BindSelectOne {win Y} { set Nearest [$win nearest $Y] if {$Nearest >= 0} { $win select from $Nearest $win select to $Nearest } } proc FileSelect {win widget Y} { BindSelectOne $widget $Y set Nearest [$widget nearest $Y] if {$Nearest >= 0} { set Path [$win.path.path get] set TmpEntry [$widget get $Nearest] if {[string compare "/" [string index $TmpEntry \ [expr [string length $TmpEntry]-1]]] == 0 || \ [string compare "@" [string index $TmpEntry \ [expr [string length $TmpEntry]-1]]] == 0} { # handle directories, and symbolic links to directories set FileName [string range $TmpEntry 0 \ [expr [string length $TmpEntry]-2]] # whoops / or @ is part of the name if {[MiscIsDir $Path/$FileName] != 1} { set FileName $TmpEntry } } { if {[string compare "*" [string index $TmpEntry \ [expr [string length $TmpEntry]-1]]] == 0} { # handle executable filenames set FileName [string range $TmpEntry 0 \ [expr [string length $TmpEntry]-2]] # whoops * is part of the name if {[file executable $Path/$FileName] != 1} { set FileName $TmpEntry } } { # a ordinary filename set FileName $TmpEntry } } # enter the selected filename into the filename field if {[MiscIsDir $Path/$FileName] != 1} { $win.file.file delete 0 end $win.file.file insert 0 $FileName } } } proc FileSelectDouble {win widget Y Pattern Action} { BindSelectOne $widget $Y set Nearest [$widget nearest $Y] if {$Nearest >= 0} { set Path [$win.path.path get] set TmpEntry [$widget get $Nearest] if {[string compare $TmpEntry "../"] == 0} { # go up one directory set TmpEntry \ [string trimright [string trimright [string trim $Path] /] @] if {[string length $TmpEntry] <= 0} { return } set Path [file dirname $TmpEntry] $win.path.path delete 0 end $win.path.path insert 0 $Path ShowFileDialog $win $Path $Pattern } { if {[string compare "/" [string index $TmpEntry \ [expr [string length $TmpEntry]-1]]] == 0 || \ [string compare "@" [string index $TmpEntry \ [expr [string length $TmpEntry]-1]]] == 0} { # handle directorys, and symbolic links to directorys set FileName [string range $TmpEntry 0 \ [expr [string length $TmpEntry]-2]] # whoops / or @ is part of the name if {[MiscIsDir $Path/$FileName] != 1} { set FileName $TmpEntry } } { if {[string compare "*" [string index $TmpEntry \ [expr [string length $TmpEntry]-1]]] == 0} { # handle executable filenames set FileName [string range $TmpEntry 0 \ [expr [string length $TmpEntry]-2]] # whoops * is part of the name if {[file executable $Path/$FileName] != 1} { set FileName $TmpEntry } } { # a ordinary filename set FileName $TmpEntry } } # change directory if {[MiscIsDir $Path/$FileName] == 1} { if {[string compare "/" [string index $Path \ [expr [string length $Path]-1]]] == 0} { append Path $FileName } { append Path / $FileName } $win.path.path delete 0 end $win.path.path insert 0 $Path ShowFileDialog $win $Path $Pattern } { # enter the selected filename into the filename field $win.file.file delete 0 end $win.file.file insert 0 "$FileName" if {[string length $Action] > 0} { eval $Action } wm withdraw $win } } } } proc NameComplete {win Type} { set NewFile "" set Matched "" if {[string compare $Type path] == 0} { set DirName [file dirname [$win.path.path get]] set FileName [file tail [$win.path.path get]] } { set DirName [file dirname [$win.path.path get]/] set FileName [file tail [$win.file.file get]] } set FoundCounter 0 if {[MiscIsDir $DirName] == 1} { catch "exec ls $DirName/" Result set Counter 0 set ListLength [llength $Result] # go through list while {$Counter < $ListLength} { if {[string length $FileName] == 0} { if {$FoundCounter == 0} { set NewFile [lindex $Result $Counter] } { set Counter1 0 set TmpFile1 $NewFile set TmpFile2 [lindex $Result $Counter] set Length1 [string length $TmpFile1] set Length2 [string length $TmpFile2] set NewFile "" if {$Length1 > $Length2} { set Length1 $Length2 } while {$Counter1 < $Length1} { if {[string compare [string index $TmpFile1 $Counter1] \ [string index $TmpFile2 $Counter1]] == 0} { append NewFile [string index $TmpFile1 $Counter1] } { break } incr Counter1 1 } } incr FoundCounter 1 } { if {[regexp "^$FileName" [lindex $Result $Counter] \ Matched] == 1} { if {$FoundCounter == 0} { set NewFile [lindex $Result $Counter] } { set Counter1 0 set TmpFile1 $NewFile set TmpFile2 [lindex $Result $Counter] set Length1 [string length $TmpFile1] set Length2 [string length $TmpFile2] set NewFile "" if {$Length1 > $Length2} { set Length1 $Length2 } while {$Counter1 < $Length1} { if {[string compare [string index $TmpFile1 $Counter1] \ [string index $TmpFile2 $Counter1]] == 0} { append NewFile [string index $TmpFile1 $Counter1] } { break } incr Counter1 1 } } incr FoundCounter 1 } } incr Counter 1 } } if {$FoundCounter == 1} { if {[MiscIsDir $DirName/$NewFile] == 1} { if {[string compare $DirName "/"] == 0} { $win.path.path delete 0 end $win.path.path insert 0 "/[string trim [string trim $NewFile /] @]/" } { $win.path.path delete 0 end $win.path.path insert 0 "[string trimright $DirName /]/[string trim [string trim $NewFile /] @]/" } } { $win.path.path delete 0 end $win.path.path insert 0 \ "[string trim [string trimright $DirName /] @]/" $win.file.file delete 0 end $win.file.file insert 0 "$NewFile" } } { if {[MiscIsDir $DirName/$NewFile] == 1 || [string compare $Type path] == 0} { $win.path.path delete 0 end $win.path.path insert 0 \ "[string trimright $DirName /]/[string trim [string trim $NewFile /] @]" } { $win.path.path delete 0 end $win.path.path insert 0 "$DirName" if {[string length $NewFile] > 0} { $win.file.file delete 0 end $win.file.file insert 0 "$NewFile" } } } } proc ShowFileDialog {win Path Pattern} { busy $win { set Path [lindex [split $Path] 0] if {[$win.files.files size] > 0} { $win.files.files delete 0 end } # read directory if {[catch "exec ls -F $Path" Result]} { set ElementList {} } if {[string match $Result "* not found"]} { set ElementList {} } set ElementList [lsort $Result] # insert .. if {[string compare $Path "/"]} { $win.files.files insert end "../" } # walk through list foreach Counter $ElementList { # insert filename if {[string match $Pattern $Counter] == 1} { if {[string compare $Counter "../"] && [string compare $Counter "./"]} { $win.files.files insert end $Counter } } else { set fn $Path/[string trim [string trim [string trim $Counter /] @] *] if {[MiscIsDir $fn]} { $win.files.files insert end $Counter } } } } } proc MiscIsDir {PathName} { if {[file isdirectory $PathName] == 1} { return 1 } { catch "file type $PathName" Type if {[string compare $Type link] == 0} { set LinkName [file readlink $PathName] catch "file type $LinkName" Type while {[string compare $Type link] == 0} { set LinkName [file readlink $LinkName] } return [file isdirectory $LinkName] } } return 0 } proc busy {win cmds} { set busy {} set list [winfo children $win] set busy $list while {$list != ""} { set next {} foreach w $list { set class [winfo class $w] set cursor [lindex [$w config -cursor] 4] if {[winfo toplevel $w] == $w} { lappend busy [list $w $cursor] } set next [concat $next [winfo children $w]] } set list $next } foreach w $busy { catch {[lindex $w 0] config -cursor watch} } update idletasks set error [catch {uplevel eval [list $cmds]} result] foreach w $busy { catch {[lindex $w 0] config -cursor [lindex $w 1]} } if $error { error $result } else { return $result } } ######################################################################## # Editor Window Handlers proc ShowEditorOf {head} { global EditorWindows set found 0 foreach win $EditorWindows { if {[WindowLink $win.head] == $head} { set parent [WindowLink $win.parent] #pack append [WindowLink $head.col2]\ # $parent {top frame nw expand fill} pack append $parent\ $win {top frame nw expand fill} set found 1 } } if {$found == 0} { NewEditorOf $head } else { update idletasks sim UpdateEditors sim UpdateMaps } } proc NewEditorOf {head} { set win [MakeWindow.editor $head [winfo screen $head]] #wm deiconify $win set parent [WindowLink $win.parent] pack append $parent\ $win {top frame nw expand fill} update idletasks sim UpdateEditors sim UpdateMaps } proc ShowEditors {} { global HeadWindows foreach win $HeadWindows { ShowEditorOf $win } } proc WithdrawEditors {} { global EditorWindows foreach win $EditorWindows { #set parent [WindowLink $win.parent] #pack unpack $parent pack unpack $win } } proc InitEditors {} { global EditorWindows foreach win $EditorWindows { InitEditor $win } } proc InitEditor {win} { set e [WindowLink $win.view] UISetToolState $win 7 $e ToolState 7 set size [$e size] $e Pan 960 800 $e AutoGoing 0 global $e.TrackState set $e.TrackState {} } proc SetEditorAutoGoto {win val} { global AutoGoto.$win set AutoGoto.$win $val set e [WindowLink $win.view] $e AutoGoto $val } proc SetEditorControls {win val} { global Controls.$win set Controls.$win $val if {$val} { pack append $win $win.leftframe {left frame center filly} } else { pack unpack $win.leftframe } } proc SetEditorOverlay {win val} { global Overlay.$win set Overlay.$win $val set e [WindowLink $win.view] $e ShowOverlay $val } proc SetEditorDynamicFilter {win val} { global DynamicFilter.$win set DynamicFilter.$win $val set e [WindowLink $win.view] $e DynamicFilter $val if {$val == 1} then { ShowFrobOf [WindowLink $win.head] } } proc SetEditorSkip {win val} { set e [WindowLink $win.view] $e Skip $val } proc EditorToolDown {mod w x y} { global [set var $w.TrackState] $w ToolMode 1 case [$w ToolState] in \ 7 { # bulldozer UIMakeSoundOn $w edit Rumble "-repeat 4" } \ 10 { # chalk StartChalk $w } case $mod in \ constrain { set $var [list constrain_start $x $y] $w ToolConstrain $x $y } \ default { set $var none } EditorTool ToolDown $w $x $y sim NeedRest 5 } proc EditorToolDrag {w x y} { EditorTool ToolDrag $w $x $y sim NeedRest 5 } proc EditorToolUp {w x y} { global [set var $w.TrackState] $w ToolMode 0 case [$w ToolState] in \ 7 { # bulldozer UIStopSoundOn $w edit 1 } \ 10 { # chalk StopChalk $w } EditorTool ToolUp $w $x $y set $var {} $w ToolConstrain -1 -1 sim UpdateMaps sim UpdateEditors sim NeedRest 5 } proc EditorTool {action w x y} { global [set var $w.TrackState] set state [eval ident "\$\{$var\}"] case [lindex $state 0] in \ constrain_start { set x0 [lindex $state 1] set y0 [lindex $state 2] set dx [expr "$x - $x0"] set dy [expr "$y - $y0"] if [expr "($dx > 16) || ($dx < -16)"] then { $w ToolConstrain -1 $y0 set $var none } else { if [expr "($dy > 16) || ($dy < -16)"] then { $w ToolConstrain $x0 -1 set $var none } } } $w $action $x $y } proc StartChalk {w} { sim CollapseMotion 0 } proc StopChalk {w} { sim CollapseMotion 1 } proc EditorPanDown {mod w x y} { global [set var $w.TrackState] $w ToolMode -1 case $mod in \ constrain { set $var [list constrain_start $x $y] $w ToolConstrain $x $y } \ default { set $var none } EditorTool PanStart $w $x $y } proc EditorPanDrag {w x y} { EditorTool PanTo $w $x $y } proc EditorPanUp {w x y} { $w AutoGoing 0 $w ToolMode 0 EditorTool PanTo $w $x $y $w ToolConstrain -1 -1 sim UpdateMaps sim UpdateEditors } proc EditorKeyDown {w k} { $w KeyDown $k } proc EditorKeyUp {w k} { $w KeyUp $k } proc BindEditorButtons {win} { set w [WindowLink $win.top] bind $win <1> "CancelPie $win ; EditorToolDown none %W %x %y" bind $win {EditorToolDrag %W %x %y} bind $win {EditorToolUp %W %x %y} bind $win "CancelPie $win ; EditorToolDown constrain %W %x %y" bind $win {EditorToolDrag %W %x %y} bind $win {EditorToolUp %W %x %y} bind $win <2> "CancelPie $win ; EditorPanDown none %W %x %y" bind $win {EditorPanDrag %W %x %y} bind $win {EditorPanUp %W %x %y} bind $win "CancelPie $win ; EditorPanDown constrain %W %x %y" bind $win {EditorPanDrag %W %x %y} bind $win {EditorPanUp %W %x %y} InitPie $win $w.toolpie } proc UISetFunds {funds} { global HeadWindows foreach win $HeadWindows { [WindowLink $win.funds] configure -text "$funds" } } proc UISetDate {date month year} { global HeadWindows global CurrentDate set CurrentDate "$date" foreach win $HeadWindows { [WindowLink $win.date] Set $month $year } } proc SetPriority {index} { case $index { \ {0} { sim Delay 2000000 sim Skips 0 } \ {1} { sim Delay 500000 sim Skips 0 } \ {2} { sim Delay 100000 sim Skips 0 } \ {3} { sim Delay 5000 sim Skips 0 } \ {4} { sim Delay 2 sim Skips 10 } \ {5} { sim Delay 1 sim Skips 100 } \ {6} { sim Delay 0 sim Skips 1000 } } } proc UISetDemand {r c i} { global HeadWindows DemandRes DemandCom DemandInd set DemandRes $r set DemandCom $c set DemandInd $i if {$r <= 0} then {set ry0 32} else {set ry0 24} set ry1 [expr "$ry0 - $r"] if {$c <= 0} then {set cy0 32} else {set cy0 24} set cy1 [expr "$cy0 - $c"] if {$i <= 0} then {set iy0 32} else {set iy0 24} set iy1 [expr "$iy0 - $i"] foreach win $HeadWindows { set can [WindowLink $win.demand] # $can coords r 8 $ry0 14 $ry1 # $can coords c 17 $cy0 23 $cy1 # $can coords i 26 $iy0 32 $iy1 $can coords r 49 $ry0 55 $ry1 $can coords c 58 $cy0 64 $cy1 $can coords i 67 $iy0 73 $iy1 } } proc UISetOptions {autobudget autogoto autobulldoze disasters sound animation messages notices} { global AutoBudget AutoGoto AutoBulldoze Disasters Sound set AutoBudget $autobudget set AutoGoto $autogoto set AutoBulldoze $autobulldoze set Disasters $disasters set Sound $sound set DoAnimation $animation set DoMessages $messages set DoNotices $notices } proc UIDidToolRes {win x y} { UIMakeSoundOn $win edit O "-speed 140" } proc UIDidToolCom {win x y} { UIMakeSoundOn $win edit A "-speed 140" } proc UIDidToolInd {win x y} { UIMakeSoundOn $win edit E "-speed 140" } proc UIDidToolFire {win x y} { UIMakeSoundOn $win edit O "-speed 130" } proc UIDidToolQry {win x y} { UIMakeSoundOn $win edit E "-speed 200" } proc UIDidToolPol {win x y} { UIMakeSoundOn $win edit E "-speed 130" } proc UIDidToolWire {win x y} { UIMakeSoundOn $win edit O "-speed 120" } proc UIDidToolDozr {win x y} { UIMakeSoundOn $win edit Rumble } proc UIDidToolRail {win x y} { UIMakeSoundOn $win edit O "-speed 100" } proc UIDidToolRoad {win x y} { UIMakeSoundOn $win edit E "-speed 100" } proc UIDidToolChlk {win x y} { } proc UIDidToolEraser {win x y} { } proc UIDidToolStad {win x y} { UIMakeSoundOn $win edit O "-speed 90" } proc UIDidToolPark {win x y} { UIMakeSoundOn $win edit A "-speed 130" } proc UIDidToolSeap {win x y} { UIMakeSoundOn $win edit E "-speed 90" } proc UIDidToolCoal {win x y} { UIMakeSoundOn $win edit O "-speed 75" } proc UIDidToolNuc {win x y} { UIMakeSoundOn $win edit E "-speed 75" } proc UIDidToolAirp {win x y} { UIMakeSoundOn $win edit A "-speed 50" } proc UISetToolState {w state} { global EditorPallets EditorPalletImages ToolInfo set win [WindowLink $w.top] #echo "UISETTOOLSTATE w $w win $win $state" ExclusivePallet $state $win $EditorPallets ic $EditorPalletImages \ raised sunken {NoFunction} {NoFunction} set c1 [WindowLink $w.cost1] if {"$c1" != ""} { set info [lindex $ToolInfo $state] set cost1 [lindex $info 1] set cost2 [lindex $info 2] $c1 configure -text "$cost1" [WindowLink $w.cost2] configure -text "$cost2" } } proc UIShowZoneStatus {zone density value crime pollution growth x y} { global QueryX QueryY set QueryX [expr "8 + 16 * $x"] set QueryY [expr "8 + 16 * $y"] UIShowPicture 9 [list $zone $density $value $crime $pollution $growth] } ######################################################################## # Map Window Handlers proc ShowMapOf {head} { global MapWindows set found 0 foreach win $MapWindows { if {"[WindowLink $win.head]" == "$head"} { global MapPanelWidth MapPanelHeight #place configure $win -x 0 -y 0 -width $MapPanelWidth -height $MapPanelHeight #[WindowLink $win.parent] configure -width $MapPanelWidth -height $MapPanelHeight set parent [WindowLink $win.parent] pack append [WindowLink $head.col1]\ $parent {top frame nw fillx} set found 1 } } if {$found == 0} { NewMapOf $head } else { update idletasks sim UpdateMaps } } proc NewMapOf {head} { set win [MakeWindow.map $head [winfo screen $head]] global MapPanelWidth MapPanelHeight #place configure $win -x 0 -y 0 -width $MapPanelWidth -height $MapPanelHeight #[WindowLink $win.parent] configure -width $MapPanelWidth -height $MapPanelHeight set parent [WindowLink $win.parent] pack append [WindowLink $head.col1]\ $parent {top frame nw fillx} sim UpdateMaps } proc ShowMaps {} { global HeadWindows foreach win $HeadWindows { ShowMapOf $win } } proc WithdrawMaps {} { global MapWindows foreach win $MapWindows { #place forget $win set parent [WindowLink $win.parent] pack unpack $parent } } proc InitMaps {} { global MapWindows foreach win $MapWindows { InitMap $win } } proc InitMap {win} { SetMapState $win 0 } proc EnableMaps {} { global MapWindows foreach win $MapWindows { EnableMap $win } } proc EnableMap {win} { [WindowLink $win.view] ShowEditors 1 [WindowLink $win.zones] config -state normal [WindowLink $win.overlays] config -state normal } proc DisableMaps {} { global MapWindows foreach win $MapWindows { DisableMap $win } } proc DisableMap {win} { [WindowLink $win.view] ShowEditors 0 [WindowLink $win.zones] config -state disabled [WindowLink $win.overlays] config -state disabled } proc SetMapState {win state} { set m [WindowLink $win.view] $m MapState $state if {$state == 14} then { ShowFrobOf [WindowLink $win.head] } } proc MapPanDown {w x y} { $w PanStart $x $y } proc MapPanDrag {w x y} { $w PanTo $x $y } proc MapPanUp {w x y} { $w PanTo $x $y sim UpdateMaps sim UpdateEditors } proc UISetMapState {w state} { global MapTitles #set win [winfo toplevel $w] set win [WindowLink $w.win] set m [WindowLink $win.view] set title [lindex $MapTitles $state] # TODO: set map text field header to title #wm title $win "$title" #wm iconname $win "$title" global [set var MapState.$win] set $var $state case $state { \ {6 8 9 10 11 12 13} { [WindowLink $win.legend] config -bitmap "@images/legendmm.xpm" } \ {7} { [WindowLink $win.legend] config -bitmap "@images/legendpm.xpm" } \ {0 1 2 3 4 5 14} { [WindowLink $win.legend] config -bitmap "@images/legendn.xpm" } } } ######################################################################## # Graph Window Handlers proc ShowGraphOf {head} { set win [WindowLink $head.graph] if {$win == {}} { set win [MakeWindow.graph $head [winfo screen $head]] } #wm deiconify $win #wm raise $win set parent [WindowLink $win.parent] pack append $parent\ $win {top frame nw fillx} update idletasks sim UpdateGraphs } proc WithdrawGraphs {} { global GraphWindows foreach win $GraphWindows { #wm withdraw $win pack unpack $win } } proc InitGraphs {} { global GraphWindows foreach win $GraphWindows { InitGraph $win } } proc InitGraph {win} { UISetGraphState $win 1 1 1 1 1 1 0 } proc UISetGraphState {win t0 t1 t2 t3 t4 t5 range} { set g [WindowLink $win.graphview] GraphPalletMask $win [expr "$t0 + ($t1<<1) + ($t2<<2) + ($t3<<3) + ($t4<<4) + ($t5<<5)"] GraphYearPallet $win $range } ######################################################################## # Scenario Window Handlers proc ShowScenarioOf {head} { set win [WindowLink $head.scenario] if {$win == {}} { set win [MakeWindow.scenario $head [winfo screen $head]] } global ScenarioPanelWidth ScenarioPanelHeight set parent [WindowLink $win.parent] pack append [WindowLink $head.col2]\ $win {top frame nw expand fill} } proc ShowScenarios {} { global HeadWindows foreach win $HeadWindows { ShowScenarioOf $win } } proc WithdrawScenarios {} { global ScenarioWindows foreach win $ScenarioWindows { pack unpack $win } } proc InitScenarios {} { global MapHistory MapHistoryNum if {$MapHistoryNum < 1} { set prev disabled } else { set prev normal } if {$MapHistoryNum == ([llength $MapHistory] - 1)} { set next disabled } else { set next normal } global ScenarioWindows foreach win $ScenarioWindows { [WindowLink $win.previous] config -state $prev [WindowLink $win.next] config -state $next } } proc InitScenario {win} { global MapHistory MapHistoryNum if {$MapHistoryNum < 1} { set prev disabled } else { set prev normal } if {$MapHistoryNum == ([llength $MapHistory] - 1)} { set next disabled } else { set next normal } [WindowLink $win.previous] config -state $prev [WindowLink $win.next] config -state $next UpdateVotesForUseThisMap } proc DeleteScenarioWindow {win} { UIQuit [WindowLink $win.head] } proc DoEnterCityName {win} { } proc InitVotesForUseThisMap {} { global VotesForUseThisMap ScenarioWindows set VotesForUseThisMap {} foreach win $ScenarioWindows { [WindowLink $win.vote] config -relief raised } UpdateVotesForUseThisMap } proc UpdateVotesForUseThisMap {} { global ScenarioWindows UpdateVotesFor UseThisMap $ScenarioWindows } proc UIUseThisMap {} { global CityName GameLevel Scenario WithdrawAll # special handling for scenarios? if {$GameLevel != -1} { sim GameLevel $GameLevel } sim CityName $CityName UINewGame UIPlayGame if {$Scenario != -1} { UIShowPicture $Scenario } } ######################################################################## # Undo/Redo Facility proc InitHistory {} { global MapHistory global MapHistoryNum set MapHistory {} set MapHistoryNum -1 } proc MakeHistory {cmd} { global MapHistory set len [llength $MapHistory] if {($len == 0) || ($cmd != [lindex $MapHistory [expr $len-1]])} { lappend MapHistory $cmd } else { incr len -1 } GotoHistory $len } proc GotoHistory {i} { global MapHistory global MapHistoryNum InitVotesForUseThisMap if {$i != $MapHistoryNum} { set MapHistoryNum $i set cmd [lindex $MapHistory $i] eval $cmd } if {$MapHistoryNum == 0} { set prev disabled } else { set prev normal } if {$MapHistoryNum == ([llength $MapHistory] - 1)} { set next disabled } else { set next normal } global ScenarioWindows foreach win $ScenarioWindows { [WindowLink $win.previous] config -state $prev [WindowLink $win.next] config -state $next } } proc NextHistory {} { global MapHistory global MapHistoryNum set len [llength $MapHistory] set i [expr "$MapHistoryNum + 1"] if {$i < $len} { GotoHistory $i } } proc PrevHistory {} { global MapHistory global MapHistoryNum set i [expr "$MapHistoryNum - 1"] if {$i >= 0} { GotoHistory $i } } ######################################################################## # Ask Window Handlers proc ShowAskOf {head} { set win [WindowLink $head.ask] if {$win == {}} { set win [MakeWindow.ask $head [winfo screen $head]] } wm deiconify $win wm raise $win return $win } proc ShowAsks {} { global HeadWindows foreach win $HeadWindows { ShowAskOf $win } } proc WithdrawAsks {} { global AskWindows foreach win $AskWindows { wm withdraw $win } } proc WithdrawAskOf {win} { set ask [WindowLink $win.ask] if {"$ask" != ""} { wm withdraw $ask } } proc AskQuestion {color title text left middle right} { global HeadWindows foreach win $HeadWindows { AskQuestionOn $win $color $title $text $left $middle $right } } proc AskQuestionOn {head color title text left middle right} { ShowAskOf $head set win [WindowLink $head.ask] set t [WindowLink $win.title] $t configure -text $title $t configure -background $color set t [WindowLink $win.text] $t configure -state normal $t delete 0.0 end $t insert end "${text}\n" $t configure -state disabled set bf [WindowLink $win.frame] set l [WindowLink $win.left] set m [WindowLink $win.middle] set r [WindowLink $win.vote] set rf [WindowLink $win.voteframe] if {$left != ""} { $l config \ -text [lindex $left 0] \ -command [format [lindex $left 2] $head] SetHelp $l [lindex $left 1] pack append $bf $l {left frame center} } else { pack unpack $l } if {$middle != ""} { $m config \ -text [lindex $middle 0] \ -command [format [lindex $middle 2] $head] SetHelp $m [lindex $middle 1] pack append $bf $m {left frame center expand} } else { pack unpack $m } if {$right != ""} { set notify [format [lindex $right 2] $head] set preview [format [lindex $right 3] $head] set cmd [list DoVote $win Ask $notify $preview] $r config \ -text [lindex $right 0] \ -command $cmd SetHelp $r [lindex $right 1] pack append $bf $rf {right frame center} } else { pack unpack $rf } InitVotesForAsk } proc BindVotingButton {win but name} { set w [WindowLink $win.top] bind $but "VoteButtonEnter $win $but" bind $but "VoteButtonLeave $win $but" bind $but <1> "VoteButtonDown $win $but $name" bind $but "VoteButtonUp $win $but $name" bind $but <2> "VoteButtonDown $win $but $name" bind $but "VoteButtonUp $win $but $name" bind $but <3> "VoteButtonDown $win $but $name" bind $but "VoteButtonUp $win $but $name" } proc VoteButtonEnter {win but} { global tk_priv set screen [winfo screen $but] if {[lindex [$but config -state] 4] != "disabled"} { $but config -state active set tk_priv(window@$screen) $but } else { set tk_priv(window@$screen) "" } } proc VoteButtonLeave {win but} { global tk_priv if {[lindex [$but config -state] 4] != "disabled"} { $but config -state normal } set screen [winfo screen $but] set tk_priv(window@$screen) "" } proc VoteButtonDown {win but name} { global tk_priv set screen [winfo screen $but] set rel [lindex [$but config -relief] 4] set tk_priv(relief@$screen) $rel if {[lindex [$but config -state] 4] != "disabled"} { set head [WindowLink $win.head] if {[IsVotingFor $head $name]} { $but config -relief raised } else { $but config -relief sunken } } } proc VoteButtonUp {win but name} { global tk_priv set screen [winfo screen $but] $but config -relief $tk_priv(relief@$screen) if {($but == $tk_priv(window@$screen)) && ([lindex [$but config -state] 4] != "disabled")} { uplevel #0 [list $but invoke] set head [WindowLink $win.head] if {[IsVotingFor $head $name]} { $but config -relief sunken } else { $but config -relief raised } } } proc PressVoteButton {win but name} { global tk_priv uplevel #0 [list $but invoke] set head [WindowLink $win.head] if {[IsVotingFor $head $name]} { $but config -relief sunken } else { $but config -relief raised } } proc IsVotingFor {win name} { global VotesFor$name set votes [eval ident "\$\{VotesFor$name\}"] if {[lsearch $votes $win] == -1} { return 0 } else { return 1 } } proc DoVote {win name notify preview} { global VotesFor$name set votes [eval ident "\$\{VotesFor$name\}"] set win [WindowLink $win.head] set i [lsearch $votes $win] if {$i == -1} { lappend VotesFor$name $win } else { set VotesFor$name [lreplace $votes $i $i] } UpdateVotesFor$name set votes [eval ident "\$\{VotesFor$name\}"] if {[llength $votes] >= [NeededVotes]} { eval "$notify" } else { eval "$preview" } } proc UpdateVotesFor {name wins} { global VotesFor$name set votes [eval llength "\$\{VotesFor$name\}"] set needed [NeededVotes] foreach win $wins { set head [WindowLink $win.head] if {[IsVotingFor $head $name]} { set border [expr "($needed - $votes) * 1"] set pad [expr "6 - $border"] [WindowLink $win.vote] config -padx $pad -pady $pad [WindowLink $win.voteframe] config -borderwidth $border } else { set border [expr "($needed - $votes - 1) * 1"] set pad [expr "6 - $border"] [WindowLink $win.vote] config -padx $pad -pady $pad [WindowLink $win.voteframe] config -borderwidth $border } } } proc InitVotesForAsk {} { global VotesForAsk AskWindows set VotesForAsk {} foreach win $AskWindows { [WindowLink $win.vote] config -relief raised } sim PendingTool -1 UpdateVotesForAsk } proc UpdateVotesForAsk {} { global AskWindows UpdateVotesFor Ask $AskWindows } ######################################################################## # Player Window Handlers proc ShowPlayerOf {head} { set win [WindowLink $head.player] if {$win == {}} { set win [MakeWindow.player $head [winfo screen $head]] } wm deiconify $win wm raise $win return $win } proc ShowPlayers {} { global HeadWindows foreach win $HeadWindows { ShowPlayerOf $win } } proc WithdrawPlayers {} { global PlayerWindows foreach win $PlayerWindows { wm withdraw $win } } proc UpdatePlayers {} { global HeadWindows PlayerWindows set players "" foreach win $HeadWindows { set server [winfo screen $win] # if {[string first : $server] == 0} { # set server "[exec hostname]:0" # } lappend players $server } sim Players [llength $players] foreach win $PlayerWindows { set list [WindowLink $win.players] $list delete 0 end eval "$list insert 0 $players" } UpdateVotesForUseThisMap UpdateVotesForAsk UpdateVotesForBudget } proc UIShowPlayer {win} { ShowPlayerOf $win } proc DoNewPlayer {win} { set field [WindowLink $win.display] set dpy [$field get] if {"$dpy" != ""} { $field delete 0 end sim Flush update idletasks if {[AddPlayer $dpy] != ""} { wm withdraw $win } } } ######################################################################## # Notice Window Handlers proc ShowNoticeOf {head} { set win [WindowLink $head.notice] if {$win == {}} { set win [MakeWindow.notice $head [winfo screen $head]] } global NoticePanelWidth NoticePanelHeight #place configure $win -x 0 -y 0 -width $NoticePanelWidth -height $NoticePanelHeight pack append [WindowLink $head.w2] \ $win {top frame nw expand fill} return $win } proc ShowNotices {} { global HeadWindows foreach win $HeadWindows { ShowNoticeOf $win } } proc WithdrawNotices {} { global NoticeWindows foreach win $NoticeWindows { #place forget $win pack unpack $win } } proc ReShowPictureOn {{head ""}} { global ShowingPicture ShowingParms UIShowPictureOn $head $ShowingPicture $ShowingParms } proc UIShowPicture {id {parms ""}} { UIShowPictureOn "" $id $parms } proc UIShowPictureOn {where id {parms ""}} { global DoNotices Messages ShowingPicture ShowingParms if {$DoNotices == 0} { return } set ShowingPicture $id set ShowingParms $parms set msg $Messages($id) set color [lindex $msg 0] set title [lindex $msg 1] set body [lindex $msg 2] if {$parms != ""} { set cmd "format {$body} $parms" set body [uplevel #0 $cmd] } set props [lindex $msg 3] if {"$where" == ""} { global HeadWindows set where $HeadWindows } foreach head $where { NoticeMessageOn $head "$title" $color "$body" Medium $props } } proc NoticeMessageOn {head title color text font props} { ShowNoticeOf $head set win [WindowLink $head.notice] set t [WindowLink $win.title] $t configure -text $title -background $color set t [WindowLink $win.text] $t configure -state normal -font [Font $head $font] $t delete 0.0 end $t insert end "${text}\n" $t configure -state disabled set left "" catch {set left [keylget props left]} set l [WindowLink $win.left] if {$left != ""} { $l config -bitmap $left place $l -in $t -anchor sw -relx .05 -rely .95 } else { place forget $l } set middle "" catch {set middle [keylget props middle]} set m [WindowLink $win.middle] if {$middle != ""} { $m config -bitmap $middle place $m -in $t -anchor s -relx .5 -rely .95 } else { place forget $m } set right "" catch {set right [keylget props right]} set r [WindowLink $win.right] if {$right != ""} { $r config -bitmap $right place $r -in $t -anchor se -relx .95 -rely .95 } else { place forget $r } set view "" catch {set view [keylget props view]} set vf [WindowLink $win.viewframe] global v set v [WindowLink $win.view] set bg [WindowLink $win.background] if {$view != ""} { uplevel #0 "$view" pack unpack $t pack append $bg $vf {left frame center fill} pack append $bg $t {right frame center fill expand} } else { pack unpack $vf } } proc UIPopUpMessage {msg} { DoSendMessage $msg } proc ComeToMe {view} { set win [winfo toplevel $view] set xy [$view Pan] set x [expr "[lindex $xy 0] >>4"] set y [expr "[lindex $xy 1] >>4"] ComeTo $win $x $y } proc ComeTo {win x y} { global EditorWindows set head [WindowLink $win.head] set myeds {} set myautoeds {} foreach ed $EditorWindows { if {"[WindowLink $ed.head]" == "$head"} { lappend myeds $ed set view [WindowLink $ed.view] if {[$view AutoGoto]} { lappend myautoeds $ed } } } if {[llength $myautoeds]} { UIAutoGotoOn $x $y $myautoeds } else { if {[llength $myeds]} { UIAutoGotoOn $x $y $myeds } } } proc FollowView {view id} { $view Follow $id set skips 999999 if {[sim DoAnimation]} { set head [WindowLink [winfo toplevel $view].head] global EditorWindows foreach win $EditorWindows { if {"[WindowLink $win.head]" == "$head"} { set s [[WindowLink $win.view] Skip] set skips [min $skips $s] } } if {$skips == 999999} { set skips 0 } } $view Skip $skips $view Update } proc PanView {view x y} { FollowView $view "" $view Pan $x $y } ######################################################################## # Help Window Handlers proc ShowHelpOf {head} { set win [WindowLink $head.help] if {$win == {}} { set win [MakeWindow.help $head [winfo screen $head]] } wm deiconify $win wm raise $win return $win } proc ShowHelps {} { global HeadWindows foreach win $HeadWindows { ShowHelpOf $win } } proc WithdrawHelps {} { global HelpWindows foreach win $HelpWindows { wm withdraw $win } } ######################################################################## # Frob Window Handlers proc ShowFrobOf {head} { set win [WindowLink $head.frob] if {$win == {}} { set win [MakeWindow.frob $head [winfo screen $head]] } wm deiconify $win wm raise $win return $win } proc ShowFrobs {} { global HeadWindows foreach win $HeadWindows { ShowFrobOf $win } } proc WithdrawFrobs {} { global FrobWindows foreach win $FrobWindows { wm withdraw $win } } proc UISetDynamic {i min max} { sim DynamicData [expr "$i*2"] $min sim DynamicData [expr "$i*2+1"] $max } ######################################################################## # Help Handler proc LoadHelp {} { global ResourceDir source $ResourceDir/help.tcl } proc HandleHelp {win x y rootx rooty} { global HelpLoaded HelpWidgets Messages if {$HelpLoaded == 0} { LoadHelp set HelpLoaded 1 } set orig $win set head [WindowLink [winfo toplevel $win].head] set id "" while {1} { catch {set id $HelpWidgets($win)} if {$id != ""} { break } set list [split $win .] set len [expr "[llength $list] - 2"] set list [lrange $list 0 $len] if {[llength $list] <= 1} { set id Window break } set win [join $list .] } if [info exists Messages($id)] { UIShowHelpOn $head $id } else { UIShowHelpOn $head Window } } proc UIShowHelpOn {win id {parms ""}} { global Messages ShowingPicture ShowingParms ResourceDir set head [WindowLink $win.head] set msg $Messages($id) set color [lindex $msg 0] set title [lindex $msg 1] set body [lindex $msg 2] if {$parms != ""} { set cmd "format {$body} $parms" set body [uplevel #0 $cmd] } set props [lindex $msg 3] ShowHelpOf $head set win [WindowLink $head.help] set t [WindowLink $win.title] $t configure -text $title -background $color set t [WindowLink $win.text] $t configure -state normal -font [Font $head Large] $t delete 0.0 end $t insert end "${body}\n" FormatHTML $ResourceDir/doc/$id.html $t $t configure -state disabled } proc FormatHTML {filename text} { set f "" catch { set f [open $filename] set line "" set header "" set title "" gets $f header gets $f title while {[gets $f line] >= 0} { if {"$line" == ""} { break } if {([string index $line 0] == "#") || ([string length $line] == 0)} { continue } $text insert end "$line\n" } } if {$f != ""} { close $f } } proc SetHelp {win id} { global HelpWidgets set HelpWidgets($win) $id } proc Help {id title {msg {}} {props {}}} { Message $id #7f7fff $title $msg $props } ######################################################################## # Pie Menu Handlers # Set up the bindings to pop up $pie when the right button is clicked in $win proc InitPie {win pie} { bind $win {} bind $win <3> "PieMenuDown $win $pie $pie Initial %X %Y" bind $win {} bind $win {} } # Set up the bindings to continue tracking $pie # Get this: we keep the tracking machine state in the bindings! proc ActivatePie {win root pie state} { bind $win "PieMenuMotion $win $root $pie $state %X %Y" bind $win <3> "PieMenuDown $win $root $pie $state %X %Y" bind $win "PieMenuMotion $win $root $pie $state %X %Y" bind $win "PieMenuUp $win $root $pie $state %X %Y" } # Cancel and reset a pie menu proc CancelPie {win} { set binding [bind $win <3>] set root [lindex $binding 2] set pie [lindex $binding 3] set state [lindex $binding 4] if {"$state" != "Initial"} { catch {$root ungrab $win} $pie unpost $pie activate none UIMakeSoundOn $win fancy Oop } InitPie $win $root } # Handle pie menu button down proc PieMenuDown {win root pie state x y} { case $state { Initial { ActivatePie $win $root $pie FirstDown update idletasks catch {$root grab $win} $pie activate none $pie post $x $y PreviewPieMenu $win $pie $x $y update idletasks } ClickedUp { TrackPieMenu $pie $x $y ActivatePie $win $root $pie SecondDown } SelectedUp { $pie activate none $pie post $x $y $pie defer PreviewPieMenu $win $pie $x $y ActivatePie $win $root $pie SecondDown } FirstDown { # error CancelPie $win } SecondDown { # error CancelPie $win } } } # Handle pie menu button motion proc PieMenuMotion {win root pie state x y} { case $state { FirstDown { TrackPieMenu $pie $x $y $pie defer } ClickedUp { $pie activate none $pie post $x $y } SecondDown { TrackPieMenu $pie $x $y $pie defer } SelectedUp { $pie activate none $pie post $x $y } Initial { # error CancelPie $win } } } # Handle pie menu button up proc PieMenuUp {win root pie state x y} { case $state { FirstDown { TrackPieMenu $pie $x $y set active [$pie index active] if {$active == "none"} { $pie show catch {$root grab $win} ActivatePie $win $root $pie ClickedUp } else { set label [lindex [$pie entryconfig $active -label] 4] set submenu [lindex [$pie entryconfig $active -piemenu] 4] UIMakeSoundOn $win mode $label if {$submenu == {}} { set reward [$pie pending] catch {$root ungrab $win} $pie unpost $pie activate none if {$reward} { sim Funds [expr "[sim Funds] + 5"] UIMakeSoundOn $win fancy Aaah } eval [lindex [$pie entryconfig $active -command] 4] InitPie $win $root } else { $pie unpost $pie activate none $submenu activate none $submenu post $x $y PreviewPieMenu $win $submenu $x $y catch {$root grab $win} ActivatePie $win $root $submenu SelectedUp } } } SecondDown { TrackPieMenu $pie $x $y set active [$pie index active] if {$active == "none"} { CancelPie $win } else { set label [lindex [$pie entryconfig $active -label] 4] set submenu [lindex [$pie entryconfig $active -piemenu] 4] UIMakeSoundOn $win mode $label if {$submenu == {}} { set reward [$pie pending] catch {$root ungrab $win} $pie unpost $pie activate none if {$reward} { sim Funds [expr "[sim Funds] + 5"] UIMakeSoundOn $win fancy Aaah } eval [lindex [$pie entryconfig $active -command] 4] InitPie $win $root } else { $pie unpost $pie activate none $submenu activate none $submenu post $x $y PreviewPieMenu $win $submenu $x $y catch {$root grab $win} ActivatePie $win $root $submenu SelectedUp } } } Initial { # error CancelPie $win } ClickedUp { # error CancelPie $win } SelectedUp { # error CancelPie $win } } } # Track the selected item proc TrackPieMenu {pie x y} { $pie activate @$x,$y } proc PreviewPieMenu {win pie x y} { set preview [lindex [$pie config -preview] 4] if {"$preview" != ""} { set rx [winfo rootx $win] set ry [winfo rooty $win] set x [expr "$x - $rx"] set y [expr "$y - $ry"] eval [format $preview $x $y] } } ######################################################################## # Pallet Handlers proc ExclusivePallet {state parent children prefix images inactive active cmd} { #echo "ExclusivePallet state $state parent $parent children $children prefix $prefix images $images inactive $inactive active $active cmd $cmd" set i 0 foreach child $children { set name [lindex $images $i] if {$i == $state} then { $parent.$child config \ -bitmap "@images/${prefix}${name}hi.xpm" \ -relief $active } else { $parent.$child config \ -bitmap "@images/${prefix}${name}.xpm" \ -relief $inactive } incr i } eval [concat $cmd $state] } proc NonExclusivePallet {mask parent children prefix images inactive active cmd} { set i 0 foreach child $children { set name [lindex $images $i] if {$mask & (1<<$i)} then { $parent.$child config \ -bitmap "@images/${prefix}${name}hi.xpm" \ -relief $active } else { $parent.$child config \ -bitmap "@images/${prefix}${name}.xpm" \ -relief $inactive } incr i } eval [concat $cmd $mask] } proc EditorPallet {win state} { global EditorPalletSounds UIMakeSoundOn $win mode [lindex $EditorPalletSounds $state] EditorSetTool $win $state } proc EditorSetTool {win state} { global EditorPallets global EditorPalletImages ExclusivePallet $state $win $EditorPallets ic $EditorPalletImages \ flat raised "$win.centerframe.view ToolState" } proc GraphPallet {win state} { set mask [[WindowLink $win.graphview] Mask] set mask [expr "$mask ^ (1<<$state)"] GraphPalletMask $win $mask } proc GraphPalletMask {win mask} { global GraphPallets global GraphPalletImages NonExclusivePallet $mask $win $GraphPallets gr $GraphPalletImages \ flat flat "SetGraphState $win" } proc GraphYearPallet {win state} { global GraphYearPallets global GraphYearPalletImages ExclusivePallet $state $win $GraphYearPallets gr $GraphYearPalletImages \ flat flat "SetGraphYearState $win" } proc SetGraphYearState {win state} { set graph [WindowLink $win.graphview] if {$state == 0} { $graph Range 10 } else { $graph Range 120 } } proc SetGraphState {win mask} { global GraphPallets set graph [WindowLink $win.graphview] $graph Mask $mask } ######################################################################## # Button Handlers proc sim_butEnter {w} { global tk_priv set screen [winfo screen $w] set tk_priv(window@$screen) $w } proc sim_butLeave {w} { global tk_priv set screen [winfo screen $w] set tk_priv(window@$screen) "" } proc sim_butDown {w} { global tk_priv set screen [winfo screen $w] set pict [lindex [$w config -bitmap] 4] set tk_priv(relief@$screen) $pict $w config -bitmap [lindex [split $pict .] 0]hi.xpm update idletasks } proc sim_butUp {w} { global tk_priv set screen [winfo screen $w] $w config -bitmap $tk_priv(relief@$screen) update idletasks if {$w == $tk_priv(window@$screen)} { uplevel #0 [list $w invoke] } } proc BindSimButton {w} { bind $w {sim_butEnter %W} bind $w {sim_butLeave %W} bind $w <1> {sim_butDown %W} bind $w {sim_butUp %W} bind $w <2> {sim_butDown %W} bind $w {sim_butUp %W} bind $w <3> {sim_butDown %W} bind $w {sim_butUp %W} } ######################################################################## # Internal Callbacks proc UIStartSimCity {homedir resourcedir hostname} { global HomeDir ResourceDir HostName HeadWindows set HomeDir $homedir set ResourceDir $resourcedir set HostName $hostname sim InitGame sim GameStarted update foreach display [sim Displays] { if {"[AddPlayer $display]" == ""} { echo Couldn't add a player on $display ... } } if {"$HeadWindows" == ""} { echo SimCity is exiting because it couldn't connect to any players. sim ReallyQuit } } proc UISelectCity {win} { AskQuestion [Color $win #ff0000 #ffffff] "Choose Another City" \ "Do you want to abandon this city and choose another one?" \ "{Keep playing.} SelectCity.No {RejectPlan}" \ "" \ "{Another city!} SelectCity.Yes {UIPickScenarioMode}" } proc UIQuit {head} { if {[sim Players] == 1} { set l "{Keep playing.} Quit.No {RejectPlan}" set m "" set r "{I quit!} Quit.IQuit {DoReallyQuit %s}" } else { set l "{Keep playing.} Quit.No {RejectPlan}" set m "{I quit!} Quit.IResign {DoIResign %s}" set r "{Everyone quit!} Quit.AllQuit {DoReallyQuit %s}" } AskQuestion [Color $head #ff0000 #ffffff] "Quit Playing SimCity" \ "Do you want to quit playing SimCity?" \ $l $m $r } proc DoIResign {head} { global VotesForAsk set display [winfo screen $head] CrushHead $head DecRefDisplay $display UISetMessage "The player on X11 Display $display has resigned." UpdatePlayers if {([sim Players] == 0) || ([llength $VotesForAsk] >= [sim Players])} { sim ReallyQuit } } proc DoReallyQuit {head} { sim ReallyQuit } proc UIPickScenarioMode {} { global State global CityLibDir set State scenario sim Pause WithdrawAll InitHistory UIGenerateCityNow InitHeads InitAllHeadMenus InitScenarios InitVotesForUseThisMap ShowHeads ShowMaps DisableMaps ShowScenarios UIShowPicture 300 } proc ForcePickScenarioMode {} { global State if {"$State" != "scenario"} { UIPickScenarioMode } } proc UIGenerateCityNow {} { global CityName GameLevel sim CityName NowHere sim GameLevel 0 UIGenerateNewCity } proc UIGenerateNewCity {} { global CityName GameLevel if {$GameLevel == -1} { set GameLevel 0 } MakeHistory "DoNewCity NowHere $GameLevel [sim Rand] [sim TreeLevel] [sim LakeLevel] [sim CurveLevel] [sim CreateIsland]" } proc DoNewCity {name level {r ""} {tl -1} {ll -1} {cl -1} {ci -1}} { global Scenario set Scenario -1 sim TreeLevel $tl sim LakeLevel $ll sim CurveLevel $cl sim CreateIsland $ci if {"$r" == ""} { sim GenerateNewCity } else { sim GenerateSomeCity $r } sim CityName $name sim GameLevel $level UIShowPicture 48 } proc UIDidGenerateNewCity {} { sim Update } proc ListenTo {port} { set sock file[sim ListenTo $port] filehandler $sock r HearFrom } proc HearFrom {mode file} { sim HearFrom $file } proc DoMidiKeyboard {args} { echo Keyboard $args } proc DoMidiSlider {args} { echo Slider $args } global PacketOpcodes set PacketOpcodes { {0 {"echo" numbers}} {1 {"DoMidiKeyboard 1" numbers}} {2 {"DoMidiSlider 2" numbers}} {3 {"DoMidiSlider 3" numbers}} {4 {"DoMidiSlider 4" numbers}} {5 {"DoMidiSlider 5" numbers}} {6 {"DoMidiSlider 6" numbers}} {7 {"DoMidiSlider 7" numbers}} {8 {"DoMidiSlider 8" numbers}} {9 {"DoMidiSlider 9" numbers}} {10 {"DoMidiSlider 10" numbers}} {11 {"DoMidiSlider 11" numbers}} {12 {"DoMidiSlider 12" numbers}} {13 {"DoMidiSlider 13" numbers}} {14 {"DoMidiSlider 14" numbers}} {15 {"DoMidiSlider 15" numbers}} {16 {"DoMidiSlider 16" numbers}} } global TokenTable set TokenTable { { 0 } { 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 } { } {!} {"} {#} {$} {%} {&} {'} {(} {)} {*} {+} {,} {-} {.} {/} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {:} {;} {<} {=} {>} {?} {@} {A} {B} {C} {D} {E} {F} {G} {H} {I} {J} {K} {L} {M} {N} {O} {P} {Q} {R} {S} {T} {U} {V} {W} {X} {Y} {Z} {[} {\\} {]} {^} {_} {`} {a} {b} {c} {d} {e} {f} {g} {h} {i} {j} {k} {l} {m} {n} {o} {p} {q} {r} {s} {t} {u} {v} {w} {x} {y} {z} {\{} {|} {\}} {~} {_} } proc HandlePacket {sock addr data} { global PacketOpcodes global TokenTable set opcode [lvarpop data] set operation "" catch {set operation [keylget PacketOpcodes $opcode]} if {"$operation" != ""} { set func [lindex $operation 0] set format [lindex $operation 1] case $format { numbers { set cmd [format "%s %s" $func $data] } numberlist { set cmd [format "%s {%s}" $func $data] } tokens { set cmd [format "%s " $func] foreach token $data { set cmd [format "%s%s" $cmd [lindex $TokenTable $token]] } } } echo "EXECUTING $cmd" eval $cmd } else { echo BOGUS PACKET from $addr containing $data } } proc IncRefDisplay {display} { global DisplayRegistry if ![info exists DisplayRegistry($display)] { set DisplayRegistry($display) 0 } incr DisplayRegistry($display) } proc DecRefDisplay {display} { global DisplayRegistry incr DisplayRegistry($display) -1 if {$DisplayRegistry($display) <= 0} { CloseDisplay $display } } proc CloseDisplay {display} { } proc DoStopSimCity {} { KillSoundServers destroy . } proc AddPlayer {display} { set i [string first : $display] if {$i == 0} { } else { if {$i == -1} { set display "$display:0" } } echo Adding a player on $display ... set head [MakeWindow.head $display] if {"$head" != ""} { set display [winfo screen $head] IncRefDisplay $display PrepHead $head UISetMessage "Added a player on X11 Display \"$display\"." UpdatePlayers } else { UISetMessage "Couldn't add a player on X11 Display \"$display\"!" } return $head } proc FireBomb {} { sim FireBomb } proc DropFireBombs {} { FireBomb after 300 FireBomb after 600 FireBomb after 900 FireBomb } proc UIMacrowave {} { if {[sim Rand] & 1} { eco } else { melt } UIMakeSound warning Oop {"-repeat 16"} UIMakeSound warning Boing {"-repeat 5"} } proc UIMakeMonster {} { sim MakeMonster [sim Rand 120] [sim Rand 100] } proc Kaboom {} { UIMacrowave UIMakeMonster sim MakeTornado sim MakeEarthquake after 1000 UIShowPicture 45 after 2000 UIMakeSound warning Sorry } proc melt {} { sim HeatSteps 1 sim HeatFlow -7 sim HeatRule 0 } proc eco {} { sim HeatSteps 1 sim HeatFlow 19 sim HeatRule 1 } proc oops {} { sim HeatSteps 0 } proc RockTheVote {} { if {[sim HeatRule] == 1} { sim HeatRule 0 sim HeatFlow [expr "[sim Rand 100] - 50"] } else { sim HeatRule 1 sim HeatFlow [sim Rand 256] } } proc TogglePause {} { global State if {"$State" != "play" || [sim Speed]} { sim Speed 0 } else { sim Speed 3 RockTheVote } MakeRunningSound } proc SetSpeedTime {time} { sim Speed $time MakeRunningSound } proc MakeRunningSound {} { global State if {"$State" == "play" && [sim Speed]} { UIMakeSound edit Boing "-speed 1[sim Speed]0" } else { UIMakeSound edit Boing "-speed 90" } } proc SayDemands {} { global DemandRes DemandCom DemandInd set slope 3 set r [expr "100 + ($DemandRes * $slope)"] set c [expr "100 + ($DemandCom * $slope)"] set i [expr "100 + ($DemandInd * $slope)"] after 020 "UIMakeSound edit O \"-speed $r\"" after 220 "UIMakeSound edit A \"-speed $c\"" after 440 "UIMakeSound edit E \"-speed $i\"" } proc UISaveCity {win} { global SaveCityWin set SaveCityWin $win sim SaveCity } proc UISaveCityAs {{win ""}} { global SaveCityWin if {"$win" == ""} {set win $SaveCityWin} set SaveCityWin $win global CityDir set file [ShowFileOf $win] DoFileDialog $file "Choose a File to Save the City" $CityDir "*.cty" "" \ "UIDoReallySaveCity" "" } proc UIDoReallySaveCity {name path} { global CityDir if {![string match *.cty $name]} { set name $name.cty } set CityDir $path sim SaveCityAs $path/$name } proc UIDidSaveCity {} { DoSendMessage "Saved the city in \"[sim CityFileName]\"." status } proc UIDidntSaveCity {msg} { DoSendMessage $msg alert UIMakeSound warning Sorry "-speed 85" } proc UILoadScenario {scen} { MakeHistory "DoScenario $scen" } proc DoScenario {scen} { global Scenario set Scenario $scen sim LoadScenario $scen UIShowPicture $scen } proc UIDidLoadScenario {} { } proc UIStartScenario {id} { global Scenario set Scenario $id UILoadScenario $id UIPlayGame UIShowPicture $id } proc UIPlayNewCity {} { UIGenerateNewCity UIPlayGame } proc UIStartLoad {} { UIPlayGame } proc UIReallyStartGame {} { UIPickScenarioMode } proc UIPlayGame {} { global State global Priority set State play sim Resume sim Speed 3 sim AutoGoto 1 SetPriority $Priority InitHeads InitAllHeadMenus ShowInitial sim NeedRest 10 } proc UISetSpeed {speed} { global Time State set Time $speed if {"$State" == "play"} { UISetMessage [lindex { {Time pauses.} {Time flows slow.} {Time flows medium.} {Time flows fast.} } $speed] } UIUpdateRunning } proc UIUpdateRunning {} { global HeadWindows Time State if {($State == "play") && $Time} { set pict "@images/simcityg.xpm" } else { set pict "@images/simcitys.xpm" } foreach win $HeadWindows { set can [WindowLink $win.demand] $can itemconfig simcity -bitmap $pict } } proc DoSetGameLevel {level} { sim GameLevel $level } proc UISetGameLevel {level} { global GameLevel set GameLevel $level } proc UISetCityName {name} { global EditorWindows global CityName set CityName $name set title "SimCity Editor on $name" foreach win $EditorWindows { # TODO: set editor window and icon title #wm title $win "$title" #wm iconname $win "$title" } } proc UILoadCity {win} { # if changed, r-u-sure? global CityDir set file [ShowFileOf $win] DoFileDialog $file "Choose a City to Load" $CityDir "*.cty" "" \ "UIDoLoadCity" "" } proc UIDoLoadCity {name path} { global CityDir set CityDir $path if {![string match *.cty $name]} { set name $name.cty } MakeHistory "DoLoadCity $path/$name" } proc DoLoadCity {filename} { sim LoadCity $filename } proc UIDidLoadCity {} { global State GameLevel Scenario set Scenario -1 set GameLevel -1 if {$State == "play"} { UIPlayGame } else { UIShowPicture 49 [sim CityFileName] } } proc UIDidntLoadCity {msg} { DoSendMessage $msg alert UIMakeSound warning Sorry "-speed 85" UIShowPicture 49 [sim CityFileName] sim Fill 0 sim UpdateMaps } proc UINewGame {} { global OldBudget set OldBudget 0 sim InitGame sim EraseOverlay InitEditors InitMaps InitGraphs update sim UpdateMaps } proc UIDidPan {w x y} { if {[$w ToolMode] == 1} { EditorToolDrag $w $x $y } update idletasks } proc UIDidStopPan {win} { UIMakeSoundOn $win fancy Skid "-volume 25" $win TweakCursor } proc UIEarthQuake {} { } proc UIAutoGoto {x y {except {}}} { global EditorWindows set didOne 0 set x [expr "$x * 16 + 8"] set y [expr "$y * 16 + 8"] foreach win $EditorWindows { if {"$win" != "$except"} { set view [WindowLink $win.view] if {[$view AutoGoto]} { set didOne 1 $view AutoGoal $x $y } } } if {$didOne} { sim UpdateMaps } } proc UIAutoGotoOn {x y eds} { set x [expr "$x * 16 + 8"] set y [expr "$y * 16 + 8"] foreach win $eds { [WindowLink $win.view] AutoGoal $x $y } sim UpdateMaps } proc DoLeaveGame {head} { } proc UILoseGame {} { UIPickScenarioMode UIShowPicture 200 } proc UIWinGame {} { UIShowPicture 100 } proc DoPendTool {view tool x y} { global HeadWindows ToolInfo VotesForAsk set win [WindowLink $view.top] set head [WindowLink $win.head] if {($tool == [sim PendingTool]) && ($x == [sim PendingX]) && ($y == [sim PendingY])} { if {[lsearch $VotesForAsk $head] != -1} { # you can only vote once UIMakeSound edit Oop } else { UIMakeSound edit Boing set ask [WindowLink $head.ask] PressVoteButton $ask [WindowLink $ask.vote] Ask } } else { UIAutoGoto $x $y $win UIMakeSound edit Boing set info [lindex $ToolInfo $tool] set a [lindex $info 0] set name [lindex $info 1] set cost [lindex $info 2] set title "Build $a $name" set question "Do you support the plan to build $a $name for $cost?" AskQuestion [Color $win #00ff00 #ffffff] "$title" \ "$question" \ "{Veto plan.} Plan.Veto {RejectPlan}" \ "{Goto plan.} Plan.Goto {ComeTo %s $x $y}" \ "{Support plan!} Plan.Support {SupportPlan $view %s $tool $x $y} {PreviewSupportPlan $view %s $tool $x $y}" set VotesForAsk $head set ask [WindowLink $head.ask] [WindowLink $ask.vote] config -relief sunken UpdateVotesForAsk sim PendingTool $tool sim PendingX $x sim PendingY $y sim Votes [llength $VotesForAsk] } } proc RejectPlan {} { sim PendingTool -1 if {[sim Players] > 1} { UIMakeSound edit Sorry } WithdrawAsks } proc NeededVotes {} { global FreeVotes set players [sim Players] set needed [expr "$players - $FreeVotes"] return [max 0 $needed] } proc SupportPlan {view h tool x y} { global VotesForAsk sim Votes [llength $VotesForAsk] sim PendingTool -1 sim OverRide 1 $view DoTool $tool $x $y sim OverRide 0 WithdrawAsks UIMakeSound edit Aaah } proc PreviewSupportPlan {view h tool x y} { global VotesForAsk sim Votes [llength $VotesForAsk] } proc StartWebServer {} { global WebServer WebSocket StopWebServer # catch { set WebServer [connect -server localhost $WebSocket] # } if {"$WebServer" != ""} { filehandler $WebServer rwe ConnectWebServer } } proc StopWebServer {} { global WebServer if {"$WebServer" != ""} { catch { close $WebServer } set WebServer {} } } proc ConnectWebServer {mode server} { echo ConnectWebServer $mode $server set client {} catch { set client [accept $server] } global ${client}State global ${client}GetCommand global ${client}GetHeaders set ${client}State 0 if {"$client" != ""} { filehandler $client re HandleWebClient } } proc HandleWebClient {mode client} { echo HandleWebClient mode $mode client $client if {$mode == "r"} { ReadWebClient $client } } proc ReadWebClient {client} { echo ReadWebClient $client set str {} set success 0 gets $client str set str [string trimright $str "\015"] global ${client}State global ${client}GetCommand global ${client}GetHeaders set state [eval ident "\$${client}State"] echo ReadWebClient state $state case $state { {0} { if {[string match "GET *" $str]} { set ${client}GetCommand $str set ${client}GetHeaders {} set ${client}State 1 } } {1} { if {"$str" != ""} then { lappend ${client}GetHeaders $str } else { set cmd [eval ident "\$${client}GetCommand"] set headers [eval ident "\$${client}GetHeaders"] set ${client}GetCommand {} set ${client}GetHeaders {} set ${client}State 0 HandleHTTPGet $client $cmd $headers } } } } proc HandleHTTPGet {client cmd headers} { echo "HandleHTTPGet: $client $cmd $headers" set content "Hello

Hello!

\r\n" puts $client "HTTP/1.1 200 OK\r\nContent-Length: [string length $content]\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n$content" nonewline flush $client }