Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ski for openSUSE:Factory checked in 
at 2026-05-14 21:46:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ski (Old)
 and      /work/SRC/openSUSE:Factory/.ski.new.1966 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ski"

Thu May 14 21:46:19 2026 rev:9 rq:1353225 version:6.16

Changes:
--------
--- /work/SRC/openSUSE:Factory/ski/ski.changes  2025-04-20 20:10:07.566551057 
+0200
+++ /work/SRC/openSUSE:Factory/.ski.new.1966/ski.changes        2026-05-14 
21:46:21.054967368 +0200
@@ -1,0 +2,6 @@
+Thu May  7 18:42:29 UTC 2026 - Carsten Ziepke <[email protected]>
+
+- update to 6.16:
+  * Code-hardening changes suggested by CharGPT 5.3.
+
+-------------------------------------------------------------------

Old:
----
  ski-6.15.tar.gz

New:
----
  ski-6.16.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ski.spec ++++++
--- /var/tmp/diff_new_pack.V16an4/_old  2026-05-14 21:46:21.734995347 +0200
+++ /var/tmp/diff_new_pack.V16an4/_new  2026-05-14 21:46:21.734995347 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package ski
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           ski
-Version:        6.15
+Version:        6.16
 Release:        0
 Summary:        Skiing simulation with curses interface in python
 License:        BSD-3-Clause
@@ -44,6 +44,7 @@
 
 %prep
 %autosetup -p0
+sed -i -e 's|PREFIX      ?= /usr/local|PREFIX      ?= /usr|g' Makefile
 
 %build
 %make_build CFLAGS="%{optflags}"
@@ -53,7 +54,7 @@
 
 %files
 %license COPYING
-%doc NEWS README
+%doc NEWS README.adoc
 %dir %{_datadir}/appdata/
 %{_bindir}/%{name}
 %{_datadir}/appdata/ski.adoc

++++++ ski-6.15.tar.gz -> ski-6.16.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ski-6.15/Makefile new/ski-6.16/Makefile
--- old/ski-6.15/Makefile       2024-02-09 12:45:39.000000000 +0100
+++ new/ski-6.16/Makefile       2026-04-05 19:32:33.000000000 +0200
@@ -4,12 +4,15 @@
 # SPDX-FileCopyrightText: (C) Eric S. Raymond <[email protected]>
 # SPDX-License-Identifier: BSD-2-Clause
 #
-VERS=$(shell sed <ski -n -e '/version *= *"\(.*\)"/s//\1/p')
 
-SOURCES = README COPYING NEWS ski ski.adoc ski.6 Makefile \
-       control ski.png ski.desktop
+PREFIX      ?= /usr/local
+BINDIR      ?= $(PREFIX)/bin
+DATADIR     ?= $(PREFIX)/share
+MANDIR      ?= $(DATADIR)/man
 
-all: ski.6
+VERSION=$(shell sed <ski -n -e '/version[^=]*= *"\(.*\)"/s//\1/p')
+
+# Rules
 
 # Note: to suppress the footers with timestamps being generated in HTML,
 # we use "-a nofooter".
@@ -22,48 +25,69 @@
 .adoc.html:
        asciidoctor -D. -a nofooter -a webfonts! $<
 
+.PHONY: all clean pylint spellcheck
+.PHONY: install uninstall version dist release refresh
+
+# Build
+
+all: ski.6
+
 clean:
-       rm -f *~ *.6 *.html *.rpm *.lsm MANIFEST
+       rm -f *~ *.6 *.html
+
+# Validate
+
+pylint:
+       @pylint --score=n ski
+
+spellcheck:
+       @spellcheck ski.adoc
+
+# Intall/uninstall
 
 install: ski.6 uninstall
-       install -m 0755 -d $(DESTDIR)/usr/bin
-       install -m 0755 -d $(DESTDIR)/usr/share/man/man6
-       install -m 0755 -d $(DESTDIR)//usr/share/applications/
-       install -m 0755 -d $(DESTDIR)/usr/share/pixmaps/
-       install -m 0755 -d $(DESTDIR)/usr/share/appdata
-       install -m 0755 ski $(DESTDIR)/usr/bin/
-       install -m 0644 ski.6 $(DESTDIR)/usr/share/man/man6/
-       install -m 0644 ski.desktop $(DESTDIR)/usr/share/applications
-       install -m 0644 ski.png $(DESTDIR)/usr/share/pixmaps/
-       install -m 0644 ski.adoc $(DESTDIR)/usr/share/appdata/
+       install -m 0755 -d $(DESTDIR)$(BINDIR)
+       install -m 0755 -d $(DESTDIR)$(MANDIR)/man6
+       install -m 0755 -d $(DESTDIR)$(DATADIR)/applications/
+       install -m 0755 -d $(DESTDIR)$(DATADIR)/pixmaps/
+       install -m 0755 -d $(DESTDIR)$(DATADIR)/appdata
+       install -m 0755 ski $(DESTDIR)$(BINDIR)/
+       install -m 0644 ski.6 $(DESTDIR)$(MANDIR)/man6/
+       install -m 0644 ski.desktop $(DESTDIR)$(DATADIR)/applications
+       install -m 0644 ski.png $(DESTDIR)$(DATADIR)/pixmaps/
+       install -m 0644 ski.adoc $(DESTDIR)$(DATADIR)/appdata/
 
 uninstall:
-       rm -f /usr/bin/ski /usr/share/man/man6/ski.6
-       rm -f /usr/share/applications/ski.desktop
-       rm -f /usr/share/pixmaps/ski.png
-       rm -f /usr/share/appdata/ski.adoc
+       rm -f $(DESTDIR)$(BINDIR)/ski $(MANDIR)/man6/ski.6
+       rm -f $(DESTDIR)$(DATADIR)/applications/ski.desktop
+       rm -f $(DESTDIR)$(DATADIR)/pixmaps/ski.png
+       rm -f $(DESTDIR)$(DATADIR)/appdata/ski.adoc
 
-pylint:
-       @pylint --score=n ski
+# Export
+
+SOURCES = README.adoc COPYING NEWS ski ski.adoc ski.6 Makefile \
+       control ski.png ski.desktop
 
 version:
-       @echo $(VERS)
+       @echo $(VERSION)
 
-ski-$(VERS).tar.gz: $(SOURCES)
-       @ls $(SOURCES) | sed s:^:ski-$(VERS)/: >MANIFEST
-       @(cd ..; ln -s ski ski-$(VERS))
-       (cd ..; tar -czf ski/ski-$(VERS).tar.gz `cat ski/MANIFEST`)
-       @ls -l ski-$(VERS).tar.gz
-       @(cd ..; rm ski-$(VERS))
+ski-$(VERSION).tar.gz: $(SOURCES)
+       mkdir ski-$(VERSION)
+       cp -r $(SOURCES) ski-$(VERSION)
+       tar -czf ski-$(VERSION).tar.gz ski-$(VERSION)
+       rm -fr ski-$(VERSION)
+       ls -l ski-$(VERSION).tar.gz
 
-dist: ski-$(VERS).tar.gz
+dist: ski-$(VERSION).tar.gz
 
 NEWSVERSION=$(shell sed -n <NEWS '/^[0-9]/s/:.*//p' | head -1)
 
-release: ski-$(VERS).tar.gz ski.html
-       @[ $(VERS) = $(NEWSVERSION) ] || { echo "Version mismatch!"; exit 1; }
-       shipper version=$(VERS) | sh -e -x
+release: ski-$(VERSION).tar.gz ski.html
+       @[ $(VERSION) = $(NEWSVERSION) ] || { echo "Version mismatch!"; exit 1; 
}
+       shipper version=$(VERSION) | sh -e -x
 
 refresh: ski.html
-       @[ $(VERS) = $(NEWSVERSION) ] || { echo "Version mismatch!"; exit 1; }
-       shipper -N -w version=$(VERS) | sh -e -x
+       @[ $(VERSION) = $(NEWSVERSION) ] || { echo "Version mismatch!"; exit 1; 
}
+       shipper -N -w version=$(VERSION) | sh -e -x
+
+# end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ski-6.15/NEWS new/ski-6.16/NEWS
--- old/ski-6.15/NEWS   2024-02-09 13:40:39.000000000 +0100
+++ new/ski-6.16/NEWS   2026-04-05 19:32:33.000000000 +0200
@@ -1,5 +1,8 @@
                                ski project history
 
+6.16: 2026-04-05::
+  Code-hardening changes suggested by CharGPT 5.3.
+
 6.15: 2024-02-09::
   Fix minor bug related to Python 3 decoding.
   Make player more conspicuous on a black screen.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ski-6.15/README new/ski-6.16/README
--- old/ski-6.15/README 2019-04-26 20:20:50.000000000 +0200
+++ new/ski-6.16/README 1970-01-01 01:00:00.000000000 +0100
@@ -1,32 +0,0 @@
-                       ski, a fun and silly game
-
-Imagine you are skiing down an infinite slope, facing such hazards as
-trees, ice, bare ground, and the man-eating Yeti!  Unfortunately,
-you have put your jet-powered skis on backwards, so you can't see
-ahead where you are going; only behind where you have been.  However,
-you can turn to either side, jump or hop through the air, teleport
-through hyperspace, launch nuclear ICBMs, and cast spells to call the
-Fire Demon.  And since the hazards occur in patches, you can
-skillfully outmaneuver them.  A fun and very silly game that proves
-you don't need fancy graphical user interfaces to have a good time.
-
-This is a Python reimplementation of a C game from 1990, with on-line
-help added.  The original was by Mark Stevans, this implementation is
-released under open-source terms by Eric S. Raymond.
-
-The internals of this game are actually kind of interesting.  The terrain
-generator is a simple cellular automaton that generates crude 2D fractals.
-
-See
-               http://www.catb.org/~esr/ski/
-
-for updates and related resources.
-
-On 15 May 2006 Mark Stevans wrote:
->Just wanted to thank you.  Very nice port, love the full-color
->graphics.  Originally it was FORTRAN on DEC-10's, ported to C around
->1981.  Your Python version should keep Ski! viable for another 10-20
->years, but I might try to put up a Ruby version for the heck of it....
-
-Years later I learned that the game had originally been written to use
-VT-100 terminals.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ski-6.15/README.adoc new/ski-6.16/README.adoc
--- old/ski-6.15/README.adoc    1970-01-01 01:00:00.000000000 +0100
+++ new/ski-6.16/README.adoc    2026-04-05 19:32:33.000000000 +0200
@@ -0,0 +1,36 @@
+=  ski, a fun and silly game
+
+Imagine you are skiing down an infinite slope, facing such hazards as
+trees, ice, bare ground, and the man-eating Yeti!  Unfortunately,
+you have put your jet-powered skis on backwards, so you can't see
+ahead where you are going; only behind where you have been.  However,
+you can turn to either side, jump or hop through the air, teleport
+through hyperspace, launch nuclear ICBMs, and cast spells to call the
+Fire Demon.  And since the hazards occur in patches, you can
+skillfully outmaneuver them.  A fun and very silly game that proves
+you don't need fancy graphical user interfaces to have a good time.
+
+This is a Python reimplementation of a C game from 1990, with on-line
+help added.  The original was by Mark Stevans, this implementation is
+released under open-source terms by Eric S. Raymond.
+
+The internals of this game are actually kind of interesting.  The terrain
+generator is a simple cellular automaton that generates crude 2D fractals.
+
+See http://www.catb.org/~esr/ski/ for updates and related resources.
+
+----
+On 15 May 2006 Mark Stevans wrote:
+>Just wanted to thank you.  Very nice port, love the full-color
+>graphics.  Originally it was FORTRAN on DEC-10's, ported to C around
+>1981.  Your Python version should keep Ski! viable for another 10-20
+>years, but I might try to put up a Ruby version for the heck of it....
+----
+
+Years later I learned that the game had originally been written to use
+VT-100 terminals.
+
+This code is commonly packaged as "ski".
+
+image:https://repology.org/badge/vertical-allrepos/ski-game.svg[Repology
+package status]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ski-6.15/control new/ski-6.16/control
--- old/ski-6.15/control        2024-02-05 20:25:03.000000000 +0100
+++ new/ski-6.16/control        2026-04-05 19:32:33.000000000 +0200
@@ -16,7 +16,7 @@
  skillfully outmaneuver them.  A fun and very silly game that proves
  you don't need fancy graphical user interfaces to have a good time.
 
-XBS-Destinations: [email protected]
+XBS-Packaged-As: ski-game
 
 Homepage: http://www.catb.org/~esr/ski
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ski-6.15/ski new/ski-6.16/ski
--- old/ski-6.15/ski    2024-02-09 13:03:43.000000000 +0100
+++ new/ski-6.16/ski    2026-04-05 19:32:33.000000000 +0200
@@ -15,26 +15,31 @@
  ? = print this help message.
 
 """
-# This code runs under both Python 2 and Python 3. Preserve this property!
-from __future__ import print_function
+# Python 3 only.
 
 # pylint: 
disable=invalid-name,missing-function-docstring,no-else-return,redefined-outer-name,consider-using-f-string,consider-using-enumerate
 
 # pylint: disable=multiple-imports
-import time, random, curses, copy, sys, os
+import copy
+import curses
+import os
+import random
+import sys
+import time
+from typing import Final, NoReturn, Optional
+
+version: Final[str] = "6.16"
+
+REP_SNOW: Final[str] = "."
+REP_TREE: Final[str] = "Y"
+REP_GROUND: Final[str] = ":"
+REP_ICE: Final[str] = "#"
+REP_PLAYER: Final[str] = "I"
+REP_YETI: Final[str] = "A"
+REP_ICBM: Final[str] = "*"
+REP_DEMON: Final[str] = "D"
 
-version = "6.15"
-
-REP_SNOW = "."
-REP_TREE = "Y"
-REP_GROUND = ":"
-REP_ICE = "#"
-REP_PLAYER = "I"
-REP_YETI = "A"
-REP_ICBM = "*"
-REP_DEMON = "D"
-
-terrain_key = [
+terrain_key_parts: Final[list[str]] = [
     "Terrain types:   ",
     REP_SNOW,
     " = snow      ",
@@ -56,62 +61,62 @@
 ]
 
 # Length of line
-LINE_LEN = 70
+LINE_LEN: Final[int] = 70
 
 # Minimum distance from the player at which a new Yeti may appear.
-MIN_YETI_APPEARANCE_DISTANCE = 3
+MIN_YETI_APPEARANCE_DISTANCE: Final[int] = 3
 
 # Constant multiplied into the first element of the cellular growth
 # automaton probability array with each passing level.
-LEVEL_MULTIPLIER = 1.01
+LEVEL_MULTIPLIER: Final[float] = 1.01
 
 # Absolute value of maximum horizontal player speed.
-MAX_HORIZONTAL_PLAYER_SPEED = 5
+MAX_HORIZONTAL_PLAYER_SPEED: Final[int] = 5
 
-ICBM_SPEED = 3  # Horizontal speed of an ICBM.
-ICBM_RANGE = 2  # Horizontal Yeti lethality range of the ICBM.
-DEMON_RANGE = 1  # Horizontal Yeti lethality range of the demon.
-DEMON_SPEED = 1  # Horizontal maximum speed of the Fire Demon.
+ICBM_SPEED: Final[int] = 3  # Horizontal speed of an ICBM.
+ICBM_RANGE: Final[int] = 2  # Horizontal Yeti lethality range of the ICBM.
+DEMON_RANGE: Final[int] = 1  # Horizontal Yeti lethality range of the demon.
+DEMON_SPEED: Final[int] = 1  # Horizontal maximum speed of the Fire Demon.
 
 # Per-turn probabilities
-PROB_YETI_MELT = 1.0  # Of Yeti spontaneously melting.
-PROB_SKIS_MELT_YETI = 20.0  # Of melting Yeti by jumping over it.
-PROB_BAD_SPELL = 10.0  # Of "Summon Fire Demon" spell going awry.
-PROB_BAD_TELEPORT = 10.0  # Of a teleport going wrong.
-PROB_BAD_ICBM = 30.0  # Of your ICBM exploding on launch.
-PROB_SLIP_ON_ICE = 2.0  # Of slipping when on ice.
-PROB_FALL_ON_GROUND = 10.0  # Of falling down on bare ground.
-PROB_HIT_TREE = 25.0  # Of hitting tree, each turn in trees
-PROB_BAD_LANDING = 3.0  # Of landing badly from jump or hop.
+PROB_YETI_MELT: Final[float] = 1.0  # Of Yeti spontaneously melting.
+PROB_SKIS_MELT_YETI: Final[float] = 20.0  # Of melting Yeti by jumping over it.
+PROB_BAD_SPELL: Final[float] = 10.0  # Of "Summon Fire Demon" spell going awry.
+PROB_BAD_TELEPORT: Final[float] = 10.0  # Of a teleport going wrong.
+PROB_BAD_ICBM: Final[float] = 30.0  # Of your ICBM exploding on launch.
+PROB_SLIP_ON_ICE: Final[float] = 2.0  # Of slipping when on ice.
+PROB_FALL_ON_GROUND: Final[float] = 10.0  # Of falling down on bare ground.
+PROB_HIT_TREE: Final[float] = 25.0  # Of hitting tree, each turn in trees
+PROB_BAD_LANDING: Final[float] = 3.0  # Of landing badly from jump or hop.
 
 # Number of points awarded to the player for the successful completion
 # of one jump.  For scoring purposes, a hop is considered to consist
 # of exactly one half-jump.
-POINTS_PER_JUMP = 20
+POINTS_PER_JUMP: Final[int] = 20
 
 # Number of points awarded to the player for each meter of horizontal
 # or vertical motion during each turn.
-POINTS_PER_METER = 1
+POINTS_PER_METER: Final[int] = 1
 
 # Number of points awarded to the player for each Yeti that melts
 # during the course of the game, regardless of whether the player
 # passively caused the Yeti to melt by luring him from a snowbank, or
 # actively melted the Yeti using his skis, an ICBM, or with the
 # assistance of the Fire Demon.
-POINTS_PER_MELTED_YETI = 100
+POINTS_PER_MELTED_YETI: Final[int] = 100
 
 # Number of points docked from your score for each degree of injury.
-POINTS_PER_INJURY_DEGREE = -40
+POINTS_PER_INJURY_DEGREE: Final[int] = -40
 
 # The injury categories.
-SLIGHT_INJURY = 0
-MODERATE_INJURY = 3
-SEVERE_INJURY = 6
+SLIGHT_INJURY: Final[int] = 0
+MODERATE_INJURY: Final[int] = 3
+SEVERE_INJURY: Final[int] = 6
 
 # The randomness of injury degrees.
-INJURY_RANDOMNESS = 6
+INJURY_RANDOMNESS: Final[int] = 6
 
-colordict = {
+COLOR_INDICES: Final[dict[str, int]] = {
     REP_SNOW: curses.COLOR_WHITE,
     REP_TREE: curses.COLOR_GREEN,
     REP_PLAYER: curses.A_STANDOUT,
@@ -122,12 +127,16 @@
     REP_DEMON: curses.COLOR_RED,
 }
 
+colordict: Final[dict[str, str]] = {}
+reset: str = ""
+terrain_key: str = ""
+
 
-def percent(X):
-    return (random.randint(0, 9999) / 100.0) <= (X)
+def percent(x: float) -> bool:
+    return random.random() * 100 < x
 
 
-def exists(X):
+def exists(X: Optional[int]) -> bool:
     return X is not None
 
 
@@ -135,7 +144,7 @@
 class SkiWorld:
     "The game state."
 
-    def __init__(self):
+    def __init__(self) -> None:
         # Constants controlling the multiple cellular growth
         # automatons that are executed in parallel to generate
         # hazards.
@@ -148,37 +157,37 @@
         #    [2] hazards edge stability
         #    [3] appearance of holes in solid hazards (this allows the Yeti
         #        to work his way through forests)
-        self.prob_tree = [0.0, 30.0, 70.0, 90.0]
-        self.prob_ice = [0.0, 30.0, 70.0, 90.0]
-        self.prob_ground = [0.0, 30.0, 70.0, 90.0]
-
-        self.level_num = 0
-        self.slope = [REP_SNOW] * LINE_LEN
-        self.player_pos = self.teleport()
-        self.yeti = None
-        self.icbm_pos = None
-        self.demon_pos = None
+        self.prob_tree: list[float] = [0.0, 30.0, 70.0, 90.0]
+        self.prob_ice: list[float] = [0.0, 30.0, 70.0, 90.0]
+        self.prob_ground: list[float] = [0.0, 30.0, 70.0, 90.0]
+
+        self.level_num: int = 0
+        self.slope: list[str] = [REP_SNOW] * LINE_LEN
+        self.player_pos: int = self.teleport()
+        self.yeti: Optional[int] = None
+        self.icbm_pos: Optional[int] = None
+        self.demon_pos: Optional[int] = None
 
         # Randomize the appearance probabilities.
         self.prob_tree[0] = (random.randint(0, 99)) / 500.0 + 0.05
         self.prob_ice[0] = (random.randint(0, 99)) / 500.0 + 0.05
         self.prob_ground[0] = (random.randint(0, 99)) / 500.0 + 0.05
-        self.prob_yeti_appearance = (random.randint(0, 99)) / 25.0 + 1.0
+        self.prob_yeti_appearance: float = (random.randint(0, 99)) / 25.0 + 1.0
 
-    def terrain(self):
+    def terrain(self) -> str:
         "What kind of terrain are we on?"
         return self.slope[self.player_pos]
 
-    def nearby(self, pos, minval=1):
+    def nearby(self, pos: Optional[int], minval: int = 1) -> bool:
         "Is the specified position near enough to the player?"
         return exists(pos) and abs(pos - self.player_pos) <= minval
 
-    def teleport(self):
+    def teleport(self) -> int:
         "Return a random location"
-        return random.choice(list(range(len(self.slope))))
+        return random.randrange(len(self.slope))
 
     # pylint: disable=too-many-branches
-    def gen_next_slope(self):
+    def gen_next_slope(self) -> None:
         # Generates the slope of the next level, dependent upon
         # the characteristics of the current level, the probabilities, and the
         # position of the player.
@@ -235,7 +244,7 @@
             else:
                 self.slope[i] = REP_SNOW
 
-    def update_level(self):
+    def update_level(self, player: "SkiPlayer") -> None:
         # Go to the next level, and move the player.
         self.level_num += 1
 
@@ -266,7 +275,7 @@
         self.prob_ground[0] *= LEVEL_MULTIPLIER
         self.prob_yeti_appearance *= LEVEL_MULTIPLIER
 
-    def manipulate_objects(self, player):
+    def manipulate_objects(self, player: "SkiPlayer") -> None:
         # If there is a Yeti, the player's jet-powered skis may melt him,
         # or he may spontaneously melt. Otherwise move him towards the player.
         # If there is a        tree in the way, the Yeti is blocked.
@@ -320,11 +329,11 @@
 
         # If there is a Yeti and a fire demon, he might get melted.
         if exists(self.yeti) and exists(self.demon_pos):
-            if abs(self.yeti - self.demon_pos) <= 1:
+            if abs(self.yeti - self.demon_pos) <= DEMON_RANGE:
                 self.yeti = None
                 player.num_snomen_melted += 1
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         "Create a picture of the current level."
         picture = copy.copy(self.slope)
         picture[self.player_pos] = REP_PLAYER
@@ -340,7 +349,7 @@
 
 class SkiPlayer:
     "The player in all his glory."
-    injuries = (
+    injuries: tuple[str, ...] = (
         "However, you escaped injury!",
         "But you weren't hurt at all!",
         "But you only got a few scratches.",
@@ -355,14 +364,14 @@
         "I'm sorry to tell you that you have been killed....",
     )
 
-    def __init__(self):
-        self.jump_count = -1
-        self.num_snomen_melted = 0
-        self.num_jumps_attempted = 0.0
-        self.player_speed = 0
-        self.meters_travelled = 0
+    def __init__(self) -> None:
+        self.jump_count: int = -1
+        self.num_snomen_melted: int = 0
+        self.num_jumps_attempted: float = 0.0
+        self.player_speed: int = 0
+        self.meters_travelled: int = 0
 
-    def __accident(self, msg, severity):
+    def __accident(self, msg: str, severity: int) -> NoReturn:
         # "__accident" is called when the player gets into an __accident,
         # which ends the game.  "msg" is the description of the
         # __accident type, and "severity" is the severity.  This
@@ -403,12 +412,12 @@
         score = max(score, 0)
 
         # Print the player's score.
-        print("Your score for this run is %ld." % score)
+        print("Your score for this run is %d." % score)
 
         # Exit the game with a code indicating successful completion.
         sys.exit(0)
 
-    def check_obstacles(self, world):
+    def check_obstacles(self, world: SkiWorld) -> None:
         # If we are just landing after a jump, we might fall down.
         if (self.jump_count == 0) and percent(PROB_BAD_LANDING):
             self.__accident("Whoops!  A bad landing!", SLIGHT_INJURY)
@@ -429,15 +438,15 @@
         if world.nearby(world.yeti):
             self.__accident("Yikes!  The Yeti's got you!", MODERATE_INJURY)
 
-    def update_player(self):
+    def update_player(self) -> None:
         "Update state of player for current move."
         self.meters_travelled += abs(self.player_speed) + 1
         # If the player was jumping, decrement the jump count.
-        if player.jump_count >= 0:
-            player.jump_count -= 1
+        if self.jump_count >= 0:
+            self.jump_count -= 1
 
     # pylint: disable=too-many-return-statements,too-many-branches
-    def do_command(self, world, cmdline):
+    def do_command(self, world: SkiWorld, cmdline: str) -> bool:
         # Print a prompt, and read a command.  Return True to advance game.
         cmd = cmdline[0].upper()
         if cmd == "?":
@@ -486,39 +495,39 @@
             return True
 
 
-def colorize(picture):
+def colorize(picture: list[str]) -> str:
     "Colorize special characters in a display list."
-    for (i, c) in enumerate(picture):
+    for i, c in enumerate(picture):
         if i == 0 or (c != picture[i - 1][-1]):
             if c in colordict:
-                picture[i] = colordict[c].decode("ascii") + c
+                picture[i] = colordict[c] + c
             else:
                 picture[i] = reset + c
-    picture += reset
+    picture.append(reset)
     return "".join(picture)
 
 
 # Main sequence
 if __name__ == "__main__":
-    try:
-        # pylint: disable=redefined-builtin
-        input = raw_input
-    except NameError:
-        pass
+    # C-style initialization of the random number generator.
+    # Unneeded - by default Python seeds from a good entropy source
+    # random.seed(time.time())
 
-    # Initialize the random number generator.
-    random.seed(time.time())
+    try:
+        curses.setupterm()
+    except curses.error as e:
+        print(e, file=sys.stderr)
+        raise SystemExit(1)
 
     # Arrange for color to be available
-    curses.setupterm()
     color = curses.tigetstr("setaf")
-    for (ch, idx) in list(colordict.items()):
+    for ch, idx in list(COLOR_INDICES.items()):
         if color:
-            colordict[ch] = curses.tparm(color, idx)
+            colordict[ch] = curses.tparm(color, idx).decode("ascii")
         else:
-            colordict[ch] = b""
+            colordict[ch] = ""
     reset = (curses.tigetstr("sgr0") or b"").decode("ascii")
-    terrain_key = colorize(terrain_key)
+    terrain_key = colorize(terrain_key_parts)
 
     print("SKI!  Version %s.  Type ? for help." % version)
     world = SkiWorld()
@@ -553,10 +562,14 @@
                 if not player.do_command(world, cmd):
                     continue
             world.manipulate_objects(player)
-            world.update_level()
+            world.update_level(player)
             player.update_player()
     except (KeyboardInterrupt, EOFError):
         sys.stdout.write(reset)
         print("\nBye!")
-
+    finally:
+        # Should never happen
+        if reset:
+            sys.stdout.write(reset)
+            sys.stdout.flush()
 # end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ski-6.15/ski.6 new/ski-6.16/ski.6
--- old/ski-6.15/ski.6  2024-02-09 13:04:23.000000000 +0100
+++ new/ski-6.16/ski.6  2026-04-05 19:32:33.000000000 +0200
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: ski
 .\"    Author: [see the "AUTHOR(S)" section]
-.\" Generator: Asciidoctor 2.0.16
-.\"      Date: 2024-02-09
+.\" Generator: Asciidoctor 2.0.20
+.\"      Date: 2026-02-01
 .\"    Manual: \ \&
 .\"    Source: \ \&
 .\"  Language: English
 .\"
-.TH "SKI" "6" "2024-02-09" "\ \&" "\ \&"
+.TH "SKI" "6" "2026-02-01" "\ \&" "\ \&"
 .ie \n(.g .ds Aq \(aq
 .el       .ds Aq '
 .ss \n[.ss] 0
@@ -160,7 +160,7 @@
 i
 .RS 4
 Launch ICBM with nuclear warhead.  If your backpack is working well,
-an ICBM will be launched from it towards the Yeti, travelling at
+an ICBM will be launched from it towards the Yeti, traveling at
 three spaces per turn.  Launching ICBMs is dangerous, but once one is
 going, it can\(cqt hurt you.  If it is launched and loses its 
negative\-infrared
 lock on the Yeti, it self\-destructs.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ski-6.15/ski.adoc new/ski-6.16/ski.adoc
--- old/ski-6.15/ski.adoc       2024-02-09 12:46:39.000000000 +0100
+++ new/ski-6.16/ski.adoc       2026-04-05 19:32:33.000000000 +0200
@@ -3,6 +3,8 @@
 // SPDX-FileCopyrightText: (C) Eric S. Raymond <[email protected]>
 // SPDX-License-Identifier: BSD-2-Clause
 
+// spellcheck: add Stevans
+
 == NAME ==
 ski - an unusual skiing simulation game
 
@@ -99,7 +101,7 @@
     fall down.
 i::
     Launch ICBM with nuclear warhead.  If your backpack is working well,
-    an ICBM will be launched from it towards the Yeti, travelling at
+    an ICBM will be launched from it towards the Yeti, traveling at
     three spaces per turn.  Launching ICBMs is dangerous, but once one is
     going, it can't hurt you.  If it is launched and loses its 
negative-infrared
     lock on the Yeti, it self-destructs.

Reply via email to