Files
scoundrel-ports/scoundrel-jim.tcl
2026-06-08 21:16:47 +03:00

173 lines
4.4 KiB
Tcl
Executable File

#!/usr/bin/env jimsh
# Scoundrel roguelike solitaire game port to Jim Tcl
# Created by Luxferre in 2026, released into the public domain
# helpers
proc shuffle list {
set n [llength $list]
loop i 1 $n {
set j $(int(rand() * $n))
set temp [lindex $list $i]
lset list $i [lindex $list $j]
lset list $j $temp
}
return $list
}
proc get_valid_choice {prompt pat} {
set c --
puts -nonewline [format "%s " $prompt]
stdout flush
stdin tty input raw
while {$c ni $pat} {
set c [string tolower [stdin read 1]]
}
stdin tty input cooked
return $c
}
# variables and states
set score -208
set hp 20
set can_run 1
set engaged 0
set drank 0
set weapon 0
set durability 0
set rooms_clrd 0
set last_potion_val 0
# deck and room
set deck [shuffle [concat [range 1 14] [range 1 32]]]
set room {}
# game logic functions
proc game_field_display {} {
global hp weapon durability room deck can_run engaged
puts "--------------------------"
puts [format "H%02d | W%02d | D%02d | Deck: %02d" $hp $weapon $durability [llength $deck]]
puts "--------------------------"
foreach x $room {
if $($x < 14) {
puts -nonewline [format "M%02d " $($x + 1)]
} elseif $($x < 23) {
puts -nonewline [format "W%02d " $($x - 12)]
} else {
puts -nonewline [format "H%02d " $($x - 21)]
}
}
puts -nonewline "\n 1 2 3 4"
if {$can_run == 1 && $engaged == 0} {puts -nonewline " r)un->"}
}
# monster handling logic (adds monster value to the score)
proc handle_monster {val} {
global weapon durability hp score
set healthlost $val
puts [format "You encounter a monster of strength %d." $val]
if {$weapon > 0 && $durability >= $val} {
if {[get_valid_choice "Use weapon? (y/n)" "y n"] == "y"} {
set healthlost $($val - $weapon)
if {$healthlost < 0} {set healthlost 0}
puts [format "\nYou fight the monster with your %d-level weapon." $weapon]
set durability $($val - 1)
if {$durability < 2} {
set healthlost 0
set weapon 0
puts "Your weapon fully breaks!"
}
} else {puts "\nYou fight the monster barehanded."}
} else {puts "You fight the monster barehanded."}
set hp $($hp - $healthlost)
if {$hp < 0} {set hp 0}
puts [format "Lost %d HP. New HP: %d" $healthlost $hp]
incr score $val
}
# weapon handling logic
proc handle_weapon {val} {
global weapon durability
set weapon $val
set durability 14
puts [format "Equipped a %d-level weapon." $weapon]
}
# potion handling logic
proc handle_potion {val} {
global hp drank deck room
if {$drank > 0} {
puts "Already drank a potion here! Discarding..."
} else {
if {[llength $deck] == 0 && [llength $room] == 0} {set last_potion_val $val}
incr hp $val
if {$hp > 20} {set hp 20}
set drank 1
puts [format "Drank a %d-level potion. New HP: %d" $val $hp]
}
}
# game banner
puts "----- Scoundrel 2026 -----"
puts " Jim Tcl port by Luxferre"
puts " Good luck!"
# main game loop
while {([llength $deck] + [llength $room]) > 0 && $hp > 0} {
if {$engaged == 0} {
while {[llength $deck] > 0 && [llength $room] < 4} {
lappend room [lindex $deck 0]
set deck [lreplace $deck 0 0]
}
}
game_field_display
set chs {1 2 3 4 q}
if {$can_run == 1 && $engaged == 0} {set chs {1 2 3 4 q r}}
set ch [get_valid_choice {} $chs]
puts {}
if {$ch == "q"} {
if {[get_valid_choice "Really quit? (y/n)" "y n"] == "y"} {
puts "\nQuitting!"
exit
}
} elseif {$ch == "r"} {
set can_run 0
while {[llength $room] > 0} {
set idx [rand 0 [llength $room]]
lappend deck [lindex $room $idx]
set room [lreplace $room $idx $idx]
}
puts "You run from the room."
} else {
incr ch -1
set item [lindex $room $ch]
if {$item > 0} {
set engaged 1
set room [lreplace $room $ch $ch]
if {$item < 14} {
handle_monster $($item + 1)
} elseif {$item < 23} {
handle_weapon $($item - 12)
} else {handle_potion $($item - 21)}
if {[llength $deck] > 0 && [llength $room] == 1} {
set can_run 1
set engaged 0
set drank 0
incr rooms_clrd
}
}
}
}
# now score and output the game result
if {$hp > 0} {
set score $hp
if {$hp == 20} {incr score $last_potion_val}
incr rooms_clrd
puts -nonewline "You win!"
} else {
puts -nonewline "You lose!"
}
puts [format " Your score: %d. Rooms cleared: %d" $score $rooms_clrd]